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 10KB

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