ItEr12S09RFNavegacionOrganizacionTraballoItEr11S10: Manipulation of a ProjectWork's tasks tree.

This commit is contained in:
Óscar González Fernández 2009-06-10 17:53:49 +02:00 committed by Javier Moran Rua
parent d8d9b0d4fd
commit ca26bd6b6d
22 changed files with 922 additions and 407 deletions

View file

@ -17,7 +17,7 @@ public class ActivityWork {
this.workingHours = workingHours;
}
public int getWorkingHours() {
public Integer getWorkingHours() {
return workingHours;
}

View file

@ -0,0 +1,21 @@
package org.navalplanner.business.workorders.entities;
/**
* Container of TaskWorks. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public interface ITaskWorkContainer {
public void add(TaskWork task);
public void remove(TaskWork task);
public void replace(TaskWork oldTask, TaskWork newTask);
public void up(TaskWork task);
public void down(TaskWork task);
public void add(int position, TaskWork task);
}

View file

@ -11,7 +11,7 @@ import org.hibernate.validator.NotNull;
* It represents a project with its related information. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class ProjectWork {
public class ProjectWork implements ITaskWorkContainer {
private static Date copy(Date date) {
return date != null ? new Date(date.getTime()) : date;
@ -99,11 +99,39 @@ public class ProjectWork {
}
public void add(TaskWork task) {
taskWorks.add(task);
getTasksManipulator().add(task);
}
private TaskWorkListManipulator getTasksManipulator() {
return new TaskWorkListManipulator(taskWorks);
}
public List<TaskWork> getTaskWorks() {
return new ArrayList<TaskWork>(taskWorks);
}
public void remove(TaskWork task) {
getTasksManipulator().remove(task);
}
public void replace(TaskWork oldTask, TaskWork newTask) {
getTasksManipulator().replace(oldTask, newTask);
}
@Override
public void up(TaskWork task) {
getTasksManipulator().up(task);
}
@Override
public void down(TaskWork task) {
getTasksManipulator().down(task);
}
@Override
public void add(int position, TaskWork task) {
getTasksManipulator().add(position, task);
}
}

View file

@ -20,15 +20,22 @@ public abstract class TaskWork {
private Set<ActivityWork> activityWorks = new HashSet<ActivityWork>();
public int getWorkHours() {
public Integer getWorkHours() {
int result = 0;
Set<ActivityWork> a = activityWorks;
for (ActivityWork activityWork : a) {
result += activityWork.getWorkingHours();
Integer workingHours = activityWork.getWorkingHours();
if (workingHours != null) {
result += workingHours;
}
}
return result;
}
public void setActivities(List<ActivityWork> activities) {
this.activityWorks = new HashSet<ActivityWork>(activities);
}
public void addActivity(ActivityWork activityWork) {
activityWorks.add(activityWork);
}
@ -55,4 +62,36 @@ public abstract class TaskWork {
public void setName(String name) {
this.name = name;
}
public abstract boolean isLeaf();
public abstract List<TaskWork> getChildren();
public Date getInitDate() {
return initDate;
}
public void setInitDate(Date initDate) {
this.initDate = initDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public abstract void remove(TaskWork lastAsTask);
public abstract void replace(TaskWork old, TaskWork newTask);
public abstract TaskWorkContainer asContainer();
public void forceLoadActivities() {
for (ActivityWork activityWork : activityWorks) {
activityWork.getWorkingHours();
}
}
}

View file

@ -3,16 +3,57 @@ package org.navalplanner.business.workorders.entities;
import java.util.ArrayList;
import java.util.List;
public class TaskWorkContainer extends TaskWork {
public class TaskWorkContainer extends TaskWork implements ITaskWorkContainer {
private List<TaskWork> children = new ArrayList<TaskWork>();
@Override
public List<TaskWork> getChildren() {
return new ArrayList<TaskWork>(children);
}
public void addTask(TaskWorkLeaf leaf) {
children.add(leaf);
@Override
public boolean isLeaf() {
return false;
}
@Override
public void remove(TaskWork child) {
getManipulator().remove(child);
}
@Override
public void replace(TaskWork oldTask, TaskWork newTask) {
getManipulator().replace(oldTask, newTask);
}
@Override
public void add(TaskWork task) {
getManipulator().add(task);
}
@Override
public void up(TaskWork task) {
getManipulator().up(task);
}
private TaskWorkListManipulator getManipulator() {
return new TaskWorkListManipulator(children);
}
@Override
public TaskWorkContainer asContainer() {
return this;
}
@Override
public void down(TaskWork task) {
getManipulator().down(task);
}
@Override
public void add(int position, TaskWork task) {
children.add(position, task);
}
}

View file

@ -1,4 +1,36 @@
package org.navalplanner.business.workorders.entities;
import java.util.ArrayList;
import java.util.List;
public class TaskWorkLeaf extends TaskWork {
@Override
public List<TaskWork> getChildren() {
return new ArrayList<TaskWork>();
}
@Override
public boolean isLeaf() {
return true;
}
public void remove(TaskWork taskWork) {
}
@Override
public TaskWorkContainer asContainer() {
TaskWorkContainer result = new TaskWorkContainer();
result.setName(getName());
result.setInitDate(getInitDate());
result.setEndDate(getEndDate());
result.setActivities(getActivities());
return result;
}
@Override
public void replace(TaskWork old, TaskWork newTask) {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,57 @@
package org.navalplanner.business.workorders.entities;
import java.util.Collections;
import java.util.List;
/**
* Implementation of {@link TaskWork}. <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class TaskWorkListManipulator implements ITaskWorkContainer {
private final List<TaskWork> taskWorks;
public TaskWorkListManipulator(List<TaskWork> taskWorks) {
this.taskWorks = taskWorks;
}
@Override
public void add(TaskWork task) {
taskWorks.add(task);
}
@Override
public void remove(TaskWork task) {
taskWorks.remove(task);
}
@Override
public void replace(TaskWork oldTask, TaskWork newTask) {
Collections.replaceAll(taskWorks, oldTask, newTask);
}
@Override
public void up(TaskWork task) {
int position = taskWorks.indexOf(task);
if (position < taskWorks.size() - 1) {
taskWorks.remove(position);
taskWorks.add(position + 1, task);
}
}
@Override
public void down(TaskWork task) {
int position = taskWorks.indexOf(task);
if (position > 0) {
taskWorks.remove(position);
taskWorks.add(position - 1, task);
}
}
@Override
public void add(int position, TaskWork task) {
taskWorks.add(position, task);
}
}

View file

@ -12,7 +12,7 @@
<property name="description" access="field"></property>
<property name="responsible" access="field"></property>
<property name="customer" access="field"></property>
<list name="taskWorks" access="field" cascade="all-delete-orphan">
<list name="taskWorks" access="field" cascade="all">
<key column="projectId" not-null="false"></key>
<index column="positionInProject"></index>
<one-to-many class="TaskWork" />
@ -23,7 +23,7 @@
<id name="id" type="long" access="field">
<generator class="native" />
</id>
<set name="activityWorks" access="field" cascade="all-delete-orphan">
<set name="activityWorks" access="field" cascade="all">
<key column="PARENT_TASK" not-null="false"></key>
<one-to-many class="ActivityWork" />
</set>
@ -34,7 +34,7 @@
<joined-subclass name="TaskWorkContainer">
<key column="TASKWORKID"></key>
<list name="children" access="field" cascade="all-delete-orphan">
<list name="children" access="field" cascade="all">
<key column="parent" not-null="false"></key>
<index column="positionInContainer"></index>
<one-to-many class="TaskWork" />

View file

@ -20,7 +20,7 @@ public class ProjectWorkTest {
ProjectWork projectWork = new ProjectWork();
TaskWorkContainer container = new TaskWorkContainer();
TaskWorkLeaf leaf = new TaskWorkLeaf();
container.addTask(leaf);
container.add(leaf);
projectWork.add(container);
assertThat(projectWork.getTaskWorks().size(), equalTo(1));
}
@ -32,7 +32,7 @@ public class ProjectWorkTest {
TaskWorkLeaf[] created = new TaskWorkLeaf[100];
for (int i = 0; i < created.length; i++) {
created[i] = new TaskWorkLeaf();
container.addTask(created[i]);
container.add(created[i]);
}
for (int i = 0; i < created.length; i++) {
assertThat(container.getChildren().get(i),

View file

@ -107,7 +107,7 @@ public class ProjectWorkServiceTest {
for (int i = 0; i < tasks.length; i++) {
TaskWorkLeaf leaf = createValidLeaf("bla");
tasks[i] = leaf;
container.addTask(leaf);
container.add(leaf);
}
projectWorkService.save(projectWork);
projectWorkService.onTransaction(new OnTransaction<Void>() {
@ -153,7 +153,7 @@ public class ProjectWorkServiceTest {
container.setName("bla");
TaskWorkLeaf leaf = new TaskWorkLeaf();
leaf.setName("leaf");
container.addTask(leaf);
container.add(leaf);
projectWork.add(container);
ActivityWork activityWork = new ActivityWork();
activityWork.setWorkingHours(3);

View file

@ -0,0 +1,47 @@
package org.navalplanner.web.common.converters;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.services.IProjectWorkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* A {@link Converter} for {@link ProjectWork} <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class ProjectWorkConverter implements Converter<ProjectWork> {
@Autowired
private IProjectWorkService projectWorkService;
@Override
public ProjectWork asObject(String stringRepresentation) {
try {
return projectWorkService
.find(Long.parseLong(stringRepresentation));
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public String asString(ProjectWork entity) {
return entity.getId() + "";
}
@Override
public String asStringUngeneric(Object entity) {
return asString((ProjectWork) entity);
}
@Override
public Class<ProjectWork> getType() {
return ProjectWork.class;
}
}

View file

@ -3,6 +3,7 @@ package org.navalplanner.web.workorders;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ITaskWorkContainer;
import org.navalplanner.business.workorders.entities.ProjectWork;
/**
@ -19,10 +20,12 @@ public interface IProjectWorkModel {
void save() throws ValidationException;
ProjectWork getProject();
ITaskWorkContainer getProject();
void remove(ProjectWork projectWork);
void prepareForRemove(ProjectWork project);
TaskTreeModel getTasksTreeModel();
}

View file

@ -3,6 +3,7 @@ package org.navalplanner.web.workorders;
import java.util.List;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ITaskWorkContainer;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
@ -47,7 +48,7 @@ public class ProjectWorkCRUDController extends GenericForwardComposer {
return cachedOnlyOneVisible;
}
public ProjectWork getProject() {
public ITaskWorkContainer getProject() {
return projectWorkModel.getProject();
}
@ -61,7 +62,7 @@ public class ProjectWorkCRUDController extends GenericForwardComposer {
}
}
private void goToList() {
public void goToList() {
Util.reloadBindings(listWindow);
getVisibility().showOnly(listWindow);
}
@ -128,6 +129,16 @@ public class ProjectWorkCRUDController extends GenericForwardComposer {
messagesForUser = new MessagesForUser(messagesContainer);
comp.setVariable("controller", this, true);
getVisibility().showOnly(listWindow);
setupTaskTreeController(comp, "editWindow");
setupTaskTreeController(comp, "createWindow");
}
private void setupTaskTreeController(Component comp, String window)
throws Exception {
TaskWorksTreeController controller = new TaskWorksTreeController(
projectWorkModel);
controller
.doAfterCompose(comp.getFellow(window).getFellow("tasksTree"));
}
}

View file

@ -8,6 +8,7 @@ import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.workorders.entities.ITaskWorkContainer;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.services.IProjectWorkService;
import org.springframework.beans.factory.annotation.Autowired;
@ -31,6 +32,8 @@ public class ProjectWorkModel implements IProjectWorkModel {
private ClassValidator<ProjectWork> projectValidator = new ClassValidator<ProjectWork>(
ProjectWork.class);
private TaskTreeModel tasksTreeModel;
@Autowired
public ProjectWorkModel(IProjectWorkService projectService) {
Validate.notNull(projectService);
@ -49,6 +52,7 @@ public class ProjectWorkModel implements IProjectWorkModel {
Validate.notNull(project);
try {
this.project = projectService.find(project.getId());
this.tasksTreeModel = new TaskTreeModel(this.project);
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
@ -57,6 +61,7 @@ public class ProjectWorkModel implements IProjectWorkModel {
@Override
public void prepareForCreate() {
this.project = new ProjectWork();
this.tasksTreeModel = new TaskTreeModel(this.project);
this.project.setInitDate(new Date());
}
@ -71,7 +76,7 @@ public class ProjectWorkModel implements IProjectWorkModel {
}
@Override
public ProjectWork getProject() {
public ITaskWorkContainer getProject() {
return project;
}
@ -89,4 +94,9 @@ public class ProjectWorkModel implements IProjectWorkModel {
this.project = project;
}
@Override
public TaskTreeModel getTasksTreeModel() {
return tasksTreeModel;
}
}

View file

@ -0,0 +1,188 @@
package org.navalplanner.web.workorders;
import java.util.ArrayList;
import java.util.List;
import org.navalplanner.business.workorders.entities.ITaskWorkContainer;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.entities.TaskWork;
import org.navalplanner.business.workorders.entities.TaskWorkContainer;
import org.navalplanner.business.workorders.entities.TaskWorkLeaf;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;
/**
* Model for a the tasks tree for a project <br />
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class TaskTreeModel extends SimpleTreeModel {
private static List<SimpleTreeNode> asNodes(List<TaskWork> taskWorks) {
ArrayList<SimpleTreeNode> result = new ArrayList<SimpleTreeNode>();
for (TaskWork taskWork : taskWorks) {
result.add(asNode(taskWork));
}
return result;
}
private static SimpleTreeNode asNode(TaskWork taskWork) {
taskWork.forceLoadActivities();
return new SimpleTreeNode(taskWork, asNodes(taskWork.getChildren()));
}
private static SimpleTreeNode createRootNodeAndDescendants(
ProjectWork project) {
return new SimpleTreeNode(project, asNodes(project.getTaskWorks()));
}
public TaskTreeModel(ProjectWork projectWork) {
super(createRootNodeAndDescendants(projectWork));
}
public void reloadFromProjectWork() {
ProjectWork root = getRootAsProject();
SimpleTreeNode rootAsNode = getRootAsNode();
rootAsNode.getChildren().clear();
rootAsNode.getChildren().addAll(asNodes(root.getTaskWorks()));
}
public void addTask() {
addTaskAtImpl(getRootAsNode());
reloadFromProjectWork();
}
private TaskWork createNewTask() {
TaskWork newTask = new TaskWorkLeaf();
newTask.setName("Nova Tarefa");
return newTask;
}
public void addTaskAt(SimpleTreeNode node) {
addTaskAtImpl(node);
reloadFromProjectWork();
}
private void addTaskAtImpl(SimpleTreeNode node) {
addTaskAtImpl(node, createNewTask());
}
private void addTaskAtImpl(SimpleTreeNode node, TaskWork task) {
addTaskAtImpl(node, task, node.getChildCount());
}
private void addTaskAtImpl(SimpleTreeNode destinationNode, TaskWork task,
int position) {
ITaskWorkContainer container = turnIntoContainerIfNeeded(destinationNode);
container.add(position, task);
}
private ITaskWorkContainer turnIntoContainerIfNeeded(
SimpleTreeNode selectedForTurningIntoContainer) {
ITaskWorkContainer parentContainer = asTaskContainer(getParent(selectedForTurningIntoContainer));
if (selectedForTurningIntoContainer.getData() instanceof ITaskWorkContainer)
return (ITaskWorkContainer) selectedForTurningIntoContainer
.getData();
TaskWork toBeTurned = asTask(selectedForTurningIntoContainer);
TaskWorkContainer asContainer = toBeTurned.asContainer();
parentContainer.replace(toBeTurned, asContainer);
return asContainer;
}
private SimpleTreeNode getParent(SimpleTreeNode node) {
int[] position = getPath(node);
SimpleTreeNode current = getRootAsNode();
SimpleTreeNode[] path = new SimpleTreeNode[position.length];
for (int i = 0; i < position.length; i++) {
path[i] = (SimpleTreeNode) current.getChildAt(position[i]);
current = path[i];
}
int parentOfLast = path.length - 2;
if (parentOfLast >= 0)
return path[parentOfLast];
else
return getRootAsNode();
}
public void indent(SimpleTreeNode nodeToIndent) {
SimpleTreeNode parentOfSelected = getParent(nodeToIndent);
int position = parentOfSelected.getChildren().indexOf(nodeToIndent);
if (position == 0) {
return;
}
SimpleTreeNode destination = (SimpleTreeNode) parentOfSelected
.getChildren().get(position - 1);
moveImpl(nodeToIndent, destination, destination.getChildCount());
reloadFromProjectWork();
}
public void unindent(SimpleTreeNode nodeToUnindent) {
SimpleTreeNode parent = getParent(nodeToUnindent);
if (getRootAsNode() == parent) {
return;
}
SimpleTreeNode destination = getParent(parent);
moveImpl(nodeToUnindent, destination, destination.getChildren()
.indexOf(parent) + 1);
reloadFromProjectWork();
}
public void move(SimpleTreeNode toBeMoved, SimpleTreeNode destination) {
moveImpl(toBeMoved, destination, destination.getChildCount());
reloadFromProjectWork();
}
private void moveImpl(SimpleTreeNode toBeMoved, SimpleTreeNode destination,
int position) {
if (destination.getChildren().contains(toBeMoved)) {
return;// it's already moved
}
removeNodeImpl(toBeMoved);
addTaskAtImpl(destination, asTask(toBeMoved), position);
}
public int[] getPath(SimpleTreeNode destination) {
int[] path = getPath(getRootAsNode(), destination);
return path;
}
public void up(SimpleTreeNode node) {
ITaskWorkContainer taskWorkContainer = asTaskContainer(getParent(node));
taskWorkContainer.up(asTask(node));
reloadFromProjectWork();
}
public void down(SimpleTreeNode node) {
ITaskWorkContainer taskWorkContainer = asTaskContainer(getParent(node));
taskWorkContainer.down(asTask(node));
reloadFromProjectWork();
}
private ProjectWork getRootAsProject() {
return (ProjectWork) getRootAsNode().getData();
}
private static TaskWork asTask(SimpleTreeNode node) {
return (TaskWork) node.getData();
}
private static ITaskWorkContainer asTaskContainer(SimpleTreeNode node) {
return (ITaskWorkContainer) node.getData();
}
private SimpleTreeNode getRootAsNode() {
return (SimpleTreeNode) getRoot();
}
public void removeNode(SimpleTreeNode value) {
removeNodeImpl(value);
reloadFromProjectWork();
}
private void removeNodeImpl(SimpleTreeNode value) {
if (value == getRootAsNode())
return;
ITaskWorkContainer taskContainer = asTaskContainer(getParent(value));
taskContainer.remove(asTask(value));
}
}

View file

@ -0,0 +1,329 @@
package org.navalplanner.web.workorders;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.entities.TaskWork;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.api.Tree;
/**
* Controller for {@link WorkOrganization} view of WorkOrder entitites <br />
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class TaskWorksTreeController extends GenericForwardComposer {
private Tree tree;
private TaskWorkTreeitemRenderer renderer = new TaskWorkTreeitemRenderer();
private TreeViewStateSnapshot snapshotOfOpenedNodes;
private final IProjectWorkModel projectWorkModel;
public TaskWorkTreeitemRenderer getRenderer() {
return renderer;
}
public TaskWorksTreeController(IProjectWorkModel projectWorkModel) {
this.projectWorkModel = projectWorkModel;
}
public void indent() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getTasksTreeModel().indent(getSelectedNode());
Util.reloadBindings(tree);
}
}
public TaskTreeModel getTasksTreeModel() {
return projectWorkModel.getTasksTreeModel();
}
public void unindent() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getTasksTreeModel().unindent(getSelectedNode());
Util.reloadBindings(tree);
}
}
public void up() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getTasksTreeModel().up(getSelectedNode());
Util.reloadBindings(tree);
}
}
public void down() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getTasksTreeModel().down(getSelectedNode());
Util.reloadBindings(tree);
}
}
private SimpleTreeNode getSelectedNode() {
return (SimpleTreeNode) tree.getSelectedItemApi().getValue();
}
public void move(Component dropedIn, Component dragged) {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
Treerow from = (Treerow) dragged;
Treerow to = (Treerow) dropedIn;
SimpleTreeNode fromNode = (SimpleTreeNode) ((Treeitem) from.getParent())
.getValue();
SimpleTreeNode toNode = (SimpleTreeNode) ((Treeitem) to.getParent())
.getValue();
getTasksTreeModel().move(fromNode, toNode);
Util.reloadBindings(tree);
}
public void addTaskWork() {
snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
if (tree.getSelectedCount() == 1) {
getTasksTreeModel().addTaskAt(getSelectedNode());
} else {
getTasksTreeModel().addTask();
}
Util.reloadBindings(tree);
}
private static class TreeViewStateSnapshot {
private final Set<Object> all;
private final Set<Object> dataOpen;
private TreeViewStateSnapshot(Set<Object> dataOpen, Set<Object> all) {
this.dataOpen = dataOpen;
this.all = all;
}
public static TreeViewStateSnapshot snapshotOpened(Tree tree) {
Iterator<Treeitem> itemsIterator = tree.getTreechildrenApi()
.getItems().iterator();
Set<Object> dataOpen = new HashSet<Object>();
Set<Object> all = new HashSet<Object>();
while (itemsIterator.hasNext()) {
Treeitem treeitem = (Treeitem) itemsIterator.next();
Object value = getAssociatedValue(treeitem);
if (treeitem.isOpen()) {
dataOpen.add(value);
}
all.add(value);
}
return new TreeViewStateSnapshot(dataOpen, all);
}
private static Object getAssociatedValue(Treeitem treeitem) {
SimpleTreeNode node = (SimpleTreeNode) treeitem.getValue();
return node.getData();
}
public void openIfRequired(Treeitem item) {
Object value = getAssociatedValue(item);
item.setOpen(isNewlyCreated(value) || wasOpened(value));
}
private boolean wasOpened(Object value) {
return dataOpen.contains(value);
}
private boolean isNewlyCreated(Object value) {
return !all.contains(value);
}
}
public void removeTaskWork() {
Set<Treeitem> selectedItems = tree.getSelectedItems();
for (Treeitem treeItem : selectedItems) {
SimpleTreeNode value = (SimpleTreeNode) treeItem.getValue();
getTasksTreeModel().removeNode(value);
}
Util.reloadBindings(tree);
}
void doEditFor(ProjectWork projectWork) {
Util.reloadBindings(tree);
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setVariable("tasksTreeController", this, true);
}
private static interface Getter<T> {
public T get();
}
private static interface Setter<T> {
public void set(T value);
}
private static Textbox bind(Textbox textBox, Getter<String> getter) {
textBox.setValue(getter.get());
textBox.setDisabled(true);
return textBox;
}
private static Textbox bind(final Textbox textBox,
final Getter<String> getter, final Setter<String> setter) {
textBox.setValue(getter.get());
textBox.addEventListener("onChange", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
InputEvent newInput = (InputEvent) event;
String value = newInput.getValue();
setter.set(value);
textBox.setValue(getter.get());
}
});
return textBox;
}
private static Datebox bind(final Datebox dateBox,
final Getter<Date> getter, final Setter<Date> setter) {
dateBox.setValue(getter.get());
dateBox.addEventListener("onChange", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
setter.set(dateBox.getValue());
dateBox.setValue(getter.get());
}
});
return dateBox;
}
public class TaskWorkTreeitemRenderer implements TreeitemRenderer {
public void TaskWorkTreeitemRenderer() {
}
@Override
public void render(Treeitem item, Object data) throws Exception {
SimpleTreeNode t = (SimpleTreeNode) data;
item.setValue(data);
final TaskWork taskWork = (TaskWork) t.getData();
if (snapshotOfOpenedNodes != null) {
snapshotOfOpenedNodes.openIfRequired(item);
}
// Contruct treecells
int[] path = getTasksTreeModel().getPath(t);
Treecell cellForName = new Treecell(pathAsString(path));
cellForName.appendChild(bind(new Textbox(), new Getter<String>() {
@Override
public String get() {
return taskWork.getName();
}
}, new Setter<String>() {
@Override
public void set(String value) {
taskWork.setName(value);
}
}));
Treecell cellForHours = new Treecell();
cellForHours.appendChild(bind(new Textbox(), new Getter<String>() {
@Override
public String get() {
return taskWork.getWorkHours() + "";
}
}));
Treecell tcDateStart = new Treecell();
tcDateStart.appendChild(bind(new Datebox(), new Getter<Date>() {
@Override
public Date get() {
return taskWork.getInitDate();
}
}, new Setter<Date>() {
@Override
public void set(Date value) {
taskWork.setInitDate(value);
}
}));
Treecell tcDateEnd = new Treecell();
tcDateEnd.appendChild(bind(new Datebox(), new Getter<Date>() {
@Override
public Date get() {
return taskWork.getEndDate();
}
}, new Setter<Date>() {
@Override
public void set(Date value) {
taskWork.setEndDate(value);
}
}));
Treerow tr = null;
/*
* Since only one treerow is allowed, if treerow is not null, append
* treecells to it. If treerow is null, contruct a new treerow and
* attach it to item.
*/
if (item.getTreerow() == null) {
tr = new Treerow();
tr.setParent(item);
} else {
tr = item.getTreerow();
tr.getChildren().clear();
}
// Attach treecells to treerow
tr.setDraggable("true");
tr.setDroppable("true");
cellForName.setParent(tr);
tcDateStart.setParent(tr);
tcDateEnd.setParent(tr);
cellForHours.setParent(tr);
// item.setOpen(false);
tr.addEventListener("onDrop", new EventListener() {
@Override
public void onEvent(org.zkoss.zk.ui.event.Event arg0)
throws Exception {
DropEvent dropEvent = (DropEvent) arg0;
move((Component) dropEvent.getTarget(),
(Component) dropEvent.getDragged());
}
});
}
private String pathAsString(int[] path) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < path.length; i++) {
if (i != 0) {
result.append(".");
}
result.append(path[i] + 1);
}
return result.toString();
}
}
}

View file

@ -1,232 +0,0 @@
package org.navalplanner.web.workorders;
import org.zkoss.zk.ui.event.Event;
import java.awt.dnd.DragSourceEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.navalplanner.web.common.Util;
import org.zkoss.ganttz.Task;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.metainfo.EventHandlerMap;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.api.Tree;
import org.zkoss.zul.api.Window;
import org.zkoss.zul.event.TreeDataListener;
/**
* Controller for {@link WorkOrganization} view of WorkOrder entitites <br />
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class WorkOrganizationController extends GenericForwardComposer {
private Tree tree;
private WorkOrganizationModel model;
private List taskWorkList = new ArrayList();
private TaskWorkTreeitemRenderer renderer = new TaskWorkTreeitemRenderer();
public WorkOrganizationController() {
}
public TaskWorkTreeitemRenderer getRenderer() {
return renderer;
}
public WorkOrganizationController(Tree tree) {
this.tree = tree;
}
public void move(Component self, Component dragged) {
/* if (self instanceof Treeitem) {
if (dragged.getParent().getId().equals("right")) {
self.insertBefore(dragged, self.getNextSibling());
} else {
self.insertBefore(dragged, self.getNextSibling());
}
} else {
self.appendChild(dragged);
} */
Treeitem elem = new Treeitem("Elemento");
//elem.appendChild(dragged);
if (self != null) {
System.out.println("SELF: " + self.toString());
}
if (dragged != null) {
System.out.println("DRAGGED: " + dragged.toString());
}
self.appendChild(elem);
}
public void addTaskWork() {
if (tree == null) {
System.out.println("Tree is null");
} else {
int index = tree.getSelectedCount();
taskWorkList.add(
index,
new SimpleTreeNode(new TaskWork("Nueva tarea", null, null, 10), new ArrayList()));
this.tree.setModel(this.model);
}
Util.reloadBindings(tree);
}
public void removeTaskWork() {
if (tree == null) {
System.out.println("Tree is null");
} else {
if (!(taskWorkList.isEmpty())) {
// Handle subchildren!
int index = tree.getSelectedCount();
// System.out.println(
// "TREE+ "+tree.getSelectedItems().toArray().toString());
taskWorkList.remove(index);
this.tree.setModel(this.model);
}
}
Util.reloadBindings(tree);
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setVariable("controller", this, true);
// Get real TaskWorkList
List children1 = new ArrayList();
children1.add(new SimpleTreeNode(new TaskWork("uno", null, null, 10), new ArrayList()));
children1.add(new SimpleTreeNode(new TaskWork("dos", null, null, 10), new ArrayList()));
children1.add(new SimpleTreeNode(new TaskWork("tres", null, null, 10), new ArrayList()));
children1.add(new SimpleTreeNode(new TaskWork("cuatro", null, null, 10), new ArrayList()));
SimpleTreeNode stn1 =
new SimpleTreeNode(new TaskWork("uno", null, null, 10), children1);
SimpleTreeNode stn2 =
new SimpleTreeNode(new TaskWork("dos", null, null, 10), children1);
SimpleTreeNode stn3 =
new SimpleTreeNode(new TaskWork("tres", null, null, 10), new ArrayList());
SimpleTreeNode stn4 =
new SimpleTreeNode(new TaskWork("cuatro", null, null, 10), children1);
taskWorkList.add(stn1);
taskWorkList.add(stn2);
taskWorkList.add(stn3);
taskWorkList.add(stn4);
this.model = new WorkOrganizationModel(taskWorkList);
// Set model (annalize parameter values)
// this.model = new WorkOrganizationModel(taskWorkList);
// this.tree.setModel(this.model);
}
public WorkOrganizationModel getTasksWork() {
return this.model;
}
// -------------------------------------------------
// -------------------------------------------------
public class TaskWork {
private String name;
private Date startDate;
private Date endDate;
private int hours;
public TaskWork(String name, Date startdate, Date enddate, int hours) {
this.name = name;
this.startDate = startdate;
this.endDate = enddate;
this.hours = hours;
}
public Date getEndDate() {
return endDate;
}
public int getHours() {
return hours;
}
public String getName() {
return name;
}
public Date getStartDate() {
return startDate;
}
}
// -------------------------------------------------
// -------------------------------------------------
public class TaskWorkTreeitemRenderer implements TreeitemRenderer {
public void TaskWorkTreeitemRenderer() {
}
@Override
public void render(Treeitem item, Object data) throws Exception {
SimpleTreeNode t = (SimpleTreeNode) data;
TaskWork taskWork = (TaskWork) t.getData();
//Contruct treecells
Treecell tcName = new Treecell(taskWork.getName());
tcName.appendChild(new Textbox(taskWork.getName()));
Treecell tcAccountId = new Treecell();
tcAccountId.appendChild(new Textbox("" + taskWork.getHours()));
Treecell tcDateStart = new Treecell();
tcDateStart.appendChild(new Datebox(taskWork.getStartDate()));
Treecell tcDateEnd = new Treecell();
tcDateStart.appendChild(new Datebox(taskWork.getEndDate()));
Treerow tr = null;
/*
* Since only one treerow is allowed, if treerow is not null,
* append treecells to it. If treerow is null, contruct a new
* treerow and attach it to item.
*/
if (item.getTreerow() == null) {
tr = new Treerow();
tr.setParent(item);
} else {
tr = item.getTreerow();
tr.getChildren().clear();
}
//Attach treecells to treerow
tr.setDraggable("true");
tr.setDroppable("true");
tcName.setParent(tr);
tcDateStart.setParent(tr);
tcDateEnd.setParent(tr);
tcAccountId.setParent(tr);
item.setOpen(false);
tr.addEventListener("onDrop", new EventListener() {
@Override
public void onEvent(org.zkoss.zk.ui.event.Event arg0) throws Exception {
DropEvent dropEvent = (DropEvent) arg0;
move((Component) dropEvent.getTarget(),
(Component) dropEvent.getDragged());
System.out.println("Dragging"+dropEvent.toString());
}
});
}
}
}

View file

@ -1,20 +0,0 @@
package org.navalplanner.web.workorders;
import java.util.List;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.event.TreeDataListener;
/**
* Model for WorkOrganization <br />
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
* Pending of real implementation of methods
*/
public class WorkOrganizationModel extends SimpleTreeModel {
public WorkOrganizationModel(List children) {
super(new SimpleTreeNode("Root", children));
}
}

View file

@ -1,40 +1,61 @@
<?component name="tasksTree" inline="true" macroURI="_tasksTree.zul"?>
<window id="${arg.top_id}" title="${arg.title}">
<grid fixedLayout="false">
<columns>
<column label="Nome" />
<column label="Comezo" />
<column label="Final" />
<column label="Responsable" />
<column label="Cliente" />
<column label="Descripción" />
</columns>
<rows>
<row>
<label value="Nome" />
<textbox value="@{controller.project.name}" />
</row>
<row>
<label value="Comezo" />
<datebox value="@{controller.project.initDate}" />
</row>
<row>
<label value="Final" />
<datebox value="@{controller.project.endDate}" />
</row>
<row>
<label value="Responsable" />
<textbox value="@{controller.project.responsible}" />
</row>
<row>
<label value="Cliente" />
<textbox value="@{controller.project.customer}" />
</row>
<row>
<label value="Descripción" />
<textbox value="@{controller.project.description}" rows="4"/>
</row>
</rows>
</grid>
<tabbox>
<tabs>
<tab label="Edición"></tab>
<tab label="Tarefas"></tab>
</tabs>
<tabpanels>
<tabpanel>
<grid fixedLayout="false">
<columns>
<column label="Nome" />
<column label="Comezo" />
<column label="Final" />
<column label="Responsable" />
<column label="Cliente" />
<column label="Descripción" />
</columns>
<rows>
<row>
<label value="Nome" />
<textbox value="@{controller.project.name}" />
</row>
<row>
<label value="Comezo" />
<datebox
value="@{controller.project.initDate}" />
</row>
<row>
<label value="Final" />
<datebox
value="@{controller.project.endDate}" />
</row>
<row>
<label value="Responsable" />
<textbox
value="@{controller.project.responsible}" />
</row>
<row>
<label value="Cliente" />
<textbox
value="@{controller.project.customer}" />
</row>
<row>
<label value="Descripción" />
<textbox
value="@{controller.project.description}"
rows="4" />
</row>
</rows>
</grid>
</tabpanel>
<tabpanel>
<tasksTree />
</tabpanel>
</tabpanels>
</tabbox>
<button onClick="controller.save();"
label="${arg.save_button_label}" />
<button onClick="controller.cancel();"

View file

@ -20,9 +20,6 @@
<button label="Remove"
onClick="controller.confirmRemove(self.parent.parent.value);">
</button>
<button label="Details"
href="/workorders/workorganization.zul">
</button>
</hbox>
<label value="@{project.name}" />
<label value="@{project.initDate}" />

View file

@ -0,0 +1,40 @@
<vbox id="tasksTree">
<vbox>
<hbox>
<button label="Nova tarefa"
onClick="tasksTreeController.addTaskWork();">
</button>
<button label="Eliminar tarefa"
onClick="tasksTreeController.removeTaskWork();">
</button>
<button label="Convertir en subtarefa"
onClick="tasksTreeController.indent();">
</button>
<button label="Unindent" onClick="tasksTreeController.unindent();" />
<button label="Baixar" onClick="tasksTreeController.up();"></button>
<button label="Subir" onClick="tasksTreeController.down();"></button>
</hbox>
</vbox>
<vbox>
<tree id="tree" width="900px" multiple="true" droppable="true"
onDrop="tasksTreeController.move(self, event.dragged)"
model="@{tasksTreeController.tasksTreeModel}"
treeitemRenderer="@{tasksTreeController.renderer}" pageSize="5">
<treecols sizable="true">
<treecol label="Nome e descripción" />
<treecol label="Comezo estimado" />
<treecol label="Fin estimado" />
<treecol label="Horas" />
</treecols>
</tree>
</vbox>
<!--zscript>
void move(Component dragged) {
if (self instanceof Treerow) {
self.parent.insertBefore(dragged, self.getNextSibling() );
} else {
self.appendChild(dragged);
}
}
</zscript-->
</vbox>

View file

@ -1,97 +0,0 @@
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<?page id="Create"?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro.css"?>
<?link rel="stylesheet" type="text/css" href="/resources/css/resources.css"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window self="@{define(content)}"
apply="org.navalplanner.web.workorders.WorkOrganizationController"
title="Organización de traballo">
<vbox>
<label value="@{project.name}" />
<label value="@{project.initDate}" />
<label value="@{project.endDate}" />
<label value="@{project.responsible}" />
<label value="@{project.customer}" />
<label value="@{project.description}" />
</vbox>
<vbox>
<hbox>
<button label="Nova tarefa"
onClick="controller.addTaskWork();">
</button>
<button label="Eliminar tarefa"
onClick="controller.removeTaskWork();">
</button>
<button label="Convertir en subtarefa"
onClick="controller.addTask(self.parent.parent.value);">
</button>
<button label="Baixar"
onClick="controller.addTask(self.parent.parent.value);">
</button>
<button label="Subir"
onClick="controller.addTask(self.parent.parent.value);">
</button>
</hbox>
</vbox>
<vbox>
<tree id="tree" width="900px" multiple="true"
droppable="true" onDrop="controller.move(self, event.dragged)"
model="@{controller.tasksWork}"
treeitemRenderer="@{controller.renderer}"
pageSize="5">
<treecols sizable="true">
<treecol label="Nome e descripción" />
<treecol label="Comezo estimado" />
<treecol label="Fin estimado" />
<treecol label="Horas" />
</treecols>
<!--treechildren>
<treeitem>
<treerow draggable="true" self="@{each='taskWork'}" value="@{taskWork}">
<treecell label="@{taskWork.name}">
<textbox value="Task 1 Name" width="230px"/>
</treecell>
<treecell>
<datebox/>
</treecell>
<treecell>
<datebox/>
</treecell>
<treecell>
<textbox value="10" width="30px"/> hours
</treecell>
</treerow>
</treeitem>
<treeitem>
<treerow draggable="true">
<treecell label=" Task 1 ">
<textbox value="Task 1 Name" width="230px"/>
</treecell>
<treecell>
<datebox/>
</treecell>
<treecell>
<datebox/>
</treecell>
<treecell>
<textbox value="10" width="30px"/> hours
</treecell>
</treerow>
</treeitem>
</treechildren-->
</tree>
</vbox>
</window>
<!--zscript>
void move(Component dragged) {
if (self instanceof Treerow) {
self.parent.insertBefore(dragged, self.getNextSibling() );
} else {
self.appendChild(dragged);
}
}
</zscript-->
</zk>