001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.contrib.tree.components;
016    
017    import org.apache.tapestry.BaseComponent;
018    import org.apache.tapestry.IMarkupWriter;
019    import org.apache.tapestry.IRequestCycle;
020    import org.apache.tapestry.event.PageDetachListener;
021    import org.apache.tapestry.contrib.tree.model.ITreeDataModel;
022    import org.apache.tapestry.contrib.tree.model.ITreeModel;
023    import org.apache.tapestry.contrib.tree.model.ITreeRowSource;
024    import org.apache.tapestry.contrib.tree.model.TreeRowObject;
025    
026    import java.util.Iterator;
027    import org.apache.tapestry.event.PageEvent;
028    
029    
030    /**
031     * @author tsveltin ?
032     */
033    public abstract class TreeDataView extends BaseComponent implements
034            ITreeRowSource, PageDetachListener {
035        private TreeRowObject m_objTreeRowObject = null;
036    
037        private int m_nTreeDeep = -1;
038        
039        public abstract TreeView getTreeView();
040    
041        public TreeDataView()
042        {
043            super();
044            initialize();
045        }
046    
047        public void initialize()
048        {
049            m_objTreeRowObject = null;
050            m_nTreeDeep = -1;
051        }
052    
053        public void pageDetached(PageEvent event) {
054            initialize();
055        }
056    
057        public void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
058        {
059            // render data
060            Object objExistedTreeModelSource = cycle.getAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE);
061            cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, this);
062    
063            TreeView objView = getTreeView();
064            ITreeModel objTreeModel = objView.getTreeModel();
065            ITreeDataModel objTreeDataModel = objTreeModel.getTreeDataModel();
066    
067            Object objRoot = objTreeDataModel.getRoot();
068            Object objRootUID = objTreeDataModel.getUniqueKey(objRoot, null);
069            
070            if (getShowRootNode()) {
071    
072                walkTree(objRoot, objRootUID, 0, objTreeModel, writer, cycle,
073                         TreeRowObject.FIRST_LAST_ROW, new int[0], true);
074            } else {
075    
076                boolean bFirst = true;
077    
078                int nChildenCount = objTreeModel.getTreeDataModel().getChildCount(objRoot);
079                int nRowPossiotionType = nChildenCount == 1 ? TreeRowObject.FIRST_LAST_ROW : TreeRowObject.FIRST_ROW;
080    
081                for (Iterator iter = objTreeModel.getTreeDataModel().getChildren(objRoot); iter.hasNext();)
082                {
083                    Object objChild = iter.next();
084                    Object objChildUID = objTreeModel.getTreeDataModel().getUniqueKey(objChild, objRoot);
085    
086                    boolean bChildLast = !iter.hasNext();
087                    if (!bFirst) {
088    
089                        if (bChildLast)
090                            nRowPossiotionType = TreeRowObject.LAST_ROW;
091                        else
092                            nRowPossiotionType = TreeRowObject.MIDDLE_ROW;
093                    }
094    
095                    walkTree(objChild, objChildUID, 0, objTreeModel, writer, cycle,
096                             nRowPossiotionType, new int[0], bChildLast);
097    
098                    bFirst = false;
099                }
100            }
101    
102            cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, objExistedTreeModelSource);
103        }
104    
105        public void walkTree(Object objParent, Object objParentUID, int nDepth,
106                             ITreeModel objTreeModel, IMarkupWriter writer, IRequestCycle cycle,
107                             int nRowPossiotionType, int[] arrConnectImages, boolean bLast)
108        {
109            int rowPositionType = nRowPossiotionType;
110            m_nTreeDeep = nDepth;
111            int nNumberOfChildren = objTreeModel.getTreeDataModel().getChildCount(
112                    objParent);
113            boolean bLeaf = (nNumberOfChildren == 0) ? true : false;
114            m_objTreeRowObject = new TreeRowObject(objParent, objParentUID, nDepth,
115                                                   bLeaf, rowPositionType, arrConnectImages);
116    
117            super.renderComponent(writer, cycle);
118    
119            boolean bContain = objTreeModel.getTreeStateModel()
120                    .isUniqueKeyExpanded(objParentUID);
121            if (bContain) {
122                int[] arrConnectImagesNew = new int[arrConnectImages.length + 1];
123                System.arraycopy(arrConnectImages, 0, arrConnectImagesNew, 0,
124                                 arrConnectImages.length);
125                if (bLast)
126                    arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.EMPTY_CONN_IMG;
127                else arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.LINE_CONN_IMG;
128    
129                for (Iterator iter = objTreeModel.getTreeDataModel().getChildren(
130                        objParent); iter.hasNext();) {
131                    Object objChild = iter.next();
132                    Object objChildUID = objTreeModel.getTreeDataModel()
133                            .getUniqueKey(objChild, objParentUID);
134                    boolean bChildLast = !iter.hasNext();
135                    if (bChildLast)
136                        rowPositionType = TreeRowObject.LAST_ROW;
137                    else rowPositionType = TreeRowObject.MIDDLE_ROW;
138                    walkTree(objChild, objChildUID, nDepth + 1, objTreeModel,
139                             writer, cycle, rowPositionType, arrConnectImagesNew,
140                             bChildLast);
141                }
142            }
143        }
144    
145        public int getTreeDeep()
146        {
147            return m_nTreeDeep;
148        }
149    
150        /**
151         * @see org.apache.tapestry.contrib.tree.model.ITreeRowSource#getTreeRow()
152         */
153        public TreeRowObject getTreeRow()
154        {
155            return getTreeRowObject();
156        }
157    
158        public TreeRowObject getTreeRowObject()
159        {
160            return m_objTreeRowObject;
161        }
162    
163        public void setTreeRowObject(TreeRowObject object)
164        {
165            m_objTreeRowObject = object;
166        }
167    
168        public abstract boolean getShowRootNode();
169    
170    }