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.

TreeConnector.java 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.Iterator;
  6. import com.google.gwt.core.client.GWT;
  7. import com.google.gwt.user.client.ui.Widget;
  8. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  9. import com.vaadin.terminal.gwt.client.TooltipInfo;
  10. import com.vaadin.terminal.gwt.client.UIDL;
  11. import com.vaadin.terminal.gwt.client.ui.VTree.TreeNode;
  12. public class TreeConnector extends AbstractComponentConnector {
  13. public static final String ATTRIBUTE_NODE_STYLE = "style";
  14. public static final String ATTRIBUTE_NODE_CAPTION = "caption";
  15. public static final String ATTRIBUTE_NODE_ICON = "icon";
  16. public static final String ATTRIBUTE_ACTION_CAPTION = "caption";
  17. public static final String ATTRIBUTE_ACTION_ICON = ATTRIBUTE_NODE_ICON;
  18. @Override
  19. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  20. // Ensure correct implementation and let container manage caption
  21. super.updateFromUIDL(uidl, client);
  22. if (!isRealUpdate(uidl)) {
  23. return;
  24. }
  25. getWidget().rendering = true;
  26. getWidget().client = client;
  27. if (uidl.hasAttribute("partialUpdate")) {
  28. handleUpdate(uidl);
  29. getWidget().rendering = false;
  30. return;
  31. }
  32. getWidget().paintableId = uidl.getId();
  33. getWidget().immediate = getState().isImmediate();
  34. getWidget().disabled = !getState().isEnabled();
  35. getWidget().readonly = getState().isReadOnly();
  36. getWidget().dragMode = uidl.hasAttribute("dragMode") ? uidl
  37. .getIntAttribute("dragMode") : 0;
  38. getWidget().isNullSelectionAllowed = uidl
  39. .getBooleanAttribute("nullselect");
  40. if (uidl.hasAttribute("alb")) {
  41. getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb");
  42. }
  43. getWidget().body.clear();
  44. // clear out any references to nodes that no longer are attached
  45. getWidget().clearNodeToKeyMap();
  46. TreeNode childTree = null;
  47. UIDL childUidl = null;
  48. for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
  49. childUidl = (UIDL) i.next();
  50. if ("actions".equals(childUidl.getTag())) {
  51. updateActionMap(childUidl);
  52. continue;
  53. } else if ("-ac".equals(childUidl.getTag())) {
  54. getWidget().updateDropHandler(childUidl);
  55. continue;
  56. }
  57. childTree = getWidget().new TreeNode();
  58. updateNodeFromUIDL(childTree, childUidl);
  59. getWidget().body.add(childTree);
  60. childTree.addStyleDependentName("root");
  61. childTree.childNodeContainer.addStyleDependentName("root");
  62. }
  63. if (childTree != null && childUidl != null) {
  64. boolean leaf = !childUidl.getTag().equals("node");
  65. childTree.addStyleDependentName(leaf ? "leaf-last" : "last");
  66. childTree.childNodeContainer.addStyleDependentName("last");
  67. }
  68. final String selectMode = uidl.getStringAttribute("selectmode");
  69. getWidget().selectable = !"none".equals(selectMode);
  70. getWidget().isMultiselect = "multi".equals(selectMode);
  71. if (getWidget().isMultiselect) {
  72. getWidget().multiSelectMode = uidl
  73. .getIntAttribute("multiselectmode");
  74. }
  75. getWidget().selectedIds = uidl.getStringArrayVariableAsSet("selected");
  76. // Update lastSelection and focusedNode to point to *actual* nodes again
  77. // after the old ones have been cleared from the body. This fixes focus
  78. // and keyboard navigation issues as described in #7057 and other
  79. // tickets.
  80. if (getWidget().lastSelection != null) {
  81. getWidget().lastSelection = getWidget().getNodeByKey(
  82. getWidget().lastSelection.key);
  83. }
  84. if (getWidget().focusedNode != null) {
  85. getWidget().setFocusedNode(
  86. getWidget().getNodeByKey(getWidget().focusedNode.key));
  87. }
  88. if (getWidget().lastSelection == null
  89. && getWidget().focusedNode == null
  90. && !getWidget().selectedIds.isEmpty()) {
  91. getWidget().setFocusedNode(
  92. getWidget().getNodeByKey(
  93. getWidget().selectedIds.iterator().next()));
  94. getWidget().focusedNode.setFocused(false);
  95. }
  96. getWidget().rendering = false;
  97. }
  98. @Override
  99. protected Widget createWidget() {
  100. return GWT.create(VTree.class);
  101. }
  102. @Override
  103. public VTree getWidget() {
  104. return (VTree) super.getWidget();
  105. }
  106. private void handleUpdate(UIDL uidl) {
  107. final TreeNode rootNode = getWidget().getNodeByKey(
  108. uidl.getStringAttribute("rootKey"));
  109. if (rootNode != null) {
  110. if (!rootNode.getState()) {
  111. // expanding node happened server side
  112. rootNode.setState(true, false);
  113. }
  114. renderChildNodes(rootNode, (Iterator) uidl.getChildIterator());
  115. }
  116. }
  117. /**
  118. * Registers action for the root and also for individual nodes
  119. *
  120. * @param uidl
  121. */
  122. private void updateActionMap(UIDL uidl) {
  123. final Iterator<?> it = uidl.getChildIterator();
  124. while (it.hasNext()) {
  125. final UIDL action = (UIDL) it.next();
  126. final String key = action.getStringAttribute("key");
  127. final String caption = action
  128. .getStringAttribute(ATTRIBUTE_ACTION_CAPTION);
  129. String iconUrl = null;
  130. if (action.hasAttribute(ATTRIBUTE_ACTION_ICON)) {
  131. iconUrl = getConnection().translateVaadinUri(
  132. action.getStringAttribute(ATTRIBUTE_ACTION_ICON));
  133. }
  134. getWidget().registerAction(key, caption, iconUrl);
  135. }
  136. }
  137. public void updateNodeFromUIDL(TreeNode treeNode, UIDL uidl) {
  138. String nodeKey = uidl.getStringAttribute("key");
  139. treeNode.setText(uidl.getStringAttribute(ATTRIBUTE_NODE_CAPTION));
  140. treeNode.key = nodeKey;
  141. getWidget().registerNode(treeNode);
  142. if (uidl.hasAttribute("al")) {
  143. treeNode.actionKeys = uidl.getStringArrayAttribute("al");
  144. }
  145. if (uidl.getTag().equals("node")) {
  146. if (uidl.getChildCount() == 0) {
  147. treeNode.childNodeContainer.setVisible(false);
  148. } else {
  149. renderChildNodes(treeNode, (Iterator) uidl.getChildIterator());
  150. treeNode.childrenLoaded = true;
  151. }
  152. } else {
  153. treeNode.addStyleName(TreeNode.CLASSNAME + "-leaf");
  154. }
  155. if (uidl.hasAttribute(ATTRIBUTE_NODE_STYLE)) {
  156. treeNode.setNodeStyleName(uidl
  157. .getStringAttribute(ATTRIBUTE_NODE_STYLE));
  158. }
  159. String description = uidl.getStringAttribute("descr");
  160. if (description != null && getConnection() != null) {
  161. // Set tooltip
  162. TooltipInfo info = new TooltipInfo(description);
  163. getConnection().registerTooltip(this, nodeKey, info);
  164. } else {
  165. // Remove possible previous tooltip
  166. getConnection().registerTooltip(this, nodeKey, null);
  167. }
  168. if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) {
  169. treeNode.setState(true, false);
  170. }
  171. if (uidl.getBooleanAttribute("selected")) {
  172. treeNode.setSelected(true);
  173. // ensure that identifier is in selectedIds array (this may be a
  174. // partial update)
  175. getWidget().selectedIds.add(nodeKey);
  176. }
  177. treeNode.setIcon(uidl.getStringAttribute(ATTRIBUTE_NODE_ICON));
  178. }
  179. void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i) {
  180. containerNode.childNodeContainer.clear();
  181. containerNode.childNodeContainer.setVisible(true);
  182. while (i.hasNext()) {
  183. final UIDL childUidl = i.next();
  184. // actions are in bit weird place, don't mix them with children,
  185. // but current node's actions
  186. if ("actions".equals(childUidl.getTag())) {
  187. updateActionMap(childUidl);
  188. continue;
  189. }
  190. final TreeNode childTree = getWidget().new TreeNode();
  191. updateNodeFromUIDL(childTree, childUidl);
  192. containerNode.childNodeContainer.add(childTree);
  193. if (!i.hasNext()) {
  194. childTree
  195. .addStyleDependentName(childTree.isLeaf() ? "leaf-last"
  196. : "last");
  197. childTree.childNodeContainer.addStyleDependentName("last");
  198. }
  199. }
  200. containerNode.childrenLoaded = true;
  201. }
  202. }