001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.pm.graphic.spreadsheet.time;
051:
052: import java.util.ArrayList;
053: import java.util.EventListener;
054:
055: import javax.swing.event.EventListenerList;
056:
057: import com.projity.field.Field;
058: import com.projity.field.FieldContext;
059: import com.projity.field.FieldParseException;
060: import com.projity.graphic.configuration.ActionList;
061: import com.projity.graphic.configuration.CellStyle;
062: import com.projity.grouping.core.Node;
063: import com.projity.grouping.core.model.NodeModel;
064: import com.projity.pm.graphic.model.cache.GraphicNode;
065: import com.projity.pm.graphic.model.cache.NodeModelCache;
066: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheetModel;
067: import com.projity.pm.graphic.timescale.CoordinatesConverter;
068: import com.projity.pm.time.HasStartAndEnd;
069: import com.projity.timescale.TimeScaleEvent;
070: import com.projity.timescale.TimeScaleListener;
071: import com.projity.util.Alert;
072:
073: /**
074: *
075: */
076: public class TimeSpreadSheetModel extends CommonSpreadSheetModel
077: implements TimeScaleListener {
078: protected ArrayList selectedFieldArray;
079: //timescale
080: protected CoordinatesConverter coord;
081: protected ArrayList timeIntervals; // cache: data filled by
082: FieldContext fieldContext = new FieldContext(); // this is re-used like a renderer
083: //TimeSpreadSheetModel with coord.getProjectTimeIterator()
084: ArrayList fieldArray;
085:
086: public final ArrayList getFieldArray() {
087: return fieldArray;
088: }
089:
090: public TimeSpreadSheetModel(NodeModelCache cache,
091: ArrayList fieldArray, CellStyle cellStyle,
092: ActionList actionList) {
093: super (cache, null, cellStyle, actionList);
094: this .fieldArray = fieldArray;
095: selectedFieldArray = new ArrayList();
096: timeIntervals = new ArrayList();
097: resetSelectedFieldArray();
098: //initCellStyle();
099: setFieldContext(fieldContext);
100: }
101:
102: // public void graphicNodesCompositeEvent(CompositeCacheEvent compositeEvent){
103: // fireTableStructureChanged();
104: //// for (Iterator i=compositeEvent.getNodeEvents().iterator();i.hasNext();){
105: //// final CacheEvent e=(CacheEvent)i.next();
106: //// e.forIntervals(new Closure() {
107: //// public void execute(Object obj) {
108: //// CacheInterval i = (CacheInterval) obj;
109: //// if (e.getType()==CacheEvent.NODES_CHANGED)
110: //// fireTableRowsUpdated(i.getStart(), i.getEnd());
111: //// else if (e.getType()==CacheEvent.NODES_INSERTED)
112: //// fireTableRowsInserted(i.getStart(), i.getEnd());
113: //// else if (e.getType()==CacheEvent.NODES_REMOVED)
114: //// fireTableRowsDeleted(i.getStart(), i.getEnd());
115: //// }
116: //// });
117: //// }
118: // }
119:
120: // public TimeSpreadSheetModel(NodeModel model,ArrayList fieldArray, CellStyle cellStyle,String viewName) {
121: // super(NodeModelCacheFactory.getInstance().createDefaultCache(model,viewName),fieldArray,cellStyle);
122: // selectedFieldArray=new ArrayList();
123: // resetSelectedFieldArray();
124: // //initCellStyle();
125: // setFieldContext(fieldContext);
126: // }
127:
128: /*public void initCellStyle(){
129: cellStyle=new CellStyle(){
130: CellFormat cellProperties=new CellFormat();
131: public CellFormat getCellProperties(GraphicNode node){
132: cellProperties.setBold(node.isSummary());
133: cellProperties.setCompositeIcon(node.isSummary());
134: cellProperties.setBackground((node.isAssignment())?"NORMAL_LIGHT_YELLOW":"NORMAL_YELLOW");
135: return cellProperties;
136: }
137:
138: };
139:
140: }*/
141:
142: public void resetSelectedFieldArray() {
143: int oldSize = selectedFieldArray.size();
144: selectedFieldArray.clear();
145: if (fieldArray.size() > 0)
146: selectedFieldArray.add(fieldArray.get(0));
147: //only size is used
148: if (oldSize != selectedFieldArray.size()) {
149: fireFieldArrayChanged(this );
150: fireUpdateAll();
151: }
152: }
153:
154: public void setFieldArray(ArrayList fieldArray) {
155: this .fieldArray = fieldArray;
156: resetSelectedFieldArray();
157: }
158:
159: public ArrayList getSelectedFieldArray() {
160: return selectedFieldArray;
161: }
162:
163: public void setSelectedFieldArray(ArrayList selectedFieldArray) {
164: int oldSize = this .selectedFieldArray.size();
165: this .selectedFieldArray = selectedFieldArray;
166: //only size is used
167: if (oldSize != selectedFieldArray.size()) {
168: fireFieldArrayChanged(this );
169: fireUpdateAll();
170: }
171: }
172:
173: public void selectFieldArray(Field field) {
174: int oldSize = selectedFieldArray.size();
175: if (selectedFieldArray.contains(field)) {
176: selectedFieldArray.remove(field);
177: if (selectedFieldArray.size() == 0)
178: resetSelectedFieldArray();
179: } else {
180: selectedFieldArray.add(selectedFieldArray.size(), field);
181: }
182: //only size is used
183: if (oldSize != selectedFieldArray.size()) {
184: fireFieldArrayChanged(this );
185: fireUpdateAll();
186: }
187: }
188:
189: public boolean isComposite(GraphicNode node) {
190: return node.isComposite();
191: }
192:
193: /*public int getColumnCount() {
194: return 0;//TODO
195: }*/
196:
197: public int getRowMultiple() {
198: return selectedFieldArray.size();
199: }
200:
201: void resetTimeIntervals() {
202: timeIntervals.clear();
203: }
204:
205: void addTimeInterval(HasStartAndEnd interval) {
206: timeIntervals.add(interval);
207: }
208:
209: public Object getValueAt(int row, int col) {
210: if (col == 0)
211: return getFieldInRow(row).toString();
212: // Node node=getNodeInRow(row/getRowMultiple());
213: Node node = getNodeInRow(row);
214: if (node.isVoid())
215: return null;
216: getFieldContext().setInterval(
217: (HasStartAndEnd) timeIntervals.get(col - 1));
218:
219: return getFieldInRow(row).getValue(node,
220: getCache().getWalkersModel(), fieldContext); //TODO
221: }
222:
223: public void setValueAt(Object value, int row, int col) {
224: Object oldValue = getValueAt(row, col);
225: if (oldValue == null && (value == null || "".equals(value)))
226: return;
227:
228: if (col == 0)
229: return;
230: try {
231: Node rowNode = getNodeInRow(row);
232:
233: if (rowNode.isVirtual())
234: return;
235: getFieldContext().setInterval(
236: (HasStartAndEnd) timeIntervals.get(col - 1));
237:
238: getCache().getModel().setFieldValue(getFieldInRow(row),
239: rowNode, this , value, fieldContext,
240: NodeModel.NORMAL);
241: fireTableCellUpdated(row, col);
242: } catch (FieldParseException e) {
243: Alert.error(e.getMessage()); //TODO clean up messages
244: }
245:
246: }
247:
248: public Field getFieldInRow(int row) {
249: if (selectedFieldArray.size() == 0)
250: return null;
251: return (Field) selectedFieldArray.get(row % getRowMultiple());
252: }
253:
254: public Class getColumnClass(int col) { //for header only
255: if (col == 0)
256: return String.class;
257: return null;
258: }
259:
260: public Class getRowClass(int row) {
261: Field field = getFieldInRow(row);
262: if (field == null)
263: return String.class;
264: else
265: return field.getDisplayType();
266: }
267:
268: protected int columnCount = 1;
269:
270: void incrementColumnCount() {
271: columnCount++;
272: }
273:
274: void decrementColumnCount() {
275: columnCount--;
276: }
277:
278: public int getColumnCount() {
279: return columnCount;//((coord==null)?0:coord.countProjectIntervals())+1;
280: }
281:
282: public boolean isCellEditable(int row, int col) {
283: if (col == 0)
284: return false;
285: Node node = getNodeInRow(row);
286: if (node.isVoid())
287: return true;
288:
289: getFieldContext().setInterval(
290: (HasStartAndEnd) timeIntervals.get(col - 1));
291:
292: return !getFieldInRow(row).isReadOnly(node,
293: getCache().getWalkersModel(), fieldContext);
294: }
295:
296: // timescale
297: public CoordinatesConverter getCoord() {
298: return coord;
299: }
300:
301: public void setCoord(CoordinatesConverter coord) {
302: if (this .coord != null)
303: this .coord.removeTimeScaleListener(this );
304: this .coord = coord;
305: coord.addTimeScaleListener(this );
306: }
307:
308: public void timeScaleChanged(TimeScaleEvent e) {
309: }
310:
311: //selectedFieldArray event handling
312:
313: protected EventListenerList listenerList = new EventListenerList();
314:
315: public void addFieldArrayListener(FieldArrayListener l) {
316: listenerList.add(FieldArrayListener.class, l);
317: }
318:
319: public void removeFieldArrayListener(FieldArrayListener l) {
320: listenerList.remove(FieldArrayListener.class, l);
321: }
322:
323: public FieldArrayListener[] getFieldArrayListeners() {
324: return (FieldArrayListener[]) listenerList
325: .getListeners(FieldArrayListener.class);
326: }
327:
328: protected void fireFieldArrayChanged(Object source) {
329: Object[] listeners = listenerList.getListenerList();
330: FieldArrayEvent e = null;
331: for (int i = listeners.length - 2; i >= 0; i -= 2) {
332: if (listeners[i] == FieldArrayListener.class) {
333: if (e == null) {
334: e = new FieldArrayEvent(source,
335: getSelectedFieldArray());
336: }
337: ((FieldArrayListener) listeners[i + 1])
338: .fieldArrayChanged(e);
339: }
340: }
341: }
342:
343: public EventListener[] getFieldArrayListeners(Class listenerType) {
344: return listenerList.getListeners(listenerType);
345: }
346:
347: }
|