Source Code Cross Referenced for Tree.java in  » Ajax » zk » org » zkoss » zul » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » zk » org.zkoss.zul 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Tree.java
0002:
0003:        {{IS_NOTE
0004:        	Purpose:
0005:        		
0006:        	Description:
0007:        		
0008:        	History:
0009:        		Wed Jul  6 18:51:33     2005, Created by tomyeh
0010:        }}IS_NOTE
0011:
0012:        Copyright (C) 2005 Potix Corporation. All Rights Reserved.
0013:
0014:        {{IS_RIGHT
0015:        	This program is distributed under GPL Version 2.0 in the hope that
0016:        	it will be useful, but WITHOUT ANY WARRANTY.
0017:        }}IS_RIGHT
0018:         */
0019:        package org.zkoss.zul;
0020:
0021:        import java.util.Arrays;
0022:        import java.util.List;
0023:        import java.util.Set;
0024:        import java.util.LinkedHashSet;
0025:        import java.util.Iterator;
0026:        import java.util.ListIterator;
0027:        import java.util.Collection;
0028:        import java.util.Collections;
0029:        import java.util.AbstractCollection;
0030:        import java.util.ArrayList;
0031:
0032:        import org.zkoss.lang.Exceptions;
0033:        import org.zkoss.lang.Objects;
0034:        import org.zkoss.util.logging.Log;
0035:        import org.zkoss.xml.HTMLs;
0036:
0037:        import org.zkoss.zk.ui.Component;
0038:        import org.zkoss.zk.ui.UiException;
0039:        import org.zkoss.zk.ui.WrongValueException;
0040:        import org.zkoss.zk.ui.ext.client.Selectable;
0041:        import org.zkoss.zk.ui.ext.client.InnerWidth;
0042:        import org.zkoss.zk.ui.event.Event;
0043:        import org.zkoss.zk.ui.event.EventListener;
0044:        import org.zkoss.zk.ui.event.Events;
0045:
0046:        //import org.zkoss.zul.Listbox.Renderer;
0047:
0048:        import org.zkoss.zul.event.ListDataEvent;
0049:        import org.zkoss.zul.event.TreeDataEvent;
0050:        import org.zkoss.zul.event.TreeDataListener;
0051:        import org.zkoss.zul.impl.XulElement;
0052:
0053:        /**
0054:         *  A container which can be used to hold a tabular
0055:         * or hierarchical set of rows of elements.
0056:         *
0057:         * <p>Event:
0058:         * <ol>
0059:         * <li>org.zkoss.zk.ui.event.SelectEvent is sent when user changes
0060:         * the selection.</li>
0061:         * </ol>
0062:         *
0063:         * <p>Default {@link #getSclass}: tree.
0064:         *
0065:         * @author tomyeh
0066:         */
0067:        public class Tree extends XulElement {
0068:            private transient Treecols _treecols;
0069:            private transient Treefoot _treefoot;
0070:            private transient Treechildren _treechildren;
0071:            /** A list of selected items. */
0072:            private transient Set _selItems;
0073:            /** The first selected item. */
0074:            private transient Treeitem _sel;
0075:            private transient Collection _heads;
0076:            private int _rows = 0;
0077:            /** The name. */
0078:            private String _name;
0079:            /** The style class prefix for generating icons. */
0080:            private String _iconScls = "tree";
0081:            /** # of items per page. */
0082:            private int _pgsz = 10;
0083:            private boolean _multiple, _checkmark;
0084:            private boolean _vflex;
0085:            /** disable smartUpdate; usually caused by the client. */
0086:            private transient boolean _noSmartUpdate;
0087:            private String _innerWidth = "100%";
0088:
0089:            public Tree() {
0090:                init();
0091:                setSclass("tree");
0092:            }
0093:
0094:            private void init() {
0095:                _selItems = new LinkedHashSet(5);
0096:                _heads = new AbstractCollection() {
0097:                    public int size() {
0098:                        int sz = getChildren().size();
0099:                        if (_treechildren != null)
0100:                            --sz;
0101:                        if (_treefoot != null)
0102:                            --sz;
0103:                        return sz;
0104:                    }
0105:
0106:                    public Iterator iterator() {
0107:                        return new Iter();
0108:                    }
0109:                };
0110:            }
0111:
0112:            /** Returns the treecols that this tree owns (might null).
0113:             */
0114:            public Treecols getTreecols() {
0115:                return _treecols;
0116:            }
0117:
0118:            /** Returns the treefoot that this tree owns (might null).
0119:             */
0120:            public Treefoot getTreefoot() {
0121:                return _treefoot;
0122:            }
0123:
0124:            /** Returns the treechildren that this tree owns (might null).
0125:             */
0126:            public Treechildren getTreechildren() {
0127:                return _treechildren;
0128:            }
0129:
0130:            /** Returns a collection of heads, including {@link #getTreecols}
0131:             * and auxiliary heads ({@link Auxhead}) (never null).
0132:             *
0133:             * @since 3.0.0
0134:             */
0135:            public Collection getHeads() {
0136:                return _heads;
0137:            }
0138:
0139:            /** Returns the rows. Zero means no limitation.
0140:             * <p>Default: 0.
0141:             */
0142:            public int getRows() {
0143:                return _rows;
0144:            }
0145:
0146:            /** Sets the rows.
0147:             * <p>Note: if both {@link #setHeight} is specified with non-empty,
0148:             * {@link #setRows} is ignored
0149:             */
0150:            public void setRows(int rows) throws WrongValueException {
0151:                if (rows < 0)
0152:                    throw new WrongValueException("Illegal rows: " + rows);
0153:
0154:                if (_rows != rows) {
0155:                    _rows = rows;
0156:                    smartUpdate("z.size", Integer.toString(_rows));
0157:                }
0158:            }
0159:
0160:            /** Returns the name of this component.
0161:             * <p>Default: null.
0162:             * <p>The name is used only to work with "legacy" Web application that
0163:             * handles user's request by servlets.
0164:             * It works only with HTTP/HTML-based browsers. It doesn't work
0165:             * with other kind of clients.
0166:             * <p>Don't use this method if your application is purely based
0167:             * on ZK's event-driven model.
0168:             */
0169:            public String getName() {
0170:                return _name;
0171:            }
0172:
0173:            /** Sets the name of this component.
0174:             * <p>The name is used only to work with "legacy" Web application that
0175:             * handles user's request by servlets.
0176:             * It works only with HTTP/HTML-based browsers. It doesn't work
0177:             * with other kind of clients.
0178:             * <p>Don't use this method if your application is purely based
0179:             * on ZK's event-driven model.
0180:             *
0181:             * @param name the name of this component.
0182:             */
0183:            public void setName(String name) {
0184:                if (name != null && name.length() == 0)
0185:                    name = null;
0186:                if (!Objects.equals(_name, name)) {
0187:                    _name = name;
0188:                    if (_name != null)
0189:                        smartUpdate("z.name", _name);
0190:                    else
0191:                        invalidate(); //1) generate _value; 2) add submit listener
0192:                }
0193:            }
0194:
0195:            /** Returns whether the check mark shall be displayed in front
0196:             * of each item.
0197:             * <p>Default: false.
0198:             */
0199:            public final boolean isCheckmark() {
0200:                return _checkmark;
0201:            }
0202:
0203:            /** Sets whether the check mark shall be displayed in front
0204:             * of each item.
0205:             * <p>The check mark is a checkbox if {@link #isMultiple} returns
0206:             * true. It is a radio button if {@link #isMultiple} returns false.
0207:             */
0208:            public void setCheckmark(boolean checkmark) {
0209:                if (_checkmark != checkmark) {
0210:                    _checkmark = checkmark;
0211:                    invalidate();
0212:                }
0213:            }
0214:
0215:            /** Returns whether to grow and shrink vertical to fit their given space,
0216:             * so called vertial flexibility.
0217:             *
0218:             * <p>Note: this attribute is ignored if {@link #setRows} is specified
0219:             *
0220:             * <p>Default: false.
0221:             */
0222:            public final boolean isVflex() {
0223:                return _vflex;
0224:            }
0225:
0226:            /** Sets whether to grow and shrink vertical to fit their given space,
0227:             * so called vertial flexibility.
0228:             *
0229:             * <p>Note: this attribute is ignored if {@link #setRows} is specified
0230:             */
0231:            public void setVflex(boolean vflex) {
0232:                if (_vflex != vflex) {
0233:                    _vflex = vflex;
0234:                    smartUpdate("z.flex", _vflex);
0235:                }
0236:            }
0237:
0238:            /**
0239:             * Sets the inner width of this component.
0240:             * The inner width is the width of the inner table.
0241:             * By default, it is 100%. That is, it is the same as the width
0242:             * of this component. However, it is changed when the user
0243:             * is sizing the column's width.
0244:             *
0245:             * <p>Application developers rarely call this method, unless
0246:             * they want to preserve the widths of sizable columns
0247:             * changed by the user.
0248:             * To preserve the widths, the developer have to store the widths of
0249:             * all columns and the inner width ({@link #getInnerWidth}),
0250:             * and then restore them when re-creating this component.
0251:             *
0252:             * @param innerWidth the inner width. If null, "100%" is assumed.
0253:             * @since 3.0.0
0254:             */
0255:            public void setInnerWidth(String innerWidth) {
0256:                if (innerWidth == null)
0257:                    innerWidth = "100%";
0258:                if (!_innerWidth.equals(innerWidth)) {
0259:                    _innerWidth = innerWidth;
0260:                    smartUpdate("z.innerWidth", innerWidth);
0261:                }
0262:            }
0263:
0264:            /**
0265:             * Returns the inner width of this component.
0266:             * The inner width is the width of the inner table.
0267:             * <p>Default: "100%"
0268:             * @see #setInnerWidth
0269:             * @since 3.0.0
0270:             */
0271:            public String getInnerWidth() {
0272:                return _innerWidth;
0273:            }
0274:
0275:            /** Returns the seltype.
0276:             * <p>Default: "single".
0277:             */
0278:            public String getSeltype() {
0279:                return _multiple ? "multiple" : "single";
0280:            }
0281:
0282:            /** Sets the seltype.
0283:             * Currently, only "single" is supported.
0284:             */
0285:            public void setSeltype(String seltype) throws WrongValueException {
0286:                if ("single".equals(seltype))
0287:                    setMultiple(false);
0288:                else if ("multiple".equals(seltype))
0289:                    setMultiple(true);
0290:                else
0291:                    throw new WrongValueException("Unknown seltype: " + seltype);
0292:            }
0293:
0294:            /** Returns whether multiple selections are allowed.
0295:             * <p>Default: false.
0296:             */
0297:            public boolean isMultiple() {
0298:                return _multiple;
0299:            }
0300:
0301:            /** Sets whether multiple selections are allowed.
0302:             */
0303:            public void setMultiple(boolean multiple) {
0304:                if (_multiple != multiple) {
0305:                    _multiple = multiple;
0306:                    if (!_multiple && _selItems.size() > 1) {
0307:                        final Treeitem item = getSelectedItem();
0308:                        for (Iterator it = _selItems.iterator(); it.hasNext();) {
0309:                            final Treeitem ti = (Treeitem) it.next();
0310:                            if (ti != item) {
0311:                                ti.setSelectedDirectly(false);
0312:                                it.remove();
0313:                            }
0314:                        }
0315:                        //No need to update z.selId because z.multiple will do the job
0316:                    }
0317:                    if (isCheckmark())
0318:                        invalidate(); //change check mark
0319:                    else
0320:                        smartUpdate("z.multiple", _multiple);
0321:                }
0322:            }
0323:
0324:            /** Returns the ID of the selected item (it is stored as the z.selId
0325:             * attribute of the tree).
0326:             */
0327:            private String getSelectedId() {
0328:                //NOTE: Treerow's uuid; not Treeitem's
0329:                final Treerow tr = _sel != null ? _sel.getTreerow() : null;
0330:                return tr != null ? tr.getUuid() : "zk_n_a";
0331:            }
0332:
0333:            /** Returns a readonly list of all descending {@link Treeitem}
0334:             * (children's children and so on).
0335:             *
0336:             * <p>Note: the performance of the size method of returned collection
0337:             * is no good.
0338:             */
0339:            public Collection getItems() {
0340:                return _treechildren != null ? _treechildren.getItems()
0341:                        : Collections.EMPTY_LIST;
0342:            }
0343:
0344:            /** Returns the number of child {@link Treeitem}.
0345:             * The same as {@link #getItems}.size().
0346:             * <p>Note: the performance of this method is no good.
0347:             */
0348:            public int getItemCount() {
0349:                return _treechildren != null ? _treechildren.getItemCount() : 0;
0350:            }
0351:
0352:            /**  Deselects all of the currently selected items and selects
0353:             * the given item.
0354:             * <p>It is the same as {@link #setSelectedItem}.
0355:             * @param item the item to select. If null, all items are deselected.
0356:             */
0357:            public void selectItem(Treeitem item) {
0358:                if (item == null) {
0359:                    clearSelection();
0360:                } else {
0361:                    if (item.getTree() != this )
0362:                        throw new UiException("Not a child: " + item);
0363:
0364:                    if (_sel != item || (_multiple && _selItems.size() > 1)) {
0365:                        for (Iterator it = _selItems.iterator(); it.hasNext();) {
0366:                            final Treeitem ti = (Treeitem) it.next();
0367:                            ti.setSelectedDirectly(false);
0368:                        }
0369:                        _selItems.clear();
0370:
0371:                        _sel = item;
0372:                        item.setSelectedDirectly(true);
0373:                        _selItems.add(item);
0374:
0375:                        final Treerow tr = item.getTreerow();
0376:                        if (tr != null)
0377:                            smartUpdate("select", tr.getUuid());
0378:                    }
0379:                }
0380:            }
0381:
0382:            /** Selects the given item, without deselecting any other items
0383:             * that are already selected..
0384:             */
0385:            public void addItemToSelection(Treeitem item) {
0386:                if (item.getTree() != this )
0387:                    throw new UiException("Not a child: " + item);
0388:
0389:                if (!item.isSelected()) {
0390:                    if (!_multiple) {
0391:                        selectItem(item);
0392:                    } else {
0393:                        item.setSelectedDirectly(true);
0394:                        _selItems.add(item);
0395:                        smartUpdateSelection();
0396:                        if (fixSelected())
0397:                            smartUpdate("z.selId", getSelectedId());
0398:                    }
0399:                }
0400:            }
0401:
0402:            /**  Deselects the given item without deselecting other items.
0403:             */
0404:            public void removeItemFromSelection(Treeitem item) {
0405:                if (item.getTree() != this )
0406:                    throw new UiException("Not a child: " + item);
0407:
0408:                if (item.isSelected()) {
0409:                    if (!_multiple) {
0410:                        clearSelection();
0411:                    } else {
0412:                        item.setSelectedDirectly(false);
0413:                        _selItems.remove(item);
0414:                        smartUpdateSelection();
0415:                        if (fixSelected())
0416:                            smartUpdate("z.selId", getSelectedId());
0417:                        //No need to use response because such info is carried on tags
0418:                    }
0419:                }
0420:            }
0421:
0422:            /** Note: we have to update all selection at once, since addItemToSelection
0423:             * and removeItemFromSelection might be called interchangeably.
0424:             */
0425:            private void smartUpdateSelection() {
0426:                final StringBuffer sb = new StringBuffer(80);
0427:                for (Iterator it = _selItems.iterator(); it.hasNext();) {
0428:                    final Treeitem item = (Treeitem) it.next();
0429:                    final Treerow tr = item.getTreerow();
0430:                    if (tr != null) {
0431:                        if (sb.length() > 0)
0432:                            sb.append(',');
0433:                        sb.append(tr.getUuid());
0434:                    }
0435:                }
0436:                smartUpdate("chgSel", sb.toString());
0437:            }
0438:
0439:            /** If the specified item is selected, it is deselected.
0440:             * If it is not selected, it is selected. Other items in the tree
0441:             * that are selected are not affected, and retain their selected state.
0442:             */
0443:            public void toggleItemSelection(Treeitem item) {
0444:                if (item.isSelected())
0445:                    removeItemFromSelection(item);
0446:                else
0447:                    addItemToSelection(item);
0448:            }
0449:
0450:            /** Clears the selection.
0451:             */
0452:            public void clearSelection() {
0453:                if (!_selItems.isEmpty()) {
0454:                    for (Iterator it = _selItems.iterator(); it.hasNext();) {
0455:                        final Treeitem item = (Treeitem) it.next();
0456:                        item.setSelectedDirectly(false);
0457:                    }
0458:                    _selItems.clear();
0459:                    _sel = null;
0460:                    smartUpdate("select", "");
0461:                }
0462:            }
0463:
0464:            /** Selects all items.
0465:             */
0466:            public void selectAll() {
0467:                if (!_multiple)
0468:                    throw new UiException(
0469:                            "Appliable only to the multiple seltype: " + this );
0470:
0471:                //we don't invoke getItemCount first because it is slow!
0472:                boolean changed = false, first = true;
0473:                for (Iterator it = getItems().iterator(); it.hasNext();) {
0474:                    final Treeitem item = (Treeitem) it.next();
0475:                    if (!item.isSelected()) {
0476:                        _selItems.add(item);
0477:                        item.setSelectedDirectly(true);
0478:                        changed = true;
0479:                    }
0480:                    if (first) {
0481:                        _sel = item;
0482:                        first = false;
0483:                    }
0484:                }
0485:                smartUpdate("selectAll", "true");
0486:            }
0487:
0488:            /** Returns the selected item.
0489:             */
0490:            public Treeitem getSelectedItem() {
0491:                return _sel;
0492:            }
0493:
0494:            /**  Deselects all of the currently selected items and selects
0495:             * the given item.
0496:             * <p>It is the same as {@link #selectItem}.
0497:             */
0498:            public void setSelectedItem(Treeitem item) {
0499:                selectItem(item);
0500:            }
0501:
0502:            /** Returns all selected items.
0503:             */
0504:            public Set getSelectedItems() {
0505:                return Collections.unmodifiableSet(_selItems);
0506:            }
0507:
0508:            /** Returns the number of items being selected.
0509:             */
0510:            public int getSelectedCount() {
0511:                return _selItems.size();
0512:            }
0513:
0514:            /** Clears all child tree items ({@link Treeitem}.
0515:             * <p>Note: after clear, {@link #getTreechildren} won't be null, but
0516:             * it has no child
0517:             */
0518:            public void clear() {
0519:                if (_treechildren == null)
0520:                    return;
0521:
0522:                final List l = _treechildren.getChildren();
0523:                if (l.isEmpty())
0524:                    return; //nothing to do
0525:
0526:                for (Iterator it = new ArrayList(l).iterator(); it.hasNext();)
0527:                    ((Component) it.next()).detach();
0528:            }
0529:
0530:            /** Returns the page size that is used by all {@link Treechildren}
0531:             * to display a portion of their child {@link Treeitem},
0532:             * or -1 if no limitation.
0533:             *
0534:             * <p>Default: 10.
0535:             *
0536:             * @since 2.4.1
0537:             */
0538:            public int getPageSize() {
0539:                return _pgsz;
0540:            }
0541:
0542:            /** Sets the page size that is used by all {@link Treechildren}
0543:             * to display a portion of their child {@link Treeitem}.
0544:             *
0545:             * @param size the page size. If non-positive, there won't be
0546:             * any limitation. In other wordss, all {@link Treeitem} are shown.
0547:             * Notice: since the browser's JavaScript engine is slow to
0548:             * handle huge trees, it is better not to set a non-positive size
0549:             * if your tree is huge.
0550:             * @since 2.4.1
0551:             */
0552:            public void setPageSize(int size) throws WrongValueException {
0553:                if (size <= 0)
0554:                    size = -1; //no limitation
0555:                if (_pgsz != size) {
0556:                    _pgsz = size;
0557:                    updateActivePageChildren(_treechildren);
0558:                    invalidate();
0559:                    //FUTURE: trade-off: search and update only
0560:                    //necessary Treechildren is faster or not
0561:                }
0562:            }
0563:
0564:            /** Updates the active page for all tree children if necessary.
0565:             */
0566:            private static void updateActivePageChildren(Treechildren tc) {
0567:                if (tc != null) {
0568:                    if (tc.getPageSizeDirectly() == 0) {
0569:                        final int pgcnt = tc.getPageCount();
0570:                        if (tc.getActivePage() >= pgcnt)
0571:                            tc.setActivePageDirectly(pgcnt - 1);
0572:                        //no need to invalidate since the whole tree is change
0573:                    }
0574:
0575:                    for (Iterator it = tc.getChildren().iterator(); it
0576:                            .hasNext();) {
0577:                        final Treeitem ti = (Treeitem) it.next();
0578:                        updateActivePageChildren(ti.getTreechildren()); //recursive
0579:                    }
0580:                }
0581:            }
0582:
0583:            /** Returns the style class prefix used to generate the icons of this tree.
0584:             *
0585:             * <p>Default: tree.</br>
0586:             * Another builtin style class: dottree (the style used prior 3.0).
0587:             *
0588:             * <p>Assume that the icon style class is <code>tree</code>, then
0589:             * the following style classes are used for the icons of each tree item:
0590:             * <dl>
0591:             * <dt>tree-root-open</dt>
0592:             * <dd>The icon used to represent the open state for tree items at the root level.</dd>
0593:             * <dt>tree-root-close</dt>
0594:             * <dd>The icon used to represent the close state for tree items at the root level.</dd>
0595:             * <dt>tree-tee-open</dt>
0596:             * <dd>The icon used to represent the open state for tree items that have next siblings.</dd>
0597:             * <dt>tree-tee-close</dt>
0598:             * <dd>The icon used to represent the close state for tree items at have next siblings.</dd>
0599:             * <dt>tree-last-open</dt>
0600:             * <dd>The icon used to represent the open state for tree items that don't have next siblings.</dd>
0601:             * <dt>tree-last-close</dt>
0602:             * <dd>The icon used to represent the close state for tree items at don't have next siblings.</dd>
0603:             * <dt>tree-tee</dt>
0604:             * <dd>The icon used to represent the T-shape icon.</dd>
0605:             * <dt>tree-vbar</dt>
0606:             * <dd>The icon used to represent the |-shape (vertical bar) icon.</dd>
0607:             * <dt>tree-last</dt>
0608:             * <dd>The icon used to represent the L-shape icon -- no next sibling.</dd>
0609:             * <dt>tree-spacer</dt>
0610:             * <dd>The icon used to represent the blank icon.</dd>
0611:             * </dl>
0612:             *
0613:             * @since 3.0.0
0614:             */
0615:            public String getIconSclass() {
0616:                return _iconScls;
0617:            }
0618:
0619:            /** Sets the style class prefix used to generate the icons of this tree.
0620:             *
0621:             * @since 3.0.0
0622:             * @see #getIconSclass
0623:             */
0624:            public void setIconSclass(String scls) {
0625:                if (!Objects.equals(_iconScls, scls)) {
0626:                    _iconScls = scls;
0627:                    invalidate();
0628:                }
0629:            }
0630:
0631:            //-- Component --//
0632:            public void smartUpdate(String attr, String value) {
0633:                if (!_noSmartUpdate)
0634:                    super .smartUpdate(attr, value);
0635:            }
0636:
0637:            public boolean insertBefore(Component newChild, Component refChild) {
0638:                if (newChild instanceof  Treecols) {
0639:                    if (_treecols != null && _treecols != newChild)
0640:                        throw new UiException("Only one treecols is allowed: "
0641:                                + this );
0642:                    _treecols = (Treecols) newChild;
0643:                } else if (newChild instanceof  Treefoot) {
0644:                    if (_treefoot != null && _treefoot != newChild)
0645:                        throw new UiException("Only one treefoot is allowed: "
0646:                                + this );
0647:                    _treefoot = (Treefoot) newChild;
0648:                } else if (newChild instanceof  Treechildren) {
0649:                    if (_treechildren != null && _treechildren != newChild)
0650:                        throw new UiException(
0651:                                "Only one treechildren is allowed: " + this );
0652:                    _treechildren = (Treechildren) newChild;
0653:                    fixSelectedSet();
0654:                } else if (!(newChild instanceof  Auxhead)) {
0655:                    throw new UiException("Unsupported newChild: " + newChild);
0656:                }
0657:
0658:                if (super .insertBefore(newChild, refChild)) {
0659:                    //not need to invalidate since auxhead visible only with _treecols
0660:                    if (!(newChild instanceof  Auxhead))
0661:                        invalidate();
0662:                    return true;
0663:                }
0664:                return false;
0665:            }
0666:
0667:            /** Called by {@link Treeitem} when is added to a tree. */
0668:            /*package*/void onTreeitemAdded(Treeitem item) {
0669:                fixNewChild(item);
0670:                onTreechildrenAdded(item.getTreechildren());
0671:            }
0672:
0673:            /** Called by {@link Treeitem} when is removed from a tree. */
0674:            /*package*/void onTreeitemRemoved(Treeitem item) {
0675:                boolean fixSel = false;
0676:                if (item.isSelected()) {
0677:                    _selItems.remove(item);
0678:                    fixSel = _sel == item;
0679:                    if (fixSel && !_multiple) {
0680:                        _sel = null;
0681:                        smartUpdate("z.selId", getSelectedId());
0682:                        assert _selItems.isEmpty();
0683:                    }
0684:                }
0685:                onTreechildrenRemoved(item.getTreechildren());
0686:                if (fixSel)
0687:                    fixSelected();
0688:            }
0689:
0690:            /** Called by {@link Treechildren} when is added to a tree. */
0691:            /*package*/void onTreechildrenAdded(Treechildren tchs) {
0692:                if (tchs == null || tchs.getParent() == this )
0693:                    return; //already being processed by insertBefore
0694:
0695:                //main the selected status
0696:                for (Iterator it = tchs.getItems().iterator(); it.hasNext();)
0697:                    fixNewChild((Treeitem) it.next());
0698:            }
0699:
0700:            /** Fixes the status of new added child. */
0701:            private void fixNewChild(Treeitem item) {
0702:                if (item.isSelected()) {
0703:                    if (_sel != null && !_multiple) {
0704:                        item.setSelectedDirectly(false);
0705:                        item.invalidate();
0706:                    } else {
0707:                        if (_sel == null)
0708:                            _sel = item;
0709:                        _selItems.add(item);
0710:                        smartUpdate("z.selId", getSelectedId());
0711:                    }
0712:                }
0713:            }
0714:
0715:            /** Called by {@link Treechildren} when is removed from a tree. */
0716:            /*package*/void onTreechildrenRemoved(Treechildren tchs) {
0717:                if (tchs == null || tchs.getParent() == this )
0718:                    return; //already being processed by onChildRemoved
0719:
0720:                //main the selected status
0721:                boolean fixSel = false;
0722:                for (Iterator it = tchs.getItems().iterator(); it.hasNext();) {
0723:                    final Treeitem item = (Treeitem) it.next();
0724:                    if (item.isSelected()) {
0725:                        _selItems.remove(item);
0726:                        if (_sel == item) {
0727:                            if (!_multiple) {
0728:                                _sel = null;
0729:                                smartUpdate("z.selId", getSelectedId());
0730:                                assert _selItems.isEmpty();
0731:                                return; //done
0732:                            }
0733:                            fixSel = true;
0734:                        }
0735:                    }
0736:                }
0737:                if (fixSel)
0738:                    fixSelected();
0739:            }
0740:
0741:            public void onChildAdded(Component child) {
0742:                super .onChildAdded(child);
0743:                invalidate();
0744:            }
0745:
0746:            public void onChildRemoved(Component child) {
0747:                if (child instanceof  Treecols) {
0748:                    _treecols = null;
0749:                } else if (child instanceof  Treefoot) {
0750:                    _treefoot = null;
0751:                } else if (child instanceof  Treechildren) {
0752:                    _treechildren = null;
0753:                    _selItems.clear();
0754:                    _sel = null;
0755:                }
0756:                super .onChildRemoved(child);
0757:                invalidate();
0758:            }
0759:
0760:            /** Fixes all info about the selected status. */
0761:            private void fixSelectedSet() {
0762:                _sel = null;
0763:                _selItems.clear();
0764:                for (Iterator it = getItems().iterator(); it.hasNext();) {
0765:                    final Treeitem item = (Treeitem) it.next();
0766:                    if (item.isSelected()) {
0767:                        if (_sel == null) {
0768:                            _sel = item;
0769:                        } else if (!_multiple) {
0770:                            item.setSelectedDirectly(false);
0771:                            continue;
0772:                        }
0773:                        _selItems.add(item);
0774:                    }
0775:                }
0776:            }
0777:
0778:            /** Make _sel to be the first selected item. */
0779:            private boolean fixSelected() {
0780:                Treeitem sel = null;
0781:                switch (_selItems.size()) {
0782:                case 1:
0783:                    sel = (Treeitem) _selItems.iterator().next();
0784:                case 0:
0785:                    break;
0786:                default:
0787:                    for (Iterator it = getItems().iterator(); it.hasNext();) {
0788:                        final Treeitem item = (Treeitem) it.next();
0789:                        if (item.isSelected()) {
0790:                            sel = item;
0791:                            break;
0792:                        }
0793:                    }
0794:                }
0795:
0796:                if (sel != _sel) {
0797:                    _sel = sel;
0798:                    return true;
0799:                }
0800:                return false;
0801:            }
0802:
0803:            //-- super --//
0804:            public String getOuterAttrs() {
0805:                final StringBuffer sb = new StringBuffer(64).append(super 
0806:                        .getOuterAttrs());
0807:                HTMLs.appendAttribute(sb, "z.name", _name);
0808:                HTMLs.appendAttribute(sb, "z.size", getRows());
0809:                HTMLs.appendAttribute(sb, "z.selId", getSelectedId());
0810:                if (_multiple)
0811:                    HTMLs.appendAttribute(sb, "z.multiple", true);
0812:                //if (_checkmark)
0813:                //	HTMLs.appendAttribute(sb, "z.checkmark",  _checkmark);
0814:                if (_vflex)
0815:                    HTMLs.appendAttribute(sb, "z.vflex", true);
0816:                appendAsapAttr(sb, Events.ON_SELECT);
0817:
0818:                final Treechildren tc = getTreechildren();
0819:                if (tc != null) {
0820:                    HTMLs.appendAttribute(sb, "z.tchsib", tc.getUuid());
0821:                    //we have to generate first, since # of page might grow later
0822:
0823:                    final int pgcnt = tc.getPageCount();
0824:                    if (pgcnt > 1) {
0825:                        HTMLs.appendAttribute(sb, "z.pgc", pgcnt);
0826:                        HTMLs.appendAttribute(sb, "z.pgi", tc.getActivePage());
0827:                        HTMLs.appendAttribute(sb, "z.pgsz", tc.getPageSize());
0828:                    }
0829:                }
0830:                return sb.toString();
0831:            }
0832:
0833:            //Cloneable//
0834:            public Object clone() {
0835:                int cntSel = _selItems.size();
0836:
0837:                final Tree clone = (Tree) super .clone();
0838:                clone.init();
0839:
0840:                int cnt = 0;
0841:                if (_treecols != null)
0842:                    ++cnt;
0843:                if (_treefoot != null)
0844:                    ++cnt;
0845:                if (_treechildren != null)
0846:                    ++cnt;
0847:                if (cnt > 0 || cntSel > 0)
0848:                    clone.afterUnmarshal(cnt, cntSel);
0849:
0850:                return clone;
0851:            }
0852:
0853:            /** @param cnt # of children that need special handling (used for optimization).
0854:             * -1 means process all of them
0855:             * @param cntSel # of selected items
0856:             */
0857:            private void afterUnmarshal(int cnt, int cntSel) {
0858:                if (cnt != 0) {
0859:                    for (Iterator it = getChildren().iterator(); it.hasNext();) {
0860:                        final Object child = it.next();
0861:                        if (child instanceof  Treecols) {
0862:                            _treecols = (Treecols) child;
0863:                            if (--cnt == 0)
0864:                                break;
0865:                        } else if (child instanceof  Treefoot) {
0866:                            _treefoot = (Treefoot) child;
0867:                            if (--cnt == 0)
0868:                                break;
0869:                        } else if (child instanceof  Treechildren) {
0870:                            _treechildren = (Treechildren) child;
0871:                            if (--cnt == 0)
0872:                                break;
0873:                        }
0874:                    }
0875:                }
0876:
0877:                _sel = null;
0878:                _selItems.clear();
0879:                if (cntSel != 0) {
0880:                    for (Iterator it = getItems().iterator(); it.hasNext();) {
0881:                        final Treeitem ti = (Treeitem) it.next();
0882:                        if (ti.isSelected()) {
0883:                            if (_sel == null)
0884:                                _sel = ti;
0885:                            _selItems.add(ti);
0886:                            if (--cntSel == 0)
0887:                                break;
0888:                        }
0889:                    }
0890:                }
0891:            }
0892:
0893:            //-- Serializable --//
0894:            private synchronized void readObject(java.io.ObjectInputStream s)
0895:                    throws java.io.IOException, ClassNotFoundException {
0896:                s.defaultReadObject();
0897:
0898:                init();
0899:
0900:                afterUnmarshal(-1, -1);
0901:            }
0902:
0903:            //-- ComponentCtrl --//
0904:            protected Object newExtraCtrl() {
0905:                return new ExtraCtrl();
0906:            }
0907:
0908:            // TODO AREA JEFF ADDED
0909:
0910:            private static final Log log = Log.lookup(Tree.class);
0911:
0912:            private TreeModel _model;
0913:
0914:            private TreeitemRenderer _renderer;
0915:
0916:            private TreeDataListener _dataListener;
0917:
0918:            /*
0919:             * Handles when the tree model's content changed 
0920:             */
0921:            private void onTreeDataChange(TreeDataEvent event) {
0922:                //if the treepaht is empty, render tree's treechildren
0923:                Object data = event.getParent();
0924:                Component parent = getChildByNode(data);
0925:                int indexFrom = event.getIndexFrom();
0926:                int indexTo = event.getIndexTo();
0927:                /* 
0928:                 * Loop through indexes array
0929:                 * if INTERVAL_REMOVED, from end to beginning
0930:                 */
0931:                switch (event.getType()) {
0932:                case TreeDataEvent.INTERVAL_ADDED:
0933:                    for (int i = indexFrom; i <= indexTo; i++)
0934:                        onTreeDataInsert(parent, data, i);
0935:                    break;
0936:                case TreeDataEvent.INTERVAL_REMOVED:
0937:                    for (int i = indexTo; i >= indexFrom; i--)
0938:                        onTreeDataRemoved(parent, data, i);
0939:                    break;
0940:                case TreeDataEvent.CONTENTS_CHANGED:
0941:                    for (int i = indexFrom; i <= indexTo; i++)
0942:                        onTreeDataContentChanged(parent, data, i);
0943:                    break;
0944:                }
0945:
0946:            }
0947:
0948:            private Treechildren getParentTreechildren(Object parent) {
0949:                final Treechildren ch = (parent instanceof  Tree) ? ((Tree) parent)
0950:                        .getTreechildren()
0951:                        : ((Treeitem) parent).getTreechildren();
0952:                return (ch != null) ? ch : new Treechildren();
0953:            }
0954:
0955:            /*
0956:             * Handle Treedata insertion
0957:             */
0958:            private void onTreeDataInsert(Component parent, Object node,
0959:                    int index) {
0960:                /* 	Find the sibling to insertBefore;
0961:                 * 	if there is no sibling or new item is inserted at end.
0962:                 */
0963:                Treeitem newTi = new Treeitem();
0964:                Treechildren ch = getParentTreechildren(parent);
0965:                renderItem(newTi, _model.getChild(node, index));
0966:                List siblings = ch.getChildren();
0967:                //if there is no sibling or new item is inserted at end.
0968:                if (siblings.size() == 0 || index == siblings.size()) {
0969:                    ch.insertBefore(newTi, null);
0970:                } else {
0971:                    ch.insertBefore(newTi, (Treeitem) siblings.get(index));
0972:                }
0973:                ch.setParent(parent);
0974:                //if parent is Treeitem, setOpen
0975:                if (parent instanceof  Treeitem)
0976:                    ((Treeitem) parent).setOpen(true);
0977:            }
0978:
0979:            /*
0980:             * Handle event that child is removed
0981:             */
0982:            private void onTreeDataRemoved(Component parent, Object node,
0983:                    int index) {
0984:                List items = getParentTreechildren(parent).getChildren();
0985:                if (items.size() > 1) {
0986:                    ((Treeitem) items.get(index)).detach();
0987:                } else {
0988:                    getParentTreechildren(parent).detach();
0989:                }
0990:                //if parent is Treeitem, setOpen
0991:                if (parent instanceof  Treeitem)
0992:                    ((Treeitem) parent).setOpen(true);
0993:            }
0994:
0995:            /*
0996:             * Handle event that child's content is changed
0997:             */
0998:            private void onTreeDataContentChanged(Component parent,
0999:                    Object node, int index) {
1000:                List items = getParentTreechildren(parent).getChildren();
1001:
1002:                /* 
1003:                 * find the associated tree compoent(parent)
1004:                 * notice:
1005:                 * if parent is root
1006:                 */
1007:                if (parent instanceof  Tree)
1008:                    renderTree();
1009:                else {
1010:                    /*
1011:                     * 2008/02/01 --- issue: [ 1884112 ] When Updating TreeModel, throws a IndexOutOfBoundsException
1012:                     * When I update a children node data of the TreeModel , and fire a 
1013:                     * CONTENTS_CHANGED event, it will throw a IndexOutOfBoundsException , If a 
1014:                     * node doesn't open yet or not load yet.
1015:                     * 
1016:                     * if parent is loaded, change content. 
1017:                     * else do nothing
1018:                     */
1019:                    if (items.size() > 0) {
1020:                        Treeitem ti = (Treeitem) items.get(index);
1021:                        /*
1022:                         * When content of treeitem is changed, the treeitem is rendered as 
1023:                         * unloaded item.
1024:                         * 2007/11/05 --- issue: Can not dynamically update content of treeitem from treemodel
1025:                         */
1026:                        ti.setLoaded(false);
1027:                        renderItem(ti, _model.getChild(node, index));
1028:                        ti.setOpen(true);
1029:                    }
1030:                }
1031:            }
1032:
1033:            /**
1034:             * Return the Tree or Treeitem component by a given associated node in model.<br>
1035:             * This implmentation calls {@link TreeModel#getPath} method to locate assoicated
1036:             * Treeitem (or Tree) via path. You can override this method to speed up 
1037:             * performance if possible.
1038:             * @since 3.0.0
1039:             */
1040:            protected Component getChildByNode(Object node) {
1041:                int[] path = _model.getPath(_model.getRoot(), node);
1042:
1043:                //If path is null or empty, return root(Tree) 
1044:                if (path == null || path.length == 0)
1045:                    return this ;
1046:                else {
1047:                    Treeitem ti = (Treeitem) this .getTreechildren()
1048:                            .getChildren().get(path[0]);
1049:                    for (int i = 1; i < path.length; i++) {
1050:                        ti = (Treeitem) ti.getTreechildren().getChildren().get(
1051:                                path[i]);
1052:                    }
1053:                    return ti;
1054:                }
1055:            }
1056:
1057:            /*
1058:             * Initial Tree data listener
1059:             */
1060:            private void initDataListener() {
1061:                if (_dataListener == null)
1062:                    _dataListener = new TreeDataListener() {
1063:                        public void onChange(TreeDataEvent event) {
1064:                            onTreeDataChange(event);
1065:                        }
1066:                    };
1067:
1068:                _model.addTreeDataListener(_dataListener);
1069:            }
1070:
1071:            /** Sets the tree model associated with this tree. 
1072:             *
1073:             * @param model the tree model to associate, or null to dis-associate
1074:             * any previous model.
1075:             * @exception UiException if failed to initialize with the model
1076:             * @since 3.0.0
1077:             */
1078:            public void setModel(TreeModel model) throws Exception {
1079:                _model = model;
1080:                syncModel();
1081:                initDataListener();
1082:            }
1083:
1084:            //--TreeModel dependent codes--//
1085:            /** Returns the list model associated with this tree, or null
1086:             * if this tree is not associated with any tree data model.
1087:             * @return the list model associated with this tree
1088:             * @since 3.0.0
1089:             */
1090:            public TreeModel getModel() {
1091:                return _model;
1092:            }
1093:
1094:            /** Synchronizes the tree to be consistent with the specified model.
1095:             */
1096:            private void syncModel() throws Exception {
1097:                if (_renderer == null)
1098:                    _renderer = getRealRenderer();
1099:                renderTree();
1100:            }
1101:
1102:            /** Sets the renderer which is used to render each item
1103:             * if {@link #getModel} is not null.
1104:             *
1105:             * <p>Note: changing a render will not cause the tree to re-render.
1106:             * If you want it to re-render, you could assign the same model again 
1107:             * (i.e., setModel(getModel())), or fire an {@link TreeDataEvent} event.
1108:             *
1109:             * @param renderer the renderer, or null to use the default.
1110:             * @exception UiException if failed to initialize with the model
1111:             * @since 3.0.0
1112:             */
1113:            public void setTreeitemRenderer(TreeitemRenderer renderer) {
1114:                _renderer = renderer;
1115:            }
1116:
1117:            /** Returns the renderer to render each item, or null if the default
1118:             * renderer is used.
1119:             * @return the renderer to render each item, or null if the default
1120:             * @since 3.0.0
1121:             */
1122:            public TreeitemRenderer getTreeitemRenderer() {
1123:                return _renderer;
1124:            }
1125:
1126:            /*
1127:             * Render the root of Tree
1128:             * Notice: _model.getRoot() is mapped to Tree, not first Treeitem
1129:             */
1130:            private void renderTree() {
1131:                if (_treechildren != null)
1132:                    _treechildren = null;
1133:                Treechildren children = new Treechildren();
1134:                children.setParent(this );
1135:                Object node = _model.getRoot();
1136:                int childCount = _model.getChildCount(node);
1137:                for (int i = 0; i < childCount; i++) {
1138:                    renderTreeChild(node, i);
1139:                }
1140:            }
1141:
1142:            /*
1143:             * Helper method for renderTree
1144:             */
1145:            private void renderTreeChild(Object node, int index) {
1146:                Treeitem ti = new Treeitem();
1147:                Object data = _model.getChild(node, index);
1148:                try {
1149:                    _renderer.render(ti, data);
1150:                } catch (Throwable ex) {
1151:                    try {
1152:                        ti.setLabel(Exceptions.getMessage(ex));
1153:                    } catch (Throwable t) {
1154:                        log.error(t);
1155:                    }
1156:                    ti.setOpen(true);
1157:                }
1158:                if (!_model.isLeaf(data)) {
1159:                    Treechildren ch = new Treechildren();
1160:                    ch.setParent(ti);
1161:                }
1162:                ti.setParent(_treechildren);
1163:            }
1164:
1165:            private static final TreeitemRenderer getDefaultItemRenderer() {
1166:                return _defRend;
1167:            }
1168:
1169:            private static final TreeitemRenderer _defRend = new TreeitemRenderer() {
1170:                public void render(Treeitem ti, Object data) {
1171:                    Treecell tc = new Treecell(data.toString());
1172:                    Treerow tr = null;
1173:                    if (ti.getTreerow() == null) {
1174:                        tr = new Treerow();
1175:                        tr.setParent(ti);
1176:                    } else {
1177:                        tr = ti.getTreerow();
1178:                        tr.getChildren().clear();
1179:                    }
1180:                    tc.setParent(tr);
1181:                    ti.setOpen(false);
1182:                }
1183:            };
1184:
1185:            /** Returns the renderer used to render items.
1186:             */
1187:            private TreeitemRenderer getRealRenderer() {
1188:                return _renderer != null ? _renderer : getDefaultItemRenderer();
1189:            }
1190:
1191:            /** Used to render treeitem if _model is specified. */
1192:            private class Renderer implements  java.io.Serializable {
1193:                private final TreeitemRenderer _renderer;
1194:                private boolean _rendered, _ctrled;
1195:
1196:                private Renderer() {
1197:                    _renderer = getRealRenderer();
1198:                }
1199:
1200:                private void render(Treeitem item) throws Throwable {
1201:                    if (!item.isOpen())
1202:                        return; //nothing to do
1203:                    if (!_rendered && (_renderer instanceof  RendererCtrl)) {
1204:                        ((RendererCtrl) _renderer).doTry();
1205:                        _ctrled = true;
1206:                    }
1207:
1208:                    try {
1209:                        Object node = getAssociatedNode(item, Tree.this );
1210:                        _renderer.render(item, node);
1211:                    } catch (Throwable ex) {
1212:                        try {
1213:                            item.setLabel(Exceptions.getMessage(ex));
1214:                        } catch (Throwable t) {
1215:                            log.error(t);
1216:                        }
1217:                        item.setOpen(true);
1218:                        throw ex;
1219:                    }
1220:
1221:                    item.setOpen(true);
1222:                    _rendered = true;
1223:                }
1224:
1225:                private void doCatch(Throwable ex) {
1226:                    if (_ctrled) {
1227:                        try {
1228:                            ((RendererCtrl) _renderer).doCatch(ex);
1229:                        } catch (Throwable t) {
1230:                            throw UiException.Aide.wrap(t);
1231:                        }
1232:                    } else {
1233:                        throw UiException.Aide.wrap(ex);
1234:                    }
1235:                }
1236:
1237:                private void doFinally() {
1238:                    if (_ctrled)
1239:                        ((RendererCtrl) _renderer).doFinally();
1240:                }
1241:            }
1242:
1243:            /** Renders the specified {@link Treeitem} if not loaded yet,
1244:             * with {@link #getTreeitemRenderer}.
1245:             *
1246:             * <p>It does nothing if {@link #getModel} returns null.
1247:             *
1248:             * @see #renderItems
1249:             * @since 3.0.0
1250:             */
1251:            public void renderItem(Treeitem item) {
1252:                if (_model == null)
1253:                    return;
1254:                final Renderer renderer = new Renderer();
1255:                try {
1256:                    renderItem(item, getAssociatedNode(item, this ));
1257:                } catch (Throwable ex) {
1258:                    renderer.doCatch(ex);
1259:                } finally {
1260:                    renderer.doFinally();
1261:                }
1262:            }
1263:
1264:            /** Renders the specified {@link Treeitem} with data if not loaded yet,
1265:             * with {@link #getTreeitemRenderer}.
1266:             *
1267:             * <p>It does nothing if {@link #getModel} returns null.
1268:             *
1269:             *<p>Note: Since the corresponding data is given,
1270:             * This method has better performance than 
1271:             * renderItem(Treeitem item) due to not searching for its 
1272:             * corresponding data. 
1273:             * @see #renderItems
1274:             * @since 3.0.0
1275:             * 
1276:             * 
1277:             */
1278:            public void renderItem(Treeitem item, Object data) {
1279:                if (_model == null)
1280:                    return;
1281:                final Renderer renderer = new Renderer();
1282:                try {
1283:                    dfRenderItem(data, item);
1284:                } catch (Throwable ex) {
1285:                    renderer.doCatch(ex);
1286:                } finally {
1287:                    renderer.doFinally();
1288:                }
1289:            }
1290:
1291:            /**
1292:             * Render the treetiem with given node and its children
1293:             */
1294:            private void dfRenderItem(Object node, Treeitem item)
1295:                    throws Exception {
1296:                //if treeitem is not loaded, load it
1297:                if (!item.isLoaded()) {
1298:                    Treechildren children = null;
1299:
1300:                    if (item.getTreechildren() != null) {
1301:                        children = item.getTreechildren();
1302:                        /* 
1303:                         * When the treeitem is rendered after 1st time, dropped all
1304:                         * the descending treeitems first.
1305:                         */
1306:                        if (children.getItemCount() > 0)
1307:                            children.getChildren().clear();
1308:                    } else {
1309:                        children = new Treechildren();
1310:                        _renderer.render(item, node);
1311:                    }
1312:                    /*
1313:                     * After modified the node in tree model, if node is leaf, 
1314:                     * its treechildren is needed to be dropped.
1315:                     */
1316:                    if (_model.isLeaf(node)) {
1317:                        _renderer.render(item, node);
1318:                        if (item.getTreechildren() != null)
1319:                            item.getTreechildren().detach();
1320:                    } else {
1321:                        /*
1322:                         * render children of item
1323:                         */
1324:                        for (int i = 0; i < _model.getChildCount(node); i++) {
1325:                            Treeitem ti = new Treeitem();
1326:                            Object data = _model.getChild(node, i);
1327:                            _renderer.render(ti, data);
1328:                            if (!_model.isLeaf(data)) {
1329:                                Treechildren ch = new Treechildren();
1330:                                ch.setParent(ti);
1331:                            }
1332:                            ti.setParent(children);
1333:                        }
1334:                        children.setParent(item);
1335:                    }
1336:                    //After the treeitem is loaded with data, set treeitem to be loaded
1337:                    item.setLoaded(true);
1338:                }
1339:            }
1340:
1341:            /** Renders the specified {@link Treeitem}s with data if not loaded yet,
1342:             * with {@link #getTreeitemRenderer}.
1343:             *
1344:             * <p>It does nothing if {@link #getModel} returns null.
1345:             *
1346:             * @see #renderItem
1347:             * @since 3.0.0
1348:             */
1349:            public void renderItems(Set items) {
1350:                if (_model == null)
1351:                    return;
1352:
1353:                if (items.isEmpty())
1354:                    return; //nothing to do
1355:
1356:                final Renderer renderer = new Renderer();
1357:                try {
1358:                    for (Iterator it = items.iterator(); it.hasNext();) {
1359:                        Treeitem item = (Treeitem) it.next();
1360:                        Object data = getAssociatedNode(item, this );
1361:                        dfRenderItem(data, item);
1362:                    }
1363:                } catch (Throwable ex) {
1364:                    renderer.doCatch(ex);
1365:                } finally {
1366:                    renderer.doFinally();
1367:                }
1368:            }
1369:
1370:            /**
1371:             * Return a node which is an associated Treeitem ti in a Tree tree
1372:             * @since 3.0.0
1373:             */
1374:            protected Object getAssociatedNode(Treeitem ti, Tree t) {
1375:                return getNodeByPath(getTreeitemPath(t, ti), _model.getRoot());
1376:            }
1377:
1378:            /**
1379:             * return the path which is from ZK Component root to ZK Component lastNode 
1380:             */
1381:            private List getTreeitemPath(Component root, Component lastNode) {
1382:                List al = new ArrayList();
1383:                Component curNode = lastNode;
1384:                while (!root.equals(curNode)) {
1385:                    if (curNode instanceof  Treeitem) {
1386:                        al.add(new Integer(((Treeitem) curNode).indexOf()));
1387:                    }
1388:                    curNode = curNode.getParent();
1389:                }
1390:                return al;
1391:            }
1392:
1393:            /**
1394:             * Get the node from tree by given path
1395:             * @param path
1396:             * @param root
1397:             * @return the node from tree by given path
1398:             * @since 3.0.0
1399:             */
1400:            private Object getNodeByPath(List path, Object root) {
1401:                Object node = root;
1402:                int pathSize = path.size() - 1;
1403:                for (int i = pathSize; i >= 0; i--) {
1404:                    node = _model.getChild(node, ((Integer) (path.get(i)))
1405:                            .intValue());
1406:                }
1407:                return node;
1408:            }
1409:
1410:            /**
1411:             * Load treeitems through path <b>path</b>
1412:             * <br>Note: By using this method, all treeitems in path will be rendered
1413:             * @param path - an int[] path, see {@link TreeModel#getPath} 
1414:             * @return the treeitem from tree by given path
1415:             * @since 3.0.0
1416:             */
1417:            public Treeitem renderItemByPath(int[] path) {
1418:                if (path == null || path.length == 0)
1419:                    return null;
1420:                //Start from root-Tree
1421:                Treeitem ti = null;
1422:                List children = this .getTreechildren().getChildren();
1423:                /*
1424:                 * Go through each stop in path and render corresponding treeitem
1425:                 */
1426:                for (int i = 0; i < path.length; i++) {
1427:                    if (path[i] < 0 || path[i] > children.size())
1428:                        return null;
1429:                    ti = (Treeitem) children.get(path[i]);
1430:                    renderItem(ti);
1431:                    if (i < path.length - 1)
1432:                        ti.setOpen(true);
1433:                    if (ti.getTreechildren() != null) {
1434:                        children = ti.getTreechildren().getChildren();
1435:                    } else {
1436:                        if (i != path.length - 1) {
1437:                            return null;
1438:                        }
1439:                    }
1440:                }
1441:                return ti;
1442:            }
1443:
1444:            //TODO AREA JEFF ADDED END
1445:
1446:            /** A utility class to implement {@link #getExtraCtrl}.
1447:             * It is used only by component developers.
1448:             */
1449:
1450:            protected class ExtraCtrl extends XulElement.ExtraCtrl implements 
1451:                    InnerWidth, Selectable {
1452:                //InnerWidth//
1453:                public void setInnerWidthByClient(String width) {
1454:                    _innerWidth = width == null ? "100%" : width;
1455:                }
1456:
1457:                //-- Selectable --//
1458:                public void selectItemsByClient(Set selItems) {
1459:                    _noSmartUpdate = true;
1460:                    try {
1461:                        if (!_multiple || selItems == null
1462:                                || selItems.size() <= 1) {
1463:                            final Treeitem item = selItems != null
1464:                                    && selItems.size() > 0 ? (Treeitem) selItems
1465:                                    .iterator().next()
1466:                                    : null;
1467:                            selectItem(item);
1468:                        } else {
1469:                            for (Iterator it = new ArrayList(_selItems)
1470:                                    .iterator(); it.hasNext();) {
1471:                                final Treeitem item = (Treeitem) it.next();
1472:                                if (!selItems.remove(item))
1473:                                    removeItemFromSelection(item);
1474:                            }
1475:                            for (Iterator it = selItems.iterator(); it
1476:                                    .hasNext();)
1477:                                addItemToSelection((Treeitem) it.next());
1478:                        }
1479:                    } finally {
1480:                        _noSmartUpdate = false;
1481:                    }
1482:                }
1483:            }
1484:
1485:            /** An iterator used by _heads.
1486:             */
1487:            private class Iter implements  Iterator {
1488:                private final ListIterator _it = getChildren().listIterator();
1489:
1490:                public boolean hasNext() {
1491:                    while (_it.hasNext()) {
1492:                        Object o = _it.next();
1493:                        if (o instanceof  Treecols || o instanceof  Auxhead) {
1494:                            _it.previous();
1495:                            return true;
1496:                        }
1497:                    }
1498:                    return false;
1499:                }
1500:
1501:                public Object next() {
1502:                    for (;;) {
1503:                        Object o = _it.next();
1504:                        if (o instanceof  Treecols || o instanceof  Auxhead)
1505:                            return o;
1506:                    }
1507:                }
1508:
1509:                public void remove() {
1510:                    throw new UnsupportedOperationException();
1511:                }
1512:            }
1513:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.