001: /* AbstractTreeModel.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Aug 10 2007, Created by Jeff Liu
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zul;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.LinkedList;
024: import java.util.List;
025:
026: import org.zkoss.io.Serializables;
027:
028: import org.zkoss.zk.ui.Component;
029: import org.zkoss.zul.event.TreeDataListener;
030: import org.zkoss.zul.event.TreeDataEvent;
031:
032: /**
033: * A skeletal implementation for {@link TreeModel}.
034: *
035: * @author Jeff Liu
036: * @since ZK 3.0.0
037: */
038: public abstract class AbstractTreeModel implements TreeModel,
039: java.io.Serializable {
040:
041: /**
042: * The root object to be return by method {@link #getRoot()}.
043: */
044: private Object _root;
045:
046: private transient List _listeners = new LinkedList();
047:
048: /**
049: * Constructor
050: * @param root - root of tree
051: */
052: public AbstractTreeModel(Object root) {
053: _root = root;
054: }
055:
056: /**
057: * Return the root of tree
058: * @return the root of tree
059: */
060: public Object getRoot() {
061: return _root;
062: }
063:
064: /** Fires a {@link TreeDataEvent} for all registered listener
065: *
066: * <p>Note: you can invoke this method only in an event listener.
067: */
068: protected void fireEvent(Object node, int indexFrom, int indexTo,
069: int evtType) {
070: final TreeDataEvent evt = new TreeDataEvent(this , evtType,
071: node, indexFrom, indexTo);
072: for (Iterator it = _listeners.iterator(); it.hasNext();)
073: ((TreeDataListener) it.next()).onChange(evt);
074: }
075:
076: //-TreeModel-//
077: public int[] getPath(Object parent, Object lastNode) {
078: List l = new ArrayList();
079: dfSearch(l, parent, lastNode);
080: Object[] objs = l.toArray();
081: int[] path = new int[objs.length];
082: for (int i = 0; i < objs.length; i++) {
083: path[i] = ((Integer) objs[i]).intValue();
084: }
085: return path;
086: }
087:
088: /**
089: * Helper method:
090: * Depth first search to find the path which is from node to target
091: * @param al path
092: * @param node origin
093: * @param target destination
094: * @return whether the target is found or not
095: */
096: private boolean dfSearch(List path, Object node, Object target) {
097: if (node.equals(target)) {
098: return true;
099: } else {
100: int size = getChildCount(node);
101: for (int i = 0; i < size; i++) {
102: boolean flag = dfSearch(path, getChild(node, i), target);
103: if (flag) {
104: path.add(0, new Integer(i));
105: return true;
106: }
107: }
108: }
109: return false;
110: }
111:
112: //-- TreeModel --//
113: public void addTreeDataListener(TreeDataListener l) {
114: _listeners.add(l);
115: }
116:
117: //-- TreeModel --//
118: public void removeTreeDataListener(TreeDataListener l) {
119: _listeners.remove(l);
120: }
121:
122: //Serializable//
123: private synchronized void writeObject(java.io.ObjectOutputStream s)
124: throws java.io.IOException {
125: s.defaultWriteObject();
126:
127: Serializables.smartWrite(s, _listeners);
128: }
129:
130: private synchronized void readObject(java.io.ObjectInputStream s)
131: throws java.io.IOException, ClassNotFoundException {
132: s.defaultReadObject();
133:
134: _listeners = new LinkedList();
135: Serializables.smartRead(s, _listeners);
136: }
137: }
|