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.

VAbstractPaintableWidget.java 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import com.google.gwt.user.client.DOM;
  6. import com.google.gwt.user.client.ui.FocusWidget;
  7. import com.google.gwt.user.client.ui.Focusable;
  8. import com.google.gwt.user.client.ui.Widget;
  9. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  10. import com.vaadin.terminal.gwt.client.TooltipInfo;
  11. import com.vaadin.terminal.gwt.client.UIDL;
  12. import com.vaadin.terminal.gwt.client.VPaintableMap;
  13. import com.vaadin.terminal.gwt.client.VPaintableWidget;
  14. import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer;
  15. public abstract class VAbstractPaintableWidget implements VPaintableWidget {
  16. public static final String ATTRIBUTE_DESCRIPTION = "description";
  17. public static final String ATTRIBUTE_ERROR = "error";
  18. private Widget widget;
  19. private ApplicationConnection connection;
  20. private String id;
  21. private VPaintableWidgetContainer parent;
  22. /* State variables */
  23. private boolean enabled = true;
  24. private boolean visible = true;
  25. /**
  26. * Default constructor
  27. */
  28. public VAbstractPaintableWidget() {
  29. }
  30. /**
  31. * Called after the application connection reference has been set up
  32. */
  33. public void init() {
  34. }
  35. /**
  36. * Creates and returns the widget for this VPaintableWidget. This method
  37. * should only be called once when initializing the paintable.
  38. *
  39. * @return
  40. */
  41. protected abstract Widget createWidget();
  42. /**
  43. * Returns the widget associated with this paintable. The widget returned by
  44. * this method must not changed during the life time of the paintable.
  45. *
  46. * @return The widget associated with this paintable
  47. */
  48. public Widget getWidgetForPaintable() {
  49. if (widget == null) {
  50. widget = createWidget();
  51. }
  52. return widget;
  53. }
  54. /*
  55. * (non-Javadoc)
  56. *
  57. * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection()
  58. */
  59. public final ApplicationConnection getConnection() {
  60. return connection;
  61. }
  62. /*
  63. * (non-Javadoc)
  64. *
  65. * @see
  66. * com.vaadin.terminal.gwt.client.VPaintable#setConnection(com.vaadin.terminal
  67. * .gwt.client.ApplicationConnection)
  68. */
  69. public final void setConnection(ApplicationConnection connection) {
  70. this.connection = connection;
  71. }
  72. public String getId() {
  73. return id;
  74. }
  75. public void setId(String id) {
  76. this.id = id;
  77. }
  78. public VPaintableWidgetContainer getParent() {
  79. if (parent != null) {
  80. return parent;
  81. }
  82. // FIXME: Hierarchy should be set by framework instead of looked up here
  83. VPaintableMap paintableMap = VPaintableMap.get(getConnection());
  84. Widget w = getWidgetForPaintable();
  85. while (w != null) {
  86. w = w.getParent();
  87. if (paintableMap.isPaintable(w)) {
  88. parent = (VPaintableWidgetContainer) paintableMap
  89. .getPaintable(w);
  90. return parent;
  91. }
  92. }
  93. return null;
  94. }
  95. protected static boolean isRealUpdate(UIDL uidl) {
  96. return !isCachedUpdate(uidl) && !uidl.getBooleanAttribute("invisible");
  97. }
  98. protected static boolean isCachedUpdate(UIDL uidl) {
  99. return uidl.getBooleanAttribute("cached");
  100. }
  101. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  102. if (isCachedUpdate(uidl)) {
  103. return;
  104. }
  105. VPaintableMap paintableMap = VPaintableMap.get(getConnection());
  106. // register the listened events by the server-side to the event-handler
  107. // of the component
  108. paintableMap.registerEventListenersFromUIDL(getId(), uidl);
  109. // Visibility
  110. setVisible(!uidl.getBooleanAttribute("invisible"), uidl);
  111. if (uidl.getId().startsWith("PID_S")) {
  112. DOM.setElementProperty(getWidgetForPaintable().getElement(), "id",
  113. uidl.getId().substring(5));
  114. }
  115. if (!isVisible()) {
  116. // component is invisible, delete old size to notify parent, if
  117. // later made visible
  118. paintableMap.setOffsetSize(this, null);
  119. return;
  120. }
  121. /*
  122. * Disabled state may affect (override) tabindex so the order must be
  123. * first setting tabindex, then enabled state.
  124. */
  125. if (uidl.hasAttribute("tabindex")
  126. && getWidgetForPaintable() instanceof Focusable) {
  127. ((Focusable) getWidgetForPaintable()).setTabIndex(uidl
  128. .getIntAttribute("tabindex"));
  129. }
  130. setEnabled(!uidl.getBooleanAttribute("disabled"));
  131. // Style names
  132. String styleName = getStyleNameFromUIDL(getWidgetForPaintable()
  133. .getStylePrimaryName(), uidl,
  134. getWidgetForPaintable() instanceof Field);
  135. getWidgetForPaintable().setStyleName(styleName);
  136. // Update tooltip
  137. TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(this, null);
  138. if (uidl.hasAttribute(ATTRIBUTE_DESCRIPTION)) {
  139. tooltipInfo
  140. .setTitle(uidl.getStringAttribute(ATTRIBUTE_DESCRIPTION));
  141. } else {
  142. tooltipInfo.setTitle(null);
  143. }
  144. // add error info to tooltip if present
  145. if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
  146. tooltipInfo.setErrorUidl(uidl.getErrors());
  147. } else {
  148. tooltipInfo.setErrorUidl(null);
  149. }
  150. // Set captions
  151. if (delegateCaptionHandling()) {
  152. getParent().updateCaption(this, uidl);
  153. }
  154. /*
  155. * updateComponentSize need to be after caption update so caption can be
  156. * taken into account
  157. */
  158. getConnection().updateComponentSize(this, uidl);
  159. }
  160. /**
  161. * Sets the enabled state of this paintable
  162. *
  163. * @param enabled
  164. * true if the paintable is enabled, false otherwise
  165. */
  166. protected void setEnabled(boolean enabled) {
  167. this.enabled = enabled;
  168. if (getWidgetForPaintable() instanceof FocusWidget) {
  169. FocusWidget fw = (FocusWidget) getWidgetForPaintable();
  170. fw.setEnabled(enabled);
  171. }
  172. }
  173. public boolean isEnabled() {
  174. return enabled;
  175. }
  176. /**
  177. * Return true if parent handles caption, false if the paintable handles the
  178. * caption itself.
  179. *
  180. *
  181. * @deprecated This should always return true and all components should let
  182. * the parent handle the caption and use other attributes for
  183. * internal texts in the component
  184. * @return
  185. */
  186. @Deprecated
  187. protected boolean delegateCaptionHandling() {
  188. return true;
  189. }
  190. /**
  191. * Sets the visible state for this paintable.
  192. *
  193. * @param visible
  194. * true if the paintable should be made visible, false otherwise
  195. * @param captionUidl
  196. * The UIDL that is passed to the parent and onwards to VCaption
  197. * if the caption needs to be updated as a result of the
  198. * visibility change.
  199. */
  200. protected void setVisible(boolean visible, UIDL captionUidl) {
  201. boolean wasVisible = this.visible;
  202. this.visible = visible;
  203. getWidgetForPaintable().setVisible(visible);
  204. if (wasVisible != visible) {
  205. // Changed invisibile <-> visible
  206. if (wasVisible && delegateCaptionHandling()) {
  207. // Must hide caption when component is hidden
  208. getParent().updateCaption(this, captionUidl);
  209. }
  210. }
  211. }
  212. protected boolean isVisible() {
  213. return visible;
  214. }
  215. /**
  216. * Generates the style name for the widget based on the given primary style
  217. * name (typically returned by Widget.getPrimaryStyleName()) and the UIDL.
  218. * An additional "modified" style name can be added if the field parameter
  219. * is set to true.
  220. *
  221. * @param primaryStyleName
  222. * @param uidl
  223. * @param isField
  224. * @return
  225. */
  226. protected static String getStyleNameFromUIDL(String primaryStyleName,
  227. UIDL uidl, boolean field) {
  228. boolean enabled = !uidl.getBooleanAttribute("disabled");
  229. StringBuffer styleBuf = new StringBuffer();
  230. styleBuf.append(primaryStyleName);
  231. // first disabling and read-only status
  232. if (!enabled) {
  233. styleBuf.append(" ");
  234. styleBuf.append(ApplicationConnection.DISABLED_CLASSNAME);
  235. }
  236. if (uidl.getBooleanAttribute("readonly")) {
  237. styleBuf.append(" ");
  238. styleBuf.append("v-readonly");
  239. }
  240. // add additional styles as css classes, prefixed with component default
  241. // stylename
  242. if (uidl.hasAttribute("style")) {
  243. final String[] styles = uidl.getStringAttribute("style").split(" ");
  244. for (int i = 0; i < styles.length; i++) {
  245. styleBuf.append(" ");
  246. styleBuf.append(primaryStyleName);
  247. styleBuf.append("-");
  248. styleBuf.append(styles[i]);
  249. styleBuf.append(" ");
  250. styleBuf.append(styles[i]);
  251. }
  252. }
  253. // add modified classname to Fields
  254. if (field && uidl.hasAttribute("modified")) {
  255. styleBuf.append(" ");
  256. styleBuf.append(ApplicationConnection.MODIFIED_CLASSNAME);
  257. }
  258. // add error classname to components w/ error
  259. if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
  260. styleBuf.append(" ");
  261. styleBuf.append(primaryStyleName);
  262. styleBuf.append(ApplicationConnection.ERROR_CLASSNAME_EXT);
  263. }
  264. // add required style to required components
  265. if (uidl.hasAttribute("required")) {
  266. styleBuf.append(" ");
  267. styleBuf.append(primaryStyleName);
  268. styleBuf.append(ApplicationConnection.REQUIRED_CLASSNAME_EXT);
  269. }
  270. return styleBuf.toString();
  271. }
  272. }