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
015package org.apache.tapestry.contrib.tree.components;
016
017import java.util.Iterator;
018
019import org.apache.tapestry.BaseComponent;
020import org.apache.tapestry.IMarkupWriter;
021import org.apache.tapestry.IRequestCycle;
022import org.apache.tapestry.contrib.tree.model.ITreeDataModel;
023import org.apache.tapestry.contrib.tree.model.ITreeModel;
024import org.apache.tapestry.contrib.tree.model.ITreeRowSource;
025import org.apache.tapestry.contrib.tree.model.TreeRowObject;
026
027/**
028 * @author tsveltin ?
029 */
030public abstract class TreeDataView extends BaseComponent implements ITreeRowSource
031{
032    private TreeRowObject m_objTreeRowObject = null;
033
034    private int m_nTreeDeep = -1;
035
036    public TreeDataView()
037    {
038        super();
039        initialize();
040    }
041
042    public void initialize()
043    {
044        m_objTreeRowObject = null;
045        m_nTreeDeep = -1;
046    }
047
048    public abstract TreeView getTreeView();
049
050    public void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
051    {
052        // render data
053        Object objExistedTreeModelSource = cycle
054                .getAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE);
055        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, this);
056
057        TreeView objView = getTreeView();
058        ITreeModel objTreeModel = objView.getTreeModel();
059        ITreeDataModel objTreeDataModel = objTreeModel.getTreeDataModel();
060
061        Object objRoot = objTreeDataModel.getRoot();
062        Object objRootUID = objTreeDataModel.getUniqueKey(objRoot, null);
063        if (getShowRootNode())
064        {
065            walkTree(
066                    objRoot,
067                    objRootUID,
068                    0,
069                    objTreeModel,
070                    writer,
071                    cycle,
072                    TreeRowObject.FIRST_LAST_ROW,
073                    new int[0],
074                    true);
075        }
076        else
077        {
078            boolean bFirst = true;
079            int nChildenCount = objTreeModel.getTreeDataModel().getChildCount(objRoot);
080            int nRowPossiotionType = nChildenCount == 1 ? TreeRowObject.FIRST_LAST_ROW
081                    : TreeRowObject.FIRST_ROW;
082            for (Iterator iter = objTreeModel.getTreeDataModel().getChildren(objRoot); iter
083                    .hasNext();)
084            {
085                Object objChild = iter.next();
086                Object objChildUID = objTreeModel.getTreeDataModel()
087                        .getUniqueKey(objChild, objRoot);
088                boolean bChildLast = !iter.hasNext();
089                if (!bFirst)
090                {
091                    if (bChildLast)
092                        nRowPossiotionType = TreeRowObject.LAST_ROW;
093                    else
094                        nRowPossiotionType = TreeRowObject.MIDDLE_ROW;
095                }
096
097                walkTree(
098                        objChild,
099                        objChildUID,
100                        0,
101                        objTreeModel,
102                        writer,
103                        cycle,
104                        nRowPossiotionType,
105                        new int[0],
106                        bChildLast);
107
108                bFirst = false;
109            }
110        }
111
112        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, objExistedTreeModelSource);
113    }
114
115    public void walkTree(Object objParent, Object objParentUID, int nDepth,
116            ITreeModel objTreeModel, IMarkupWriter writer, IRequestCycle cycle,
117            int nRowPossiotionType, int[] arrConnectImages, boolean bLast)
118    {
119        m_nTreeDeep = nDepth;
120        int nNumberOfChildren = objTreeModel.getTreeDataModel().getChildCount(objParent);
121        boolean bLeaf = (nNumberOfChildren == 0) ? true : false;
122        m_objTreeRowObject = new TreeRowObject(objParent, objParentUID, nDepth, bLeaf,
123                nRowPossiotionType, arrConnectImages);
124
125        super.renderComponent(writer, cycle);
126
127        boolean bContain = objTreeModel.getTreeStateModel().isUniqueKeyExpanded(objParentUID);
128        if (bContain)
129        {
130            int[] arrConnectImagesNew = new int[arrConnectImages.length + 1];
131            System.arraycopy(arrConnectImages, 0, arrConnectImagesNew, 0, arrConnectImages.length);
132            if (bLast)
133                arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.EMPTY_CONN_IMG;
134            else
135                arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.LINE_CONN_IMG;
136
137            for (Iterator iter = objTreeModel.getTreeDataModel().getChildren(objParent); iter
138                    .hasNext();)
139            {
140                Object objChild = iter.next();
141                Object objChildUID = objTreeModel.getTreeDataModel().getUniqueKey(
142                        objChild,
143                        objParentUID);
144                boolean bChildLast = !iter.hasNext();
145                if (bChildLast)
146                    nRowPossiotionType = TreeRowObject.LAST_ROW;
147                else
148                    nRowPossiotionType = TreeRowObject.MIDDLE_ROW;
149                walkTree(
150                        objChild,
151                        objChildUID,
152                        nDepth + 1,
153                        objTreeModel,
154                        writer,
155                        cycle,
156                        nRowPossiotionType,
157                        arrConnectImagesNew,
158                        bChildLast);
159            }
160        }
161    }
162
163    public int getTreeDeep()
164    {
165        return m_nTreeDeep;
166    }
167
168    /**
169     * @see org.apache.tapestry.contrib.tree.model.ITreeRowSource#getTreeRow()
170     */
171    public TreeRowObject getTreeRow()
172    {
173        return getTreeRowObject();
174    }
175
176    public TreeRowObject getTreeRowObject()
177    {
178        return m_objTreeRowObject;
179    }
180
181    public void setTreeRowObject(TreeRowObject object)
182    {
183        m_objTreeRowObject = object;
184    }
185
186    public abstract boolean getShowRootNode();
187
188}