You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RichTextArea.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * Copyright 2000-2014 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.util.Map;
  18. import org.jsoup.nodes.Element;
  19. import com.vaadin.data.Property;
  20. import com.vaadin.legacy.ui.LegacyAbstractField;
  21. import com.vaadin.legacy.ui.LegacyTextField;
  22. import com.vaadin.server.PaintException;
  23. import com.vaadin.server.PaintTarget;
  24. import com.vaadin.shared.ui.textarea.RichTextAreaState;
  25. import com.vaadin.ui.declarative.DesignContext;
  26. /**
  27. * A simple RichTextArea to edit HTML format text.
  28. *
  29. * Note, that using {@link LegacyTextField#setMaxLength(int)} method in
  30. * {@link RichTextArea} may produce unexpected results as formatting is counted
  31. * into length of field.
  32. */
  33. public class RichTextArea extends LegacyAbstractField<String> implements
  34. LegacyComponent {
  35. /**
  36. * Null representation.
  37. */
  38. private String nullRepresentation = "null";
  39. /**
  40. * Is setting to null from non-null value allowed by setting with null
  41. * representation .
  42. */
  43. private boolean nullSettingAllowed = false;
  44. /**
  45. * Temporary flag that indicates all content will be selected after the next
  46. * paint. Reset to false after painted.
  47. */
  48. private boolean selectAll = false;
  49. /**
  50. * Constructs an empty <code>RichTextArea</code> with no caption.
  51. */
  52. public RichTextArea() {
  53. setValue("");
  54. }
  55. /**
  56. *
  57. * Constructs an empty <code>RichTextArea</code> with the given caption.
  58. *
  59. * @param caption
  60. * the caption for the editor.
  61. */
  62. public RichTextArea(String caption) {
  63. this();
  64. setCaption(caption);
  65. }
  66. /**
  67. * Constructs a new <code>RichTextArea</code> that's bound to the specified
  68. * <code>Property</code> and has no caption.
  69. *
  70. * @param dataSource
  71. * the data source for the editor value
  72. */
  73. public RichTextArea(Property dataSource) {
  74. setPropertyDataSource(dataSource);
  75. }
  76. /**
  77. * Constructs a new <code>RichTextArea</code> that's bound to the specified
  78. * <code>Property</code> and has the given caption.
  79. *
  80. * @param caption
  81. * the caption for the editor.
  82. * @param dataSource
  83. * the data source for the editor value
  84. */
  85. public RichTextArea(String caption, Property dataSource) {
  86. this(dataSource);
  87. setCaption(caption);
  88. }
  89. /**
  90. * Constructs a new <code>RichTextArea</code> with the given caption and
  91. * initial text contents.
  92. *
  93. * @param caption
  94. * the caption for the editor.
  95. * @param value
  96. * the initial text content of the editor.
  97. */
  98. public RichTextArea(String caption, String value) {
  99. setValue(value);
  100. setCaption(caption);
  101. }
  102. @Override
  103. public void paintContent(PaintTarget target) throws PaintException {
  104. if (selectAll) {
  105. target.addAttribute("selectAll", true);
  106. selectAll = false;
  107. }
  108. // Adds the content as variable
  109. String value = getValue();
  110. if (value == null) {
  111. value = getNullRepresentation();
  112. }
  113. if (value == null) {
  114. throw new IllegalStateException(
  115. "Null values are not allowed if the null-representation is null");
  116. }
  117. target.addVariable(this, "text", value);
  118. }
  119. @Override
  120. public void setReadOnly(boolean readOnly) {
  121. super.setReadOnly(readOnly);
  122. // IE6 cannot support multi-classname selectors properly
  123. // TODO Can be optimized now that support for I6 is dropped
  124. if (readOnly) {
  125. addStyleName("v-richtextarea-readonly");
  126. } else {
  127. removeStyleName("v-richtextarea-readonly");
  128. }
  129. }
  130. /**
  131. * Selects all text in the rich text area. As a side effect, focuses the
  132. * rich text area.
  133. *
  134. * @since 6.5
  135. */
  136. public void selectAll() {
  137. /*
  138. * Set selection range functionality is currently being
  139. * planned/developed for GWT RTA. Only selecting all is currently
  140. * supported. Consider moving selectAll and other selection related
  141. * functions to AbstractTextField at that point to share the
  142. * implementation. Some third party components extending
  143. * AbstractTextField might however not want to support them.
  144. */
  145. selectAll = true;
  146. focus();
  147. markAsDirty();
  148. }
  149. @Override
  150. public void changeVariables(Object source, Map<String, Object> variables) {
  151. // Sets the text
  152. if (variables.containsKey("text") && !isReadOnly()) {
  153. // Only do the setting if the string representation of the value
  154. // has been updated
  155. String newValue = (String) variables.get("text");
  156. final String oldValue = getValue();
  157. if (newValue != null
  158. && (oldValue == null || isNullSettingAllowed())
  159. && newValue.equals(getNullRepresentation())) {
  160. newValue = null;
  161. }
  162. if (newValue != oldValue
  163. && (newValue == null || !newValue.equals(oldValue))) {
  164. boolean wasModified = isModified();
  165. setValue(newValue, true);
  166. // If the modified status changes,
  167. // repaint is needed after all.
  168. if (wasModified != isModified()) {
  169. markAsDirty();
  170. }
  171. }
  172. }
  173. }
  174. @Override
  175. public Class<String> getType() {
  176. return String.class;
  177. }
  178. /**
  179. * Gets the null-string representation.
  180. *
  181. * <p>
  182. * The null-valued strings are represented on the user interface by
  183. * replacing the null value with this string. If the null representation is
  184. * set null (not 'null' string), painting null value throws exception.
  185. * </p>
  186. *
  187. * <p>
  188. * The default value is string 'null'.
  189. * </p>
  190. *
  191. * @return the String Textual representation for null strings.
  192. * @see LegacyTextField#isNullSettingAllowed()
  193. */
  194. public String getNullRepresentation() {
  195. return nullRepresentation;
  196. }
  197. /**
  198. * Is setting nulls with null-string representation allowed.
  199. *
  200. * <p>
  201. * If this property is true, writing null-representation string to text
  202. * field always sets the field value to real null. If this property is
  203. * false, null setting is not made, but the null values are maintained.
  204. * Maintenance of null-values is made by only converting the textfield
  205. * contents to real null, if the text field matches the null-string
  206. * representation and the current value of the field is null.
  207. * </p>
  208. *
  209. * <p>
  210. * By default this setting is false
  211. * </p>
  212. *
  213. * @return boolean Should the null-string represenation be always converted
  214. * to null-values.
  215. * @see LegacyTextField#getNullRepresentation()
  216. */
  217. public boolean isNullSettingAllowed() {
  218. return nullSettingAllowed;
  219. }
  220. /**
  221. * Sets the null-string representation.
  222. *
  223. * <p>
  224. * The null-valued strings are represented on the user interface by
  225. * replacing the null value with this string. If the null representation is
  226. * set null (not 'null' string), painting null value throws exception.
  227. * </p>
  228. *
  229. * <p>
  230. * The default value is string 'null'
  231. * </p>
  232. *
  233. * @param nullRepresentation
  234. * Textual representation for null strings.
  235. * @see LegacyTextField#setNullSettingAllowed(boolean)
  236. */
  237. public void setNullRepresentation(String nullRepresentation) {
  238. this.nullRepresentation = nullRepresentation;
  239. }
  240. /**
  241. * Sets the null conversion mode.
  242. *
  243. * <p>
  244. * If this property is true, writing null-representation string to text
  245. * field always sets the field value to real null. If this property is
  246. * false, null setting is not made, but the null values are maintained.
  247. * Maintenance of null-values is made by only converting the textfield
  248. * contents to real null, if the text field matches the null-string
  249. * representation and the current value of the field is null.
  250. * </p>
  251. *
  252. * <p>
  253. * By default this setting is false.
  254. * </p>
  255. *
  256. * @param nullSettingAllowed
  257. * Should the null-string represenation be always converted to
  258. * null-values.
  259. * @see LegacyTextField#getNullRepresentation()
  260. */
  261. public void setNullSettingAllowed(boolean nullSettingAllowed) {
  262. this.nullSettingAllowed = nullSettingAllowed;
  263. }
  264. @Override
  265. public boolean isEmpty() {
  266. return super.isEmpty() || getValue().length() == 0;
  267. }
  268. @Override
  269. public void clear() {
  270. setValue("");
  271. }
  272. @Override
  273. public void readDesign(Element design, DesignContext designContext) {
  274. super.readDesign(design, designContext);
  275. setValue(design.html(), false, true);
  276. }
  277. @Override
  278. public void writeDesign(Element design, DesignContext designContext) {
  279. super.writeDesign(design, designContext);
  280. design.html(getValue());
  281. }
  282. @Override
  283. protected RichTextAreaState getState() {
  284. return (RichTextAreaState) super.getState();
  285. }
  286. }