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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. if (!isRealUpdate(uidl)) {
  128. return;
  129. }
  130. /*
  131. * Disabled state may affect (override) tabindex so the order must be
  132. * first setting tabindex, then enabled state.
  133. */
  134. if (uidl.hasAttribute("tabindex")
  135. && getWidgetForPaintable() instanceof Focusable) {
  136. ((Focusable) getWidgetForPaintable()).setTabIndex(uidl
  137. .getIntAttribute("tabindex"));
  138. }
  139. setEnabled(!uidl.getBooleanAttribute("disabled"));
  140. // Style names
  141. String styleName = getStyleNameFromUIDL(getWidgetForPaintable()
  142. .getStylePrimaryName(), uidl,
  143. getWidgetForPaintable() instanceof Field);
  144. getWidgetForPaintable().setStyleName(styleName);
  145. // Update tooltip
  146. TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(this, null);
  147. if (uidl.hasAttribute(ATTRIBUTE_DESCRIPTION)) {
  148. tooltipInfo
  149. .setTitle(uidl.getStringAttribute(ATTRIBUTE_DESCRIPTION));
  150. } else {
  151. tooltipInfo.setTitle(null);
  152. }
  153. // add error info to tooltip if present
  154. if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
  155. tooltipInfo.setErrorUidl(uidl.getErrors());
  156. } else {
  157. tooltipInfo.setErrorUidl(null);
  158. }
  159. // Set captions
  160. if (delegateCaptionHandling()) {
  161. getParent().updateCaption(this, uidl);
  162. }
  163. /*
  164. * updateComponentSize need to be after caption update so caption can be
  165. * taken into account
  166. */
  167. getConnection().updateComponentSize(this);
  168. }
  169. /**
  170. * Sets the enabled state of this paintable
  171. *
  172. * @param enabled
  173. * true if the paintable is enabled, false otherwise
  174. */
  175. protected void setEnabled(boolean enabled) {
  176. this.enabled = enabled;
  177. if (getWidgetForPaintable() instanceof FocusWidget) {
  178. FocusWidget fw = (FocusWidget) getWidgetForPaintable();
  179. fw.setEnabled(enabled);
  180. }
  181. }
  182. public boolean isEnabled() {
  183. return enabled;
  184. }
  185. /**
  186. * Return true if parent handles caption, false if the paintable handles the
  187. * caption itself.
  188. *
  189. *
  190. * @deprecated This should always return true and all components should let
  191. * the parent handle the caption and use other attributes for
  192. * internal texts in the component
  193. * @return
  194. */
  195. @Deprecated
  196. protected boolean delegateCaptionHandling() {
  197. return true;
  198. }
  199. /**
  200. * Sets the visible state for this paintable.
  201. *
  202. * @param visible
  203. * true if the paintable should be made visible, false otherwise
  204. * @param captionUidl
  205. * The UIDL that is passed to the parent and onwards to VCaption
  206. * if the caption needs to be updated as a result of the
  207. * visibility change.
  208. */
  209. protected void setVisible(boolean visible, UIDL captionUidl) {
  210. boolean wasVisible = this.visible;
  211. this.visible = visible;
  212. getWidgetForPaintable().setVisible(visible);
  213. if (wasVisible != visible) {
  214. // Changed invisibile <-> visible
  215. if (wasVisible && delegateCaptionHandling()) {
  216. // Must hide caption when component is hidden
  217. getParent().updateCaption(this, captionUidl);
  218. }
  219. }
  220. }
  221. protected boolean isVisible() {
  222. return visible;
  223. }
  224. /**
  225. * Generates the style name for the widget based on the given primary style
  226. * name (typically returned by Widget.getPrimaryStyleName()) and the UIDL.
  227. * An additional "modified" style name can be added if the field parameter
  228. * is set to true.
  229. *
  230. * @param primaryStyleName
  231. * @param uidl
  232. * @param isField
  233. * @return
  234. */
  235. protected static String getStyleNameFromUIDL(String primaryStyleName,
  236. UIDL uidl, boolean field) {
  237. boolean enabled = !uidl.getBooleanAttribute("disabled");
  238. StringBuffer styleBuf = new StringBuffer();
  239. styleBuf.append(primaryStyleName);
  240. // first disabling and read-only status
  241. if (!enabled) {
  242. styleBuf.append(" ");
  243. styleBuf.append(ApplicationConnection.DISABLED_CLASSNAME);
  244. }
  245. if (uidl.getBooleanAttribute("readonly")) {
  246. styleBuf.append(" ");
  247. styleBuf.append("v-readonly");
  248. }
  249. // add additional styles as css classes, prefixed with component default
  250. // stylename
  251. if (uidl.hasAttribute("style")) {
  252. final String[] styles = uidl.getStringAttribute("style").split(" ");
  253. for (int i = 0; i < styles.length; i++) {
  254. styleBuf.append(" ");
  255. styleBuf.append(primaryStyleName);
  256. styleBuf.append("-");
  257. styleBuf.append(styles[i]);
  258. styleBuf.append(" ");
  259. styleBuf.append(styles[i]);
  260. }
  261. }
  262. // add modified classname to Fields
  263. if (field && uidl.hasAttribute("modified")) {
  264. styleBuf.append(" ");
  265. styleBuf.append(ApplicationConnection.MODIFIED_CLASSNAME);
  266. }
  267. // add error classname to components w/ error
  268. if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
  269. styleBuf.append(" ");
  270. styleBuf.append(primaryStyleName);
  271. styleBuf.append(ApplicationConnection.ERROR_CLASSNAME_EXT);
  272. }
  273. // add required style to required components
  274. if (uidl.hasAttribute("required")) {
  275. styleBuf.append(" ");
  276. styleBuf.append(primaryStyleName);
  277. styleBuf.append(ApplicationConnection.REQUIRED_CLASSNAME_EXT);
  278. }
  279. return styleBuf.toString();
  280. }
  281. }