Merge branch 'master' into foiling

Conflicts:
	java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java
	java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorRaceChart.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorRaceChartSettings.java
	java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java
This commit is contained in:
Steffen Schaefer committed 2016-06-09 08:52:37 +02:00
commit 4597ee9882
189 files changed
+5447 -3538

No files matched your search

@@ -33,6 +33,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMap;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapLifecycle;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapResources;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
@@ -150,11 +152,12 @@ public class StartAnalysisCard extends Composite implements HasWidgets, StartAna
zoomTypes.add(ZoomTypes.BUOYS);
}
AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor();
RaceMapSettings raceMapSettings = RaceMapSettings.readSettingsFromURL();
RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingServiceAsync,
asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */);
raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel,
StringMessages.INSTANCE, false, false, false, false, startAnalysisDTO.regattaAndRaceIdentifier,
raceMapResources, /* showHeaderPanel */ true);
raceMap = new RaceMap(new RaceMapLifecycle(StringMessages.INSTANCE), raceMapSettings, sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel,
StringMessages.INSTANCE, startAnalysisDTO.regattaAndRaceIdentifier,
raceMapResources, /* isSimulationEnabled */ false, /* showHeaderPanel */ true);
raceMap.getSettings().setZoomSettings(new RaceMapZoomSettings(zoomTypes, false));
raceMap.getSettings().setHelpLinesSettings(getHelpLineSettings());
raceMap.getSettings().setTailLengthInMilliseconds(startAnalysisDTO.tailLenghtInMilliseconds);
@@ -12,9 +12,13 @@ import com.sap.sse.common.media.MediaSubType;
import com.sap.sse.common.media.MimeType;
/**
* See http://my.opera.com/core/blog/2010/03/03/everything-you-need-to-know-about-html5-video-and-audio-2
* The {@link #hashCode()} and {@link #equals(Object)} methods are based solely on the {@link #dbId} field.
* <p>
*
* @author D047974
* See http://my.opera.com/core/blog/2010/03/03/everything-you-need-to-know-about-html5-video-and-audio-2
* <p>
*
* @author Jens Rommel (D047974)
*
*/
public class MediaTrack implements Serializable {
@@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -70,7 +71,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
private final Map<String, DynamicTrack<HDGM>> hdgmTrack;
private final FixReceiver receiver;
private final DeclinationService declinationService;
private final ConcurrentHashMap<IgtimiWindListener, IgtimiWindListener> listeners;
private final ConcurrentMap<IgtimiWindListener, IgtimiWindListener> listeners;
private class FixReceiver extends IgtimiFixReceiverAdapter {
@Override
@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -43,7 +44,7 @@ public class WebSocketConnectionManager extends WebSocketAdapter implements Live
private final Account account;
private final FixFactory fixFactory;
private boolean receivedServerHeartbeatInInterval;
private final ConcurrentHashMap<BulkFixReceiver, BulkFixReceiver> listeners;
private final ConcurrentMap<BulkFixReceiver, BulkFixReceiver> listeners;
private TimePoint igtimiServerTimepoint;
private TimePoint localTimepointWhenServerTimepointWasReceived;
@@ -18,86 +18,80 @@ import com.sap.sse.common.media.MimeType;
*/
public interface MediaDB {
/**
* Stores a new track to the database, returning the db-generated id.
*/
String insertMediaTrack(String title, String url, TimePoint startTime,
Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> assignedRaces);
/**
* Stores a new track to the database, returning the db-generated id.
*/
String insertMediaTrack(String title, String url, TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> assignedRaces);
/**
* Stores a new track to the database, using the db id of the specified
* trackToImport.
*
* @return true if a new track has been added to db, e.g. the specified dbId
* didn't exist.
* @throws NullpointerException
* When trackToImport.dbId is null.
* @throws IllegalArgumentException
* When track with specified dbId already exists.
*/
void insertMediaTrackWithId(String dbId, String videoTitle, String url,
TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> regattaAndRace);
/**
* Stores a new track to the database, using the db id of the specified trackToImport.
*
* @return true if a new track has been added to db, e.g. the specified dbId didn't exist.
* @throws NullpointerException
* When trackToImport.dbId is null.
* @throws IllegalArgumentException
* When track with specified dbId already exists.
*/
void insertMediaTrackWithId(String dbId, String videoTitle, String url, TimePoint startTime, Duration duration,
MimeType mimeType, Set<RegattaAndRaceIdentifier> regattaAndRace);
List<MediaTrack> loadAllMediaTracks();
List<MediaTrack> loadAllMediaTracks();
void deleteMediaTrack(String dbId);
void deleteMediaTrack(String dbId);
void updateTitle(String dbId, String title);
void updateTitle(String dbId, String title);
void updateUrl(String dbId, String url);
void updateUrl(String dbId, String url);
void updateStartTime(String dbId, TimePoint startTime);
void updateStartTime(String dbId, TimePoint startTime);
void updateDuration(String dbId, Duration duration);
void updateDuration(String dbId, Duration duration);
void updateRace(String dbId, Set<RegattaAndRaceIdentifier> race);
void updateRace(String dbId, Set<RegattaAndRaceIdentifier> race);
MediaDB TEST_STUB = new MediaDB() {
MediaDB TEST_STUB = new MediaDB() {
@Override
public String insertMediaTrack(String title, String url,
TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> assignedRaces) {
return "0";
}
@Override
public String insertMediaTrack(String title, String url, TimePoint startTime, Duration duration,
MimeType mimeType, Set<RegattaAndRaceIdentifier> assignedRaces) {
return "0";
}
@Override
public void insertMediaTrackWithId(String dbId, String videoTitle,
String url, TimePoint startTime, Duration duration,
MimeType mimeType, Set<RegattaAndRaceIdentifier> assingedRace) {
};
@Override
public void insertMediaTrackWithId(String dbId, String videoTitle, String url, TimePoint startTime,
Duration duration, MimeType mimeType, Set<RegattaAndRaceIdentifier> assingedRace) {
};
@Override
public List<MediaTrack> loadAllMediaTracks() {
return Collections.emptyList();
}
@Override
public List<MediaTrack> loadAllMediaTracks() {
return Collections.emptyList();
}
@Override
public void deleteMediaTrack(String dbId) {
}
@Override
public void deleteMediaTrack(String dbId) {
}
@Override
public void updateTitle(String dbId, String title) {
}
@Override
public void updateTitle(String dbId, String title) {
}
@Override
public void updateUrl(String dbId, String url) {
}
@Override
public void updateUrl(String dbId, String url) {
}
@Override
public void updateStartTime(String dbId, TimePoint startTime) {
}
@Override
public void updateStartTime(String dbId, TimePoint startTime) {
}
@Override
public void updateDuration(String dbId, Duration duration) {
}
@Override
public void updateDuration(String dbId, Duration duration) {
}
@Override
public void updateRace(String dbId, Set<RegattaAndRaceIdentifier> race) {
}
@Override
public void updateRace(String dbId, Set<RegattaAndRaceIdentifier> race) {
}
};
};
}
@@ -51,7 +51,6 @@ public class MediaDBImpl implements MediaDB {
@Override
public String insertMediaTrack(String title, String url, TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> assignedRaces) {
BasicDBObject dbMediaTrack = new BasicDBObject();
dbMediaTrack.put(DbNames.Fields.MEDIA_TITLE.name(), title);
dbMediaTrack.put(DbNames.Fields.MEDIA_URL.name(), url);
@@ -76,7 +75,6 @@ public class MediaDBImpl implements MediaDB {
@Override
public void insertMediaTrackWithId(String dbId, String title, String url, TimePoint startTime, Duration duration,
MimeType mimeType, Set<RegattaAndRaceIdentifier> assignedRaces) {
BasicDBObject dbMediaTrack = new BasicDBObject();
dbMediaTrack.put(DbNames.Fields._id.name(), new ObjectId(dbId));
dbMediaTrack.put(DbNames.Fields.MEDIA_TITLE.name(), title);
@@ -92,8 +90,6 @@ public class MediaDBImpl implements MediaDB {
object.put(DbNames.Fields.RACE_NAME.name(), assignedRace.getRaceName());
assignedRacesDb.add(object);
}
} else {
System.currentTimeMillis();
}
dbMediaTrack.put(DbNames.Fields.ASSIGNED_RACES.name(), assignedRacesDb);
DBCollection dbVideos = getVideoCollection();
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -17,6 +17,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -123,7 +124,7 @@ public class DomainFactoryImpl implements DomainFactory {
* Maps from the TracTrac race UUIDs to the domain model's {@link RaceDefinition} objects that represent the race
* identified by that UUID
*/
private final ConcurrentHashMap<UUID, RaceDefinition> raceCache = new ConcurrentHashMap<>();
private final ConcurrentMap<UUID, RaceDefinition> raceCache = new ConcurrentHashMap<>();
private final MetadataParser metadataParser;
@@ -2,7 +2,6 @@ package com.sap.sailing.domain.base;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
@@ -72,7 +71,7 @@ public interface DomainFactory extends SharedDomainFactory {
TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace);
TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet, Collection<MediaTrack> mediatracks);
Fleet fleet, Iterable<MediaTrack> mediatracks);
/**
* @param trackedRace must not be <code>null</code>
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
@@ -176,7 +175,7 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
@Override
public TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard,
RaceColumn raceColumn, Fleet fleet, Collection<MediaTrack> mediaTracks) {
RaceColumn raceColumn, Fleet fleet, Iterable<MediaTrack> mediaTracks) {
TrackedRaceStatisticsDTO statisticsDTO = new TrackedRaceStatisticsDTO();
// GPS data
statisticsDTO.hasGPSData = trackedRace.hasGPSData();
@@ -14,6 +14,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -101,7 +102,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
private static final Logger logger = Logger.getLogger(RegattaImpl.class.getName());
private static final long serialVersionUID = 6509564189552478869L;
private ConcurrentHashMap<String, RaceDefinition> races;
private ConcurrentMap<String, RaceDefinition> races;
private final BoatClass boatClass;
private transient Set<RegattaListener> regattaListeners;
private List<? extends Series> series;
@@ -7,6 +7,7 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorChangeListener;
@@ -41,7 +42,7 @@ public class LeaderboardCacheManager {
private final WeakHashMap<Leaderboard, CacheInvalidationUponScoreCorrectionListener> scoreCorrectionListeners;
private final NamedReentrantReadWriteLock scoreCorrectionAndCompetitorChangeListenersLock;
private final WeakHashMap<Leaderboard, CacheInvalidationUponCompetitorChangeListener> competitorChangeListeners;
private final ConcurrentWeakHashMap<Leaderboard, ConcurrentHashMap<TrackedRace, Set<CacheInvalidationListener>>> invalidationListenersPerLeaderboard;
private final ConcurrentWeakHashMap<Leaderboard, ConcurrentMap<TrackedRace, Set<CacheInvalidationListener>>> invalidationListenersPerLeaderboard;
private final WeakHashMap<Leaderboard, RaceColumnListener> raceColumnListeners;
private class CacheInvalidationListener extends AbstractRaceChangeListener {
@@ -199,7 +200,7 @@ public class LeaderboardCacheManager {
}
private void removeFromCache(Leaderboard leaderboard) {
ConcurrentHashMap<TrackedRace, Set<CacheInvalidationListener>> listenersMap = invalidationListenersPerLeaderboard.remove(leaderboard);
ConcurrentMap<TrackedRace, Set<CacheInvalidationListener>> listenersMap = invalidationListenersPerLeaderboard.remove(leaderboard);
if (listenersMap != null) {
for (Map.Entry<TrackedRace, Set<CacheInvalidationListener>> e : listenersMap.entrySet()) {
synchronized (e.getValue()) { // the Set is a Collections.synchronizedSet, and synchronization is required for iteration
@@ -299,7 +300,7 @@ public class LeaderboardCacheManager {
}
private void registerListener(final Leaderboard leaderboard, TrackedRace trackedRace) {
ConcurrentHashMap<TrackedRace, Set<CacheInvalidationListener>> invalidationListeners;
ConcurrentMap<TrackedRace, Set<CacheInvalidationListener>> invalidationListeners;
final CacheInvalidationListener listener;
listener = new CacheInvalidationListener(leaderboard, trackedRace);
trackedRace.addListener(listener);
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.leaderboard.caching;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Leg;
@@ -48,7 +49,7 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea
/**
* the leg types at "timePoint"
*/
final ConcurrentHashMap<Leg, LegType> legTypeCache;
final ConcurrentMap<Leg, LegType> legTypeCache;
/**
* the wind at competitor's position at timePoint; <code>null</code> values are represented by {@link #NULL_WIND}.
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.leaderboard.impl;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -60,7 +61,7 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike {
private Iterable<Competitor> allCompetitorsCache;
private final ConcurrentHashMap<Pair<RaceColumn, Fleet>, Iterable<Competitor>> allCompetitorsCacheByRace;
private final ConcurrentMap<Pair<RaceColumn, Fleet>, Iterable<Competitor>> allCompetitorsCacheByRace;
public CompetitorProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) {
super();
@@ -7,6 +7,7 @@ import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -39,12 +40,12 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
/**
* If no max point reason is provided for a competitor/race, {@link MaxPointsReason#NONE} should be the default.
*/
private final ConcurrentHashMap<com.sap.sse.common.Util.Pair<Competitor, RaceColumn>, MaxPointsReason> maxPointsReasons;
private final ConcurrentMap<com.sap.sse.common.Util.Pair<Competitor, RaceColumn>, MaxPointsReason> maxPointsReasons;
/**
* If no score correction is provided here, the uncorrected points are the default.
*/
private final ConcurrentHashMap<com.sap.sse.common.Util.Pair<Competitor, RaceColumn>, Double> correctedScores;
private final ConcurrentMap<com.sap.sse.common.Util.Pair<Competitor, RaceColumn>, Double> correctedScores;
/**
* If <code>null</code>, despite a non-<code>null</code> {@link #timePointOfLastCorrectionsValidity} value the
@@ -15,6 +15,7 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -371,7 +372,7 @@ public class CandidateFinderImpl implements CandidateFinder {
* second} element has those that have been removed.
*/
private Map<Competitor, Util.Pair<List<Candidate>, List<Candidate>>> invalidateAfterCourseChange(int zeroBasedIndexOfWaypointChanged) {
ConcurrentHashMap<Competitor, Util.Pair<List<Candidate>, List<Candidate>>> result = new ConcurrentHashMap<>();
ConcurrentMap<Competitor, Util.Pair<List<Candidate>, List<Candidate>>> result = new ConcurrentHashMap<>();
Course course = race.getRace().getCourse();
for (Competitor c : race.getRace().getCompetitors()) {
distanceCache.get(c).clear();
@@ -11,6 +11,7 @@ import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -70,7 +71,7 @@ public class WaypointPositionAndDistanceCache {
* symmetrically under the map's monitor being held, i.e., if (w1, w2) is a cache key then so is
* (w2, w1), with equal value.
*/
private final ConcurrentHashMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> distanceCache;
private final ConcurrentMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> distanceCache;
/**
* Caches minimum distances between the positions cached in {@link #waypointPositionCache}. For two-mark control
@@ -80,7 +81,7 @@ public class WaypointPositionAndDistanceCache {
* {@link #waypointPositionCache}, it is also invalidated here. Keys always occur symmetrically under the map's
* monitor being held, i.e., if (w1, w2) is a cache key then so is (w2, w1), with equal value.
*/
private final ConcurrentHashMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> minimumDistanceCache;
private final ConcurrentMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> minimumDistanceCache;
/**
* The duration of the time ranges whose center time points serve as keys for the {@link NavigableMap}s used as
@@ -277,7 +278,7 @@ public class WaypointPositionAndDistanceCache {
for (Waypoint otherWaypoint : waypoints) {
ControlPoint otherControlPoint = otherWaypoint.getControlPoint();
if (otherControlPoint != controlPoint) {
for (ConcurrentHashMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> cache : Arrays.asList(distanceCache, minimumDistanceCache)) {
for (ConcurrentMap<Pair<ControlPoint, ControlPoint>, SortedMap<TimePoint, Distance>> cache : Arrays.asList(distanceCache, minimumDistanceCache)) {
final Map<TimePoint, Distance> distanceMap = cache.get(new Pair<>(controlPoint, otherControlPoint));
if (distanceMap != null) {
distanceMap.remove(timePoint);
@@ -66,7 +66,7 @@ public class TopLevelMasterData implements Serializable {
private final Map<DeviceConfigurationMatcher, DeviceConfiguration> deviceConfigurations;
public TopLevelMasterData(final Set<LeaderboardGroup> groupsToExport, final Iterable<Event> allEvents,
final Map<String, Regatta> regattaForRaceIdString, final Collection<MediaTrack> allMediaTracks,
final Map<String, Regatta> regattaForRaceIdString, final Iterable<MediaTrack> allMediaTracks,
GPSFixStore gpsFixStore, boolean exportWind, Map<DeviceConfigurationMatcher, DeviceConfiguration> deviceConfigurations) {
this.raceIdStringsForRegatta = convertToRaceIdStringsForRegattaMap(regattaForRaceIdString);
this.leaderboardGroups = groupsToExport;
@@ -302,7 +302,7 @@ public class TopLevelMasterData implements Serializable {
* Copies only those media tracks from allMediaTracks to filteredMediaTracks which are
* assigned to races related to the exported LeaderboardGroup.
*/
private void filterMediaTracks(Collection<MediaTrack> allMediaTracks, Set<MediaTrack> filteredMediaTracks) {
private void filterMediaTracks(Iterable<MediaTrack> allMediaTracks, Set<MediaTrack> filteredMediaTracks) {
Set<RaceIdentifier> raceIdentitifiersForMediaExport = collectRaceIdentifiersForMediaExport();
for (MediaTrack mediaTrack : allMediaTracks) {
for (RegattaAndRaceIdentifier raceIdentifier : mediaTrack.assignedRaces) {
@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
@@ -146,7 +147,7 @@ public abstract class AbstractRankingMetric implements RankingMetric {
* <code>null</code> values are encoded as the {@link #NULL_COMPETITOR} and must be translated back to <code>null</code> before returning
* to a caller outside of this class.
*/
private final ConcurrentHashMap<Leg, Competitor> competitorFarthestAheadInLeg;
private final ConcurrentMap<Leg, Competitor> competitorFarthestAheadInLeg;
public AbstractRankingInfo(final TimePoint timePoint) {
this.timePoint = timePoint;
@@ -1,8 +1,8 @@
package com.sap.sailing.domain.trackfiles;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
@@ -16,7 +16,7 @@ public class TrackFileImportDeviceIdentifierImpl implements TrackFileImportDevic
private final String trackName;
private final TimePoint timePoint;
private static final Map<UUID, TrackFileImportDeviceIdentifier> cache = new ConcurrentHashMap<>();
private static final ConcurrentMap<UUID, TrackFileImportDeviceIdentifier> cache = new ConcurrentHashMap<>();
public static TrackFileImportDeviceIdentifier getOrCreate(UUID uuid) {
if (cache.containsKey(uuid)) {
@@ -3,9 +3,9 @@ package com.sap.sailing.domain.tracking;
import java.io.ObjectOutputStream;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.RaceDefinition;
@@ -43,7 +43,7 @@ public abstract class TrackedRaceWithWindEssentials implements TrackedRace {
* intra-leg computations are done dynamically based on wind information, selecting a different wind information
* source can alter the intra-leg results. See {@link #currentWindSource}.
*/
protected final Map<WindSource, WindTrack> windTracks;
protected final ConcurrentMap<WindSource, WindTrack> windTracks;
protected final RaceDefinition race;
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.NavigableSet;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Competitor;
@@ -45,8 +46,8 @@ public abstract class AbstractRaceRankComparator<C extends Comparable<C>> implem
private final TimePoint timePoint;
private final DummyMarkPassingWithTimePointOnly markPassingWithTimePoint;
private final boolean lessIsBetter;
private final ConcurrentHashMap<Competitor, MarkPassing> lastMarkPassingBeforeTimePoint;
private final ConcurrentHashMap<Competitor, TrackedLegOfCompetitor> currentLeg;
private final ConcurrentMap<Competitor, MarkPassing> lastMarkPassingBeforeTimePoint;
private final ConcurrentMap<Competitor, TrackedLegOfCompetitor> currentLeg;
private final MarkPassing NULL_MARK_PASSING = new MarkPassingImpl(null, null, null);
private final TrackedLegOfCompetitor NULL_TRACKED_LEG_OF_COMPETITOR = new TrackedLegOfCompetitorImpl(null, null);
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.tracking.impl;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
@@ -55,7 +56,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
private static final Logger logger = Logger.getLogger(DynamicTrackedRaceLogListener.class.getName());
private ConcurrentHashMap<RaceLog, ReadonlyRaceState> raceLogs = new ConcurrentHashMap<>();
private ConcurrentMap<RaceLog, ReadonlyRaceState> raceLogs = new ConcurrentHashMap<>();
private DynamicTrackedRace trackedRace;
@@ -5,6 +5,7 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -26,8 +27,8 @@ import com.sap.sse.util.impl.ApproximateTime;
*/
public class ShortTimeWindCache {
private static final Logger logger = Logger.getLogger(ShortTimeWindCache.class.getName());
private final ConcurrentHashMap<Triple<Position, TimePoint, Set<WindSource>>,
WindWithConfidence<com.sap.sse.common.Util.Pair<Position, TimePoint>>> cache;
private final ConcurrentMap<Triple<Position, TimePoint, Set<WindSource>>,
WindWithConfidence<com.sap.sse.common.Util.Pair<Position, TimePoint>>> cache;
/**
* The keys of {@link #cache} in the order in which to invalidate them, keyed by the time they were entered into the cache.
@@ -15,6 +15,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.BoatClass;
@@ -61,7 +62,7 @@ public class TrackedLegImpl implements TrackedLeg {
private final Leg leg;
private final Map<Competitor, TrackedLegOfCompetitor> trackedLegsOfCompetitors;
private TrackedRaceImpl trackedRace;
private transient ConcurrentHashMap<TimePoint, List<TrackedLegOfCompetitor>> competitorTracksOrderedByRank;
private transient ConcurrentMap<TimePoint, List<TrackedLegOfCompetitor>> competitorTracksOrderedByRank;
public TrackedLegImpl(DynamicTrackedRaceImpl trackedRace, Leg leg, Iterable<Competitor> competitors) {
super();
@@ -25,6 +25,7 @@ import java.util.TimerTask;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -183,7 +184,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
* By default, all wind sources are used, none are excluded. However, e.g., for performance reasons, particular wind
* sources such as the track-based estimation wind source, may be excluded by adding them to this set.
*/
private final ConcurrentHashMap<WindSource, TrackedRaceImpl> windSourcesToExclude;
private final ConcurrentMap<WindSource, TrackedRaceImpl> windSourcesToExclude;
/**
* Keeps the oldest timestamp that is fed into this tracked race, either from a boat fix, a mark fix, a race
@@ -291,12 +292,12 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
*/
private transient SmartFutureCache<Competitor, com.sap.sse.common.Util.Triple<TimePoint, TimePoint, List<Maneuver>>, EmptyUpdateInterval> maneuverCache;
private transient ConcurrentHashMap<TimePoint, Future<Wind>> directionFromStartToNextMarkCache;
private transient ConcurrentMap<TimePoint, Future<Wind>> directionFromStartToNextMarkCache;
protected transient MarkPassingCalculator markPassingCalculator;
private final boolean hasMarkPassingCalculator;
private final ConcurrentHashMap<Mark, GPSFixTrack<Mark, GPSFix>> markTracks;
private final ConcurrentMap<Mark, GPSFixTrack<Mark, GPSFix>> markTracks;
private final Map<Pair<Competitor, String>, DynamicTrack<?>> sensorTracks;
@@ -323,7 +324,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
/**
* Keys are the {@link RaceLog#getId() IDs} of the race logs that are stored as values.
*/
protected transient ConcurrentHashMap<Serializable, RaceLog> attachedRaceLogs;
protected transient ConcurrentMap<Serializable, RaceLog> attachedRaceLogs;
/**
* Holds optional race states for the race logs in {@link #attachedRaceLogs}. By using a {@link WeakHashMap},
@@ -335,9 +336,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
/**
* Keys are the {@link RegattaLog#getId() IDs} of the regatta logs that are stored as values.
*/
protected transient ConcurrentHashMap<Serializable, RegattaLog> attachedRegattaLogs;
protected transient ConcurrentMap<Serializable, RegattaLog> attachedRegattaLogs;
private transient ConcurrentHashMap<RaceExecutionOrderProvider, RaceExecutionOrderProvider> attachedRaceExecutionOrderProviders;
private transient ConcurrentMap<RaceExecutionOrderProvider, RaceExecutionOrderProvider> attachedRaceExecutionOrderProviders;
/**
* The time delay to the current point in time in milliseconds.
@@ -366,7 +367,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
*/
private final NamedReentrantReadWriteLock loadingFromGPSFixStoreLock;
private final ConcurrentHashMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock> locksForMarkPassings;
private final ConcurrentMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock> locksForMarkPassings;
/**
* Caches wind requests for a few seconds to accelerate access in live mode
@@ -9,6 +9,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -48,7 +49,7 @@ public class TrackedRegattaImpl implements TrackedRegatta {
*/
private final Map<RaceDefinition, TrackedRace> trackedRaces;
private transient ConcurrentHashMap<RaceListener, RaceListener> raceListeners;
private transient ConcurrentMap<RaceListener, RaceListener> raceListeners;
public TrackedRegattaImpl(Regatta regatta) {
super();
@@ -1,4 +1,4 @@
eclipse.preferences.version=1
entryPointModules=
filesCopiedToWebInfLib=gwt-servlet.jar
gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgLiAtbG9jYWxXb3JrZXJzIDQgLXN0cmljdCAtbG9nTGV2ZWwgVFJBQ0VdXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDIwMjRtIC1EZ3d0LnVzZWFyY2hpdmVzPWZhbHNlXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5EYXRhTWluaW5nPC9lbnRyeS1wb2ludC1tb2R1bGU+PC9nd3QtY29tcGlsZS1zZXR0aW5ncz4\=
gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgLiAtbG9jYWxXb3JrZXJzIDQgLXN0cmljdCAtbG9nTGV2ZWwgVFJBQ0VdXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDIwMjRtIC1EZ3d0LnVzZWFyY2hpdmVzPWZhbHNlXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5BZG1pbkNvbnNvbGU8L2VudHJ5LXBvaW50LW1vZHVsZT48L2d3dC1jb21waWxlLXNldHRpbmdzPg\=\=
@@ -10,7 +10,6 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.mvp.AbstractMvpEntryPoint;
public class AutoPlayEntryPoint extends AbstractMvpEntryPoint<StringMessages, AutoPlayAppClientFactory> {
@Override
public void doOnModuleLoad() {
AutoPlayAppClientFactory clientFactory = GWT.create(AutoPlayAppClientFactory.class);
@@ -5,7 +5,8 @@ import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.DefaultErrorReporter;
@@ -24,10 +25,12 @@ public class DesktopApplicationView extends Composite implements ApplicationTopL
private static ErrorReporter errorReporter = new DefaultErrorReporter<StringMessages>(StringMessages.INSTANCE);
@UiField
SimplePanel mainContentPanel;
SimpleLayoutPanel mainContentPanel;
public DesktopApplicationView(PlaceNavigator navigator) {
initWidget(uiBinder.createAndBindUi(this));
RootLayoutPanel.get().add(this.asWidget());
}
@Override
@@ -1,7 +1,5 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel>
<g:SimplePanel ui:field="mainContentPanel" />
</g:HTMLPanel>
<g:SimpleLayoutPanel ui:field="mainContentPanel" />
</ui:UiBinder>
@@ -1,9 +1,14 @@
package com.sap.sailing.gwt.autoplay.client.app;
import java.util.Map;
public interface PlaceNavigator {
void goToStart();
void goToPlayer(String eventUuidAsString, boolean fullscreen,
Map<String, String> leaderboardParameters, Map<String, String> raceboardParameters);
}
package com.sap.sailing.gwt.autoplay.client.app;
import com.sap.sailing.gwt.autoplay.client.place.player.AutoPlayerConfiguration;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
public interface PlaceNavigator {
void goToStart();
void goToPlayer(AutoPlayerConfiguration playerConfig, PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings,
PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecycleWithAllSettings);
}
@@ -1,32 +1,35 @@
package com.sap.sailing.gwt.autoplay.client.app;
import java.util.Map;
import com.google.gwt.place.shared.PlaceController;
import com.sap.sailing.gwt.autoplay.client.place.player.PlayerPlace;
import com.sap.sailing.gwt.autoplay.client.place.start.StartPlace;
public class PlaceNavigatorImpl implements PlaceNavigator {
private final PlaceController placeController;
protected PlaceNavigatorImpl(PlaceController placeController) {
super();
this.placeController = placeController;
}
@Override
public void goToStart() {
placeController.goTo(new StartPlace());
}
@Override
public void goToPlayer(String eventUuidAsString, boolean fullscreen,
Map<String, String> leaderboardParameters, Map<String, String> raceboardParameters) {
PlayerPlace playerPlace = new PlayerPlace(eventUuidAsString, fullscreen,
leaderboardParameters.get(PlayerPlace.PARAM_LEADEROARD_NAME),
leaderboardParameters.get(PlayerPlace.PARAM_LEADEROARD_ZOOM),
raceboardParameters.get(PlayerPlace.PARAM_RACEBOARD_AUTOSELECT_MEDIA));
placeController.goTo(playerPlace);
}
}
package com.sap.sailing.gwt.autoplay.client.app;
import com.google.gwt.place.shared.PlaceController;
import com.sap.sailing.gwt.autoplay.client.place.player.AutoPlayerConfiguration;
import com.sap.sailing.gwt.autoplay.client.place.player.PlayerPlace;
import com.sap.sailing.gwt.autoplay.client.place.start.StartPlace;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
public class PlaceNavigatorImpl implements PlaceNavigator {
private final PlaceController placeController;
protected PlaceNavigatorImpl(PlaceController placeController) {
super();
this.placeController = placeController;
}
@Override
public void goToStart() {
placeController.goTo(new StartPlace());
}
@Override
public void goToPlayer(
AutoPlayerConfiguration playerConfig,
PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings,
PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecyclesWithAllSettings) {
PlayerPlace playerPlace = new PlayerPlace(playerConfig, leaderboardPerspectiveLifecycleWithAllSettings, raceboardPerspectiveLifecyclesWithAllSettings);
placeController.goTo(playerPlace);
}
}
@@ -1,379 +1,236 @@
package com.sap.sailing.gwt.autoplay.client.place.player;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.BoatDTO;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeader;
import com.sap.sailing.gwt.autoplay.client.shared.oldleaderboard.OldLeaderboard;
import com.sap.sailing.gwt.common.client.CSS3Util;
import com.sap.sailing.gwt.common.client.FullscreenUtil;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
import com.sap.sailing.gwt.ui.client.MediaServiceAsync;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
import com.sap.sse.security.ui.client.UserService;
public class AutoPlayController implements RaceTimesInfoProviderListener {
private static final int REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD = 10000;
private static final long REFRESH_INTERVAL_IN_MILLIS_RACEBOARD = 1000;
private final SailingServiceAsync sailingService;
private final MediaServiceAsync mediaService;
private final UserService userService;
private final ErrorReporter errorReporter;
private final UserAgentDetails userAgent;
private final AsyncActionsExecutor asyncActionsExecutor;
/**
* We use two timers: one for the leaderboard, one for the race board. This way, we can stop one while the other continues.
* This way, the other component stops its auto-updates.
*/
private final Timer leaderboardTimer;
private final Timer raceboardTimer;
private final RaceTimesInfoProvider raceTimesInfoProvider;
private AutoPlayModes activeTvView;
private final boolean isfullscreenMode;
private boolean isInitialScreen = true;
// leaderboard related attributes
private LeaderboardDTO leaderboard;
private final String leaderboardName;
private final String leaderboardGroupName;
private final String leaderboardZoom;
private LeaderboardSettings leaderboardSettings;
// raceboard related attributes
private RegattaAndRaceIdentifier currentLiveRace;
private boolean showRaceDetails;
private boolean showWindChart;
private final RaceBoardViewConfiguration raceboardViewConfig;
private final PlayerView playerView;
private Widget currentContentWidget;
private static int SAP_HEADER_HEIGHT = 70;
public AutoPlayController(SailingServiceAsync sailingService, MediaServiceAsync mediaService,
UserService userService, ErrorReporter errorReporter, boolean isfullscreenMode,
String leaderboardGroupName, String leaderboardName, final String leaderboardZoom,
UserAgentDetails userAgent, long delayToLiveInMillis, boolean showRaceDetails,
RaceBoardViewConfiguration raceboardViewConfig, PlayerView playerView) {
this.raceboardViewConfig = raceboardViewConfig;
this.sailingService = sailingService;
this.mediaService = mediaService;
this.userService = userService;
this.isfullscreenMode = isfullscreenMode;
this.errorReporter = errorReporter;
this.leaderboardName = leaderboardName;
this.leaderboardZoom = leaderboardZoom;
this.leaderboardGroupName = leaderboardGroupName;
this.userAgent = userAgent;
this.showRaceDetails = showRaceDetails;
this.playerView = playerView;
asyncActionsExecutor = new AsyncActionsExecutor();
showWindChart = false;
leaderboard = null;
leaderboardSettings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, null, /* autoExpandFirstRace */ false, /* showRegattaRank */ true, /* showCompetitorSailIdColumn */ true, /* showCompetitorFullNameColumn */ true);
leaderboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
leaderboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
leaderboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD);
leaderboardTimer.play();
raceboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
raceboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
raceboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_RACEBOARD);
raceboardTimer.play();
raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, errorReporter, new ArrayList<RegattaAndRaceIdentifier>(), 3000l);
raceTimesInfoProvider.addRaceTimesInfoProviderListener(this);
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
if(leaderboardZoom != null && leaderboardZoom.equalsIgnoreCase("auto")) {
autoZoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget);
}
}
});
}
private LeaderboardPanel createLeaderboardPanel(String leaderboardGroupName, String leaderboardName, boolean showRaceDetails) {
CompetitorSelectionModel selectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true);
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
leaderboardSettings, true,
/* preSelectedRace */null, selectionModel, leaderboardTimer, leaderboardGroupName, leaderboardName,
errorReporter, StringMessages.INSTANCE, userAgent, showRaceDetails, /* competitorSearchTextBox */ null, /* showRegattaRank */
/* showSelectionCheckbox */false, /* raceTimesInfoProvider */null, false, /* autoExpandLastRaceColumn */
/* adjustTimerDelay */true, /*autoApplyTopNFilter*/ false, false) {
@Override
protected void setLeaderboard(LeaderboardDTO leaderboard) {
super.setLeaderboard(leaderboard);
AutoPlayController.this.leaderboard = leaderboard;
updateRaceTimesInfoProvider();
}
};
leaderboardPanel.getContentWidget().getElement().getStyle().setFontWeight(FontWeight.BOLD);
return leaderboardPanel;
}
private void updateRaceTimesInfoProvider() {
boolean addedRaces = false;
for (RaceColumnDTO race : leaderboard.getRaceList()) {
for (FleetDTO fleet : race.getFleets()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) {
raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false);
addedRaces = true;
}
}
}
if (addedRaces) {
raceTimesInfoProvider.forceTimesInfosUpdate();
}
}
private RaceBoardPanel createRaceBoardPanel(String leaderboardName, RegattaAndRaceIdentifier raceToShow, Map<CompetitorDTO, BoatDTO> competitorsAndTheirBoats) {
RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, userService, asyncActionsExecutor,
competitorsAndTheirBoats, raceboardTimer, raceToShow, leaderboardName, null, /* event */null, raceboardViewConfig,
errorReporter, StringMessages.INSTANCE, userAgent, raceTimesInfoProvider, /* showMapControls */ false,
/* isScreenLargeEnoughToOfferChartSupport */ true);
return raceBoardPanel;
}
private void showLeaderboard() {
if (activeTvView != AutoPlayModes.Leaderboard) {
playerView.clear();
boolean withFullscreenButton = isfullscreenMode && isInitialScreen;
SAPHeader sapHeader = new SAPHeader(TextMessages.INSTANCE.leaderboard() + ": " + leaderboardName, withFullscreenButton);
playerView.getDockPanel().addNorth(sapHeader, SAP_HEADER_HEIGHT);
LeaderboardPanel leaderboardPanel = createLeaderboardPanel(leaderboardGroupName, leaderboardName, showRaceDetails);
OldLeaderboard oldLeaderboard = new OldLeaderboard(leaderboardPanel);
leaderboardPanel.addLeaderboardUpdateListener(oldLeaderboard);
currentContentWidget = oldLeaderboard.getContentWidget();
if(leaderboardZoom != null) {
if(leaderboardZoom.equalsIgnoreCase("auto")) {
autoZoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget);
} else {
try {
Double zoom = Double.valueOf(leaderboardZoom);
zoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget, zoom);
} catch (NumberFormatException e) {
// do nothing
}
}
}
playerView.getDockPanel().add(oldLeaderboard);
currentLiveRace = null;
activeTvView = AutoPlayModes.Leaderboard;
raceboardTimer.pause();
leaderboardTimer.setPlayMode(PlayModes.Live);
isInitialScreen = false;
}
}
private void zoomContentWidget(final int headerHeight, final Widget contentWidget, final double scaleFactor) {
if(contentWidget != null) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
boolean invokeAgain = true;
if(currentContentWidget.getOffsetHeight() > 50) {
scaleContentWidget(headerHeight, contentWidget, scaleFactor);
FullscreenUtil.requestFullscreen();
invokeAgain = false;
}
return invokeAgain;
}
}, 1000);
}
}
private void autoZoomContentWidget(final int headerHeight, final Widget contentWidget) {
if(contentWidget != null) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
boolean invokeAgain = true;
if(currentContentWidget.getOffsetHeight() > 50) {
scaleContentWidget(headerHeight, contentWidget);
invokeAgain = false;
}
return invokeAgain;
}
}, 1000);
}
}
private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor) {
int clientWidth = Window.getClientWidth();
int contentWidth = contentWidget.getOffsetWidth();
double diffX = clientWidth - contentWidth * scaleFactor;
scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX);
}
private void scaleContentWidget(int headerHeight, Widget contentWidget) {
int clientWidth = Window.getClientWidth();
int clientHeight = Window.getClientHeight() - headerHeight;
int contentWidth = contentWidget.getOffsetWidth();
int contentHeight = contentWidget.getOffsetHeight();
double scaleFactorX = clientWidth / (double) contentWidth;
double scaleFactorY = clientHeight / (double) contentHeight;
Double scaleFactor = scaleFactorX > scaleFactorY ? scaleFactorY : scaleFactorX;
if(scaleFactor < 1.0) {
scaleFactor = 1.0;
}
double diffX = clientWidth - contentWidth * scaleFactor;
scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX);
}
private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor, double diffX) {
if(scaleFactor > 0.0) {
CSS3Util.setProperty(contentWidget.getElement().getStyle(), "transform", "translateX(" + diffX / 2.0 + "px) scale(" + scaleFactor + ")");
CSS3Util.setProperty(contentWidget.getElement().getStyle(), "transformOrigin", "0 0");
}
}
private void showRaceBoard() {
if (activeTvView != AutoPlayModes.Raceboard) {
sailingService.getRaceboardData(currentLiveRace.getRegattaName(), currentLiveRace.getRaceName(),
leaderboardName, null, null, new AsyncCallback<RaceboardDataDTO>() {
@Override
public void onSuccess(RaceboardDataDTO result) {
playerView.clear();
RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace, result.getCompetitorAndTheirBoats());
raceBoardPanel.setSize("100%", "100%");
if (showWindChart) {
raceBoardPanel.setWindChartVisible(true);
}
FlowPanel timePanel = createTimePanel(raceBoardPanel);
final Button toggleButton = raceBoardPanel.getTimePanel().getAdvancedToggleButton();
toggleButton.setVisible(false);
playerView.getDockPanel().addSouth(timePanel, 67);
playerView.getDockPanel().add(raceBoardPanel);
activeTvView = AutoPlayModes.Raceboard;
leaderboardTimer.pause();
raceboardTimer.setPlayMode(PlayModes.Live);
isInitialScreen = false;
}
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error while loading data for raceboard: " + caught.getMessage());
}
});
}
}
private FlowPanel createTimePanel(RaceBoardPanel raceBoardPanel) {
FlowPanel timeLineInnerBgPanel = new FlowPanel();
timeLineInnerBgPanel.addStyleName("timeLineInnerBgPanel");
timeLineInnerBgPanel.add(raceBoardPanel.getTimePanel());
FlowPanel timeLineInnerPanel = new FlowPanel();
timeLineInnerPanel.add(timeLineInnerBgPanel);
timeLineInnerPanel.addStyleName("timeLineInnerPanel");
FlowPanel timelinePanel = new FlowPanel();
timelinePanel.add(timeLineInnerPanel);
timelinePanel.addStyleName("timeLinePanel");
return timelinePanel;
}
public void updatePlayMode(AutoPlayModes tvView) {
switch (tvView) {
case Leaderboard:
showLeaderboard();
break;
case Raceboard:
showRaceBoard();
break;
}
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
raceboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
leaderboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
if (currentLiveRace != null) {
RaceTimesInfoDTO currentRaceTimes = raceTimesInfo.get(currentLiveRace);
Date endOfRace = currentRaceTimes.endOfRace;
long waitTimeAfterEndOfRace = 60 * 1000; // 1 min
if (endOfRace != null && raceboardTimer.getTime().getTime() > endOfRace.getTime() + waitTimeAfterEndOfRace
&& raceboardTimer.getPlayMode() == PlayModes.Live) {
updatePlayMode(AutoPlayModes.Leaderboard);
}
} else {
currentLiveRace = checkForLiveRace();
if (currentLiveRace != null) {
updatePlayMode(AutoPlayModes.Raceboard);
} else {
updatePlayMode(AutoPlayModes.Leaderboard);
}
}
}
private RegattaAndRaceIdentifier checkForLiveRace() {
RegattaAndRaceIdentifier result = null;
Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos = raceTimesInfoProvider.getRaceTimesInfos();
for (RaceColumnDTO race : leaderboard.getRaceList()) {
for (FleetDTO fleet : race.getFleets()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
if (raceIdentifier != null) {
RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier);
if (raceTimes != null && raceTimes.startOfTracking != null && raceTimes.endOfRace == null) {
return raceIdentifier;
}
}
}
}
return result;
}
}
package com.sap.sailing.gwt.autoplay.client.place.player;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspective;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener;
import com.sap.sailing.gwt.ui.client.MediaServiceAsync;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
import com.sap.sse.security.ui.client.UserService;
public class AutoPlayController implements RaceTimesInfoProviderListener, LeaderboardUpdateListener {
private static final int REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD = 10000;
private static final long REFRESH_INTERVAL_IN_MILLIS_RACEBOARD = 1000;
private static final long WAIT_TIME_AFTER_END_OF_RACE_MIILIS = 60 * 1000; // 1 min
private final SailingServiceAsync sailingService;
private final MediaServiceAsync mediaService;
private final UserService userService;
private final ErrorReporter errorReporter;
private final UserAgentDetails userAgent;
private final AsyncActionsExecutor asyncActionsExecutor;
/**
* We use two timers: one for the leaderboard, one for the race board. This way, we can stop one while the other continues.
* This way, the other component stops its auto-updates.
*/
private final Timer leaderboardTimer;
private final Timer raceboardTimer;
private final RaceTimesInfoProvider raceTimesInfoProvider;
private AutoPlayModes activeTvView;
private boolean isInitialScreen = true;
// leaderboard perspective related attributes
private LeaderboardDTO currentLeaderboard;
// raceboard perspective related attributes
private RegattaAndRaceIdentifier currentLiveRace;
private final PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings;
private final PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecycleWithAllSettings;
private final PlayerView playerView;
private final AutoPlayerConfiguration autoPlayerConfiguration;
public AutoPlayController(SailingServiceAsync sailingService, MediaServiceAsync mediaService,
UserService userService, ErrorReporter errorReporter, AutoPlayerConfiguration autoPlayerConfiguration,
UserAgentDetails userAgent, long delayToLiveInMillis, boolean showRaceDetails, PlayerView playerView,
PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings,
PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecycleWithAllSettings) {
this.sailingService = sailingService;
this.mediaService = mediaService;
this.userService = userService;
this.errorReporter = errorReporter;
this.autoPlayerConfiguration = autoPlayerConfiguration;
this.userAgent = userAgent;
this.playerView = playerView;
this.leaderboardPerspectiveLifecycleWithAllSettings = leaderboardPerspectiveLifecycleWithAllSettings;
this.raceboardPerspectiveLifecycleWithAllSettings = raceboardPerspectiveLifecycleWithAllSettings;
asyncActionsExecutor = new AsyncActionsExecutor();
currentLeaderboard = null;
leaderboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
leaderboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
leaderboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD);
leaderboardTimer.play();
raceboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
raceboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
raceboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_RACEBOARD);
raceboardTimer.play();
raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, errorReporter, new ArrayList<RegattaAndRaceIdentifier>(), 3000l);
raceTimesInfoProvider.addRaceTimesInfoProviderListener(this);
}
private void showLeaderboard() {
if (activeTvView != AutoPlayModes.Leaderboard) {
playerView.clearContent();
boolean withFullscreenButton = autoPlayerConfiguration.isFullscreenMode() && isInitialScreen;
LeaderboardWithHeaderPerspective leaderboardPerspective = new LeaderboardWithHeaderPerspective(leaderboardPerspectiveLifecycleWithAllSettings,
sailingService, asyncActionsExecutor,
new CompetitorSelectionModel(/* hasMultiSelection */ true), leaderboardTimer,
autoPlayerConfiguration.getLeaderboardName(), errorReporter, StringMessages.INSTANCE,
userAgent, withFullscreenButton);
playerView.setContent(leaderboardPerspective);
currentLiveRace = null;
activeTvView = AutoPlayModes.Leaderboard;
raceboardTimer.pause();
leaderboardTimer.setPlayMode(PlayModes.Live);
leaderboardPerspective.addLeaderboardUpdateListener(this);
isInitialScreen = false;
}
}
private void showRaceBoard() {
if (activeTvView != AutoPlayModes.Raceboard) {
sailingService.getRaceboardData(currentLiveRace.getRegattaName(), currentLiveRace.getRaceName(),
autoPlayerConfiguration.getLeaderboardName(), null, null, new AsyncCallback<RaceboardDataDTO>() {
@Override
public void onSuccess(RaceboardDataDTO result) {
playerView.clearContent();
RaceBoardPanel raceboardPerspective = new RaceBoardPanel(raceboardPerspectiveLifecycleWithAllSettings,
sailingService, mediaService, userService, asyncActionsExecutor,
result.getCompetitorAndTheirBoats(), raceboardTimer, currentLiveRace, autoPlayerConfiguration.getLeaderboardName(),
/** leaderboardGroupName */ null, /** eventId */ null, errorReporter,
StringMessages.INSTANCE, userAgent, raceTimesInfoProvider);
playerView.setContent(raceboardPerspective);
activeTvView = AutoPlayModes.Raceboard;
leaderboardTimer.pause();
raceboardTimer.setPlayMode(PlayModes.Live);
isInitialScreen = false;
}
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error while loading data for raceboard: " + caught.getMessage());
}
});
}
}
public void updatePlayMode(AutoPlayModes tvView) {
switch (tvView) {
case Leaderboard:
showLeaderboard();
break;
case Raceboard:
showRaceBoard();
break;
}
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
raceboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
leaderboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
if (currentLiveRace != null) {
RaceTimesInfoDTO currentRaceTimes = raceTimesInfo.get(currentLiveRace);
Date endOfRace = currentRaceTimes.endOfRace;
if (endOfRace != null && raceboardTimer.getTime().getTime() > endOfRace.getTime() + WAIT_TIME_AFTER_END_OF_RACE_MIILIS
&& raceboardTimer.getPlayMode() == PlayModes.Live) {
updatePlayMode(AutoPlayModes.Leaderboard);
}
} else {
currentLiveRace = checkForLiveRace(raceboardTimer.getLiveTimePointInMillis());
if (currentLiveRace != null) {
updatePlayMode(AutoPlayModes.Raceboard);
} else {
updatePlayMode(AutoPlayModes.Leaderboard);
}
}
}
private RegattaAndRaceIdentifier checkForLiveRace(long serverTimePointAsMillis) {
RegattaAndRaceIdentifier result = null;
Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos = raceTimesInfoProvider.getRaceTimesInfos();
for (RaceColumnDTO race : currentLeaderboard.getRaceList()) {
for (FleetDTO fleet : race.getFleets()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
if(raceIdentifier != null) {
RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier);
if (raceTimes != null && raceTimes.startOfTracking != null && raceTimes.getStartOfRace() != null && raceTimes.endOfRace == null) {
long startTimeInMs = raceTimes.getStartOfRace().getTime();
long timeToSwitchBeforeRaceStartInMs = autoPlayerConfiguration.getTimeToSwitchBeforeRaceStartInSeconds() * 1000;
long delayToLiveInMs = raceTimes.delayToLiveInMs;
// the switch to the live race should happen at a defined timepoint before the race start (default is 3 min)
if (serverTimePointAsMillis - delayToLiveInMs > startTimeInMs - timeToSwitchBeforeRaceStartInMs) {
return raceIdentifier;
}
}
}
}
}
return result;
}
private void updateRaceTimesInfoProvider() {
boolean addedRaces = false;
for (RaceColumnDTO race : currentLeaderboard.getRaceList()) {
for (FleetDTO fleet : race.getFleets()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) {
raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false);
addedRaces = true;
}
}
}
if (addedRaces) {
raceTimesInfoProvider.forceTimesInfosUpdate();
}
}
@Override
public void updatedLeaderboard(LeaderboardDTO leaderboard) {
this.currentLeaderboard = leaderboard;
updateRaceTimesInfoProvider();
}
@Override
public void currentRaceSelected(RaceIdentifier raceIdentifier, RaceColumnDTO raceColumn) {
// no-op
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.gwt.autoplay.client.place.player;
public class AutoPlayerConfiguration {
public final static String PARAM_EVENTID = "eventId";
public final static String PARAM_FULLSCREEN = "fullscreen";
public final static String PARAM_LEADEROARD_NAME = "leaderboardName";
public final static String PARAM_TIME_TO_SWITCH_BEFORE_RACE_START = "timeToSwitchBeforeRaceStart";
private String eventUidAsString;
private String leaderboardName;
private boolean fullscreenMode;
private long timeToSwitchBeforeRaceStartInSeconds;
public AutoPlayerConfiguration(String eventUidAsString, String leaderboardName, boolean fullscreenMode, long timeToSwitchBeforeRaceStartInSeconds) {
this.eventUidAsString = eventUidAsString;
this.leaderboardName = leaderboardName;
this.fullscreenMode = fullscreenMode;
this.timeToSwitchBeforeRaceStartInSeconds = timeToSwitchBeforeRaceStartInSeconds;
}
public String getEventUidAsString() {
return eventUidAsString;
}
public String getLeaderboardName() {
return leaderboardName;
}
public boolean isFullscreenMode() {
return fullscreenMode;
}
public long getTimeToSwitchBeforeRaceStartInSeconds() {
return timeToSwitchBeforeRaceStartInSeconds;
}
}
@@ -4,7 +4,7 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.autoplay.client.app.PlaceNavigator;
@@ -14,19 +14,19 @@ public class DesktopPlayerView extends Composite implements PlayerView {
interface PlayerViewUiBinder extends UiBinder<Widget, DesktopPlayerView> {
}
@UiField DockLayoutPanel dockPanel;
@UiField SimpleLayoutPanel contentPanel;
public DesktopPlayerView(PlaceNavigator navigator) {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void clear() {
dockPanel.clear();
public void clearContent() {
contentPanel.clear();
}
@Override
public DockLayoutPanel getDockPanel() {
return dockPanel;
public void setContent(Widget contentWidget) {
contentPanel.setWidget(contentWidget);
}
}
@@ -3,6 +3,5 @@
xmlns:s="urn:import:com.sap.sailing.gwt.autoplay.client.place"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<g:DockLayoutPanel ui:field="dockPanel" unit='PX'>
</g:DockLayoutPanel>
<g:SimpleLayoutPanel ui:field="contentPanel" />
</ui:UiBinder>
@@ -1,93 +1,63 @@
package com.sap.sailing.gwt.autoplay.client.place.player;
import java.util.UUID;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardEntryPoint;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Duration;
import com.sap.sse.gwt.client.mvp.ErrorView;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
public class PlayerActivity extends AbstractActivity {
private final PlayerClientFactory clientFactory;
private final PlayerPlace playerPlace;
private AutoPlayController autoPlayController;
private static final String PARAM_SHOW_RACE_DETAILS = "showRaceDetails";
private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis";
public PlayerActivity(PlayerPlace playerPlace, PlayerClientFactory clientFactory) {
this.playerPlace = playerPlace;
this.clientFactory = clientFactory;
this.autoPlayController = null;
}
@Override
public void start(final AcceptsOneWidget panel, EventBus eventBus) {
final boolean showRaceDetails = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_RACE_DETAILS, false);
final long delayToLiveMillis = Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS) != null ? Long
.valueOf(Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS)) : 5000l; // default 5s
UUID eventUUID = UUID.fromString(playerPlace.getEventUuidAsString());
clientFactory.getSailingService().getEventById(eventUUID, true, new AsyncCallback<EventDTO>() {
@Override
public void onSuccess(final EventDTO event) {
UserAgentDetails userAgent = new UserAgentDetails(Window.Navigator.getUserAgent());
RaceBoardViewConfiguration readRaceboardConfiguration = readRaceboardConfiguration();
PlayerView view = clientFactory.createPlayerView();
panel.setWidget(view.asWidget());
RootLayoutPanel.get().add(view.asWidget());
autoPlayController = new AutoPlayController(clientFactory.getSailingService(), clientFactory
.getMediaService(), clientFactory.getUserService(), clientFactory.getErrorReporter(), playerPlace
.isFullscreen(), /* leaderboardGroupName */"", playerPlace.getLeaderboardIdAsNameString(),
playerPlace.getLeaderboardZoom(), userAgent, delayToLiveMillis, showRaceDetails,
readRaceboardConfiguration, view);
autoPlayController.updatePlayMode(AutoPlayModes.Leaderboard);
}
@Override
public void onFailure(Throwable caught) {
createErrorView("Error while loading the event with service getEventById()", caught, panel);
}
});
}
private RaceBoardViewConfiguration readRaceboardConfiguration() {
Boolean autoSelectMedia = Boolean.valueOf(playerPlace.getRaceboardAutoSelectMedia());
final boolean showLeaderboard = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_LEADERBOARD, true /* default */);
final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_WINDCHART, false /* default */);
final boolean showViewStreamlets = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLETS, false /* default */);
final boolean showViewStreamletColors = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLET_COLORS, false /* default */);
final boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, false /* default */);
final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default */);
String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/);
final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default */);
final Duration initialDurationAfterRaceStartInReplay = RaceBoardEntryPoint.parseDuration(GwtHttpRequestUtils.getStringParameter(
RaceBoardViewConfiguration.PARAM_TIME_AFTER_RACE_START_AS_HOURS_COLON_MILLIS_COLON_SECONDS, null /* default */));
return new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard,
showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, autoSelectMedia, defaultMedia, initialDurationAfterRaceStartInReplay);
}
private void createErrorView(String errorMessage, Throwable errorReason, AcceptsOneWidget panel) {
ErrorView view = clientFactory.createErrorView(errorMessage, errorReason);
panel.setWidget(view.asWidget());
}
}
package com.sap.sailing.gwt.autoplay.client.place.player;
import java.util.UUID;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.gwt.client.mvp.ErrorView;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
public class PlayerActivity extends AbstractActivity {
private final PlayerClientFactory clientFactory;
private final PlayerPlace playerPlace;
private AutoPlayController autoPlayController;
private static final String PARAM_SHOW_RACE_DETAILS = "showRaceDetails";
private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis";
public PlayerActivity(PlayerPlace playerPlace, PlayerClientFactory clientFactory) {
this.playerPlace = playerPlace;
this.clientFactory = clientFactory;
this.autoPlayController = null;
}
@Override
public void start(final AcceptsOneWidget panel, EventBus eventBus) {
final boolean showRaceDetails = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_RACE_DETAILS, false);
final long delayToLiveMillis = Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS) != null ? Long
.valueOf(Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS)) : 5000l; // default 5s
UUID eventUUID = UUID.fromString(playerPlace.getConfiguration().getEventUidAsString());
clientFactory.getSailingService().getEventById(eventUUID, true, new AsyncCallback<EventDTO>() {
@Override
public void onSuccess(final EventDTO event) {
UserAgentDetails userAgent = new UserAgentDetails(Window.Navigator.getUserAgent());
PlayerView view = clientFactory.createPlayerView();
panel.setWidget(view.asWidget());
autoPlayController = new AutoPlayController(clientFactory.getSailingService(), clientFactory
.getMediaService(), clientFactory.getUserService(), clientFactory.getErrorReporter(),
playerPlace.getConfiguration(), userAgent, delayToLiveMillis, showRaceDetails, view,
playerPlace.getLeaderboardPerspectiveLifecycleWithAllSettings(),
playerPlace.getRaceboardPerspectiveLifecycleWithAllSettings());
autoPlayController.updatePlayMode(AutoPlayModes.Leaderboard);
}
@Override
public void onFailure(Throwable caught) {
createErrorView("Error while loading the event with service getEventById()", caught, panel);
}
});
}
private void createErrorView(String errorMessage, Throwable errorReason, AcceptsOneWidget panel) {
ErrorView view = clientFactory.createErrorView(errorMessage, errorReason);
panel.setWidget(view.asWidget());
}
}
@@ -1,80 +1,65 @@
package com.sap.sailing.gwt.autoplay.client.place.player;
import com.google.gwt.place.shared.PlaceTokenizer;
import com.sap.sailing.gwt.common.client.AbstractBasePlace;
public class PlayerPlace extends AbstractBasePlace {
// general parameters
private final String eventUuidAsString;
private final boolean fullscreen;
public final static String PARAM_EVENTID = "eventId";
public final static String PARAM_FULLSCREEN = "fullscreen";
// leaderboard parameters
private final String leaderboardIdAsNameString;
private final String leaderboardZoom;
public final static String PARAM_LEADEROARD_NAME = "leaderboardName";
public final static String PARAM_LEADEROARD_ZOOM = "leaderboardZoom";
// raceboard parameters
private String raceboardAutoSelectMedia;
public final static String PARAM_RACEBOARD_AUTOSELECT_MEDIA = "autoSelectMedia";
public PlayerPlace(String url) {
super(url);
eventUuidAsString = getParameter(PARAM_EVENTID);
fullscreen = Boolean.valueOf(getParameter(PARAM_FULLSCREEN));
leaderboardIdAsNameString = getParameter(PARAM_LEADEROARD_NAME);
leaderboardZoom = getParameter(PARAM_LEADEROARD_ZOOM);
raceboardAutoSelectMedia = getParameter(PARAM_RACEBOARD_AUTOSELECT_MEDIA);
}
public PlayerPlace(String eventUuidAsString, boolean fullscreen,
String leaderboardIdAsNameString, String leaderboardZoomAsString, String raceboardAutoSelectMedia) {
super(PARAM_EVENTID, eventUuidAsString, PARAM_FULLSCREEN, String.valueOf(fullscreen),
PARAM_LEADEROARD_NAME, leaderboardIdAsNameString, PARAM_LEADEROARD_ZOOM, leaderboardZoomAsString,
PARAM_RACEBOARD_AUTOSELECT_MEDIA, raceboardAutoSelectMedia);
this.eventUuidAsString = eventUuidAsString;
this.fullscreen = fullscreen;
this.leaderboardIdAsNameString = leaderboardIdAsNameString;
this.leaderboardZoom = leaderboardZoomAsString;
this.raceboardAutoSelectMedia = raceboardAutoSelectMedia;
}
public String getEventUuidAsString() {
return eventUuidAsString;
}
public String getLeaderboardIdAsNameString() {
return leaderboardIdAsNameString;
}
public String getLeaderboardZoom() {
return leaderboardZoom;
}
public String getRaceboardAutoSelectMedia() {
return raceboardAutoSelectMedia;
}
public boolean isFullscreen() {
return fullscreen;
}
public static class Tokenizer implements PlaceTokenizer<PlayerPlace> {
@Override
public String getToken(PlayerPlace place) {
return place.getParametersAsToken();
}
@Override
public PlayerPlace getPlace(String url) {
return new PlayerPlace(url);
}
}
}
package com.sap.sailing.gwt.autoplay.client.place.player;
import com.google.gwt.place.shared.PlaceTokenizer;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
import com.sap.sailing.gwt.common.client.AbstractBasePlace;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
public class PlayerPlace extends AbstractBasePlace {
private final AutoPlayerConfiguration playerConfiguration;
private final PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings;
private final PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecycleWithAllSettings;
public PlayerPlace(String url) {
super(url);
String eventUuidAsString = getParameter(AutoPlayerConfiguration.PARAM_EVENTID);
String leaderboardName= getParameter(AutoPlayerConfiguration.PARAM_LEADEROARD_NAME);
Boolean fullscreen = Boolean.valueOf(getParameter(AutoPlayerConfiguration.PARAM_FULLSCREEN));
Integer timeToSwitchBeforeRaceStartInSeconds = Integer.valueOf(getParameter(AutoPlayerConfiguration.PARAM_TIME_TO_SWITCH_BEFORE_RACE_START));
this.playerConfiguration = new AutoPlayerConfiguration(eventUuidAsString, leaderboardName, fullscreen, timeToSwitchBeforeRaceStartInSeconds);
this.leaderboardPerspectiveLifecycleWithAllSettings = null;
this.raceboardPerspectiveLifecycleWithAllSettings = null;
}
public PlayerPlace(AutoPlayerConfiguration playerConfiguration,
PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecycleWithAllSettings,
PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecycleWithAllSettings) {
super(AutoPlayerConfiguration.PARAM_EVENTID, playerConfiguration.getEventUidAsString(),
AutoPlayerConfiguration.PARAM_FULLSCREEN, String.valueOf(playerConfiguration.isFullscreenMode()),
AutoPlayerConfiguration.PARAM_LEADEROARD_NAME, playerConfiguration.getLeaderboardName(),
AutoPlayerConfiguration.PARAM_TIME_TO_SWITCH_BEFORE_RACE_START, String.valueOf(playerConfiguration.getTimeToSwitchBeforeRaceStartInSeconds()));
this.playerConfiguration = playerConfiguration;
this.leaderboardPerspectiveLifecycleWithAllSettings = leaderboardPerspectiveLifecycleWithAllSettings;
this.raceboardPerspectiveLifecycleWithAllSettings = raceboardPerspectiveLifecycleWithAllSettings;
}
public AutoPlayerConfiguration getConfiguration() {
return this.playerConfiguration;
}
public static class Tokenizer implements PlaceTokenizer<PlayerPlace> {
@Override
public String getToken(PlayerPlace place) {
return place.getParametersAsToken();
}
@Override
public PlayerPlace getPlace(String url) {
return new PlayerPlace(url);
}
}
public PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> getLeaderboardPerspectiveLifecycleWithAllSettings() {
return leaderboardPerspectiveLifecycleWithAllSettings;
}
public PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> getRaceboardPerspectiveLifecycleWithAllSettings() {
return raceboardPerspectiveLifecycleWithAllSettings;
}
}
@@ -1,11 +1,10 @@
package com.sap.sailing.gwt.autoplay.client.place.player;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
public interface PlayerView {
Widget asWidget();
public void clear();
public DockLayoutPanel getDockPanel();
public void clearContent();
public void setContent(Widget contentWidget);
}
@@ -1,219 +1,270 @@
package com.sap.sailing.gwt.autoplay.client.place.start;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.gwt.autoplay.client.app.PlaceNavigator;
import com.sap.sailing.gwt.autoplay.client.place.player.PlayerPlace;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeader;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.event.LocaleChangeEvent;
public class DesktopStartView extends Composite implements StartView {
private static StartPageViewUiBinder uiBinder = GWT.create(StartPageViewUiBinder.class);
interface StartPageViewUiBinder extends UiBinder<Widget, DesktopStartView> {
}
@UiField(provided=true) SAPHeader sapHeader;
@UiField(provided=true) ListBox localeSelectionBox;
@UiField(provided=true) ListBox eventSelectionBox;
@UiField(provided=true) ListBox leaderboardSelectionBox;
@UiField CheckBox leaderboardAutoZoomBox;
@UiField CheckBox startInFullscreenModeBox;
@UiField CheckBox autoSelectMediaBox;
@UiField TextBox leaderboardZoomBox;
@UiField Button startAutoPlayButton;
@UiField DivElement leaderboardSelectionDiv;
@UiField DivElement leaderboardZoomDiv;
@UiField DivElement leaderboardAutoZoomDiv;
private final PlaceNavigator navigator;
private final EventBus eventBus;
private final List<EventDTO> events;
private Map<String, String> raceboardParameters;
private Map<String, String> leaderboardParameters;
public DesktopStartView(PlaceNavigator navigator, EventBus eventBus) {
super();
this.navigator = navigator;
this.eventBus = eventBus;
this.events = new ArrayList<EventDTO>();
this.raceboardParameters = new HashMap<String, String>();
this.leaderboardParameters = new HashMap<String, String>();
sapHeader = new SAPHeader("Auto player configuration", false);
eventSelectionBox = new ListBox();
eventSelectionBox.setMultipleSelect(false);
leaderboardSelectionBox = new ListBox();
leaderboardSelectionBox.setMultipleSelect(false);
localeSelectionBox = new ListBox();
localeSelectionBox.setMultipleSelect(false);
LocaleInfo currentLocale = LocaleInfo.getCurrentLocale();
int i = 0;
for (String localeName : LocaleInfo.getAvailableLocaleNames()) {
if(!localeName.equals("default")) {
String displayName = LocaleInfo.getLocaleNativeDisplayName(localeName);
localeSelectionBox.addItem(displayName);
if(currentLocale.getLocaleName().equals(localeName)) {
localeSelectionBox.setSelectedIndex(i);
}
i++;
}
}
initWidget(uiBinder.createAndBindUi(this));
this.ensureDebugId("AutoPlayStartView");
leaderboardAutoZoomBox.setValue(true);
leaderboardZoomBox.setEnabled(false);
startInFullscreenModeBox.setValue(true);
leaderboardSelectionDiv.getStyle().setVisibility(Visibility.HIDDEN);
leaderboardZoomDiv.getStyle().setVisibility(Visibility.HIDDEN);
leaderboardAutoZoomDiv.getStyle().setVisibility(Visibility.HIDDEN);
startAutoPlayButton.setEnabled(false);
startAutoPlayButton.addStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
}
@Override
public void setEvents(List<EventDTO> events) {
this.events.clear();
this.events.addAll(events);
eventSelectionBox.addItem("Please select an event");
for(EventDTO event: events) {
eventSelectionBox.addItem(event.getName());
}
}
@UiHandler("eventSelectionBox")
void onEventSelectionChange(ChangeEvent event) {
EventDTO selectedEvent = getSelectedEvent();
if(selectedEvent != null) {
leaderboardSelectionBox.clear();
leaderboardSelectionBox.addItem("Please select a leaderboard");
for(LeaderboardGroupDTO leaderboardGroup: selectedEvent.getLeaderboardGroups()) {
for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) {
leaderboardSelectionBox.addItem(leaderboard.name);
}
}
}
leaderboardSelectionDiv.getStyle().setVisibility(selectedEvent != null ? Visibility.VISIBLE : Visibility.HIDDEN);
}
@UiHandler("leaderboardSelectionBox")
void onLeaderboardSelectionChange(ChangeEvent event) {
String selectedLeaderboardName = getSelectedLeaderboardName();
if(selectedLeaderboardName != null) {
startAutoPlayButton.setEnabled(true);
startAutoPlayButton.removeStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
} else {
startAutoPlayButton.setEnabled(false);
startAutoPlayButton.addStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
}
leaderboardZoomDiv.getStyle().setVisibility(selectedLeaderboardName != null ? Visibility.VISIBLE : Visibility.HIDDEN);
leaderboardAutoZoomDiv.getStyle().setVisibility(selectedLeaderboardName != null ? Visibility.VISIBLE : Visibility.HIDDEN);
}
@UiHandler("localeSelectionBox")
void onLocaleSelectionChange(ChangeEvent event) {
String selectedLocale = getSelectedLocale();
LocaleChangeEvent localeChangeEvent = new LocaleChangeEvent(selectedLocale);
eventBus.fireEvent(localeChangeEvent);
}
@UiHandler("startAutoPlayButton")
void startAutoPlayClicked(ClickEvent event) {
EventDTO selectedEvent = getSelectedEvent();
String selectedLeaderboardName = getSelectedLeaderboardName();
String leaderboardZoom = getLeaderboardZoom();
Boolean isAutoSelectMedia = autoSelectMediaBox.getValue();
if(selectedEvent != null && selectedLeaderboardName != null) {
leaderboardParameters.put(PlayerPlace.PARAM_LEADEROARD_ZOOM, leaderboardZoom);
leaderboardParameters.put(PlayerPlace.PARAM_LEADEROARD_NAME, selectedLeaderboardName);
raceboardParameters.put(PlayerPlace.PARAM_RACEBOARD_AUTOSELECT_MEDIA, String.valueOf(isAutoSelectMedia));
navigator.goToPlayer(selectedEvent.id.toString(), startInFullscreenModeBox.getValue(),
leaderboardParameters, raceboardParameters);
}
}
@UiHandler("leaderboardAutoZoomBox")
public void onLeaderboardAutoZoomClicked(ValueChangeEvent<Boolean> ev) {
leaderboardZoomBox.setEnabled(!leaderboardAutoZoomBox.getValue());
}
private String getLeaderboardZoom() {
return leaderboardAutoZoomBox.getValue() == true ? "auto" : String.valueOf(leaderboardZoomBox.getValue());
}
private String getSelectedLocale() {
String result = null;
int selectedIndex = localeSelectionBox.getSelectedIndex();
if(selectedIndex >= 0) {
String selectedLocale = localeSelectionBox.getItemText(selectedIndex);
for (String localeName : LocaleInfo.getAvailableLocaleNames()) {
if(!localeName.equals("default")) {
String displayName = LocaleInfo.getLocaleNativeDisplayName(localeName);
if(displayName.equals(selectedLocale)) {
result = localeName;
break;
}
}
}
}
return result;
}
private String getSelectedLeaderboardName() {
String result = null;
int selectedIndex = leaderboardSelectionBox.getSelectedIndex();
if(selectedIndex > 0) {
result = leaderboardSelectionBox.getItemText(selectedIndex);
}
return result;
}
private EventDTO getSelectedEvent() {
EventDTO result = null;
int selectedIndex = eventSelectionBox.getSelectedIndex();
if(events != null && selectedIndex > 0) {
String selectedItemText = eventSelectionBox.getItemText(selectedIndex);
for(EventDTO event: events) {
if(event.getName().equals(selectedItemText)) {
result = event;
break;
}
}
}
return result;
}
}
package com.sap.sailing.gwt.autoplay.client.place.start;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.IntegerBox;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO;
import com.sap.sailing.gwt.autoplay.client.app.PlaceNavigator;
import com.sap.sailing.gwt.autoplay.client.place.player.AutoPlayerConfiguration;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
import com.sap.sailing.gwt.common.client.GWTLocaleUtil;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
import com.sap.sse.gwt.client.event.LocaleChangeEvent;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeLifecycleTabbedSettingsDialog;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycle;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication;
public class DesktopStartView extends Composite implements StartView {
private static StartPageViewUiBinder uiBinder = GWT.create(StartPageViewUiBinder.class);
interface StartPageViewUiBinder extends UiBinder<Widget, DesktopStartView> {
}
@UiField(provided=true) SAPHeaderWithAuthentication sapHeader;
@UiField(provided=true) ListBox localeSelectionBox;
@UiField(provided=true) ListBox eventSelectionBox;
@UiField(provided=true) ListBox leaderboardSelectionBox;
@UiField CheckBox startInFullscreenModeBox;
@UiField Button startAutoPlayButton;
@UiField DivElement leaderboardSelectionUi;
@UiField DivElement screenConfigurationUi;
@UiField FlowPanel leaderboardPerspectiveSettingsPanel;
@UiField FlowPanel raceboardPerspectiveSettingsPanel;
@UiField CheckBox autoSwitchToRaceboard;
@UiField IntegerBox timeToRaceStartInSeconds;
private final PlaceNavigator navigator;
private final EventBus eventBus;
private final List<EventDTO> events;
private PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> leaderboardPerspectiveLifecyclesAndSettings;
private PerspectiveLifecycleWithAllSettings<RaceBoardPerspectiveLifecycle, RaceBoardPerspectiveSettings> raceboardPerspectiveLifecyclesAndSettings;
private final int defaultTimeToRaceStartTimeInSeconds = 180;
public DesktopStartView(PlaceNavigator navigator, EventBus eventBus) {
super();
this.navigator = navigator;
this.eventBus = eventBus;
this.events = new ArrayList<EventDTO>();
sapHeader = new SAPHeaderWithAuthentication(StringMessages.INSTANCE.sapSailingAnalytics(), StringMessages.INSTANCE.autoplayConfiguration());
eventSelectionBox = new ListBox();
eventSelectionBox.setMultipleSelect(false);
leaderboardSelectionBox = new ListBox();
leaderboardSelectionBox.setMultipleSelect(false);
localeSelectionBox = new ListBox();
localeSelectionBox.setMultipleSelect(false);
LocaleInfo currentLocale = LocaleInfo.getCurrentLocale();
int i = 0;
for (String localeName : GWTLocaleUtil.getAvailableLocales()) {
String displayName = GWTLocaleUtil.getDecoratedLanguageDisplayNameWithDefaultLocaleSupport(localeName);
localeSelectionBox.addItem(displayName, localeName);
if (currentLocale.getLocaleName().equals(localeName)) {
localeSelectionBox.setSelectedIndex(i);
}
i++;
}
initWidget(uiBinder.createAndBindUi(this));
this.ensureDebugId("AutoPlayStartView");
startInFullscreenModeBox.setValue(true);
autoSwitchToRaceboard.setValue(true);
timeToRaceStartInSeconds.setValue(defaultTimeToRaceStartTimeInSeconds);
leaderboardSelectionUi.getStyle().setVisibility(Visibility.HIDDEN);
screenConfigurationUi.getStyle().setVisibility(Visibility.HIDDEN);
startAutoPlayButton.setEnabled(false);
startAutoPlayButton.addStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
}
private void updatePerspectives(AbstractLeaderboardDTO leaderboard) {
LeaderboardWithHeaderPerspectiveLifecycle leaderboardPerspectiveLifecycle = new LeaderboardWithHeaderPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE);
leaderboardPerspectiveLifecyclesAndSettings = new PerspectiveLifecycleWithAllSettings<>(leaderboardPerspectiveLifecycle, leaderboardPerspectiveLifecycle.createDefaultSettings());
RaceBoardPerspectiveLifecycle raceboardPerspectiveLifecycle = new RaceBoardPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE);
raceboardPerspectiveLifecyclesAndSettings = new PerspectiveLifecycleWithAllSettings<>(raceboardPerspectiveLifecycle, raceboardPerspectiveLifecycle.createDefaultSettings());
}
private <PL extends PerspectiveLifecycle<PS>, PS extends Settings> void openPerspectiveSettingsDialog(final PerspectiveLifecycleWithAllSettings<PL, PS> perspectiveLifecycleAndSettings) {
PerspectiveCompositeLifecycleTabbedSettingsDialog<PL,PS> dialog = new PerspectiveCompositeLifecycleTabbedSettingsDialog<>(StringMessages.INSTANCE,
perspectiveLifecycleAndSettings, perspectiveLifecycleAndSettings.getPerspectiveLifecycle().getLocalizedShortName(), new DialogCallback<PerspectiveCompositeSettings<PS>>() {
@Override
public void ok(PerspectiveCompositeSettings<PS> newSettings) {
perspectiveLifecycleAndSettings.setAllSettings(newSettings);
};
@Override
public void cancel() {
}
});
dialog.show();
}
@Override
public void setEvents(List<EventDTO> events) {
this.events.clear();
this.events.addAll(events);
eventSelectionBox.addItem(StringMessages.INSTANCE.pleaseSelectAnEvent());
for(EventDTO event: events) {
eventSelectionBox.addItem(event.getName());
}
}
@UiHandler("eventSelectionBox")
void onEventSelectionChange(ChangeEvent event) {
EventDTO selectedEvent = getSelectedEvent();
if(selectedEvent != null) {
leaderboardSelectionBox.clear();
leaderboardSelectionBox.addItem(StringMessages.INSTANCE.selectALeaderboard());
for(LeaderboardGroupDTO leaderboardGroup: selectedEvent.getLeaderboardGroups()) {
for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) {
leaderboardSelectionBox.addItem(leaderboard.name);
}
}
}
leaderboardSelectionUi.getStyle().setVisibility(selectedEvent != null ? Visibility.VISIBLE : Visibility.HIDDEN);
}
@UiHandler("leaderboardSelectionBox")
void onLeaderboardSelectionChange(ChangeEvent event) {
String selectedLeaderboardName = getSelectedLeaderboardName();
if(selectedLeaderboardName != null) {
startAutoPlayButton.setEnabled(true);
startAutoPlayButton.removeStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
StrippedLeaderboardDTO selectedLeaderboard = getSelectedLeaderboard();
this.updatePerspectives(selectedLeaderboard);
createPerspectiveSettingsUI(leaderboardPerspectiveLifecyclesAndSettings, leaderboardPerspectiveSettingsPanel);
createPerspectiveSettingsUI(raceboardPerspectiveLifecyclesAndSettings, raceboardPerspectiveSettingsPanel);
} else {
startAutoPlayButton.setEnabled(false);
startAutoPlayButton.addStyleName(SharedResources.INSTANCE.mainCss().buttoninactive());
}
screenConfigurationUi.getStyle().setVisibility(selectedLeaderboardName != null ? Visibility.VISIBLE : Visibility.HIDDEN);
}
private <PL extends PerspectiveLifecycle<PS>, PS extends Settings> void createPerspectiveSettingsUI(
final PerspectiveLifecycleWithAllSettings<PL,PS> perspectiveLifecycleWithAllSettings,
FlowPanel perspectiveSettingsPanel) {
perspectiveSettingsPanel.clear();
Button perspectiveSettingsButton = new Button(StringMessages.INSTANCE.settings());
perspectiveSettingsButton.getElement().getStyle().setMarginRight(10, Unit.PX);
perspectiveSettingsPanel.add(perspectiveSettingsButton);
perspectiveSettingsButton.setEnabled(perspectiveLifecycleWithAllSettings.getAllSettings().hasSettings());
perspectiveSettingsButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
openPerspectiveSettingsDialog(perspectiveLifecycleWithAllSettings);
}
});
}
@UiHandler("localeSelectionBox")
void onLocaleSelectionChange(ChangeEvent event) {
String selectedLocale = getSelectedLocale();
LocaleChangeEvent localeChangeEvent = new LocaleChangeEvent(selectedLocale);
eventBus.fireEvent(localeChangeEvent);
}
@UiHandler("startAutoPlayButton")
void startAutoPlayClicked(ClickEvent event) {
EventDTO selectedEvent = getSelectedEvent();
String selectedLeaderboardName = getSelectedLeaderboardName();
if(selectedEvent != null && selectedLeaderboardName != null) {
navigator.goToPlayer(new AutoPlayerConfiguration(selectedEvent.id.toString(), selectedLeaderboardName,
startInFullscreenModeBox.getValue(), timeToRaceStartInSeconds.getValue()),
leaderboardPerspectiveLifecyclesAndSettings, raceboardPerspectiveLifecyclesAndSettings);
}
}
private String getSelectedLocale() {
String result = null;
int selectedIndex = localeSelectionBox.getSelectedIndex();
if (selectedIndex >= 0) {
String selectedLocale = localeSelectionBox.getValue(selectedIndex);
for (String localeName : GWTLocaleUtil.getAvailableLocales()) {
if (selectedLocale.equals(localeName)) {
result = localeName;
break;
}
}
}
return result;
}
private String getSelectedLeaderboardName() {
String result = null;
int selectedIndex = leaderboardSelectionBox.getSelectedIndex();
if(selectedIndex > 0) {
result = leaderboardSelectionBox.getItemText(selectedIndex);
}
return result;
}
private StrippedLeaderboardDTO getSelectedLeaderboard() {
EventDTO selectedEvent = getSelectedEvent();
String selectedLeaderboardName = getSelectedLeaderboardName();
for (LeaderboardGroupDTO leaderboardGroup : selectedEvent.getLeaderboardGroups()) {
for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.getLeaderboards()) {
if (leaderboard.name.equals(selectedLeaderboardName)) {
return leaderboard;
}
}
}
return null;
}
private EventDTO getSelectedEvent() {
EventDTO result = null;
int selectedIndex = eventSelectionBox.getSelectedIndex();
if(events != null && selectedIndex > 0) {
String selectedItemText = eventSelectionBox.getItemText(selectedIndex);
for(EventDTO event: events) {
if(event.getName().equals(selectedItemText)) {
result = event;
break;
}
}
}
return result;
}
}
@@ -1,75 +1,109 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sailing.gwt.autoplay.client.shared"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<g:HTMLPanel>
<s:header.SAPHeader ui:field="sapHeader" />
<div style="height:1em;" />
<div class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Display language:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:ListBox ui:field="localeSelectionBox" />
</div>
</div>
<div class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Start browser in full screen mode:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:CheckBox ui:field="startInFullscreenModeBox" />
</div>
</div>
<div class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Event:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:ListBox ui:field="eventSelectionBox" />
</div>
</div>
<div ui:field="leaderboardSelectionDiv" class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Leaderboard:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:ListBox ui:field="leaderboardSelectionBox" />
</div>
</div>
<div ui:field="leaderboardAutoZoomDiv" class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Leaderboard Auto-Zoom:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:CheckBox ui:field="leaderboardAutoZoomBox" />
</div>
</div>
<div ui:field="leaderboardZoomDiv" class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Leaderboard Zoom-Factor:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:TextBox ui:field="leaderboardZoomBox" />
</div>
</div>
<div class="{res.mediaCss.grid}" style="padding-bottom:1em;">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<span>Auto-Play video:</span>
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:CheckBox ui:field="autoSelectMediaBox" />
</div>
</div>
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
&nbsp;
</div>
<div class="{res.mediaCss.small2} {res.mediaCss.columns}">
<g:Button ui:field="startAutoPlayButton" text="Start autoplay" styleName="{res.mainCss.button}" />
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sse.security.ui.authentication.generic.sapheader"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_ubi" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:style>
.row {
padding-bottom:1em;
}
.perspectiveConfigurationPanel {
width: 100%;
}
.headline {
background-color: #eeeeee;
margin-top: 1em;
margin-bottom: 1em;
}
</ui:style>
<g:HTMLPanel>
<s:SAPHeaderWithAuthentication ui:field="sapHeader" />
<div style="height:1em;" />
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n_ubi.chooseALanguage}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:ListBox ui:field="localeSelectionBox" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.event}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:ListBox ui:field="eventSelectionBox" />
</div>
</div>
<div ui:field="leaderboardSelectionUi" class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.leaderboard}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:ListBox ui:field="leaderboardSelectionBox" />
</div>
</div>
<div ui:field="screenConfigurationUi">
<div class="{res.mediaCss.grid} {style.row} {style.headline}">
<div class="{res.mediaCss.columns}"><ui:text from='{i18n.autoplaySettings}' /></div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.startBrowserFullscreen}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:CheckBox ui:field="startInFullscreenModeBox" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.switchToLiveRaceAutomatically}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:CheckBox ui:field="autoSwitchToRaceboard" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.timeBeforeRaceStart}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:IntegerBox ui:field="timeToRaceStartInSeconds" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row} {style.headline}">
<div class="{res.mediaCss.columns}"><ui:text from='{i18n.page}' />&nbsp;<ui:text from='{i18n.settings}' /></div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.leaderboard}' /> <ui:text from='{i18n.page}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:FlowPanel ui:field="leaderboardPerspectiveSettingsPanel" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
<span><ui:text from='{i18n.raceViewer}' /> <ui:text from='{i18n.page}' />:</span>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:FlowPanel ui:field="raceboardPerspectiveSettingsPanel" />
</div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.columns}"><hr/></div>
</div>
<div class="{res.mediaCss.grid} {style.row}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large3} {res.mediaCss.columns}">
&nbsp;
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large9} {res.mediaCss.columns}">
<g:Button ui:field="startAutoPlayButton" text="{i18n.startAutoplay}" styleName="{res.mainCss.button}" />
</div>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,44 +0,0 @@
.siteheader {
font-size: 15px;
font-size: 1rem;
background: #333;
border-bottom: 5px solid #f0ab00;
height: 70px;
line-height: 4em;
width: 100%;
overflow: hidden;
text-align:center;
}
.siteheaderLeft {
float:left;
width: 25%;
text-align: left;
}
.siteheaderCentered {
width: 50%;
display: inline-block;
margin:0 auto;
}
.siteheaderRight {
float:right;
width: 25%;
text-align: right;
}
.logo {
margin: 0.8em 10px;
float: left;
}
.logotitle {
display: inline;
color: #f6f9fc;
font-weight: bold;
}
.pagetitle {
color: #ffffff;
font-size: 1.5rem;
font-weight: bold;
}
@@ -1,48 +0,0 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.FullscreenUtil;
public class SAPHeader extends Composite {
private static SAPHeaderUiBinder uiBinder = GWT.create(SAPHeaderUiBinder.class);
interface SAPHeaderUiBinder extends UiBinder<Widget, SAPHeader> {
}
@UiField DivElement pageTitleDiv;
@UiField Button startFullScreenButton;
public SAPHeader(String pageTitle, boolean startInAutoScreenMode) {
SAPHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
pageTitleDiv.setInnerText(pageTitle);
startFullScreenButton.setVisible(startInAutoScreenMode);
// the 'fullscreen' button should disappear after some seconds (10)
if(startInAutoScreenMode) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
startFullScreenButton.setVisible(false);
return false;
}
}, 10000);
}
}
@UiHandler("startFullScreenButton")
void startFullScreenClicked(ClickEvent e) {
FullscreenUtil.requestFullscreen();
}
}
@@ -1,22 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeaderResources" />
<g:HTMLPanel>
<header class="{local_res.css.siteheader}">
<div class="{local_res.css.siteheaderLeft}">
<g:Image resource="{local_res.logo}" pixelSize="80, 40" altText="SAP Sailing Analytics" styleName="{local_res.css.logo}"/>
<p class="{local_res.css.logotitle}">Sailing Analytics</p>
</div>
<div class="{local_res.css.siteheaderCentered}">
<div ui:field="pageTitleDiv" class="{local_res.css.pagetitle}"></div>
</div>
<div class="{local_res.css.siteheaderRight}">
<g:Button ui:field="startFullScreenButton" styleName="{res.mainCss.button}" text="Fullscreen" />
<span>&nbsp;</span>
</div>
</header>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,71 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.FullscreenUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.sapheader.SAPHeader;
import com.sap.sse.gwt.client.shared.components.AbstractCompositeComponent;
public class SAPHeaderComponent extends AbstractCompositeComponent<SAPHeaderComponentSettings> {
private SAPHeaderComponentSettings settings;
private final SAPHeaderComponentLifecycle componentLifecycle;
private final SAPHeader sapHeader;
public SAPHeaderComponent(SAPHeaderComponentLifecycle componentLifecycle, SAPHeaderComponentSettings settings,
StringMessages stringMessages, boolean startInAutoScreenMode) {
this.componentLifecycle = componentLifecycle;
this.settings = settings;
this.sapHeader = new SAPHeader(stringMessages.sapSailingAnalytics());
sapHeader.setHeaderTitle(settings.getTitle());
initWidget(sapHeader);
if(startInAutoScreenMode) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
FullscreenUtil.requestFullscreen();
return false;
}
}, 1000);
}
}
@Override
public String getLocalizedShortName() {
return componentLifecycle.getLocalizedShortName();
}
@Override
public Widget getEntryWidget() {
return this;
}
@Override
public boolean hasSettings() {
return componentLifecycle.hasSettings();
}
@Override
public SAPHeaderComponentSettingsDialogComponent getSettingsDialogComponent() {
return componentLifecycle.getSettingsDialogComponent(settings);
}
@Override
public SAPHeaderComponentSettings getSettings() {
return settings;
}
@Override
public void updateSettings(SAPHeaderComponentSettings newSettings) {
this.settings = newSettings;
sapHeader.setHeaderTitle(settings.getTitle());
}
@Override
public String getDependentCssClassName() {
return "";
}
}
@@ -0,0 +1,47 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import java.io.Serializable;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class SAPHeaderComponentLifecycle implements ComponentLifecycle<SAPHeaderComponentSettings, SAPHeaderComponentSettingsDialogComponent> {
private final StringMessages stringMessages;
private final String defaultTitle;
public SAPHeaderComponentLifecycle(String defaultTitle, StringMessages stringMessages) {
this.defaultTitle = defaultTitle;
this.stringMessages = stringMessages;
}
@Override
public SAPHeaderComponentSettingsDialogComponent getSettingsDialogComponent(SAPHeaderComponentSettings settings) {
return new SAPHeaderComponentSettingsDialogComponent(cloneSettings(settings), stringMessages);
}
@Override
public SAPHeaderComponentSettings createDefaultSettings() {
return new SAPHeaderComponentSettings(defaultTitle);
}
@Override
public SAPHeaderComponentSettings cloneSettings(SAPHeaderComponentSettings settings) {
return new SAPHeaderComponentSettings(settings.getTitle());
}
@Override
public String getLocalizedShortName() {
return "SAP Header";
}
@Override
public boolean hasSettings() {
return true;
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
}
@@ -0,0 +1,22 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import com.sap.sse.common.settings.AbstractSettings;
public class SAPHeaderComponentSettings extends AbstractSettings {
private final String title;
/**
* The default settings
*/
public SAPHeaderComponentSettings() {
title = "";
}
public SAPHeaderComponentSettings(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
@@ -0,0 +1,60 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class SAPHeaderComponentSettingsDialogComponent implements SettingsDialogComponent<SAPHeaderComponentSettings> {
private final SAPHeaderComponentSettings initialSettings;
private TextBox titleTextBox;
private final StringMessages stringMessages;
public SAPHeaderComponentSettingsDialogComponent(SAPHeaderComponentSettings initialSettings, StringMessages stringMessages) {
super();
this.stringMessages = stringMessages;
this.initialSettings = initialSettings;
}
@Override
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
VerticalPanel vp = new VerticalPanel();
Grid grid = new Grid(1,2);
grid.setCellSpacing(5);
vp.add(grid);
titleTextBox = dialog.createTextBox(initialSettings.getTitle());
grid.setWidget(0, 0, new Label(stringMessages.title() + ":"));
grid.setWidget(0, 1, titleTextBox);
return vp;
}
@Override
public SAPHeaderComponentSettings getResult() {
return new SAPHeaderComponentSettings(titleTextBox.getValue());
}
@Override
public Validator<SAPHeaderComponentSettings> getValidator() {
return new Validator<SAPHeaderComponentSettings>() {
@Override
public String getErrorMessage(SAPHeaderComponentSettings valueToValidate) {
return null;
}
};
}
@Override
public FocusWidget getFocusWidget() {
return titleTextBox;
}
}
@@ -1,26 +0,0 @@
package com.sap.sailing.gwt.autoplay.client.shared.header;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
public interface SAPHeaderResources extends ClientBundle {
public static final SAPHeaderResources INSTANCE = GWT.create(SAPHeaderResources.class);
@Source("com/sap/sailing/gwt/autoplay/client/shared/header/SAPHeader.css")
LocalCss css();
public interface LocalCss extends CssResource {
String siteheader();
String siteheaderLeft();
String siteheaderCentered();
String siteheaderRight();
String logo();
String logotitle();
String pagetitle();
}
@Source("logo-small@2x.png")
ImageResource logo();
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -0,0 +1,80 @@
package com.sap.sailing.gwt.autoplay.client.shared.leaderboard;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DoubleBox;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class LeaderboardPerspectiveSettingsDialogComponent implements SettingsDialogComponent<LeaderboardWithHeaderPerspectiveSettings> {
private CheckBox leaderboardAutoZoomBox;
private DoubleBox leaderboardZoomFactorBox;
private final StringMessages stringMessages;
private final LeaderboardWithHeaderPerspectiveSettings initialSettings;
public LeaderboardPerspectiveSettingsDialogComponent(LeaderboardWithHeaderPerspectiveSettings settings, StringMessages stringMessages) {
this.initialSettings = settings;
this.stringMessages = stringMessages;
}
@Override
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
VerticalPanel vp = new VerticalPanel();
Grid grid = new Grid(2,2);
vp.add(grid);
leaderboardAutoZoomBox = dialog.createCheckbox("");
leaderboardAutoZoomBox.setValue(initialSettings.isLeaderboardAutoZoom());
leaderboardAutoZoomBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
leaderboardZoomFactorBox.setEnabled(!event.getValue());
}
});
grid.setWidget(0, 0, new Label(stringMessages.autoZoom()));
grid.setWidget(0, 1, leaderboardAutoZoomBox);
leaderboardZoomFactorBox = dialog.createDoubleBox(5);
leaderboardZoomFactorBox.setValue(initialSettings.getLeaderboardZoomFactor());
leaderboardZoomFactorBox.setEnabled(!initialSettings.isLeaderboardAutoZoom());
grid.setWidget(1, 0, new Label(stringMessages.zoomFactor()));
grid.setWidget(1, 1, leaderboardZoomFactorBox);
return vp;
}
@Override
public LeaderboardWithHeaderPerspectiveSettings getResult() {
LeaderboardWithHeaderPerspectiveSettings result = new LeaderboardWithHeaderPerspectiveSettings(leaderboardAutoZoomBox.getValue(), leaderboardZoomFactorBox.getValue());
return result;
}
@Override
public Validator<LeaderboardWithHeaderPerspectiveSettings> getValidator() {
return new Validator<LeaderboardWithHeaderPerspectiveSettings>() {
@Override
public String getErrorMessage(LeaderboardWithHeaderPerspectiveSettings valueToValidate) {
String errorMessage = null;
return errorMessage;
}
};
}
@Override
public FocusWidget getFocusWidget() {
return leaderboardAutoZoomBox;
}
}
@@ -0,0 +1,229 @@
package com.sap.sailing.gwt.autoplay.client.shared.leaderboard;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeaderComponent;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeaderComponentLifecycle;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeaderComponentSettings;
import com.sap.sailing.gwt.autoplay.client.shared.oldleaderboard.OldLeaderboard;
import com.sap.sailing.gwt.common.client.CSS3Util;
import com.sap.sailing.gwt.common.client.FullscreenUtil;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener;
import com.sap.sailing.gwt.ui.client.LeaderboardUpdateProvider;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanelLifecycle;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.gwt.client.shared.perspective.AbstractPerspectiveComposite;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
/**
* A perspective managing a header with a single leaderboard filling the rest of the screen.
*
* @author Frank Mittag
*
*/
public class LeaderboardWithHeaderPerspective extends AbstractPerspectiveComposite<LeaderboardWithHeaderPerspectiveLifecycle,
LeaderboardWithHeaderPerspectiveSettings> implements LeaderboardUpdateProvider {
private final DockLayoutPanel dockPanel;
private final static int SAP_HEADER_HEIGHT = 70;
private final Widget currentContentWidget;
private final LeaderboardPanel leaderboardPanel;
private final StringMessages stringMessages;
private final PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> componentLifecyclesAndSettings;
public LeaderboardWithHeaderPerspective(PerspectiveLifecycleWithAllSettings<LeaderboardWithHeaderPerspectiveLifecycle, LeaderboardWithHeaderPerspectiveSettings> perspectiveLifecycleWithAllSettings,
SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
CompetitorSelectionProvider competitorSelectionProvider, Timer timer,
String leaderboardName, final ErrorReporter errorReporter, final StringMessages stringMessages,
UserAgentDetails userAgent, boolean startInFullScreenMode) {
super(perspectiveLifecycleWithAllSettings.getPerspectiveLifecycle(), perspectiveLifecycleWithAllSettings.getPerspectiveSettings());
this.stringMessages = stringMessages;
this.componentLifecyclesAndSettings = perspectiveLifecycleWithAllSettings;
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
if(LeaderboardWithHeaderPerspective.this.getPerspectiveSettings().isLeaderboardAutoZoom()) {
autoZoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget);
}
}
});
SAPHeaderComponentLifecycle sapHeaderLifecycle = getPerspectiveLifecycle().getSapHeaderLifecycle();
SAPHeaderComponent sapHeader = createSAPHeader(sapHeaderLifecycle,
perspectiveLifecycleWithAllSettings.findComponentSettingsByLifecycle(sapHeaderLifecycle),
stringMessages, startInFullScreenMode);
leaderboardPanel = createLeaderboardPanel(sailingService, asyncActionsExecutor,
competitorSelectionProvider, timer, leaderboardName, errorReporter, stringMessages, userAgent);
leaderboardPanel.getContentWidget().getElement().getStyle().setFontWeight(FontWeight.BOLD);
components.add(sapHeader);
components.add(leaderboardPanel);
dockPanel = new DockLayoutPanel(Unit.PX);
dockPanel.addNorth(sapHeader, SAP_HEADER_HEIGHT);
OldLeaderboard oldLeaderboard = new OldLeaderboard(leaderboardPanel);
leaderboardPanel.addLeaderboardUpdateListener(oldLeaderboard);
currentContentWidget = oldLeaderboard.getContentWidget();
if(getPerspectiveSettings().isLeaderboardAutoZoom()) {
autoZoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget);
} else {
Double zoom = getPerspectiveSettings().getLeaderboardZoomFactor();
zoomContentWidget(SAP_HEADER_HEIGHT, currentContentWidget, zoom);
}
dockPanel.add(oldLeaderboard);
initWidget(dockPanel);
}
@Override
public Widget getEntryWidget() {
return this;
}
@Override
public boolean isVisible() {
return false;
}
@Override
public void setVisible(boolean visibility) {
}
@Override
public String getDependentCssClassName() {
return "";
}
private void zoomContentWidget(final int headerHeight, final Widget contentWidget, final double scaleFactor) {
if(contentWidget != null) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
boolean invokeAgain = true;
if(currentContentWidget.getOffsetHeight() > 50) {
scaleContentWidget(headerHeight, contentWidget, scaleFactor);
FullscreenUtil.requestFullscreen();
invokeAgain = false;
}
return invokeAgain;
}
}, 1000);
}
}
private void autoZoomContentWidget(final int headerHeight, final Widget contentWidget) {
if(contentWidget != null) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
boolean invokeAgain = true;
if(currentContentWidget.getOffsetHeight() > 50) {
scaleContentWidget(headerHeight, contentWidget);
invokeAgain = false;
}
return invokeAgain;
}
}, 1000);
}
}
private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor) {
int clientWidth = Window.getClientWidth();
int contentWidth = contentWidget.getOffsetWidth();
double diffX = clientWidth - contentWidth * scaleFactor;
scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX);
}
private void scaleContentWidget(int headerHeight, Widget contentWidget) {
int clientWidth = Window.getClientWidth();
int clientHeight = Window.getClientHeight() - headerHeight;
int contentWidth = contentWidget.getOffsetWidth();
int contentHeight = contentWidget.getOffsetHeight();
double scaleFactorX = clientWidth / (double) contentWidth;
double scaleFactorY = clientHeight / (double) contentHeight;
Double scaleFactor = scaleFactorX > scaleFactorY ? scaleFactorY : scaleFactorX;
if(scaleFactor < 1.0) {
scaleFactor = 1.0;
}
double diffX = clientWidth - contentWidth * scaleFactor;
scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX);
}
private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor, double diffX) {
if(scaleFactor > 0.0) {
CSS3Util.setProperty(contentWidget.getElement().getStyle(), "transform", "translateX(" + diffX / 2.0 + "px) scale(" + scaleFactor + ")");
CSS3Util.setProperty(contentWidget.getElement().getStyle(), "transformOrigin", "0 0");
}
}
@Override
public void addLeaderboardUpdateListener(LeaderboardUpdateListener listener) {
leaderboardPanel.addLeaderboardUpdateListener(listener);
}
@Override
public void removeLeaderboardUpdateListener(LeaderboardUpdateListener listener) {
leaderboardPanel.removeLeaderboardUpdateListener(listener);
}
private SAPHeaderComponent createSAPHeader(SAPHeaderComponentLifecycle componentLifecycle, SAPHeaderComponentSettings settings,
final StringMessages stringMessages, boolean withFullscreenButton) {
return new SAPHeaderComponent(componentLifecycle, settings, stringMessages, withFullscreenButton);
}
private LeaderboardPanel createLeaderboardPanel(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
CompetitorSelectionProvider competitorSelectionProvider, Timer timer,
String leaderboardName, final ErrorReporter errorReporter, final StringMessages stringMessages,
final UserAgentDetails userAgent) {
LeaderboardPanelLifecycle leaderboardPanelLifecycle = getPerspectiveLifecycle().getLeaderboardPanelLifecycle();
LeaderboardSettings leaderboardSettings = componentLifecyclesAndSettings.findComponentSettingsByLifecycle(leaderboardPanelLifecycle);
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
leaderboardSettings, /*isEmbedded*/true, /* preSelectedRace */null,
competitorSelectionProvider, timer, /* leaderboardGroupName */"",
leaderboardName, errorReporter, stringMessages,
userAgent, /*showRaceDetails */false, /* competitorSearchTextBox */ null, /* showRegattaRank */
/* showSelectionCheckbox */false, /* raceTimesInfoProvider */null, false, /* autoExpandLastRaceColumn */
/* adjustTimerDelay */true, /*autoApplyTopNFilter*/ false, false);
return leaderboardPanel;
}
@Override
public SettingsDialogComponent<LeaderboardWithHeaderPerspectiveSettings> getPerspectiveOwnSettingsDialogComponent() {
return new LeaderboardPerspectiveSettingsDialogComponent(getPerspectiveSettings(), stringMessages);
}
@Override
public boolean hasPerspectiveOwnSettings() {
return true;
}
}
@@ -0,0 +1,61 @@
package com.sap.sailing.gwt.autoplay.client.shared.leaderboard;
import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO;
import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeaderComponentLifecycle;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanelLifecycle;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.gwt.client.shared.perspective.AbstractPerspectiveLifecycle;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings;
public class LeaderboardWithHeaderPerspectiveLifecycle extends AbstractPerspectiveLifecycle<LeaderboardWithHeaderPerspectiveSettings> {
private final SAPHeaderComponentLifecycle sapHeaderLifecycle;
private final LeaderboardPanelLifecycle leaderboardPanelLifecycle;
private final StringMessages stringMessages;
public LeaderboardWithHeaderPerspectiveLifecycle(AbstractLeaderboardDTO leaderboard, StringMessages stringMessages) {
super();
this.stringMessages = stringMessages;
this.leaderboardPanelLifecycle = new LeaderboardPanelLifecycle(leaderboard, stringMessages);
this.sapHeaderLifecycle = new SAPHeaderComponentLifecycle(stringMessages.leaderboard() + ": " + leaderboard.getDisplayName(), stringMessages);
this.componentLifecycles.add(leaderboardPanelLifecycle);
this.componentLifecycles.add(sapHeaderLifecycle);
}
@Override
public LeaderboardWithHeaderPerspectiveSettings createPerspectiveOwnDefaultSettings() {
return new LeaderboardWithHeaderPerspectiveSettings();
}
@Override
public PerspectiveCompositeSettings<LeaderboardWithHeaderPerspectiveSettings> cloneSettings(
PerspectiveCompositeSettings<LeaderboardWithHeaderPerspectiveSettings> settings) {
throw new UnsupportedOperationException("Method not implemented yet.");
}
@Override
public SettingsDialogComponent<LeaderboardWithHeaderPerspectiveSettings> getPerspectiveOwnSettingsDialogComponent(LeaderboardWithHeaderPerspectiveSettings perspectiveSettings) {
return new LeaderboardPerspectiveSettingsDialogComponent(perspectiveSettings, stringMessages);
}
@Override
public String getLocalizedShortName() {
return stringMessages.leaderboard() + " " + stringMessages.page();
}
@Override
public boolean hasSettings() {
return true;
}
public SAPHeaderComponentLifecycle getSapHeaderLifecycle() {
return sapHeaderLifecycle;
}
public LeaderboardPanelLifecycle getLeaderboardPanelLifecycle() {
return leaderboardPanelLifecycle;
}
}
@@ -0,0 +1,34 @@
package com.sap.sailing.gwt.autoplay.client.shared.leaderboard;
import com.sap.sse.common.settings.AbstractSettings;
/**
* Represents the parameters for configuring a standalone leaderboard with a header view
*
* @author Frank
*
*/
public class LeaderboardWithHeaderPerspectiveSettings extends AbstractSettings {
private final boolean leaderboardAutoZoom;
private final Double leaderboardZoomFactor;
public final static String PARAM_LEADEROARD_AUTO_ZOOM = "leaderboardAutoZoom";
public final static String PARAM_LEADEROARD_ZOOM_FACTOR = "leaderboardZoomFactor";
public LeaderboardWithHeaderPerspectiveSettings() {
this(true, 1.0);
}
public LeaderboardWithHeaderPerspectiveSettings(boolean leaderboardAutoZoom, Double leaderboardZoomFactor) {
this.leaderboardAutoZoom = leaderboardAutoZoom;
this.leaderboardZoomFactor = leaderboardZoomFactor;
}
public boolean isLeaderboardAutoZoom() {
return leaderboardAutoZoom;
}
public Double getLeaderboardZoomFactor() {
return leaderboardZoomFactor;
}
}
@@ -208,6 +208,7 @@ public interface TextMessages extends Messages {
String solutionsTrainingText();
String solutionsSimulatorText();
String sapSailingAnalytics();
String autoPlayerConfiguration();
String contentSapSailingAnalytics1();
String contentSapSailingAnalytics2();
@@ -199,6 +199,7 @@ solutionsPostText=Access to data collected at sailing events gives sailors the o
solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete''s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.
solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
autoPlayerConfiguration=Auto Player Configuration
sapSailingAnalytics=SAP Sailing Analytics
contentSapSailingAnalytics1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.
@@ -220,6 +221,5 @@ strategySimulator=Strategy Simulator
contentStrategySimulator=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
strategySimulatorReadMore=Learn More
impressum=Imprint
@@ -188,6 +188,7 @@ contentSapInSailing6=Offizieller Technologiepartner der Travemünder Woche
contentSapInSailing7=Technischer Partner der Europäischen Segelligen
contentSapInSailing8=Titelsponsor des SAP Extreme Sailing Teams
contentSapInSailing9=Offizieller technischer Partner der Extreme Sailing Series
autoPlayerConfiguration=Auto Player Konfiguration
contentSapInSailing10=Premium-Partner der deutschen Segel-Nationalmannschaft Audi Sailing Team Germany
contentSapInSailing11=Premium-Partner der Kieler Woche, der größten Regatta der Welt
contentSapInSailing12=Titelsponsor der SAP 5O5 World Championships
@@ -220,5 +221,4 @@ strategySimulator=Strategie-Simulator
contentStrategySimulator=Während eines Rennens hängt viel von der Wahl der richtigen Strategie ab. Der Strategie-Simulator vereinfacht die Ermittlung der besten Segelstrategie für diverse Wind- und Strömungsbedingungen. Da Wind und Strömung sofort in der Simulation geändert werden können, lässt sich die Robustheit einer Strategie selbst für unsichere Wetterbedingungen problemlos bewerten.
strategySimulatorReadMore=Mehr erfahren
impressum=Impressum
@@ -35,7 +35,8 @@ import com.sap.sailing.gwt.home.shared.places.start.StartPlace;
import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
@@ -150,8 +151,8 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
linkParams.put("raceName", trackedRaceName);
// TODO this must only be forwarded if there is a logged-on user
// linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true");
linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, "true");
linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_NAVIGATION_PANEL, "true");
linkParams.put(RaceMapSettings.PARAM_SHOW_MAPCONTROLS, "true");
linkParams.put(RaceBoardPerspectiveSettings.PARAM_VIEW_SHOW_NAVIGATION_PANEL, "true");
linkParams.put("regattaName", regattaName);
return linkParams;
}
@@ -1,5 +1,6 @@
package com.sap.sailing.gwt.regattaoverview.client;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -765,6 +766,11 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
storeRegattaRaceStatesSettings(settings);
}
@Override
public RegattaRaceStatesSettings getSettings() {
return settings;
}
private void refreshTableWithNewSettings() {
if (eventDTO != null && raceGroupDTOs != null) {
loadAndUpdateEventLog();
@@ -964,4 +970,9 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
public void setRepeatedInfoLabel(FlowPanel repeatedInfoLabel) {
this.repeatedInfoLabel = repeatedInfoLabel;
}
@Override
public Serializable getId() {
return getLocalizedShortName();
}
}
@@ -491,4 +491,9 @@ public abstract class AbstractTrackedRacesListComposite extends SimplePanel impl
public RefreshableSelectionModel<RaceDTO> getSelectionModel() {
return refreshableSelectionModel;
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -34,7 +34,8 @@ public class AssignRacesToMediaDialog extends DataEntryDialog<Set<RegattaAndRace
public AssignRacesToMediaDialog(SailingServiceAsync sailingService, final MediaTrack mediaTrack,
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages,
Validator<Set<RegattaAndRaceIdentifier>> validator, DialogCallback<Set<RegattaAndRaceIdentifier>> callback) {
super(stringMessages.linkedRaces(), null, stringMessages.ok(), stringMessages.cancel(), validator, callback);
super(stringMessages.linkedRaces(), stringMessages.selectFromRacesWithOverlappingTimeRange(),
stringMessages.ok(), stringMessages.cancel(), validator, callback);
this.stringMessages = stringMessages;
this.mediaTrack = mediaTrack;
trackedRacesListComposite = new TrackedRacesListComposite(sailingService, errorReporter, regattaRefresher,
@@ -63,7 +64,7 @@ public class AssignRacesToMediaDialog extends DataEntryDialog<Set<RegattaAndRace
Grid formGrid = new Grid(2, 2);
panel.add(formGrid);
Label message = new Label();
message.setText("Loading Regattas and Races");
message.setText(stringMessages.loadingRegattasAndRaces());
formGrid.setWidget(0, 0, message);
formGrid.setWidget(1, 1, trackedRacesListComposite);
formGrid.getWidget(1, 1).setVisible(false);
@@ -76,7 +77,6 @@ public class AssignRacesToMediaDialog extends DataEntryDialog<Set<RegattaAndRace
return panel;
}
@Override
protected Set<RegattaAndRaceIdentifier> getResult() {
return getAssignedRaces();
@@ -92,15 +92,15 @@ public class AssignRacesToMediaDialog extends DataEntryDialog<Set<RegattaAndRace
updateUI();
}
public void updateUI() {
private void updateUI() {
Grid grid = (Grid) panel.getWidget(0);
if (hasRaceCandidates) {
grid.getWidget(0, 0).setVisible(false);
grid.getWidget(1, 1).setVisible(true);
this.getOkButton().setVisible(true);
} else {
Label label = (Label)grid.getWidget(0, 0);
label.setText("No Races available");
Label label = (Label) grid.getWidget(0, 0);
label.setText(stringMessages.noRacesAvailable());
grid.getWidget(0, 0).setVisible(true);
grid.getWidget(1, 1).setVisible(false);
this.getOkButton().setVisible(false);
@@ -44,7 +44,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.FlushableCellTable;
import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn;
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveSettings;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
@@ -506,7 +506,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements
public SafeHtml getValue(LeaderboardGroupDTO group) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLEncoder.encode("/gwt/Spectator.html?leaderboardGroupName=" + group.getName()
+ "&showRaceDetails=true&"+RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES+"=true"
+ "&showRaceDetails=true&"+RaceBoardPerspectiveSettings.PARAM_CAN_REPLAY_DURING_LIVE_RACES+"=true"
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
return ANCHORTEMPLATE.cell(link, group.getName());
}
@@ -4,7 +4,6 @@ import static com.google.gwt.dom.client.BrowserEvents.CLICK;
import static com.google.gwt.dom.client.BrowserEvents.KEYUP;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
@@ -49,6 +48,7 @@ import com.sap.sailing.gwt.ui.client.media.NewMediaWithRaceSelectionDialog;
import com.sap.sailing.gwt.ui.client.media.TimeFormatUtil;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
@@ -137,18 +137,16 @@ public class MediaPanel extends FlowPanel {
protected void loadMediaTracks() {
mediaTrackListDataProvider.getList().clear();
mediaService.getAllMediaTracks(new AsyncCallback<Collection<MediaTrack>>() {
mediaService.getAllMediaTracks(new AsyncCallback<Iterable<MediaTrack>>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError(t.toString());
}
@Override
public void onSuccess(Collection<MediaTrack> allMediaTracks) {
mediaTrackListDataProvider.getList().addAll(allMediaTracks);
allMediaTracks.clear();
allMediaTracks.addAll(mediaTrackListDataProvider.getList());
filterableMediaTracks.updateAll(allMediaTracks);
public void onSuccess(Iterable<MediaTrack> allMediaTracks) {
Util.addAll(allMediaTracks, mediaTrackListDataProvider.getList());
filterableMediaTracks.updateAll(mediaTrackListDataProvider.getList());
mediaTrackListDataProvider.refresh();
}
});
@@ -539,20 +537,21 @@ public class MediaPanel extends FlowPanel {
}
private String listAssignedRaces(MediaTrack mediaTrack) {
final String result;
if (mediaTrack.assignedRaces.size() > 1) {
return String.valueOf(mediaTrack.assignedRaces.size());
result = String.valueOf(mediaTrack.assignedRaces.size());
} else {
String value = "";
for (RegattaAndRaceIdentifier assignedRace : mediaTrack.assignedRaces) {
value += assignedRace.getRegattaName() + " " + assignedRace.getRaceName() + ", ";
}
if (value.length() > 1) {
return value.substring(0, value.length() - 2);
} else
return value;
result = value.substring(0, value.length() - 2);
} else {
result = value;
}
}
return result;
}
public void onShow() {
@@ -191,5 +191,11 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite
return "trackedRacesListComposite";
}
@Override
public TrackedRacesSettings getSettings() {
// TODO Auto-generated method stub
return null;
}
}
@@ -1,18 +1,16 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Collection;
import com.google.gwt.user.client.rpc.RemoteService;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.media.MediaTrack;
public interface MediaService extends RemoteService {
Collection<MediaTrack> getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier);
Iterable<MediaTrack> getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier);
Collection<MediaTrack> getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier);
Iterable<MediaTrack> getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier);
Collection<MediaTrack> getAllMediaTracks();
Iterable<MediaTrack> getAllMediaTracks();
String addMediaTrack(MediaTrack mediaTrack);
@@ -1,7 +1,5 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Collection;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.media.MediaTrack;
@@ -9,12 +7,12 @@ import com.sap.sailing.domain.common.media.MediaTrack;
public interface MediaServiceAsync {
void getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier,
AsyncCallback<Collection<MediaTrack>> callback);
AsyncCallback<Iterable<MediaTrack>> callback);
void getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier,
AsyncCallback<Collection<MediaTrack>> callback);
AsyncCallback<Iterable<MediaTrack>> callback);
void getAllMediaTracks(AsyncCallback<Collection<MediaTrack>> asyncCallback);
void getAllMediaTracks(AsyncCallback<Iterable<MediaTrack>> asyncCallback);
void addMediaTrack(MediaTrack mediaTrack, AsyncCallback<String> asyncCallback);
@@ -1,185 +1,184 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
package com.sap.sailing.gwt.ui.client;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.shared.UserDTO;
public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements RaceTimesInfoProviderListener {
private final RaceTimesInfoProvider raceTimesInfoProvider;
private RegattaAndRaceIdentifier selectedRace;
private boolean autoAdjustPlayMode;
private RaceTimesInfoDTO lastRaceTimesInfo;
private boolean hasCanReplayDuringLiveRacesPermission = false;
private final UserService userService;
private final UserStatusEventHandler userStatusEventHandler = new UserStatusEventHandler() {
@Override
public void onUserStatusChange(UserDTO user) {
RaceTimePanel.this.hasCanReplayDuringLiveRacesPermission = user != null && user.hasPermission(
Permission.CAN_REPLAY_DURING_LIVE_RACES.getStringPermission(), SailingPermissionsForRoleProvider.INSTANCE);
}
};
/**
* When a marker update is required but min/max are not yet initialized, this flag is set. If later
* {@link #setMinMax(Date, Date, boolean)} is invoked and this flag is set, a {@link #redrawAllMarkers(RaceTimesInfoDTO)}
* will be issued and the flag is cleared.
*/
private boolean redrawAllMarkersPendingForMinMaxBeingInitialized;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.shared.UserDTO;
public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements RaceTimesInfoProviderListener {
private final RaceTimesInfoProvider raceTimesInfoProvider;
private RegattaAndRaceIdentifier selectedRace;
private boolean autoAdjustPlayMode;
private RaceTimesInfoDTO lastRaceTimesInfo;
private boolean hasCanReplayDuringLiveRacesPermission = false;
private final UserService userService;
private final RaceTimePanelLifecycle componentLifecycle;
private final UserStatusEventHandler userStatusEventHandler = new UserStatusEventHandler() {
@Override
public void onUserStatusChange(UserDTO user) {
RaceTimePanel.this.hasCanReplayDuringLiveRacesPermission = user != null && user.hasPermission(
Permission.CAN_REPLAY_DURING_LIVE_RACES.getStringPermission(), SailingPermissionsForRoleProvider.INSTANCE);
}
};
/**
* When a marker update is required but min/max are not yet initialized, this flag is set. If later
* {@link #setMinMax(Date, Date, boolean)} is invoked and this flag is set, a {@link #redrawAllMarkers(RaceTimesInfoDTO)}
* will be issued and the flag is cleared.
*/
private boolean redrawAllMarkersPendingForMinMaxBeingInitialized;
private final Duration initialTimeAfterRaceStartInReplayMode;
public RaceTimePanel(UserService userService, Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
public RaceTimePanel(RaceTimePanelLifecycle componentLifecycle, UserService userService, Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible, boolean forcePaddingRightToAlignToCharts,
RegattaAndRaceIdentifier selectedRaceIdentifier, Duration initialTimeAfterRaceStartInReplayMode) {
super(timer, timeRangeProvider, stringMessages, canReplayWhileLiveIsPossible, forcePaddingRightToAlignToCharts);
this.userService = userService;
this.raceTimesInfoProvider = raceTimesInfoProvider;
selectedRace = null;
autoAdjustPlayMode = true;
selectedRace = selectedRaceIdentifier;
this.componentLifecycle = componentLifecycle;
this.userService = userService;
this.raceTimesInfoProvider = raceTimesInfoProvider;
selectedRace = null;
autoAdjustPlayMode = true;
selectedRace = selectedRaceIdentifier;
this.initialTimeAfterRaceStartInReplayMode = initialTimeAfterRaceStartInReplayMode;
if (!raceTimesInfoProvider.containsRaceIdentifier(selectedRace)) {
raceTimesInfoProvider.addRaceIdentifier(selectedRace, true);
}
}
@Override
protected void onLoad() {
super.onLoad();
userService.addUserStatusEventHandler(userStatusEventHandler);
userStatusEventHandler.onUserStatusChange(userService.getCurrentUser());
}
@Override
protected void onUnload() {
super.onUnload();
userService.removeUserStatusEventHandler(userStatusEventHandler);
}
@Override
protected boolean canReplayWhileLiveIsPossible() {
return this.hasCanReplayDuringLiveRacesPermission;
}
/**
* If the race's start time is already known and the <code>time</code> is before the start we can set the count-down label
*/
@Override
protected String getTimeToStartLabelText(Date time) {
String result = null;
RaceTimesInfoDTO selectedRaceTimes = raceTimesInfoProvider.getRaceTimesInfo(selectedRace);
if (selectedRaceTimes.startOfRace != null) {
if (time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) {
long timeToStartInMs = selectedRaceTimes.startOfRace.getTime() - time.getTime();
result = timeToStartInMs < 1000 ? stringMessages.start() : stringMessages.timeToStart(DateAndTimeFormatterUtil.formatElapsedTime(timeToStartInMs));
} else {
long timeSinceStartInMs = time.getTime() - selectedRaceTimes.startOfRace.getTime();
result = stringMessages.timeSinceStart(DateAndTimeFormatterUtil.formatElapsedTime(timeSinceStartInMs));
}
}
return result;
}
@Override
public void updateSettings(RaceTimePanelSettings newSettings) {
super.updateSettings(newSettings);
raceTimesInfoProvider.setRequestInterval(newSettings.getRefreshInterval());
}
@Override
public RaceTimePanelSettings getSettings() {
RaceTimePanelSettings result = new RaceTimePanelSettings();
result.setRefreshInterval(timer.getRefreshInterval());
result.setRaceTimesInfo(raceTimesInfoProvider.getRaceTimesInfo(selectedRace));
return result;
}
@Override
public SettingsDialogComponent<RaceTimePanelSettings> getSettingsDialogComponent() {
return new RaceTimePanelSettingsDialogComponent(getSettings(), stringMessages);
}
private void updateTimeInfo(RaceTimesInfoDTO raceTimesInfo) {
if (raceTimesInfo == null) {
// in case the race is not tracked anymore we reset the time slider
resetTimeSlider();
} else {
// timer will only accept this update if the delay hasn't been updated explicitly
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) &&
(raceTimesInfo.newestTrackingEvent != null || raceTimesInfo.endOfRace != null || raceTimesInfo.endOfTracking != 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
boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
setLiveGenerallyPossible(liveModeToBeMadePossible);
setJumpToLiveEnablement(liveModeToBeMadePossible && timer.getPlayMode() != PlayModes.Live);
if (autoAdjustPlayMode && liveModeToBeMadePossible) {
timer.setPlayMode(PlayModes.Live);
}
updatePlayPauseButtonsVisibility(timer.getPlayMode());
if (liveModeToBeMadePossible && !canReplayWhileLiveIsPossible() &&
timer.getPlayMode()==PlayModes.Replay && timer.getPlayState()==PlayStates.Playing) {
// pause timer because it must not be playing in replay mode while the race is live
timer.pause();
}
boolean timerAlreadyInitialized = getFromTime() != null && getToTime() != null && timeSlider.getCurrentValue() != null;
if (!timeRangeProvider.isZoomed()) {
updateMinMax(raceTimesInfo);
if (!timerAlreadyInitialized) {
initTimerPosition(raceTimesInfo);
}
updateLegMarkers(raceTimesInfo);
}
} else {
// the tracked race did not start yet or has no events yet
// maybe show a special state for this like "Race did not start yet"
}
}
lastRaceTimesInfo = raceTimesInfo; // TODO bug 3122: when not redrawn yet because min/max not initialized yet, further redraw is disabled by this.
}
@Override
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
super.onTimeZoomChanged(zoomStartTimepoint, zoomEndTimepoint);
timeSlider.setZoomed(true);
setMinMax(zoomStartTimepoint, zoomEndTimepoint, false);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
@Override
public void onTimeZoomReset() {
super.onTimeZoomReset();
timeSlider.setZoomed(false);
timeSlider.setMinValue(new Double(timeRangeProvider.getFromTime().getTime()), false);
timeSlider.setMaxValue(new Double(timeRangeProvider.getToTime().getTime()), false);
timeSlider.setCurrentValue(new Double(timer.getTime().getTime()), true);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
/**
* If and only if the {@link #selectedRace}'s timing is described by the {@link #raceTimesInfoProvider} and
if (!raceTimesInfoProvider.containsRaceIdentifier(selectedRace)) {
raceTimesInfoProvider.addRaceIdentifier(selectedRace, true);
}
}
@Override
protected void onLoad() {
super.onLoad();
userService.addUserStatusEventHandler(userStatusEventHandler);
userStatusEventHandler.onUserStatusChange(userService.getCurrentUser());
}
@Override
protected void onUnload() {
super.onUnload();
userService.removeUserStatusEventHandler(userStatusEventHandler);
}
@Override
protected boolean canReplayWhileLiveIsPossible() {
return this.hasCanReplayDuringLiveRacesPermission;
}
/**
* If the race's start time is already known and the <code>time</code> is before the start we can set the count-down label
*/
@Override
protected String getTimeToStartLabelText(Date time) {
String result = null;
RaceTimesInfoDTO selectedRaceTimes = raceTimesInfoProvider.getRaceTimesInfo(selectedRace);
if (selectedRaceTimes.startOfRace != null) {
if (time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) {
long timeToStartInMs = selectedRaceTimes.startOfRace.getTime() - time.getTime();
result = timeToStartInMs < 1000 ? stringMessages.start() : stringMessages.timeToStart(DateAndTimeFormatterUtil.formatElapsedTime(timeToStartInMs));
} else {
long timeSinceStartInMs = time.getTime() - selectedRaceTimes.startOfRace.getTime();
result = stringMessages.timeSinceStart(DateAndTimeFormatterUtil.formatElapsedTime(timeSinceStartInMs));
}
}
return result;
}
@Override
public void updateSettings(RaceTimePanelSettings newSettings) {
super.updateSettings(newSettings);
raceTimesInfoProvider.setRequestInterval(newSettings.getRefreshInterval());
}
@Override
public RaceTimePanelSettings getSettings() {
return new RaceTimePanelSettings(timer.getRefreshInterval());
}
@Override
public SettingsDialogComponent<RaceTimePanelSettings> getSettingsDialogComponent() {
return componentLifecycle.getSettingsDialogComponent(getSettings());
}
private void updateTimeInfo(RaceTimesInfoDTO raceTimesInfo) {
if (raceTimesInfo == null) {
// in case the race is not tracked anymore we reset the time slider
resetTimeSlider();
} else {
// timer will only accept this update if the delay hasn't been updated explicitly
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) &&
(raceTimesInfo.newestTrackingEvent != null || raceTimesInfo.endOfRace != null || raceTimesInfo.endOfTracking != 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
boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
setLiveGenerallyPossible(liveModeToBeMadePossible);
setJumpToLiveEnablement(liveModeToBeMadePossible && timer.getPlayMode() != PlayModes.Live);
if (autoAdjustPlayMode && liveModeToBeMadePossible) {
timer.setPlayMode(PlayModes.Live);
}
updatePlayPauseButtonsVisibility(timer.getPlayMode());
if (liveModeToBeMadePossible && !canReplayWhileLiveIsPossible() &&
timer.getPlayMode()==PlayModes.Replay && timer.getPlayState()==PlayStates.Playing) {
// pause timer because it must not be playing in replay mode while the race is live
timer.pause();
}
boolean timerAlreadyInitialized = getFromTime() != null && getToTime() != null && timeSlider.getCurrentValue() != null;
if (!timeRangeProvider.isZoomed()) {
updateMinMax(raceTimesInfo);
if (!timerAlreadyInitialized) {
initTimerPosition(raceTimesInfo);
}
updateLegMarkers(raceTimesInfo);
}
} else {
// the tracked race did not start yet or has no events yet
// maybe show a special state for this like "Race did not start yet"
}
}
lastRaceTimesInfo = raceTimesInfo; // TODO bug 3122: when not redrawn yet because min/max not initialized yet, further redraw is disabled by this.
}
@Override
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
super.onTimeZoomChanged(zoomStartTimepoint, zoomEndTimepoint);
timeSlider.setZoomed(true);
setMinMax(zoomStartTimepoint, zoomEndTimepoint, false);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
@Override
public void onTimeZoomReset() {
super.onTimeZoomReset();
timeSlider.setZoomed(false);
timeSlider.setMinValue(new Double(timeRangeProvider.getFromTime().getTime()), false);
timeSlider.setMaxValue(new Double(timeRangeProvider.getToTime().getTime()), false);
timeSlider.setCurrentValue(new Double(timer.getTime().getTime()), true);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
/**
* If and only if the {@link #selectedRace}'s timing is described by the {@link #raceTimesInfoProvider} and
* according to the timing the current live time point is after the start of tracking or at least after
* {@link RaceTimesCalculationUtil.MIN_TIME_BEFORE_RACE_START} minutes before the race, and the current live time
* point is not after the end of tracking then live mode will be made possible (<code>true</code> will be returned).<p>
@@ -188,15 +187,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
* {@link RaceTimesInfoDTO#newestTrackingEvent} and {@link RaceTimesInfoDTO#endOfRace} values to see if---with
* a little leeway---an end for the live period may be determined. Without this logic, such races would remain
* live until the end of time.
*/
@Override
protected boolean isLiveModeToBeMadePossible() {
long liveTimePointInMillis = timer.getLiveTimePointInMillis();
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
*/
@Override
protected boolean isLiveModeToBeMadePossible() {
long liveTimePointInMillis = timer.getLiveTimePointInMillis();
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
final boolean isLiveModeToBeMadePossible;
if (lastRaceTimesInfo != null &&
// check that we're after startOfTracking or startOfRace minus some leeway:
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()) ||
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()) ||
(lastRaceTimesInfo.startOfRace != null && liveTimePointInMillis > lastRaceTimesInfo.startOfRace.getTime() - RaceTimesCalculationUtil.MIN_TIME_BEFORE_RACE_START))) {
// now check that we cannot know about an end time or are reasonably before it;
// we don't know about the end time if startOfTracking is valid but endOfTracking is not;
@@ -220,147 +219,147 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
isLiveModeToBeMadePossible = false;
}
return isLiveModeToBeMadePossible;
}
@Override
public void playStateChanged(PlayStates playState, PlayModes playMode) {
super.playStateChanged(playState, playMode);
switch (playMode) {
case Replay:
autoAdjustPlayMode = false;
break;
case Live:
break;
}
}
/**
* Obtains the min/max range for the slider bar from <code>newRaceTimesInfo</code> and adjusts the slider bar if
* needed. Since we extend the slider bar to the right when playing across the "end of time," we don't want to
* constrain it back again here. Therefore, the max value is never reduced here but at best initially set if it
* was <code>null</code> before, or extended to a later point in time.
*/
private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) {
}
@Override
public void playStateChanged(PlayStates playState, PlayModes playMode) {
super.playStateChanged(playState, playMode);
switch (playMode) {
case Replay:
autoAdjustPlayMode = false;
break;
case Live:
break;
}
}
/**
* Obtains the min/max range for the slider bar from <code>newRaceTimesInfo</code> and adjusts the slider bar if
* needed. Since we extend the slider bar to the right when playing across the "end of time," we don't want to
* constrain it back again here. Therefore, the max value is never reduced here but at best initially set if it
* was <code>null</code> before, or extended to a later point in time.
*/
private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) {
Util.Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.calculateRaceMinMax(timer, newRaceTimesInfo);
Date min = raceMinMax.getA();
Date max = raceMinMax.getB();
// never reduce max if it was already set
if (min != null && max != null && (getToTime() == null || getToTime().before(max))) {
setMinMax(min, max, /* fireEvent */ false); // no event because we guarantee time to be between min and max
}
}
@Override
public void setMinMax(Date min, Date max, boolean fireEvent) {
super.setMinMax(min, max, fireEvent);
if (redrawAllMarkersPendingForMinMaxBeingInitialized && timeSlider.isMinMaxInitialized()) {
redrawAllMarkers(lastRaceTimesInfo);
redrawAllMarkersPendingForMinMaxBeingInitialized = false;
}
}
/**
* When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was
* finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the
* {@link RaceTimesInfoDTO#endOfRace end of the race}. If that happens to be undefined (<code>null</code>), the
* {@link RaceTimesInfoDTO#startOfRace start of the race} is used instead. If that isn't available either, the timer
* remains unchanged.
* <p>
*
* When in {@link PlayModes#Live} mode, tries to advance the timer to the time point of the
* {@link RaceTimesInfoDTO#timePointOfNewestEvent timePointOfNewestEvent} received from the tracking infrastructure
* so far and puts the timer into {@link PlayStates#Playing play mode}.
*/
private void initTimerPosition(RaceTimesInfoDTO newRaceTimesInfo) {
// initialize timer position
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.newestTrackingEvent != null) {
timer.setTime(newRaceTimesInfo.newestTrackingEvent.getTime());
}
timer.play();
break;
case Replay:
// set time to start of race
if (newRaceTimesInfo.startOfRace != null) {
Date min = raceMinMax.getA();
Date max = raceMinMax.getB();
// never reduce max if it was already set
if (min != null && max != null && (getToTime() == null || getToTime().before(max))) {
setMinMax(min, max, /* fireEvent */ false); // no event because we guarantee time to be between min and max
}
}
@Override
public void setMinMax(Date min, Date max, boolean fireEvent) {
super.setMinMax(min, max, fireEvent);
if (redrawAllMarkersPendingForMinMaxBeingInitialized && timeSlider.isMinMaxInitialized()) {
redrawAllMarkers(lastRaceTimesInfo);
redrawAllMarkersPendingForMinMaxBeingInitialized = false;
}
}
/**
* When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was
* finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the
* {@link RaceTimesInfoDTO#endOfRace end of the race}. If that happens to be undefined (<code>null</code>), the
* {@link RaceTimesInfoDTO#startOfRace start of the race} is used instead. If that isn't available either, the timer
* remains unchanged.
* <p>
*
* When in {@link PlayModes#Live} mode, tries to advance the timer to the time point of the
* {@link RaceTimesInfoDTO#timePointOfNewestEvent timePointOfNewestEvent} received from the tracking infrastructure
* so far and puts the timer into {@link PlayStates#Playing play mode}.
*/
private void initTimerPosition(RaceTimesInfoDTO newRaceTimesInfo) {
// initialize timer position
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.newestTrackingEvent != null) {
timer.setTime(newRaceTimesInfo.newestTrackingEvent.getTime());
}
timer.play();
break;
case Replay:
// set time to start of race
if (newRaceTimesInfo.startOfRace != null) {
timer.setTime(newRaceTimesInfo.startOfRace.getTime() +
(initialTimeAfterRaceStartInReplayMode == null ? 0l : initialTimeAfterRaceStartInReplayMode.asMillis()));
}
break;
}
}
/**
* Expected to be called before {@link #lastRaceTimesInfo} has been updated to <code>newRaceTimesInfo</code>
*/
private void updateLegMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
boolean requiresMarkerUpdate = true;
// updating the sliderbar markers requires a lot of time, therefore we need to do this only if required
if (lastRaceTimesInfo != null && lastRaceTimesInfo.markPassingTimes.size() == newRaceTimesInfo.markPassingTimes.size()) {
requiresMarkerUpdate = false;
int numberOfLegs = newRaceTimesInfo.markPassingTimes.size();
for (int i = 0; i < numberOfLegs; i++) {
if (!Util.equalsWithNull(newRaceTimesInfo.markPassingTimes.get(i).firstPassingDate, lastRaceTimesInfo.markPassingTimes.get(i).firstPassingDate)) {
requiresMarkerUpdate = true;
break;
}
}
if ((lastRaceTimesInfo.startOfRace == null && newRaceTimesInfo.startOfRace != null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace == null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace != null
&& lastRaceTimesInfo.startOfRace.getTime() != newRaceTimesInfo.startOfRace.getTime())) {
requiresMarkerUpdate = true;
}
if ((lastRaceTimesInfo.endOfRace == null && newRaceTimesInfo.endOfRace != null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace == null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace != null
&& lastRaceTimesInfo.endOfRace.getTime() != newRaceTimesInfo.endOfRace.getTime())) {
requiresMarkerUpdate = true;
}
}
if (requiresMarkerUpdate) {
if (timeSlider.isMinMaxInitialized()) { // TODO bug 3122 later, the lastRaceTimesInfo will be updated even if not redrawn because min/max not initialized
redrawAllMarkers(newRaceTimesInfo);
} else {
redrawAllMarkersPendingForMinMaxBeingInitialized = true;
}
}
}
private void redrawAllMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
List<MarkPassingTimesDTO> markPassingTimes = newRaceTimesInfo.getMarkPassingTimes();
timeSlider.clearMarkers();
if (newRaceTimesInfo.startOfRace != null) {
long markerTime = newRaceTimesInfo.startOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("S", new Double(markerTime));
}
}
int markPassingCounter = 1;
for (MarkPassingTimesDTO markPassingTimesDTO: markPassingTimes) {
// ignore the start mark passing
if (markPassingCounter > 1 && markPassingTimesDTO.firstPassingDate != null) {
long markerTime = markPassingTimesDTO.firstPassingDate.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker(markPassingTimesDTO.getName(), new Double(markerTime));
}
}
markPassingCounter++;
}
if (newRaceTimesInfo.endOfRace != null) {
long markerTime = newRaceTimesInfo.endOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("E", new Double(markerTime));
}
}
timeSlider.redraw();
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
updateTimeInfo(raceTimesInfos.get(selectedRace));
}
}
}
break;
}
}
/**
* Expected to be called before {@link #lastRaceTimesInfo} has been updated to <code>newRaceTimesInfo</code>
*/
private void updateLegMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
boolean requiresMarkerUpdate = true;
// updating the sliderbar markers requires a lot of time, therefore we need to do this only if required
if (lastRaceTimesInfo != null && lastRaceTimesInfo.markPassingTimes.size() == newRaceTimesInfo.markPassingTimes.size()) {
requiresMarkerUpdate = false;
int numberOfLegs = newRaceTimesInfo.markPassingTimes.size();
for (int i = 0; i < numberOfLegs; i++) {
if (!Util.equalsWithNull(newRaceTimesInfo.markPassingTimes.get(i).firstPassingDate, lastRaceTimesInfo.markPassingTimes.get(i).firstPassingDate)) {
requiresMarkerUpdate = true;
break;
}
}
if ((lastRaceTimesInfo.startOfRace == null && newRaceTimesInfo.startOfRace != null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace == null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace != null
&& lastRaceTimesInfo.startOfRace.getTime() != newRaceTimesInfo.startOfRace.getTime())) {
requiresMarkerUpdate = true;
}
if ((lastRaceTimesInfo.endOfRace == null && newRaceTimesInfo.endOfRace != null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace == null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace != null
&& lastRaceTimesInfo.endOfRace.getTime() != newRaceTimesInfo.endOfRace.getTime())) {
requiresMarkerUpdate = true;
}
}
if (requiresMarkerUpdate) {
if (timeSlider.isMinMaxInitialized()) { // TODO bug 3122 later, the lastRaceTimesInfo will be updated even if not redrawn because min/max not initialized
redrawAllMarkers(newRaceTimesInfo);
} else {
redrawAllMarkersPendingForMinMaxBeingInitialized = true;
}
}
}
private void redrawAllMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
List<MarkPassingTimesDTO> markPassingTimes = newRaceTimesInfo.getMarkPassingTimes();
timeSlider.clearMarkers();
if (newRaceTimesInfo.startOfRace != null) {
long markerTime = newRaceTimesInfo.startOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("S", new Double(markerTime));
}
}
int markPassingCounter = 1;
for (MarkPassingTimesDTO markPassingTimesDTO: markPassingTimes) {
// ignore the start mark passing
if (markPassingCounter > 1 && markPassingTimesDTO.firstPassingDate != null) {
long markerTime = markPassingTimesDTO.firstPassingDate.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker(markPassingTimesDTO.getName(), new Double(markerTime));
}
}
markPassingCounter++;
}
if (newRaceTimesInfo.endOfRace != null) {
long markerTime = newRaceTimesInfo.endOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("E", new Double(markerTime));
}
}
timeSlider.redraw();
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
updateTimeInfo(raceTimesInfos.get(selectedRace));
}
}
@@ -0,0 +1,45 @@
package com.sap.sailing.gwt.ui.client;
import java.io.Serializable;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class RaceTimePanelLifecycle implements
ComponentLifecycle<RaceTimePanelSettings, RaceTimePanelSettingsDialogComponent> {
private final StringMessages stringMessages;
public RaceTimePanelLifecycle(StringMessages stringMessages) {
this.stringMessages = stringMessages;
}
@Override
public RaceTimePanelSettingsDialogComponent getSettingsDialogComponent(RaceTimePanelSettings settings) {
return new RaceTimePanelSettingsDialogComponent(cloneSettings(settings), stringMessages);
}
@Override
public RaceTimePanelSettings createDefaultSettings() {
return new RaceTimePanelSettings(1000);
}
@Override
public RaceTimePanelSettings cloneSettings(RaceTimePanelSettings settings) {
return new RaceTimePanelSettings(settings.getRefreshInterval());
}
@Override
public String getLocalizedShortName() {
return "TimePanel";
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
@Override
public boolean hasSettings() {
return true;
}
}
@@ -1,20 +1,8 @@
package com.sap.sailing.gwt.ui.client;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
public class RaceTimePanelSettings extends TimePanelSettings {
private RaceTimesInfoDTO raceTimesInfo;
public RaceTimePanelSettings() {
super();
public RaceTimePanelSettings(long refreshInterval) {
super(refreshInterval);
}
public RaceTimesInfoDTO getRaceTimesInfo() {
return raceTimesInfo;
}
public void setRaceTimesInfo(RaceTimesInfoDTO raceTimesInfo) {
this.raceTimesInfo = raceTimesInfo;
}
}
@@ -9,8 +9,8 @@ public class RaceTimePanelSettingsDialogComponent extends TimePanelSettingsDialo
@Override
public RaceTimePanelSettings getResult() {
RaceTimePanelSettings result = new RaceTimePanelSettings();
result.setRefreshInterval(refreshIntervalBox.getValue() == null ? -1 : (long) (refreshIntervalBox.getValue() * 1000));
long refreshInternal = refreshIntervalBox.getValue() == null ? -1 : (long) (refreshIntervalBox.getValue() * 1000);
RaceTimePanelSettings result = new RaceTimePanelSettings(refreshInternal);
return result;
}
}
@@ -90,6 +90,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String leaderboardSettings();
@Override
String settings();
String page();
String linkedRaces();
String selectAtLeastOneLegDetail();
String currentSpeedOverGroundInKnots();
@@ -134,7 +135,10 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String declinationCheckbox();
String raceStartTrackingColumn();
String pauseAutomaticRefresh();
String autoZoom();
String zoomFactor();
String autoRefresh();
String autoPlayMedia();
String delayInSeconds();
String delayBetweenAutoAdvances();
String delayMustBeNonNegative();
@@ -1204,6 +1208,13 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String editSeries();
String pleaseSelectAtLeastOneRegatta();
String pleaseSelectAnEvent();
String selectALeaderboard();
String autoplayConfiguration();
String startAutoplay();
String autoplaySettings();
String startBrowserFullscreen();
String switchToLiveRaceAutomatically();
String timeBeforeRaceStart();
String showXYDiagram();
String xyDiagram();
String boatSpeed();
@@ -1537,6 +1548,10 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String fixSuccessfullyRemoved();
String dragToChangePosition();
String moveFix();
String raceViewer();
String mapControls();
String manage2SailEvent();
String noEventsYet();
String selectResultImportProvider();
@@ -1593,4 +1608,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String simulationLegendAlgorithmTimedOutText();
String simulationLegendMixedLegText();
String noTracksFound();
String noRacesAvailable();
String loadingRegattasAndRaces();
String selectFromRacesWithOverlappingTimeRange();
}
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=Race Manager App
raceViewer=Race viewer
mapControls=Map controls
page=Page
tracTracEvents=TracTrac Events
swissTimingEvents=SwissTiming Events
trackedBefore=History of tracked events
@@ -277,6 +280,9 @@ home=Home
clickAndDragToZoomIn=Click and drag in the plot area to zoom in
windSpeed=Wind speed (kts)
allTimesInUTC=All times in UTC
autoPlayMedia=Play media automatically
zoomFactor=Zoom factor
autoZoom=Auto zoom
autoZoomTo=Auto zoom to
autoZoomToBoats=Boats
autoZoomToBuoys=Buoys
@@ -1169,6 +1175,13 @@ filteredBy=filtered by
editSeries=Edit Series
pleaseSelectAtLeastOneRegatta=Please select at least one regatta
pleaseSelectAnEvent=Please select an event
selectALeaderboard=Please select a leaderboard
autoplayConfiguration=Autoplay configuration
startAutoplay=Start autoplay
autoplaySettings=Autoplay settings
startBrowserFullscreen=Start browser in fullscreen mode
switchToLiveRaceAutomatically=Switch to live race automatically
timeBeforeRaceStart=time before race start (in s)
errorTryingToGetEvents=Error trying to get events: {0}
showXYDiagram=Show x-y-diagram
xyDiagram=x-y-Diagram
@@ -1562,9 +1575,12 @@ current=Current
simulationLegendAlgorithmTimedOutText = out-of-bounds
simulationLegendMixedLegText = ambiguous wind
noTracksFound=No tracks found
noRacesAvailable=No races available
loadingRegattasAndRaces=Loading Regattas and Races
selectFromRacesWithOverlappingTimeRange=Select from the races whose time range overlaps with media track those to which the track shall be linked
currentRideHeightInMeters=Ride Height
currentRideHeightInMetersTooltip=The current Foiling ride height
currentOrAverageRideHeightInMeters=Ride Height (\u2205 at end)
currentOrAverageRideHeightInMetersTooltip=Current Foiling ride height in meters while leg is still running; average ride height when leg is completed.
pleaseCreateAtLeastOneMappingForCompetitor=Please create at least one mapping by first selecting a track on the left hand side and then selecting a competitor on the right hand side
importAdditionalSensorData=Import additional sensor data
importAdditionalSensorData=Import additional sensor data
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=Race Manager App
raceViewer=Race viewer
mapControls=Kartensteuerelemente
page=Seite
createNewEvent=Create New Event
tracTracEvents=TracTrac Events
swissTimingEvents=SwissTiming Events
@@ -279,6 +282,9 @@ home=Startseite
clickAndDragToZoomIn=Anklicken und ziehen zum Hineinzoomen
windSpeed=Wind speed (sm/h)
allTimesInUTC=Alle Zeiten in UTC
autoPlayMedia=Audio oder Video automatisch abspielen
zoomFactor=Vergrößerungsfaktor
autoZoom=Auto-Zoom
autoZoomTo=Auto-Zoom nach
autoZoomToBoats=Booten
autoZoomToBuoys=Tonnen
@@ -1161,6 +1167,13 @@ editSeries=Serie bearbeiten
filteredBy=gefiltert nach
pleaseSelectAtLeastOneRegatta=Bitte wenigstens eine Regatta auswählen
pleaseSelectAnEvent=Bitte eine Veranstaltung auswählen
selectALeaderboard=Bitte ein Leaderboard auswählen
autoplayConfiguration=Automatisches Abspielen konfigurieren
startAutoplay=Automatisches Abspielen starten
autoplaySettings=Einstellungen für automatisches Abspielen
startBrowserFullscreen=Browser im Vollbildmodus starten
switchToLiveRaceAutomatically=Automatisches Umschalten zum Live-Rennen
timeBeforeRaceStart=Zeit vor dem Rennstart (in s)
errorTryingToGetEvents=Fehler beim Laden von Veranstaltungen: {0}
createDefaultSettingsForAllRegattas=Standardeinstellungen für alle Regatten anlegen...
noOverallEventSelected=Keine übergeordnete Veranstaltung ausgewählt...
@@ -1547,9 +1560,12 @@ current=Strömung
simulationLegendAlgorithmTimedOutText=außerhalb des zul. Bereichs
simulationLegendMixedLegText=mehrdeutiger Wind
noTracksFound=Keine Tracks gefunden
noRacesAvailable=Keine Rennen verfügbar
loadingRegattasAndRaces=Regatten und Rennen werden geladen
selectFromRacesWithOverlappingTimeRange=Das oder die Rennen aus der Liste derer zum Verknüpfen auswählen, die zeitlich mit dem Medien-Track überlappen
currentRideHeightInMeters=Fahrhöhe
currentRideHeightInMetersTooltip=Die aktuelle Fahrhöhe (Foiling).
currentOrAverageRideHeightInMeters=Fahrhöhe (\u2205 nach Abschluss)
currentOrAverageRideHeightInMetersTooltip=Momentane Fahrhöhe (Foiling) während der Teilnehmer sich im Bahnabschnitt befindet; Durchschnitt, nachdem der Teilnehmer den Abschnitt beendet hat.
pleaseCreateAtLeastOneMappingForCompetitor=Bitte erstellen Sie mindestens eine Zuordnung, indem Sie zunächst einen Track auf der linken Seite und anschließend einen Teilnehmer auf der rechten Seite auswählen
importAdditionalSensorData=Zusätzliche Sensordaten importieren
importAdditionalSensorData=Zusätzliche Sensordaten importieren
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=レースマネージャアプリ
raceViewer=Race viewer
mapControls=Map controls
page=Page
tracTracEvents=TracTrac イベント
swissTimingEvents=SwissTiming イベント
trackedBefore=追跡イベントの履歴
@@ -275,6 +278,9 @@ home=ホーム
clickAndDragToZoomIn=拡大するプロット領域をクリックしてドラッグ
windSpeed=風速 (kt)
allTimesInUTC=時刻はすべて UTC
autoPlayMedia=Play media automatically
zoomFactor=Zoom factor
autoZoom=Auto zoom
autoZoomTo=自動拡大:
autoZoomToBoats=艇
autoZoomToBuoys=ブイ
@@ -1167,6 +1173,13 @@ filteredBy=フィルタキー
editSeries=シリーズ編集
pleaseSelectAtLeastOneRegatta=レガッタを少なくとも 1 つ選択してください
pleaseSelectAnEvent=イベントを選択してください
selectALeaderboard=Please select a leaderboard
autoplayConfiguration=Autoplay configuration
startAutoplay=Start autoplay
autoplaySettings=Autoplay settings
startBrowserFullscreen=Start browser in fullscreen mode
switchToLiveRaceAutomatically=Switch to live race automatically
timeBeforeRaceStart=time before race start (in s)
errorTryingToGetEvents=イベント {0} を取得しようとしてエラーが発生
showXYDiagram=x-y ダイアグラム表示
xyDiagram=x-y ダイアグラム
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=Приложение Race Manager
raceViewer=Race viewer
mapControls=Map controls
page=Page
tracTracEvents=События TracTrac
swissTimingEvents=События SwissTiming
trackedBefore=История отслеживаемых событий
@@ -275,6 +278,9 @@ home=Главная
clickAndDragToZoomIn=Щелкните и перетащите в область визуализации для увеличения
windSpeed=Скорость ветра (уз)
allTimesInUTC=Время UTC
autoPlayMedia=Play media automatically
zoomFactor=Zoom factor
autoZoom=Auto zoom
autoZoomTo=Автоувеличение до
autoZoomToBoats=Лодки
autoZoomToBuoys=Буи
@@ -1167,6 +1173,13 @@ filteredBy=отфильтровано по
editSeries=Изменить серию
pleaseSelectAtLeastOneRegatta=Выберите не менее одной регаты
pleaseSelectAnEvent=Выберите событие
selectALeaderboard=Please select a leaderboard
autoplayConfiguration=Autoplay configuration
startAutoplay=Start autoplay
autoplaySettings=Autoplay settings
startBrowserFullscreen=Start browser in fullscreen mode
switchToLiveRaceAutomatically=Switch to live race automatically
timeBeforeRaceStart=time before race start (in s)
errorTryingToGetEvents=Ошибка при попытке получить события: {0}
showXYDiagram=Показать диаграмму x-y
xyDiagram=Диаграмма x-y
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=Race Manager 应用
raceViewer=Race viewer
mapControls=Map controls
page=Page
tracTracEvents=TracTrac 活动
swissTimingEvents=SwissTiming 活动
trackedBefore=已跟踪活动的历史记录
@@ -275,6 +278,9 @@ home=主页
clickAndDragToZoomIn=单击并拖动绘图区以放大
windSpeed=风速 (kts)
allTimesInUTC=所有时间均为 UTC 格式
autoPlayMedia=Play media automatically
zoomFactor=Zoom factor
autoZoom=Auto zoom
autoZoomTo=自动放大/缩小
autoZoomToBoats=船只
autoZoomToBuoys=浮标
@@ -1167,6 +1173,13 @@ filteredBy=筛选方式
editSeries=编辑系列
pleaseSelectAtLeastOneRegatta=请至少选择一场比赛
pleaseSelectAnEvent=请选择活动
selectALeaderboard=Please select a leaderboard
autoplayConfiguration=Autoplay configuration
startAutoplay=Start autoplay
autoplaySettings=Autoplay settings
startBrowserFullscreen=Start browser in fullscreen mode
switchToLiveRaceAutomatically=Switch to live race automatically
timeBeforeRaceStart=time before race start (in s)
errorTryingToGetEvents=尝试获取活动出错: {0}
showXYDiagram=显示 x-y 图
xyDiagram=x-y 图
@@ -1,5 +1,8 @@
manage2Sail=Manage2Sail
raceCommitteeApp=Race Manager 应用
raceViewer=Race viewer
mapControls=Map controls
page=Page
tracTracEvents=TracTrac 活动
swissTimingEvents=SwissTiming 活动
trackedBefore=已跟踪活动的历史记录
@@ -275,6 +278,9 @@ home=主页
clickAndDragToZoomIn=单击并拖动绘图区以放大
windSpeed=风速 (kts)
allTimesInUTC=所有时间均为 UTC 格式
autoPlayMedia=Play media automatically
zoomFactor=Zoom factor
autoZoom=Auto zoom
autoZoomTo=自动放大/缩小
autoZoomToBoats=船只
autoZoomToBuoys=浮标
@@ -1167,6 +1173,13 @@ filteredBy=筛选方式
editSeries=编辑系列
pleaseSelectAtLeastOneRegatta=请至少选择一场比赛
pleaseSelectAnEvent=请选择活动
selectALeaderboard=Please select a leaderboard
autoplayConfiguration=Autoplay configuration
startAutoplay=Start autoplay
autoplaySettings=Autoplay settings
startBrowserFullscreen=Start browser in fullscreen mode
switchToLiveRaceAutomatically=Switch to live race automatically
timeBeforeRaceStart=time before race start (in s)
errorTryingToGetEvents=尝试获取活动出错: {0}
showXYDiagram=显示 x-y 图
xyDiagram=x-y 图
@@ -90,6 +90,7 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
protected static TimePanelCss timePanelCss = TimePanelCssResources.INSTANCE.css();
private final boolean forcePaddingRightToAlignToCharts;
/**
* @param forcePaddingRightToAlignToCharts
* if <code>true</code>, the right padding will always be set such that the time panel lines up with
@@ -558,7 +559,7 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
updateTimeSliderPadding(possible);
updatePlayPauseButtonsVisibility(timer.getPlayMode());
}
private void updateTimeSliderPadding(boolean backToLivePlayButtonVisible) {
Style timePanelStyle = timePanelSlider.getElement().getStyle();
if (backToLivePlayButtonVisible || forcePaddingRightToAlignToCharts) {
@@ -571,8 +572,7 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
@SuppressWarnings("unchecked")
public T getSettings() {
TimePanelSettings result = new TimePanelSettings();
result.setRefreshInterval(timer.getRefreshInterval());
TimePanelSettings result = new TimePanelSettings(timer.getRefreshInterval());
return (T) result;
}
@@ -635,4 +635,10 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
public Button getBackToLiveButton() {
return backToLivePlayButton;
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -3,18 +3,13 @@ package com.sap.sailing.gwt.ui.client;
import com.sap.sse.common.settings.AbstractSettings;
public class TimePanelSettings extends AbstractSettings {
private long refreshInterval;
private final long refreshInterval;
public TimePanelSettings() {
refreshInterval = 1000;
public TimePanelSettings(long refreshInterval) {
this.refreshInterval = refreshInterval;
}
public long getRefreshInterval() {
return refreshInterval;
}
public void setRefreshInterval(long refreshInterval) {
this.refreshInterval = refreshInterval;
}
}
@@ -9,70 +9,64 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class TimePanelSettingsDialogComponent<T extends TimePanelSettings>
implements SettingsDialogComponent<T> {
protected DoubleBox refreshIntervalBox;
protected final StringMessages stringMessages;
protected final T initialSettings;
protected FlowPanel mainContentPanel;
public class TimePanelSettingsDialogComponent<T extends TimePanelSettings> implements SettingsDialogComponent<T> {
protected DoubleBox refreshIntervalBox;
protected final StringMessages stringMessages;
protected final T initialSettings;
protected FlowPanel mainContentPanel;
private static String STYLE_LABEL = "settingsDialogLabel";
private static String STYLE_INPUT = "settingsDialogValue";
private static String STYLE_BOXPANEL = "boxPanel";
private static String STYLE_LABEL = "settingsDialogLabel";
private static String STYLE_INPUT = "settingsDialogValue";
private static String STYLE_BOXPANEL = "boxPanel";
public TimePanelSettingsDialogComponent(T settings,
StringMessages stringMessages) {
this.stringMessages = stringMessages;
initialSettings = settings;
}
public TimePanelSettingsDialogComponent(T settings, StringMessages stringMessages) {
this.stringMessages = stringMessages;
initialSettings = settings;
}
protected StringMessages getStringMessages() {
return stringMessages;
}
protected StringMessages getStringMessages() {
return stringMessages;
}
@Override
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
mainContentPanel = new FlowPanel();
FlowPanel labelAndRefreshIntervalBoxPanel = new FlowPanel();
Label labelIntervalBox = new Label(stringMessages.refreshInterval()
+ ":");
labelIntervalBox.setStyleName(STYLE_LABEL);
labelAndRefreshIntervalBoxPanel.add(labelIntervalBox);
refreshIntervalBox = dialog.createDoubleBox(
((double) initialSettings.getRefreshInterval()) / 1000, 4);
refreshIntervalBox.setStyleName(STYLE_INPUT);
labelAndRefreshIntervalBoxPanel.setStyleName(STYLE_BOXPANEL);
labelAndRefreshIntervalBoxPanel.add(refreshIntervalBox);
mainContentPanel.add(labelAndRefreshIntervalBoxPanel);
return mainContentPanel;
}
@Override
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
mainContentPanel = new FlowPanel();
FlowPanel labelAndRefreshIntervalBoxPanel = new FlowPanel();
Label labelIntervalBox = new Label(stringMessages.refreshInterval() + ":");
labelIntervalBox.setStyleName(STYLE_LABEL);
labelAndRefreshIntervalBoxPanel.add(labelIntervalBox);
refreshIntervalBox = dialog.createDoubleBox(((double) initialSettings.getRefreshInterval()) / 1000, 4);
refreshIntervalBox.setStyleName(STYLE_INPUT);
labelAndRefreshIntervalBoxPanel.setStyleName(STYLE_BOXPANEL);
labelAndRefreshIntervalBoxPanel.add(refreshIntervalBox);
mainContentPanel.add(labelAndRefreshIntervalBoxPanel);
return mainContentPanel;
}
@SuppressWarnings("unchecked")
@Override
public T getResult() {
T result = (T) new TimePanelSettings();
result.setRefreshInterval(refreshIntervalBox.getValue() == null ? -1
: (long) (refreshIntervalBox.getValue() * 1000));
return result;
}
@SuppressWarnings("unchecked")
@Override
public T getResult() {
long refreshInterval = refreshIntervalBox.getValue() == null ? -1
: (long) (refreshIntervalBox.getValue() * 1000);
return (T) new TimePanelSettings(refreshInterval);
}
@Override
public Validator<T> getValidator() {
return new Validator<T>() {
@Override
public String getErrorMessage(TimePanelSettings valueToValidate) {
String errorMessage = null;
if (valueToValidate.getRefreshInterval() < 500) {
errorMessage = stringMessages
.refreshIntervalMustBeGreaterThanXSeconds("0.5");
}
return errorMessage;
}
};
}
@Override
public Validator<T> getValidator() {
return new Validator<T>() {
@Override
public String getErrorMessage(TimePanelSettings valueToValidate) {
String errorMessage = null;
if (valueToValidate.getRefreshInterval() < 500) {
errorMessage = stringMessages.refreshIntervalMustBeGreaterThanXSeconds("0.5");
}
return errorMessage;
}
};
}
@Override
public FocusWidget getFocusWidget() {
return refreshIntervalBox;
}
@Override
public FocusWidget getFocusWidget() {
return refreshIntervalBox;
}
}
@@ -0,0 +1,45 @@
package com.sap.sailing.gwt.ui.client.media;
import java.io.Serializable;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class MediaPlayerLifecycle implements ComponentLifecycle<MediaPlayerSettings, MediaPlayerSettingsDialogComponent> {
private final StringMessages stringMessages;
public MediaPlayerLifecycle(StringMessages stringMessages) {
this.stringMessages = stringMessages;
}
@Override
public MediaPlayerSettingsDialogComponent getSettingsDialogComponent(MediaPlayerSettings settings) {
return new MediaPlayerSettingsDialogComponent(settings, stringMessages);
}
@Override
public MediaPlayerSettings createDefaultSettings() {
return new MediaPlayerSettings();
}
@Override
public MediaPlayerSettings cloneSettings(MediaPlayerSettings settings) {
return new MediaPlayerSettings(settings.isAutoSelectMedia());
}
@Override
public String getLocalizedShortName() {
return stringMessages.videoComponentShortName();
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
@Override
public boolean hasSettings() {
return true;
}
}
@@ -38,9 +38,9 @@ import com.sap.sailing.gwt.ui.client.media.shared.MediaPlayer;
import com.sap.sailing.gwt.ui.client.media.shared.VideoPlayer;
import com.sap.sailing.gwt.ui.client.media.shared.VideoSynchPlayer;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.MediaType;
import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
import com.sap.sse.gwt.client.player.PlayStateListener;
@@ -48,21 +48,21 @@ import com.sap.sse.gwt.client.player.TimeListener;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.shared.components.Component;
import com.sap.sse.gwt.client.shared.components.AbstractComponent;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
import com.sap.sse.gwt.client.useragent.UserAgentDetails.AgentTypes;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.shared.UserDTO;
public class MediaPlayerManagerComponent implements Component<AbstractSettings>, PlayStateListener, TimeListener,
public class MediaPlayerManagerComponent extends AbstractComponent<MediaPlayerSettings> implements PlayStateListener, TimeListener,
MediaPlayerManager, CloseHandler<Window>, ClosingHandler {
static interface VideoContainerFactory<T> {
T createVideoContainer(VideoSynchPlayer videoPlayer, boolean showSynchControls, MediaServiceAsync mediaService,
ErrorReporter errorReporter, PlayerCloseListener playerCloseListener, PopoutListener popoutListener);
}
private final SimplePanel rootPanel = new SimplePanel();
private final UserService userService;
@@ -80,14 +80,16 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
private final ErrorReporter errorReporter;
private final UserAgentDetails userAgent;
private final PopupPositionProvider popupPositionProvider;
private boolean autoSelectMedia;
private MediaPlayerSettings settings;
private final MediaPlayerLifecycle mediaPlayerLifecycle;
private PlayerChangeListener playerChangeListener;
public MediaPlayerManagerComponent(RegattaAndRaceIdentifier selectedRaceIdentifier,
public MediaPlayerManagerComponent(MediaPlayerLifecycle mediaPlayerLifecycle, RegattaAndRaceIdentifier selectedRaceIdentifier,
RaceTimesInfoProvider raceTimesInfoProvider, Timer raceTimer, MediaServiceAsync mediaService,
UserService userService, StringMessages stringMessages, ErrorReporter errorReporter,
UserAgentDetails userAgent, PopupPositionProvider popupPositionProvider, boolean autoSelectMedia) {
UserAgentDetails userAgent, PopupPositionProvider popupPositionProvider, MediaPlayerSettings settings) {
this.mediaPlayerLifecycle = mediaPlayerLifecycle;
this.userService = userService;
this.raceIdentifier = selectedRaceIdentifier;
this.raceTimesInfoProvider = raceTimesInfoProvider;
@@ -104,7 +106,7 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
this.errorReporter = errorReporter;
this.userAgent = userAgent;
this.popupPositionProvider = popupPositionProvider;
this.autoSelectMedia = autoSelectMedia;
this.settings = settings;
Window.addCloseHandler(this);
Window.addWindowClosingHandler(this);
@@ -282,9 +284,9 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
*
* @return
*/
private AsyncCallback<Collection<MediaTrack>> getAssignedMediaCallback() {
private AsyncCallback<Iterable<MediaTrack>> getAssignedMediaCallback() {
return new AsyncCallback<Collection<MediaTrack>>() {
return new AsyncCallback<Iterable<MediaTrack>>() {
@Override
public void onFailure(Throwable caught) {
@@ -294,14 +296,14 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
}
@Override
public void onSuccess(Collection<MediaTrack> mediaTracks) {
public void onSuccess(Iterable<MediaTrack> mediaTracks) {
MediaPlayerManagerComponent.this.assignedMediaTracks.clear();
MediaPlayerManagerComponent.this.assignedMediaTracks.addAll(mediaTracks);
Util.addAll(mediaTracks, MediaPlayerManagerComponent.this.assignedMediaTracks);
for (MediaTrack mediaTrack : MediaPlayerManagerComponent.this.assignedMediaTracks) {
setStatus(mediaTrack);
}
if (autoSelectMedia) {
if (settings.isAutoSelectMedia()) {
playDefault();
}
notifyStateChange();
@@ -316,9 +318,9 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
*
* @return
*/
private AsyncCallback<Collection<MediaTrack>> getOverlappingMediaCallback() {
private AsyncCallback<Iterable<MediaTrack>> getOverlappingMediaCallback() {
return new AsyncCallback<Collection<MediaTrack>>() {
return new AsyncCallback<Iterable<MediaTrack>>() {
@Override
public void onFailure(Throwable caught) {
@@ -328,9 +330,9 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
}
@Override
public void onSuccess(Collection<MediaTrack> mediaTracks) {
public void onSuccess(Iterable<MediaTrack> mediaTracks) {
MediaPlayerManagerComponent.this.overlappingMediaTracks.clear();
MediaPlayerManagerComponent.this.overlappingMediaTracks.addAll(mediaTracks);
Util.addAll(mediaTracks, MediaPlayerManagerComponent.this.overlappingMediaTracks);
for (MediaTrack mediaTrack : MediaPlayerManagerComponent.this.overlappingMediaTracks) {
setStatus(mediaTrack);
}
@@ -730,22 +732,27 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
@Override
public String getLocalizedShortName() {
return stringMessages.videoComponentShortName();
return mediaPlayerLifecycle.getLocalizedShortName();
}
@Override
public boolean hasSettings() {
return false;
return mediaPlayerLifecycle.hasSettings();
}
@Override
public SettingsDialogComponent<AbstractSettings> getSettingsDialogComponent() {
throw new UnsupportedOperationException();
public SettingsDialogComponent<MediaPlayerSettings> getSettingsDialogComponent() {
return mediaPlayerLifecycle.getSettingsDialogComponent(mediaPlayerLifecycle.cloneSettings(settings));
}
@Override
public void updateSettings(AbstractSettings newSettings) {
throw new UnsupportedOperationException();
public void updateSettings(MediaPlayerSettings newSettings) {
this.settings = newSettings;
}
@Override
public MediaPlayerSettings getSettings() {
return settings;
}
@Override
@@ -798,5 +805,4 @@ public class MediaPlayerManagerComponent implements Component<AbstractSettings>,
public ErrorReporter getErrorReporter() {
return errorReporter;
}
}
@@ -0,0 +1,32 @@
package com.sap.sailing.gwt.ui.client.media;
import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
public class MediaPlayerSettings extends AbstractSettings {
private final boolean autoPlayMedia;
public static final String PARAM_AUTOPLAY_MEDIA = "autoSelectMedia";
/**
* The default settings
*/
public MediaPlayerSettings() {
this.autoPlayMedia = true;
}
public MediaPlayerSettings(boolean autoPlayMedia) {
this.autoPlayMedia = autoPlayMedia;
}
public boolean isAutoSelectMedia() {
return autoPlayMedia;
}
public static MediaPlayerSettings readSettingsFromURL() {
final Boolean autoPlayMedia = GwtHttpRequestUtils.getBooleanParameter(PARAM_AUTOPLAY_MEDIA, true /* default */);
return new MediaPlayerSettings(autoPlayMedia);
}
}
@@ -0,0 +1,60 @@
package com.sap.sailing.gwt.ui.client.media;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class MediaPlayerSettingsDialogComponent implements SettingsDialogComponent<MediaPlayerSettings> {
private final MediaPlayerSettings initialSettings;
private CheckBox autoPlayMediaCheckbox;
private final StringMessages stringMessages;
public MediaPlayerSettingsDialogComponent(MediaPlayerSettings initialSettings, StringMessages stringMessages) {
this.initialSettings = initialSettings;
this.stringMessages = stringMessages;
}
@Override
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
VerticalPanel vp = new VerticalPanel();
Grid grid = new Grid(1,2);
grid.setCellSpacing(5);
vp.add(grid);
autoPlayMediaCheckbox = dialog.createCheckbox("");
autoPlayMediaCheckbox.setValue(initialSettings.isAutoSelectMedia());
grid.setWidget(0, 0, new Label(stringMessages.autoPlayMedia() + ":"));
grid.setWidget(0, 1, autoPlayMediaCheckbox);
return vp;
}
@Override
public MediaPlayerSettings getResult() {
return new MediaPlayerSettings(autoPlayMediaCheckbox.getValue());
}
@Override
public Validator<MediaPlayerSettings> getValidator() {
return new Validator<MediaPlayerSettings>() {
@Override
public String getErrorMessage(MediaPlayerSettings valueToValidate) {
return null;
}
};
}
@Override
public FocusWidget getFocusWidget() {
return autoPlayMediaCheckbox;
}
}
@@ -74,10 +74,12 @@ import com.sap.sse.gwt.client.shared.components.Component;
* @author Benjamin Ebling (D056866), Axel Uhl (d043530)
*
*/
public abstract class AbstractCompetitorRaceChart<SettingsType extends ChartSettings> extends AbstractRaceChart implements
public abstract class AbstractCompetitorRaceChart<SettingsType extends ChartSettings> extends AbstractRaceChart<SettingsType> implements
CompetitorSelectionChangeListener, RequiresResize {
public static final String LOAD_COMPETITOR_CHART_DATA_CATEGORY = "loadCompetitorChartData";
public static final long DEFAULT_STEPSIZE = 5000;
private static final int LINE_WIDTH = 1;
private final Label noCompetitorsSelectedLabel;
@@ -90,7 +92,7 @@ public abstract class AbstractCompetitorRaceChart<SettingsType extends ChartSett
private final boolean allowTimeAdjust;
private final String leaderboardGroupName;
private final String leaderboardName;
private long stepSize = 5000;
private long stepSize = DEFAULT_STEPSIZE;
private final Map<Pair<CompetitorDTO, DetailType>, Series> dataSeriesForDetailTypeAndCompetitor = new HashMap<>();
private final Map<Pair<CompetitorDTO, DetailType>, Series> markPassingSeriesByCompetitor = new HashMap<>();
private Long timeOfEarliestRequestInMillis;
@@ -23,6 +23,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.charts.ChartCssResources.ChartsCss;
import com.sap.sse.common.settings.Settings;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
@@ -32,9 +33,10 @@ import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.TimeZoomChangeListener;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.shared.components.Component;
import com.sap.sse.gwt.client.shared.components.SettingsDialog;
public abstract class AbstractRaceChart extends AbsolutePanel implements TimeListener, TimeZoomChangeListener, TimeRangeChangeListener {
public abstract class AbstractRaceChart<SettingsType extends Settings> extends AbsolutePanel implements Component<SettingsType>, TimeListener, TimeZoomChangeListener, TimeRangeChangeListener {
/**
* Used as the turboThreshold for the Highcharts series; this is basically the maximum number of points in a series
* to be displayed. Default is 1000. See also bug 1742.
@@ -244,4 +246,9 @@ public abstract class AbstractRaceChart extends AbsolutePanel implements TimeLis
timePlotLine.setValue(date.getTime());
chart.getXAxis().addPlotLines(timePlotLine);
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -453,4 +453,14 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component<Ab
@Override
public void filteredCompetitorsListChanged(Iterable<CompetitorDTO> filteredCompetitors) {
}
@Override
public AbstractSettings getSettings() {
return null;
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -101,11 +101,10 @@ import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.shared.components.Component;
import com.sap.sse.gwt.client.shared.components.SettingsDialog;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class EditMarkPositionPanel extends AbstractRaceChart implements Component<AbstractSettings>, RequiresResize, SelectionChangeEvent.Handler {
public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> implements RequiresResize, SelectionChangeEvent.Handler {
protected static final int FIX_OVERLAY_Z_ORDER = 230;
private final RaceMap raceMap;
private final LeaderboardPanel leaderboardPanel;
@@ -984,4 +983,9 @@ public class EditMarkPositionPanel extends AbstractRaceChart implements Componen
public void setLeaderboard(LeaderboardDTO leaderboard) {
raceIdentifierToLeaderboardRaceColumnAndFleetMapper.setLeaderboard(leaderboard);
}
@Override
public AbstractSettings getSettings() {
return null;
}
}
@@ -163,4 +163,14 @@ public class MarksPanel extends SimplePanel implements Component<AbstractSetting
public void select(MarkDTO mark) {
markTable.getSelectionModel().setSelected(mark, true);
}
@Override
public AbstractSettings getSettings() {
return null;
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -25,6 +25,11 @@ public class MultiCompetitorLeaderboardChart extends AbstractCompetitorLeaderboa
return true;
}
@Override
public MultiCompetitorLeaderboardChartSettings getSettings() {
return settings;
}
@Override
public SettingsDialogComponent<MultiCompetitorLeaderboardChartSettings> getSettingsDialogComponent() {
MultiCompetitorLeaderboardChartSettings chartSettings = new MultiCompetitorLeaderboardChartSettings(settings.getDetailType());
@@ -32,7 +32,9 @@ public class MultiCompetitorRaceChart extends AbstractCompetitorRaceChart<MultiC
private boolean hasOverallLeaderboard;
public MultiCompetitorRaceChart(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
private final MultiCompetitorRaceChartLifecycle lifeycycle;
public MultiCompetitorRaceChart(MultiCompetitorRaceChartLifecycle lifeycycle, SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
CompetitorSelectionProvider competitorSelectionProvider, RegattaAndRaceIdentifier selectedRaceIdentifier,
Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, final StringMessages stringMessages,
final ErrorReporter errorReporter, boolean compactChart, boolean allowTimeAdjust,
@@ -40,6 +42,7 @@ public class MultiCompetitorRaceChart extends AbstractCompetitorRaceChart<MultiC
super(sailingService, asyncActionsExecutor, competitorSelectionProvider, selectedRaceIdentifier, timer, timeRangeWithZoomProvider, stringMessages, errorReporter,
/* show initially */DetailType.WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD, null, compactChart,
allowTimeAdjust, leaderboardGroupName, leaderboardName);
this.lifeycycle = lifeycycle;
if (leaderboardGroupName != null) {
sailingService.getLeaderboardGroupByName(leaderboardGroupName, false,
new AsyncCallback<LeaderboardGroupDTO>() {
@@ -82,6 +85,11 @@ public class MultiCompetitorRaceChart extends AbstractCompetitorRaceChart<MultiC
}
}
@Override
public MultiCompetitorRaceChartSettings getSettings() {
return new MultiCompetitorRaceChartSettings(getAbstractSettings(), getSelectedFirstDetailType(), getSelectedSecondDetailType());
}
@Override
protected Component<MultiCompetitorRaceChartSettings> getComponent() {
return this;
@@ -89,7 +97,7 @@ public class MultiCompetitorRaceChart extends AbstractCompetitorRaceChart<MultiC
@Override
public String getLocalizedShortName() {
return stringMessages.competitorCharts();
return lifeycycle.getLocalizedShortName();
}
@Override
@@ -0,0 +1,49 @@
package com.sap.sailing.gwt.ui.client.shared.charts;
import java.io.Serializable;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class MultiCompetitorRaceChartLifecycle implements ComponentLifecycle<MultiCompetitorRaceChartSettings, MultiCompetitorRaceChartSettingsComponent> {
private final StringMessages stringMessages;
private final boolean hasOverallLeaderboard;
public MultiCompetitorRaceChartLifecycle(StringMessages stringMessages, boolean hasOverallLeaderboard) {
this.stringMessages = stringMessages;
this.hasOverallLeaderboard = hasOverallLeaderboard;
}
@Override
public MultiCompetitorRaceChartSettingsComponent getSettingsDialogComponent(MultiCompetitorRaceChartSettings settings) {
return new MultiCompetitorRaceChartSettingsComponent(settings, stringMessages, hasOverallLeaderboard);
}
@Override
public MultiCompetitorRaceChartSettings createDefaultSettings() {
ChartSettings chartSettings = new ChartSettings(AbstractCompetitorRaceChart.DEFAULT_STEPSIZE);
DetailType defaultDetailType = DetailType.WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD;
return new MultiCompetitorRaceChartSettings(chartSettings, defaultDetailType, null);
}
@Override
public MultiCompetitorRaceChartSettings cloneSettings(MultiCompetitorRaceChartSettings settings) {
return new MultiCompetitorRaceChartSettings(new ChartSettings(settings.getStepSize()), settings.getFirstDetailType(), settings.getSecondDetailType());
}
@Override
public String getLocalizedShortName() {
return stringMessages.competitorCharts();
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
@Override
public boolean hasSettings() {
return true;
}
}
@@ -6,9 +6,9 @@ public class MultiCompetitorRaceChartSettings extends ChartSettings {
private final DetailType firstDetailType;
private final DetailType secondDetailType;
public MultiCompetitorRaceChartSettings(ChartSettings superResult, DetailType firstDetailType,
public MultiCompetitorRaceChartSettings(ChartSettings settings, DetailType firstDetailType,
DetailType secondDetailType) {
super(superResult);
super(settings);
this.firstDetailType = firstDetailType;
this.secondDetailType = secondDetailType;
}
@@ -56,16 +56,16 @@ import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.shared.components.Component;
import com.sap.sse.gwt.client.shared.components.SettingsDialog;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class WindChart extends AbstractRaceChart implements Component<WindChartSettings>, RequiresResize {
public class WindChart extends AbstractRaceChart<WindChartSettings> implements RequiresResize {
public static final String LODA_WIND_CHART_DATA_CATEGORY = "loadWindChartData";
private static final int LINE_WIDTH = 1;
private final WindChartSettings settings;
private final WindChartLifecycle windChartLifecycle;
/**
* Holds one series for each wind source for which data has been received.
@@ -89,10 +89,11 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
* constructor must ensure to trigger {@link RaceSelectionChangeListener#onRaceSelectionChange(List)} at
* least once to ensure that this chart sets its {@link AbstractRaceChart#selectedRaceIdentifier} field.
*/
public WindChart(SailingServiceAsync sailingService, RegattaAndRaceIdentifier selectedRaceIdentifier, Timer timer,
public WindChart(WindChartLifecycle windChartLifecycle, SailingServiceAsync sailingService, RegattaAndRaceIdentifier selectedRaceIdentifier, Timer timer,
TimeRangeWithZoomProvider timeRangeWithZoomProvider, WindChartSettings settings, final StringMessages stringMessages,
AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, boolean compactChart) {
super(sailingService, selectedRaceIdentifier, timer, timeRangeWithZoomProvider, stringMessages, asyncActionsExecutor, errorReporter);
this.windChartLifecycle = windChartLifecycle;
this.settings = settings;
windSourceDirectionSeries = new HashMap<WindSource, Series>();
windSourceSpeedSeries = new HashMap<WindSource, Series>();
@@ -206,7 +207,7 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
@Override
public String getLocalizedShortName() {
return stringMessages.wind();
return windChartLifecycle.getLocalizedShortName();
}
@Override
@@ -419,14 +420,12 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
@Override
public boolean hasSettings() {
return true;
return windChartLifecycle.hasSettings();
}
@Override
public SettingsDialogComponent<WindChartSettings> getSettingsDialogComponent() {
WindChartSettings windChartSettings = new WindChartSettings(settings.isShowWindSpeedSeries(), settings.getWindSpeedSourcesToDisplay(),
settings.isShowWindDirectionsSeries(), settings.getWindDirectionSourcesToDisplay(), settings.getResolutionInMilliseconds());
return new WindChartSettingsDialogComponent(windChartSettings, stringMessages);
return windChartLifecycle.getSettingsDialogComponent(windChartLifecycle.cloneSettings(settings));
}
/**
@@ -622,5 +621,9 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
public String getDependentCssClassName() {
return "windChart";
}
@Override
public WindChartSettings getSettings() {
return settings;
}
}
@@ -0,0 +1,46 @@
package com.sap.sailing.gwt.ui.client.shared.charts;
import java.io.Serializable;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class WindChartLifecycle implements ComponentLifecycle<WindChartSettings, WindChartSettingsDialogComponent> {
private final StringMessages stringMessages;
public WindChartLifecycle(StringMessages stringMessages) {
this.stringMessages = stringMessages;
}
@Override
public WindChartSettingsDialogComponent getSettingsDialogComponent(WindChartSettings settings) {
return new WindChartSettingsDialogComponent(settings, stringMessages);
}
@Override
public WindChartSettings createDefaultSettings() {
return new WindChartSettings();
}
@Override
public WindChartSettings cloneSettings(WindChartSettings settings) {
return new WindChartSettings(settings.isShowWindSpeedSeries(), settings.getWindSpeedSourcesToDisplay(),
settings.isShowWindDirectionsSeries(), settings.getWindDirectionSourcesToDisplay(),
settings.getResolutionInMilliseconds());
}
@Override
public String getLocalizedShortName() {
return stringMessages.wind();
}
@Override
public boolean hasSettings() {
return true;
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
}
@@ -21,10 +21,10 @@ import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.LoadApi;
import com.google.gwt.maps.client.LoadApi.LoadLibrary;
import com.google.gwt.maps.client.MapOptions;
@@ -330,6 +330,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
private RaceMapImageManager raceMapImageManager;
private final RaceMapSettings settings;
private final RaceMapLifecycle raceMapLifecycle;
private final StringMessages stringMessages;
@@ -371,9 +372,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
private RaceSimulationOverlay simulationOverlay;
private WindStreamletsRaceboardOverlay streamletOverlay;
private final boolean showViewStreamlets;
private final boolean showViewStreamletColors;
private final boolean showViewSimulation;
private final boolean isSimulationEnabled;
private static final String GET_POLAR_CATEGORY = "getPolar";
@@ -393,8 +393,6 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
*/
private boolean requiresCoordinateSystemUpdateWhenCoursePositionAndWindDirectionIsKnown;
private final boolean showMapControls;
/**
* Tells whether currently an auto-zoom is in progress; this is used particularly to keep the smooth CSS boat transitions
* active while auto-zooming whereas stopping them seems the better option for manual zooms.
@@ -409,18 +407,19 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
private final NumberFormat numberFormatOneDecimal = NumberFormat.getFormat("0.0");
public RaceMap(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
public RaceMap(RaceMapLifecycle raceMapLifecycle, RaceMapSettings raceMapSettings, SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
ErrorReporter errorReporter, Timer timer, CompetitorSelectionProvider competitorSelection, StringMessages stringMessages,
boolean showMapControls, boolean showViewStreamlets, boolean showViewStreamletColors, boolean showViewSimulation,
RegattaAndRaceIdentifier raceIdentifier, RaceMapResources raceMapResources, boolean showHeaderPanel) {
RegattaAndRaceIdentifier raceIdentifier, RaceMapResources raceMapResources,
boolean isSimulationEnabled, boolean showHeaderPanel) {
this.raceMapLifecycle = raceMapLifecycle;
this.setSize("100%", "100%");
this.showMapControls = showMapControls;
this.stringMessages = stringMessages;
this.sailingService = sailingService;
this.raceIdentifier = raceIdentifier;
this.asyncActionsExecutor = asyncActionsExecutor;
this.errorReporter = errorReporter;
this.timer = timer;
this.isSimulationEnabled = isSimulationEnabled;
timer.addTimeListener(this);
raceMapImageManager = new RaceMapImageManager(raceMapResources);
markDTOs = new HashMap<String, MarkDTO>();
@@ -435,21 +434,18 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
this.competitorSelection = competitorSelection;
this.raceCompetitorSet = new RaceCompetitorSet(competitorSelection);
competitorSelection.addCompetitorSelectionChangeListener(this);
settings = new RaceMapSettings();
settings = raceMapSettings;
coordinateSystem = new DelegateCoordinateSystem(new IdentityCoordinateSystem());
fixesAndTails = new FixesAndTails(coordinateSystem);
updateCoordinateSystemFromSettings();
lastTimeChangeBeforeInitialization = null;
isMapInitialized = false;
this.showViewStreamlets = showViewStreamlets;
this.showViewStreamletColors = showViewStreamletColors;
this.showViewSimulation = showViewSimulation;
this.hasPolar = false;
headerPanel = new FlowPanel();
headerPanel.setStyleName("RaceMap-HeaderPanel");
panelForLeftHeaderLabels = new AbsolutePanel();
panelForRightHeaderLabels = new AbsolutePanel();
initializeData(showMapControls, showHeaderPanel);
initializeData(settings.isShowMapControls(), showHeaderPanel);
combinedWindPanel = new CombinedWindPanel(raceMapImageManager, raceMapResources.raceMapStyle(), stringMessages, coordinateSystem);
combinedWindPanel.setVisible(false);
trueNorthIndicatorPanel = new TrueNorthIndicatorPanel(this, raceMapImageManager, raceMapResources.raceMapStyle(), stringMessages, coordinateSystem);
@@ -489,7 +485,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
coordinateSystem.setCoordinateSystem(new RotateAndTranslateCoordinateSystem(centerOfCourse,
lastCombinedTrueWindFromDirection.add(new DegreeBearingImpl(90))));
if (map != null) {
mapOptions = getMapOptions(showMapControls, /* wind-up */ true);
mapOptions = getMapOptions(settings.isShowMapControls(), /* wind-up */ true);
} else {
mapOptions = null;
}
@@ -506,7 +502,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
} else {
if (map != null) {
mapOptions = getMapOptions(showMapControls, /* wind-up */ false);
mapOptions = getMapOptions(settings.isShowMapControls(), /* wind-up */ false);
} else {
mapOptions = null;
}
@@ -620,12 +616,12 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
streamletOverlay = new WindStreamletsRaceboardOverlay(getMap(), /* zIndex */ 0,
timer, raceIdentifier, sailingService, asyncActionsExecutor, stringMessages, coordinateSystem);
streamletOverlay.addToMap();
if (showViewStreamlets) {
streamletOverlay.setColors(showViewStreamletColors);
if (settings.isShowWindStreamletOverlay()) {
streamletOverlay.setColors(settings.isShowWindStreamletColors());
streamletOverlay.setVisible(true);
}
if (showViewSimulation) {
if (isSimulationEnabled) {
// determine availability of polar diagram
setHasPolar();
// initialize simulation canvas
@@ -947,7 +943,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
quickRanks = raceMapDataDTO.quickRanks;
competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber =
raceMapDataDTO.competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber;
if (showViewSimulation && settings.isShowSimulationOverlay()) {
if (isSimulationEnabled && settings.isShowSimulationOverlay()) {
lastLegNumber = raceMapDataDTO.coursePositions.currentLegNumber;
simulationOverlay.updateLeg(Math.max(lastLegNumber, 1), /* clearCanvas */ false, raceMapDataDTO.simulationResultVersion);
}
@@ -2047,7 +2043,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
vPanel.add(createInfoWindowLabelAndValue(stringMessages.position(), formatPosition(markDTO.position.getLatDeg(), markDTO.position.getLngDeg())));
return vPanel;
}
public Widget getInfoWindowContent(ManeuverDTO maneuver) {
SpeedWithBearingDTO before = maneuver.speedWithBearingBefore;
SpeedWithBearingDTO after = maneuver.speedWithBearingAfter;
@@ -2245,18 +2241,18 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
private void createAndAddMarkerOfManeuver(ManeuverDTO maneuver) {
LatLng latLng = coordinateSystem.toLatLng(maneuver.position);
LatLng latLng = coordinateSystem.toLatLng(maneuver.position);
Marker maneuverMarker = raceMapImageManager.maneuverIconsForTypeAndDirectionIndicatingColor
.get(new Pair<ManeuverType, ManeuverColor>(maneuver.type, ManeuverColor.getManeuverColor(maneuver)));
MarkerOptions options = MarkerOptions.newInstance();
options.setIcon(maneuverMarker.getIcon_MarkerImage());
Marker marker = Marker.newInstance(options);
marker.setPosition(latLng);
MarkerOptions options = MarkerOptions.newInstance();
options.setIcon(maneuverMarker.getIcon_MarkerImage());
Marker marker = Marker.newInstance(options);
marker.setPosition(latLng);
marker.setTitle(ManeuverTypeFormatter.format(maneuver.type, stringMessages));
marker.addClickHandler(new ManeuverMarkerClickedListener(this, maneuver));
maneuverMarkers.add(marker);
marker.setMap(map);
}
maneuverMarkers.add(marker);
marker.setMap(map);
}
/**
* @param date
@@ -2428,7 +2424,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
@Override
public String getLocalizedShortName() {
return stringMessages.map();
return raceMapLifecycle.getLocalizedShortName();
}
@Override
@@ -2438,12 +2434,12 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
@Override
public boolean hasSettings() {
return true;
return raceMapLifecycle.hasSettings();
}
@Override
public SettingsDialogComponent<RaceMapSettings> getSettingsDialogComponent() {
return new RaceMapSettingsDialogComponent(settings, stringMessages, this.showViewSimulation && this.hasPolar);
return new RaceMapSettingsDialogComponent(settings, stringMessages, this.isSimulationEnabled && this.hasPolar);
}
@Override
@@ -2891,4 +2887,10 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
InfoWindow getLastInfoWindow() {
return lastInfoWindow;
}
@Override
public String getId() {
return getLocalizedShortName();
}
}
@@ -0,0 +1,44 @@
package com.sap.sailing.gwt.ui.client.shared.racemap;
import java.io.Serializable;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
public class RaceMapLifecycle implements ComponentLifecycle<RaceMapSettings, RaceMapSettingsDialogComponent> {
private final StringMessages stringMessages;
public RaceMapLifecycle(StringMessages stringMessages) {
this.stringMessages = stringMessages;
}
@Override
public RaceMapSettingsDialogComponent getSettingsDialogComponent(RaceMapSettings settings) {
return new RaceMapSettingsDialogComponent(settings, stringMessages, false);
}
@Override
public RaceMapSettings createDefaultSettings() {
return new RaceMapSettings();
}
@Override
public RaceMapSettings cloneSettings(RaceMapSettings settings) {
return new RaceMapSettings(settings);
}
@Override
public String getLocalizedShortName() {
return stringMessages.map();
}
@Override
public Serializable getComponentId() {
return getLocalizedShortName();
}
@Override
public boolean hasSettings() {
return true;
}
}
@@ -7,11 +7,11 @@ import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
public class RaceMapSettings extends AbstractSettings {
private static final Set<ManeuverType> DEFAULT_SHOWN_MANEUVER = getDefaultManeuvers();
public static final String PARAM_SHOW_MAPCONTROLS = "showMapControls";
private boolean showDouglasPeuckerPoints = false;
private final Set<ManeuverType> maneuverTypesToShow;
@@ -38,6 +38,8 @@ public class RaceMapSettings extends AbstractSettings {
private boolean showSimulationOverlay = false;
private boolean showMapControls = true;
/**
* If <code>true</code>, all map contents will be transformed to a water-only environment, rotating all directions /
* bearings / headings so that an assumed average wind direction for the race is coming from the top of the map
@@ -49,10 +51,16 @@ public class RaceMapSettings extends AbstractSettings {
private boolean windUp = false;
public RaceMapSettings() {
maneuverTypesToShow = DEFAULT_SHOWN_MANEUVER;
this.maneuverTypesToShow = getDefaultManeuvers();
this.zoomSettings = new RaceMapZoomSettings();
this.helpLinesSettings = new RaceMapHelpLinesSettings();
}
public RaceMapSettings(boolean showMapCcontrol) {
this();
this.showMapControls = showMapCcontrol;
}
/**
* "Copy constructor" that produces a new settings object that equals the one passed as argument
*/
@@ -68,6 +76,7 @@ public class RaceMapSettings extends AbstractSettings {
this.showSimulationOverlay = settings.showSimulationOverlay;
this.showWindStreamletOverlay = settings.showWindStreamletOverlay;
this.showWindStreamletColors = settings.showWindStreamletColors;
this.showMapControls = settings.showMapControls;
this.tailLengthInMilliseconds = settings.tailLengthInMilliseconds;
this.windUp = settings.windUp;
this.zoomSettings = new RaceMapZoomSettings(settings.zoomSettings.getTypesToConsiderOnZoom(), settings.zoomSettings.isZoomToSelectedCompetitors());
@@ -159,7 +168,7 @@ public class RaceMapSettings extends AbstractSettings {
public void setHelpLinesSettings(RaceMapHelpLinesSettings helpLinesSettings) {
this.helpLinesSettings = helpLinesSettings;
}
public boolean getTransparentHoverlines() {
return this.transparentHoverlines;
}
@@ -199,8 +208,16 @@ public class RaceMapSettings extends AbstractSettings {
public void setWindUp(boolean windUp) {
this.windUp = windUp;
}
private static HashSet<ManeuverType> getDefaultManeuvers() {
public boolean isShowMapControls() {
return showMapControls;
}
public void setShowMapControls(boolean showMapControls) {
this.showMapControls = showMapControls;
}
private HashSet<ManeuverType> getDefaultManeuvers() {
HashSet<ManeuverType> types = new HashSet<ManeuverType>();
types.add(ManeuverType.JIBE);
types.add(ManeuverType.TACK);
@@ -208,4 +225,8 @@ public class RaceMapSettings extends AbstractSettings {
return types;
}
public static RaceMapSettings readSettingsFromURL() {
final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_MAPCONTROLS, true /* default */);
return new RaceMapSettings(showMapControls);
}
}
@@ -48,15 +48,16 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
private DoubleBox buoyZoneRadiusBox;
private CheckBox transparentHoverlines;
private IntegerBox hoverlineStrokeWeight;
private boolean showViewSimulation;
private boolean isSimulationEnabled;
private final StringMessages stringMessages;
private final RaceMapSettings initialSettings;
private ArrayList<CheckBox> disableOnlySelectedWhenAreFalse;
public RaceMapSettingsDialogComponent(RaceMapSettings settings, StringMessages stringMessages, boolean showViewSimulation) {
this.showViewSimulation = showViewSimulation;
public RaceMapSettingsDialogComponent(RaceMapSettings settings, StringMessages stringMessages, boolean isSimulationEnabled) {
this.isSimulationEnabled = isSimulationEnabled;
this.stringMessages = stringMessages;
initialSettings = settings;
}
@@ -89,7 +90,7 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
}
});
if (showViewSimulation) {
if (isSimulationEnabled) {
showSimulationOverlayCheckbox = dialog.createCheckbox(stringMessages.showSimulationOverlay());
showSimulationOverlayCheckbox.setValue(initialSettings.isShowSimulationOverlay());
vp.add(showSimulationOverlayCheckbox);
@@ -267,7 +268,8 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
result.setShowOnlySelectedCompetitors(showOnlySelectedCompetitorsCheckBox.getValue());
result.setShowWindStreamletOverlay(showWindStreamletOverlayCheckbox.getValue());
result.setShowWindStreamletColors(showWindStreamletColorsCheckbox.getValue());
if (showViewSimulation) {
result.setShowMapControls(initialSettings.isShowMapControls());
if (isSimulationEnabled) {
result.setShowSimulationOverlay(showSimulationOverlayCheckbox.getValue());
} else {
result.setShowSimulationOverlay(false);
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff. Show more