Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

AbstractColorPicker.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Copyright 2000-2018 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.ui;
  17. import java.io.Serializable;
  18. import java.util.Collection;
  19. import java.util.Locale;
  20. import java.util.Objects;
  21. import org.jsoup.nodes.Attributes;
  22. import org.jsoup.nodes.Element;
  23. import com.vaadin.shared.ui.colorpicker.AbstractColorPickerState;
  24. import com.vaadin.shared.ui.colorpicker.Color;
  25. import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc;
  26. import com.vaadin.ui.components.colorpicker.ColorPickerPopup;
  27. import com.vaadin.ui.declarative.DesignAttributeHandler;
  28. import com.vaadin.ui.declarative.DesignContext;
  29. /**
  30. * An abstract class that defines default implementation for a color picker
  31. * component.
  32. *
  33. * @since 7.0.0
  34. */
  35. public abstract class AbstractColorPicker extends AbstractField<Color> {
  36. /**
  37. * Interface for converting 2d-coordinates to a Color.
  38. */
  39. public interface Coordinates2Color extends Serializable {
  40. /**
  41. * Calculates a color from coordinates.
  42. *
  43. * @param x
  44. * the x-coordinate
  45. * @param y
  46. * the y-coordinate
  47. *
  48. * @return the color
  49. */
  50. public Color calculate(int x, int y);
  51. /**
  52. * Calculates coordinates from a color.
  53. *
  54. * @param c
  55. * the c
  56. *
  57. * @return the integer array with the coordinates
  58. */
  59. public int[] calculate(Color c);
  60. }
  61. /**
  62. * The style of the color picker popup.
  63. */
  64. public enum PopupStyle {
  65. /** A full popup with all tabs visible. */
  66. POPUP_NORMAL("normal"),
  67. /** A simple popup with only the swatches (palette) tab. */
  68. POPUP_SIMPLE("simple");
  69. private final String style;
  70. PopupStyle(String styleName) {
  71. style = styleName;
  72. }
  73. @Override
  74. public String toString() {
  75. return style;
  76. }
  77. }
  78. protected static final String STYLENAME_DEFAULT = "v-colorpicker";
  79. protected static final String STYLENAME_BUTTON = "v-button";
  80. protected static final String STYLENAME_AREA = "v-colorpicker-area";
  81. protected PopupStyle popupStyle = PopupStyle.POPUP_NORMAL;
  82. private ColorPickerPopup window;
  83. /** The currently selected color. */
  84. protected Color color;
  85. private UI parent;
  86. private String popupCaption = null;
  87. private int positionX = 0;
  88. private int positionY = 0;
  89. protected boolean rgbVisible = true;
  90. protected boolean hsvVisible = true;
  91. protected boolean swatchesVisible = true;
  92. protected boolean historyVisible = true;
  93. protected boolean textfieldVisible = true;
  94. private ColorPickerServerRpc rpc = new ColorPickerServerRpc() {
  95. @Override
  96. public void openPopup(boolean openPopup) {
  97. showPopup(openPopup);
  98. }
  99. @Override
  100. public void changeColor(String col) {
  101. Color valueC = new Color(
  102. Integer.parseInt(col.substring(1, col.length()), 16));
  103. color = valueC;
  104. setValue(color,true);
  105. }
  106. };
  107. /**
  108. * Instantiates a new color picker.
  109. */
  110. public AbstractColorPicker() {
  111. this("Colors", Color.WHITE);
  112. }
  113. /**
  114. * Instantiates a new color picker.
  115. *
  116. * @param popupCaption
  117. * the caption of the popup window
  118. */
  119. public AbstractColorPicker(String popupCaption) {
  120. this(popupCaption, Color.WHITE);
  121. }
  122. /**
  123. * Instantiates a new color picker.
  124. *
  125. * @param popupCaption
  126. * the caption of the popup window
  127. * @param initialColor
  128. * the initial color
  129. */
  130. public AbstractColorPicker(String popupCaption, Color initialColor) {
  131. super();
  132. registerRpc(rpc);
  133. setValue(initialColor);
  134. this.popupCaption = popupCaption;
  135. setDefaultStyles();
  136. setCaption("");
  137. }
  138. /**
  139. * Returns the current selected color of this color picker.
  140. *
  141. * @return the selected color, not null
  142. */
  143. @Override
  144. public Color getValue() {
  145. return color;
  146. }
  147. /**
  148. * Sets the selected color of this color picker. If the new color is not
  149. * equal to getValue(), fires a {@link ValueChangeEvent}.
  150. *
  151. * @param color
  152. * the new selected color, not null
  153. * @throws NullPointerException
  154. * if {@code color} is {@code null}
  155. */
  156. @Override
  157. public void setValue(Color color) {
  158. Objects.requireNonNull(color, "color cannot be null");
  159. super.setValue(color);
  160. if (window != null) {
  161. window.setValue(color);
  162. }
  163. }
  164. /**
  165. * Set true if the component should show a default caption (css-code for the
  166. * currently selected color, e.g. #ffffff) when no other caption is
  167. * available.
  168. *
  169. * @param enabled
  170. * {@code true} to enable the default caption, {@code false} to
  171. * disable
  172. */
  173. public void setDefaultCaptionEnabled(boolean enabled) {
  174. getState().showDefaultCaption = enabled;
  175. }
  176. /**
  177. * Returns true if the component shows the default caption (css-code for the
  178. * currently selected color, e.g. #ffffff) if no other caption is available.
  179. *
  180. * @return {@code true} if the default caption is enabled, {@code false}
  181. * otherwise
  182. */
  183. public boolean isDefaultCaptionEnabled() {
  184. return getState(false).showDefaultCaption;
  185. }
  186. /**
  187. * Sets the position of the popup window.
  188. *
  189. * @param x
  190. * the x-coordinate
  191. * @param y
  192. * the y-coordinate
  193. */
  194. public void setPosition(int x, int y) {
  195. positionX = x;
  196. positionY = y;
  197. if (window != null) {
  198. window.setPositionX(x);
  199. window.setPositionY(y);
  200. }
  201. }
  202. /**
  203. * Sets the style of the popup window.
  204. *
  205. * @param style
  206. * the popup window style
  207. */
  208. public void setPopupStyle(PopupStyle style) {
  209. popupStyle = style;
  210. switch (style) {
  211. case POPUP_NORMAL:
  212. setRGBVisibility(true);
  213. setHSVVisibility(true);
  214. setSwatchesVisibility(true);
  215. setHistoryVisibility(true);
  216. setTextfieldVisibility(true);
  217. break;
  218. case POPUP_SIMPLE:
  219. setRGBVisibility(false);
  220. setHSVVisibility(false);
  221. setSwatchesVisibility(true);
  222. setHistoryVisibility(false);
  223. setTextfieldVisibility(false);
  224. break;
  225. default:
  226. assert false : "Unknown popup style " + style;
  227. }
  228. }
  229. /**
  230. * Gets the style for the popup window.
  231. *
  232. * @since 7.5.0
  233. * @return popup window style
  234. */
  235. public PopupStyle getPopupStyle() {
  236. return popupStyle;
  237. }
  238. /**
  239. * Sets the visibility of the RGB tab.
  240. *
  241. * @param visible
  242. * {@code true} to display the RGB tab, {@code false} to hide it
  243. */
  244. public void setRGBVisibility(boolean visible) {
  245. if (!visible && !hsvVisible && !swatchesVisible) {
  246. throw new IllegalArgumentException("Cannot hide all tabs.");
  247. }
  248. rgbVisible = visible;
  249. if (window != null) {
  250. window.setRGBTabVisible(visible);
  251. }
  252. }
  253. /**
  254. * Gets the visibility of the RGB Tab.
  255. *
  256. * @since 7.5.0
  257. * @return visibility of the RGB tab
  258. */
  259. public boolean getRGBVisibility() {
  260. return rgbVisible;
  261. }
  262. /**
  263. * Sets the visibility of the HSV Tab.
  264. *
  265. * @param visible
  266. * {@code true} to display the HSV tab, {@code false} to hide it
  267. */
  268. public void setHSVVisibility(boolean visible) {
  269. if (!visible && !rgbVisible && !swatchesVisible) {
  270. throw new IllegalArgumentException("Cannot hide all tabs.");
  271. }
  272. hsvVisible = visible;
  273. if (window != null) {
  274. window.setHSVTabVisible(visible);
  275. }
  276. }
  277. /**
  278. * Gets the visibility of the HSV tab.
  279. *
  280. * @since 7.5.0
  281. * @return {@code true} if the HSV tab is currently displayed, {@code false}
  282. * otherwise
  283. */
  284. public boolean getHSVVisibility() {
  285. return hsvVisible;
  286. }
  287. /**
  288. * Sets the visibility of the Swatches (palette) tab.
  289. *
  290. * @param visible
  291. * {@code true} to display the Swatches tab, {@code false} to
  292. * hide it
  293. */
  294. public void setSwatchesVisibility(boolean visible) {
  295. if (!visible && !hsvVisible && !rgbVisible) {
  296. throw new IllegalArgumentException("Cannot hide all tabs.");
  297. }
  298. swatchesVisible = visible;
  299. if (window != null) {
  300. window.setSwatchesTabVisible(visible);
  301. }
  302. }
  303. /**
  304. * Gets the visibility of the Swatches (palette) tab.
  305. *
  306. * @since 7.5.0
  307. * @return {@code true} if the Swatches tab is currently displayed,
  308. * {@code false} otherwise
  309. */
  310. public boolean getSwatchesVisibility() {
  311. return swatchesVisible;
  312. }
  313. /**
  314. * Sets the visibility of the color history, displaying recently picked
  315. * colors.
  316. *
  317. * @param visible
  318. * {@code true} to display the history, {@code false} to hide it
  319. */
  320. public void setHistoryVisibility(boolean visible) {
  321. historyVisible = visible;
  322. if (window != null) {
  323. window.setHistoryVisible(visible);
  324. }
  325. }
  326. /**
  327. * Gets the visibility of the Color history.
  328. *
  329. * @since 7.5.0
  330. * @return {@code true} if the history is currently displayed, {@code false}
  331. * otherwise
  332. */
  333. public boolean getHistoryVisibility() {
  334. return historyVisible;
  335. }
  336. /**
  337. * Sets the visibility of the CSS color code text field.
  338. *
  339. * @param visible
  340. * {@code true} to display the CSS text field, {@code false} to
  341. * hide it
  342. */
  343. public void setTextfieldVisibility(boolean visible) {
  344. textfieldVisible = visible;
  345. if (window != null) {
  346. window.setPreviewVisible(visible);
  347. }
  348. }
  349. /**
  350. * Gets the visibility of CSS color code text field.
  351. *
  352. * @since 7.5.0
  353. * @return {@code true} if the CSS text field is currently displayed,
  354. * {@code false} otherwise
  355. */
  356. public boolean getTextfieldVisibility() {
  357. return textfieldVisible;
  358. }
  359. @Override
  360. protected AbstractColorPickerState getState() {
  361. return (AbstractColorPickerState) super.getState();
  362. }
  363. @Override
  364. protected AbstractColorPickerState getState(boolean markAsDirty) {
  365. return (AbstractColorPickerState) super.getState(markAsDirty);
  366. }
  367. /**
  368. * Sets the default styles of the component.
  369. */
  370. protected abstract void setDefaultStyles();
  371. /**
  372. * Shows a popup-window for color selection.
  373. */
  374. public void showPopup() {
  375. showPopup(true);
  376. }
  377. /**
  378. * Hides a popup-window for color selection.
  379. */
  380. public void hidePopup() {
  381. showPopup(false);
  382. }
  383. /**
  384. * Shows or hides the popup window depending on the given parameter. If
  385. * there is no such window yet, one is created.
  386. *
  387. * @param open
  388. * {@code true} to display the popup, {@code false} to hide it
  389. */
  390. protected void showPopup(boolean open) {
  391. if (open && !isReadOnly()) {
  392. if (parent == null) {
  393. parent = getUI();
  394. }
  395. Color color = getValue();
  396. if (window == null) {
  397. window = new ColorPickerPopup(color);
  398. window.setCaption(popupCaption);
  399. window.setRGBTabVisible(rgbVisible);
  400. window.setHSVTabVisible(hsvVisible);
  401. window.setSwatchesTabVisible(swatchesVisible);
  402. window.setHistoryVisible(historyVisible);
  403. window.setPreviewVisible(textfieldVisible);
  404. window.addCloseListener(
  405. event -> getState().popupVisible = false);
  406. window.addValueChangeListener(event -> {
  407. setValue(event.getValue());
  408. rpc.changeColor(event.getValue().getCSS());
  409. });
  410. window.getHistory().setValue(color);
  411. window.setPositionX(positionX);
  412. window.setPositionY(positionY);
  413. window.setVisible(true);
  414. window.setValue(color);
  415. parent.addWindow(window);
  416. window.focus();
  417. } else if (!parent.equals(window.getParent())) {
  418. window.setRGBTabVisible(rgbVisible);
  419. window.setHSVTabVisible(hsvVisible);
  420. window.setSwatchesTabVisible(swatchesVisible);
  421. window.setHistoryVisible(historyVisible);
  422. window.setPreviewVisible(textfieldVisible);
  423. window.setValue(color);
  424. window.getHistory().setValue(color);
  425. window.setVisible(true);
  426. parent.addWindow(window);
  427. window.focus();
  428. }
  429. window.setValue(color);
  430. } else if (window != null) {
  431. window.setVisible(false);
  432. parent.removeWindow(window);
  433. }
  434. getState().popupVisible = open;
  435. }
  436. @Override
  437. public void readDesign(Element design, DesignContext designContext) {
  438. super.readDesign(design, designContext);
  439. Attributes attributes = design.attributes();
  440. if (design.hasAttr("color")) {
  441. // Ignore the # character
  442. String hexColor = DesignAttributeHandler
  443. .readAttribute("color", attributes, String.class)
  444. .substring(1);
  445. doSetValue(new Color(Integer.parseInt(hexColor, 16)));
  446. }
  447. if (design.hasAttr("popup-style")) {
  448. setPopupStyle(PopupStyle.valueOf("POPUP_"
  449. + attributes.get("popup-style").toUpperCase(Locale.ROOT)));
  450. }
  451. if (design.hasAttr("position")) {
  452. String[] position = attributes.get("position").split(",");
  453. setPosition(Integer.parseInt(position[0]),
  454. Integer.parseInt(position[1]));
  455. }
  456. }
  457. @Override
  458. public void writeDesign(Element design, DesignContext designContext) {
  459. super.writeDesign(design, designContext);
  460. Attributes attribute = design.attributes();
  461. DesignAttributeHandler.writeAttribute("color", attribute,
  462. getValue().getCSS(), Color.WHITE.getCSS(), String.class,
  463. designContext);
  464. DesignAttributeHandler.writeAttribute("popup-style", attribute,
  465. popupStyle == PopupStyle.POPUP_NORMAL ? "normal" : "simple",
  466. "normal", String.class, designContext);
  467. DesignAttributeHandler.writeAttribute("position", attribute,
  468. positionX + "," + positionY, "0,0", String.class,
  469. designContext);
  470. }
  471. @Override
  472. protected Collection<String> getCustomAttributes() {
  473. Collection<String> result = super.getCustomAttributes();
  474. result.add("color");
  475. result.add("position");
  476. result.add("popup-style");
  477. return result;
  478. }
  479. @Override
  480. protected void doSetValue(Color color) {
  481. this.color = color;
  482. getState().color = color.getCSS();
  483. }
  484. @Override
  485. public Color getEmptyValue() {
  486. return Color.WHITE;
  487. }
  488. }