diff --git a/src/org/hwo/ui/netplan/BaseNetPlanObject.java b/src/org/hwo/ui/gantt/BaseGanttObject.java similarity index 53% rename from src/org/hwo/ui/netplan/BaseNetPlanObject.java rename to src/org/hwo/ui/gantt/BaseGanttObject.java index d0d6786..5f18cf7 100644 --- a/src/org/hwo/ui/netplan/BaseNetPlanObject.java +++ b/src/org/hwo/ui/gantt/BaseGanttObject.java @@ -1,11 +1,11 @@ -package org.hwo.ui.netplan; +package org.hwo.ui.gantt; import java.util.LinkedList; import java.util.List; import org.hwo.datetime.DateTime; -public class BaseNetPlanObject implements INetPlanObject { +public class BaseGanttObject implements IGanttObject { private DateTime startTime, endTime; @@ -13,12 +13,12 @@ public class BaseNetPlanObject implements INetPlanObject { private String label, detailedLabel; - List dependencies; - List resources; + List dependencies; + List resources; - public BaseNetPlanObject() { - dependencies = new LinkedList(); - resources = new LinkedList(); + public BaseGanttObject() { + dependencies = new LinkedList(); + resources = new LinkedList(); } @Override @@ -49,42 +49,49 @@ public class BaseNetPlanObject implements INetPlanObject { } @Override - public INetPlanObject[] getDependencies() { - return this.dependencies.toArray(new INetPlanObject[0]); + public IGanttObject[] getDependencies() { + return this.dependencies.toArray(new IGanttObject[0]); } @Override - public void addDependency(INetPlanObject depend) { + public void addDependency(IGanttObject depend) { if (!this.dependencies.contains(depend)) this.dependencies.add(depend); } @Override - public void removeDependency(INetPlanObject depend) { + public void removeDependency(IGanttObject depend) { this.dependencies.remove(depend); } @Override - public INetPlanResource[] getResources() { - return this.resources.toArray(new INetPlanResource[0]); + public IGanttResource[] getResources() { + return this.resources.toArray(new IGanttResource[0]); } @Override - public void addResource(INetPlanResource resource) { + public void addResource(IGanttResource resource) { if (!this.resources.contains(resource)) this.resources.add(resource); } @Override - public void removeResource(INetPlanResource resource) { + public void removeResource(IGanttResource resource) { this.resources.remove(resource); } + @Override + public void replaceResource(IGanttResource oldResource, IGanttResource newResource) { + addResource(newResource); + removeResource(oldResource); + } + @Override public String getDetailedLabel() { - // TODO Auto-generated method stub - return null; - }public void setDetailedLabel(String detailedLabel) { + return this.detailedLabel; + } + public void setDetailedLabel(String detailedLabel) { this.detailedLabel = detailedLabel; } + public String getShortLabel() { return label; } @@ -92,5 +99,12 @@ public class BaseNetPlanObject implements INetPlanObject { this.label = label; } + @Override + public void addNotify(JGantt gantt) { + } + @Override + public void removeNotify(JGantt gantt) { + } + } diff --git a/src/org/hwo/ui/gantt/BaseGanttResource.java b/src/org/hwo/ui/gantt/BaseGanttResource.java new file mode 100644 index 0000000..c1729d0 --- /dev/null +++ b/src/org/hwo/ui/gantt/BaseGanttResource.java @@ -0,0 +1,85 @@ +package org.hwo.ui.gantt; + +import org.hwo.datetime.DateTime; + +public class BaseGanttResource implements IGanttResource { + + private String shortLabel; + private String detailedLabel; + private int maxParallelUsage; + + private ResourceAvailability resourceAvailability; + + public BaseGanttResource(String shortLabel,String detailedLabel) { + this.shortLabel = shortLabel; + this.detailedLabel = detailedLabel; + this.maxParallelUsage = 1; + } + + + @Override + public String getLabel() { + return this.shortLabel; + } + + @Override + public String getDetailedLabel() { + return this.detailedLabel; + } + + + public void setResourceAvailability( + ResourceAvailability resourceAvailability) { + this.resourceAvailability = resourceAvailability; + } + + @Override + public ResourceAvailability getAvailability() { + return resourceAvailability; + } + + @Override + public ResourceAvailability getAvailability(DateTime fromDateTime) { + return resourceAvailability.findAvailableAfter(fromDateTime); + } + + @Override + public int getMaxParallelUsage() { + return this.maxParallelUsage; + } + + public void setMaxParallelUsage(int maxParallelUsage) { + this.maxParallelUsage = maxParallelUsage; + } + + + + public DateTime calculateUsageTime(DateTime begin,int seconds){ + ResourceAvailability ra = getAvailability(begin); + DateTime dt = new DateTime(begin); + + if (ra != null && dt.isBefore(ra.getStartTime())){ + dt = ra.getStartTime(); + } + + while (ra != null){ + int availSeconds = ra.getSeconds(dt); + + //System.err.println(String.format("RES: %s needs %d seconds from %s. Has %d seconds.", shortLabel, seconds, dt.toString(), availSeconds)); + + if (availSeconds >= seconds){ // Soll kann erfüllt werden... + DateTime endTime = new DateTime(dt); + endTime.addSeconds(seconds); + return endTime; + } + + seconds -= availSeconds; + + ra = ra.getNext(); + dt = ra.getStartTime(); + } + return null; + } + + +} diff --git a/src/org/hwo/ui/gantt/GanttException.java b/src/org/hwo/ui/gantt/GanttException.java new file mode 100644 index 0000000..55b87b9 --- /dev/null +++ b/src/org/hwo/ui/gantt/GanttException.java @@ -0,0 +1,5 @@ +package org.hwo.ui.gantt; + +public class GanttException extends Exception { + +} diff --git a/src/org/hwo/ui/gantt/GanttMouseEventListener.java b/src/org/hwo/ui/gantt/GanttMouseEventListener.java new file mode 100644 index 0000000..0d9b658 --- /dev/null +++ b/src/org/hwo/ui/gantt/GanttMouseEventListener.java @@ -0,0 +1,9 @@ +package org.hwo.ui.gantt; + +import org.hwo.datetime.DateTime; + +public interface GanttMouseEventListener { + + public void mouseClick(JGantt gantt,IGanttResource ganttResource,DateTime dateTime,IGanttObject ganttObject); + +} diff --git a/src/org/hwo/ui/gantt/GanttResolver.java b/src/org/hwo/ui/gantt/GanttResolver.java new file mode 100644 index 0000000..3027bb7 --- /dev/null +++ b/src/org/hwo/ui/gantt/GanttResolver.java @@ -0,0 +1,69 @@ +package org.hwo.ui.gantt; + +import org.hwo.datetime.DateTime; + +public class GanttResolver { + JGantt gantt; + + public GanttResolver(JGantt gantt) { + this.gantt = gantt; + + } + + /* Optimieren links: (Einsetzen) + * + * Schneidendes Objekt bei startTime finden, startTime korrigieren, wiederholen für abhängige in gleicher resource + * + * + */ + public void leftOptimize(IGanttObject object){ + + for (IGanttResource resource: object.getResources()){ + IGanttObject o = gantt.findObjectAt(resource, object.getStartTime()); + + if (o != null){ + DateTime dt = o.getEndTime(); + dt.addSeconds(1); + + System.err.println(String.format("Resolver: Move Start Time of %s from %s to %s after end of %s",object.toString(),object.getStartTime(),dt.toString(),o.toString())); + + object.setStartTime(dt); + + for (IGanttObject dobj: gantt.findDependedObjects(o, resource)){ + leftOptimize(dobj); + } + } + + } + } + + /* Optimieren rechts: (Verschieben) + * + * Objekte mit StartTime innerhalb finden, und nach rechts verschieben + * + * + */ + public void rightOptimize(IGanttObject object){ + + for (IGanttResource resource: object.getResources()){ + IGanttObject o = gantt.findObjectAt(resource, object.getStartTime()); + + if (o != null){ + DateTime dt = o.getEndTime(); + dt.addSeconds(1); + + System.err.println(String.format("Resolver: Move Start Time of %s from %s to %s after end of %s",object.toString(),object.getStartTime(),dt.toString(),o.toString())); + + object.setStartTime(dt); + + for (IGanttObject dobj: gantt.findDependedObjects(o, resource)){ + leftOptimize(dobj); + } + + } + + } + } + + +} diff --git a/src/org/hwo/ui/gantt/IGanttDrawable.java b/src/org/hwo/ui/gantt/IGanttDrawable.java new file mode 100644 index 0000000..66af478 --- /dev/null +++ b/src/org/hwo/ui/gantt/IGanttDrawable.java @@ -0,0 +1,10 @@ +package org.hwo.ui.gantt; + +import java.awt.Graphics2D; +import java.awt.Rectangle; + +public interface IGanttDrawable { + + void paint(Graphics2D g,Rectangle rect); + +} diff --git a/src/org/hwo/ui/netplan/INetPlanObject.java b/src/org/hwo/ui/gantt/IGanttObject.java similarity index 54% rename from src/org/hwo/ui/netplan/INetPlanObject.java rename to src/org/hwo/ui/gantt/IGanttObject.java index 71dfc3e..ab95f48 100644 --- a/src/org/hwo/ui/netplan/INetPlanObject.java +++ b/src/org/hwo/ui/gantt/IGanttObject.java @@ -1,8 +1,8 @@ -package org.hwo.ui.netplan; +package org.hwo.ui.gantt; import org.hwo.datetime.DateTime; -public interface INetPlanObject { +public interface IGanttObject { boolean canMove(); // Startzeitpunkt kann verändert werden boolean canStretch(); // Dauer kann verändert werden @@ -21,17 +21,21 @@ public interface INetPlanObject { String getDetailedLabel(); /* Abhängige Objekte */ - INetPlanObject[] getDependencies(); + IGanttObject[] getDependencies(); - void addDependency(INetPlanObject depend); - void removeDependency(INetPlanObject depend); + void addDependency(IGanttObject depend); + void removeDependency(IGanttObject depend); /* Notwendige Resourcen */ - INetPlanResource[] getResources(); - - void addResource(INetPlanResource resource); - void removeResource(INetPlanResource resource); + IGanttResource[] getResources(); + void addResource(IGanttResource resource); + void removeResource(IGanttResource resource); + void replaceResource(IGanttResource oldResource,IGanttResource newResource); + void addNotify(JGantt gantt); + void removeNotify(JGantt gantt); + + } diff --git a/src/org/hwo/ui/netplan/INetPlanResource.java b/src/org/hwo/ui/gantt/IGanttResource.java similarity index 77% rename from src/org/hwo/ui/netplan/INetPlanResource.java rename to src/org/hwo/ui/gantt/IGanttResource.java index ec6c8b5..5174401 100644 --- a/src/org/hwo/ui/netplan/INetPlanResource.java +++ b/src/org/hwo/ui/gantt/IGanttResource.java @@ -1,8 +1,8 @@ -package org.hwo.ui.netplan; +package org.hwo.ui.gantt; import org.hwo.datetime.DateTime; -public interface INetPlanResource { +public interface IGanttResource { String getLabel(); String getDetailedLabel(); diff --git a/src/org/hwo/ui/gantt/JGantt.java b/src/org/hwo/ui/gantt/JGantt.java new file mode 100644 index 0000000..fe582ef --- /dev/null +++ b/src/org/hwo/ui/gantt/JGantt.java @@ -0,0 +1,531 @@ +package org.hwo.ui.gantt; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.Scrollable; +import javax.swing.SwingConstants; + +import org.hwo.datetime.Date; +import org.hwo.datetime.DateTime; +import org.hwo.datetime.TimeOfDay; + +public class JGantt extends JComponent { + + GanttResolver resolver; + + List ganttObjects; + List ganttResources; + + List ganttDrawables; + + Date firstDate; + int days; + + int zoom; + + boolean timeVisible; + + + boolean relevantChange; + + JViewport topPane, + leftPane; + + + IGanttObject selectedObject; + + + List ganttMouseEventListener; + + + public JGantt() { + ganttMouseEventListener = new ArrayList(); + + resolver = new GanttResolver(this); + + ganttObjects = new ArrayList(); + ganttResources = new ArrayList(); + ganttDrawables = new ArrayList(); + + firstDate = new Date(); + days = 31; + zoom = 1; + + timeVisible = false; + + relevantChange = true; + + setDoubleBuffered(true); + + topPane = new JViewport(); + topPane.add(new TopPane()); + leftPane = new JViewport(); + leftPane.add(new Leftpane()); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + switch (e.getButton()){ + case MouseEvent.BUTTON1: + if (e.getClickCount()==1){ + DateTime dt = getDateTimeAt(e.getPoint().x); + IGanttResource r = getResourceAt(e.getPoint().y); + IGanttObject o = null; + if (r != null) + o = getObjectAt(r, dt); + + fireGanttMouseClick(JGantt.this, r, dt, o); + } + break; + } + } + }); + + addGanttMouseListener(new GanttMouseEventListener() { + + @Override + public void mouseClick(JGantt gantt, IGanttResource ganttResource, + DateTime dateTime, IGanttObject ganttObject) { + setSelectedObject(ganttObject); + } + }); + + } + + public void addGanttMouseListener(GanttMouseEventListener listener){ + ganttMouseEventListener.add(listener); + } + public void removeGanttMouseListener(GanttMouseEventListener listener){ + ganttMouseEventListener.add(listener); + } + + public void fireGanttMouseClick(JGantt gantt,IGanttResource ganttResource,DateTime dateTime,IGanttObject ganttObject){ + for (GanttMouseEventListener listener: ganttMouseEventListener){ + listener.mouseClick(this, ganttResource, dateTime, ganttObject); + } + }; + + + public int getZoom() { + return zoom; + } + public void setZoom(int zoom) { + this.zoom = zoom; + relevantChange = true; + repaint(); + } + + public void addGanttObject(IGanttObject object){ + if (!this.ganttObjects.contains(object)){ + this.ganttObjects.add(object); + + if (IGanttDrawable.class.isInstance(object)){ + ganttDrawables.add((IGanttDrawable)object); + } + + resolver.leftOptimize(object); + object.addNotify(this); + } + + for (IGanttResource res: object.getResources()){ + addGanttResource(res); + } + + repaint(); + } + public void removeGanttObject(IGanttObject object){ + if (this.ganttObjects.contains(object)){ + this.ganttObjects.remove(object); + + if (this.ganttDrawables.contains(object)){ + this.ganttDrawables.remove(object); + } + + object.removeNotify(this); + } + repaint(); + } + public IGanttObject[] getGanttObjects(){ + return this.ganttObjects.toArray(new IGanttObject[0]); + } + + public void addGanttResource(IGanttResource resource){ + if (!this.ganttResources.contains(resource)) + this.ganttResources.add(resource); + } + public void removeGanttResource(IGanttResource resource){ + this.ganttResources.remove(resource); + } + public IGanttResource[] getGanttResources(){ + return this.ganttResources.toArray(new IGanttResource[0]); + } + + public Date getFirstDate() { + return new Date(firstDate); + } + public void setFirstDate(Date firstDate) { + this.firstDate = new Date(firstDate); + } + + public int getDays() { + return days; + } + public void setDays(int days) { + this.days = days; + } + + public void setTimeVisible(boolean timeVisible) { + this.timeVisible = timeVisible; + } + public boolean isTimeVisible(){ + return this.timeVisible; + } + + public IGanttObject getSelectedObject() { + return selectedObject; + } + public void setSelectedObject(IGanttObject selectedObject) { + this.selectedObject = selectedObject; + repaint(); + } + + public IGanttObject findObjectAt(IGanttResource resource,DateTime dateTime){ + System.err.println(String.format("JGantt: Find Object on Resource %s at %s",resource.toString(),dateTime.toString())); + + for (IGanttObject o: ganttObjects){ + if (o.getStartTime().isBefore(dateTime) && o.getEndTime().isAfter(dateTime) && Arrays.asList(o.getResources()).contains(resource)){ + return o; + } + } + return null; + } + + public IGanttResource getResourceAt(int y){ + if (y > minHeight) + return null; + + IGanttResource res = ganttResources.get((y-6) / lineHeight); + return res; + } + + public DateTime getDateTimeAt(int x){ + Date date = new Date(firstDate); + date.addDays(x / dayColumnWidth); + TimeOfDay time = new TimeOfDay( TimeOfDay.SECONDSPERDAY * (x % dayColumnWidth) / dayColumnWidth ); + return new DateTime(date, time); + } + + private IGanttObject getObjectAt(IGanttResource resource,DateTime dateTime){ + IGanttObject o = findObjectAt(resource,dateTime); + + return o; + } + + private IGanttObject[] findParallelObjects(IGanttObject object,IGanttResource resource){ + LinkedList rl = new LinkedList(); + +/* for (IGanttObject o:ganttObjects) + if (Arrays.asList(o.getResources()).contains(o) + */ + return rl.toArray(new IGanttObject[0]); + } + + public IGanttObject[] findDependedObjects(IGanttObject object){ + LinkedList rl = new LinkedList(); + + for (IGanttObject o:ganttObjects) + if (Arrays.asList(o.getDependencies()).contains(object)) + rl.add(o); + + return rl.toArray(new IGanttObject[0]); + } + + public IGanttObject[] findDependedObjects(IGanttObject object,IGanttResource resource){ + LinkedList rl = new LinkedList(); + + for (IGanttObject o:ganttObjects) + if (Arrays.asList(o.getDependencies()).contains(object) && Arrays.asList(o.getResources()).contains(resource)) + rl.add(o); + + return rl.toArray(new IGanttObject[0]); + } + + /********* + * Layout variables... + */ + + int resourceLines; + int lineHeight, + headerLineHeight; + int resourceBaseHeight; + + int leftColumnWidth; + + int dayColumnWidth; + + int minHeight; + int minWidth; + + void paintObject(Graphics2D g,Rectangle rect,IGanttObject object){ + + if (ganttDrawables.contains(object)){ + ((IGanttDrawable)object).paint(g, rect); + } else { + if (selectedObject == object) + g.setColor(Color.RED); + else + g.setColor(new Color(255,192,192)); + + g.fillRoundRect(rect.x,rect.y,rect.width,rect.height, 8, 8); + g.drawRoundRect(rect.x,rect.y,rect.width,rect.height, 8, 8); + + if (selectedObject == object) + g.setColor(Color.WHITE); + else + g.setColor(Color.BLACK); + + g.drawString(object.getShortLabel(), rect.x + 4, rect.y + lineHeight - 8); + } + } + + + @Override + public void paint(Graphics _g) { + Graphics2D g = (Graphics2D)_g; + + int n; + + updateSizes(); + + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + + g.setColor(Color.BLACK); +// g.drawLine(leftColumnWidth, 0, leftColumnWidth, getHeight()); + + Date lastDate = getFirstDate(); + lastDate.addDays(days-1); + + + for (n = 0; n < days; n++){ + int l = ((n) * dayColumnWidth); + + g.drawLine(((n+1) * dayColumnWidth), 0, ((n+1) * dayColumnWidth), minHeight); + } + + + n = 0; + for (IGanttResource resource: this.ganttResources){ + n += resource.getMaxParallelUsage(); + + g.setColor(Color.LIGHT_GRAY); + + g.drawLine(0, 4 + (n * lineHeight), minWidth, 4 + (n * lineHeight)); + } + + for (IGanttObject object: ganttObjects){ + if (object.getEndTime().getDate().isBefore(firstDate) || object.getStartTime().getDate().isAfter(lastDate)) + continue; + + int pos = 2 + (object.getStartTime().getDate().daysAfter(firstDate) * dayColumnWidth); + int width = (object.getEndTime().getDate().daysAfter(object.getStartTime().getDate()) * dayColumnWidth) + dayColumnWidth - 4; + int posOffset = dayColumnWidth * object.getStartTime().getTime().getSecondsOfTheDay() / TimeOfDay.SECONDSPERDAY; + + pos += posOffset; + width -= posOffset + dayColumnWidth * (TimeOfDay.SECONDSPERDAY - object.getEndTime().getTime().getSecondsOfTheDay()) / TimeOfDay.SECONDSPERDAY; + + for (IGanttResource res: object.getResources()){ + int vpos = 6 + (ganttResources.indexOf(res) * lineHeight); + + Rectangle rect = new Rectangle(pos, vpos, width, lineHeight - 4); + paintObject(g, rect, object); + + } + } + + + } + + + private void updateSizes(){ + if (!relevantChange) + return; + + Graphics2D g = (Graphics2D)getGraphics(); + FontMetrics fm = getFontMetrics(getFont()); + + //lineHeight = (int)(getFont().getSize2D()*72) + 4; + lineHeight = getFont().getSize() + 8; + headerLineHeight = getFont().getSize() + 2; + + resourceBaseHeight = headerLineHeight * 4; + + if (isTimeVisible()) + dayColumnWidth = 96; + else + dayColumnWidth = ((int)fm.getStringBounds("WWW", g).getWidth()) + 10; + + dayColumnWidth *= zoom; + + resourceLines = 0; + leftColumnWidth = 0; + for (IGanttResource resource: this.ganttResources){ + int lw = (int)fm.getStringBounds(resource.getLabel(), g).getWidth(); + + if (lw > leftColumnWidth) + leftColumnWidth = lw; + + resourceLines += resource.getMaxParallelUsage(); + } + + leftColumnWidth += 15; + + + minHeight = 4 + (lineHeight * resourceLines); + minWidth = ( dayColumnWidth * days ); + + setPreferredSize(new Dimension(minWidth, minHeight)); + + leftPane.setSize(new Dimension(leftColumnWidth,minHeight)); + topPane.setSize(new Dimension(minWidth, resourceBaseHeight)); + + relevantChange = false; + } + + + + + public class TopPane extends JComponent { + + @Override + public Dimension getPreferredSize() { + return new Dimension(minWidth,resourceBaseHeight); + } + + @Override + public void paint(Graphics _g) { + Graphics2D g = (Graphics2D)_g; + + int n; + int ayear = 0; + int aweek = 0; + + updateSizes(); + + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + + g.setColor(Color.BLACK); +// g.drawLine(leftColumnWidth, 0, leftColumnWidth, getHeight()); + + g.drawLine(0, resourceBaseHeight, getWidth(), resourceBaseHeight); + g.drawLine(0, headerLineHeight, minWidth, headerLineHeight); + g.drawLine(0, 2 * headerLineHeight, minWidth, 2 * headerLineHeight); + + Date date = getFirstDate(); + + for (n = 0; n < days; n++){ + int l = ((n) * dayColumnWidth); + + g.drawLine(((n+1) * dayColumnWidth), resourceBaseHeight - (2 * headerLineHeight), ((n+1) * dayColumnWidth), resourceBaseHeight * 4); + + g.drawString(String.format("%02d.%02d", date.getDay(),date.getMonth()), l + 2, resourceBaseHeight - headerLineHeight - 2); + g.drawString(String.format("%s", date.weekdays[date.getWeekDay()]), l + 2, resourceBaseHeight - 2); + + if (ayear != date.getYear()){ + g.drawString(String.format("%02d", date.getYear()), l + 2, resourceBaseHeight - (3 * headerLineHeight) - 2); + if (ayear != 0){ + g.drawLine(((n) * dayColumnWidth), resourceBaseHeight - (4 * headerLineHeight), ((n) * dayColumnWidth), resourceBaseHeight - (3 * headerLineHeight)); + } + ayear = date.getYear(); + } + + int w = date.getWeek(); + + if (aweek != w){ + g.drawString(String.format("%02d", w), l + 2, resourceBaseHeight - (2 * headerLineHeight) - 2); + if (aweek != 0){ + g.drawLine(((n) * dayColumnWidth), resourceBaseHeight - (3 * headerLineHeight), ((n) * dayColumnWidth), resourceBaseHeight - (2 * headerLineHeight)); + } + aweek = w; + } + + date.addDays(1); + } + } + } + + public class Leftpane extends JComponent { + + public Leftpane() { + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(leftColumnWidth,minHeight); + } + + @Override + public void paint(Graphics _g) { + Graphics2D g = (Graphics2D)_g; + + int n; + + updateSizes(); + + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + + g.setColor(Color.BLACK); + g.drawLine(leftColumnWidth - 1, 0, leftColumnWidth - 1, getHeight()); + +// g.drawLine(0, 0, getWidth(), 0); + + n = 0; + for (IGanttResource resource: ganttResources){ + n += resource.getMaxParallelUsage(); + + g.setColor(Color.BLACK); + g.drawString(resource.getLabel(), 2, 1 + (n * lineHeight)); + g.setColor(Color.LIGHT_GRAY); + + g.drawLine(0, 4 + (n * lineHeight), getWidth(), 4 + (n * lineHeight)); + } + } + + } + + @Override + public void addNotify() { + super.addNotify(); + + if (JViewport.class.isInstance(getParent()) && JScrollPane.class.isInstance(getParent().getParent())) + { + JScrollPane sp = (JScrollPane)getParent().getParent(); + sp.setColumnHeader(topPane); + sp.setRowHeader(leftPane); + } + + + } + @Override + public void removeNotify() { + super.removeNotify(); + } + +} diff --git a/src/org/hwo/ui/netplan/JNetPlanTestDialog.java b/src/org/hwo/ui/gantt/JGanttTestDialog.java similarity index 67% rename from src/org/hwo/ui/netplan/JNetPlanTestDialog.java rename to src/org/hwo/ui/gantt/JGanttTestDialog.java index 5dacc4a..a0618a9 100644 --- a/src/org/hwo/ui/netplan/JNetPlanTestDialog.java +++ b/src/org/hwo/ui/gantt/JGanttTestDialog.java @@ -1,4 +1,4 @@ -package org.hwo.ui.netplan; +package org.hwo.ui.gantt; import java.awt.BorderLayout; import java.awt.FlowLayout; @@ -26,17 +26,17 @@ import org.hwo.datetime.TimeOfDay; import java.awt.Color; import java.awt.Font; -public class JNetPlanTestDialog extends JDialog { +public class JGanttTestDialog extends JDialog { private final JPanel contentPanel = new JPanel(); - private JNetPlan netPlan; + private JGantt netPlan; /** * Create the dialog. */ - public JNetPlanTestDialog() { + public JGanttTestDialog() { setModal(true); - setTitle("JNetPlan Test Dialog"); + setTitle("JGantt Test Dialog"); setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setBounds(100, 100, 975, 481); @@ -59,8 +59,8 @@ public class JNetPlanTestDialog extends JDialog { gbc_scrollPane.gridy = 0; contentPanel.add(scrollPane, gbc_scrollPane); { - netPlan = new JNetPlan(); - netPlan.setDays(45); + netPlan = new JGantt(); + netPlan.setDays(230); netPlan.setFont(new Font("DejaVu Sans", Font.PLAIN, 16)); netPlan.setBackground(Color.WHITE); scrollPane.setViewportView(netPlan); @@ -94,8 +94,8 @@ public class JNetPlanTestDialog extends JDialog { private void initialize(){ for (int i=0;i<10;i++){ - BaseNetPlanResource res = new BaseNetPlanResource(String.format("Resource %d",i), "-"); - netPlan.addNetPlanResource(res); + BaseGanttResource res = new BaseGanttResource(String.format("Resource %d",i), "-"); + netPlan.addGanttResource(res); } Date d = new Date(); @@ -105,17 +105,38 @@ public class JNetPlanTestDialog extends JDialog { Date d2 = new Date(d); d2.addDays(4); - BaseNetPlanObject o = new BaseNetPlanObject(); + BaseGanttObject o = new BaseGanttObject(); o.setStartTime(new DateTime(d, new TimeOfDay())); - o.setEndTime(new DateTime(d2, TimeOfDay.beforeMidnight())); - + o.setEndTime(new DateTime(d2, TimeOfDay.beforeMidnight())); o.setShortLabel("Eine Aufgabe"); - o.addResource(netPlan.getNetPlanResources()[0]); - o.addResource(netPlan.getNetPlanResources()[3]); - o.addResource(netPlan.getNetPlanResources()[7]); - - netPlan.addNetPlanObject(o); + o.addResource(netPlan.getGanttResources()[0]); + o.addResource(netPlan.getGanttResources()[3]); + o.addResource(netPlan.getGanttResources()[7]); + netPlan.addGanttObject(o); + + d.addDays(2); + d2.addDays(6); + o = new BaseGanttObject(); + o.setStartTime(new DateTime(d, new TimeOfDay())); + o.setEndTime(new DateTime(d2, TimeOfDay.beforeMidnight())); + o.setShortLabel("Eine Aufgabe"); + o.addResource(netPlan.getGanttResources()[1]); + o.addResource(netPlan.getGanttResources()[2]); + netPlan.addGanttObject(o); + + d.addDays(3); + d2.addDays(-2); + + o = new BaseGanttObject(); + o.setStartTime(new DateTime(d, new TimeOfDay())); + o.setEndTime(new DateTime(d2, TimeOfDay.beforeMidnight())); + o.setShortLabel("Eine Aufgabe"); + o.addResource(netPlan.getGanttResources()[0]); + o.addResource(netPlan.getGanttResources()[7]); + netPlan.addGanttObject(o); + + //netPlan.setSelectedObject(o); } diff --git a/src/org/hwo/ui/netplan/ResourceAvailability.java b/src/org/hwo/ui/gantt/ResourceAvailability.java similarity index 86% rename from src/org/hwo/ui/netplan/ResourceAvailability.java rename to src/org/hwo/ui/gantt/ResourceAvailability.java index 0328ead..6143821 100644 --- a/src/org/hwo/ui/netplan/ResourceAvailability.java +++ b/src/org/hwo/ui/gantt/ResourceAvailability.java @@ -1,4 +1,4 @@ -package org.hwo.ui.netplan; +package org.hwo.ui.gantt; import org.hwo.datetime.Date; import org.hwo.datetime.DateTime; @@ -142,6 +142,13 @@ public class ResourceAvailability { return null; } + public int getSeconds(){ + return startTime.secondsBefore(endTime); + } + + public int getSeconds(DateTime from){ + return from.secondsBefore(endTime); + } @Override public String toString() { @@ -149,7 +156,7 @@ public class ResourceAvailability { ResourceAvailability ra = this; while (ra != null){ - sb.append(String.format("%s %s - %s %s\n",Date.weekdays[ra.getStartTime().getDate().getWeekDay()],ra.getStartTime().toString(),Date.weekdays[ra.getEndTime().getDate().getWeekDay()],ra.getEndTime().toString())); + sb.append(String.format("%s %s - %s %s (%d seconds)\n",Date.weekdays[ra.getStartTime().getDate().getWeekDay()],ra.getStartTime().toString(),Date.weekdays[ra.getEndTime().getDate().getWeekDay()],ra.getEndTime().toString(),ra.getSeconds())); ra = ra.getNext(); } @@ -161,19 +168,27 @@ public class ResourceAvailability { return generateWeekly(from, days, available,new TimeOfDay(),TimeOfDay.beforeMidnight()); } public static ResourceAvailability generateWeekly(Date from,int days,boolean[] available,TimeOfDay timeStart,TimeOfDay timeEnd){ + Date to; + from.addDays(-1); ResourceAvailability head = new ResourceAvailability(new DateTime(from, new TimeOfDay())); head.setEndTime(new DateTime(from, TimeOfDay.beforeMidnight())); - - for (int i=0;i netPlanObjects; - List netPlanResources; - - Date firstDate; - int days; - - boolean timeVisible; - - - boolean relevantChange; - - JViewport topPane, - leftPane; - - - - public JNetPlan() { - netPlanObjects = new ArrayList(); - netPlanResources = new ArrayList(); - - firstDate = new Date(); - days = 31; - - timeVisible = false; - - relevantChange = true; - - setDoubleBuffered(true); - - topPane = new JViewport(); - topPane.add(new TopPane()); - leftPane = new JViewport(); - leftPane.add(new Leftpane()); - } - - public void addNetPlanObject(INetPlanObject object){ - if (!this.netPlanObjects.contains(object)) - this.netPlanObjects.add(object); - - for (INetPlanResource res: object.getResources()){ - addNetPlanResource(res); - } - } - public void removeNetPlanObject(INetPlanObject object){ - this.netPlanObjects.remove(object); - } - public INetPlanObject[] getNetPlanObjects(){ - return this.netPlanObjects.toArray(new INetPlanObject[0]); - } - - public void addNetPlanResource(INetPlanResource resource){ - if (!this.netPlanResources.contains(resource)) - this.netPlanResources.add(resource); - } - public void removeNetPlanResource(INetPlanResource resource){ - this.netPlanResources.remove(resource); - } - public INetPlanResource[] getNetPlanResources(){ - return this.netPlanResources.toArray(new INetPlanResource[0]); - } - - public Date getFirstDate() { - return new Date(firstDate); - } - public void setFirstDate(Date firstDate) { - this.firstDate = new Date(firstDate); - } - - public int getDays() { - return days; - } - public void setDays(int days) { - this.days = days; - } - - public void setTimeVisible(boolean timeVisible) { - this.timeVisible = timeVisible; - } - public boolean isTimeVisible(){ - return this.timeVisible; - } - - /********* - * Layout variables... - */ - - int resourceLines; - int lineHeight; - int resourceBaseHeight; - - int leftColumnWidth; - - int dayColumnWidth; - - int minHeight; - int minWidth; - - @Override - public void paint(Graphics _g) { - Graphics2D g = (Graphics2D)_g; - - int n; - - updateSizes(); - - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - - g.setColor(Color.BLACK); -// g.drawLine(leftColumnWidth, 0, leftColumnWidth, getHeight()); - - Date date = getFirstDate(); - - for (n = 0; n < days; n++){ - int l = ((n) * dayColumnWidth); - - g.drawLine(((n+1) * dayColumnWidth), 0, ((n+1) * dayColumnWidth), minHeight); - } - - - n = 0; - for (INetPlanResource resource: this.netPlanResources){ - n += resource.getMaxParallelUsage(); - - g.setColor(Color.LIGHT_GRAY); - - g.drawLine(0, 4 + (n * lineHeight), minWidth, 4 + (n * lineHeight)); - } - - for (INetPlanObject object: netPlanObjects){ - int pos = 2 + (object.getStartTime().getDate().daysAfter(firstDate) * dayColumnWidth); - int width = (object.getEndTime().getDate().daysAfter(object.getStartTime().getDate()) * dayColumnWidth) + dayColumnWidth - 4; - - for (INetPlanResource res: object.getResources()){ - int vpos = 6 + (netPlanResources.indexOf(res) * lineHeight); - g.setColor(Color.RED); - g.fillRoundRect(pos, vpos, width, lineHeight - 4, 8, 8); - g.drawRoundRect(pos, vpos, width, lineHeight - 4, 8, 8); - g.setColor(Color.WHITE); - g.drawString(object.getShortLabel(), pos + 4, vpos + lineHeight - 8); - - //System.err.println(String.format("[%d/%d] [%d/%d]",pos,vpos,width,lineHeight - 4)); - } - } - - - } - - - private void updateSizes(){ - if (!relevantChange) - return; - - Graphics2D g = (Graphics2D)getGraphics(); - FontMetrics fm = getFontMetrics(getFont()); - - //lineHeight = (int)(getFont().getSize2D()*72) + 4; - lineHeight = getFont().getSize() + 8; - - resourceBaseHeight = lineHeight * 3; - - if (isTimeVisible()) - dayColumnWidth = 96; - else - dayColumnWidth = ((int)fm.getStringBounds("WWW", g).getWidth()) + 10; - - resourceLines = 0; - leftColumnWidth = 0; - for (INetPlanResource resource: this.netPlanResources){ - int lw = (int)fm.getStringBounds(resource.getLabel(), g).getWidth(); - - if (lw > leftColumnWidth) - leftColumnWidth = lw; - - resourceLines += resource.getMaxParallelUsage(); - } - - leftColumnWidth += 5; - - - minHeight = 4 + (lineHeight * resourceLines); - minWidth = ( dayColumnWidth * days ); - - setPreferredSize(new Dimension(minWidth, minHeight)); - - leftPane.setSize(new Dimension(leftColumnWidth,minHeight)); - topPane.setSize(new Dimension(minWidth, 4 * lineHeight)); - - relevantChange = false; - } - - - - - public class TopPane extends JComponent { - - @Override - public Dimension getPreferredSize() { - return new Dimension(minWidth,4 * lineHeight); - } - - @Override - public void paint(Graphics _g) { - Graphics2D g = (Graphics2D)_g; - - int n; - - updateSizes(); - - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - - g.setColor(Color.BLACK); -// g.drawLine(leftColumnWidth, 0, leftColumnWidth, getHeight()); - - g.drawLine(0, resourceBaseHeight, getWidth(), resourceBaseHeight); - - Date date = getFirstDate(); - - for (n = 0; n < days; n++){ - int l = ((n) * dayColumnWidth); - - g.drawLine(((n+1) * dayColumnWidth), resourceBaseHeight - (2 * lineHeight), ((n+1) * dayColumnWidth), minHeight); - - g.drawString(String.format("%d", date.getDay()), l + 2, resourceBaseHeight - lineHeight - 2); - g.drawString(String.format("%s", date.weekdays[date.getWeekDay()]), l + 2, resourceBaseHeight - 2); - - date.addDays(1); - } - } - } - - public class Leftpane extends JComponent { - - public Leftpane() { - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(leftColumnWidth,minHeight); - } - - @Override - public void paint(Graphics _g) { - Graphics2D g = (Graphics2D)_g; - - int n; - - updateSizes(); - - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - - g.setColor(Color.BLACK); -// g.drawLine(leftColumnWidth, 0, leftColumnWidth, getHeight()); - -// g.drawLine(0, 0, getWidth(), 0); - - n = 0; - for (INetPlanResource resource: netPlanResources){ - n += resource.getMaxParallelUsage(); - - g.setColor(Color.BLACK); - g.drawString(resource.getLabel(), 2, 1 + (n * lineHeight)); - g.setColor(Color.LIGHT_GRAY); - - g.drawLine(0, 4 + (n * lineHeight), getWidth(), 4 + (n * lineHeight)); - } - } - - } - - /* - @Override - public Dimension getPreferredScrollableViewportSize() { - return getPreferredSize(); - } - - @Override - public int getScrollableBlockIncrement(Rectangle visibleRect, - int orientation, int direction) { - if (orientation == SwingConstants.HORIZONTAL) - return visibleRect.width / 2; - else - return visibleRect.height / 2; - } - - @Override - public boolean getScrollableTracksViewportHeight() { - return false; - } - - @Override - public boolean getScrollableTracksViewportWidth() { - return false; - } - - @Override - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, int direction) { - if (orientation == SwingConstants.HORIZONTAL) - return 10; - else - return lineHeight; - } - */ - @Override - public void addNotify() { - super.addNotify(); - - if (JViewport.class.isInstance(getParent()) && JScrollPane.class.isInstance(getParent().getParent())) - { - JScrollPane sp = (JScrollPane)getParent().getParent(); - sp.setColumnHeader(topPane); - sp.setRowHeader(leftPane); - } - - - } - @Override - public void removeNotify() { - super.removeNotify(); - } - -} diff --git a/src/org/hwo/ui/netplan/NetPlanException.java b/src/org/hwo/ui/netplan/NetPlanException.java deleted file mode 100644 index 541ac0e..0000000 --- a/src/org/hwo/ui/netplan/NetPlanException.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.hwo.ui.netplan; - -public class NetPlanException extends Exception { - -}