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.

VTextField.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import com.google.gwt.user.client.DOM;
  6. import com.google.gwt.user.client.Element;
  7. import com.google.gwt.user.client.Event;
  8. import com.google.gwt.user.client.ui.ChangeListener;
  9. import com.google.gwt.user.client.ui.FocusListener;
  10. import com.google.gwt.user.client.ui.TextBoxBase;
  11. import com.google.gwt.user.client.ui.Widget;
  12. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  13. import com.vaadin.terminal.gwt.client.BrowserInfo;
  14. import com.vaadin.terminal.gwt.client.Paintable;
  15. import com.vaadin.terminal.gwt.client.UIDL;
  16. import com.vaadin.terminal.gwt.client.Util;
  17. import com.vaadin.terminal.gwt.client.VTooltip;
  18. /**
  19. * This class represents a basic text input field with one row.
  20. *
  21. * @author IT Mill Ltd.
  22. *
  23. */
  24. public class VTextField extends TextBoxBase implements Paintable, Field,
  25. ChangeListener, FocusListener {
  26. /**
  27. * The input node CSS classname.
  28. */
  29. public static final String CLASSNAME = "v-textfield";
  30. /**
  31. * This CSS classname is added to the input node on hover.
  32. */
  33. public static final String CLASSNAME_FOCUS = "focus";
  34. protected String id;
  35. protected ApplicationConnection client;
  36. private String valueBeforeEdit = null;
  37. private boolean immediate = false;
  38. private int extraHorizontalPixels = -1;
  39. private int extraVerticalPixels = -1;
  40. private int maxLength = -1;
  41. private static final String CLASSNAME_PROMPT = "prompt";
  42. private static final String ATTR_INPUTPROMPT = "prompt";
  43. private String inputPrompt = null;
  44. private boolean prompting = false;
  45. public VTextField() {
  46. this(DOM.createInputText());
  47. }
  48. protected VTextField(Element node) {
  49. super(node);
  50. if (BrowserInfo.get().isIE()) {
  51. // Fixes IE margin problem (#2058)
  52. DOM.setStyleAttribute(node, "marginTop", "-1px");
  53. DOM.setStyleAttribute(node, "marginBottom", "-1px");
  54. }
  55. setStyleName(CLASSNAME);
  56. addChangeListener(this);
  57. addFocusListener(this);
  58. sinkEvents(VTooltip.TOOLTIP_EVENTS);
  59. }
  60. @Override
  61. public void onBrowserEvent(Event event) {
  62. super.onBrowserEvent(event);
  63. if (client != null) {
  64. client.handleTooltipEvent(event, this);
  65. }
  66. }
  67. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  68. this.client = client;
  69. id = uidl.getId();
  70. if (client.updateComponent(this, uidl, true)) {
  71. return;
  72. }
  73. if (uidl.getBooleanAttribute("readonly")) {
  74. setReadOnly(true);
  75. } else {
  76. setReadOnly(false);
  77. }
  78. inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
  79. setMaxLength(uidl.hasAttribute("maxLength") ? uidl
  80. .getIntAttribute("maxLength") : -1);
  81. immediate = uidl.getBooleanAttribute("immediate");
  82. if (uidl.hasAttribute("cols")) {
  83. setColumns(new Integer(uidl.getStringAttribute("cols")).intValue());
  84. }
  85. String text = uidl.hasVariable("text") ? uidl.getStringVariable("text")
  86. : null;
  87. setPrompting(inputPrompt != null && focusedTextField != this
  88. && (text == null || text.equals("")));
  89. if (prompting) {
  90. setText(inputPrompt);
  91. addStyleDependentName(CLASSNAME_PROMPT);
  92. } else {
  93. setText(text);
  94. removeStyleDependentName(CLASSNAME_PROMPT);
  95. }
  96. valueBeforeEdit = uidl.getStringVariable("text");
  97. }
  98. private void setMaxLength(int newMaxLength) {
  99. if (newMaxLength > 0) {
  100. maxLength = newMaxLength;
  101. if (getElement().getTagName().toLowerCase().equals("textarea")) {
  102. // NOP no maxlength property for textarea
  103. } else {
  104. getElement().setPropertyInt("maxLength", maxLength);
  105. }
  106. } else if (maxLength != -1) {
  107. if (getElement().getTagName().toLowerCase().equals("textarea")) {
  108. // NOP no maxlength property for textarea
  109. } else {
  110. getElement().setAttribute("maxlength", "");
  111. }
  112. maxLength = -1;
  113. }
  114. }
  115. protected int getMaxLength() {
  116. return maxLength;
  117. }
  118. public void onChange(Widget sender) {
  119. if (client != null && id != null) {
  120. String newText = getText();
  121. if (!prompting && newText != null
  122. && !newText.equals(valueBeforeEdit)) {
  123. client.updateVariable(id, "text", getText(), immediate);
  124. valueBeforeEdit = newText;
  125. }
  126. }
  127. }
  128. private static VTextField focusedTextField;
  129. public static void flushChangesFromFocusedTextField() {
  130. if (focusedTextField != null) {
  131. focusedTextField.onChange(null);
  132. }
  133. }
  134. public void onFocus(Widget sender) {
  135. addStyleDependentName(CLASSNAME_FOCUS);
  136. if (prompting) {
  137. setText("");
  138. removeStyleDependentName(CLASSNAME_PROMPT);
  139. }
  140. focusedTextField = this;
  141. }
  142. public void onLostFocus(Widget sender) {
  143. removeStyleDependentName(CLASSNAME_FOCUS);
  144. focusedTextField = null;
  145. String text = getText();
  146. setPrompting(inputPrompt != null && (text == null || "".equals(text)));
  147. if (prompting) {
  148. setText(inputPrompt);
  149. addStyleDependentName(CLASSNAME_PROMPT);
  150. }
  151. onChange(sender);
  152. }
  153. private void setPrompting(boolean prompting) {
  154. this.prompting = prompting;
  155. }
  156. public void setColumns(int columns) {
  157. setColumns(getElement(), columns);
  158. }
  159. private native void setColumns(Element e, int c)
  160. /*-{
  161. try {
  162. switch(e.tagName.toLowerCase()) {
  163. case "input":
  164. //e.size = c;
  165. e.style.width = c+"em";
  166. break;
  167. case "textarea":
  168. //e.cols = c;
  169. e.style.width = c+"em";
  170. break;
  171. default:;
  172. }
  173. } catch (e) {}
  174. }-*/;
  175. /**
  176. * @return space used by components paddings and borders
  177. */
  178. private int getExtraHorizontalPixels() {
  179. if (extraHorizontalPixels < 0) {
  180. detectExtraSizes();
  181. }
  182. return extraHorizontalPixels;
  183. }
  184. /**
  185. * @return space used by components paddings and borders
  186. */
  187. private int getExtraVerticalPixels() {
  188. if (extraVerticalPixels < 0) {
  189. detectExtraSizes();
  190. }
  191. return extraVerticalPixels;
  192. }
  193. /**
  194. * Detects space used by components paddings and borders. Used when
  195. * relational size are used.
  196. */
  197. private void detectExtraSizes() {
  198. Element clone = Util.cloneNode(getElement(), false);
  199. DOM.setElementAttribute(clone, "id", "");
  200. DOM.setStyleAttribute(clone, "visibility", "hidden");
  201. DOM.setStyleAttribute(clone, "position", "absolute");
  202. // due FF3 bug set size to 10px and later subtract it from extra pixels
  203. DOM.setStyleAttribute(clone, "width", "10px");
  204. DOM.setStyleAttribute(clone, "height", "10px");
  205. DOM.appendChild(DOM.getParent(getElement()), clone);
  206. extraHorizontalPixels = DOM.getElementPropertyInt(clone, "offsetWidth") - 10;
  207. extraVerticalPixels = DOM.getElementPropertyInt(clone, "offsetHeight") - 10;
  208. DOM.removeChild(DOM.getParent(getElement()), clone);
  209. }
  210. @Override
  211. public void setHeight(String height) {
  212. if (height.endsWith("px")) {
  213. int h = Integer.parseInt(height.substring(0, height.length() - 2));
  214. h -= getExtraVerticalPixels();
  215. if (h < 0) {
  216. h = 0;
  217. }
  218. super.setHeight(h + "px");
  219. } else {
  220. super.setHeight(height);
  221. }
  222. }
  223. @Override
  224. public void setWidth(String width) {
  225. if (width.endsWith("px")) {
  226. int w = Integer.parseInt(width.substring(0, width.length() - 2));
  227. w -= getExtraHorizontalPixels();
  228. if (w < 0) {
  229. w = 0;
  230. }
  231. super.setWidth(w + "px");
  232. } else {
  233. super.setWidth(width);
  234. }
  235. }
  236. }