/src/main/java/org/mbari/dss/client/views/PlaybackView.java
Java | 647 lines | 483 code | 97 blank | 67 comment | 34 complexity | fd2c05c39241445495342a9a15e16cbd MD5 | raw file
- /*
- * @(#)PlaybackView.java
- *
- * Copyright 2011 MBARI
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- package org.mbari.dss.client.views;
- //~--- non-JDK imports --------------------------------------------------------
- import com.allen_sauer.gwt.log.client.Log;
- import com.google.gwt.user.client.Timer;
- import com.google.gwt.user.client.ui.Widget;
- import com.smartgwt.client.data.DateRange;
- import com.smartgwt.client.types.Alignment;
- import com.smartgwt.client.widgets.IButton;
- import com.smartgwt.client.widgets.Label;
- import com.smartgwt.client.widgets.Progressbar;
- import com.smartgwt.client.widgets.Slider;
- import com.smartgwt.client.widgets.events.ClickEvent;
- import com.smartgwt.client.widgets.events.ClickHandler;
- import com.smartgwt.client.widgets.events.ValueChangedEvent;
- import com.smartgwt.client.widgets.events.ValueChangedHandler;
- import com.smartgwt.client.widgets.form.DynamicForm;
- import com.smartgwt.client.widgets.form.fields.DateItem;
- import com.smartgwt.client.widgets.form.fields.TimeItem;
- import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
- import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
- import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
- import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
- import com.smartgwt.client.widgets.layout.HLayout;
- import com.smartgwt.client.widgets.layout.VLayout;
- import org.mbari.dss.client.data.DataUtil;
- import org.mbari.dss.client.data.DssTimer;
- import org.mbari.dss.client.events.EventFirer;
- import org.mbari.dss.client.events.PlaybackTimerEvent;
- //~--- JDK imports ------------------------------------------------------------
- import java.util.Date;
- /**
- * To playback the specified date range of platform tracks
- *
- * For some ideas on animation playback in OL, see
- * http://osgeo-org.1803224.n2.nabble.com/Has-anyone-tried-animation-or-how-to-td1829343.html
- *
- * @author dcline
- */
- public class PlaybackView implements DssView {
- private int frameDelaySecs = 10;
- private int progressDelayMSec = 0;
- private PlaybackTimer timer = new PlaybackTimer();
- private State state = State.LOAD_STOP;
- private SliderDateLabel startSliderLabel = new SliderDateLabel();
- private SliderDateLabel endSliderLabel = new SliderDateLabel();
- private PlaybackDateLabel currentDateLabel = new PlaybackDateLabel();
- private int updateMin = 60; // 1 hour
- private DateRange selectedRange = new DateRange();
- private DateRange playbackRange = new DateRange();
- private DateRange loadedRange = new DateRange();
- private final Slider endSlider, startSlider;
- private FrameDelaySelectItem frameDelaySelect;
- private final IButton playBtn, loadBtn, resetBtn;
- private final Progressbar progressBar;
- private Label progressBarLabel;
- private Timer progressBarTimer;
- private int progressBarValue;
- private CustomSelectItem updateSelect;
- private final VLayout vLayout;
- public enum State { LOAD_STOP, LOAD_START, LOAD_FINI }
- public PlaybackView() {
- progressBar = new Progressbar();
- progressBar.setHeight(24);
- progressBar.setWidth(150);
- progressBar.setVertical(false);
- progressBarTimer = _createProgressBarTimer();
- progressBarLabel = new Label("Current Loading Progress:");
- progressBarLabel.setHeight(16);
- endSlider = new DateSlider("End Date");
- startSlider = new DateSlider("Start Date");
- startSlider.addValueChangedHandler(new ValueChangedHandler() {
- public void onValueChanged(ValueChangedEvent event) {
- int timeStepMinutes = event.getValue();
- long totalSeconds = loadedRange.getStartDate().getTime() + ((long) timeStepMinutes) * 60000L;
- Date startDate = new Date(totalSeconds);
- startSliderLabel._formatLabel(new Date(totalSeconds).toString());
- timeStepMinutes = (int) endSlider.getValue();
- totalSeconds = loadedRange.getStartDate().getTime() + ((long) timeStepMinutes) * 60000L;
- Date endDate = new Date(totalSeconds);
- playbackRange.setStartDate(startDate);
- playbackRange.setEndDate(endDate);
- if (state == State.LOAD_FINI) {
- EventFirer.fireEvent(new PlaybackTimerEvent(playbackRange,
- PlaybackTimerEvent.Event.PLAYBACK_RANGE_CHANGED));
- }
- }
- });
- endSlider.addValueChangedHandler(new ValueChangedHandler() {
- public void onValueChanged(ValueChangedEvent event) {
- int timeStepMinutes = event.getValue();
- long totalSeconds = loadedRange.getStartDate().getTime() + ((long) timeStepMinutes) * 60000L;
- Date endDate = new Date(totalSeconds);
- endSliderLabel._formatLabel(new Date(totalSeconds).toString());
- timeStepMinutes = (int) startSlider.getValue();
- totalSeconds = loadedRange.getStartDate().getTime() + ((long) timeStepMinutes) * 60000L;
- Date startDate = new Date(totalSeconds);
- playbackRange.setStartDate(startDate);
- playbackRange.setEndDate(endDate);
- if (state == State.LOAD_FINI) {
- EventFirer.fireEvent(new PlaybackTimerEvent(playbackRange,
- PlaybackTimerEvent.Event.PLAYBACK_RANGE_CHANGED));
- }
- }
- });
- selectedRange = DataUtil.getInitialDateRange();
- playbackRange.setStartDate(new Date(selectedRange.getStartDate().getTime()));
- playbackRange.setEndDate(new Date(selectedRange.getEndDate().getTime()));
- loadedRange.setStartDate(new Date(selectedRange.getStartDate().getTime()));
- loadedRange.setEndDate(new Date(selectedRange.getEndDate().getTime()));
-
- // TODO: implement client-side to parse out PDT/PST from
- // date since the 3-letter format isn't support in the GWT toolkit
- String timezone = "PDT";
- DateItem startDateItem = new DateItem();
- startDateItem.setName("Start");
- startDateItem.setTitle("Start" + "(" + timezone + ")");
- startDateItem.setValue(selectedRange.getStartDate());
- startDateItem.addChangedHandler(_createStartDateItemChangeHandler());
- TimeItem startTimeItem = new TimeItem("timeItem", "Time");
- startTimeItem.setUseMask(true);
- startTimeItem.setValue(selectedRange.getStartDate());
- startTimeItem.addChangedHandler(_createStartTimeItemChangeHandler());
- DateItem endDateItem = new DateItem();
- endDateItem.setName("End");
- endDateItem.setTitle("End" + "(" + timezone + ")");
- endDateItem.setValue(selectedRange.getEndDate());
- endDateItem.addChangedHandler(_createEndDateItemChangeHandler());
- TimeItem endTimeItem = new TimeItem("timeItem", "Time");
- endTimeItem.setUseMask(true);
- endTimeItem.setValue(selectedRange.getEndDate());
- endTimeItem.addChangedHandler(_createEndTimeItemChangeHandler());
- _initSliders();
- playBtn = new IButton("Animate Map");
- playBtn.setShowRollOver(true);
- playBtn.setShowDisabled(true);
- playBtn.setShowDown(true);
- playBtn.setTitle("Animate Map");
- playBtn.addClickHandler(_createPlayClickHandler());
- loadBtn = new IButton("Load");
- loadBtn.setWidth(150);
- loadBtn.setShowRollOver(true);
- loadBtn.setShowDisabled(true);
- loadBtn.setShowDown(true);
- loadBtn.setTitle("Load");
- loadBtn.addClickHandler(_createLoadClickHandler());
- resetBtn = new IButton("Load");
- resetBtn.setWidth(150);
- resetBtn.setShowRollOver(true);
- resetBtn.setShowDisabled(true);
- resetBtn.setShowDown(true);
- resetBtn.setTitle("Reset");
- resetBtn.addClickHandler(_createResetClickHandler());
- HLayout progressCanvas = new HLayout();
- progressCanvas.setWidth100();
- progressCanvas.setAlign(Alignment.CENTER);
- progressCanvas.addMember(progressBarLabel);
- progressCanvas.addMember(progressBar);
- DynamicForm form = new DynamicForm();
- form.setNumCols(3);
- form.setAlign(Alignment.LEFT);
- form.setWidth100();
- form.setFields(startDateItem, startTimeItem, endDateItem, endTimeItem);
- HLayout buttonCanvasLoad = new HLayout();
- buttonCanvasLoad.setAlign(Alignment.CENTER);
- loadBtn.setWidth(125);
- loadBtn.setTooltip("Loads sensor and platform tracks for selected dates");
- buttonCanvasLoad.addMember(loadBtn);
- HLayout buttonCanvasPlay = new HLayout();
- buttonCanvasPlay.setAlign(Alignment.CENTER);
- playBtn.setWidth(125);
- playBtn.setTooltip("Plays animation");
- buttonCanvasPlay.addMember(playBtn);
- HLayout resetCanvasPlay = new HLayout();
- resetCanvasPlay.setAlign(Alignment.CENTER);
- resetBtn.setWidth(125);
- resetBtn.setTooltip("Resets map back to real-time updates");
- resetCanvasPlay.addMember(resetBtn);
- vLayout = new VLayout();
- vLayout.setMembersMargin(5);
- vLayout.setLayoutMargin(10);
- vLayout.setAlign(Alignment.CENTER);
- vLayout.setAutoHeight();
- vLayout.addMember(form);
- vLayout.addMember(endSliderLabel);
- vLayout.addMember(endSlider);
- vLayout.addMember(startSliderLabel);
- vLayout.addMember(startSlider);
- vLayout.addMember(currentDateLabel);
- vLayout.addMember(progressCanvas);
- vLayout.addMember(buttonCanvasLoad);
- vLayout.addMember(buttonCanvasPlay);
- vLayout.addMember(resetCanvasPlay);
- vLayout.addMember(_createFrameDelayForm());
- vLayout.addMember(_createUpdateSelectForm());
- vLayout.setHeight(50);
- _setState(State.LOAD_STOP);
- }
- private void _initSliders() {
- if (state != State.LOAD_FINI) {
- // initialize the timer slider to the total duration in seconds
- float maxTimeMins = (float) (selectedRange.getEndDate().getTime() - selectedRange.getStartDate().getTime())
- / 60000L;
- endSlider.setMinValue(0);
- endSlider.setMaxValue(maxTimeMins);
- endSlider.setValue(maxTimeMins);
- endSliderLabel._formatLabel(selectedRange.getEndDate().toString());
- startSlider.setMinValue(0);
- startSlider.setMaxValue(maxTimeMins);
- startSlider.setValue(0);
- startSliderLabel._formatLabel(selectedRange.getStartDate().toString());
- }
- }
- private DynamicForm _createFrameDelayForm() {
- final DynamicForm form = new DynamicForm();
- form.setNumCols(3);
- frameDelaySelect = new FrameDelaySelectItem("Frame Delay");
- frameDelaySelect.setValue("10 sec");
- frameDelaySelect.setTooltip("Frame rate for animation");
- frameDelaySelect.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- try {
- String value = frameDelaySelect.getString2SecsDict((String) event.getValue());
- frameDelaySecs = Integer.parseInt(value);
- } catch (Exception e) {
- // TODO: log exception
- }
- }
- });
- form.setFields(frameDelaySelect);
- return form;
- }
- private DynamicForm _createUpdateSelectForm() {
- final DynamicForm form = new DynamicForm();
- form.setNumCols(3);
- updateSelect = new CustomSelectItem("Display");
- updateSelect.setValue("1 hour");
- updateSelect.setTooltip("Duration to display each frame during animation playback");
- updateSelect.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- try {
- String value = updateSelect.getDayName2MinsDict((String) event.getValue());
- updateMin = Integer.parseInt(value);
- } catch (Exception e) {
- // TODO: log exception
- }
- }
- });
- form.setFields(updateSelect);
- return form;
- }
- /**
- * Updates the playback label with the string
- *
- * @param string
- */
- public void updateText(String string) {
- currentDateLabel._formatLabel(string);
- }
- /**
- * Return the date range
- *
- * @return
- */
- public DateRange getDateRange() {
- return selectedRange;
- }
- public void resetPlayButton(boolean state) {
- if (state == true) {
- playBtn.setTitle("Animate Map");
- } else {
- playBtn.setTitle("Stop Animation");
- }
- }
- void reset() {
- _setState(State.LOAD_STOP);
- }
- private void playPause() {
- if (playBtn.getTitle().equals("Animate Map")) {
- resetPlayButton(false);
- timer.changeRange(playbackRange);
- timer.changeDisplayMins(updateMin);
- timer.changeTimerPeriodSeconds(frameDelaySecs);
- timer.start();
- } else {
- resetPlayButton(true);
- timer.stop();
- }
- }
- private ClickHandler _createResetClickHandler() {
- return new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- _setState(State.LOAD_STOP);
- DssTimer.getInstance().init();
- }
- };
- }
- private ClickHandler _createPlayClickHandler() {
- return new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- playPause();
- }
- };
- }
- private ClickHandler _createLoadClickHandler() {
- return new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- int timeStepMins = (int) ((selectedRange.getEndDate().getTime()
- - selectedRange.getStartDate().getTime()) / 60000L);
- if (state == State.LOAD_START) {
- _setState(State.LOAD_STOP);
- } else {
- _setState(State.LOAD_START);
- DssTimer.getInstance().setPlayback(selectedRange, timeStepMins, timeStepMins,
- DssTimer.Mode.PLAYBACK);
- }
- }
- };
- }
- public State getState() {
- return this.state;
- }
- private void _setState(State newState) {
- this.state = newState;
- if (newState == State.LOAD_START) {
- frameDelaySelect.disable();
- updateSelect.disable();
- endSlider.disable();
- startSlider.disable();
- playBtn.disable();
- loadBtn.setTitle("Stop Loading");
- progressBar.setVisible(true);
- progressBarLabel.setVisible(true);
- progressBarValue = 0;
- progressDelayMSec = (int) ((playbackRange.getEndDate().getTime() - playbackRange.getStartDate().getTime())
- / 60000L);
- progressBarTimer.schedule(50);
- } else if (newState == State.LOAD_FINI) {
- loadedRange.setStartDate(new Date(selectedRange.getStartDate().getTime()));
- loadedRange.setEndDate(new Date(selectedRange.getEndDate().getTime()));
- playbackRange.setStartDate(new Date(selectedRange.getStartDate().getTime()));
- playbackRange.setEndDate(new Date(selectedRange.getEndDate().getTime()));
- frameDelaySelect.enable();
- updateSelect.enable();
- endSlider.enable();
- startSlider.enable();
- playBtn.enable();
- loadBtn.setTitle("Load");
- progressBarValue = 100;
- progressBar.setVisible(false);
- progressBarLabel.setVisible(false);
- } else if (newState == State.LOAD_STOP) {
- frameDelaySelect.disable();
- updateSelect.disable();
- endSlider.disable();
- startSlider.disable();
- playBtn.disable();
- loadBtn.setTitle("Load");
- loadBtn.enable();
- progressBarValue = 0;
- progressBarTimer.cancel();
- progressBar.setVisible(false);
- progressBarLabel.setVisible(false);
- endSlider.disable();
- startSlider.disable();
- playBtn.disable();
- playBtn.setTitle("Animate Map");
- }
- }
- /**
- * Helper method to reset the load button visibility if selected
- * a date outside the loaded range
- *
- * @param date
- */
- private void checkRange(Date date) {
- if (state == State.LOAD_FINI) {
- Date start = loadedRange.getStartDate();
- Date end = loadedRange.getEndDate();
- if ((date.getTime() < start.getTime())
- || (date.getTime() > end.getTime())) {
- loadBtn.enable();
- }
- }
- }
- void handleNavDataRetrieved() {
- if (state.equals(State.LOAD_START)) {
- _setState(State.LOAD_FINI);
- }
- }
- private Timer _createProgressBarTimer() {
- return new Timer() {
- public void run() {
- progressBarValue += 1 + (int) (10 * Math.random());
- if (progressBarValue >= 100) {
- if (state != State.LOAD_FINI) {
- progressBarValue = 0;
- } else {
- progressBarValue = 100;
- progressBarLabel.setContents("Loading Complete");
- }
- }
- progressBar.setPercentDone(progressBarValue);
- progressBarLabel.setContents("Loading Progress: " + progressBarValue + "%");
- if (progressBarValue != 100) {
- schedule(progressDelayMSec + (int) (50 * Math.random()));
- } else {
- progressBar.setVisible(false);
- progressBarLabel.setVisible(false);
- return;
- }
- }
- };
- }
- private ChangedHandler _createEndDateItemChangeHandler() {
- return new ChangedHandler() {
- @Override
- public void onChanged(ChangedEvent event) {
- Date date = (Date) event.getValue();
- Date endDate = selectedRange.getEndDate();
- endDate.setMonth(date.getMonth());
- endDate.setDate(date.getDate());
- endDate.setYear(date.getYear());
- checkRange(endDate);
- selectedRange.setEndDate(endDate);
-
- _initSliders();
- }
- };
- }
- private ChangedHandler _createEndTimeItemChangeHandler() {
- return new ChangedHandler() {
- @Override
- public void onChanged(ChangedEvent event) {
- Date date = (Date) event.getValue();
- Date endDate = selectedRange.getEndDate();
- endDate.setHours(date.getHours());
- endDate.setMinutes(date.getMinutes());
- endDate.setSeconds(date.getSeconds());
- selectedRange.setEndDate(endDate);
- checkRange(endDate);
- _initSliders();
- }
- };
- }
- private ChangedHandler _createStartDateItemChangeHandler() {
- return new ChangedHandler() {
- @Override
- public void onChanged(ChangedEvent event) {
- Date date = (Date) event.getValue();
- Date startDate = selectedRange.getStartDate();
- startDate.setMonth(date.getMonth());
- startDate.setDate(date.getDate());
- startDate.setYear(date.getYear());
- selectedRange.setStartDate(startDate);
- checkRange(startDate);
- _initSliders();
- }
- };
- }
- private ChangedHandler _createStartTimeItemChangeHandler() {
- return new ChangedHandler() {
- @Override
- public void onChanged(ChangedEvent event) {
- Date date = (Date) event.getValue();
- Date startDate = selectedRange.getStartDate();
- startDate.setHours(date.getHours());
- startDate.setMinutes(date.getMinutes());
- startDate.setSeconds(date.getSeconds());
- selectedRange.setStartDate(startDate);
- checkRange(startDate);
- _initSliders();
- }
- };
- }
- /**
- * Gets the type of the instance.
- * @return the {@link DssViewKey}
- */
- public DssViewKey getType() {
- return DssViewKey.PLAYBACK_VIEW;
- }
- public Widget getWidget() {
- return vLayout;
- }
- /**
- * Date slider for controller start/end dates
- */
- class DateSlider extends Slider {
- public DateSlider(String title) {
- this.setWidth(250);
- this.setVertical(false);
- this.setStepPercent(5.0f);
- this.setTitle(title);
- this.setShowRange(false);
- this.setShowValue(false);
- }
- }
- /**
- * Label for displaying playback date and time
- */
- class PlaybackDateLabel extends Label {
- public PlaybackDateLabel() {
- setAlign(Alignment.LEFT);
- setHeight(40);
- setWidth100();
- }
- private void _formatLabel(String label) {
- setContents("<b>Playback Time</b><br>" + label);
- }
- }
- /**
- * Label for displaying start/end date and time
- */
- class SliderDateLabel extends Label {
- public SliderDateLabel() {
- setAlign(Alignment.LEFT);
- setHeight(40);
- setWidth100();
- }
- private void _formatLabel(String label) {
- setContents(label);
- }
- }
- }