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.Collection;
055:
056: import javax.swing.JScrollPane;
057:
058: import org.apache.commons.collections.Closure;
059:
060: import com.projity.configuration.Dictionary;
061: import com.projity.field.FieldContext;
062: import com.projity.graphic.configuration.CellStyle;
063: import com.projity.graphic.configuration.GraphicConfiguration;
064: import com.projity.graphic.configuration.SpreadSheetFieldArray;
065: import com.projity.grouping.core.Node;
066: import com.projity.grouping.core.transform.ViewTransformer;
067: import com.projity.grouping.core.transform.filtering.NodeFilter;
068: import com.projity.grouping.core.transform.filtering.SelectionFilter;
069: import com.projity.help.HelpUtil;
070: import com.projity.menu.MenuManager;
071: import com.projity.pm.graphic.frames.DocumentFrame;
072: import com.projity.pm.graphic.model.cache.NodeModelCache;
073: import com.projity.pm.graphic.model.cache.NodeModelCacheFactory;
074: import com.projity.pm.graphic.model.cache.ReferenceNodeModelCache;
075: import com.projity.pm.graphic.model.transform.NodeCacheTransformer;
076: import com.projity.pm.graphic.spreadsheet.SpreadSheet;
077: import com.projity.pm.graphic.spreadsheet.SpreadSheetModel;
078: import com.projity.pm.graphic.spreadsheet.SpreadSheetUtils;
079: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheet;
080: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheetModel;
081: import com.projity.pm.graphic.spreadsheet.selection.event.SelectionNodeEvent;
082: import com.projity.pm.graphic.spreadsheet.selection.event.SelectionNodeListener;
083: import com.projity.pm.graphic.spreadsheet.time.FieldArrayEvent;
084: import com.projity.pm.graphic.spreadsheet.time.FieldArrayListener;
085: import com.projity.pm.graphic.spreadsheet.time.TimeSpreadSheet;
086: import com.projity.pm.graphic.spreadsheet.time.TimeSpreadSheetModel;
087: import com.projity.pm.graphic.timescale.CoordinatesConverter;
088: import com.projity.pm.graphic.timescale.ScaledScrollPane;
089: import com.projity.pm.graphic.views.synchro.Synchronizer;
090: import com.projity.pm.resource.Resource;
091: import com.projity.pm.task.Project;
092: import com.projity.strings.Messages;
093: import com.projity.undo.UndoController;
094: import com.projity.workspace.WorkspaceSetting;
095:
096: /**
097: *
098: */
099: public class UsageDetailView extends SplittedView implements BaseView,
100: FieldArrayListener, SelectionNodeListener {
101: private static final long serialVersionUID = 8603734334991284800L;
102: protected SpreadSheet spreadSheet;
103: protected TimeSpreadSheet timeSpreadSheet;
104: protected ReferenceNodeModelCache refCache;
105: protected NodeModelCache cache;
106: protected CoordinatesConverter coord;
107: private Project project;
108: DocumentFrame documentFrame;
109: protected boolean taskUsage;
110: FieldContext fieldContext;
111: protected ScaledScrollPane timeScrollPane;
112: protected CellStyle cellStyle;
113: protected String viewName;
114: protected boolean hasEmptyRows;
115: private boolean subView;
116:
117: /**
118: * @param project
119: * @param manager
120: *
121: */
122: public UsageDetailView(DocumentFrame documentFrame,
123: MenuManager manager, Synchronizer synchronizer) {
124: super (synchronizer);
125: this .documentFrame = documentFrame;
126: this .project = documentFrame.getProject();
127: setNeedVoidBar(true);
128: // setScaled(true);
129:
130: setDeltaDivider(GraphicConfiguration.getInstance()
131: .getRowHeaderWidth());
132: }
133:
134: public void init(ReferenceNodeModelCache refCache,
135: boolean taskUsage, CoordinatesConverter coord,
136: boolean subView, String viewName, Closure transformerClosure) {
137: this .coord = coord;
138: this .subView = subView;
139: hasEmptyRows = !subView;
140: this .viewName = viewName;
141: this .cache = NodeModelCacheFactory.getInstance()
142: .createFilteredCache(refCache, viewName,
143: transformerClosure);
144:
145: this .taskUsage = taskUsage;
146: fieldContext = new FieldContext();
147: fieldContext.setLeftAssociation(taskUsage);
148: HelpUtil.addDocHelp(this , taskUsage ? (subView ? "Task_Usage"
149: : "Task_Usage_Detail") : (subView ? "Resource_Usage"
150: : "Resource_Usage_Detail"));
151: super .init();
152: // cache.update(); //this is not required by certain views
153: }
154:
155: public void cleanUp() {
156: super .cleanUp();
157: coord.removeTimeScaleListener(timeScrollPane);
158: ((TimeSpreadSheetModel) timeSpreadSheet.getModel())
159: .removeFieldArrayListener(this );
160: spreadSheet.cleanUp();
161: timeSpreadSheet.cleanUp();
162: spreadSheet = null;
163: timeSpreadSheet = null;
164: refCache = null;
165: cache = null;
166: coord = null;
167: project = null;
168: documentFrame = null;
169: fieldContext = null;
170: timeScrollPane = null;
171: cellStyle = null;
172: viewName = null;
173: }
174:
175: protected JScrollPane createLeftScrollPane() {
176: spreadSheet = new SpreadSheet() {
177: private static final long serialVersionUID = 1996911145637609217L;
178:
179: public boolean isNodeDeletable(Node node) {
180: return !(node.getImpl() instanceof Resource); // only delete resource on res list
181: }
182: };
183: spreadSheet
184: .setSpreadSheetCategory((taskUsage) ? taskAssignmentSpreadsheetCategory
185: : resourceAssignmentSpreadsheetCategory); // for columns. must do first
186: SpreadSheetFieldArray fields = getFields();
187: spreadSheet.setCache(cache, fields, fields.getCellStyle(),
188: fields.getActionList());
189: ((SpreadSheetModel) spreadSheet.getModel())
190: .setFieldContext(fieldContext);
191:
192: cache.update(); //this is not required by certain views
193:
194: return SpreadSheetUtils.makeSpreadsheetScrollPane(spreadSheet);
195: }
196:
197: protected JScrollPane createRightScrollPane() {
198: timeSpreadSheet = new TimeSpreadSheet(project);
199: timeSpreadSheet.setSpreadSheetCategory(timeSpreadsheetCategory);
200: SpreadSheetFieldArray fields = getDistributionFields();
201: timeSpreadSheet.setCache(cache, fields, fields.getCellStyle(),
202: fields.getActionList());
203: ((TimeSpreadSheetModel) timeSpreadSheet.getModel())
204: .addFieldArrayListener(this );
205:
206: timeScrollPane = new ScaledScrollPane(timeSpreadSheet, coord,
207: documentFrame);
208: timeSpreadSheet.createDefaultColumnsFromModel();
209: // timeSpreadSheet.revalidate();
210: // timeSpreadSheet.repaint();
211: return timeScrollPane;
212: }
213:
214: // spreadsheet fields
215: private SpreadSheetFieldArray getFields() {
216: if (taskUsage)
217: return (SpreadSheetFieldArray) Dictionary
218: .get(
219: taskAssignmentSpreadsheetCategory,
220: Messages
221: .getString("Spreadsheet.Assignment.taskUsage")); // TODO don't hardcode
222: else
223: return (SpreadSheetFieldArray) Dictionary
224: .get(
225: resourceAssignmentSpreadsheetCategory,
226: Messages
227: .getString("Spreadsheet.Assignment.resourceUsage")); // TODO don't hardcode
228: }
229:
230: private SpreadSheetFieldArray getDistributionFields() {
231: return (SpreadSheetFieldArray) Dictionary
232: .get(
233: timeSpreadsheetCategory,
234: Messages
235: .getString(taskUsage ? "Spreadsheet.TaskUsage.default"
236: : "Spreadsheet.ResourceUsage.default")); // TODO don't hardcode
237: }
238:
239: /**
240: * @return Returns the spreadSheet.
241: */
242: public SpreadSheet getSpreadSheet() {
243: return spreadSheet;
244: }
245:
246: public TimeSpreadSheet getTimeSpreadSheet() {
247: return timeSpreadSheet;
248: }
249:
250: public void forceUpdateOfTimeSpreadSheet() {
251: // dynamic time spreadsheets don't update themselves for a stange reason fix here
252: int height = ((CommonSpreadSheetModel) spreadSheet.getModel())
253: .getRowCount()
254: * ((TimeSpreadSheetModel) timeSpreadSheet.getModel())
255: .getRowMultiple()
256: * GraphicConfiguration.getInstance().getRowHeight();
257: timeSpreadSheet
258: .setPreferredSize(new Dimension((int) coord.toW(coord
259: .getEnd()
260: - coord.getOrigin()), height/*spreadSheet.getPreferredSize().height*/));
261: timeSpreadSheet.setSize(timeSpreadSheet.getPreferredSize());
262: timeSpreadSheet.revalidate();
263: }
264:
265: public void fieldArrayChanged(FieldArrayEvent e) {
266: int num = e.getFieldArray().size();
267: int rowHeight = GraphicConfiguration.getInstance()
268: .getRowHeight()
269: * num;
270: spreadSheet.setRowHeight(rowHeight);
271: forceUpdateOfTimeSpreadSheet(); // because it doesn't update automatically
272: }
273:
274: public void selectionChanged(SelectionNodeEvent e) {
275: if (e.getSource() == spreadSheet
276: || !(e.getSource() instanceof CommonSpreadSheet))
277: return;
278: CommonSpreadSheet sp = (CommonSpreadSheet) e.getSource();
279: boolean taskSelection;
280: if (taskSpreadsheetCategory.equals(sp.getSpreadSheetCategory())
281: || taskAssignmentSpreadsheetCategory.equals(sp
282: .getSpreadSheetCategory()))
283: taskSelection = true;
284: else if (resourceSpreadsheetCategory.equals(sp
285: .getSpreadSheetCategory())
286: || resourceAssignmentSpreadsheetCategory.equals(sp
287: .getSpreadSheetCategory()))
288: taskSelection = false;
289: else
290: return;
291:
292: ViewTransformer transformer = ((NodeCacheTransformer) cache
293: .getVisibleNodes().getTransformer()).getTransformer();
294: NodeFilter filter = transformer.getHiddenFilter();
295: if (filter instanceof SelectionFilter) {
296: ((SelectionFilter) filter).setSelectedNodesImpl(
297: documentFrame.getTopSpreadSheet()
298: .getSelectedNodesImpl(), taskSelection);
299: forceUpdateOfTimeSpreadSheet(); // because it doesn't update automatically
300: }
301: }
302:
303: public UndoController getUndoController() {
304: if (showsTasks())
305: return project.getUndoController();
306: else
307: return project.getResourcePool().getUndoController();
308: }
309:
310: public void zoomIn() {
311: coord.zoomIn();
312: }
313:
314: public void zoomOut() {
315: coord.zoomOut();
316: }
317:
318: public boolean canZoomIn() {
319: return coord.canZoomIn();
320: }
321:
322: public boolean canZoomOut() {
323: return coord.canZoomOut();
324: }
325:
326: public int getScale() {
327: return coord.getTimescaleManager().getCurrentScaleIndex();
328: }
329:
330: public boolean hasNormalMinWidth() {
331: return false;
332: }
333:
334: public String getViewName() {
335: return viewName;
336: }
337:
338: public boolean showsTasks() {
339: return taskUsage;
340: }
341:
342: public boolean showsResources() {
343: return !taskUsage;
344: }
345:
346: public void onActivate(boolean activate) {
347: }
348:
349: public boolean isPrintable() {
350: return false;
351: }
352:
353: public void restoreWorkspace(WorkspaceSetting w, int context) {
354: Workspace ws = (Workspace) w;
355: spreadSheet.restoreWorkspace(ws.spreadSheet, context);
356: timeSpreadSheet.restoreWorkspace(ws.timeSpreadSheet, context);
357: timeSpreadSheet
358: .setSelectedFieldArray((ArrayList) SpreadSheetFieldArray
359: .fromIdArray(ws.selectedFieldArray));
360: timeScrollPane.restoreWorkspace(ws.scrollPane, context);
361: setDividerLocation(ws.dividerLocation);
362: }
363:
364: public WorkspaceSetting createWorkspace(int context) {
365: Workspace ws = new Workspace();
366: ws.spreadSheet = spreadSheet.createWorkspace(context);
367: ws.timeSpreadSheet = timeSpreadSheet.createWorkspace(context);
368: ws.selectedFieldArray = SpreadSheetFieldArray
369: .toIdArray(timeSpreadSheet.getSelectedFieldArray());
370: ws.scrollPane = timeScrollPane.createWorkspace(context);
371: ws.dividerLocation = getDividerLocation();
372: return ws;
373: }
374:
375: public static class Workspace implements WorkspaceSetting {
376: private static final long serialVersionUID = 8588696931239304763L;
377: WorkspaceSetting spreadSheet;
378: WorkspaceSetting timeSpreadSheet;
379: Collection selectedFieldArray;
380: WorkspaceSetting scrollPane;
381: int dividerLocation;
382:
383: public WorkspaceSetting getSpreadSheet() {
384: return spreadSheet;
385: }
386:
387: public void setSpreadSheet(WorkspaceSetting spreadSheet) {
388: this .spreadSheet = spreadSheet;
389: }
390:
391: public Collection getSelectedFieldArray() {
392: return selectedFieldArray;
393: }
394:
395: public void setSelectedFieldArray(Collection selectedFieldArray) {
396: this .selectedFieldArray = selectedFieldArray;
397: }
398:
399: public WorkspaceSetting getTimeSpreadSheet() {
400: return timeSpreadSheet;
401: }
402:
403: public void setTimeSpreadSheet(WorkspaceSetting timeSpreadSheet) {
404: this .timeSpreadSheet = timeSpreadSheet;
405: }
406:
407: public WorkspaceSetting getScrollPane() {
408: return scrollPane;
409: }
410:
411: public void setScrollPane(WorkspaceSetting scrollPane) {
412: this .scrollPane = scrollPane;
413: }
414:
415: public int getDividerLocation() {
416: return dividerLocation;
417: }
418:
419: public void setDividerLocation(int dividerLocation) {
420: this .dividerLocation = dividerLocation;
421: }
422:
423: }
424:
425: public boolean canScrollToTask() {
426: // TODO Auto-generated method stub
427: return false;
428: }
429:
430: public void scrollToTask() {
431: // TODO Auto-generated method stub
432:
433: }
434:
435: public NodeModelCache getCache() {
436: return cache;
437: }
438:
439: }
|