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.reports.view;
051:
052: import java.awt.BorderLayout;
053: import java.awt.event.ActionEvent;
054: import java.awt.event.ActionListener;
055: import java.util.ArrayList;
056: import java.util.HashMap;
057:
058: import javax.swing.DefaultComboBoxModel;
059: import javax.swing.JComboBox;
060: import javax.swing.JLabel;
061: import javax.swing.JPanel;
062:
063: import net.sf.jasperreports.engine.JRException;
064: import net.sf.jasperreports.engine.JasperFillManager;
065: import net.sf.jasperreports.engine.JasperPrint;
066: import net.sf.jasperreports.engine.JasperReport;
067:
068: import org.apache.commons.collections.Closure;
069: import org.apache.commons.collections.CollectionUtils;
070: import org.apache.commons.collections.Predicate;
071:
072: import com.projity.configuration.Dictionary;
073: import com.projity.configuration.ReportDefinition;
074: import com.projity.configuration.ScriptConfiguration;
075: import com.projity.contrib.ClassResolverFilter;
076: import com.projity.field.Field;
077: import com.projity.graphic.configuration.SpreadSheetFieldArray;
078: import com.projity.grouping.core.model.NodeModel;
079: import com.projity.grouping.core.transform.filtering.PredicatedNodeFilterIterator;
080: import com.projity.help.HelpUtil;
081: import com.projity.pm.graphic.frames.DocumentFrame;
082: import com.projity.pm.graphic.frames.GraphicManager;
083: import com.projity.pm.graphic.model.cache.GeneralFilteredIterator;
084: import com.projity.pm.graphic.model.cache.NodeModelCache;
085: import com.projity.pm.graphic.model.cache.NodeModelCacheFactory;
086: import com.projity.pm.graphic.model.cache.ReferenceNodeModelCache;
087: import com.projity.pm.graphic.model.event.CacheListener;
088: import com.projity.pm.graphic.model.event.CompositeCacheEvent;
089: import com.projity.pm.graphic.spreadsheet.SpreadSheet;
090: import com.projity.pm.graphic.timescale.CoordinatesConverter;
091: import com.projity.pm.graphic.views.BaseView;
092: import com.projity.pm.task.Project;
093: import com.projity.reports.adapter.DataSource;
094: import com.projity.reports.adapter.DataSourceProvider;
095: import com.projity.reports.adapter.ReportUtil;
096: import com.projity.reports.adapter.ReportViewer;
097: import com.projity.strings.Messages;
098: import com.projity.undo.UndoController;
099: import com.projity.util.Environment;
100: import com.projity.workspace.WorkspaceSetting;
101:
102: /**
103: *
104: */
105: public class ReportView extends JPanel implements BaseView,
106: CacheListener {
107: private static final long serialVersionUID = 5457040745964404658L;
108: protected JPanel report;
109: protected Project project;
110: private ReportViewer viewer = null;
111: private DocumentFrame documentFrame;
112: private boolean xmlFile = true;
113: private ReportDefinition reportDefinition = null;
114: JLabel reportLabel;
115: JComboBox reportChoice;
116: JLabel columnsLabel;
117: JComboBox columnsChoice;
118: CoordinatesConverter coord;
119: SpreadSheetFieldArray fieldArray = null;
120: BorderLayout layout = new java.awt.BorderLayout();
121: NodeModelCache cache;
122: private boolean initializing;
123: boolean dirty = true;
124: NodeModelCache taskCache = null;
125: NodeModelCache resourceCache = null;
126: private String viewName = DataSourceProvider.TASK_REPORT_VIEW;// initial report is task based
127: private Closure transformerClosure;
128:
129: /**
130: *
131: */
132: public ReportView(DocumentFrame documentFrame) {
133: super ();
134: this .documentFrame = documentFrame;
135: this .project = documentFrame.getProject();
136: HelpUtil.addDocHelp(this , "Report_View");
137: //Note that the hook to the filter/sort/group combos is done in makeViewer according to the report type
138: if (!Environment.getStandAlone()) {
139: try {
140: Class.forName("bsh.BshClassManager").getMethod(
141: "setClassResolverFilter",
142: new Class[] { ClassResolverFilter.class })
143: .invoke(
144: null,
145: new Object[] { ScriptConfiguration
146: .getInstance() });
147: } catch (Exception e) {
148: e.printStackTrace();
149: }
150: }
151: //BshClassManager.setClassResolverFilter(ScriptConfiguration.getInstance());
152: transformerClosure = documentFrame
153: .addTransformerInitializationClosure();
154: }
155:
156: public void cleanUp() {
157: if (cache != null)
158: cache.removeNodeModelListener(this );
159: report = null;
160: project = null;
161: viewer = null;
162: documentFrame = null;
163: reportDefinition = null;
164: reportLabel = null;
165: reportChoice = null;
166: columnsLabel = null;
167: columnsChoice = null;
168: coord = null;
169: fieldArray = null;
170: layout = null;
171: cache = null;
172: taskCache = null;
173: resourceCache = null;
174: viewName = null;
175: }
176:
177: private NodeModelCache newFilteredCache(
178: ReferenceNodeModelCache cache, String viewName) {
179: NodeModelCache c = NodeModelCacheFactory.getInstance()
180: .createFilteredCache(cache, viewName,
181: transformerClosure);
182: c.update();
183: return c;
184: }
185:
186: private NodeModel updateCacheForView(String viewName) {
187: if (viewName.equals(DataSourceProvider.TASK_REPORT_VIEW)) {
188: if (taskCache == null)
189: taskCache = newFilteredCache(
190: (ReferenceNodeModelCache) documentFrame
191: .getTaskNodeModelCache(), viewName);
192: cache = taskCache;
193: } else if (viewName
194: .equals(DataSourceProvider.RESOURCE_REPORT_VIEW)) {
195: if (resourceCache == null)
196: resourceCache = newFilteredCache(
197: (ReferenceNodeModelCache) documentFrame
198: .getResourceNodeModelCache(), viewName);
199: cache = resourceCache;
200: } else if (viewName
201: .equals(DataSourceProvider.PROJECT_REPORT_VIEW)) {
202: cache = null;
203: return GraphicManager.getInstance(this ).getProjectFactory()
204: .getPortfolio().getNodeModel();
205: }
206: return cache.getModel();
207:
208: }
209:
210: private void showReport() {
211: try {
212: makeViewer();
213: } catch (JRException e) {
214: System.out.println(e.getMessage());
215: e.printStackTrace();
216: }
217:
218: }
219:
220: private void makeViewer() throws JRException {
221: if (!dirty)
222: return;
223:
224: documentFrame.showWaitCursor(true);
225:
226: if (cache != null) { // remove old listener
227: cache.removeNodeModelListener(this );
228: }
229:
230: DataSource dataSource;
231:
232: SpreadSheetFieldArray fa = null;
233: if (fieldArray != null) {
234: fa = (SpreadSheetFieldArray) fieldArray.clone();
235: CollectionUtils.filter(fa, new Predicate() {
236: public boolean evaluate(Object arg0) {
237: return !((Field) arg0).isGraphical(); // get rid of fields that can't be shown
238: }
239: });
240: }
241: JasperReport report = ReportUtil.getReport(reportDefinition,
242: coord.getProjectTimeIterator(), fa);
243:
244: viewName = DataSourceProvider.getViewName(report);
245: //System.out.println("viewName="+viewName);
246: documentFrame.setComboBoxesViewName(viewName);
247:
248: NodeModel model = null;
249: PredicatedNodeFilterIterator iterator;
250: if (viewName == DataSourceProvider.REPORT_VIEW) { // special case to just use project
251: cache = null;
252: ArrayList list = new ArrayList();
253: list.add(project);
254: iterator = GeneralFilteredIterator
255: .instance(list.iterator());
256: } else {
257: model = updateCacheForView(viewName);
258: if (cache == null) {
259: iterator = GeneralFilteredIterator.instance(model
260: .iterator());
261: //for (Iterator i=GeneralFilteredIterator.instance(model.iterator());i.hasNext();) System.out.println("Report model iterator: "+i.next());
262: } else {
263: iterator = GeneralFilteredIterator.instance(cache
264: .getIterator());
265: //for (Iterator i=GeneralFilteredIterator.instance(cache.getIterator());i.hasNext();) System.out.println("Report cache iterator: "+i.next());
266: }
267: }
268: dataSource = DataSourceProvider.createDataSource(report,
269: project, iterator, model);
270:
271: // projet name is used as report's title
272: // and passed as a parameter
273: HashMap params = new HashMap();
274: params.put("projectName", project.getName()); //$NON-NLS-1$
275:
276: JasperPrint jasperPrint = JasperFillManager.fillReport(report,
277: params, dataSource);
278: if (viewer != null) {
279: viewer.changeReport(jasperPrint);
280: } else {
281: viewer = new ReportViewer(jasperPrint);
282: add(viewer, BorderLayout.CENTER);
283: }
284: // add new listener
285: if (cache != null) {
286: cache.addNodeModelListener(this );
287: }
288: dirty = false;
289:
290: documentFrame.showWaitCursor(false);
291:
292: }
293:
294: private JPanel header() {
295: JPanel panel = new JPanel();
296: panel.add(reportLabel);
297: panel.add(reportChoice);
298: panel.add(columnsLabel);
299: panel.add(columnsChoice);
300: return panel;
301: }
302:
303: private void initColumns() {
304: String ssFields = reportDefinition.getMainSpreadsheetCategory();
305: if (ssFields == null
306: || ssFields.equals("assignmentSpreadsheet")) { //$NON-NLS-1$
307: columnsChoice.setVisible(false);
308: columnsLabel.setVisible(false);
309: return;
310: }
311: columnsChoice.setVisible(true);
312: columnsLabel.setVisible(true);
313: DefaultComboBoxModel model = new DefaultComboBoxModel(
314: Dictionary.getAll(ssFields));
315: columnsChoice.setModel(model);
316: columnsChoice.setSelectedItem(fieldArray);
317: }
318:
319: public void init(CoordinatesConverter coord) {
320: initializing = true;
321: this .coord = coord;
322: setLayout(layout);
323: reportLabel = new JLabel(Messages
324: .getString("ReportView.Report")); //$NON-NLS-1$
325: reportChoice = new JComboBox(ReportUtil.getReportDefinitions());
326: reportChoice.setSelectedIndex(0);
327: reportDefinition = (ReportDefinition) reportChoice
328: .getSelectedItem();
329: fieldArray = reportDefinition.getMainFieldArray();
330: reportChoice.addActionListener(new ActionListener() {
331:
332: public void actionPerformed(ActionEvent arg0) {
333: reportDefinition = (ReportDefinition) ((JComboBox) arg0
334: .getSource()).getSelectedItem();
335: fieldArray = reportDefinition.getMainFieldArray();
336: dirty = true;
337: showReport();
338: initColumns();
339: }
340: });
341:
342: columnsLabel = new JLabel(Messages
343: .getString("ReportView.Columns")); //$NON-NLS-1$
344: columnsChoice = new JComboBox();
345: initColumns();
346: columnsChoice.addActionListener(new ActionListener() {
347:
348: public void actionPerformed(ActionEvent arg0) {
349: fieldArray = (SpreadSheetFieldArray) ((JComboBox) arg0
350: .getSource()).getSelectedItem();
351: dirty = true;
352: showReport();
353: }
354: });
355: add(header(), BorderLayout.PAGE_START);
356: showReport();
357: initializing = false;
358: }
359:
360: public void graphicNodesCompositeEvent(
361: CompositeCacheEvent compositeEvent) {
362: if (initializing)
363: return;
364: dirty = true;
365: if (!isShowing())
366: return;
367: if (!isVisible()) { // set it as dirty and recalculate when shown because it's expensive to recalc report if not shown
368: return;
369: }
370: showReport();
371: }
372:
373: public UndoController getUndoController() {
374: return null;
375: }
376:
377: public void zoomIn() {
378: viewer.zoomIn();
379: }
380:
381: public void zoomOut() {
382: viewer.zoomOut();
383: }
384:
385: public boolean canZoomIn() {
386: return true;
387: }
388:
389: public boolean canZoomOut() {
390: return true;
391: }
392:
393: public int getScale() {
394: return -1;
395: }
396:
397: public SpreadSheet getSpreadSheet() {
398: return null;
399: }
400:
401: public boolean hasNormalMinWidth() {
402: return true;
403: }
404:
405: public String getViewName() {
406: return viewName;
407: }
408:
409: public boolean showsTasks() {
410: return false;
411: }
412:
413: public boolean showsResources() {
414: return false;
415: }
416:
417: /**
418: * Because it can be expensive to recalc a report, if the report is not visible, it is only recalced when made visible
419: */
420: public void onActivate(boolean activate) {
421: if (activate)
422: showReport();
423: }
424:
425: public boolean isPrintable() {
426: return false;
427: }
428:
429: public void restoreWorkspace(WorkspaceSetting w, int context) {
430: Workspace ws = (Workspace) w;
431: if (ws.reportName != null) {
432: ReportDefinition def = ReportUtil
433: .getFromName(ws.reportName);
434: if (def != null)
435: reportChoice.setSelectedItem(def);
436: }
437: if (ws.fieldArrayName != null) {
438: SpreadSheetFieldArray s = (SpreadSheetFieldArray) Dictionary
439: .get(reportDefinition.getMainSpreadsheetCategory(),
440: ws.fieldArrayName);
441: if (s != null)
442: columnsChoice.setSelectedItem(s);
443: }
444: }
445:
446: public WorkspaceSetting createWorkspace(int context) {
447: Workspace ws = new Workspace();
448: if (reportDefinition != null)
449: ws.reportName = reportDefinition.getName();
450: if (fieldArray != null)
451: ws.fieldArrayName = fieldArray.toString();
452: return ws;
453: }
454:
455: public static class Workspace implements WorkspaceSetting {
456: private static final long serialVersionUID = -7768176701769503845L;
457: //TODO Zoom not set - a bit of a pain to do
458: String fieldArrayName = null;
459: String reportName = null;
460:
461: public String getFieldArrayName() {
462: return fieldArrayName;
463: }
464:
465: public void setFieldArrayName(String fieldArrayName) {
466: this .fieldArrayName = fieldArrayName;
467: }
468:
469: public String getReportName() {
470: return reportName;
471: }
472:
473: public void setReportName(String reportName) {
474: this .reportName = reportName;
475: }
476: }
477:
478: public boolean canScrollToTask() {
479: // TODO Auto-generated method stub
480: return false;
481: }
482:
483: public void scrollToTask() {
484: // TODO Auto-generated method stub
485:
486: }
487:
488: public NodeModelCache getCache() {
489: return cache;
490: }
491:
492: }
|