Package org.zkoss.ganttz.timetracker

Source Code of org.zkoss.ganttz.timetracker.TimeTracker

/*
* 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.zkoss.ganttz.timetracker;

import static org.zkoss.ganttz.i18n.I18nHelper._;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Date;

import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.zkoss.ganttz.DatesMapperOnInterval;
import org.zkoss.ganttz.IDatesMapper;
import org.zkoss.ganttz.data.Task;
import org.zkoss.ganttz.timetracker.zoom.DetailItem;
import org.zkoss.ganttz.timetracker.zoom.IDetailItemModificator;
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
import org.zkoss.ganttz.timetracker.zoom.SeveralModificators;
import org.zkoss.ganttz.timetracker.zoom.TimeTrackerState;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.ganttz.util.Interval;
import org.zkoss.ganttz.util.LongOperationFeedback;
import org.zkoss.ganttz.util.WeakReferencedListeners;
import org.zkoss.ganttz.util.LongOperationFeedback.ILongOperation;
import org.zkoss.ganttz.util.WeakReferencedListeners.IListenerNotification;
import org.zkoss.zk.ui.Component;

public class TimeTracker {

    public interface IDetailItemFilter {

        public Collection<DetailItem> selectsFirstLevel(
                Collection<DetailItem> firstLevelDetails);

        public Collection<DetailItem> selectsSecondLevel(
                Collection<DetailItem> secondLevelDetails);

        public Interval getCurrentPaginationInterval();

        public void resetInterval();

    }

    private ZoomLevel detailLevel = ZoomLevel.DETAIL_ONE;

    private WeakReferencedListeners<IZoomLevelChangedListener> zoomListeners = WeakReferencedListeners
            .create();

    private IDatesMapper datesMapper = null;

    private Collection<DetailItem> detailsFirstLevelCached = null;

    private Collection<DetailItem> detailsSecondLevelCached = null;

    private Interval interval;

    private final IDetailItemModificator firstLevelModificator;

    private final IDetailItemModificator secondLevelModificator;

    private final Component componentOnWhichGiveFeedback;

    private boolean registeredFirstTask = false;

    private IDetailItemFilter filter = null;

    public IDetailItemFilter getFilter() {
        return filter;
    }

    public TimeTracker(Interval interval, ZoomLevel zoomLevel, Component parent) {
        this(interval, zoomLevel, SeveralModificators.empty(),
                SeveralModificators.empty(), parent);
    }

    public TimeTracker(Interval interval, Component componentOnWhichGiveFeedback) {
        this(interval, SeveralModificators.empty(),
                SeveralModificators.empty(), componentOnWhichGiveFeedback);
    }

    public TimeTracker(Interval interval,
            IDetailItemModificator firstLevelModificator,
            IDetailItemModificator secondLevelModificator,
            Component componentOnWhichGiveFeedback) {
        Validate.notNull(interval);
        Validate.notNull(firstLevelModificator);
        Validate.notNull(secondLevelModificator);
        Validate.notNull(componentOnWhichGiveFeedback);
        this.interval = interval;
        this.firstLevelModificator = firstLevelModificator;
        this.secondLevelModificator = secondLevelModificator;
        this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
    }

    public TimeTracker(Interval interval, ZoomLevel zoomLevel,
            IDetailItemModificator firstLevelModificator,
            IDetailItemModificator secondLevelModificator,
            Component componentOnWhichGiveFeedback) {
        this(interval, firstLevelModificator, secondLevelModificator,
                componentOnWhichGiveFeedback);
        detailLevel = zoomLevel;
    }

    public void setFilter(IDetailItemFilter filter) {
        this.filter = filter;
        datesMapper = null;
    }

    public ZoomLevel getDetailLevel() {
        return detailLevel;
    }

    public void addZoomListener(IZoomLevelChangedListener listener) {
        zoomListeners.addListener(listener);
    }

    public Collection<DetailItem> getDetailsFirstLevel() {
        if (detailsFirstLevelCached == null) {
            detailsFirstLevelCached = getTimeTrackerState()
                    .getFirstLevelDetails(interval);
        }
        return filterFirstLevel(detailsFirstLevelCached);
    }

    private Collection<DetailItem> filterFirstLevel(
            Collection<DetailItem> firstLevelDetails) {
        if (filter == null) {
            return firstLevelDetails;
        }
        return filter.selectsFirstLevel(firstLevelDetails);
    }

    public Collection<DetailItem> getDetailsSecondLevel() {
        if (detailsSecondLevelCached == null) {
            detailsSecondLevelCached = getTimeTrackerState()
                    .getSecondLevelDetails(interval);
        }
        return filterSecondLevel(detailsSecondLevelCached);
    }

    private Collection<DetailItem> filterSecondLevel(
            Collection<DetailItem> secondLevelDetails) {
        if (filter == null) {
            return secondLevelDetails;
        }
        return filter.selectsSecondLevel(secondLevelDetails);
    }

    private Interval realIntervalCached;

    public Interval getRealInterval() {
        if (realIntervalCached == null) {
            realIntervalCached = getTimeTrackerState().getRealIntervalFor(
                    interval);
        }
        return realIntervalCached;
    }

    public TimeTrackerState getTimeTrackerState() {
        return detailLevel.getTimeTrackerState(firstLevelModificator,
                secondLevelModificator);
    }

    private void fireZoomChanged() {
        zoomListeners
                .fireEvent(new IListenerNotification<IZoomLevelChangedListener>() {
                    @Override
                    public void doNotify(IZoomLevelChangedListener listener) {
                        listener.zoomLevelChanged(detailLevel);
                    }
                });
    }

    public int getHorizontalSize() {
        int horizontalSize = 0;
        for (DetailItem detailItem : getDetailsSecondLevel()) {
            horizontalSize += detailItem.getSize();
        }
        return horizontalSize;
    }

    private void clearDetailLevelDependantData() {
        datesMapper = null;
        detailsFirstLevelCached = detailsSecondLevelCached = null;
        realIntervalCached = null;
    }

    public void resetMapper() {
        datesMapper = null;
        realIntervalCached = null;
    }

    public IDatesMapper getMapper() {
        if (datesMapper == null) {
            if (filter == null) {
                datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
                        getRealInterval());
            } else {
                datesMapper = new DatesMapperOnInterval(getHorizontalSize(),
                        filter.getCurrentPaginationInterval());
            }
        }
        return datesMapper;
    }

    public void zoomIncrease() {
        detailLevel = detailLevel.next();
        invalidatingChangeHappenedWithFeedback();
    }

    private void invalidatingChangeHappenedWithFeedback() {
        LongOperationFeedback.execute(componentOnWhichGiveFeedback,
                new ILongOperation() {

                    @Override
                    public void doAction() {
                        invalidatingChangeHappened();
                    }

                    @Override
                    public String getName() {
                        return _("changing zoom");
                    }
                });
    }

    public void setZoomLevel(ZoomLevel zoomLevel) {
        detailLevel = zoomLevel;
        invalidatingChangeHappenedWithFeedback();
    }

    private void invalidatingChangeHappened() {
        clearDetailLevelDependantData();
        fireZoomChanged();
    }

    public void zoomDecrease() {
        detailLevel = detailLevel.previous();
        invalidatingChangeHappenedWithFeedback();
    }

    public void trackPosition(final Task task) {
        task
                .addFundamentalPropertiesChangeListener(new PropertyChangeListener() {

                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        updateIntervalIfNeeded(task);
                    }
                });
        updateIntervalIfNeeded(task);
    }

    private void updateIntervalIfNeeded(Task task) {
        if (registeredFirstTask == false) {
            registeredFirstTask = true;
            interval = new Interval(startMinusTwoWeeks(task),
                    endPlusOneMonth(task));
            invalidatingChangeHappened();
        } else {
            LocalDate newStart = interval.getStart();
            LocalDate newFinish = interval.getFinish();

            boolean changed = false;
            if (interval.getStart().compareTo(startMinusTwoWeeks(task)) > 0) {
                newStart = startMinusTwoWeeks(task);
                changed = true;
            }

            if (interval.getFinish()
                    .compareTo(endPlusOneMonth(task)) < 0) {
                newFinish = endPlusOneMonth(task);
                changed = true;
            }

            if (changed) {
                interval = new Interval(newStart, newFinish);
                invalidatingChangeHappened();
            }
        }
    }

    private Date max(Date date1, Date date2) {
        if (date1 == null) {
            return date2;
        }
        if (date2 == null) {
            return date1;
        }
        return date1.compareTo(date2) > 0 ? date1 : date2;
    }

    private Date min(Date date1, Date date2) {
        if (date1 == null) {
            return date2;
        }
        if (date2 == null) {
            return date1;
        }
        return date1.compareTo(date2) <= 0 ? date1 : date2;
    }

    private LocalDate endPlusOneMonth(Task task) {
        Date taskEnd = max(task.getEndDate().toDayRoundedDate(),
                task.getDeadline());
        return new LocalDate(taskEnd).plusMonths(1);
    }

    private LocalDate startMinusTwoWeeks(Task task) {
        // the deadline could be before the start
        Date start = min(task.getBeginDate().toDayRoundedDate(),
                task.getDeadline());
        // the last consolidated value could be before the start
        if (task.getConsolidatedline() != null) {
            start = min(start, task.getConsolidatedline().toDayRoundedDate());
        }
        return new LocalDate(start).minusWeeks(2);
    }

}
TOP

Related Classes of org.zkoss.ganttz.timetracker.TimeTracker

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.