org.cruxframework.crux.widgets.client.timer.Timer.java Source code

Java tutorial

Introduction

Here is the source code for org.cruxframework.crux.widgets.client.timer.Timer.java

Source

/*
 * Copyright 2011 cruxframework.org.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.cruxframework.crux.widgets.client.timer;

import java.util.Date;

import org.cruxframework.crux.core.client.collection.FastList;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.widgets.client.WidgetMsgFactory;
import org.cruxframework.crux.widgets.client.event.timeout.HasTimeoutHandlers;
import org.cruxframework.crux.widgets.client.event.timeout.TimeoutEvent;
import org.cruxframework.crux.widgets.client.event.timeout.TimeoutHandler;

import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;

/**
 * A time counter capable of firing scheduled events.
 * @author Gesse S. F. Dafe
 */
public class Timer extends Composite implements HasTimeoutHandlers {
    public static final String DEFAULT_STYLE_NAME = "crux-Timer";
    public static final String DEFAULT_PATTERN = "HH:mm:ss";

    private final Label widget;
    private long initial;
    private long creationTime;
    private boolean regressive;
    private boolean allowChanges;
    private String pattern;
    private DateTimeFormat formatter;

    private boolean running = false;
    private long startTime = 0;
    private FastList<TimeouTask> events = new FastList<TimeouTask>();

    private TimeProcessor timeProcessor;

    /**
     * @param width
     * @param height
     * @param styleName
     */
    public Timer(long initial, boolean regressive, String pattern, boolean start) {
        this.initial = initial;
        this.creationTime = initial;
        this.regressive = regressive;
        this.pattern = pattern;

        if (StringUtils.isEmpty(this.pattern)) {
            this.formatter = DateTimeFormat.getFormat(DEFAULT_PATTERN);
        } else {
            this.formatter = DateTimeFormat.getFormat(this.pattern);
        }

        this.timeProcessor = new TimeProcessor(this);
        this.allowChanges = !start;

        widget = new Label();
        widget.setStyleName(DEFAULT_STYLE_NAME);
        widget.setText(format(initial));

        initWidget(widget);

        if (start) {
            start();
        }

        addAttachHandler(new Handler() {
            @Override
            public void onAttachOrDetach(AttachEvent event) {
                if (!event.isAttached()) {
                    stop();
                }
            }
        });
    }

    /**
     * @param amount
     * @return
     */
    @SuppressWarnings("deprecation")
    private String format(long amount) {
        Date when = new Date(0, 0, 1, 0, 0, 0);

        long secs = amount % 60;
        long mins = ((amount - secs) / 60) % 60;
        long hours = (amount - mins * 60 - secs) / (60 * 60);

        when.setHours((int) hours);
        when.setMinutes((int) mins);
        when.setSeconds((int) secs);

        return formatter.format(when);
    }

    /**
     * 
     */
    public void start() {
        if (!this.running) {
            this.startTime = (new Date()).getTime();
            this.running = true;
            timeProcessor.scheduleRepeating(500);
        }
    }

    /**
     * 
     */
    public void stop() {
        if (this.running) {
            this.running = false;
            this.timeProcessor.cancel();
            this.initial += ((new Date()).getTime() - this.startTime) / 1000;
            this.update();
        }
    }

    /**
     * 
     */
    public void reset() {
        stop();
        this.initial = creationTime;
        start();
    }

    /**
     * 
     */
    public void clear() {
        clear(false);
    }

    /**
     * 
     */
    public void clear(boolean reprocessTimeoutEvents) {
        stop();

        if (reprocessTimeoutEvents) {
            resetTimeoutEvents();
        }

        this.initial = creationTime;
        this.allowChanges = true;

        update();
    }

    /**
     * 
     */
    void update() {
        long diffTime = this.initial;

        if (this.running) {
            long delta = ((new Date()).getTime() - this.startTime) / 1000;

            if (this.regressive) {
                diffTime = diffTime - delta;
                diffTime = diffTime < 0 ? 0 : diffTime;
            } else {
                diffTime = diffTime + delta;
            }
        }

        this.widget.setText(this.format(diffTime));

        if (this.running) {
            this.checkForTimeoutEvents(diffTime);
        }
    }

    /**
     * @param currentCount
     */
    private void checkForTimeoutEvents(long currentCount) {
        if (this.events != null) {
            for (int i = 0; i < events.size(); i++) {
                TimeouTask task = events.get(i);
                if (!task.isProcessed()) {
                    if ((this.regressive && task.getTime() >= currentCount)
                            || (!this.regressive && task.getTime() <= currentCount)) {
                        task.setProcessed(true);
                        task.process(this);
                    }
                }
            }
        }
    }

    /**
     * @param currentCount
     */
    private void resetTimeoutEvents() {
        if (this.events != null) {
            for (int i = 0; i < events.size(); i++) {
                TimeouTask task = events.get(i);
                task.setProcessed(false);
            }
        }
    }

    /**
     * @see org.cruxframework.crux.widgets.client.event.timeout.HasTimeoutHandlers#addTimeoutHandler(org.cruxframework.crux.widgets.client.event.timeout.TimeoutHandler)
     */
    public HandlerRegistration addTimeoutHandler(TimeoutHandler handler) {
        TimeouTask task = new TimeouTask(handler);
        this.events.add(task);
        return addHandler(handler, TimeoutEvent.getType());
    }

    /**
     * @param initial the initial to set
     */
    public void setInitial(long initial) {
        if (!allowChanges) {
            throw new IllegalStateException(WidgetMsgFactory.getMessages().startedTimerCannotBeModified());
        } else {
            this.initial = initial;
        }
    }

    /**
     * @param regressive the regressive to set
     */
    public void setRegressive(boolean regressive) {
        if (!allowChanges) {
            throw new IllegalStateException(WidgetMsgFactory.getMessages().startedTimerCannotBeModified());
        } else {
            this.regressive = regressive;
        }
    }

    /**
     * @return the pattern
     */
    public String getPattern() {
        return pattern;
    }

    /**
     * @param pattern the pattern to set
     */
    public void setPattern(String pattern) {
        this.pattern = pattern;

        if (!StringUtils.isEmpty(this.pattern)) {
            this.formatter = DateTimeFormat.getFormat(this.pattern);
        } else {
            this.formatter = DateTimeFormat.getFormat(DEFAULT_PATTERN);
        }
    }
}

/**
 * TODO - Gesse - Comment this
 * @author Gesse S. F. Dafe
 */
class TimeProcessor extends com.google.gwt.user.client.Timer {
    private Timer timer;

    public TimeProcessor(Timer timer) {
        this.timer = timer;
    }

    @Override
    public void run() {
        this.timer.update();
    }
}

/**
 * TODO - Gesse - Comment this
 * @author Gesse S. F. Dafe
 */
class TimeouTask {
    private boolean processed;
    TimeoutHandler handler;

    /**
     * @param handler
     */
    public TimeouTask(TimeoutHandler handler) {
        this.handler = handler;
    }

    /**
     * @param timer
     */
    public void process(Timer timer) {
        handler.onTimeout(new TimeoutEvent(timer));
    }

    /**
     * @return the processed
     */
    public boolean isProcessed() {
        return processed;
    }

    /**
     * @param processed the processed to set
     */
    public void setProcessed(boolean processed) {
        this.processed = processed;
    }

    /**
     * @return the time
     */
    public long getTime() {
        return handler.getScheduledTime();
    }
}