diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java index 05edc581746..04d88dd0ef9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java @@ -94,11 +94,7 @@ public class RaceTimePanel extends TimePanel implements R if (raceTimesInfo.startOfTracking != null && raceTimesInfo.timePointOfNewestEvent != null) { // we set here the min and max of the time slider, the start and end of the race as well as the known // leg markers - long livePlayDelayInMillis = timer.getLivePlayDelayInMillis(); - long eventTimeoutTolerance = 30 * 1000; // 30s - long liveTimePointInMillis = System.currentTimeMillis() - livePlayDelayInMillis; - if (liveTimePointInMillis < raceTimesInfo.timePointOfNewestEvent.getTime() + eventTimeoutTolerance - && liveTimePointInMillis > raceTimesInfo.startOfTracking.getTime()) { + if (isLiveModeToBeMadePossible()) { // don't worry; this will only fire an event if something actually changed // FIXME bug 323: dont' set the play mode but only make sure the time panel's "Live" button is enabled timer.setPlayMode(PlayModes.Live); @@ -118,6 +114,15 @@ public class RaceTimePanel extends TimePanel implements R } } + @Override + protected boolean isLiveModeToBeMadePossible() { + long livePlayDelayInMillis = timer.getLivePlayDelayInMillis(); + long eventTimeoutTolerance = 30 * 1000; // 30s + long liveTimePointInMillis = System.currentTimeMillis() - livePlayDelayInMillis; + return (liveTimePointInMillis < lastRaceTimesInfo.timePointOfNewestEvent.getTime() + eventTimeoutTolerance + && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()); + } + @Override public void onRaceSelectionChange(List selectedRaces) { if (selectedRaces != null && !selectedRaces.isEmpty()) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanelSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanelSettingsDialogComponent.java index 9f780d6617c..d4630824f11 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanelSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanelSettingsDialogComponent.java @@ -14,17 +14,15 @@ public class RaceTimePanelSettingsDialogComponent extends TimePanelSettingsDialo @Override public Widget getAdditionalWidget(DataEntryDialog dialog) { Widget widget = super.getAdditionalWidget(dialog); - HorizontalPanel labelAndTDelayForLiveBoxPanel = new HorizontalPanel(); labelAndTDelayForLiveBoxPanel.setSpacing(5); - labelAndTDelayForLiveBoxPanel.add(new Label("Delay for live mode:")); + labelAndTDelayForLiveBoxPanel.add(new Label(getStringMessages().delayForLiveMode())); RaceTimesInfoDTO raceTimesInfo = initialSettings.getRaceTimesInfo(); - if(raceTimesInfo != null && raceTimesInfo.startOfTracking != null) { + if (raceTimesInfo != null && raceTimesInfo.startOfTracking != null) { long delayforLiveModeInMs = System.currentTimeMillis() - raceTimesInfo.getStartOfTracking().getTime(); labelAndTDelayForLiveBoxPanel.add(new Label(delayforLiveModeInMs / 1000 + " s")); } mainContentPanel.add(labelAndTDelayForLiveBoxPanel); - return widget; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 941fa8aa2a3..e43960e4357 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -261,4 +261,5 @@ public interface StringMessages extends Messages { String directionChange(); String speedChange(); String degreesShort(); + String delayForLiveMode(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 9553668c380..527d2bf1a86 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -255,4 +255,5 @@ competitorCharts=Competitor charts selectAtLeastOneCompetitor=Select at least one competitor directionChange=Direction change speedChange=Speed change -degreesShort=deg \ No newline at end of file +degreesShort=deg +delayForLiveMode=Delay for live mode: \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 1fba046e849..a66baf5ecb7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -256,4 +256,5 @@ competitorCharts=Competitor charts selectAtLeastOneCompetitor=Mindestens einen Segler auswählen directionChange=Richtungsänderung speedChange=Geschwindigkeitsänderung -degreesShort=deg \ No newline at end of file +degreesShort=deg +delayForLiveMode=Verzögerung im Live-Modus: \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java index 5589a8e3fd2..9196642131d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java @@ -160,6 +160,7 @@ public class TimePanel extends FormPanel implements backToLivePlayButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { + TimePanel.this.timer.setPlayMode(PlayModes.Live); TimePanel.this.timer.play(); } }); @@ -327,6 +328,9 @@ public class TimePanel extends FormPanel implements @Override public void playStateChanged(PlayStates playState, PlayModes playMode) { + boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible(); + setLiveGenerallyPossible(liveModeToBeMadePossible); + setJumpToLiveEnablement(liveModeToBeMadePossible && playMode != PlayModes.Live); switch (playState) { case Playing: playPauseImage.setResource(pauseButtonImg); @@ -335,13 +339,11 @@ public class TimePanel extends FormPanel implements } else { playModeImage.setResource(playModeReplayActiveImg); } - backToLivePlayButton.setEnabled(false); break; case Paused: case Stopped: playPauseImage.setResource(playButtonImg); playModeImage.setResource(playModeInactiveImg); - backToLivePlayButton.setEnabled(true); break; } @@ -351,7 +353,6 @@ public class TimePanel extends FormPanel implements timeDelayLabel.setText(stringMessages.timeDelay() + ": " + timer.getCurrentDelayInMillis() / 1000 + " s"); timeDelayLabel.setVisible(true); sliderBar.setEnabled(true); - backToLivePlayButton.setVisible(true); playSpeedBox.setEnabled(false); slowDownButton.setEnabled(false); speedUpButton.setEnabled(false); @@ -361,13 +362,30 @@ public class TimePanel extends FormPanel implements timeDelayLabel.setText(""); playModeLabel.setText(stringMessages.playModeReplay()); sliderBar.setEnabled(true); - backToLivePlayButton.setVisible(false); playSpeedBox.setEnabled(true); slowDownButton.setEnabled(true); speedUpButton.setEnabled(true); break; } } + + protected boolean isLiveModeToBeMadePossible() { + return false; + } + + /** + * Enables the {@link #backToLivePlayButton} if and only if enabled is true. + */ + protected void setJumpToLiveEnablement(boolean enabled) { + backToLivePlayButton.setEnabled(enabled); + } + + /** + * Iff possible, makes the {@link #backToLivePlayButton} button visible. + */ + protected void setLiveGenerallyPossible(boolean possible) { + backToLivePlayButton.setVisible(possible); + } @SuppressWarnings("unchecked") public T getSettings() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanelSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanelSettingsDialogComponent.java index c2fd84f00b5..806dc5f7795 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanelSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanelSettingsDialogComponent.java @@ -21,6 +21,10 @@ public class TimePanelSettingsDialogComponent imple this.stringMessages = stringMessages; initialSettings = settings; } + + protected StringMessages getStringMessages() { + return stringMessages; + } @Override public Widget getAdditionalWidget(DataEntryDialog dialog) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/Timer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/Timer.java index b7169db79c7..375d4fcf547 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/Timer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/Timer.java @@ -9,7 +9,11 @@ import com.google.gwt.core.client.Scheduler.RepeatingCommand; /** * Manages a timer and can auto-advance it at a given acceleration/deceleration rate, with a given delay compared to - * real time. It can be {@link #pause() paused} and {@link #resume() resumed}. + * real time. It can be {@link #pause() paused} and {@link #resume() resumed}. It can be in one of two play modes: + * {@link PlayModes#Live} and {@link PlayModes#Replay}. In live play mode the timer is always in state {@link PlayStates#Playing} + * and adjusts the time to now-{@link #livePlayDelayInMillis}. As soon as it's paused or stopped it enters + * {@link PlayModes#Replay}. By entering {@link PlayModes#Live} with {@link #setPlayMode(PlayModes)}, the timer starts + * playing right away. * * @author Axel Uhl (d043530) * @@ -43,7 +47,8 @@ public class Timer { private PlayStates playState; /** - * The current play mode of the timer + * The current play mode of the timer: live or replay. In live mode the timer will adjust to now-delay each time it + * refreshes. In replay mode it will advance time by the refresh interval times the play speed factor. */ private PlayModes playMode; @@ -60,6 +65,7 @@ public class Timer { /** * Factor by which the timer runs faster than real time. 1.0 means real-time, 2.0 means twice as fast as real time, and so on. + * Applies only if the timer is in replay mode. */ private double playSpeedFactor; @@ -143,36 +149,46 @@ public class Timer { return time; } + /** + * When setting the play mode to live, the timer will automatically be put into play state playing. + */ public void setPlayMode(PlayModes newPlayMode) { if (this.playMode != newPlayMode) { this.playMode = newPlayMode; for (PlayStateListener playStateListener : playStateListeners) { playStateListener.playStateChanged(playState, playMode); } + if (newPlayMode == PlayModes.Live) { + play(); + } } } /** * Pauses this timer after the next time advance. {@link #playing} is set to false if not already - * paused, and registered {@link PlayStateListener}s will be notified. + * paused, and registered {@link PlayStateListener}s will be notified. If the play mode was live, it'll be set to + * replay. */ public void pause() { if (playState == PlayStates.Playing) { playState = PlayStates.Paused; // this will cause the repeating command to stop executing - for (PlayStateListener playStateListener : playStateListeners) { playStateListener.playStateChanged(playState, playMode); } + setPlayMode(PlayModes.Replay); } } + /** + * Puts the timer into the stopped state. If it was in live mode, puts it into replay mode. + */ public void stop() { if (playState == PlayStates.Playing) { playState = PlayStates.Stopped; - for (PlayStateListener playStateListener : playStateListeners) { playStateListener.playStateChanged(playState, playMode); } + setPlayMode(PlayModes.Replay); } }