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.

ITree.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package com.itmill.toolkit.terminal.gwt.client.ui;
  2. import java.util.HashMap;
  3. import java.util.HashSet;
  4. import java.util.Iterator;
  5. import java.util.Set;
  6. import com.google.gwt.user.client.DOM;
  7. import com.google.gwt.user.client.Element;
  8. import com.google.gwt.user.client.Event;
  9. import com.google.gwt.user.client.ui.Tree;
  10. import com.google.gwt.user.client.ui.TreeItem;
  11. import com.google.gwt.user.client.ui.TreeListener;
  12. import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
  13. import com.itmill.toolkit.terminal.gwt.client.Paintable;
  14. import com.itmill.toolkit.terminal.gwt.client.UIDL;
  15. /**
  16. * TODO todo dump GWT's Tree implementation and use Toolkit 4 style
  17. * DOM structure
  18. *
  19. */
  20. public class ITree extends Tree implements Paintable {
  21. public static final String CLASSNAME = "i-tree";
  22. Set selectedIds = new HashSet();
  23. ApplicationConnection client;
  24. String paintableId;
  25. private boolean selectable;
  26. private boolean multiselect;
  27. private HashMap keyToNode = new HashMap();
  28. /**
  29. * This map contains captions and icon urls for
  30. * actions like:
  31. * * "33_c" -> "Edit"
  32. * * "33_i" -> "http://dom.com/edit.png"
  33. */
  34. private HashMap actionMap = new HashMap();
  35. public ITree() {
  36. super();
  37. setStyleName(CLASSNAME);
  38. }
  39. private void updateActionMap(UIDL c) {
  40. Iterator it = c.getChildIterator();
  41. while(it.hasNext()) {
  42. UIDL action = (UIDL) it.next();
  43. String key = action.getStringAttribute("key");
  44. String caption = action.getStringAttribute("caption");
  45. actionMap.put(key + "_c", caption);
  46. if(action.hasAttribute("icon")) {
  47. // TODO need some uri handling ??
  48. actionMap.put(key + "_i", action.getStringAttribute("icon"));
  49. }
  50. }
  51. }
  52. public String getActionCaption(String actionKey) {
  53. return (String) actionMap.get(actionKey + "_c");
  54. }
  55. public String getActionIcon(String actionKey) {
  56. return (String) actionMap.get(actionKey + "_i");
  57. }
  58. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  59. // Ensure correct implementation and let container manage caption
  60. if (client.updateComponent(this, uidl, true))
  61. return;
  62. this.client = client;
  63. if(uidl.hasAttribute("partialUpdate")) {
  64. handleUpdate(uidl);
  65. return;
  66. }
  67. this.paintableId = uidl.getId();
  68. clear();
  69. for (Iterator i = uidl.getChildIterator(); i.hasNext();) {
  70. UIDL childUidl = (UIDL)i.next();
  71. if("actions".equals(childUidl.getTag())){
  72. updateActionMap(childUidl);
  73. continue;
  74. }
  75. TreeNode childTree = new TreeNode();
  76. addItem(childTree);
  77. childTree.updateFromUIDL(childUidl, client);
  78. }
  79. String selectMode = uidl.getStringAttribute("selectmode");
  80. selectable = selectMode != null;
  81. multiselect = "multi".equals(selectMode);
  82. addTreeListener(new TreeListener() {
  83. public void onTreeItemStateChanged(TreeItem item) {
  84. if (item instanceof TreeNode) {
  85. TreeNode tn = (TreeNode) item;
  86. if(item.getState()) {
  87. if(!tn.isChildrenLoaded()) {
  88. String key = tn.key;
  89. ITree.this.client.updateVariable(paintableId, "expand", new String[] {key}, true);
  90. }
  91. } else {
  92. // TODO collapse
  93. }
  94. }
  95. }
  96. public void onTreeItemSelected(TreeItem item) {
  97. TreeNode n = ((TreeNode) item);
  98. if (!selectable) return;
  99. String key = n.key;
  100. if (key != null) {
  101. if(selectedIds.contains(key) && multiselect) {
  102. selectedIds.remove(key);
  103. n.setISelected(false);
  104. } else {
  105. if (!multiselect)
  106. selectedIds.clear();
  107. selectedIds.add(key);
  108. n.setISelected(true);
  109. }
  110. ITree.this.client.updateVariable(ITree.this.paintableId, "selected", selectedIds.toArray(), true);
  111. }
  112. }
  113. });
  114. selectedIds = uidl.getStringArrayVariableAsSet("selected");
  115. }
  116. private void handleUpdate(UIDL uidl) {
  117. TreeNode rootNode = (TreeNode) keyToNode.get(uidl.getStringAttribute("rootKey"));
  118. if(rootNode != null) {
  119. rootNode.renderChildNodes(uidl.getChildIterator());
  120. }
  121. }
  122. private class TreeNode extends TreeItem implements IActionOwner {
  123. String key;
  124. boolean isLeaf = false;
  125. private String[] actionKeys = null;
  126. private boolean childrenLoaded;
  127. public TreeNode() {
  128. super();
  129. attachContextMenuEvent(getElement());
  130. }
  131. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  132. this.setText(uidl.getStringAttribute("caption"));
  133. key = uidl.getStringAttribute("key");
  134. keyToNode.put(key, this);
  135. if(uidl.hasAttribute("al"))
  136. actionKeys = uidl.getStringArrayAttribute("al");
  137. if(uidl.getTag().equals("node")) {
  138. isLeaf = false;
  139. if(uidl.getChidlCount() == 0) {
  140. TreeNode childTree = new TreeNode();
  141. childTree.setText("Loading...");
  142. childrenLoaded = false;
  143. this.addItem(childTree);
  144. } else {
  145. renderChildNodes(uidl.getChildIterator());
  146. }
  147. } else {
  148. isLeaf = true;
  149. }
  150. if(uidl.getBooleanAttribute("expanded") && !getState()) {
  151. setState(true);
  152. }
  153. setSelected(uidl.getBooleanAttribute("selected"));
  154. }
  155. private void renderChildNodes(Iterator i) {
  156. removeItems();
  157. while (i.hasNext()) {
  158. UIDL childUidl = (UIDL)i.next();
  159. if("actions".equals(childUidl.getTag())) {
  160. updateActionMap(childUidl);
  161. continue;
  162. }
  163. TreeNode childTree = new TreeNode();
  164. this.addItem(childTree);
  165. childTree.updateFromUIDL(childUidl, client);
  166. }
  167. childrenLoaded = true;
  168. }
  169. public boolean isChildrenLoaded() {
  170. return childrenLoaded;
  171. }
  172. public IAction[] getActions() {
  173. if(actionKeys == null)
  174. return new IAction[] {};
  175. IAction[] actions = new IAction[actionKeys.length];
  176. for (int i = 0; i < actions.length; i++) {
  177. String actionKey = actionKeys[i];
  178. ITreeAction a = new ITreeAction(this, String.valueOf(key), actionKey);
  179. a.setCaption(getActionCaption(actionKey));
  180. actions[i] = a;
  181. }
  182. return actions;
  183. }
  184. public ApplicationConnection getClient() {
  185. return client;
  186. }
  187. public String getPaintableId() {
  188. return paintableId;
  189. }
  190. /**
  191. * Adds/removes IT Mill Toolkit spesific style name.
  192. * (GWT treenode does not support multiselects)
  193. *
  194. * @param selected
  195. */
  196. public void setISelected(boolean selected) {
  197. setStyleName(getElement(), "i-tree-node-selected", selected);
  198. }
  199. public void showContextMenu(Event event) {
  200. if(actionKeys != null) {
  201. int left = DOM.eventGetClientX(event);
  202. int top = DOM.eventGetClientY(event);
  203. client.getContextMenu().showAt(this, left, top);
  204. }
  205. DOM.eventCancelBubble(event, true);
  206. }
  207. private native void attachContextMenuEvent(Element el) /*-{
  208. var node = this;
  209. el.oncontextmenu = function(e) {
  210. if(!e)
  211. e = $wnd.event;
  212. node.@com.itmill.toolkit.terminal.gwt.client.ui.ITree.TreeNode::showContextMenu(Lcom/google/gwt/user/client/Event;)(e);
  213. return false;
  214. };
  215. }-*/;
  216. }
  217. }