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

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