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.views;
051:
052: import java.awt.Dimension;
053: import java.util.ArrayList;
054: import java.util.Iterator;
055: import java.util.List;
056: import java.util.SortedSet;
057: import java.util.TreeSet;
058:
059: import javax.swing.JScrollPane;
060: import javax.swing.event.ChangeEvent;
061: import javax.swing.event.ChangeListener;
062:
063: import com.projity.configuration.Configuration;
064: import com.projity.configuration.Dictionary;
065: import com.projity.configuration.Settings;
066: import com.projity.field.FieldContext;
067: import com.projity.graphic.configuration.BarStyles;
068: import com.projity.graphic.configuration.CellStyle;
069: import com.projity.graphic.configuration.GraphicConfiguration;
070: import com.projity.graphic.configuration.SpreadSheetCategories;
071: import com.projity.graphic.configuration.SpreadSheetFieldArray;
072: import com.projity.grouping.core.model.NodeModel;
073: import com.projity.help.HelpUtil;
074: import com.projity.menu.MenuActionConstants;
075: import com.projity.menu.MenuManager;
076: import com.projity.pm.graphic.frames.DocumentFrame;
077: import com.projity.pm.graphic.gantt.Gantt;
078: import com.projity.pm.graphic.model.cache.NodeModelCache;
079: import com.projity.pm.graphic.model.cache.NodeModelCacheFactory;
080: import com.projity.pm.graphic.model.cache.ReferenceNodeModelCache;
081: import com.projity.pm.graphic.spreadsheet.SpreadSheet;
082: import com.projity.pm.graphic.spreadsheet.SpreadSheetModel;
083: import com.projity.pm.graphic.spreadsheet.SpreadSheetUtils;
084: import com.projity.pm.graphic.timescale.CoordinatesConverter;
085: import com.projity.pm.graphic.timescale.ScaledScrollPane;
086: import com.projity.pm.graphic.views.synchro.Synchronizer;
087: import com.projity.pm.scheduling.ScheduleEvent;
088: import com.projity.pm.scheduling.ScheduleEventListener;
089: import com.projity.pm.snapshot.Snapshottable;
090: import com.projity.pm.task.Project;
091: import com.projity.pm.task.Task;
092: import com.projity.pm.task.TaskSnapshot;
093: import com.projity.pm.time.HasStartAndEnd;
094: import com.projity.strings.Messages;
095: import com.projity.undo.UndoController;
096: import com.projity.workspace.WorkspaceSetting;
097:
098: /**
099: *
100: */
101: public class GanttView extends SplittedView implements BaseView,
102: ScheduleEventListener {
103: /**
104: *
105: */
106: private static final long serialVersionUID = 514828655690086836L;
107: protected SpreadSheet spreadSheet;
108: protected Gantt gantt;
109: protected SortedSet baseLines = new TreeSet();
110:
111: protected ScaledScrollPane ganttScrollPane;
112: protected NodeModel model;
113: protected NodeModelCache cache;
114: protected CoordinatesConverter coord;
115: private Project project;
116: DocumentFrame documentFrame;
117: FieldContext fieldContext;
118: CellStyle cellStyle;
119: private boolean tracking = false;
120: public static final String spreadsheetCategory = taskSpreadsheetCategory;
121:
122: /**
123: * @param project
124: * @param manager
125: *
126: */
127: public GanttView(DocumentFrame documentFrame, MenuManager manager,
128: Synchronizer synchronizer) {
129: super (synchronizer);
130: this .documentFrame = documentFrame;
131: this .project = documentFrame.getProject();
132: HelpUtil.addDocHelp(this , "Gantt_Chart");
133: setNeedVoidBar(true);
134: //setScaled(true);
135: }
136:
137: public void init(ReferenceNodeModelCache cache, NodeModel model,
138: CoordinatesConverter coord) {
139: this .coord = coord;
140: this .cache = NodeModelCacheFactory.getInstance()
141: .createFilteredCache((ReferenceNodeModelCache) cache,
142: getViewName(), null);
143:
144: fieldContext = new FieldContext();
145: fieldContext.setLeftAssociation(true);
146: /*cellStyle=new CellStyle(){
147: CellFormat cellProperties=new CellFormat();
148: public CellFormat getCellProperties(GraphicNode node){
149: cellProperties.setBold(node.isSummary());
150: cellProperties.setItalic(node.isAssignment());
151: //cellProperties.setBackground((node.isAssignment())?"NORMAL_LIGHT_YELLOW":"NORMAL_YELLOW");
152: cellProperties.setCompositeIcon(node.isComposite());
153: return cellProperties;
154: }
155:
156: };*/
157: super .init();
158: updateHeight(project);
159: updateSize();
160:
161: //sync the height of spreadsheet and gantt
162: leftScrollPane.getViewport().addChangeListener(
163: new ChangeListener() {
164: private Dimension olddl = null;
165:
166: public void stateChanged(ChangeEvent e) {
167: Dimension dl = leftScrollPane.getViewport()
168: .getViewSize();
169: if (dl.equals(olddl))
170: return;
171: olddl = dl;
172: // Dimension dr=rightScrollPane.getViewport().getViewSize();
173: // ((Gantt)rightScrollPane.getViewport().getView()).setPreferredSize(new Dimension((int)dr.getWidth(),(int)dl.getHeight()));
174: // rightScrollPane.getViewport().revalidate();
175: ((Gantt) rightScrollPane.getViewport()
176: .getView())
177: .setPreferredSize(new Dimension(
178: rightScrollPane.getViewport()
179: .getViewSize().width,
180: dl.height));
181: }
182: });
183:
184: //TODO automatic scrolling to add as an option
185: // spreadSheet.getRowHeader().getSelectionModel().addListSelectionListener(new ListSelectionListener(){
186: // public void valueChanged(ListSelectionEvent e) {
187: // if (!e.getValueIsAdjusting()&&spreadSheet.getRowHeader().getSelectedRowCount()==1){
188: // List impls=spreadSheet.getSelectedNodesImpl();
189: // if (impls.size()!=1) return;
190: // Object impl=impls.get(0);
191: // if (!(impl instanceof HasStartAndEnd)) return;
192: // HasStartAndEnd interval=(HasStartAndEnd)impl;
193: // gantt.scrollToTask(interval, true);
194: // }
195: // }
196: // });
197:
198: cache.update();
199:
200: //Call this last to be sure everything is initialized
201: //gantt.insertCacheData(); //useless?
202:
203: }
204:
205: public void cleanUp() {
206: super .cleanUp();
207: coord.removeTimeScaleListener(ganttScrollPane);
208: project.removeScheduleListener(this );
209: spreadSheet.cleanUp();
210: gantt.cleanUp();
211: spreadSheet = null;
212: gantt = null;
213: baseLines = null;
214: ganttScrollPane = null;
215: model = null;
216: cache = null;
217: coord = null;
218: project = null;
219: documentFrame = null;
220: fieldContext = null;
221: cellStyle = null;
222: }
223:
224: public void setBarStyles(String styleName) {
225: if (gantt == null)
226: return;
227: gantt.setBarStyles((BarStyles) Dictionary.get(
228: BarStyles.category, styleName));
229: }
230:
231: protected JScrollPane createLeftScrollPane() {
232: spreadSheet = new SpreadSheet();
233: spreadSheet.setName(project.getName());
234: spreadSheet.setSpreadSheetCategory(spreadsheetCategory); // for columns. Must do first
235: SpreadSheetFieldArray fields = getFields();
236: if (project.getFieldArray() != null) {
237: fields = project.getFieldArray();
238: }
239: spreadSheet.setCache(cache, fields, fields.getCellStyle(),
240: fields.getActionList());
241: if (project.getFieldArray() != null)
242: spreadSheet.setFieldArrayWithWidths(fields);
243: ((SpreadSheetModel) spreadSheet.getModel())
244: .setFieldContext(fieldContext);
245: project.removeScheduleListener(this ); // in case was already attached and recreating (applet)
246: project.addScheduleListener(this );
247: return SpreadSheetUtils.makeSpreadsheetScrollPane(spreadSheet);
248: }
249:
250: protected JScrollPane createRightScrollPane() {
251: gantt = new Gantt(project, "Gantt");
252: gantt.setCache(cache);
253: gantt.setBarStyles((BarStyles) Dictionary.get(
254: BarStyles.category, "standard"));
255: ganttScrollPane = new ScaledScrollPane(gantt, coord,
256: documentFrame);
257: return ganttScrollPane;
258: }
259:
260: public void activateEmptyRowHeader(boolean activate) {
261: ganttScrollPane.activateEmptyRowHeader(activate);
262: }
263:
264: //spreadsheet fields
265: private static SpreadSheetFieldArray getFields() {
266: return (SpreadSheetFieldArray) Dictionary.get(
267: spreadsheetCategory, Messages
268: .getString("Spreadsheet.Task.entry")); //TODO don't hardcode
269: }
270:
271: /**
272: *
273: * @param name
274: * @return old field array
275: */
276: public ArrayList setColumns(String name) {
277: ArrayList old = spreadSheet.getFieldArray();
278: setColumns((ArrayList) Dictionary.get(spreadsheetCategory,
279: Messages.getString(name)));
280: return old;
281: }
282:
283: public void setColumns(ArrayList fields) {
284: spreadSheet.setFieldArray(fields);
285: }
286:
287: /**
288: * @return Returns the spreadSheet.
289: */
290: public SpreadSheet getSpreadSheet() {
291: return spreadSheet;
292: }
293:
294: public void updateHeight(Integer snapshotId, boolean add) {
295: if (add)
296: baseLines.add(snapshotId);
297: else
298: baseLines.remove(snapshotId);
299: int num = (baseLines.size() == 0) ? 0 : (((Integer) baseLines
300: .last()).intValue() + 1);
301: int rowHeight = GraphicConfiguration.getInstance()
302: .getRowHeight()
303: + num
304: * GraphicConfiguration.getInstance()
305: .getBaselineHeight();
306: spreadSheet.setRowHeight(rowHeight);
307: gantt.setRowHeight(rowHeight);
308: }
309:
310: public void updateHeight(Project project) {
311: baseLines.clear();
312: for (Iterator i = project.getTaskOutlineIterator(); i.hasNext();) {
313: Task task = (Task) i.next();
314: int current = Snapshottable.CURRENT.intValue();
315: for (int s = 0; s < Settings.numGanttBaselines(); s++) {
316: if (s == current)
317: continue;
318: TaskSnapshot snapshot = (TaskSnapshot) task
319: .getSnapshot(new Integer(s));
320: if (snapshot != null)
321: baseLines.add(new Integer(s));
322: }
323: }
324: int num = (baseLines.size() == 0) ? 0 : (((Integer) baseLines
325: .last()).intValue() + 1);
326: int rowHeight = GraphicConfiguration.getInstance()
327: .getRowHeight()
328: + num
329: * GraphicConfiguration.getInstance()
330: .getBaselineHeight();
331: spreadSheet.setRowHeight(rowHeight);
332: gantt.setRowHeight(rowHeight);
333: }
334:
335: public void scheduleChanged(ScheduleEvent evt) {
336: if (evt.getType() == ScheduleEvent.SCHEDULE) {
337: //gantt.updateSize(); //done throught cache
338: } else if (evt.getType() == ScheduleEvent.ACTUAL) {
339: } else if (evt.getType() == ScheduleEvent.BASELINE) {
340: updateHeight(evt.getSnapshot(), evt.isSaveSnapshot());
341: //Warning: listeners order is important.
342: //This one must be before GanttModel one which calls updateAll after the height is setted
343: }
344: }
345:
346: public void updateSize() {
347: gantt.updateSize();
348: }
349:
350: public UndoController getUndoController() {
351: return project.getUndoController();
352: }
353:
354: public void zoomIn() {
355: coord.zoomIn();
356: }
357:
358: public void zoomOut() {
359: coord.zoomOut();
360: }
361:
362: public boolean canZoomIn() {
363: return coord.canZoomIn();
364: }
365:
366: public boolean canZoomOut() {
367: return coord.canZoomOut();
368: }
369:
370: public int getScale() {
371: return coord.getTimescaleManager().getCurrentScaleIndex();
372: }
373:
374: public boolean hasNormalMinWidth() {
375: return true;
376: }
377:
378: public String getViewName() {
379: return MenuActionConstants.ACTION_GANTT;
380: }
381:
382: public boolean showsTasks() {
383: return true;
384: }
385:
386: public boolean showsResources() {
387: return false;
388: }
389:
390: public void onActivate(boolean activate) {
391: }
392:
393: public Gantt getGantt() {
394: return gantt;
395: }
396:
397: public boolean isPrintable() {
398: return true;
399: }
400:
401: public void reinitialize() { // applet
402: createLeftScrollPane();
403: }
404:
405: public void restoreWorkspace(WorkspaceSetting w, int context) {
406: Workspace ws = (Workspace) w;
407: spreadSheet.restoreWorkspace(ws.spreadSheet, context);
408: ganttScrollPane.restoreWorkspace(ws.scrollPane, context);
409: setDividerLocation(ws.dividerLocation);
410: }
411:
412: public WorkspaceSetting createWorkspace(int context) {
413: Workspace ws = new Workspace();
414: ws.spreadSheet = spreadSheet.createWorkspace(context);
415: ws.scrollPane = ganttScrollPane.createWorkspace(context);
416: ws.dividerLocation = getDividerLocation();
417: return ws;
418: }
419:
420: public static class Workspace implements WorkspaceSetting {
421: private static final long serialVersionUID = -407561451956813994L;
422: WorkspaceSetting spreadSheet;
423: WorkspaceSetting scrollPane;
424: int dividerLocation;
425:
426: public WorkspaceSetting getSpreadSheet() {
427: return spreadSheet;
428: }
429:
430: public void setSpreadSheet(WorkspaceSetting spreadSheet) {
431: this .spreadSheet = spreadSheet;
432: }
433:
434: public WorkspaceSetting getScrollPane() {
435: return scrollPane;
436: }
437:
438: public void setScrollPane(WorkspaceSetting scrollPane) {
439: this .scrollPane = scrollPane;
440: }
441:
442: public int getDividerLocation() {
443: return dividerLocation;
444: }
445:
446: public void setDividerLocation(int dividerLocation) {
447: this .dividerLocation = dividerLocation;
448: }
449: }
450:
451: public boolean canScrollToTask() {
452: return true;
453: }
454:
455: public void scrollToTask() {
456: List impls = spreadSheet.getSelectedNodesImpl();
457: if (impls.size() == 0)
458: return;
459: Object impl = impls.get(0);
460: if (!(impl instanceof HasStartAndEnd))
461: return;
462: HasStartAndEnd interval = (HasStartAndEnd) impl;
463: gantt.scrollToTask(interval, false);
464: }
465:
466: public NodeModelCache getCache() {
467: return cache;
468: }
469:
470: public boolean isTracking() {
471: return tracking;
472: }
473:
474: public void setTracking(boolean tracking) {
475: this .tracking = tracking;
476: HelpUtil.addDocHelp(this , tracking ? "Tracking_Gantt_Chart"
477: : "Gantt_Chart");
478: }
479:
480: }
|