001: /*
002: * (C) Copyright 2000 - 2005 Nabh Information Systems, Inc.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: *
018: */
019:
020: package com.nabhinc.portal.model;
021:
022: import javax.xml.bind.Unmarshaller;
023: import javax.xml.bind.annotation.XmlRootElement;
024:
025: /**
026: * Represents a Web page layout in which there is a tree menu of portlets.
027: *
028: * @author Padmanabh Dabke
029: * (c) 2005 Nabh Information Systems, Inc. All Rights Reserved.
030: * @since 2.5
031: */
032: @XmlRootElement(name="tree")
033: public class TreeLayout extends NavigationalLayout {
034:
035: /**
036: * Root level of the tree
037: */
038: public static final int ROOT_LEVEL = 0;
039:
040: /**
041: * The deepest level of the tree
042: */
043: public static final int DEFAULT_MAX_LEVEL = 5;
044:
045: public TreeLayout() {
046: setTemplate("tree_layout.jsp");
047: this .bprComponentTemplate = "tree_content.jsp";
048: }
049:
050: public TreeLayout(PortalPage p) {
051: super (p);
052: setTemplate("tree_layout.jsp");
053: this .bprComponentTemplate = "tree_content.jsp";
054: }
055:
056: public void afterUnmarshal(Unmarshaller um, Object parent) {
057:
058: super .afterUnmarshal(um, parent);
059:
060: }
061:
062: private int getParentIndex(int childIndex) {
063: if (this .navOptions[childIndex].level == ROOT_LEVEL)
064: return -1;
065: int parentLevel = this .navOptions[childIndex].level - 1;
066: int i = childIndex - 1;
067: while (this .navOptions[i].level != parentLevel)
068: i--;
069: return i;
070: }
071:
072: public void setRowIndex(int index) {
073: super .setRowIndex(index);
074:
075: if (this .rowIndex != -1) {
076: for (int i = 0; i < this .navOptions.length; i++) {
077: this .navOptions[i].isSelected = false;
078: }
079: int parentIndex = getParentIndex(this .rowIndex);
080: while (parentIndex != -1) {
081: this .navOptions[parentIndex].isSelected = true;
082: parentIndex = getParentIndex(parentIndex);
083: }
084: }
085: }
086:
087: /**
088: * Delete a portlet at the specified index.
089: */
090: public void deleteOption(int portletIndex) {
091:
092: if (portletIndex < 0 || portletIndex >= navOptions.length) {
093: // ignore invalid indices
094: //warn("Attempt to delete a portlet with invalid portlet index.");
095: return;
096: }
097:
098: int endIndex = getEndIndex(portletIndex);
099: deleteRows(portletIndex, endIndex);
100: setRowIndex(this .rowIndex);
101: }
102:
103: private void deleteRows(int startIndex, int endIndex) {
104: int numDeleted = endIndex - startIndex + 1;
105: NavigationOption[] newOptions = new NavigationOption[navOptions.length
106: - numDeleted];
107:
108: for (int i = 0; i < startIndex; i++) {
109: newOptions[i] = navOptions[i];
110: }
111:
112: int newLen = newOptions.length;
113:
114: for (int i = startIndex; i < newLen; i++) {
115: newOptions[i] = navOptions[i + numDeleted];
116: }
117:
118: navOptions = newOptions;
119: }
120:
121: private int getEndIndex(int startIndex) {
122: if (this .navOptions[startIndex].type != NavigationOption.OPTION_TYPE_HEADER)
123: return startIndex;
124: int endIndex = -1;
125: int i = startIndex + 1;
126: int deleteLevel = this .navOptions[startIndex].level;
127: while (i < this .navOptions.length) {
128: if (this .navOptions[i].level > deleteLevel) {
129: endIndex = i;
130: } else {
131: break;
132: }
133: i++;
134: }
135:
136: if (endIndex == -1)
137: endIndex = startIndex;
138: return endIndex;
139: }
140:
141: @Override
142: public void reorderRows(int oldIndex, int newIndex, int parentIndex) {
143: int rightLevel = parentIndex == -1 ? 0
144: : this .navOptions[parentIndex].level + 1;
145: if (oldIndex == newIndex) {
146: this .navOptions[oldIndex].level = rightLevel;
147: return;
148: }
149: int endIndex = getEndIndex(oldIndex);
150: int numRows = endIndex - oldIndex + 1;
151: NavigationOption[] optionsMoved = new NavigationOption[numRows];
152: for (int i = 0; i < numRows; i++) {
153: optionsMoved[i] = this .navOptions[oldIndex + i];
154: }
155: deleteRows(oldIndex, endIndex);
156: insertRows(newIndex, optionsMoved, rightLevel);
157:
158: }
159:
160: private void insertRows(int index, NavigationOption[] optionsAdded,
161: int rightLevel) {
162: int numOptions = optionsAdded.length;
163: NavigationOption[] newOptions = new NavigationOption[this .navOptions.length
164: + numOptions];
165: for (int i = 0; i < index; i++) {
166: newOptions[i] = this .navOptions[i];
167: }
168:
169: for (int i = 0; i < numOptions; i++) {
170: newOptions[index + i] = optionsAdded[i];
171: }
172:
173: for (int i = index; i < this .navOptions.length; i++) {
174: newOptions[i + numOptions] = this .navOptions[i];
175: }
176:
177: if (newOptions[index].level != rightLevel) {
178: int delta = rightLevel - newOptions[index].level;
179: for (int i = 0; i < numOptions; i++) {
180: newOptions[i + index].level += delta;
181: }
182: }
183:
184: this.navOptions = newOptions;
185: }
186:
187: }
|