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.model.cache;
051:
052: import java.awt.geom.AffineTransform;
053: import java.awt.geom.GeneralPath;
054: import java.awt.geom.Point2D;
055: import java.util.ArrayList;
056: import java.util.Iterator;
057: import java.util.List;
058:
059: import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;
060:
061: import com.projity.functor.IntervalConsumer;
062: import com.projity.graphic.configuration.GraphicConfiguration;
063: import com.projity.grouping.core.GroupNodeImpl;
064: import com.projity.grouping.core.LazyParent;
065: import com.projity.grouping.core.Node;
066: import com.projity.grouping.core.transform.HierarchicObject;
067: import com.projity.pm.assignment.Assignment;
068: import com.projity.pm.graphic.timescale.CoordinatesConverter;
069: import com.projity.pm.scheduling.Schedule;
070: import com.projity.pm.scheduling.ScheduleInterval;
071: import com.projity.pm.scheduling.ScheduleService;
072: import com.projity.pm.task.Task;
073: import com.projity.server.data.CommonDataObject;
074: import com.projity.server.data.DataObject;
075:
076: /**
077: *
078: */
079: public class GraphicNode implements HierarchicObject {
080: protected Node node;
081: protected int level;
082: protected int pertLevel;
083: protected boolean voidNode;
084: protected boolean composite;
085: protected boolean summary;
086: protected boolean collapsed;
087: protected boolean dirty;
088:
089: /**
090: * @param node
091: * @param level
092: */
093: public GraphicNode(Node node, int level) {
094: setNode(node);
095: this .level = level;
096: dirty = false;
097: pertLevel = -1;
098: setScheduleCaching(false);
099: }
100:
101: //Not real GraphicNode this is a hack for Depencencies. This is to modify
102: /*public GraphicNode(Node node) {
103: setNode(node);
104: level = -1;
105: ganttCell=null;
106: pertCell=null;
107: treeCell=null;
108: dirty=false;
109: pertLevel=-1;
110: }*/
111:
112: /*public ReferenceNodeModelCache getCache() {
113: return cache;
114: }*/
115: /**
116: * @return Returns the level.
117: */
118: public int getLevel() {
119: return level;
120: }
121:
122: /**
123: * @param level The level to set.
124: */
125: void setLevel(int level) {
126: this .level = level;
127: dirty = true;
128: }
129:
130: public int getPertLevel() {
131: return pertLevel;
132: }
133:
134: void setPertLevel(int pertLevel) {
135: this .pertLevel = pertLevel;
136: }
137:
138: /**
139: * @return Returns the node.
140: */
141: public Node getNode() {
142: return node;
143: }
144:
145: /**
146: * @param node The node to set.
147: */
148: public void setNode(Node node) {
149: this .node = node;
150: dirty = true;
151: }
152:
153: /**
154: * @return Returns the composite.
155: */
156: public boolean isComposite() {
157: return composite;
158: }
159:
160: /**
161: * @param composite The composite to set.
162: */
163: public void setComposite(boolean composite) {
164: this .composite = composite;
165: dirty = true;
166: }
167:
168: public boolean isSummary() {
169: return summary;
170: }
171:
172: public void setSummary(boolean summary) {
173: this .summary = summary;
174: dirty = true;
175: }
176:
177: public boolean isLazyParent() {
178: return node.getImpl() instanceof LazyParent;
179: }
180:
181: public boolean isValidLazyParent() {
182: if (node.getImpl() instanceof LazyParent)
183: return ((LazyParent) node.getImpl()).isValid();
184: return false;
185: }
186:
187: public boolean isFetched() {
188: if (node.getImpl() instanceof LazyParent)
189: return ((LazyParent) node.getImpl()).isDataFetched();
190: else
191: return true;
192: }
193:
194: public boolean fetch() {
195: if (node.getImpl() instanceof LazyParent)
196: return ((LazyParent) node.getImpl()).fetchData(node);
197: return true;
198: }
199:
200: /**
201: * @return Returns the collapsed.
202: */
203: public boolean isCollapsed() {
204: return collapsed;
205: }
206:
207: /**
208: * @param collapsed The collapsed to set.
209: */
210: public void setCollapsed(boolean collapsed) {
211: this .collapsed = collapsed;
212: dirty = true;
213: }
214:
215: public boolean isVoid() {
216: return voidNode;//getNode().isVoid();
217: }
218:
219: public void setVoid(boolean voidNode) {
220: this .voidNode = voidNode;
221: dirty = true;
222: }
223:
224: public boolean isAssignment() {
225: return getNode().getImpl() instanceof Assignment;
226: }
227:
228: public boolean isGroup() {
229: return getNode().getImpl() instanceof GroupNodeImpl;
230: }
231:
232: public int getSubprojectLevel() {
233: // if (getNode().getImpl() instanceof Task){
234: // Task task=(Task)getNode().getImpl();
235: // if (task.isInSubproject()) return 1;
236: // }
237:
238: // Node node=getNode();
239: // int level=0;
240: // while (node.isInSubproject()){
241: // node=(Node)node.getParent();
242: // level+=1;
243: // }
244: // return level;
245:
246: //if (getNode().isInSubproject()) return 1;
247: //return 0;
248:
249: return node.getSubprojectLevel();
250: }
251:
252: public boolean isLinkable() {
253: Object impl = getNode().getImpl();
254: if (impl instanceof Assignment)
255: return false;
256: if (impl instanceof Task && ((Task) impl).isExternal())
257: return false;
258: return true;
259: }
260:
261: public boolean isServer() {
262: Object impl = getNode().getImpl();
263: if (!(impl instanceof DataObject))
264: return false;
265: return !CommonDataObject.isLocal((DataObject) impl);
266: }
267:
268: public boolean isDirty() {
269: return dirty;
270: }
271:
272: public void setDirty(boolean dirty) {
273: this .dirty = dirty;
274: }
275:
276: public String toString() {
277: return node.toString();
278: }
279:
280: public static Object getImpl(Object obj) {
281: if (obj instanceof GraphicNode)
282: return ((GraphicNode) obj).getNode().getImpl();
283: else if (obj instanceof Node)
284: return ((Node) obj).getImpl();
285: else
286: return obj;
287: }
288:
289: public static boolean isVoid(Object obj) {
290: if (obj instanceof GraphicNode)
291: return ((GraphicNode) obj).isVoid();
292: else if (obj instanceof Node)
293: return ((Node) obj).isVoid();
294: else
295: return obj == null;
296: }
297:
298: protected boolean scheduleCaching;
299: protected ArrayList intervals = null;
300: protected long start = -1;
301: protected long end = -1;
302: protected int intervalCount = 1;
303:
304: //TODO add recurrent tasks support
305:
306: public long getStart() {
307: return (scheduleCaching || !isSchedule()) ? start
308: : ((Schedule) node.getImpl()).getStart();
309: }
310:
311: public long getEnd() {
312: return (scheduleCaching || !isSchedule()) ? end
313: : ((Schedule) node.getImpl()).getEnd();
314: }
315:
316: public int getIntervalCount() {
317: return intervalCount;
318: }
319:
320: public boolean isScheduleCaching() {
321: return scheduleCaching;
322: }
323:
324: public void setScheduleCaching(boolean scheduleCaching) {
325: this .scheduleCaching = scheduleCaching;
326: intervals = (scheduleCaching) ? new ArrayList() : null;
327: ContainsIntervalConsumer containsConsumer = null;//clean if it wasn't scheduleCaching before
328: }
329:
330: public void updateScheduleCache() {
331: if (scheduleCaching
332: || GraphicConfiguration.getInstance()
333: .getGanttBarMinWidth() > 0) {
334: Object impl = node.getImpl();
335: if (!isSchedule())
336: return;
337: intervalConsumer.initCache(this , intervals);
338: ScheduleService.getInstance().consumeIntervals(
339: (Schedule) impl, intervalConsumer);
340: intervalCount = intervalConsumer.size > 0 ? intervalConsumer.size
341: : 1;
342: }
343: }
344:
345: protected static CacheIntervalConsumer intervalConsumer = new CacheIntervalConsumer();
346:
347: protected static class CacheIntervalConsumer implements
348: IntervalConsumer {
349: protected List cache = null;
350: protected GraphicNode gnode = null;
351: int size;
352:
353: public void initCache(GraphicNode gnode, List cache) {
354: size = 0;
355: if (cache != null)
356: cache.clear();
357: this .cache = cache;
358: this .gnode = gnode;
359: }
360:
361: public void consumeInterval(ScheduleInterval interval) {
362: if (size++ == 0)
363: gnode.start = interval.getStart();
364: gnode.end = interval.getEnd();
365: if (cache != null)
366: cache.add(interval);
367: }
368: }
369:
370: public void consumeIntervals(IntervalConsumer consumer) {
371: if (scheduleCaching) {
372: for (Iterator i = intervals.iterator(); i.hasNext();) {
373: consumer.consumeInterval((ScheduleInterval) i.next());
374: }
375: } else {
376: Object impl = node.getImpl();
377: if (isSchedule())
378: ScheduleService.getInstance().consumeIntervals(
379: (Schedule) impl, consumer);
380: }
381: }
382:
383: //contains
384: private ContainsIntervalConsumer containsConsumer = null; //need when no schedule caching
385:
386: private static class ContainsIntervalConsumer implements
387: IntervalConsumer {
388: ScheduleInterval interval = null;
389: double t, deltaT1, deltaT2;
390: CoordinatesConverter coord;
391: GraphicNode node;
392:
393: public void init(double t, double deltaT1, double deltaT2,
394: CoordinatesConverter coord, GraphicNode node) {
395: interval = null;
396: this .t = t;
397: this .deltaT1 = deltaT1;
398: this .deltaT2 = deltaT2;
399: this .coord = coord;
400: this .node = node;
401: }
402:
403: public ScheduleInterval getInterval() {
404: return interval;
405: }
406:
407: public void consumeInterval(ScheduleInterval interval) {
408: if (coord != null)
409: interval = coord.adaptSmallBarTimeInterval(interval,
410: node, null);
411: if (t >= interval.getStart() - deltaT1
412: && t <= interval.getEnd() + deltaT2)
413: this .interval = interval;
414: }
415:
416: }
417:
418: public ScheduleInterval contains(double t, double deltaT1,
419: double deltaT2, CoordinatesConverter coord) {
420: if (scheduleCaching) {
421: ScheduleInterval interval;
422: for (Iterator i = intervals.iterator(); i.hasNext();) {
423: interval = (ScheduleInterval) i.next();
424: if (coord != null)
425: interval = coord.adaptSmallBarTimeInterval(
426: interval, this , null);
427: if (t >= interval.getStart() - deltaT1
428: && t <= interval.getEnd() + deltaT2)
429: return interval;
430: }
431: return null;
432: } else {
433: if (containsConsumer == null)
434: containsConsumer = new ContainsIntervalConsumer();
435: containsConsumer.init(t, deltaT1, deltaT2, coord, this );
436: Object impl = node.getImpl();
437: if (isSchedule())
438: ScheduleService.getInstance().consumeIntervals(
439: (Schedule) impl, containsConsumer);
440: return containsConsumer.getInterval();
441: }
442: }
443:
444: // public boolean contains(double t,CoordinatesConverter coord){
445: // return contains(t,0,0,coord)!=null;
446: // }
447:
448: public boolean isSchedule() {
449: return node.getImpl() instanceof Schedule;
450: }
451:
452: protected double ganttShapeOffset = 0,
453: ganttShapeHeight = GraphicConfiguration.getInstance()
454: .getGanttBarHeight();;
455:
456: public double getGanttShapeHeight() {
457: return ganttShapeHeight;
458: }
459:
460: public void setGanttShapeHeight(double ganttShapeHeight) {
461: this .ganttShapeHeight = ganttShapeHeight;
462: }
463:
464: public double getGanttShapeOffset() {
465: return ganttShapeOffset;
466: }
467:
468: public void setGanttShapeOffset(double ganttShapeOffset) {
469: this .ganttShapeOffset = ganttShapeOffset;
470: }
471:
472: protected int row; //tmp value for performance reasons
473:
474: public int getRow() {
475: return row;
476: }
477:
478: public void setRow(int row) {
479: this .row = row;
480: }
481:
482: protected GeneralPath pertShape = null;
483: protected GeneralPath xbsShape = null;
484: protected Point2D pertCenter = null;
485: protected Point2D xbsCenter = null;
486:
487: public GeneralPath getPertShape() {
488: return pertShape;
489: }
490:
491: public void setPertShape(GeneralPath pertShape, double centerX,
492: double centerY) {
493: this .pertShape = pertShape;
494: if (pertCenter == null)
495: pertCenter = new Point2D.Double();
496: pertCenter.setLocation(centerX, centerY);
497: }
498:
499: public GeneralPath getXbsShape() {
500: return xbsShape;
501: }
502:
503: public void setXbsShape(GeneralPath xbsShape, double centerX,
504: double centerY) {
505: this .xbsShape = xbsShape;
506: setXbsCenter(centerX, centerY);
507: }
508:
509: private void setXbsCenter(double centerX, double centerY) {
510: if (xbsCenter == null)
511: xbsCenter = new Point2D.Double();
512: xbsCenter.setLocation(centerX, centerY);
513: }
514:
515: public Point2D getPertCenter() {
516: return pertCenter;
517: }
518:
519: public Point2D getXbsCenter() {
520: return xbsCenter;
521: }
522:
523: public void translatePertShape(double dx, double dy) {
524: AffineTransform t = AffineTransform
525: .getTranslateInstance(dx, dy);
526: getPertShape().transform(t);
527: Point2D point = getPertCenter();
528: point.setLocation(point.getX() + dx, point.getY() + dy);
529: }
530:
531: public void translateXbsShape(double dx, double dy) {
532: AffineTransform t = AffineTransform
533: .getTranslateInstance(dx, dy);
534: getXbsShape().transform(t);
535: Point2D point = getXbsCenter();
536: point.setLocation(point.getX() + dx, point.getY() + dy);
537: }
538:
539: public long getCompleted() {
540: if (!(getNode().getImpl() instanceof Schedule))
541: return 0;
542: long completedT = ScheduleService.getInstance().getCompleted(
543: (Schedule) getNode().getImpl());
544: return (completedT == 0) ? getStart() : completedT;
545: }
546:
547: public boolean isStarted() {
548: if (!(getNode().getImpl() instanceof Schedule))
549: return false;
550: return ((Schedule) getNode().getImpl()).getPercentComplete() > 0.0D;
551: // return ScheduleService.getInstance().getCompleted((Schedule)getNode().getImpl())!=0;
552: }
553:
554: // protected boolean manualPert=false;
555: // protected boolean manualXbs=false;
556: //
557: //
558: // public boolean isManualPert() {
559: // return manualPert;
560: // }
561: // public void setManualPert(boolean manualPert) {
562: // this.manualPert = manualPert;
563: // }
564: // public boolean isManualXbs() {
565: // return manualXbs;
566: // }
567: // public void setManualXbs(boolean manualXbs) {
568: // this.manualXbs = manualXbs;
569: // }
570:
571: protected List tmpChildren = new ArrayList();
572:
573: public List getChildren() {
574: return tmpChildren;
575: }
576:
577: }
|