Package org.libreplan.web.limitingresources

Source Code of org.libreplan.web.limitingresources.LimitingResourcesPanel$PaginatorFilter

/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
*                         Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* 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 <http://www.gnu.org/licenses/>.
*/

package org.libreplan.web.limitingresources;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.libreplan.business.planner.limiting.entities.LimitingResourceQueueElement;
import org.libreplan.business.resources.entities.LimitingResourceQueue;
import org.libreplan.web.common.Util;
import org.zkoss.ganttz.DependencyList;
import org.zkoss.ganttz.timetracker.TimeTracker;
import org.zkoss.ganttz.timetracker.TimeTracker.IDetailItemFilter;
import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
import org.zkoss.ganttz.timetracker.zoom.DetailItem;
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.ComponentsFinder;
import org.zkoss.ganttz.util.Interval;
import org.zkoss.ganttz.util.MutableTreeModel;
import org.zkoss.zk.au.AuRequest;
import org.zkoss.zk.au.AuService;
import org.zkoss.zk.au.out.AuInvoke;
import org.zkoss.zk.mesg.MZk;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.UiException;
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.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Separator;
import org.zkoss.zul.SimpleListModel;

public class LimitingResourcesPanel extends HtmlMacroComponent {

    public interface IToolbarCommand {
        public void doAction();

        public String getLabel();

        public String getImage();
    }

    private LimitingResourcesController limitingResourcesController;

    private TimeTracker timeTracker;

    private TimeTrackerComponent timeTrackerComponent;

    private TimeTrackerComponent timeTrackerHeader;

    private LimitingResourcesLeftPane leftPane;

    private QueueListComponent queueListComponent;

    private MutableTreeModel<LimitingResourceQueue> treeModel;

    private Listbox listZoomLevels;

    private Button paginationDownButton;

    private Button paginationUpButton;

    private Listbox horizontalPagination;

    private LimitingDependencyList dependencyList = new LimitingDependencyList(
            this);

    private PaginatorFilter paginatorFilter;

    private Component insertionPointLeftPanel;
    private Component insertionPointRightPanel;
    private Component insertionPointTimetracker;

    private LocalDate previousStart;
    private Interval previousInterval;

    public void paginationDown() {
        horizontalPagination.setSelectedIndex(horizontalPagination
                .getSelectedIndex() - 1);
        goToSelectedHorizontalPage();
    }

    public void paginationUp() {
        horizontalPagination.setSelectedIndex(Math.max(1, horizontalPagination
                .getSelectedIndex() + 1));
        goToSelectedHorizontalPage();
    }

    /**
     * Returns the closest upper {@link LimitingResourcesPanel} instance going
     * all the way up from comp
     *
     * @param comp
     * @return
     */
    public static LimitingResourcesPanel getLimitingResourcesPanel(
            Component comp) {
        if (comp == null) {
            return null;
        }
        if (comp instanceof LimitingResourcesPanel) {
            return (LimitingResourcesPanel) comp;
        }
        return getLimitingResourcesPanel(comp.getParent());
    }

    public LimitingResourcesPanel(
            LimitingResourcesController limitingResourcesController,
            TimeTracker timeTracker) {
        init(limitingResourcesController, timeTracker);
    }

    public void init(LimitingResourcesController limitingResourcesController,
            TimeTracker timeTracker) {
        this.limitingResourcesController = limitingResourcesController;
        this.timeTracker = timeTracker;
        this.setVariable("limitingResourcesController",
                limitingResourcesController, true);

        treeModel = createModelForTree();

        queueListComponent = new QueueListComponent(this, timeTracker,
                treeModel);

        leftPane = new LimitingResourcesLeftPane(treeModel);

        setAuService(new AuService(){
            public boolean service(AuRequest request, boolean everError){
                String command = request.getCommand();
                int zoomindex;
                int scrollLeft;

                if (command.equals("onZoomLevelChange")){
                    zoomindex=  (Integer) retrieveData(request, "zoomindex");
                    scrollLeft = (Integer) retrieveData(request, "scrollLeft");

                    setZoomLevel((ZoomLevel)((Listbox)getFellow("listZoomLevels"))
                            .getModel().getElementAt(zoomindex),
                            scrollLeft);
                    return true;
                }
                return false;
            }

            private Object retrieveData(AuRequest request, String key){
                Object value = request.getData().get(key);
                if ( value == null)
                    throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA,
                            new Object[] { key, this });

                return value;
            }
        });
    }

    public void setZoomLevel(ZoomLevel zoomLevel, int scrollLeft) {
        savePreviousData();
        getTimeTrackerComponent().updateDayScroll();
        getTimeTrackerComponent().setZoomLevel(zoomLevel, scrollLeft);
    }

    public void appendQueueElementToQueue(LimitingResourceQueueElement element) {
        queueListComponent.appendQueueElement(element);
        dependencyList.addDependenciesFor(element);
    }

    public void removeQueueElementFrom(LimitingResourceQueue queue, LimitingResourceQueueElement element) {
        queueListComponent.removeQueueElementFrom(queue, element);
        dependencyList.removeDependenciesFor(element);
    }

    private MutableTreeModel<LimitingResourceQueue> createModelForTree() {
        MutableTreeModel<LimitingResourceQueue> result = MutableTreeModel
                .create(LimitingResourceQueue.class);
        for (LimitingResourceQueue LimitingResourceQueue : getLimitingResourceQueues()) {
            result.addToRoot(LimitingResourceQueue);
        }
        return result;
    }

    private List<LimitingResourceQueue> getLimitingResourceQueues() {
        return limitingResourcesController.getLimitingResourceQueues();
    }

    public ListModel getZoomLevels() {
        ZoomLevel[] selectableZoomlevels = { ZoomLevel.DETAIL_THREE,
                ZoomLevel.DETAIL_FOUR, ZoomLevel.DETAIL_FIVE,
                ZoomLevel.DETAIL_SIX };
        return new SimpleListModel(selectableZoomlevels);
    }

    public void setZoomLevel(final ZoomLevel zoomLevel) {
        savePreviousData();
        getTimeTrackerComponent().updateDayScroll();
        timeTracker.setZoomLevel(zoomLevel);
    }

    public void zoomIncrease() {
        savePreviousData();
        getTimeTrackerComponent().updateDayScroll();
        timeTracker.zoomIncrease();
    }

    public void zoomDecrease() {
        savePreviousData();
        getTimeTrackerComponent().updateDayScroll();
        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) {
                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<Component> children = getToolbar().getChildren();
        Separator separator = ComponentsFinder.findComponentsOfType(
                Separator.class, children).get(0);
        return separator;
    }

    private Component getToolbar() {
        Component toolbar = getFellow("toolbar");
        return toolbar;
    }

    private TimeTrackerComponent timeTrackerForLimitingResourcesPanel(
            TimeTracker timeTracker) {
        return new TimeTrackerComponent(timeTracker) {
            @Override
            protected void scrollHorizontalPercentage(int daysDisplacement) {
                response("", new AuInvoke(queueListComponent,
                        "scroll_horizontal", daysDisplacement + ""));
                moveCurrentPositionScroll();
            }

            @Override
            protected void moveCurrentPositionScroll() {
                // get the previous data.
                LocalDate previousStart = getPreviousStart();

                // get the current data
                int diffDays = getTimeTrackerComponent().getDiffDays(
                        previousStart);
                double pixelPerDay = getTimeTrackerComponent().getPixelPerDay();

                response("move_scroll", new AuInvoke(queueListComponent,
                        "move_scroll", "" + diffDays, "" + pixelPerDay));
            }

            @Override
            protected void updateCurrentDayScroll() {
                System.out.println("updateCurrentDayScroll");
                double previousPixelPerDay = getTimeTracker().getMapper()
                        .getPixelsPerDay().doubleValue();

                response("update_day_scroll", new AuInvoke(queueListComponent,
                        "update_day_scroll", "" + previousPixelPerDay));

            }
        };
    }

    @Override
    public void afterCompose() {

        super.afterCompose();

        initializeBindings();
        initializeTimetracker();

        listZoomLevels
                .setSelectedIndex(timeTracker.getDetailLevel().ordinal() - 2);

        // Insert leftPane component with limitingresources list
        insertionPointLeftPanel.appendChild(leftPane);
        leftPane.afterCompose();

        // Initialize queues
        insertionPointRightPanel.appendChild(queueListComponent);
        queueListComponent.afterCompose();

        // Initialize dependencies
        rebuildDependencies();
        dependencyList.afterCompose();

        initializePagination();
    }

    /**
     * Apparently it's necessary to append {@link DependencyList} to
     * insertionPointRightPanel again every time the list of dependencies is
     * regenerated. Otherwise tasks overflow if they don't fit in current page
     *
     */
    private void rebuildDependencies() {
        dependencyList.clear();
        for (LimitingResourceQueueElement each : getLimitingResourceQueueElements()) {
            dependencyList.addDependenciesFor(each);
        }
        insertionPointRightPanel.appendChild(dependencyList);
    }

    private Set<LimitingResourceQueueElement> getLimitingResourceQueueElements() {
        return queueListComponent.getLimitingResourceElementToQueueTaskMap()
                .keySet();
    }

    private void initializeTimetracker() {
        timeTracker.addZoomListener(new IZoomLevelChangedListener() {
            @Override
            public void zoomLevelChanged(ZoomLevel newDetailLevel) {
                reloadTimetracker();
                reloadComponent();
            }

            private void reloadTimetracker() {
                timeTracker.resetMapper();
                paginatorFilter.setInterval(timeTracker.getRealInterval());
                timeTracker.setFilter(paginatorFilter);
                paginatorFilter.populateHorizontalListbox();
                paginatorFilter.goToHorizontalPage(0);
                adjustZoomPositionScroll();
            }

        });
        timeTrackerHeader = createTimeTrackerHeader();
        timeTrackerComponent = createTimeTrackerComponent();
        insertionPointTimetracker.appendChild(timeTrackerHeader);
        insertionPointRightPanel.appendChild(timeTrackerComponent);
        timeTrackerHeader.afterCompose();
        timeTrackerComponent.afterCompose();
    }

    @SuppressWarnings("serial")
    private TimeTrackerComponent createTimeTrackerHeader() {
        return new TimeTrackerComponent(timeTracker) {

            @Override
            protected void scrollHorizontalPercentage(int pixelsDisplacement) {

            }

            @Override
            protected void moveCurrentPositionScroll() {
                // TODO Auto-generated method stub
            }

            @Override
            protected void updateCurrentDayScroll() {
                // TODO Auto-generated method stub
            }
        };
    }

    private void adjustZoomPositionScroll() {
        getTimeTrackerComponent().movePositionScroll();
    }

    @SuppressWarnings("serial")
    private TimeTrackerComponent createTimeTrackerComponent() {
        return new TimeTrackerComponent(timeTracker) {
            @Override
            protected void scrollHorizontalPercentage(int pixelsDisplacement) {
                response("", new AuInvoke(queueListComponent,
                        "adjustScrollHorizontalPosition", pixelsDisplacement
                                + ""));
            }

            @Override
            protected void moveCurrentPositionScroll() {
                // TODO Auto-generated method stub
            }

            @Override
            protected void updateCurrentDayScroll() {
                // TODO Auto-generated method stub
            }
        };
    }

    private void initializePagination() {
        paginatorFilter = new PaginatorFilter();
        paginationUpButton.setDisabled(paginatorFilter.isLastPage());
        paginatorFilter.setInterval(timeTracker.getRealInterval());
        timeTracker.setFilter(paginatorFilter);
        paginatorFilter.populateHorizontalListbox();
    }

    private void initializeBindings() {

        // Zoom and pagination
        listZoomLevels = (Listbox) getFellow("listZoomLevels");
        horizontalPagination = (Listbox) getFellow("horizontalPagination");
        paginationUpButton = (Button) getFellow("paginationUpButton");
        paginationDownButton = (Button) getFellow("paginationDownButton");

        insertionPointLeftPanel = getFellow("insertionPointLeftPanel");
        insertionPointRightPanel = getFellow("insertionPointRightPanel");
        insertionPointTimetracker = getFellow("insertionPointTimetracker");
    }

    public Map<LimitingResourceQueueElement, QueueTask> getQueueTaskMap() {
        return queueListComponent.getLimitingResourceElementToQueueTaskMap();
    }

    public void clearComponents() {
        getFellow("insertionPointLeftPanel").getChildren().clear();
        getFellow("insertionPointRightPanel").getChildren().clear();
        getFellow("insertionPointTimetracker").getChildren().clear();
    }

    public TimeTrackerComponent getTimeTrackerComponent() {
        return timeTrackerComponent;
    }

    public TimeTracker getTimeTracker() {
        return timeTrackerComponent.getTimeTracker();
    }

    public void unschedule(QueueTask task) {
        LimitingResourceQueueElement queueElement = task.getLimitingResourceQueueElement();
        LimitingResourceQueue queue = queueElement.getLimitingResourceQueue();

        limitingResourcesController.unschedule(task);
        removeQueueTask(task);
        dependencyList.removeDependenciesFor(queueElement);
        queueListComponent.removeQueueElementFrom(queue, queueElement);
    }

    private void removeQueueTask(QueueTask task) {
        task.detach();
    }

    public void moveQueueTask(QueueTask queueTask) {
        if (limitingResourcesController.moveTask(queueTask.getLimitingResourceQueueElement())) {
            removeQueueTask(queueTask);
        }
    }

    public void editResourceAllocation(QueueTask queueTask) {
        limitingResourcesController.editResourceAllocation(queueTask
                .getLimitingResourceQueueElement());
    }

    public void removeDependenciesFor(LimitingResourceQueueElement element) {
        dependencyList.removeDependenciesFor(element);
    }

    public void addDependenciesFor(LimitingResourceQueueElement element) {
        dependencyList.addDependenciesFor(element);
    }

    public void refreshQueues(Collection<LimitingResourceQueue> queues) {
        for (LimitingResourceQueue each: queues) {
            refreshQueue(each);
        }
    }

    public void refreshQueue(LimitingResourceQueue queue) {
        dependencyList.removeDependenciesFor(queue);
        queueListComponent.refreshQueue(queue);
    }

    public void goToSelectedHorizontalPage() {
        paginatorFilter.goToHorizontalPage(horizontalPagination
                .getSelectedIndex());
        reloadComponent();
    }

    public void reloadComponent() {
        refreshTimetracker();
        refreshQueueComponents();
        rebuildDependencies();
    }

    private void refreshTimetracker() {
        timeTrackerHeader.recreate();
        timeTrackerComponent.recreate();
    }

    private void refreshQueueComponents() {
        queueListComponent.invalidate();
        queueListComponent.afterCompose();
        queueListComponent.refreshQueues();
        rebuildDependencies();
    }

    private class PaginatorFilter implements IDetailItemFilter {

        private DateTime intervalStart;
        private DateTime intervalEnd;

        private DateTime paginatorStart;
        private DateTime paginatorEnd;

        @Override
        public Interval getCurrentPaginationInterval() {
            return new Interval(paginatorStart.toDate(), paginatorEnd.toDate());
        }

        private Period intervalIncrease() {
            switch (timeTracker.getDetailLevel()) {
            case DETAIL_ONE:
                return Period.years(5);
            case DETAIL_TWO:
                return Period.years(5);
            case DETAIL_THREE:
                return Period.years(2);
            case DETAIL_FOUR:
                return Period.months(12);
            case DETAIL_FIVE:
                return Period.weeks(12);
            case DETAIL_SIX:
                return Period.weeks(12);
            }
            // Default month
            return Period.years(2);
        }

        public void setInterval(Interval realInterval) {
            intervalStart = realInterval.getStart().toDateTimeAtStartOfDay();
            intervalEnd = realInterval.getFinish().toDateTimeAtStartOfDay();
            paginatorStart = intervalStart;
            paginatorEnd = intervalStart.plus(intervalIncrease());
            if ((paginatorEnd.plus(intervalIncrease()).isAfter(intervalEnd))) {
                paginatorEnd = intervalEnd;
            }
            updatePaginationButtons();
            dependencyList.recreateDependencyComponents();
        }

        @Override
        public void resetInterval() {
            setInterval(timeTracker.getRealInterval());
        }

        @Override
        public Collection<DetailItem> selectsFirstLevel(
                Collection<DetailItem> firstLevelDetails) {
            ArrayList<DetailItem> result = new ArrayList<DetailItem>();
            for (DetailItem each : firstLevelDetails) {
                if ((each.getStartDate() == null)
                        || !(each.getStartDate().isBefore(paginatorStart))
                        && (each.getStartDate().isBefore(paginatorEnd))) {
                    result.add(each);
                }
            }
            return result;
        }

        @Override
        public Collection<DetailItem> selectsSecondLevel(
                Collection<DetailItem> secondLevelDetails) {
            ArrayList<DetailItem> result = new ArrayList<DetailItem>();
            for (DetailItem each : secondLevelDetails) {
                if ((each.getStartDate() == null)
                        || !(each.getStartDate().isBefore(paginatorStart))
                        && (each.getStartDate().isBefore(paginatorEnd))) {
                    result.add(each);
                }
            }
            return result;
        }

        public void populateHorizontalListbox() {
            horizontalPagination.getItems().clear();
            DateTime intervalStart = timeTracker.getRealInterval().getStart()
                    .toDateTimeAtStartOfDay();
            if (intervalStart != null) {
                DateTime itemStart = intervalStart;
                DateTime itemEnd = intervalStart.plus(intervalIncrease());
                while (intervalEnd.isAfter(itemStart)) {
                    if (intervalEnd.isBefore(itemEnd)
                            || !intervalEnd.isAfter(itemEnd
                                    .plus(intervalIncrease()))) {
                        itemEnd = intervalEnd;
                    }
                    Listitem item = new Listitem(Util.formatDate(itemStart)
                            + " - " + Util.formatDate(itemEnd.minusDays(1)));
                    horizontalPagination.appendChild(item);
                    itemStart = itemEnd;
                    itemEnd = itemEnd.plus(intervalIncrease());
                }
            }
            horizontalPagination.setSelectedIndex(0);

            // Disable pagination if there's only one page
            int size = horizontalPagination.getItems().size();
            horizontalPagination.setDisabled(size == 1);
        }

        public void goToHorizontalPage(int interval) {
            paginatorStart = intervalStart;
            paginatorStart = timeTracker.getDetailsFirstLevel().iterator()
                    .next().getStartDate();

            for (int i = 0; i < interval; i++) {
                paginatorStart = paginatorStart.plus(intervalIncrease());
            }
            paginatorEnd = paginatorStart.plus(intervalIncrease());
            if ((paginatorEnd.plus(intervalIncrease()).isAfter(intervalEnd))) {
                paginatorEnd = paginatorEnd.plus(intervalIncrease());
            }
            timeTracker.resetMapper();
            updatePaginationButtons();
        }

        private void updatePaginationButtons() {
            paginationDownButton.setDisabled(isFirstPage());
            paginationUpButton.setDisabled(isLastPage());
        }

        public boolean isFirstPage() {
            return (horizontalPagination.getSelectedIndex() <= 0)
                    || horizontalPagination.isDisabled();
        }

        private boolean isLastPage() {
            return (horizontalPagination.getItemCount() == (horizontalPagination
                    .getSelectedIndex() + 1))
                    || horizontalPagination.isDisabled();
        }
    }

    private void savePreviousData() {
        TimeTracker timeTracker = getTimeTrackerComponent().getTimeTracker();
        this.previousStart = timeTracker.getRealInterval().getStart();
        this.previousInterval = timeTracker.getMapper().getInterval();
    }

    public LocalDate getPreviousStart() {
        return previousStart;
    }

    public Interval getPreviousInterval() {
        return previousInterval;
    }

    public String getWidgetClass() {
        return "limitingresources.LimitingResourcesPanel";
    }
}
TOP

Related Classes of org.libreplan.web.limitingresources.LimitingResourcesPanel$PaginatorFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.