📄 tree.java
字号:
public int getSelectedCount() { return _selItems.size(); } /** Clears all child tree items ({@link Treeitem}. * <p>Note: after clear, {@link #getTreechildren} won't be null, but * it has no child */ public void clear() { if (_treechildren == null) return; final List l = _treechildren.getChildren(); if (l.isEmpty()) return; //nothing to do for (Iterator it = new ArrayList(l).iterator(); it.hasNext();) ((Component)it.next()).detach(); } /** Returns the page size that is used by all {@link Treechildren} * to display a portion of their child {@link Treeitem}, * or -1 if no limitation. * * <p>Default: 10. * * @since 2.4.1 */ public int getPageSize() { return _pgsz; } /** Sets the page size that is used by all {@link Treechildren} * to display a portion of their child {@link Treeitem}. * * @param size the page size. If non-positive, there won't be * any limitation. In other wordss, all {@link Treeitem} are shown. * Notice: since the browser's JavaScript engine is slow to * handle huge trees, it is better not to set a non-positive size * if your tree is huge. * @since 2.4.1 */ public void setPageSize(int size) throws WrongValueException { if (size <= 0) size = -1; //no limitation if (_pgsz != size) { _pgsz = size; updateActivePageChildren(_treechildren); invalidate(); //FUTURE: trade-off: search and update only //necessary Treechildren is faster or not } } /** Updates the active page for all tree children if necessary. */ private static void updateActivePageChildren(Treechildren tc) { if (tc != null) { if (tc.getPageSizeDirectly() == 0) { final int pgcnt = tc.getPageCount(); if (tc.getActivePage() >= pgcnt) tc.setActivePageDirectly(pgcnt - 1); //no need to invalidate since the whole tree is change } for (Iterator it = tc.getChildren().iterator(); it.hasNext();) { final Treeitem ti = (Treeitem)it.next(); updateActivePageChildren(ti.getTreechildren()); //recursive } } } /** Returns the style class prefix used to generate the icons of this tree. * * <p>Default: tree.</br> * Another builtin style class: dottree (the style used prior 3.0). * * <p>Assume that the icon style class is <code>tree</code>, then * the following style classes are used for the icons of each tree item: * <dl> * <dt>tree-root-open</dt> * <dd>The icon used to represent the open state for tree items at the root level.</dd> * <dt>tree-root-close</dt> * <dd>The icon used to represent the close state for tree items at the root level.</dd> * <dt>tree-tee-open</dt> * <dd>The icon used to represent the open state for tree items that have next siblings.</dd> * <dt>tree-tee-close</dt> * <dd>The icon used to represent the close state for tree items at have next siblings.</dd> * <dt>tree-last-open</dt> * <dd>The icon used to represent the open state for tree items that don't have next siblings.</dd> * <dt>tree-last-close</dt> * <dd>The icon used to represent the close state for tree items at don't have next siblings.</dd> * <dt>tree-tee</dt> * <dd>The icon used to represent the T-shape icon.</dd> * <dt>tree-vbar</dt> * <dd>The icon used to represent the |-shape (vertical bar) icon.</dd> * <dt>tree-last</dt> * <dd>The icon used to represent the L-shape icon -- no next sibling.</dd> * <dt>tree-spacer</dt> * <dd>The icon used to represent the blank icon.</dd> * </dl> * * @since 3.0.0 */ public String getIconSclass() { return _iconScls; } /** Sets the style class prefix used to generate the icons of this tree. * * @since 3.0.0 * @see #getIconSclass */ public void setIconSclass(String scls) { if (!Objects.equals(_iconScls, scls)) { _iconScls = scls; invalidate(); } } //-- Component --// public void smartUpdate(String attr, String value) { if (!_noSmartUpdate) super.smartUpdate(attr, value); } public boolean insertBefore(Component newChild, Component refChild) { if (newChild instanceof Treecols) { if (_treecols != null && _treecols != newChild) throw new UiException("Only one treecols is allowed: "+this); _treecols = (Treecols)newChild; } else if (newChild instanceof Treefoot) { if (_treefoot != null && _treefoot != newChild) throw new UiException("Only one treefoot is allowed: "+this); _treefoot = (Treefoot)newChild; } else if (newChild instanceof Treechildren) { if (_treechildren != null && _treechildren != newChild) throw new UiException("Only one treechildren is allowed: "+this); _treechildren = (Treechildren)newChild; fixSelectedSet(); } else if (!(newChild instanceof Auxhead)) { throw new UiException("Unsupported newChild: "+newChild); } if (super.insertBefore(newChild, refChild)) { //not need to invalidate since auxhead visible only with _treecols if (!(newChild instanceof Auxhead)) invalidate(); return true; } return false; } /** Called by {@link Treeitem} when is added to a tree. */ /*package*/ void onTreeitemAdded(Treeitem item) { fixNewChild(item); onTreechildrenAdded(item.getTreechildren()); } /** Called by {@link Treeitem} when is removed from a tree. */ /*package*/ void onTreeitemRemoved(Treeitem item) { boolean fixSel = false; if (item.isSelected()) { _selItems.remove(item); fixSel = _sel == item; if (fixSel && !_multiple) { _sel = null; smartUpdate("z.selId", getSelectedId()); assert _selItems.isEmpty(); } } onTreechildrenRemoved(item.getTreechildren()); if (fixSel) fixSelected(); } /** Called by {@link Treechildren} when is added to a tree. */ /*package*/ void onTreechildrenAdded(Treechildren tchs) { if (tchs == null || tchs.getParent() == this) return; //already being processed by insertBefore //main the selected status for (Iterator it = tchs.getItems().iterator(); it.hasNext();) fixNewChild((Treeitem)it.next()); } /** Fixes the status of new added child. */ private void fixNewChild(Treeitem item) { if (item.isSelected()) { if (_sel != null && !_multiple) { item.setSelectedDirectly(false); item.invalidate(); } else { if (_sel == null) _sel = item; _selItems.add(item); smartUpdate("z.selId", getSelectedId()); } } } /** Called by {@link Treechildren} when is removed from a tree. */ /*package*/ void onTreechildrenRemoved(Treechildren tchs) { if (tchs == null || tchs.getParent() == this) return; //already being processed by onChildRemoved //main the selected status boolean fixSel = false; for (Iterator it = tchs.getItems().iterator(); it.hasNext();) { final Treeitem item = (Treeitem)it.next(); if (item.isSelected()) { _selItems.remove(item); if (_sel == item) { if (!_multiple) { _sel = null; smartUpdate("z.selId", getSelectedId()); assert _selItems.isEmpty(); return; //done } fixSel = true; } } } if (fixSel) fixSelected(); } public void onChildAdded(Component child) { super.onChildAdded(child); invalidate(); } public void onChildRemoved(Component child) { if (child instanceof Treecols) { _treecols = null; } else if (child instanceof Treefoot) { _treefoot = null; } else if (child instanceof Treechildren) { _treechildren = null; _selItems.clear(); _sel = null; } super.onChildRemoved(child); invalidate(); } /** Fixes all info about the selected status. */ private void fixSelectedSet() { _sel = null; _selItems.clear(); for (Iterator it = getItems().iterator(); it.hasNext();) { final Treeitem item = (Treeitem)it.next(); if (item.isSelected()) { if (_sel == null) { _sel = item; } else if (!_multiple) { item.setSelectedDirectly(false); continue; } _selItems.add(item); } } } /** Make _sel to be the first selected item. */ private boolean fixSelected() { Treeitem sel = null; switch (_selItems.size()) { case 1: sel = (Treeitem)_selItems.iterator().next(); case 0: break; default: for (Iterator it = getItems().iterator(); it.hasNext();) { final Treeitem item = (Treeitem)it.next(); if (item.isSelected()) { sel = item; break; } } } if (sel != _sel) { _sel = sel; return true; } return false; } //-- super --// public String getOuterAttrs() { final StringBuffer sb = new StringBuffer(64) .append(super.getOuterAttrs()); HTMLs.appendAttribute(sb, "z.name", _name); HTMLs.appendAttribute(sb, "z.size", getRows()); HTMLs.appendAttribute(sb, "z.selId", getSelectedId()); if (_multiple) HTMLs.appendAttribute(sb, "z.multiple", true); //if (_checkmark) // HTMLs.appendAttribute(sb, "z.checkmark", _checkmark); if (_vflex) HTMLs.appendAttribute(sb, "z.vflex", true); appendAsapAttr(sb, Events.ON_SELECT); final Treechildren tc = getTreechildren(); if (tc != null) { HTMLs.appendAttribute(sb, "z.tchsib", tc.getUuid()); //we have to generate first, since # of page might grow later final int pgcnt = tc.getPageCount(); if (pgcnt > 1) { HTMLs.appendAttribute(sb, "z.pgc", pgcnt); HTMLs.appendAttribute(sb, "z.pgi", tc.getActivePage()); HTMLs.appendAttribute(sb, "z.pgsz", tc.getPageSize()); } } return sb.toString(); } //Cloneable// public Object clone() { int cntSel = _selItems.size(); final Tree clone = (Tree)super.clone(); clone.init(); int cnt = 0; if (_treecols != null) ++cnt; if (_treefoot != null) ++cnt; if (_treechildren != null) ++cnt; if (cnt > 0 || cntSel > 0) clone.afterUnmarshal(cnt, cntSel); return clone; } /** @param cnt # of children that need special handling (used for optimization). * -1 means process all of them * @param cntSel # of selected items */ private void afterUnmarshal(int cnt, int cntSel) { if (cnt != 0) { for (Iterator it = getChildren().iterator(); it.hasNext();) { final Object child = it.next(); if (child instanceof Treecols) { _treecols = (Treecols)child; if (--cnt == 0) break; } else if (child instanceof Treefoot) { _treefoot = (Treefoot)child; if (--cnt == 0) break; } else if (child instanceof Treechildren) { _treechildren = (Treechildren)child; if (--cnt == 0) break; } } } _sel = null; _selItems.clear(); if (cntSel != 0) { for (Iterator it = getItems().iterator(); it.hasNext();) { final Treeitem ti = (Treeitem)it.next(); if (ti.isSelected()) { if (_sel == null) _sel = ti; _selItems.add(ti); if (--cntSel == 0) break; } } } } //-- Serializable --// private synchronized void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); init(); afterUnmarshal(-1, -1); } //-- ComponentCtrl --// protected Object newExtraCtrl() { return new ExtraCtrl(); } // TODO AREA JEFF ADDED private static final Log log = Log.lookup(Tree.class); private TreeModel _model; private TreeitemRenderer _renderer; private TreeDataListener _dataListener; /* * Handles when the tree model's content changed */ private void onTreeDataChange(TreeDataEvent event){ //if the treepaht is empty, render tree's treechildren Object data = event.getParent(); Component parent = getChildByNode(data); int indexFrom = event.getIndexFrom(); int indexTo = event.getIndexTo(); /* * Loop through indexes array * if INTERVAL_REMOVED, from end to beginning */ switch (event.getType()) { case TreeDataEvent.INTERVAL_ADDED: for(int i=indexFrom;i<=indexTo;i++) onTreeDataInsert(parent,data,i); break; case TreeDataEvent.INTERVAL_REMOVED: for(int i=indexTo;i>=indexFrom;i--) onTreeDataRemoved(parent,data,i); break; case TreeDataEvent.CONTENTS_CHANGED: for(int i=indexFrom;i<=indexTo;i++) onTreeDataContentChanged(parent,data,i); break; } } private Treechildren getParentTreechildren(Object parent){ final Treechildren ch = (parent instanceof Tree) ? ((Tree)parent).getTreechildren() : ((Treeitem)parent).getTreechildren(); return (ch != null) ? ch : new Treechildren(); } /* * Handle Treedata insertion */ private void onTreeDataInsert(Component parent,Object node, int index){ /* Find the sibling to insertBefore; * if there is no sibling or new item is inserted at end. */ Treeitem newTi = new Treeitem(); Treechildren ch= getParentTreechildren(parent); renderItem(newTi,_model.getChild(node,index)); List siblings = ch.getChildren(); //if there is no sibling or new item is inserted at end. if(siblings.size()==0 || index == siblings.size() ){ ch.insertBefore(newTi, null); }else{ ch.insertBefore(newTi, (Treeitem)siblings.get(index)); } ch.setParent(parent); //if parent is Treeitem, setOpen if(parent instanceof Treeitem) ((Treeitem)parent).setOpen(true); } /* * Handle event that child is removed */ private void onTreeDataRemoved(Component parent,Object node, int index){ List items = getParentTreechildren(parent).getChildren(); if(items.size()>1){ ((Treeitem)items.get(index)).detach(); }else{ getParentTreechildren(parent).detach(); } //if parent is Treeitem, setOpen if(parent instanceof Treeitem) ((Treeitem)parent).setOpen(true); } /* * Handle event that child's content is changed */ private void onTreeDataContentChanged(Component parent,Object node, int index){ List items = getParentTreechildren(parent).getChildren(); /* * find the associated tree compoent(parent) * notice: * if parent is root */ if(parent instanceof Tree) renderTree(); else{ Treeitem ti = (Treeitem)items.get(index); /* * When content of treeitem is changed, the treeitem is rendered as * unloaded item. * 2007/11/05 --- issue: Can not dynamically update content of treeitem from treemodel */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -