diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesComponent.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesComponent.java
new file mode 100644
index 000000000..5cf526cc3
--- /dev/null
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesComponent.java
@@ -0,0 +1,136 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
+ * Desenvolvemento Tecnolóxico de Galic
+ * ia
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package org.zkoss.ganttz.limitingresources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.joda.time.LocalDate;
+import org.zkoss.ganttz.IDatesMapper;
+import org.zkoss.ganttz.data.resourceload.LoadPeriod;
+import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
+import org.zkoss.ganttz.timetracker.TimeTracker;
+import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
+import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
+import org.zkoss.zul.Div;
+import org.zkoss.zul.impl.XulElement;
+
+/**
+ * This class wraps ResourceLoad data inside an specific HTML Div component.
+ * @author Lorenzo Tilve Álvaro
+ */
+public class LimitingResourcesComponent extends XulElement {
+
+ public static LimitingResourcesComponent create(TimeTracker timeTracker,
+ LoadTimeLine loadLine) {
+ return new LimitingResourcesComponent(timeTracker, loadLine);
+ }
+
+ private final LoadTimeLine loadLine;
+ private final TimeTracker timeTracker;
+ private transient IZoomLevelChangedListener zoomChangedListener;
+
+ private LimitingResourcesComponent(final TimeTracker timeTracker,
+ final LoadTimeLine loadLine) {
+ this.loadLine = loadLine;
+ this.timeTracker = timeTracker;
+ createChildren(loadLine, timeTracker.getMapper());
+ zoomChangedListener = new IZoomLevelChangedListener() {
+
+ @Override
+ public void zoomLevelChanged(ZoomLevel detailLevel) {
+ getChildren().clear();
+ createChildren(loadLine, timeTracker.getMapper());
+ invalidate();
+ }
+ };
+ this.timeTracker.addZoomListener(zoomChangedListener);
+ }
+
+ private void createChildren(LoadTimeLine loadLine, IDatesMapper mapper) {
+ List
divs = createDivsForPeriods(mapper, loadLine.getLoadPeriods());
+ for (Div div : divs) {
+ appendChild(div);
+ }
+ }
+
+ public String getResourceLoadName() {
+ return loadLine.getConceptName();
+ }
+
+ public String getResourceLoadType() {
+ return loadLine.getType();
+ }
+
+
+ private static List
createDivsForPeriods(IDatesMapper datesMapper,
+ List loadPeriods) {
+ List
result = new ArrayList
();
+ for (LoadPeriod loadPeriod : loadPeriods) {
+ result.add(createDivForPeriod(datesMapper, loadPeriod));
+ }
+ return result;
+ }
+
+ private static Div createDivForPeriod(IDatesMapper datesMapper,
+ LoadPeriod loadPeriod) {
+ Div result = new Div();
+ result.setClass(String.format("taskassignmentinterval %s", loadPeriod
+ .getLoadLevel().getCategory()));
+
+ String load = "Load: " + loadPeriod.getLoadLevel().getPercentage()
+ + "% , ";
+ if (loadPeriod.getLoadLevel().getPercentage() == Integer.MAX_VALUE) {
+ load = "";
+ }
+ result.setTooltiptext(load
+ + "total work hours: " + loadPeriod.getTotalResourceWorkHours()
+ + " , " + "assigned hours: " + loadPeriod.getAssignedHours());
+
+ result.setLeft(forCSS(getStartPixels(datesMapper, loadPeriod)));
+ result.setWidth(forCSS(getWidthPixels(datesMapper, loadPeriod)));
+ return result;
+ }
+
+ private static int getWidthPixels(IDatesMapper datesMapper,
+ LoadPeriod loadPeriod) {
+ LocalDate start = loadPeriod.getStart();
+ LocalDate end = loadPeriod.getEnd();
+ return datesMapper
+ .toPixels(toMilliseconds(end) - toMilliseconds(start));
+ }
+
+ private static long toMilliseconds(LocalDate localDate) {
+ return localDate.toDateMidnight().getMillis();
+ }
+
+ private static String forCSS(int pixels) {
+ return String.format("%dpx", pixels);
+ }
+
+ private static int getStartPixels(IDatesMapper datesMapper,
+ LoadPeriod loadPeriod) {
+ return datesMapper.toPixels(loadPeriod.getStart().toDateMidnight()
+ .toDate());
+ }
+
+}
\ No newline at end of file
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java
new file mode 100644
index 000000000..343c0ce46
--- /dev/null
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesLeftPane.java
@@ -0,0 +1,197 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
+ * Desenvolvemento Tecnolóxico de Galicia
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package org.zkoss.ganttz.limitingresources;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
+import org.zkoss.ganttz.util.MutableTreeModel;
+import org.zkoss.zk.ui.Component;
+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.Div;
+import org.zkoss.zul.Label;
+import org.zkoss.zul.Popup;
+import org.zkoss.zul.Treecell;
+import org.zkoss.zul.Treechildren;
+import org.zkoss.zul.Treeitem;
+import org.zkoss.zul.TreeitemRenderer;
+import org.zkoss.zul.Treerow;
+import org.zkoss.zul.api.Tree;
+
+public class LimitingResourcesLeftPane extends HtmlMacroComponent {
+
+ private MutableTreeModel modelForTree;
+ private final LimitingResourcesList limitingResourcesList;
+
+ public LimitingResourcesLeftPane(MutableTreeModel modelForTree,
+ LimitingResourcesList resourceLoadList) {
+ this.limitingResourcesList = resourceLoadList;
+ this.modelForTree = modelForTree;
+ }
+
+
+ @Override
+ public void afterCompose() {
+ super.afterCompose();
+ getContainerTree().setModel(modelForTree);
+ getContainerTree().setTreeitemRenderer(getRendererForTree());
+ }
+
+ private TreeitemRenderer getRendererForTree() {
+ return new TreeitemRenderer() {
+ @Override
+ public void render(Treeitem item, Object data)
+ throws Exception {
+ LoadTimeLine line = (LoadTimeLine) data;
+ item.setOpen(false);
+ item.setValue(line);
+
+ Treerow row = new Treerow();
+ Treecell cell = new Treecell();
+ Component component = createComponent(line);
+ item.appendChild(row);
+ row.appendChild(cell);
+ cell.appendChild(component);
+ collapse(line);
+ addExpandedListener(item, line);
+ }
+
+ private void addExpandedListener(final Treeitem item,
+ final LoadTimeLine line) {
+ item.addEventListener("onOpen", new EventListener() {
+ @Override
+ public void onEvent(Event event) throws Exception {
+ OpenEvent openEvent = (OpenEvent) event;
+ if (openEvent.isOpen()) {
+ List closed = calculatedClosedItems(item);
+ expand(line, closed);
+ } else {
+ collapse(line);
+ }
+ }
+ });
+ }
+
+ private Component createComponent(LoadTimeLine line) {
+ return isTopLevel(line) ? createFirstLevel(line)
+ : createSecondLevel(line);
+ }
+
+ private boolean isTopLevel(LoadTimeLine line) {
+ int[] path = modelForTree.getPath(modelForTree.getRoot(), line);
+ return path.length == 0;
+ }
+ };
+ }
+
+ private void collapse(LoadTimeLine line) {
+ limitingResourcesList.collapse(line);
+ }
+
+ private void expand(LoadTimeLine line, List closed) {
+ limitingResourcesList.expand(line, closed);
+ }
+
+ private List calculatedClosedItems(Treeitem item) {
+ List result = new ArrayList();
+ Treechildren treeChildren = item.getTreechildren();
+ if (treeChildren != null) {
+ List myTreeItems = (List) treeChildren
+ .getChildren();
+ Iterator iterator = myTreeItems.iterator();
+ while (iterator.hasNext()) {
+ Treeitem child = (Treeitem) iterator.next();
+ if (!child.isOpen()) {
+ result.addAll(getLineChildrenBy(child));
+ } else {
+ result.addAll(calculatedClosedItems(child));
+ }
+ }
+ }
+ return result;
+ }
+
+ private List getLineChildrenBy(Treeitem item) {
+ List result = new ArrayList();
+ LoadTimeLine line = getLineByTreeitem(item);
+ if (line != null) {
+ result.addAll(line.getAllChildren());
+ }
+ return result;
+ }
+
+ private LoadTimeLine getLineByTreeitem(Treeitem child) {
+ LoadTimeLine line = null;
+ try {
+ line = (LoadTimeLine) child.getValue();
+ } catch (Exception e) {
+ return null;
+ }
+ return line;
+ }
+
+ private Tree getContainerTree() {
+ return (Tree) getFellow("loadsTree");
+ }
+
+ private Component createFirstLevel(LoadTimeLine principal) {
+ Div result = createLabelWithName(principal);
+ result.setSclass("firstlevel");
+ return result;
+ }
+
+ private Component createSecondLevel(LoadTimeLine loadTimeLine) {
+ Div result = createLabelWithName(loadTimeLine);
+ result.setSclass("secondlevel");
+ return result;
+ }
+
+ private Div createLabelWithName(LoadTimeLine principal) {
+ Div result = new Div();
+ Label label = new Label();
+ final String conceptName = principal.getConceptName();
+ label.setValue(conceptName);
+ limitValue(result, label, 40);
+ result.appendChild(label);
+ return result;
+ }
+
+ private static void limitValue(Div parent, Label label, int maxLength) {
+ String originalValue = label.getValue();
+ if (originalValue == null || originalValue.length() <= maxLength) {
+ return;
+ }
+ label.setValue(originalValue.substring(0, maxLength - 3) + "...");
+ label.setTooltip(createPopup(parent, originalValue));
+ }
+
+ private static Popup createPopup(Div parent, String originalValue) {
+ Popup result = new Popup();
+ result.appendChild(new Label(originalValue));
+ parent.appendChild(result);
+ return result;
+ }
+}
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java
new file mode 100644
index 000000000..7a3257ec1
--- /dev/null
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesList.java
@@ -0,0 +1,134 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
+ * Desenvolvemento Tecnolóxico de Galicia
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package org.zkoss.ganttz.limitingresources;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
+import org.zkoss.ganttz.timetracker.TimeTracker;
+import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
+import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
+import org.zkoss.ganttz.util.MutableTreeModel;
+import org.zkoss.zk.au.out.AuInvoke;
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.HtmlMacroComponent;
+import org.zkoss.zk.ui.ext.AfterCompose;
+
+/**
+ * Component to include a list of ResourceLoads inside the ResourcesLoadPanel.
+ * @author Lorenzo Tilve Álvaro
+ */
+public class LimitingResourcesList extends HtmlMacroComponent implements
+ AfterCompose {
+
+ private final IZoomLevelChangedListener zoomListener;
+
+ private Map fromTimeLineToComponent = new HashMap();
+
+ private final MutableTreeModel timelinesTree;
+
+ public LimitingResourcesList(TimeTracker timeTracker,
+ MutableTreeModel timelinesTree) {
+ this.timelinesTree = timelinesTree;
+ zoomListener = adjustTimeTrackerSizeListener();
+ timeTracker.addZoomListener(zoomListener);
+ LoadTimeLine current = timelinesTree.getRoot();
+ List toInsert = new ArrayList();
+ fill(timelinesTree, current, toInsert);
+ insertAsComponents(timeTracker, toInsert);
+ }
+
+ private void fill(MutableTreeModel timelinesTree,
+ LoadTimeLine current, List result) {
+ final int length = timelinesTree.getChildCount(current);
+ for (int i = 0; i < length; i++) {
+ LoadTimeLine child = timelinesTree.getChild(current, i);
+ result.add(child);
+ fill(timelinesTree, child, result);
+ }
+ }
+
+ private IZoomLevelChangedListener adjustTimeTrackerSizeListener() {
+ return new IZoomLevelChangedListener() {
+
+ @Override
+ public void zoomLevelChanged(ZoomLevel detailLevel) {
+ response(null, new AuInvoke(LimitingResourcesList.this,
+ "adjustTimeTrackerSize"));
+ response(null, new AuInvoke(LimitingResourcesList.this,
+ "adjustResourceLoadRows"));
+ }
+ };
+ }
+
+ private void insertAsComponents(TimeTracker timetracker,
+ List children) {
+ for (LoadTimeLine loadTimeLine : children) {
+ LimitingResourcesComponent component = LimitingResourcesComponent
+ .create(
+ timetracker, loadTimeLine);
+ appendChild(component);
+ fromTimeLineToComponent.put(loadTimeLine, component);
+ }
+ }
+
+ public void collapse(LoadTimeLine line) {
+ for (LoadTimeLine l : line.getAllChildren()) {
+ getComponentFor(l).detach();
+ }
+ }
+
+ private LimitingResourcesComponent getComponentFor(LoadTimeLine l) {
+ LimitingResourcesComponent resourceLoadComponent = fromTimeLineToComponent
+ .get(l);
+ return resourceLoadComponent;
+ }
+
+ public void expand(LoadTimeLine line, List closed) {
+ LimitingResourcesComponent parentComponent = getComponentFor(line);
+ Component nextSibling = parentComponent.getNextSibling();
+
+ List childrenToOpen = getChildrenReverseOrderFor(line);
+ childrenToOpen.removeAll(closed);
+
+ for (LoadTimeLine loadTimeLine : childrenToOpen) {
+ LimitingResourcesComponent child = getComponentFor(loadTimeLine);
+ insertBefore(child, nextSibling);
+ nextSibling = child;
+ }
+
+ }
+
+ private List getChildrenReverseOrderFor(LoadTimeLine line) {
+ List childrenOf = line.getAllChildren();
+ Collections.reverse(childrenOf);
+ return childrenOf;
+ }
+
+ @Override
+ public void afterCompose() {
+ super.afterCompose();
+ }
+}
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java
new file mode 100644
index 000000000..6d3fb9ddb
--- /dev/null
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/limitingresources/LimitingResourcesPanel.java
@@ -0,0 +1,259 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
+ * Desenvolvemento Tecnolóxico de Galicia
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package org.zkoss.ganttz.limitingresources;
+
+import static org.zkoss.ganttz.i18n.I18nHelper._;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
+import org.zkoss.ganttz.resourceload.ScriptsRequiredByResourceLoadPanel;
+import org.zkoss.ganttz.timetracker.TimeTracker;
+import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
+import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
+import org.zkoss.ganttz.util.ComponentsFinder;
+import org.zkoss.ganttz.util.MutableTreeModel;
+import org.zkoss.ganttz.util.OnZKDesktopRegistry;
+import org.zkoss.ganttz.util.script.IScriptsRegister;
+import org.zkoss.zk.au.out.AuInvoke;
+import org.zkoss.zk.ui.Component;
+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.Events;
+import org.zkoss.zul.Button;
+import org.zkoss.zul.ListModel;
+import org.zkoss.zul.Separator;
+import org.zkoss.zul.SimpleListModel;
+import org.zkoss.zul.api.Listbox;
+
+public class LimitingResourcesPanel extends HtmlMacroComponent {
+
+ public interface IToolbarCommand {
+ public void doAction();
+
+ public String getLabel();
+
+ public String getImage();
+ }
+
+ private TimeTrackerComponent timeTrackerComponent;
+
+ private LimitingResourcesLeftPane leftPane;
+
+ private LimitingResourcesList limitingResourcesList;
+
+ private List groups;
+
+ private MutableTreeModel treeModel;
+
+ private TimeTracker timeTracker;
+
+ // private WeakReferencedListeners zoomListeners =
+ // WeakReferencedListeners.create();
+
+ private Listbox listZoomLevels;
+
+ private static final String filterResources = _("Filter by resources");
+ private static final String filterCriterions = _("Filter by criterions");
+ private boolean filterbyResources = true;
+
+ public LimitingResourcesPanel(List groups,
+ TimeTracker timeTracker) {
+ init(groups, timeTracker);
+
+ }
+
+ public void init(List groups, TimeTracker timeTracker) {
+ this.groups = groups;
+ this.timeTracker = timeTracker;
+ treeModel = createModelForTree();
+ timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
+ limitingResourcesList = new LimitingResourcesList(timeTracker,
+ treeModel);
+ leftPane = new LimitingResourcesLeftPane(treeModel,
+ limitingResourcesList);
+ registerNeededScripts();
+ }
+
+ public ListModel getFilters() {
+ String[] filters = new String[] { filterResources, filterCriterions };
+ return new SimpleListModel(filters);
+ }
+
+ public void setFilter(String filterby) {
+ if (filterby.equals(filterResources)) {
+ this.filterbyResources = true;
+ } else {
+ this.filterbyResources = false;
+ }
+ }
+
+ public boolean getFilter() {
+ return filterbyResources;
+ }
+
+ // public void onApplyFilter() {
+ // zoomListeners
+ // .fireEvent(new IListenerNotification() {
+ // @Override
+ // public void doNotify(IFilterChangedListener listener) {
+ // listener.filterChanged(getFilter());
+ // }
+ // });
+ // }
+ //
+ // public void addFilterListener(IFilterChangedListener listener) {
+ // zoomListeners.addListener(listener);
+ // }
+
+ public ListModel getZoomLevels() {
+ return new SimpleListModel(ZoomLevel.values());
+ }
+
+ public void setZoomLevel(final ZoomLevel zoomLevel) {
+ timeTracker.setZoomLevel(zoomLevel);
+ }
+
+ public void zoomIncrease() {
+ timeTracker.zoomIncrease();
+ }
+
+ public void zoomDecrease() {
+ timeTracker.zoomDecrease();
+ }
+
+ public void add(final IToolbarCommand... commands) {
+ Component toolbar = getToolbar();
+ Separator separator = getSeparator();
+ for (IToolbarCommand c : commands) {
+ toolbar.insertBefore(asButton(c), separator);
+ }
+ }
+
+ private Button asButton(final IToolbarCommand c) {
+ Button result = new Button();
+ result.addEventListener(Events.ON_CLICK, new EventListener() {
+ @Override
+ public void onEvent(Event event) throws Exception {
+ c.doAction();
+ }
+ });
+ if (!StringUtils.isEmpty(c.getImage())) {
+ result.setImage(c.getImage());
+ result.setTooltiptext(c.getLabel());
+ } else {
+ result.setLabel(c.getLabel());
+ }
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Separator getSeparator() {
+ List children = getToolbar().getChildren();
+ Separator separator = ComponentsFinder.findComponentsOfType(
+ Separator.class, children).get(0);
+ return separator;
+ }
+
+ private Component getToolbar() {
+ Component toolbar = getFellow("toolbar");
+ return toolbar;
+ }
+
+ private void registerNeededScripts() {
+ getScriptsRegister().register(ScriptsRequiredByResourceLoadPanel.class);
+ }
+
+ private IScriptsRegister getScriptsRegister() {
+ return OnZKDesktopRegistry.getLocatorFor(IScriptsRegister.class)
+ .retrieve();
+ }
+
+ private MutableTreeModel createModelForTree() {
+ MutableTreeModel result = MutableTreeModel
+ .create(LoadTimeLine.class);
+ for (LoadTimeLine loadTimeLine : this.groups) {
+ result.addToRoot(loadTimeLine);
+ result = addNodes(result, loadTimeLine);
+ }
+ return result;
+ }
+
+
+ private MutableTreeModel addNodes(
+ MutableTreeModel tree, LoadTimeLine parent) {
+ if (!parent.getChildren().isEmpty()) {
+ tree.add(parent, parent.getChildren());
+ for (LoadTimeLine loadTimeLine : parent.getChildren()) {
+ tree = addNodes(tree, loadTimeLine);
+ }
+ }
+ return tree;
+ }
+
+ private TimeTrackerComponent timeTrackerForResourcesLoadPanel(
+ TimeTracker timeTracker) {
+ return new TimeTrackerComponent(timeTracker) {
+ @Override
+ protected void scrollHorizontalPercentage(int pixelsDisplacement) {
+ response("", new AuInvoke(limitingResourcesList,
+ "adjustScrollHorizontalPosition", pixelsDisplacement
+ + ""));
+ }
+ };
+ }
+
+ @Override
+ public void afterCompose() {
+ super.afterCompose();
+
+ leftPane.afterCompose();
+
+ getFellow("insertionPointRightPanel").appendChild(timeTrackerComponent);
+ getFellow("insertionPointRightPanel").appendChild(limitingResourcesList);
+ TimeTrackerComponent timeTrackerHeader = createTimeTrackerHeader();
+ getFellow("insertionPointTimetracker").appendChild(timeTrackerHeader);
+
+ timeTrackerHeader.afterCompose();
+ timeTrackerComponent.afterCompose();
+ listZoomLevels = (Listbox) getFellow("listZoomLevels");
+ listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
+ }
+
+ public void clearComponents() {
+ getFellow("insertionPointLeftPanel").getChildren().clear();
+ getFellow("insertionPointRightPanel").getChildren().clear();
+ getFellow("insertionPointTimetracker").getChildren().clear();
+ }
+
+ private TimeTrackerComponent createTimeTrackerHeader() {
+ return new TimeTrackerComponent(
+ timeTracker) {
+
+ @Override
+ protected void scrollHorizontalPercentage(int pixelsDisplacement) {
+ }
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/ganttzk/src/main/resources/metainfo/zk/lang-addon.xml b/ganttzk/src/main/resources/metainfo/zk/lang-addon.xml
index db0359088..9bba07a50 100755
--- a/ganttzk/src/main/resources/metainfo/zk/lang-addon.xml
+++ b/ganttzk/src/main/resources/metainfo/zk/lang-addon.xml
@@ -48,6 +48,29 @@
~./ganttz/resourceload/leftPane.zul
+
+
+ LimitingResourcesPanel
+ org.zkoss.ganttz.limitingresources.LimitingResourcesPanel
+ ~./ganttz/zul/limitingResourcesLayout.zul
+
+
+
+ LimitingResourcesList
+ org.zkoss.ganttz.limitingresources.LimitingResourcesList
+
+ default
+ ~./ganttz/limitingresources/limitingresourceslist.dsp
+
+
+
+
+ LimitingResourcesLeftPane
+ org.zkoss.ganttz.limitingresources.LimitingResourcesLeftPane
+ ~./ganttz/limitingresources/leftPane.zul
+
+
+
leftPaneorg.zkoss.ganttz.LeftPane
@@ -79,6 +102,17 @@
+
+ limitingresources
+ org.zkoss.ganttz.limitingresources.LimitingResourcesComponent
+
+
+ default
+ ~./ganttz/limitingresources/limitingresources.dsp
+
+
+
+
taskRoworg.zkoss.ganttz.TaskRow
diff --git a/ganttzk/src/main/resources/web/ganttz/limitingresources/leftPane.zul b/ganttzk/src/main/resources/web/ganttz/limitingresources/leftPane.zul
new file mode 100644
index 000000000..2e06c5724
--- /dev/null
+++ b/ganttzk/src/main/resources/web/ganttz/limitingresources/leftPane.zul
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ganttzk/src/main/resources/web/ganttz/limitingresources/limitingresources.dsp b/ganttzk/src/main/resources/web/ganttz/limitingresources/limitingresources.dsp
new file mode 100644
index 000000000..907fd3f43
--- /dev/null
+++ b/ganttzk/src/main/resources/web/ganttz/limitingresources/limitingresources.dsp
@@ -0,0 +1,12 @@
+<%@ taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" %>
+<%@ taglib uri="http://www.zkoss.org/dsp/zk/core" prefix="z" %>
+
+
+