View Javadoc

1   /*
2    * Ext GWT 2.2.5 - Ext for GWT
3    * Copyright(c) 2007-2010, Ext JS, LLC.
4    * licensing@extjs.com
5    * 
6    * http://extjs.com/license
7    */
8   package com.extjs.gxt.ui.client.widget.treepanel;
9   
10  import com.extjs.gxt.ui.client.GXT;
11  import com.extjs.gxt.ui.client.aria.FocusFrame;
12  import com.extjs.gxt.ui.client.core.El;
13  import com.extjs.gxt.ui.client.core.XDOM;
14  import com.extjs.gxt.ui.client.data.ModelData;
15  import com.extjs.gxt.ui.client.event.Events;
16  import com.extjs.gxt.ui.client.event.TreePanelEvent;
17  import com.extjs.gxt.ui.client.store.Store;
18  import com.extjs.gxt.ui.client.store.TreeStore;
19  import com.extjs.gxt.ui.client.util.IconHelper;
20  import com.extjs.gxt.ui.client.util.Util;
21  import com.extjs.gxt.ui.client.widget.Component;
22  import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.Joint;
23  import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.TreeNode;
24  import com.google.gwt.dom.client.NodeList;
25  import com.google.gwt.user.client.DOM;
26  import com.google.gwt.user.client.Element;
27  import com.google.gwt.user.client.Event;
28  import com.google.gwt.user.client.ui.AbstractImagePrototype;
29  import com.google.gwt.user.client.ui.Accessibility;
30  
31  @SuppressWarnings({"unchecked", "rawtypes"})
32  public class TreePanelView<M extends ModelData> {
33  
34    public enum TreeViewRenderMode {
35      ALL, BODY, CONTAINER, MAIN
36    };
37  
38    protected TreeNode over;
39    protected TreePanel<M> tree;
40    protected TreeStore<M> treeStore;
41  
42    private int cacheSize = 20;
43    private int cleanDelay = 500;
44    private int scrollDelay = 0;
45  
46    public void bind(Component component, Store store) {
47      this.tree = (TreePanel) component;
48      this.treeStore = (TreeStore) store;
49    }
50  
51    public void collapse(TreeNode node) {
52      getContainer(node).getStyle().setProperty("display", "none");
53      tree.refresh((M) node.m);
54      if (GXT.isFocusManagerEnabled()) {
55        Accessibility.setState((Element) node.getElement().getFirstChildElement(), "aria-expanded", "false");
56        FocusFrame.get().sync(tree);
57      }
58    }
59  
60    public void expand(TreeNode node) {
61      getContainer(node).getStyle().setProperty("display", "block");
62      tree.refresh((M) node.m);
63      if (GXT.isFocusManagerEnabled()) {
64        FocusFrame.get().sync(tree);
65        Accessibility.setState((Element) node.getElement().getFirstChildElement(), "aria-expanded", "true");
66      }
67    }
68  
69    public int getCacheSize() {
70      return cacheSize;
71    }
72  
73    public Element getCheckElement(TreeNode node) {
74      if (node.check == null) {
75        node.check = getElementContainer(node) != null
76            ? ((NodeList<Element>) getElementContainer(node).getChildNodes().cast()).getItem(2) : null;
77      }
78      return node.check;
79    }
80  
81    public int getCleanDelay() {
82      return cleanDelay;
83    }
84  
85    public Element getContainer(TreeNode node) {
86      if (node.container == null) {
87        String s = getTemplate(node.m, null, null, null, false, false, null, 0, TreeViewRenderMode.CONTAINER);
88        node.container = node.getElement().appendChild(XDOM.create(s));
89      }
90      return node.container;
91    }
92  
93    public Element getElementContainer(TreeNode node) {
94      if (node.elContainer == null) {
95        node.elContainer = node.getElement() != null ? (Element) node.getElement().getFirstChild() : null;
96      }
97      return node.elContainer;
98    }
99  
100   public Element getIconElement(TreeNode node) {
101     if (node.icon == null) {
102       node.icon = getElementContainer(node) != null
103           ? ((NodeList<Element>) getElementContainer(node).getChildNodes().cast()).getItem(3) : null;
104     }
105     return node.icon;
106   }
107 
108   public Element getJointElement(TreeNode node) {
109     if (node.joint == null) {
110       node.joint = ((NodeList<Element>) getElementContainer(node).getChildNodes().cast()).getItem(1);
111     }
112     return node.joint;
113   }
114 
115   public int getScrollDelay() {
116     return scrollDelay;
117   }
118 
119   public String getTemplate(ModelData m, String id, String text, AbstractImagePrototype icon, boolean checkable,
120       boolean checked, Joint joint, int level, TreeViewRenderMode renderMode) {
121     if (renderMode == TreeViewRenderMode.CONTAINER) {
122       return "<div unselectable=on class=\"x-tree3-node-ct\" role=\"group\"></div>";
123     }
124     StringBuilder sb = new StringBuilder();
125     if (renderMode == TreeViewRenderMode.ALL || renderMode == TreeViewRenderMode.MAIN) {
126       sb.append("<div unselectable=on id=\"");
127       sb.append(id);
128       sb.append("\"");
129 
130       sb.append(" class=\"x-tree3-node\"  role=\"presentation\">");
131 
132       String cls = "x-tree3-el";
133       if (GXT.isHighContrastMode) {
134         switch (joint) {
135           case COLLAPSED:
136             cls += " x-tree3-node-joint-collapse";
137             break;
138           case EXPANDED:
139             cls += " x-tree3-node-joint-expand";
140             break;
141         }
142       }
143 
144       sb.append("<div unselectable=on class=\"" + cls + "\" id=\"" + tree.getId() + "__" + id + "\" role=\"treeitem\" ");
145       sb.append(" aria-level=\"" + (level + 1) + "\">");
146     }
147     if (renderMode == TreeViewRenderMode.ALL || renderMode == TreeViewRenderMode.BODY) {
148       Element jointElement = null;
149       switch (joint) {
150         case COLLAPSED:
151           jointElement = (Element) tree.getStyle().getJointCollapsedIcon().createElement().cast();
152           break;
153         case EXPANDED:
154           jointElement = (Element) tree.getStyle().getJointExpandedIcon().createElement().cast();
155           break;
156       }
157 
158       if (jointElement != null) {
159         El.fly(jointElement).addStyleName("x-tree3-node-joint");
160       }
161 
162       sb.append("<img src=\"");
163       sb.append(GXT.BLANK_IMAGE_URL);
164       sb.append("\" style=\"height: 18px; width: ");
165       sb.append(level * getIndenting(findNode((M) m)));
166       sb.append("px;\" />");
167       sb.append(jointElement == null ? "<img src=\"" + GXT.BLANK_IMAGE_URL
168           + "\" style=\"width: 16px\" class=\"x-tree3-node-joint\" />" : DOM.toString(jointElement));
169       if (checkable) {
170         Element e = (Element) (checked ? GXT.IMAGES.checked().createElement().cast()
171             : GXT.IMAGES.unchecked().createElement().cast());
172         El.fly(e).addStyleName("x-tree3-node-check");
173         sb.append(DOM.toString(e));
174       } else {
175         sb.append("<span class=\"x-tree3-node-check\"></span>");
176       }
177       if (icon != null) {
178         Element e = icon.createElement().cast();
179         El.fly(e).addStyleName("x-tree3-node-icon");
180         sb.append(DOM.toString(e));
181       } else {
182         sb.append("<span class=\"x-tree3-node-icon\"></span>");
183       }
184       sb.append("<span  unselectable=on class=\"x-tree3-node-text\">");
185       sb.append(text);
186       sb.append("</span>");
187     }
188 
189     if (renderMode == TreeViewRenderMode.ALL || renderMode == TreeViewRenderMode.MAIN) {
190       sb.append("</div>");
191       sb.append("</div>");
192     }
193     return sb.toString();
194   }
195 
196   public Element getTextElement(TreeNode node) {
197     if (node.text == null) {
198       node.text = getElementContainer(node) != null
199           ? ((NodeList<Element>) getElementContainer(node).getChildNodes().cast()).getItem(4) : null;
200     }
201     return node.text;
202 
203   }
204 
205   public boolean isSelectableTarget(M m, Element target) {
206     TreeNode n = findNode(m);
207     if (n == null) {
208       return false;
209     }
210     boolean isNotJointTarget = false;
211     if (GXT.isIE6) {
212       isNotJointTarget = !El.fly(target).getParent().hasStyleName("x-tree3-node-joint");
213     } else {
214       isNotJointTarget = !El.fly(target).hasStyleName("x-tree3-node-joint");
215     }
216     if (isNotJointTarget && tree.isCheckable()) {
217       boolean isNotCheckTarget = !El.fly(target).hasStyleName("x-tree3-node-check");
218       return isNotCheckTarget;
219     }
220     return isNotJointTarget;
221   }
222   
223   public void onCheckChange(TreeNode node, boolean checkable, boolean check) {
224     Element checkEl = (Element) getCheckElement(node);
225     if (checkEl != null) {
226       Element e;
227       if (checkable) {
228         if (check) {
229           e = (Element) GXT.IMAGES.checked().createElement().cast();
230         } else {
231           e = (Element) GXT.IMAGES.unchecked().createElement().cast();
232         }
233       } else {
234         e = DOM.createSpan();
235       }
236       El.fly(e).addStyleName("x-tree3-node-check");
237       node.check = (Element) node.getElement().getFirstChild().insertBefore(e, checkEl);
238       El.fly(checkEl).remove();
239     }
240   }
241 
242   public void onDropChange(TreeNode node, boolean drop) {
243     El.fly(getElementContainer(node)).setStyleName("x-ftree2-node-drop", drop);
244   }
245 
246   public void onEvent(TreePanelEvent ce) {
247     int type = ce.getEventTypeInt();
248     switch (type) {
249       case Event.ONMOUSEOVER:
250         if (tree.isTrackMouseOver()) {
251           onMouseOver(ce);
252         }
253         break;
254       case Event.ONMOUSEOUT:
255         if (tree.isTrackMouseOver()) {
256           onMouseOut(ce);
257         }
258         break;
259     }
260   }
261 
262   public void onIconStyleChange(TreeNode node, AbstractImagePrototype icon) {
263     Element iconEl = getIconElement(node);
264     if (iconEl != null) {
265       Element e;
266       if (icon != null) {
267         e = (Element) icon.createElement().cast();
268       } else {
269         e = DOM.createSpan();
270       }
271       El.fly(e).addStyleName("x-tree3-node-icon");
272       node.icon = (Element) node.getElement().getFirstChild().insertBefore(e, iconEl);
273       El.fly(iconEl).remove();
274     }
275   }
276 
277   public void onJointChange(TreeNode node, Joint joint) {
278     Element jointEl = getJointElement(node);
279     if (jointEl != null) {
280       Element e;
281       switch (joint) {
282         case COLLAPSED:
283           e = (Element) tree.getStyle().getJointCollapsedIcon().createElement().cast();
284           if (GXT.isHighContrastMode) {
285             El.fly(node.elContainer).addStyleName("x-tree3-node-joint-collapse").removeStyleName(
286                 "x-tree3-node-joint-expand");
287           }
288           break;
289         case EXPANDED:
290           e = (Element) tree.getStyle().getJointExpandedIcon().createElement().cast();
291           if (GXT.isHighContrastMode) {
292             El.fly(node.elContainer).addStyleName("x-tree3-node-joint-expand").removeStyleName(
293                 "x-tree3-node-joint-collapse");
294           }
295           break;
296         default:
297           e = XDOM.create("<img src=\"" + GXT.BLANK_IMAGE_URL + "\" width=\"16px\"/>");
298           if (GXT.isHighContrastMode) {
299             El.fly(node.elContainer).removeStyleName("x-tree3-node-joint-collapse").removeStyleName(
300                 "x-tree3-node-joint-expand");
301           }
302       }
303 
304       El.fly(e).addStyleName("x-tree3-node-joint");
305       node.joint = (Element) node.getElement().getFirstChild().insertBefore(e, jointEl);
306       El.fly(jointEl).remove();
307     }
308   }
309 
310   public void onLoading(TreeNode node) {
311     onIconStyleChange(node, IconHelper.createStyle("x-tree3-loading"));
312   }
313 
314   public void onOverChange(TreeNode node, boolean select) {
315     El.fly(getElementContainer(node)).setStyleName("x-ftree2-node-over", select);
316   }
317 
318   public void onSelectChange(M model, boolean select) {
319     if (select) {
320       tree.setExpanded(treeStore.getParent(model), true);
321     }
322     TreeNode node = findNode(model);
323     if (node != null) {
324       Element e = getElementContainer(node);
325       if (e != null) {
326         El.fly(e).setStyleName("x-ftree2-selected", select);
327         if (select) {
328           String tid = tree.getId();
329           Accessibility.setState(tree.getElement(), "aria-activedescendant", tid + "__" + node.getElement().getId());
330         }
331       }
332     }
333   }
334 
335   public void onTextChange(TreeNode node, String text) {
336     Element textEl = getTextElement(node);
337     if (textEl != null) {
338       textEl.setInnerHTML(Util.isEmptyString(text) ? "&#160;" : text);
339     }
340   }
341 
342   public void setCacheSize(int cacheSize) {
343     this.cacheSize = cacheSize;
344   }
345 
346   public void setCleanDelay(int cleanDelay) {
347     this.cleanDelay = cleanDelay;
348   }
349 
350   public void setScrollDelay(int scrollDelay) {
351     this.scrollDelay = scrollDelay;
352   }
353 
354   protected TreeNode findNode(M m){
355     return tree.findNode(m);
356   }
357 
358   protected int getCalculatedRowHeight() {
359     return 21;
360   }
361 
362   protected int getIndenting(TreeNode node) {
363     return 18;
364   }
365 
366   protected void onMouseOut(TreePanelEvent ce) {
367     if (over != null) {
368       onOverChange(over, false);
369       over = null;
370     }
371   }
372 
373   protected void onMouseOver(TreePanelEvent ce) {
374     if (ce.getNode() != null) {
375       if (over != ce.getNode()) {
376         /* begin laaglu */
377         tree.fireEvent(Events.OnMouseOver, ce);
378         /* end laaglu */
379         onMouseOut(ce);
380         over = ce.getNode();
381         onOverChange(over, true);
382       }
383     }
384   }
385 
386 }