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.9KB

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