diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java index 0b9751306..1c1ec6a66 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/GanttDiagramGraph.java @@ -33,10 +33,14 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.jgrapht.DirectedGraph; import org.jgrapht.graph.SimpleDirectedGraph; import org.zkoss.ganttz.data.constraint.Constraint; import org.zkoss.ganttz.data.criticalpath.ICriticalPathCalculable; +import org.zkoss.ganttz.util.PreAndPostNotReentrantActionsWrapper; +import org.zkoss.ganttz.util.PreAndPostNotReentrantActionsWrapper.IAction; /** * This class contains a graph with the {@link Task tasks} as vertexes and the @@ -46,6 +50,12 @@ import org.zkoss.ganttz.data.criticalpath.ICriticalPathCalculable; */ public class GanttDiagramGraph implements ICriticalPathCalculable { + private static final Log LOG = LogFactory.getLog(GanttDiagramGraph.class); + + public interface IGraphChangeListener { + public void execute(); + } + private final DirectedGraph graph = new SimpleDirectedGraph( Dependency.class); @@ -61,6 +71,67 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { private final boolean dependenciesConstraintsHavePriority; + private final PreAndPostNotReentrantActionsWrapper preAndPostActions = new PreAndPostNotReentrantActionsWrapper() { + + @Override + protected void postAction() { + executeGraphChangeListeners(new ArrayList( + postGraphChangeListeners)); + } + + @Override + protected void preAction() { + executeGraphChangeListeners(new ArrayList( + preGraphChangeListeners)); + } + + private void executeGraphChangeListeners(List graphChangeListeners) { + for (IGraphChangeListener each : graphChangeListeners) { + try { + each.execute(); + } catch (Exception e) { + LOG.error("error executing execution listener", e); + } + } + } + }; + + private List preGraphChangeListeners = new ArrayList(); + + private List postGraphChangeListeners = new ArrayList(); + + public void addPreGraphChangeListener(IGraphChangeListener preGraphChangeListener) { + preGraphChangeListeners.add(preGraphChangeListener); + } + + public void removePreGraphChangeListener(IGraphChangeListener preGraphChangeListener) { + preGraphChangeListeners.remove(preGraphChangeListener); + } + + public void addPostGraphChangeListener(IGraphChangeListener postGraphChangeListener) { + postGraphChangeListeners.add(postGraphChangeListener); + } + + public void removePostGraphChangeListener(IGraphChangeListener postGraphChangeListener) { + postGraphChangeListeners.remove(postGraphChangeListener); + } + + private PropertyChangeListener decorateWithPreAndPostActions( + final PropertyChangeListener listener) { + return new PropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent evt) { + preAndPostActions.doAction(new IAction() { + @Override + public void doAction() { + listener.propertyChange(evt); + } + }); + } + }; + } + public GanttDiagramGraph(List> globalStartConstraints, List> globalEndConstraints, boolean dependenciesConstraintsHavePriority) { @@ -97,13 +168,13 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { continue; } subtask - .addFundamentalPropertiesChangeListener(new PropertyChangeListener() { + .addFundamentalPropertiesChangeListener(decorateWithPreAndPostActions(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { enforce(); } - }); + })); } } @@ -126,14 +197,14 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } this.task = task; this.task - .addFundamentalPropertiesChangeListener(new PropertyChangeListener() { + .addFundamentalPropertiesChangeListener(decorateWithPreAndPostActions(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { DependencyRulesEnforcer.this.enforce(); updateOutgoing(DependencyRulesEnforcer.this.task); } - }); + })); } void enforce() { @@ -185,14 +256,20 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { } public void enforceAllRestrictions() { - for (DependencyRulesEnforcer rulesEnforcer : rulesEnforcersByTask - .values()) { - rulesEnforcer.enforce(); - } - for (ParentShrinkingEnforcer parentShrinkingEnforcer : parentShrinkingEnforcerByTask - .values()) { - parentShrinkingEnforcer.enforce(); - } + preAndPostActions.doAction(new IAction() { + + @Override + public void doAction() { + for (DependencyRulesEnforcer rulesEnforcer : rulesEnforcersByTask + .values()) { + rulesEnforcer.enforce(); + } + for (ParentShrinkingEnforcer parentShrinkingEnforcer : parentShrinkingEnforcerByTask + .values()) { + parentShrinkingEnforcer.enforce(); + } + } + }); } public void addTopLevel(Task task) { @@ -261,11 +338,16 @@ public class GanttDiagramGraph implements ICriticalPathCalculable { Task source = dependency.getSource(); Task destination = dependency.getDestination(); graph.addEdge(source, destination, dependency); - getEnforcer(destination).enforce(); + enforceRestrictions(destination); } - public void enforceRestrictions(Task task) { - getEnforcer(task).enforce(); + public void enforceRestrictions(final Task task) { + preAndPostActions.doAction(new IAction() { + @Override + public void doAction() { + getEnforcer(task).enforce(); + } + }); } public boolean contains(Dependency dependency) {