ItEr15S12RFComportamentoGraficoPlanificadorItEr14S13: Subtasks are shown in the right pane depending on left pane's nodes expansion state.

This commit is contained in:
Óscar González Fernández 2009-07-05 17:15:30 +02:00 committed by Javier Moran Rua
parent 47555e0b6d
commit ff89434f23
13 changed files with 324 additions and 58 deletions

View file

@ -27,6 +27,7 @@ public class Dependency extends XulElement implements AfterCompose {
public Dependency() {
}
public Dependency(Task source, Task destination) {
@ -48,8 +49,8 @@ public class Dependency extends XulElement implements AfterCompose {
redrawDependency();
}
};
this.source.getTaskBean().addPropertyChangeListener(listener);
this.destination.getTaskBean().addPropertyChangeListener(listener);
this.source.getTaskBean().addFundamentalPropertiesChangeListener(listener);
this.destination.getTaskBean().addFundamentalPropertiesChangeListener(listener);
}
/**

View file

@ -5,12 +5,15 @@
package org.zkoss.ganttz;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.zkoss.ganttz.util.MenuBuilder;
import org.zkoss.ganttz.util.TaskBean;
import org.zkoss.ganttz.util.WeakReferencedListeners;
import org.zkoss.ganttz.util.MenuBuilder.ItemAction;
import org.zkoss.ganttz.util.WeakReferencedListeners.ListenerNotification;
@ -26,6 +29,46 @@ import org.zkoss.zul.impl.XulElement;
*/
public class DependencyList extends XulElement implements AfterCompose {
private final class DependencyVisibilityToggler implements
PropertyChangeListener {
private final TaskBean source;
private final TaskBean destination;
private final Dependency dependency;
private DependencyVisibilityToggler(TaskBean source,
TaskBean destination, Dependency dependency) {
this.source = source;
this.destination = destination;
this.dependency = dependency;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!evt.getPropertyName().equals("visible"))
return;
if (dependencyMustBeVisible() != isDependencyNowVisible()) {
toggleDependencyExistence(dependencyMustBeVisible());
}
}
void toggleDependencyExistence(boolean visible) {
if (visible) {
appendChild(dependency);
addContextMenu(dependency);
} else {
removeChild(dependency);
}
}
boolean isDependencyNowVisible() {
return dependency.getParent() != null;
}
boolean dependencyMustBeVisible() {
return source.isVisible() && destination.isVisible();
}
}
private static final Log LOG = LogFactory.getLog(DependencyList.class);
private TaskRemovedListener taskRemovedListener;
@ -43,9 +86,16 @@ public class DependencyList extends XulElement implements AfterCompose {
return Planner.findComponentsOfType(Dependency.class, children);
}
void addDependency(Dependency dependency) {
appendChild(dependency);
addContextMenu(dependency);
void addDependency(final Dependency dependency) {
Task source = dependency.getSource();
Task destination = dependency.getDestination();
DependencyVisibilityToggler visibilityToggler = new DependencyVisibilityToggler(
source.getTaskBean(), destination.getTaskBean(), dependency);
source.getTaskBean().addFundamentalPropertiesChangeListener(visibilityToggler);
destination.getTaskBean().addVisibilityPropertiesChangeListener(
visibilityToggler);
visibilityToggler.toggleDependencyExistence(visibilityToggler
.dependencyMustBeVisible());
}
private void addContextMenu(Dependency dependency) {

View file

@ -13,6 +13,9 @@ import org.zkoss.ganttz.TaskDetail.ITaskDetailNavigator;
import org.zkoss.ganttz.util.TaskBean;
import org.zkoss.ganttz.util.TaskContainerBean;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.OpenEvent;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.Tree;
@ -30,16 +33,40 @@ public class ListDetails extends HtmlMacroComponent {
TaskBean taskBean = (TaskBean) node.getData();
Treerow treerow = new Treerow();
treerow.setParent(item);
item.setOpen(isOpened(taskBean));
Treecell treecell = new Treecell();
treecell.setParent(treerow);
final int[] path = tasksTreeModel.getPath(tasksTreeModel.getRoot(),
node);
TaskDetail taskDetail = TaskDetail.create(taskBean,
new TreeNavigator(tasksTreeModel, path));
if (taskBean instanceof TaskContainerBean) {
expandWhenOpened((TaskContainerBean) taskBean, item);
}
taskDetail.setParent(treecell);
detailsForBeans.put(taskBean, taskDetail);
taskDetail.afterCompose();
}
private void expandWhenOpened(final TaskContainerBean taskBean,
Treeitem item) {
item.addEventListener("onOpen", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
OpenEvent openEvent = (OpenEvent) event;
taskBean.setExpanded(openEvent.isOpen());
}
});
}
}
public boolean isOpened(TaskBean taskBean) {
if (taskBean instanceof TaskContainerBean) {
TaskContainerBean container = (TaskContainerBean) taskBean;
return container.isExpanded();
}
return true;
}
private Map<TaskBean, TaskDetail> detailsForBeans = new HashMap<TaskBean, TaskDetail>();
@ -75,10 +102,6 @@ public class ListDetails extends HtmlMacroComponent {
return detailsForBeans.get(bean);
}
private TaskBean getTaskBean(SimpleTreeNode node) {
return (TaskBean) node.getData();
}
@Override
public TaskDetail getBelowDetail() {
SimpleTreeNode parent = getParent(pathToNode);
@ -119,15 +142,18 @@ public class ListDetails extends HtmlMacroComponent {
this.taskBeans = taskBeans;
}
private static TaskBean getTaskBean(SimpleTreeNode node) {
return (TaskBean) node.getData();
}
private static List<SimpleTreeNode> asSimpleTreeNodes(
List<TaskBean> taskBeans2) {
List<TaskBean> taskBeans) {
ArrayList<SimpleTreeNode> result = new ArrayList<SimpleTreeNode>();
for (TaskBean taskBean : taskBeans2) {
for (TaskBean taskBean : taskBeans) {
SimpleTreeNode node = asSimpleTreeNode(taskBean);
if (taskBean instanceof TaskContainerBean) {
TaskContainerBean container = (TaskContainerBean) taskBean;
node.getChildren()
.addAll(
node.getChildren().addAll(
asSimpleTreeNodes(container.getTasks()));
}
result.add(node);

View file

@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -127,9 +128,9 @@ public class Task extends Div implements AfterCompose {
}
};
public static Task asTask(TaskBean taskBean) {
public static Task asTask(TaskBean taskBean, TaskList taskList) {
if (taskBean instanceof TaskContainerBean) {
return TaskContainer.asTask((TaskContainerBean) taskBean);
return TaskContainer.asTask((TaskContainerBean) taskBean, taskList);
}
return new Task(taskBean);
}
@ -144,13 +145,19 @@ public class Task extends Div implements AfterCompose {
public void afterCompose() {
updateProperties();
this.taskBean.addPropertyChangeListener(new PropertyChangeListener() {
if (propertiesListener != null)
return;
propertiesListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
updateProperties();
if (isInPage()) {
updateProperties();
}
}
});
};
this.taskBean
.addFundamentalPropertiesChangeListener(propertiesListener);
}
private String _color;
@ -158,6 +165,7 @@ public class Task extends Div implements AfterCompose {
private List<WeakReference<DependencyAddedListener>> dependencyListeners = new LinkedList<WeakReference<DependencyAddedListener>>();
private final TaskBean taskBean;
private PropertyChangeListener propertiesListener;
public TaskBean getTaskBean() {
return taskBean;
@ -307,7 +315,20 @@ public class Task extends Div implements AfterCompose {
return getPlanner().getDependencyList();
}
private boolean isInPage() {
return getParent() != null;
}
public void remove() {
getTaskList().removeTask(this);
}
void publishTasks(Map<TaskBean, Task> resultAccumulated) {
resultAccumulated.put(getTaskBean(), this);
publishDescendants(resultAccumulated);
}
protected void publishDescendants(Map<TaskBean, Task> resultAccumulated) {
}
}

View file

@ -1,23 +1,83 @@
package org.zkoss.ganttz;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.zkoss.ganttz.util.TaskBean;
import org.zkoss.ganttz.util.TaskContainerBean;
import org.zkoss.ganttz.util.TaskContainerBean.IExpandListener;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.ext.AfterCompose;
/**
* This class contains the information of a task container. It can be modified and
* notifies of the changes to the interested parties. <br/>
* This class contains the information of a task container. It can be modified
* and notifies of the changes to the interested parties. <br/>
* Created at Jul 1, 2009
*
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*
*/
public class TaskContainer extends Task implements AfterCompose {
public static TaskContainer asTask(TaskContainerBean taskContainerBean) {
return new TaskContainer(taskContainerBean);
public static TaskContainer asTask(TaskContainerBean taskContainerBean,
TaskList taskList) {
return new TaskContainer(taskContainerBean, taskList);
}
public TaskContainer(TaskContainerBean taskContainerBean) {
private List<Task> subtasks = new ArrayList<Task>();
final TaskList taskList;
private IExpandListener expandListener;
public TaskContainer(TaskContainerBean taskContainerBean, TaskList taskList) {
super(taskContainerBean);
this.expandListener = new IExpandListener() {
@Override
public void expandStateChanged(boolean isNowExpanded) {
if (isNowExpanded) {
open();
} else {
close();
}
}
};
taskContainerBean.addExpandListener(expandListener);
this.taskList = taskList;
for (TaskBean taskBean : taskContainerBean.getTasks()) {
subtasks.add(Task.asTask(taskBean, taskList));
}
}
@Override
protected void publishDescendants(Map<TaskBean, Task> resultAccumulated) {
for (Task task : subtasks) {
task.publishTasks(resultAccumulated);
}
}
public void open() {
Component previous = this;
for (Task subtask : subtasks) {
taskList.addTask(previous, subtask, true);
previous = subtask;
}
}
public boolean isExpanded() {
return getTaskContainerBean().isExpanded();
}
private TaskContainerBean getTaskContainerBean() {
return (TaskContainerBean) getTaskBean();
}
private void close() {
for (Task subtask : subtasks) {
if (subtask instanceof TaskContainer) {
TaskContainer container = (TaskContainer) subtask;
container.close();
}
taskList.hideTask(subtask);
}
}
}

View file

@ -218,7 +218,7 @@ public class TaskDetail extends HtmlMacroComponent implements AfterCompose {
public void afterCompose() {
super.afterCompose();
updateComponents();
taskBean.addPropertyChangeListener(new PropertyChangeListener() {
taskBean.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {

View file

@ -50,7 +50,7 @@ public class TaskEditFormComposer extends GenericForwardComposer {
}
}
};
currentTask.addPropertyChangeListener(propertyChangeListener);
currentTask.addFundamentalPropertiesChangeListener(propertyChangeListener);
updateComponentValuesForTask(currentTask);
}

View file

@ -23,6 +23,7 @@ import org.zkoss.ganttz.util.zoom.ZoomLevel;
import org.zkoss.ganttz.util.zoom.ZoomLevelChangedListener;
import org.zkoss.zk.au.out.AuInvoke;
import org.zkoss.zk.ui.AbstractComponent;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.ext.AfterCompose;
@ -64,7 +65,7 @@ public class TaskList extends XulElement implements AfterCompose {
List<Task> tasks = Planner.findComponentsOfType(Task.class, children);
Map<TaskBean, Task> taskByTaskBean = new HashMap<TaskBean, Task>();
for (Task task : tasks) {
taskByTaskBean.put(task.getTaskBean(), task);
task.publishTasks(taskByTaskBean);
}
List<Dependency> result = new ArrayList<Dependency>();
for (DependencyBean dependencyBean : dependencies) {
@ -76,11 +77,13 @@ public class TaskList extends XulElement implements AfterCompose {
}
public void addTask(TaskBean newTask) {
addTask(Task.asTask(newTask), true);
addTask(Task.asTask(newTask, this), true);
}
public synchronized void addTask(final Task task, boolean relocate) {
task.setParent(this);
public synchronized void addTask(Component afterThis, final Task task,
boolean relocate) {
insertBefore(task, afterThis == null ? null : afterThis
.getNextSibling());
addContextMenu(task);
addListenerForTaskEditForm(task);
ListIterator<WeakReference<DependencyAddedListener>> iterator = listeners
@ -100,6 +103,17 @@ public class TaskList extends XulElement implements AfterCompose {
adjustZoomColumnsHeight();
getGanttPanel().getDependencyList().redrawDependencies();
}
if (task instanceof TaskContainer) {
TaskContainer container = (TaskContainer) task;
if (container.isExpanded()) {
container.open();
}
}
}
public synchronized void addTask(final Task task, boolean relocate) {
addTask(null, task, relocate);
}
private void addListenerForTaskEditForm(final Task task) {
@ -173,6 +187,16 @@ public class TaskList extends XulElement implements AfterCompose {
return result;
}
private List<TaskContainer> getTaskContainers() {
ArrayList<TaskContainer> result = new ArrayList<TaskContainer>();
for (Task task : getTasks()) {
if (task instanceof TaskContainer) {
result.add((TaskContainer) task);
}
}
return result;
}
private int getTasksNumber() {
return getTasks().size();
}
@ -191,7 +215,7 @@ public class TaskList extends XulElement implements AfterCompose {
@Override
public void afterCompose() {
for (TaskBean taskBean : originalTasks) {
addTask(Task.asTask(taskBean), false);
addTask(Task.asTask(taskBean, this), false);
}
if (zoomLevelChangedListener == null) {
zoomLevelChangedListener = new ZoomLevelChangedListener() {
@ -242,4 +266,9 @@ public class TaskList extends XulElement implements AfterCompose {
response("adjust_height", new AuInvoke(TaskList.this, "adjust_height"));
}
public void hideTask(Task subtask) {
removeChild(subtask);
subtask.setParent(null);
}
}

View file

@ -48,7 +48,7 @@ public class DependencyRegistry {
throw new IllegalArgumentException("container cannot be null");
this.container = container;
for (TaskBean subtask : this.container.getTasks()) {
subtask.addPropertyChangeListener(new PropertyChangeListener() {
subtask.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
@ -72,7 +72,7 @@ public class DependencyRegistry {
if (task == null)
throw new IllegalArgumentException("task cannot be null");
this.task = task;
this.task.addPropertyChangeListener(new PropertyChangeListener() {
this.task.addFundamentalPropertiesChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {

View file

@ -14,7 +14,10 @@ import java.util.Date;
*/
public class TaskBean {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
private PropertyChangeSupport fundamentalProperties = new PropertyChangeSupport(
this);
private PropertyChangeSupport visibilityProperties = new PropertyChangeSupport(
this);
private String name;
@ -25,6 +28,19 @@ public class TaskBean {
private String notes;
private boolean visible = true;
public boolean isVisible() {
return visible;
}
protected void setVisible(boolean visible) {
boolean previousValue = this.visible;
this.visible = visible;
visibilityProperties.firePropertyChange("visible", previousValue,
this.visible);
}
public TaskBean() {
}
@ -49,14 +65,14 @@ public class TaskBean {
public void setName(String name) {
String previousValue = this.name;
this.name = name;
propertyChangeSupport.firePropertyChange("name", previousValue,
fundamentalProperties.firePropertyChange("name", previousValue,
this.name);
}
public void setBeginDate(Date beginDate) {
Date previousValue = this.beginDate;
this.beginDate = beginDate;
propertyChangeSupport.firePropertyChange("beginDate", previousValue,
fundamentalProperties.firePropertyChange("beginDate", previousValue,
this.beginDate);
}
@ -67,7 +83,7 @@ public class TaskBean {
public void setLengthMilliseconds(long lengthMilliseconds) {
long previousValue = this.lengthMilliseconds;
this.lengthMilliseconds = lengthMilliseconds;
propertyChangeSupport.firePropertyChange("lengthMilliseconds",
fundamentalProperties.firePropertyChange("lengthMilliseconds",
previousValue, this.lengthMilliseconds);
}
@ -75,12 +91,17 @@ public class TaskBean {
return lengthMilliseconds;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.propertyChangeSupport.addPropertyChangeListener(listener);
public void addVisibilityPropertiesChangeListener(
PropertyChangeListener listener) {
this.visibilityProperties.addPropertyChangeListener(listener);
}
public void addFundamentalPropertiesChangeListener(PropertyChangeListener listener) {
this.fundamentalProperties.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.propertyChangeSupport.removePropertyChangeListener(listener);
this.fundamentalProperties.removePropertyChangeListener(listener);
}
public Date getEndDate() {
@ -94,7 +115,7 @@ public class TaskBean {
public void setNotes(String notes) {
String previousValue = this.notes;
this.notes = notes;
propertyChangeSupport.firePropertyChange("notes", previousValue,
fundamentalProperties.firePropertyChange("notes", previousValue,
this.notes);
}

View file

@ -6,6 +6,8 @@ import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.zkoss.ganttz.util.WeakReferencedListeners.ListenerNotification;
/**
* This class contains the information of a task container. It can be modified
* and notifies of the changes to the interested parties. <br/>
@ -14,6 +16,10 @@ import java.util.List;
*/
public class TaskContainerBean extends TaskBean {
public interface IExpandListener {
public void expandStateChanged(boolean isNowExpanded);
}
private static <T> List<T> removeNulls(Collection<T> elements) {
ArrayList<T> result = new ArrayList<T>();
for (T e : elements) {
@ -61,8 +67,18 @@ public class TaskContainerBean extends TaskBean {
private List<TaskBean> tasks = new ArrayList<TaskBean>();
private boolean expanded = false;
private WeakReferencedListeners<IExpandListener> expandListeners = WeakReferencedListeners
.create();
public void addExpandListener(IExpandListener expandListener) {
expandListeners.addListener(expandListener);
}
public void add(TaskBean task) {
tasks.add(task);
task.setVisible(expanded);
}
public List<TaskBean> getTasks() {
@ -97,4 +113,37 @@ public class TaskContainerBean extends TaskBean {
return getBiggest(getEndDates());
}
public boolean isExpanded() {
return expanded;
}
@Override
protected void setVisible(boolean visible) {
super.setVisible(visible);
if (!this.expanded) {
return;
}
for (TaskBean taskBean : tasks) {
taskBean.setVisible(true);
}
}
public void setExpanded(boolean expanded) {
boolean valueChanged = expanded != this.expanded;
this.expanded = expanded;
for (TaskBean taskBean : tasks) {
taskBean.setVisible(this.expanded);
}
if(valueChanged){
expandListeners.fireEvent(new ListenerNotification<IExpandListener>() {
@Override
public void doNotify(IExpandListener listener) {
listener
.expandStateChanged(TaskContainerBean.this.expanded);
}
});
}
}
}

View file

@ -1,11 +1,13 @@
zkDependency = {};
zkDependency.origin = function(dependency) {
return document.getElementById(dependency.getAttribute("idTaskOrig"));
var id = dependency.getAttribute("idTaskOrig");
return document.getElementById(id);
}
zkDependency.destination = function(dependency) {
return document.getElementById(dependency.getAttribute("idTaskEnd"));
var id = dependency.getAttribute("idTaskEnd");
return document.getElementById(id);
}
zkDependency.draw = function(dependency) {
@ -30,11 +32,11 @@ zkDependency.draw = function(dependency) {
zkDependency.init = function(dependency) {
zkPlanner.setupArrow(dependency);
YAHOO.util.Event.onDOMReady(function() {
var origin = zkDependency.origin(dependency);
var destination = zkDependency.destination(dependency);
zkDependency.draw(dependency);
zkTask.addRelatedDependency(origin, dependency);
zkTask.addRelatedDependency(destination, dependency);
});
var origin = zkDependency.origin(dependency);
var destination = zkDependency.destination(dependency);
zkTask.addRelatedDependency(origin, dependency);
zkTask.addRelatedDependency(destination, dependency);
}

View file

@ -38,6 +38,14 @@ public class DataForPlanner {
DependencyRegistry dependencyRegistry = new DependencyRegistry();
Date now = new Date();
Date end = twoMonthsLater(now);
TaskContainerBean container = createContainer("container", now, end);
TaskBean child1 = createTaskBean("child 1", now, end);
container.add(child1);
TaskContainerBean containerChild = createContainer("child 2", now, end);
containerChild.setExpanded(true);
container.add(containerChild);
containerChild.add(createTaskBean("another", now, end));
dependencyRegistry.addTopLevel(container);
TaskBean first = null;
TaskBean second = null;
for (int i = 0; i < tasksToCreate - 3; i++) {
@ -49,16 +57,7 @@ public class DataForPlanner {
second = taskBean;
dependencyRegistry.addTopLevel(taskBean);
}
TaskContainerBean container = new TaskContainerBean();
container.setBeginDate(now);
container.setEndDate(end);
container.setName("container");
TaskBean child1 = createTaskBean("child 1", now, end);
container.add(child1);
TaskBean child2 = createTaskBean("child 2", now, end);
container.add(child2);
dependencyRegistry.addTopLevel(container);
dependencyRegistry.add(new DependencyBean(child1, child2,
dependencyRegistry.add(new DependencyBean(child1, containerChild,
DependencyType.END_START));
dependencyRegistry.add(new DependencyBean(first, second,
DependencyType.END_START));
@ -66,6 +65,14 @@ public class DataForPlanner {
return dependencyRegistry;
}
private TaskContainerBean createContainer(String name, Date start, Date end) {
TaskContainerBean container = new TaskContainerBean();
container.setBeginDate(start);
container.setEndDate(end);
container.setName(name);
return container;
}
private TaskBean createTaskBean(String name, Date now, Date end) {
TaskBean taskBean = new TaskBean();
taskBean.setName(name);