001: /*
002: * MyGWT Widget Library
003: * Copyright(c) 2007, MyGWT.
004: * licensing@mygwt.net
005: *
006: * http://mygwt.net/license
007: */
008: package net.mygwt.ui.client.widget.tree;
009:
010: import net.mygwt.ui.client.Events;
011: import net.mygwt.ui.client.MyDOM;
012: import net.mygwt.ui.client.MyGWT;
013: import net.mygwt.ui.client.Style;
014: import net.mygwt.ui.client.event.BaseEvent;
015: import net.mygwt.ui.client.event.Listener;
016: import net.mygwt.ui.client.fx.FXStyle;
017: import net.mygwt.ui.client.util.Markup;
018:
019: import com.google.gwt.user.client.DOM;
020: import com.google.gwt.user.client.Element;
021:
022: public class TreeItemUI {
023:
024: protected static Listener clickListener = new Listener() {
025: public void handleEvent(BaseEvent be) {
026: if (be.type == Events.Click) {
027: TreeItem item = (TreeItem) be.widget;
028: Element target = be.getTarget();
029: if (target != null && be.within(item.getUI().jointEl)) {
030: item.toggle();
031: }
032: be.cancelBubble();
033: } else if (be.type == Events.DoubleClick) {
034: TreeItem item = (TreeItem) be.widget;
035: item.toggle();
036: }
037: }
038: };
039: protected static Listener mouseListener = new Listener() {
040: public void handleEvent(BaseEvent be) {
041: int type = be.type;
042: TreeItem item = (TreeItem) be.widget;
043: switch (type) {
044: case Events.MouseOver:
045: item.getUI().onOverChange(true);
046: break;
047: case Events.MouseOut:
048: item.getUI().onOverChange(false);
049: break;
050: }
051: be.cancelBubble();
052: }
053: };
054: private static Listener jointListener = new Listener() {
055: public void handleEvent(BaseEvent be) {
056: int type = be.type;
057: TreeItem item = (TreeItem) be.widget;
058: switch (type) {
059: case Events.MouseOver:
060: MyDOM.setStyleName(item.getUI().itemEl,
061: item.getUI().styleTreeJointOver, true);
062: break;
063: case Events.MouseOut:
064: MyDOM.setStyleName(item.getUI().itemEl,
065: item.getUI().styleTreeJointOver, false);
066: break;
067: }
068: be.stopEvent();
069: }
070: };
071:
072: protected int indentWidth = 18;
073: protected Element containerEl;
074: protected Element jointEl, jointDivEl;
075:
076: protected TreeItem item;
077: protected Element itemEl, indentEl;
078: protected Element checkEl, checkDivEl;
079: protected Element iconEl, iconDivEl;
080: protected Element textEl, textSpanEl;
081: private String textStyle;
082:
083: protected String styleTreeOver = "my-tree-over";
084: protected String styleTreeJointOver = "my-tree-joint-over";
085: protected String styleTreeChecked = "my-tree-checked";
086: protected String styleTreeNotChecked = "my-tree-notchecked";
087: protected String styleTreeLoading = "my-tree-loading";
088: protected String styleTreeSelected = "my-tree-sel";
089: protected String classTreeOpen = "my-tree-open";
090: protected String classTreeClose = "my-tree-close";
091:
092: protected static Listener listener = new Listener() {
093: public void handleEvent(BaseEvent be) {
094: int type = be.type;
095: TreeItem item = (TreeItem) be.widget;
096: TreeItemUI ui = item.getUI();
097: Element target = be.getTarget();
098: switch (type) {
099: case Events.Click:
100: case Events.DoubleClick:
101: if (DOM.isOrHasChild(ui.checkEl, target)) {
102: be.stopEvent();
103: item.setChecked(!item.isChecked());
104: } else {
105: clickListener.handleEvent(be);
106: }
107: return;
108: case Events.MouseOver:
109: case Events.MouseOut:
110: if (DOM.isOrHasChild(ui.jointEl, target)) {
111: jointListener.handleEvent(be);
112:
113: } else if (DOM.isOrHasChild(ui.iconEl, target)
114: || DOM.isOrHasChild(ui.textEl, target)
115: || DOM.isOrHasChild(ui.checkEl, target)) {
116: mouseListener.handleEvent(be);
117: }
118: break;
119: }
120:
121: }
122: };
123:
124: public TreeItemUI(TreeItem item) {
125: this .item = item;
126: render();
127: }
128:
129: public void onMouseOut(BaseEvent be) {
130:
131: }
132:
133: public void collapse() {
134: if (item.isRoot()) {
135: return;
136: }
137: updateJoint();
138: onIconStyleChange(null);
139: if (item.tree.getAnimate()) {
140: animCollapse();
141: } else {
142: MyDOM.setVisible(containerEl, false);
143: afterCollapse();
144: }
145: }
146:
147: public void expand() {
148: if (item.isRoot()) {
149: return;
150: }
151: updateJoint();
152: if (item.getItemCount() == 0) {
153: return;
154: }
155: onIconStyleChange(null);
156: if (item.tree.getAnimate()) {
157: animExpand();
158: } else {
159: MyDOM.setVisible(containerEl, true);
160: afterExpand();
161: }
162: }
163:
164: public Element getJointEl() {
165: return jointEl;
166: }
167:
168: public Element getCheckEl() {
169: return checkEl;
170: }
171:
172: public void onCheckChange(boolean checked) {
173: String cls = checked ? styleTreeChecked : styleTreeNotChecked;
174: MyDOM.setStyleName(checkDivEl, cls);
175: item.fireEvent(Events.CheckChange);
176: }
177:
178: public void onClick(BaseEvent be) {
179: Element target = be.getTarget();
180: if (target != null && be.within(jointEl)) {
181: item.toggle();
182: }
183: be.cancelBubble();
184: }
185:
186: public void onDoubleClick(BaseEvent be) {
187: item.toggle();
188: be.cancelBubble();
189: }
190:
191: public void onLoadingChange(boolean loading) {
192: if (loading) {
193: item.addStyleName(styleTreeLoading);
194: } else {
195: item.removeStyleName(styleTreeLoading);
196: }
197: }
198:
199: public void onIconStyleChange(String style) {
200: if (item.iconStyle != null) {
201: MyDOM.setVisible(iconEl, true);
202: MyDOM.setStyleName(iconDivEl, item.iconStyle);
203: return;
204: }
205: if (!item.leaf) {
206: String s = "";
207: if (item.isExpanded()
208: && item.tree.getOpenNodeImageStyle() != null) {
209: s = item.tree.getOpenNodeImageStyle();
210: } else if (item.isExpanded()
211: && item.tree.getNodeImageStyle() != null) {
212: s = item.tree.getNodeImageStyle();
213: } else if (!item.isExpanded()) {
214: s = item.tree.getNodeImageStyle();
215: }
216: MyDOM.setVisible(iconEl, true);
217: MyDOM.setStyleName(iconDivEl, s);
218: } else {
219: MyDOM.setVisible(iconEl, true);
220: MyDOM
221: .setStyleName(iconDivEl, item.tree
222: .getItemImageStyle());
223: return;
224: }
225:
226: }
227:
228: public void onSelectedChange(boolean selected) {
229: if (item.isRendered()) {
230: MyDOM.setStyleName(itemEl, styleTreeSelected, selected);
231: if (!selected) {
232: onOverChange(false);
233: }
234: }
235: }
236:
237: public void onOverChange(boolean over) {
238: MyDOM.setStyleName(itemEl, styleTreeOver, over);
239: }
240:
241: public void removeItem(TreeItem child) {
242: DOM.removeChild(containerEl, child.getElement());
243: }
244:
245: protected void afterCollapse() {
246: item.tree.enable();
247: MyDOM.setStyleName(itemEl, styleTreeJointOver, false);
248: item.fireEvent(Events.Collapse);
249: }
250:
251: protected void afterExpand() {
252: item.tree.enable();
253: MyDOM.setStyleName(itemEl, styleTreeJointOver, false);
254:
255: item.fireEvent(Events.Expand);
256: }
257:
258: protected void onTextChange(String text) {
259: if (!item.root) {
260: MyDOM.setInnerHTML(textSpanEl, text);
261: }
262: }
263:
264: public Listener getListener() {
265: return listener;
266: }
267:
268: protected void onTextStyleChange(String style) {
269: if (textStyle != null) {
270: MyDOM.removeStyleName(textEl, textStyle);
271: }
272: textStyle = style;
273: if (style != null) {
274: MyDOM.addStyleName(textEl, style);
275: }
276: }
277:
278: protected void render() {
279: if (item.isRoot() == true) {
280: return;
281: }
282: item.setElement(DOM.createDiv());
283: item.setStyleName("my-treeitem");
284:
285: int index = item.parentItem.indexOf(item);
286: DOM.insertChild(item.parentItem.getUI().containerEl, item
287: .getElement(), index);
288:
289: DOM.setInnerHTML(item.getElement(), Markup.TREE_ITEM);
290: itemEl = DOM.getFirstChild(item.getElement());
291: Element td = MyDOM.getSubChild(itemEl, 3);
292: indentEl = DOM.getFirstChild(td);
293: jointEl = DOM.getNextSibling(td);
294: jointDivEl = DOM.getFirstChild(jointEl);
295: checkEl = DOM.getNextSibling(DOM.getNextSibling(jointEl));
296: checkDivEl = DOM.getFirstChild(checkEl);
297: iconEl = DOM.getNextSibling(checkEl);
298: iconDivEl = DOM.getFirstChild(iconEl);
299: textEl = DOM.getNextSibling(iconEl);
300: textSpanEl = DOM.getFirstChild(textEl);
301: Element tbl = DOM.getFirstChild(item.getElement());
302: containerEl = DOM.getNextSibling(tbl);
303:
304: int style = item.tree.getStyle();
305: if ((style & Style.CHECK) != 0) {
306: MyDOM.setVisible(checkEl, true);
307: } else {
308: MyDOM.setVisible(checkEl, false);
309: }
310:
311: onTextChange(item.getText());
312: onIconStyleChange(item.getIconStyle());
313:
314: if (item.getTextStyle() != null) {
315: onTextStyleChange(item.getTextStyle());
316: }
317:
318: if (item.isChecked()) {
319: onCheckChange(true);
320: }
321:
322: MyDOM.setWidth(indentEl, getIndent());
323:
324: if (!MyGWT.isIE) {
325: DOM.setElementPropertyInt(item.getElement(), "tabIndex", 0);
326: }
327:
328: updateJoint();
329: item.disableTextSelection(true);
330:
331: }
332:
333: void animCollapse() {
334: FXStyle fx = new FXStyle(containerEl);
335: fx.duration = 300;
336: fx.addListener(Events.EffectComplete, new Listener() {
337: public void handleEvent(BaseEvent be) {
338: afterCollapse();
339: }
340: });
341: item.tree.disable();
342: fx.slideOut(Style.NORTH);
343: }
344:
345: void animExpand() {
346: FXStyle fx = new FXStyle(containerEl);
347: fx.duration = 300;
348: fx.addListener(Events.EffectComplete, new Listener() {
349: public void handleEvent(BaseEvent be) {
350: afterExpand();
351: }
352: });
353: item.tree.disable();
354: fx.slideIn(Style.SOUTH);
355: }
356:
357: public void updateJoint() {
358: if (item.isRoot()) {
359: return;
360: }
361: if (!item.leaf) {
362: String cls = item.isExpanded() ? classTreeOpen
363: : classTreeClose;
364: MyDOM.setStyleName(jointDivEl, cls);
365: } else {
366: MyDOM.setStyleName(jointDivEl, "none");
367: }
368:
369: int style = item.tree.getStyle();
370: if ((style & Style.CHECK) != 0) {
371: switch (item.tree.checkNodes) {
372: case Style.DEFAULT:
373: MyDOM.setVisible(checkEl, true);
374: break;
375: case Style.PARENT:
376: MyDOM.setVisible(checkEl, !item.isLeaf());
377: break;
378: case Style.LEAF:
379: MyDOM.setVisible(checkEl, item.isLeaf());
380: break;
381: }
382:
383: }
384: }
385:
386: protected int getIndent() {
387: return (item.getDepth() - 1) * item.tree.getIndentWidth();
388: }
389: }
|