mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-24 04:53:54 +00:00
Merge branch 'master' into bug3785
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Home.gwt.xml java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java Change-Id: I73298972a7761dc6580154ecc83d5eda1b39fadc
This commit is contained in:
commit
133fcdaa58
60 files changed
+1665
-172
No files matched your search
+5
-1
@@ -111,7 +111,11 @@ public class WebSocketConnectionManager implements LiveDataConnection {
|
||||
if (session != null) {
|
||||
session.disconnect();
|
||||
}
|
||||
client.stop();
|
||||
synchronized (this) {
|
||||
if (client != null) {
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class WebSocket extends WebSocketAdapter {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24.85 20.35"><path fill=
|
||||
"#FFF" d="M6.58,7.58H16v2H6.61A5.3,5.3,0,0,1,6.58,7.58Zm3.42-3H8.15a5.51,5.51,
|
||||
0,0,0-1.3,2H10v-2Zm-1.68,8H13v-2H6.91A5.52,5.52,0,0,0,8.32,12.58ZM2.5,
|
||||
8.5c0-.31,0-0.62,0-0.92H0v2H2.57A9.52,9.52,0,0,1,2.5,8.5Zm0.24,
|
||||
2.08H0v2H3.43A9.41,9.41,0,0,1,2.74,10.58Zm0.62-6H0v2H2.7A9.4,9.4,0,0,1,3.36,
|
||||
4.58ZM23.44,20.35l-5.65-5.65a8.45,8.45,0,1,1,1.3-1.53l5.76,5.76ZM18.5,
|
||||
8.5A6.5,6.5,0,1,0,12,15,6.51,6.51,0,0,0,18.5,8.5Z"/></svg>
|
||||
|
After Width: | Height: | Size: 506 B |
@@ -43,7 +43,8 @@
|
||||
<inherits name="com.sap.sailing.gwt.ui.SourceAdminConsole"/>
|
||||
<inherits name="com.sap.sailing.gwt.regattaoverview.SourceRegattaOverview"/>
|
||||
<inherits name="com.sap.sailing.gwt.ui.SourceLeaderboard"/>
|
||||
<inherits name='com.sap.sse.gwt.CommonControlCSS'/>
|
||||
<inherits name="com.sap.sailing.gwt.ui.SourceRaceboard"/>
|
||||
<inherits name='com.sap.sse.gwt.CommonControlCSS'/>
|
||||
<inherits name='com.sap.sailing.gwt.settings.Settings'/>
|
||||
|
||||
<replace-with class="com.sap.sailing.gwt.home.shared.utils.dateformatter.CustomEventDatesFormatter">
|
||||
|
||||
+32
@@ -135,4 +135,36 @@ public class SimpleRaceMetadataDTO implements DTO, Comparable<SimpleRaceMetadata
|
||||
final int compareByRaceName = new NaturalComparator().compare(getRaceName(), o.getRaceName());
|
||||
return compareByRaceName != 0 ? compareByRaceName : Util.compareToWithNull(getStart(), o.getStart(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to check if this {@link SimpleRaceMetadataDTO race} has valid tracking data.
|
||||
*
|
||||
* @return <code>true</code> if the {@link #getTrackingState() tracking state} is
|
||||
* {@link RaceTrackingState#TRACKED_VALID_DATA}, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean hasValidTrackingData() {
|
||||
return getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to check if this {@link SimpleRaceMetadataDTO race} is already finished.
|
||||
*
|
||||
* @return <code>true</code> if the {@link #getViewState() view state} is {@link RaceViewState#FINISHED},
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isFinished() {
|
||||
return getViewState() == RaceViewState.FINISHED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to check if this {@link SimpleRaceMetadataDTO race} is currently running.
|
||||
*
|
||||
* @return <code>true</code> if the {@link #getViewState() view state} is {@link RaceViewState#RUNNING},
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return getViewState() == RaceViewState.RUNNING;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+2
-37
@@ -9,7 +9,6 @@ import com.google.gwt.cell.client.AbstractCell;
|
||||
import com.google.gwt.cell.client.Cell;
|
||||
import com.google.gwt.cell.client.TextCell;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Style.TextTransform;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.i18n.client.DateTimeFormat;
|
||||
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
|
||||
@@ -25,9 +24,6 @@ import com.google.gwt.user.cellview.client.SafeHtmlHeader;
|
||||
import com.sap.sailing.domain.common.InvertibleComparator;
|
||||
import com.sap.sailing.domain.common.SortingOrder;
|
||||
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
|
||||
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
|
||||
import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO;
|
||||
import com.sap.sailing.gwt.home.communication.event.RaceListRaceDTO;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO;
|
||||
@@ -35,11 +31,11 @@ import com.sap.sailing.gwt.home.communication.race.FlagStateDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.RaceProgressDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState;
|
||||
import com.sap.sailing.gwt.home.communication.race.wind.AbstractWindDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.wind.WindStatisticsDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.racelist.RaceListResources.LocalCss;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad.RaceviewerLaunchPadCell;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView;
|
||||
import com.sap.sailing.gwt.home.shared.utils.HomeSailingFlagsBuilder;
|
||||
import com.sap.sailing.gwt.regattaoverview.client.FlagsMeaningExplanator;
|
||||
@@ -49,16 +45,13 @@ import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
|
||||
import com.sap.sailing.gwt.ui.shared.util.NullSafeComparableComparator;
|
||||
import com.sap.sailing.gwt.ui.shared.util.NullSafeComparatorWrapper;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
|
||||
public class RaceListColumnFactory {
|
||||
|
||||
private static final LocalCss CSS = RaceListResources.INSTANCE.css();
|
||||
private static final MainCss MAIN_CSS = SharedResources.INSTANCE.mainCss();
|
||||
private static final StringMessages I18N = StringMessages.INSTANCE;
|
||||
private static final TextMessages I18N_UBI = TextMessages.INSTANCE;
|
||||
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
|
||||
|
||||
interface CellTemplates extends SafeHtmlTemplates {
|
||||
@@ -71,12 +64,6 @@ public class RaceListColumnFactory {
|
||||
@Template("<img style=\"{0}\" src=\"images/home/windkompass_nord.svg\"/>")
|
||||
SafeHtml windDirection(SafeStyles rotation);
|
||||
|
||||
@Template("<div style=\"{0}\">{1}</div>")
|
||||
SafeHtml raceNotTracked(SafeStyles styles, String text);
|
||||
|
||||
@Template("<a href=\"{2}\" class=\"{0}\" target=\"_blank\">{1}</a>")
|
||||
SafeHtml raceViewerLinkButton(String styleNames, String text, String link);
|
||||
|
||||
@Template("<img src=\"{3}\" class=\"{0}\" /><span class=\"{1}\">{4}</span><div class=\"{2}\" title=\"{5}\">{5}</div>")
|
||||
SafeHtml winner(String styleNamesFlag, String styleNamesSailId, String styleNamesText, SafeUri flagImageURL, String sailId, String name);
|
||||
|
||||
@@ -502,28 +489,6 @@ public class RaceListColumnFactory {
|
||||
}
|
||||
|
||||
public static <T extends RaceMetadataDTO<?>> SortableRaceListColumn<T, T> getRaceViewerButtonColumn(final EventView.Presenter presenter) {
|
||||
Cell<T> cell = new AbstractCell<T>() {
|
||||
private final String watchNowStyle = getButtonStyleNames(MAIN_CSS.buttonred());
|
||||
private final String analyseRaceStyle = getButtonStyleNames(MAIN_CSS.buttonprimary());
|
||||
|
||||
@Override
|
||||
public void render(Context context, T data, SafeHtmlBuilder sb) {
|
||||
if (data.getTrackingState() != RaceTrackingState.TRACKED_VALID_DATA) {
|
||||
SafeStylesBuilder styles = new SafeStylesBuilder().textTransform(TextTransform.UPPERCASE);
|
||||
styles.trustedColor("#666").trustedNameAndValue("font-size", "0.933333333333333rem").toSafeStyles();
|
||||
styles.trustedNameAndValue("padding", "0.714285714285714em 1.071428571428571em");
|
||||
sb.append(TEMPLATE.raceNotTracked(styles.toSafeStyles(), I18N_UBI.eventRegattaRaceNotTracked()));
|
||||
} else {
|
||||
String styleNames = data.getViewState() == RaceViewState.FINISHED ? analyseRaceStyle : watchNowStyle;
|
||||
String text = data.getViewState() == RaceViewState.FINISHED ? I18N.analyseRace() : I18N_UBI.watchNow();
|
||||
sb.append(TEMPLATE.raceViewerLinkButton(styleNames, text, presenter.getRaceViewerURL(data)));
|
||||
}
|
||||
}
|
||||
|
||||
private final String getButtonStyleNames(String buttonColor) {
|
||||
return Util.join(" ", MAIN_CSS.button(), MAIN_CSS.buttonstrong(), buttonColor, MAIN_CSS.buttonarrowrightwhite());
|
||||
}
|
||||
};
|
||||
InvertibleComparator<T> comparator = new InvertibleComparatorAdapter<T>() {
|
||||
@Override
|
||||
public int compare(T o1, T o2) {
|
||||
@@ -538,7 +503,7 @@ public class RaceListColumnFactory {
|
||||
return -o1.getTrackingState().compareTo(o2.getTrackingState());
|
||||
}
|
||||
};
|
||||
return new SortableRaceListColumn<T, T>("", cell, comparator) {
|
||||
return new SortableRaceListColumn<T, T>("", new RaceviewerLaunchPadCell<T>(presenter), comparator) {
|
||||
@Override
|
||||
public String getHeaderStyle() {
|
||||
return getStyleNamesString(CSS.raceslist_head_item(), CSS.raceslist_head_itembutton());
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
.raceviewerlaunchpad {
|
||||
font-size: 1rem;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
background: #008fcc;
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -moz-inline-box;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0;
|
||||
-moz-box-flex: 0;
|
||||
-ms-flex: 0;
|
||||
flex: 0;
|
||||
text-align: center;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
-moz-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
height: 2.666666666666667em;
|
||||
padding: 0 0.333333333333333em 0 1em;
|
||||
border-radius: 0.2em;
|
||||
position: relative;
|
||||
}
|
||||
.raceviewerlaunchpadwithname {
|
||||
padding: 0.333333333333333em 0.333333333333333em 0.666666666666667em 1em;
|
||||
height: 5.333333333333333em;
|
||||
margin: 0.666666666666667em 0 0 0.666666666666667em;
|
||||
vertical-align: top;
|
||||
}
|
||||
.raceviewerlaunchpad_wrapper {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: column;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-align: start;
|
||||
-webkit-align-items: flex-start;
|
||||
-moz-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.raceviewerlaunchpad_name {
|
||||
font-size: 1.466666666666667em;
|
||||
margin-bottom: 0.333333333333333em;
|
||||
}
|
||||
.raceviewerlaunchpad_date {
|
||||
font-size: 0.666666666666667em;
|
||||
}
|
||||
.raceviewerlaunchpad_cta {
|
||||
font-size: 0.666666666666667em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.raceviewerlaunchpad:hover {
|
||||
cursor: pointer;
|
||||
background: #0081b8;
|
||||
}
|
||||
.raceviewerlaunchpadlive {
|
||||
background: #e94a1b;
|
||||
}
|
||||
.raceviewerlaunchpadlive:hover {
|
||||
background: #d54115;
|
||||
}
|
||||
.raceviewerlaunchpadlive .raceviewerlaunchpad_content_item {
|
||||
color: #e94a1b;
|
||||
}
|
||||
.raceviewerlaunchpadlive .raceviewerlaunchpad_content_item:hover {
|
||||
background: #e94a1b;
|
||||
}
|
||||
.raceviewerlaunchpadlive .raceviewerlaunchpad_content_item_icon svg {
|
||||
fill: #e94a1b;
|
||||
}
|
||||
.raceviewerlaunchpad_icon {
|
||||
margin-left: 0.666666666666667em;
|
||||
width: 1.666666666666667em;
|
||||
height: 1.333333333333333em;
|
||||
}
|
||||
.raceviewerlaunchpad_icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: #fff;
|
||||
}
|
||||
.raceviewerlaunchpad_content {
|
||||
display: block;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
box-shadow: 0px 0px 0.666666666666667em 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
.raceviewerlaunchpad_content_item {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
-moz-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
height: 3em;
|
||||
padding: 0 1.333333333333333em 0 0.666666666666667em;
|
||||
background: #fff;
|
||||
color: #008fcc;
|
||||
font-weight: normal;
|
||||
}
|
||||
.raceviewerlaunchpad_content_item:hover {
|
||||
background: #008fcc;
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.raceviewerlaunchpad_content_item:hover .raceviewerlaunchpad_content_item_icon svg {
|
||||
fill: #fff;
|
||||
}
|
||||
.raceviewerlaunchpad_content_item_icon {
|
||||
margin-right: 1em;
|
||||
}
|
||||
.raceviewerlaunchpad_content_item_icon svg {
|
||||
width: 1.333333333333333em;
|
||||
height: 1.666666666666667em;
|
||||
fill: #008fcc;
|
||||
stroke: none;
|
||||
}
|
||||
.raceviewerlaunchpad_content_item_title {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.raceviewerlaunchpad_not_tracked {
|
||||
text-transform: uppercase;
|
||||
font-size: 0.933333333333333rem;
|
||||
padding: 0.714285714285714em 1.071428571428571em;
|
||||
color: #666;
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardModes;
|
||||
|
||||
public abstract class RaceviewerLaunchPad extends Composite {
|
||||
|
||||
private static RaceviewerLaunchPadUiBinder uiBinder = GWT.create(RaceviewerLaunchPadUiBinder.class);
|
||||
|
||||
interface RaceviewerLaunchPadUiBinder extends UiBinder<Widget, RaceviewerLaunchPad> {
|
||||
}
|
||||
|
||||
@UiField RaceviewerLaunchPadResources local_res;
|
||||
@UiField DivElement itemContainerUi;
|
||||
private final PopupPanel parent;
|
||||
|
||||
public RaceviewerLaunchPad(SimpleRaceMetadataDTO data, final PopupPanel parent) {
|
||||
this.parent = parent;
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
local_res.css().ensureInjected();
|
||||
if (!data.isFinished()) {
|
||||
addStyleName(local_res.css().raceviewerlaunchpadlive());
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.WATCH_LIVE);
|
||||
} else {
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.REPLAY);
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.RACE_ANALYSIS);
|
||||
}
|
||||
if (data.isRunning() || data.isFinished()) {
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.START_ANALYSIS);
|
||||
}
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.WINNING_LANES);
|
||||
sinkEvents(Event.ONCLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(final Event event) {
|
||||
if (event.getTypeInt() == Event.ONCLICK) {
|
||||
parent.hide();
|
||||
}
|
||||
super.onBrowserEvent(event);
|
||||
}
|
||||
|
||||
private void addItem(SimpleRaceMetadataDTO data, RaceviewerLaunchPadMenuItem item) {
|
||||
String raceViewerUrl = getRaceViewerURL(data, item.raceBoardMode);
|
||||
itemContainerUi.appendChild(new RaceviewerLaunchPadItem(item.label, item.icon, raceViewerUrl).getElement());
|
||||
}
|
||||
|
||||
private enum RaceviewerLaunchPadMenuItem {
|
||||
REPLAY(StringMessages.INSTANCE.replay(), "launch-replay", RaceBoardModes.PLAYER.name()),
|
||||
WATCH_LIVE(StringMessages.INSTANCE.watchLive(), "launch-play", RaceBoardModes.PLAYER.name()),
|
||||
RACE_ANALYSIS(StringMessages.INSTANCE.raceAnalysis(), "launch-loupe", RaceBoardModes.FULL_ANALYSIS.name()),
|
||||
START_ANALYSIS(StringMessages.INSTANCE.startAnalysis(), "launch-start", RaceBoardModes.START_ANALYSIS.name()),
|
||||
WINNING_LANES(StringMessages.INSTANCE.winningLanes(), "launch-winning-lanes", RaceBoardModes.WINNING_LANES.name());
|
||||
|
||||
private String label, icon, raceBoardMode;
|
||||
|
||||
private RaceviewerLaunchPadMenuItem(String label, String iconKey, String raceBoardMode) {
|
||||
this.label = label;
|
||||
this.icon = "<svg><use xlink:href=\"#" + iconKey + "\"></use></svg>";
|
||||
this.raceBoardMode = raceBoardMode;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getRaceViewerURL(SimpleRaceMetadataDTO data, String raceBoardMode);
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<!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"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad.RaceviewerLaunchPadResources" />
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.raceviewerlaunchpad_content}">
|
||||
<svg style="display: none;">
|
||||
<symbol id="launch-winning-lanes" viewBox="0 0 16.15 21.95">
|
||||
<title>Winning Lanes icon</title>
|
||||
<path d="M4.59,21.94L0,11.12,8.23,0l7.54,8.65ZM1.14,11.25L4.88,20,14.46,8.66,8.3,1.59ZM8.4,21.95L0.62,13l10.7-12.5,4.83,11.1ZM1.94,13l6.4,7.35L15,11.48l-4-9.1Z"></path>
|
||||
</symbol>
|
||||
<symbol id="launch-play" viewBox="0 0 20 20">
|
||||
<title>Play icon</title>
|
||||
<path d="M10,2a8,8,0,1,1-8,8,8,8,0,0,1,8-8m0-2A10,10,0,1,0,20,10,10,10,0,0,0,10,0h0ZM9.71,10l0.08,0L9.71,10V10m-2-3.43v7l3.07-1.74L13.86,10,10.78,8.26,7.71,6.52h0Z"></path>
|
||||
</symbol>
|
||||
<symbol id="launch-replay" viewBox="0 0 20.35 25.44">
|
||||
<title>Replay icon</title>
|
||||
<path d="M18.18,14.72a8,8,0,1,1-16,0h2a6,6,0,1,0,6-6v4l-5-5,5-5v4A8,8,0,0,1,18.18,14.72Z"></path>
|
||||
</symbol>
|
||||
<symbol id="launch-loupe" viewBox="0 0 24.85 20.35">
|
||||
<title>Loupe icon</title>
|
||||
<path d="M6.58,7.58H16v2H6.61A5.3,5.3,0,0,1,6.58,7.58Zm3.42-3H8.15a5.51,5.51,0,0,0-1.3,2H10v-2Zm-1.68,8H13v-2H6.91A5.52,5.52,0,0,0,8.32,12.58ZM2.5,8.5c0-.31,0-0.62,0-0.92H0v2H2.57A9.52,9.52,0,0,1,2.5,8.5Zm0.24,2.08H0v2H3.43A9.41,9.41,0,0,1,2.74,10.58Zm0.62-6H0v2H2.7A9.4,9.4,0,0,1,3.36,4.58ZM23.44,20.35l-5.65-5.65a8.45,8.45,0,1,1,1.3-1.53l5.76,5.76ZM18.5,8.5A6.5,6.5,0,1,0,12,15,6.51,6.51,0,0,0,18.5,8.5Z"></path>
|
||||
</symbol>
|
||||
<symbol id="launch-start" viewBox="0 0 21 19">
|
||||
<title>Start icon</title>
|
||||
<path d="M21,0V19H20V9.32c-2,.87-4.74,2.14-10.31.43C4.37,8.12,2,8.71,1,9.25V19H0V0H1V1.14C2,0.6,4.37,0,9.69,1.64,15.26,3.35,18,2.07,20,1.21V0h1ZM3.89,5.69a0.83,0.83,0,0,0,.39.41A1.66,1.66,0,0,0,5,6.28,1.32,1.32,0,0,0,5.9,6.06a0.92,0.92,0,0,0,.38-0.68A0.73,0.73,0,0,0,6.1,4.82a2.59,2.59,0,0,0-.66-0.43A2.13,2.13,0,0,1,5,4.11a0.28,0.28,0,0,1-.09-0.23A0.29,0.29,0,0,1,5,3.65a0.6,0.6,0,0,1,.39-0.06,0.61,0.61,0,0,1,.4.15A0.5,0.5,0,0,1,6,4.09l0.62,0A1,1,0,0,0,6.31,3.4a1.27,1.27,0,0,0-.83-0.32,1.19,1.19,0,0,0-.84.2,0.85,0.85,0,0,0-.34.63,0.78,0.78,0,0,0,.07.4,0.77,0.77,0,0,0,.24.29,4.31,4.31,0,0,0,.51.3,2.25,2.25,0,0,1,.43.26,0.3,0.3,0,0,1,.1.24,0.34,0.34,0,0,1-.16.26A0.73,0.73,0,0,1,5,5.75a0.66,0.66,0,0,1-.51-0.21,0.68,0.68,0,0,1-.07-0.4l-0.61,0A1.15,1.15,0,0,0,3.89,5.69ZM8.75,4.26l0.88,0.2L9.86,4l-2.4-.55-0.22.49,0.89,0.2L7,6.53,7.65,6.67ZM10.58,7.5l0.59,0.17,0.39-3.14-0.69-.2L8.3,6.83,8.93,7l0.55-.56,1.19,0.35ZM9.85,6l1.08-1L10.75,6.29Zm3,0.63,0.26,0a0.61,0.61,0,0,1,.31.1,1,1,0,0,1,.23.44q0.17,0.59.23,0.86L14.6,8.16a7.82,7.82,0,0,0-.35-1.09A1.27,1.27,0,0,0,14,6.76a1.14,1.14,0,0,0,.76-0.23,0.93,0.93,0,0,0,.31-0.62,0.88,0.88,0,0,0-.07-0.49,0.64,0.64,0,0,0-.29-0.31A1.66,1.66,0,0,0,14.22,5L12.84,4.8l-1,3L12.46,7.9Zm0.43-1.27L14,5.47a0.84,0.84,0,0,1,.36.1,0.28,0.28,0,0,1,.11.27,0.46,0.46,0,0,1-.13.26,0.55,0.55,0,0,1-.29.16,2.39,2.39,0,0,1-.69,0L13,6.2Zm3.5,0,0.9-.11,0-.53L15.31,5l0,0.53,0.91-.11L16,8.07,16.59,8ZM20,18H19v1h1V18Zm-2,0H17v1h1V18Zm-2,0H15v1h1V18Zm-2,0H13v1h1V18Zm-2,0H11v1h1V18Zm-2,0H9v1h1V18ZM8,18H7v1H8V18ZM6,18H5v1H6V18ZM4,18H3v1H4V18ZM2,18H1v1H2V18Z"></path>
|
||||
</symbol>
|
||||
</svg>
|
||||
<div ui:field="itemContainerUi">
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.cell.client.AbstractCell;
|
||||
import com.google.gwt.cell.client.ValueUpdater;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.BrowserEvents;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.NativeEvent;
|
||||
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
|
||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
|
||||
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
|
||||
import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView.Presenter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RaceviewerLaunchPadCell<T extends RaceMetadataDTO<?>> extends AbstractCell<T> {
|
||||
|
||||
interface CellTemplates extends SafeHtmlTemplates {
|
||||
@Template("<div class=\"{0}\">{1}</div>")
|
||||
SafeHtml raceNotTracked(String styleNames, String text);
|
||||
|
||||
@Template("<div class=\"{0}\"><div>{2}</div><div class=\"{1}\"><img src=\"images/home/launch-loupe.svg\"/></div>")
|
||||
SafeHtml raceviewerLaunchPad(String styleNames, String iconStyleNames, String text);
|
||||
}
|
||||
|
||||
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
|
||||
private static final TextMessages I18N_UBI = TextMessages.INSTANCE;
|
||||
private static final StringMessages I18N = StringMessages.INSTANCE;
|
||||
|
||||
private final RaceviewerLaunchPadResources local_res = RaceviewerLaunchPadResources.INSTANCE;
|
||||
private final String notTrackedStyleNames = local_res.css().raceviewerlaunchpad_not_tracked();
|
||||
private final String analyzeStyleNames = local_res.css().raceviewerlaunchpad();
|
||||
private final String liveStyleNames = Util.join(" ", analyzeStyleNames, local_res.css().raceviewerlaunchpadlive());
|
||||
private final String iconStyleNames = local_res.css().raceviewerlaunchpad_icon();
|
||||
|
||||
private final EventView.Presenter presenter;
|
||||
private final PopupPanel panel = new PopupPanel(true, false);
|
||||
|
||||
public RaceviewerLaunchPadCell(Presenter presenter) {
|
||||
super(BrowserEvents.CLICK);
|
||||
local_res.css().ensureInjected();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(Context context, final Element parent, T data, NativeEvent event,
|
||||
ValueUpdater<T> valueUpdater) {
|
||||
if (data.hasValidTrackingData() && BrowserEvents.CLICK.equals(event.getType())
|
||||
&& parent.getFirstChildElement().isOrHasChild(Element.as(event.getEventTarget()))) {
|
||||
panel.setWidget(new RaceviewerLaunchPad(data, panel) {
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO data, String mode) {
|
||||
return presenter.getRaceViewerURL(data, mode);
|
||||
}
|
||||
});
|
||||
panel.setPopupPositionAndShow(new PositionCallback() {
|
||||
@Override
|
||||
public void setPosition(int offsetWidth, int offsetHeight) {
|
||||
int alignBottom = parent.getAbsoluteTop() + parent.getOffsetHeight() - offsetHeight;
|
||||
int top = (alignBottom - Window.getScrollTop() < 0 ? parent.getAbsoluteTop() - 1 : alignBottom + 1);
|
||||
panel.setPopupPosition(parent.getAbsoluteRight() + 1 - offsetWidth, top);
|
||||
panel.getElement().scrollIntoView();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
super.onBrowserEvent(context, parent, data, event, valueUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Context context, T data, SafeHtmlBuilder sb) {
|
||||
if (data.hasValidTrackingData()) {
|
||||
String styleNames = data.isFinished() ? analyzeStyleNames : liveStyleNames;
|
||||
sb.append(TEMPLATE.raceviewerLaunchPad(styleNames, iconStyleNames, I18N.raceDetailsToShow()));
|
||||
} else {
|
||||
sb.append(TEMPLATE.raceNotTracked(notTrackedStyleNames, I18N_UBI.eventRegattaRaceNotTracked()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.UIObject;
|
||||
|
||||
class RaceviewerLaunchPadItem extends UIObject {
|
||||
|
||||
private static RaceviewerLaunchPadItemUiBinder uiBinder = GWT.create(RaceviewerLaunchPadItemUiBinder.class);
|
||||
|
||||
interface RaceviewerLaunchPadItemUiBinder extends UiBinder<AnchorElement, RaceviewerLaunchPadItem> {
|
||||
}
|
||||
|
||||
@UiField DivElement itemLabelUi;
|
||||
@UiField DivElement itemIconContainerUi;
|
||||
private final AnchorElement anchorUi;
|
||||
|
||||
RaceviewerLaunchPadItem(String label, String icon, String raceViewerUrl) {
|
||||
setElement(anchorUi = uiBinder.createAndBindUi(this));
|
||||
anchorUi.setHref(raceViewerUrl);
|
||||
itemLabelUi.setInnerText(label);
|
||||
itemIconContainerUi.setInnerHTML(icon);
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<!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.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad.RaceviewerLaunchPadResources" />
|
||||
<a target="_blank" class="{local_res.css.raceviewerlaunchpad_content_item}">
|
||||
<div class="{local_res.css.raceviewerlaunchpad_content_item_icon}" ui:field="itemIconContainerUi">
|
||||
</div>
|
||||
<div class="{local_res.css.raceviewerlaunchpad_content_item_title}" ui:field="itemLabelUi">
|
||||
</div>
|
||||
</a>
|
||||
</ui:UiBinder>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
|
||||
public interface RaceviewerLaunchPadResources extends ClientBundle {
|
||||
public static final RaceviewerLaunchPadResources INSTANCE = GWT.create(RaceviewerLaunchPadResources.class);
|
||||
|
||||
@Source("RaceviewerLaunchPad.gss")
|
||||
LocalCss css();
|
||||
|
||||
public interface LocalCss extends CssResource {
|
||||
String raceviewerlaunchpad();
|
||||
String raceviewerlaunchpadwithname();
|
||||
String raceviewerlaunchpad_wrapper();
|
||||
String raceviewerlaunchpad_name();
|
||||
String raceviewerlaunchpad_date();
|
||||
String raceviewerlaunchpad_cta();
|
||||
String raceviewerlaunchpadlive();
|
||||
String raceviewerlaunchpad_content_item();
|
||||
String raceviewerlaunchpad_content_item_icon();
|
||||
String raceviewerlaunchpad_icon();
|
||||
String raceviewerlaunchpad_content();
|
||||
String raceviewerlaunchpad_content_item_title();
|
||||
String raceviewerlaunchpad_not_tracked();
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -106,10 +106,11 @@
|
||||
-moz-transition: background 0.2s;
|
||||
transition: background 0.2s;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
/* text-align: center; */
|
||||
color: #fff;
|
||||
padding: 0.233333333333333em 0.233333333333333em;
|
||||
vertical-align: top;
|
||||
cursor: pointer;
|
||||
}
|
||||
@media (min-width: 45em) {
|
||||
.fleet_races_race {
|
||||
@@ -136,15 +137,17 @@
|
||||
.fleet_races_race_name {
|
||||
font-size: 1.166666666666667em;
|
||||
font-weight: 700;
|
||||
position: relative;
|
||||
}
|
||||
.fleet_races_race_name:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0.466666666666667em;
|
||||
height: 0.466666666666667em;
|
||||
background: url("images/home/skip-forward.png") no-repeat center center;
|
||||
margin: 0 0 0.033333333333333em 0.133333333333333em;
|
||||
width: 1em;
|
||||
height: 0.866666666666667em;
|
||||
background: url("images/home/launch-loupe.svg") no-repeat center center;
|
||||
font-size: 1.466666666666667em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.fleet_races_race_info {
|
||||
width: 100%;
|
||||
|
||||
+9
-6
@@ -6,9 +6,12 @@ import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.Style.Display;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionFleet;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
@@ -16,14 +19,14 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
|
||||
|
||||
private static RegattaCompetitionFleetUiBinder uiBinder = GWT.create(RegattaCompetitionFleetUiBinder.class);
|
||||
|
||||
interface RegattaCompetitionFleetUiBinder extends UiBinder<Element, RegattaCompetitionFleet> {
|
||||
interface RegattaCompetitionFleetUiBinder extends UiBinder<Widget, RegattaCompetitionFleet> {
|
||||
}
|
||||
|
||||
@UiField RegattaCompetitionResources local_res;
|
||||
@UiField DivElement fleetCornerUi;
|
||||
@UiField DivElement fleetNameUi;
|
||||
@UiField DivElement competitorCountUi;
|
||||
@UiField DivElement racesContainerUi;
|
||||
@UiField FlowPanel racesContainerUi;
|
||||
|
||||
public RegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet) {
|
||||
super(fleet);
|
||||
@@ -32,9 +35,9 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, String raceViewerUrl) {
|
||||
RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, raceViewerUrl);
|
||||
racesContainerUi.appendChild(raceView.getElement());
|
||||
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
|
||||
RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, presenter);
|
||||
racesContainerUi.add(raceView);
|
||||
return raceView;
|
||||
}
|
||||
|
||||
@@ -48,7 +51,7 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Element getMainUiElement() {
|
||||
protected Widget getMainUiElement() {
|
||||
return uiBinder.createAndBindUi(this);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -4,12 +4,12 @@
|
||||
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials">
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.regattacompetition.RegattaCompetitionResources" />
|
||||
<div class="{local_res.css.fleet}">
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.fleet}">
|
||||
<div class="{local_res.css.fleet_corner}" ui:field="fleetCornerUi"></div>
|
||||
<div class="{local_res.css.fleet_details}">
|
||||
<div class="{local_res.css.fleet_details_name}" ui:field="fleetNameUi"></div>
|
||||
<div class="{local_res.css.fleet_details_competitors}" ui:field="competitorCountUi"></div>
|
||||
</div>
|
||||
<div class="{local_res.css.fleet_races}" ui:field="racesContainerUi"></div>
|
||||
</div>
|
||||
<g:FlowPanel addStyleNames="{local_res.css.fleet_races}" ui:field="racesContainerUi"/>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+5
-5
@@ -1,19 +1,19 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.regattacompetition;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionFleetRace;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter;
|
||||
|
||||
public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleetRace {
|
||||
|
||||
private static RegattaCompetitionFleetRaceUiBinder uiBinder = GWT.create(RegattaCompetitionFleetRaceUiBinder.class);
|
||||
|
||||
interface RegattaCompetitionFleetRaceUiBinder extends UiBinder<AnchorElement, RegattaCompetitionFleetRace> {
|
||||
interface RegattaCompetitionFleetRaceUiBinder extends UiBinder<Element, RegattaCompetitionFleetRace> {
|
||||
}
|
||||
|
||||
@UiField RegattaCompetitionResources local_res;
|
||||
@@ -21,8 +21,8 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
|
||||
@UiField DivElement raceStateUi;
|
||||
@UiField DivElement raceDateUi;
|
||||
|
||||
public RegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, String raceViewerUrl) {
|
||||
super(race, raceViewerUrl);
|
||||
public RegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
|
||||
super(race, presenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,7 +31,7 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnchorElement getMainUiElement() {
|
||||
protected Element getMainUiElement() {
|
||||
return uiBinder.createAndBindUi(this);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -4,11 +4,11 @@
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.regattacompetition.RegattaCompetitionResources" />
|
||||
<a class="{local_res.css.fleet_races_race}" target="_blank">
|
||||
<div class="{local_res.css.fleet_races_race}">
|
||||
<div class="{local_res.css.fleet_races_race_name}" ui:field="raceNameUi"></div>
|
||||
<div class="{local_res.css.fleet_races_race_info} {res.mediaCss.hideonsmall}">
|
||||
<div class="{local_res.css.fleet_races_race_state}" ui:field="raceStateUi"></div>
|
||||
<div class="{local_res.css.fleet_races_race_date}" ui:field="raceDateUi"></div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</ui:UiBinder>
|
||||
+10
@@ -10,6 +10,7 @@ import com.google.gwt.place.shared.Place;
|
||||
import com.google.gwt.safehtml.shared.SafeUri;
|
||||
import com.google.gwt.safehtml.shared.UriUtils;
|
||||
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.gwt.common.client.controls.tabbar.TabView;
|
||||
import com.sap.sailing.gwt.home.communication.SailingDispatchSystem;
|
||||
@@ -150,6 +151,15 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
|
||||
raceMetadata.getRegattaAndRaceIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode) {
|
||||
RaceIdentifier raceIdentifier = raceMetadata.getRegattaAndRaceIdentifier();
|
||||
Map<String, String> params = createRaceBoardLinkParameters(raceMetadata.getLeaderboardName(),
|
||||
raceMetadata.getLeaderboardGroupName(), raceIdentifier.getRegattaName(), raceIdentifier.getRaceName());
|
||||
params.put("mode", mode);
|
||||
return EntryPointLinkFactory.createRaceBoardLink(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRaceViewerURL(String leaderboardName, String leaderboardGroupName, RegattaAndRaceIdentifier raceIdentifier) {
|
||||
return EntryPointLinkFactory.createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName,
|
||||
|
||||
+2
@@ -70,6 +70,8 @@ public interface EventView<PLACE extends AbstractEventPlace, PRES extends EventV
|
||||
EventViewDTO getEventDTO();
|
||||
|
||||
String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata);
|
||||
|
||||
String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode);
|
||||
|
||||
String getRaceViewerURL(String leaderboardName, String leaderboardGroupName,
|
||||
RegattaAndRaceIdentifier raceIdentifier);
|
||||
|
||||
+2
-2
@@ -248,8 +248,8 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView<Reg
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata) {
|
||||
return currentPresenter.getRaceViewerURL(raceMetadata);
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode) {
|
||||
return currentPresenter.getRaceViewerURL(raceMetadata, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-7
@@ -47,6 +47,7 @@
|
||||
}
|
||||
.regattacompetition_phase_fleetfullwidth .regattacompetition_phase_fleet_race {
|
||||
height: 3.466666666666666666em;
|
||||
text-align: center;
|
||||
}
|
||||
.regattacompetition_phase_fleetfullwidth .regattacompetition_phase_fleet_race_title {
|
||||
position: absolute;
|
||||
@@ -67,6 +68,7 @@
|
||||
/* } */
|
||||
.regattacompetition_phase_fleetfullwidth .regattacompetition_phase_fleet_race_arrow {
|
||||
display: block;
|
||||
width: 1.6666666667em;
|
||||
}
|
||||
.regattacompetition_phase_fleet_title {
|
||||
font-size: 1.066666666666667em;
|
||||
@@ -79,8 +81,8 @@
|
||||
position: relative;
|
||||
background: #008fcc;
|
||||
margin-bottom: 0.666666666666667em;
|
||||
text-align: center;
|
||||
padding: .8em 0;
|
||||
/* text-align: center; */
|
||||
padding: .8em .4em;
|
||||
border-radius: 0.333333333333333em;
|
||||
color: #fff;
|
||||
/* color: #f6f9fc; alternative white*/
|
||||
@@ -93,7 +95,7 @@
|
||||
color: #008fcc;
|
||||
background-color: #fff;
|
||||
border: 0.133333333333333em solid #008fcc;
|
||||
padding: .666666666666667em 0;
|
||||
padding: .666666666666667em 0.266666666666667em;
|
||||
cursor: default;
|
||||
}
|
||||
.regattacompetition_phase_fleet_raceuntracked .regattacompetition_phase_fleet_race_title:after {
|
||||
@@ -125,13 +127,17 @@
|
||||
.regattacompetition_phase_fleet_race_title {
|
||||
font-size: 1.222222222222222em;
|
||||
font-weight: 700;
|
||||
position: relative;
|
||||
}
|
||||
.regattacompetition_phase_fleet_race_title:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0.75em;
|
||||
height: 0.75em;
|
||||
background: url("images/home/skip-forward.png") no-repeat center center;
|
||||
width: 1.666666666666667em;
|
||||
height: 1.1em;
|
||||
background: url("images/home/launch-loupe.svg") no-repeat center center;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0.133333333333333em;
|
||||
}
|
||||
.regattacompetition_phase_fleet_race_subtitle {
|
||||
font-size: 0.7em;
|
||||
@@ -161,4 +167,3 @@
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
+11
-8
@@ -6,38 +6,41 @@ import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionFleet;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView;
|
||||
|
||||
public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
|
||||
|
||||
private static RegattaCompetitionFleetUiBinder uiBinder = GWT.create(RegattaCompetitionFleetUiBinder.class);
|
||||
|
||||
interface RegattaCompetitionFleetUiBinder extends UiBinder<Element, RegattaCompetitionFleet> {
|
||||
interface RegattaCompetitionFleetUiBinder extends UiBinder<Widget, RegattaCompetitionFleet> {
|
||||
}
|
||||
|
||||
@UiField RegattaCompetitionResources local_res;
|
||||
@UiField DivElement fleetCornerUi;
|
||||
@UiField DivElement fleetNameUi;
|
||||
@UiField DivElement raceContainerUi;
|
||||
@UiField FlowPanel raceContainerUi;
|
||||
|
||||
public RegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet) {
|
||||
super(fleet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, String raceViewerUrl) {
|
||||
RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, raceViewerUrl);
|
||||
raceContainerUi.appendChild(raceView.getElement());
|
||||
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
|
||||
RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, presenter);
|
||||
raceContainerUi.add(raceView);
|
||||
return raceView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNumberOfFleetsInSeries(int fleetCount) {
|
||||
raceContainerUi.getStyle().setWidth(100.0 / fleetCount, Unit.PCT);
|
||||
setStyleName(raceContainerUi, local_res.css().regattacompetition_phase_fleetfullwidth(), fleetCount < 2);
|
||||
getElement().getStyle().setWidth(100.0 / fleetCount, Unit.PCT);
|
||||
setStyleName(local_res.css().regattacompetition_phase_fleetfullwidth(), fleetCount < 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,7 +50,7 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Element getMainUiElement() {
|
||||
protected Widget getMainUiElement() {
|
||||
return uiBinder.createAndBindUi(this);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -4,8 +4,9 @@
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet}" ui:field="raceContainerUi">
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.regattacompetition_phase_fleet}">
|
||||
<div class="{res.mainCss.fleetcorner}" ui:field="fleetCornerUi"></div>
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_title}" ui:field="fleetNameUi"></div>
|
||||
</div>
|
||||
<g:FlowPanel ui:field="raceContainerUi"/>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+5
-5
@@ -1,7 +1,6 @@
|
||||
package com.sap.sailing.gwt.home.mobile.partials.regattacompetition;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.Style.Display;
|
||||
@@ -11,12 +10,13 @@ import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState;
|
||||
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionFleetRace;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter;
|
||||
|
||||
public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleetRace {
|
||||
|
||||
private static RegattaCompetitionFleetRaceUiBinder uiBinder = GWT.create(RegattaCompetitionFleetRaceUiBinder.class);
|
||||
|
||||
interface RegattaCompetitionFleetRaceUiBinder extends UiBinder<AnchorElement, RegattaCompetitionFleetRace> {
|
||||
interface RegattaCompetitionFleetRaceUiBinder extends UiBinder<Element, RegattaCompetitionFleetRace> {
|
||||
}
|
||||
|
||||
@UiField RegattaCompetitionResources local_res;
|
||||
@@ -24,8 +24,8 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
|
||||
@UiField DivElement raceStateUi;
|
||||
@UiField DivElement raceDateUi;
|
||||
|
||||
public RegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, String raceViewerUrl) {
|
||||
super(race, raceViewerUrl);
|
||||
public RegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
|
||||
super(race, presenter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,7 +34,7 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnchorElement getMainUiElement() {
|
||||
protected Element getMainUiElement() {
|
||||
return uiBinder.createAndBindUi(this);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -4,12 +4,12 @@
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
|
||||
<a class="{local_res.css.regattacompetition_phase_fleet_race}" style="display:block; text-decoration:none;">
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_race}" style="display:block; text-decoration:none;">
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_race_title}" ui:field="raceNameUi"></div>
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_race_subtitle}">
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_race_state}" ui:field="raceStateUi"></div>
|
||||
<div class="{local_res.css.regattacompetition_phase_fleet_race_date}" ui:field="raceDateUi"></div>
|
||||
</div>
|
||||
<img src="images/home/skip-forward.png" class="{local_res.css.regattacompetition_phase_fleet_race_arrow}"></img>
|
||||
</a>
|
||||
<img src="images/home/launch-loupe.svg" class="{local_res.css.regattacompetition_phase_fleet_race_arrow}"></img>
|
||||
</div>
|
||||
</ui:UiBinder>
|
||||
+10
@@ -12,6 +12,7 @@ import java.util.UUID;
|
||||
import com.google.gwt.activity.shared.AbstractActivity;
|
||||
import com.google.gwt.event.shared.EventBus;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.gwt.home.communication.SailingDispatchSystem;
|
||||
import com.sap.sailing.gwt.home.communication.event.news.LeaderboardNewsEntryDTO;
|
||||
@@ -241,6 +242,15 @@ public abstract class AbstractEventActivity<PLACE extends AbstractEventPlace> ex
|
||||
raceMetadata.getRegattaAndRaceIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode) {
|
||||
RaceIdentifier raceIdentifier = raceMetadata.getRegattaAndRaceIdentifier();
|
||||
Map<String, String> params = createRaceBoardLinkParameters(raceMetadata.getLeaderboardName(),
|
||||
raceMetadata.getLeaderboardGroupName(), raceIdentifier.getRegattaName(), raceIdentifier.getRaceName());
|
||||
params.put("mode", mode);
|
||||
return EntryPointLinkFactory.createRaceBoardLink(params);
|
||||
}
|
||||
|
||||
private String getRaceViewerURL(String leaderboardName, String leaderboardGroupName, RegattaAndRaceIdentifier raceIdentifier) {
|
||||
return EntryPointLinkFactory.createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName, leaderboardGroupName,
|
||||
raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()));
|
||||
|
||||
+2
@@ -48,6 +48,8 @@ public interface EventViewBase extends IsWidget {
|
||||
PlaceNavigation<?> getMediaPageNavigation();
|
||||
|
||||
String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata);
|
||||
|
||||
String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode);
|
||||
|
||||
String getRegattaId();
|
||||
|
||||
|
||||
+3
-2
@@ -61,8 +61,9 @@ public class RacesViewImpl extends AbstractEventView<RacesView.Presenter> implem
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata) {
|
||||
return ExperimentalFeatures.ENABLE_RACE_VIEWER_LINK_ON_MOBILE ? currentPresenter.getRaceViewerURL(raceMetadata) : null;
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode) {
|
||||
return ExperimentalFeatures.ENABLE_RACE_VIEWER_LINK_ON_MOBILE
|
||||
? currentPresenter.getRaceViewerURL(raceMetadata, mode) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.gwt.home.shared.partials.regattacompetition;
|
||||
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO;
|
||||
@@ -8,10 +9,10 @@ import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompet
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
|
||||
public abstract class AbstractRegattaCompetitionFleet extends Widget implements RegattaCompetitionFleetView {
|
||||
public abstract class AbstractRegattaCompetitionFleet extends Composite implements RegattaCompetitionFleetView {
|
||||
|
||||
protected AbstractRegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet) {
|
||||
setElement(getMainUiElement());
|
||||
initWidget(getMainUiElement());
|
||||
getFleetNameUiElement().setInnerText(fleet.getFleet().getFleetName());
|
||||
getFleetCornerUiElement().getStyle().setProperty("borderTopColor", fleet.getFleet().getFleetColor());
|
||||
if (fleet.getFleet().isDefaultFleet()) {
|
||||
@@ -33,7 +34,7 @@ public abstract class AbstractRegattaCompetitionFleet extends Widget implements
|
||||
|
||||
protected abstract void onDefaultFleetName();
|
||||
|
||||
protected abstract Element getMainUiElement();
|
||||
protected abstract Widget getMainUiElement();
|
||||
|
||||
protected abstract Element getFleetNameUiElement();
|
||||
|
||||
|
||||
+52
-15
@@ -6,48 +6,85 @@ import static com.sap.sse.common.impl.MillisecondsTimePoint.now;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.text.client.DateTimeFormatRenderer;
|
||||
import com.google.gwt.user.client.ui.UIObject;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.common.client.DateUtil;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad.RaceviewerLaunchPad;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
public abstract class AbstractRegattaCompetitionFleetRace extends UIObject implements RegattaCompetitionRaceView {
|
||||
public abstract class AbstractRegattaCompetitionFleetRace extends Widget implements RegattaCompetitionRaceView {
|
||||
|
||||
private static final StringMessages I18N = StringMessages.INSTANCE;
|
||||
protected final AnchorElement anchorUiElement;
|
||||
protected final Element mainElement;
|
||||
private final SimpleRaceMetadataDTO race;
|
||||
private final RegattaCompetitionPresenter presenter;
|
||||
private final PopupPanel panel = new PopupPanel(true, false);
|
||||
|
||||
protected AbstractRegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, String raceViewerUrl) {
|
||||
this.anchorUiElement = getMainUiElement();
|
||||
if (raceViewerUrl != null) {
|
||||
anchorUiElement.setTarget("_blank");
|
||||
anchorUiElement.setHref(raceViewerUrl);
|
||||
}
|
||||
protected AbstractRegattaCompetitionFleetRace(final SimpleRaceMetadataDTO race,
|
||||
RegattaCompetitionPresenter presenter) {
|
||||
this.race = race;
|
||||
this.presenter = presenter;
|
||||
this.mainElement = getMainUiElement();
|
||||
setupRaceState(race.getTrackingState(), race.getViewState());
|
||||
getRaceNameUiElement().setInnerText(race.getRaceName());
|
||||
setupRaceStart(race.getStart());
|
||||
setElement(anchorUiElement);
|
||||
setElement(mainElement);
|
||||
if (race.hasValidTrackingData()) {
|
||||
sinkEvents(Event.ONCLICK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(Event event) {
|
||||
if (race.hasValidTrackingData() && event.getTypeInt() == Event.ONCLICK) {
|
||||
this.getElement().scrollIntoView();
|
||||
panel.setWidget(new RaceviewerLaunchPad(race, panel) {
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO data, String mode) {
|
||||
return presenter.getRaceViewerURL(data, mode);
|
||||
}
|
||||
});
|
||||
panel.setVisible(false);
|
||||
panel.show();
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
Widget button = AbstractRegattaCompetitionFleetRace.this, panelContent = panel.getWidget();
|
||||
int alignRight = button.getAbsoluteLeft() + button.getOffsetWidth() - panelContent.getOffsetWidth();
|
||||
int left = (alignRight - Window.getScrollLeft() < 0 ? button.getAbsoluteLeft() - 1 : alignRight + 1);
|
||||
int alignBottom = button.getAbsoluteTop() + button.getOffsetHeight() - panelContent.getOffsetHeight();
|
||||
int top = (alignBottom - Window.getScrollTop() < 0 ? button.getAbsoluteTop() - 1 : alignBottom + 1);
|
||||
panel.setPopupPosition(left, top);
|
||||
panel.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRaceState(RaceTrackingState trackingState, RaceViewState viewState) {
|
||||
// boolean isUntrackedRace = trackingState != RaceTrackingState.TRACKED_VALID_DATA;
|
||||
boolean isUntrackedRace = isUntrackedRace(trackingState);
|
||||
if (viewState == RaceViewState.RUNNING) {
|
||||
anchorUiElement.addClassName(getRaceLiveStyleName());
|
||||
mainElement.addClassName(getRaceLiveStyleName());
|
||||
getRaceStateUiElement().setInnerText(isUntrackedRace ? I18N.live() : I18N.actionWatch());
|
||||
} else if (viewState == RaceViewState.FINISHED) {
|
||||
getRaceStateUiElement().setInnerText(isUntrackedRace ? I18N.raceIsFinished() : I18N.actionAnalyze());
|
||||
} else {
|
||||
anchorUiElement.addClassName(getRacePlannedStyleName());
|
||||
mainElement.addClassName(getRacePlannedStyleName());
|
||||
if (viewState == RaceViewState.SCHEDULED) getRaceStateUiElement().setInnerText(I18N.raceIsPlanned());
|
||||
else getRaceStateUiElement().setInnerText(viewState.getLabel());
|
||||
}
|
||||
setStyleName(anchorUiElement, getRaceUntrackedStyleName(), isUntrackedRace);
|
||||
setStyleName(mainElement, getRaceUntrackedStyleName(), isUntrackedRace);
|
||||
}
|
||||
|
||||
private void setupRaceStart(Date startDate) {
|
||||
@@ -58,7 +95,7 @@ public abstract class AbstractRegattaCompetitionFleetRace extends UIObject imple
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AnchorElement getMainUiElement();
|
||||
protected abstract Element getMainUiElement();
|
||||
|
||||
protected abstract Element getRaceNameUiElement();
|
||||
|
||||
|
||||
+2
-5
@@ -11,7 +11,6 @@ import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDT
|
||||
import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState;
|
||||
import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionFleetView;
|
||||
import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView;
|
||||
@@ -48,9 +47,7 @@ public abstract class RegattaCompetitionPresenter implements
|
||||
Map<RegattaCompetitionRaceView, SimpleRaceMetadataDTO> raceMap = new HashMap<>();
|
||||
fleetMap.put(fleetView, raceMap);
|
||||
for (SimpleRaceMetadataDTO race : fleet.getRaces()) {
|
||||
boolean tracked = race.getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA;
|
||||
String raceViewerUrl = tracked ? getRaceViewerURL(race) : null;
|
||||
RegattaCompetitionRaceView raceView = fleetView.addRaceView(race, raceViewerUrl);
|
||||
RegattaCompetitionRaceView raceView = fleetView.addRaceView(race, this);
|
||||
raceMap.put(raceView, race);
|
||||
}
|
||||
}
|
||||
@@ -100,6 +97,6 @@ public abstract class RegattaCompetitionPresenter implements
|
||||
seriesView.doFilter(unfilteredFleetCount == 0);
|
||||
}
|
||||
|
||||
protected abstract String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata);
|
||||
protected abstract String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata, String mode);
|
||||
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ public interface RegattaCompetitionView {
|
||||
}
|
||||
|
||||
public interface RegattaCompetitionFleetView {
|
||||
RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, String raceViewerUrl);
|
||||
RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter);
|
||||
void setNumberOfFleetsInSeries(int fleetCount);
|
||||
void doFilter(boolean filter);
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,7 +31,7 @@ public class GetLeaderboardByNameAction implements AsyncAction<LeaderboardDTO> {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final String leaderboardName;
|
||||
private final Date date;
|
||||
private final Collection<String> namesOfRacesForWhichToLoadLegDetails;
|
||||
private final Collection<String> namesOfRaceColumnsForWhichToLoadLegDetails;
|
||||
private final boolean addOverallDetails;
|
||||
private final LeaderboardDTO previousLeaderboard;
|
||||
private final StringMessages stringMessages;
|
||||
@@ -40,7 +40,7 @@ public class GetLeaderboardByNameAction implements AsyncAction<LeaderboardDTO> {
|
||||
private final boolean fillTotalPointsUncorrected;
|
||||
|
||||
public GetLeaderboardByNameAction(SailingServiceAsync sailingService, String leaderboardName, Date date,
|
||||
final Collection<String> namesOfRacesForWhichToLoadLegDetails, boolean addOverallDetails,
|
||||
final Collection<String> namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails,
|
||||
LeaderboardDTO previousLeaderboard, boolean fillTotalPointsUncorrected, Timer timerToAdjustOffsetIn,
|
||||
ErrorReporter errorReporter, StringMessages stringMessages) {
|
||||
this.sailingService = sailingService;
|
||||
@@ -48,7 +48,7 @@ public class GetLeaderboardByNameAction implements AsyncAction<LeaderboardDTO> {
|
||||
this.stringMessages = stringMessages;
|
||||
this.leaderboardName = leaderboardName;
|
||||
this.date = date;
|
||||
this.namesOfRacesForWhichToLoadLegDetails = namesOfRacesForWhichToLoadLegDetails;
|
||||
this.namesOfRaceColumnsForWhichToLoadLegDetails = namesOfRaceColumnsForWhichToLoadLegDetails;
|
||||
this.addOverallDetails = addOverallDetails;
|
||||
this.previousLeaderboard = previousLeaderboard;
|
||||
this.timerToAdjustOffetIn = timerToAdjustOffsetIn;
|
||||
@@ -58,7 +58,7 @@ public class GetLeaderboardByNameAction implements AsyncAction<LeaderboardDTO> {
|
||||
@Override
|
||||
public void execute(final AsyncCallback<LeaderboardDTO> callback) {
|
||||
final long clientTimeWhenRequestWasSent = System.currentTimeMillis();
|
||||
sailingService.getLeaderboardByName(leaderboardName, date, namesOfRacesForWhichToLoadLegDetails, addOverallDetails,
|
||||
sailingService.getLeaderboardByName(leaderboardName, date, namesOfRaceColumnsForWhichToLoadLegDetails, addOverallDetails,
|
||||
previousLeaderboard==null?null:previousLeaderboard.getId(), fillTotalPointsUncorrected,
|
||||
new AsyncCallback<IncrementalOrFullLeaderboardDTO>() {
|
||||
@Override
|
||||
|
||||
+37
-1
@@ -1,8 +1,10 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.security.Permission;
|
||||
@@ -10,7 +12,7 @@ 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.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
|
||||
import com.sap.sse.gwt.client.player.Timer;
|
||||
@@ -21,6 +23,19 @@ import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.UserStatusEventHandler;
|
||||
import com.sap.sse.security.ui.shared.UserDTO;
|
||||
|
||||
/**
|
||||
* A specific {@link TimePanel} that shows and manages a time slider for a race. Receives {@link RaceTimesInfoDTO}
|
||||
* objects when registered as a {@link RaceTimesInfoProviderListener} on a {@link RaceTimesInfoProvider} and adjusts the
|
||||
* time panel including its time slider and the marks displayed and the zoom model accordingly.
|
||||
* <p>
|
||||
*
|
||||
* It is possible to register as a "transitive" {@link RaceTimesInfoProviderListener} on this object in case a component
|
||||
* is interested in being notified when this object is done with its adjustments based on a
|
||||
* {@link RaceTimesInfoProviderListener} notification.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements RaceTimesInfoProviderListener {
|
||||
private final RaceTimesInfoProvider raceTimesInfoProvider;
|
||||
|
||||
@@ -31,6 +46,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
private final UserService userService;
|
||||
private final RaceTimePanelLifecycle componentLifecycle;
|
||||
|
||||
/**
|
||||
* These listeners are notified transitively after this object has been
|
||||
* {@link RaceTimesInfoProviderListener#raceTimesInfosReceived(Map, long, Date, long) notified} about race timing
|
||||
* changes and has finished reacting accordingly. This way, e.g., a race board mode implementation can do its
|
||||
* thing while assuming that the time slider has already been adjusted accordingly, therefore allowing for the
|
||||
* timer to be set to a reasonable value.
|
||||
*/
|
||||
private final Set<RaceTimesInfoProviderListener> listeners;
|
||||
|
||||
private final UserStatusEventHandler userStatusEventHandler = new UserStatusEventHandler() {
|
||||
@Override
|
||||
public void onUserStatusChange(UserDTO user) {
|
||||
@@ -55,6 +79,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
this.componentLifecycle = componentLifecycle;
|
||||
this.userService = userService;
|
||||
this.raceTimesInfoProvider = raceTimesInfoProvider;
|
||||
this.listeners = new HashSet<>();
|
||||
selectedRace = null;
|
||||
autoAdjustPlayMode = true;
|
||||
selectedRace = selectedRaceIdentifier;
|
||||
@@ -77,6 +102,14 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
userService.removeUserStatusEventHandler(userStatusEventHandler);
|
||||
}
|
||||
|
||||
public void addRaceTimesInfoProviderListener(RaceTimesInfoProviderListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeRaceTimesInfoProviderListener(RaceTimesInfoProviderListener listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canReplayWhileLiveIsPossible() {
|
||||
return this.hasCanReplayDuringLiveRacesPermission;
|
||||
@@ -363,5 +396,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
|
||||
timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
|
||||
updateTimeInfo(raceTimesInfos.get(selectedRace));
|
||||
for (final RaceTimesInfoProviderListener listener : listeners) {
|
||||
listener.raceTimesInfosReceived(raceTimesInfos, clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -1618,6 +1618,10 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String finishTime(String timeAsString);
|
||||
String showCompetitorCharts();
|
||||
String showWindChart();
|
||||
String watchLive();
|
||||
String raceAnalysis();
|
||||
String startAnalysis();
|
||||
String winningLanes();
|
||||
String userNotificationsOnlyIfMailAddressIsVerified();
|
||||
String enabled();
|
||||
String disabled();
|
||||
|
||||
+4
@@ -1599,3 +1599,7 @@ 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
|
||||
watchLive=Watch live
|
||||
raceAnalysis=Race analysis
|
||||
startAnalysis=Start analysis
|
||||
winningLanes=Winning lanes
|
||||
+4
@@ -1584,3 +1584,7 @@ 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
|
||||
watchLive=Live mitverfolgen
|
||||
raceAnalysis=Renn-Analyse
|
||||
startAnalysis=Start-Analyse
|
||||
winningLanes=Sieger-Kurse
|
||||
@@ -302,6 +302,10 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
|
||||
hideControlsPanel();
|
||||
}
|
||||
|
||||
public TimeRangeWithZoomProvider getTimeRangeProvider() {
|
||||
return timeRangeProvider;
|
||||
}
|
||||
|
||||
private Button createSettingsButton() {
|
||||
Button settingsButton = SettingsDialog.<T>createSettingsButton(this, stringMessages);
|
||||
settingsButton.setStyleName(timePanelCss.settingsButtonStyle());
|
||||
|
||||
-5
@@ -302,11 +302,6 @@ public abstract class AbstractCompetitorRaceChart<SettingsType extends ChartSett
|
||||
Date fromDate = timeOfEarliestRequestInMillis == null ? null : new Date(timeOfEarliestRequestInMillis);
|
||||
Date toDate = timeOfLatestRequestInMillis == null ? null : new Date(timeOfLatestRequestInMillis);
|
||||
loadData(fromDate, toDate, competitorsToLoad, false);
|
||||
} else {
|
||||
// chart is not visible; adding a competitor will require re-loading all data when the
|
||||
// chart becomes visible again
|
||||
timeOfEarliestRequestInMillis = null;
|
||||
timeOfLatestRequestInMillis = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -225,8 +225,7 @@ public abstract class AbstractRaceChart<SettingsType extends Settings> extends A
|
||||
@Override
|
||||
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
changeMinMaxAndExtremesInterval(zoomStartTimepoint, zoomEndTimepoint, true);
|
||||
// Probably there is a function for this in a newer version of highcharts: http://jsfiddle.net/mqz3N/1071/
|
||||
// chart.showResetZoom();
|
||||
chart.showResetZoom(); // Patched method
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -6,6 +6,10 @@ public class MultiCompetitorRaceChartSettings extends ChartSettings {
|
||||
private final DetailType firstDetailType;
|
||||
private final DetailType secondDetailType;
|
||||
|
||||
/**
|
||||
* @param firstDetailType must not be {@code null}
|
||||
* @param secondDetailType may be {@code null} if only one detail is to be displayed per competitor in the chart
|
||||
*/
|
||||
public MultiCompetitorRaceChartSettings(ChartSettings settings, DetailType firstDetailType,
|
||||
DetailType secondDetailType) {
|
||||
super(settings);
|
||||
|
||||
+27
@@ -43,6 +43,15 @@ public class RaceCompetitorSet extends RaceCompetitorIdsAsStringWithMD5Hash {
|
||||
* When {@link #idsAsStringOfCompetitorsParticipatingInRace} is <code>null</code> then so is this field, and vice versa.
|
||||
*/
|
||||
private Iterable<CompetitorDTO> competitorsParticipatingInRace;
|
||||
|
||||
private Set<CompetitorsForRaceDefinedListener> competitorsForRaceDefinedListeners;
|
||||
|
||||
/**
|
||||
* Such listeners are notified whenever the response to {@link #getCompetitorsParticipatingInRace()} changes.
|
||||
*/
|
||||
public static interface CompetitorsForRaceDefinedListener {
|
||||
void competitorsForRaceDefined(Iterable<CompetitorDTO> competitors);
|
||||
}
|
||||
|
||||
RaceCompetitorSet() {} // for GWT serialization only
|
||||
|
||||
@@ -54,6 +63,7 @@ public class RaceCompetitorSet extends RaceCompetitorIdsAsStringWithMD5Hash {
|
||||
*/
|
||||
public RaceCompetitorSet(CompetitorSelectionProvider competitorSelection) {
|
||||
super();
|
||||
this.competitorsForRaceDefinedListeners = new HashSet<>();
|
||||
this.competitorSelection = competitorSelection;
|
||||
this.competitorsParticipatingInRace = competitorSelection.getAllCompetitors();
|
||||
competitorSelection.addCompetitorSelectionChangeListener(new CompetitorSelectionChangeListener() {
|
||||
@@ -76,6 +86,7 @@ public class RaceCompetitorSet extends RaceCompetitorIdsAsStringWithMD5Hash {
|
||||
@Override
|
||||
public void competitorsListChanged(final Iterable<CompetitorDTO> competitors) {
|
||||
competitorsParticipatingInRace = computeCompetitorsFromIDs(competitors);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,11 +96,27 @@ public class RaceCompetitorSet extends RaceCompetitorIdsAsStringWithMD5Hash {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void addCompetitorsForRaceDefinedListener(CompetitorsForRaceDefinedListener listener) {
|
||||
competitorsForRaceDefinedListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeCompetitorsForRaceDefinedListener(CompetitorsForRaceDefinedListener listener) {
|
||||
competitorsForRaceDefinedListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setIdsAsStringsOfCompetitorsInRace(Set<String> idsAsStringsOfCompetitorsInRace) throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
||||
super.setIdsAsStringsOfCompetitorsInRace(idsAsStringsOfCompetitorsInRace);
|
||||
competitorsParticipatingInRace = computeCompetitorsFromIDs(competitorSelection.getAllCompetitors());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (final CompetitorsForRaceDefinedListener listener : competitorsForRaceDefinedListeners) {
|
||||
listener.competitorsForRaceDefined(competitorsParticipatingInRace);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<CompetitorDTO> getCompetitorsParticipatingInRace() {
|
||||
return competitorsParticipatingInRace;
|
||||
}
|
||||
|
||||
+23
-2
@@ -99,6 +99,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.client.shared.filter.QuickRankProvider;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceCompetitorSet.CompetitorsForRaceDefinedListener;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
|
||||
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
|
||||
@@ -473,7 +474,11 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateCoordinateSystemFromSettings() {
|
||||
/**
|
||||
* @return {@code true} if the map was redrawn by the call to this method
|
||||
*/
|
||||
private boolean updateCoordinateSystemFromSettings() {
|
||||
boolean redrawn = false;
|
||||
final MapOptions mapOptions;
|
||||
orientationChangeInProgress = true;
|
||||
if (getSettings().isWindUp()) {
|
||||
@@ -511,6 +516,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
if (mapOptions != null) { // if no coordinate system change happened that affects an existing map, don't redraw
|
||||
fixesAndTails.clearTails();
|
||||
redraw();
|
||||
redrawn = true;
|
||||
// zooming and setting options while the event loop is still working doesn't work reliably; defer until event loop returns
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
@@ -525,6 +531,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
}
|
||||
});
|
||||
}
|
||||
return redrawn;
|
||||
}
|
||||
|
||||
private void loadMapsAPIV3(final boolean showMapControls, final boolean showHeaderPanel) {
|
||||
@@ -745,6 +752,10 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
return map;
|
||||
}
|
||||
|
||||
public RaceSimulationOverlay getSimulationOverlay() {
|
||||
return simulationOverlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Panel where labels or other controls for the header can be positioned
|
||||
*/
|
||||
@@ -1025,7 +1036,9 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
final Iterable<CompetitorDTO> competitorsToShow, Map<CompetitorDTO, List<GPSFixDTOWithSpeedWindTackAndLegType>> boatData, boolean updateTailsOnly) {
|
||||
final Map<CompetitorDTO, Runnable> tailPreparersPerCompetitor =
|
||||
fixesAndTails.updateFixes(boatData, hasTailOverlapForCompetitor, RaceMap.this, transitionTimeInMillis);
|
||||
showBoatsOnMap(newTime, transitionTimeInMillis, competitorsToShow, updateTailsOnly, tailPreparersPerCompetitor);
|
||||
showBoatsOnMap(newTime, transitionTimeInMillis,
|
||||
/* re-calculate; it could have changed since the asynchronous request was made: */ getCompetitorsToShow(),
|
||||
updateTailsOnly, tailPreparersPerCompetitor);
|
||||
if (!updateTailsOnly) {
|
||||
showCompetitorInfoOnMap(newTime, transitionTimeInMillis, competitorSelection.getSelectedFilteredCompetitors());
|
||||
// even though the wind data is retrieved by a separate call, re-draw the advantage line because it needs to
|
||||
@@ -2887,4 +2900,12 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
return getLocalizedShortName();
|
||||
}
|
||||
|
||||
public void addCompetitorsForRaceDefinedListener(CompetitorsForRaceDefinedListener listener) {
|
||||
raceCompetitorSet.addCompetitorsForRaceDefinedListener(listener);
|
||||
}
|
||||
|
||||
public void removeCompetitorsForRaceDefinedListener(CompetitorsForRaceDefinedListener listener) {
|
||||
raceCompetitorSet.removeCompetitorsForRaceDefinedListener(listener);
|
||||
}
|
||||
|
||||
}
|
||||
+30
-18
@@ -526,7 +526,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
final LeaderboardDTO previousLeaderboard = getLeaderboard();
|
||||
getSailingService().getLeaderboardByName(getLeaderboardName(),
|
||||
timer.getPlayMode() == PlayModes.Live ? null : getLeaderboardDisplayDate(),
|
||||
/* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(),
|
||||
/* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaceColumns(),
|
||||
shallAddOverallDetails(), previousLeaderboard.getId(), /* fillTotalPointsUncorrected */ false,
|
||||
new MarkedAsyncCallback<IncrementalOrFullLeaderboardDTO>(
|
||||
new AsyncCallback<IncrementalOrFullLeaderboardDTO>() {
|
||||
@@ -586,7 +586,11 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
}
|
||||
return raceTimesInfoProvider;
|
||||
}
|
||||
|
||||
|
||||
public AsyncActionsExecutor getExecutor() {
|
||||
return asyncActionsExecutor;
|
||||
}
|
||||
|
||||
protected class CompetitorColumn extends LeaderboardSortableColumnWithMinMax<LeaderboardRowDTO, LeaderboardRowDTO> {
|
||||
private final CompetitorColumnBase<LeaderboardRowDTO> base;
|
||||
|
||||
@@ -1661,7 +1665,10 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
*/
|
||||
@Override
|
||||
public void addedToSelection(CompetitorDTO competitor) {
|
||||
getSelectionModel().setSelected(getRow(competitor.getIdAsString()), true);
|
||||
final LeaderboardRowDTO row = getRow(competitor.getIdAsString());
|
||||
if (row != null) {
|
||||
getSelectionModel().setSelected(row, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1669,7 +1676,10 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
*/
|
||||
@Override
|
||||
public void removedFromSelection(CompetitorDTO competitor) {
|
||||
getSelectionModel().setSelected(getRow(competitor.getIdAsString()), false);
|
||||
final LeaderboardRowDTO row = getRow(competitor.getIdAsString());
|
||||
if (row != null) {
|
||||
getSelectionModel().setSelected(row, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2265,7 +2275,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
if (needsDataLoading()) {
|
||||
GetLeaderboardByNameAction getLeaderboardByNameAction = new GetLeaderboardByNameAction(sailingService,
|
||||
getLeaderboardName(), useNullAsTimePoint() ? null : date,
|
||||
/* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(), shallAddOverallDetails(), /* previousLeaderboard */
|
||||
/* namesOfRaceColumnsForWhichToLoadLegDetails */getNamesOfExpandedRaceColumns(), shallAddOverallDetails(), /* previousLeaderboard */
|
||||
getLeaderboard(), isFillTotalPointsUncorrected(), timer, errorReporter, stringMessages);
|
||||
this.asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY,
|
||||
new AsyncCallback<LeaderboardDTO>() {
|
||||
@@ -2309,18 +2319,18 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
/**
|
||||
* Determine from column expansion state which races need their leg details
|
||||
*/
|
||||
private Collection<String> getNamesOfExpandedRaces() {
|
||||
Collection<String> namesOfExpandedRaces = new ArrayList<String>();
|
||||
private Collection<String> getNamesOfExpandedRaceColumns() {
|
||||
Collection<String> namesOfExpandedRaceColumns = new ArrayList<String>();
|
||||
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
|
||||
Column<LeaderboardRowDTO, ?> column = getLeaderboardTable().getColumn(i);
|
||||
if (column instanceof RaceColumn<?>) {
|
||||
RaceColumn<?> raceColumn = (RaceColumn<?>) column;
|
||||
if (raceColumn.isExpanded()) {
|
||||
namesOfExpandedRaces.add(raceColumn.getRaceColumnName());
|
||||
namesOfExpandedRaceColumns.add(raceColumn.getRaceColumnName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return namesOfExpandedRaces;
|
||||
return namesOfExpandedRaceColumns;
|
||||
}
|
||||
|
||||
private boolean shallAddOverallDetails() {
|
||||
@@ -2347,7 +2357,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
* Assigns <code>leaderboard</code> to {@link #leaderboard} and updates the UI accordingly. Also updates the min/max
|
||||
* values on the columns.
|
||||
*/
|
||||
protected void updateLeaderboard(LeaderboardDTO leaderboard) {
|
||||
public void updateLeaderboard(LeaderboardDTO leaderboard) {
|
||||
if (leaderboard != null) {
|
||||
Collection<RaceColumn<?>> columnsToCollapseAndExpandAgain = getExpandedRaceColumnsWhoseDisplayedLegCountChanged(leaderboard);
|
||||
for (RaceColumn<?> columnToCollapseAndExpandAgain : columnsToCollapseAndExpandAgain) {
|
||||
@@ -2564,14 +2574,16 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
* @return all competitors for which the {@link #getLeaderboard() leaderboard} has an entry whose
|
||||
* {@link LeaderboardEntryDTO#race} equals <code>race</code>
|
||||
*/
|
||||
private Iterable<CompetitorDTO> getCompetitors(RaceIdentifier race) {
|
||||
public Iterable<CompetitorDTO> getCompetitors(RaceIdentifier race) {
|
||||
Set<CompetitorDTO> result = new HashSet<CompetitorDTO>();
|
||||
for (RaceColumnDTO raceColumn : getLeaderboard().getRaceList()) {
|
||||
if (raceColumn.hasTrackedRace(race)) {
|
||||
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : getLeaderboard().rows.entrySet()) {
|
||||
LeaderboardEntryDTO entry = e.getValue().fieldsByRaceColumnName.get(raceColumn.getRaceColumnName());
|
||||
if (entry != null && entry.race != null && entry.race.equals(race)) {
|
||||
result.add(e.getKey());
|
||||
if (getLeaderboard() != null) {
|
||||
for (RaceColumnDTO raceColumn : getLeaderboard().getRaceList()) {
|
||||
if (raceColumn.hasTrackedRace(race)) {
|
||||
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : getLeaderboard().rows.entrySet()) {
|
||||
LeaderboardEntryDTO entry = e.getValue().fieldsByRaceColumnName.get(raceColumn.getRaceColumnName());
|
||||
if (entry != null && entry.race != null && entry.race.equals(race)) {
|
||||
result.add(e.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3040,7 +3052,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
||||
return leaderboardTable;
|
||||
}
|
||||
|
||||
protected SailingServiceAsync getSailingService() {
|
||||
public SailingServiceAsync getSailingService() {
|
||||
return sailingService;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1012,7 +1012,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateLeaderboard(LeaderboardDTO leaderboard) {
|
||||
public void updateLeaderboard(LeaderboardDTO leaderboard) {
|
||||
super.updateLeaderboard(leaderboard);
|
||||
if (leaderboard != null) {
|
||||
String lastScoreCorrectionComment = leaderboard.getComment();
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.core.shared.GWT;
|
||||
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.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.ui.actions.GetLeaderboardByNameAction;
|
||||
import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimePanel;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceCompetitorSet.CompetitorsForRaceDefinedListener;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
import com.sap.sse.gwt.client.player.Timer;
|
||||
|
||||
/**
|
||||
* Abstract base class for implementing a {@link RaceBoardMode}. The {@link #applyTo(RaceBoardPanel)} method registers
|
||||
* this object as a leaderboard update listener and as a race times info provider listener, also as a
|
||||
* {@link CompetitorsForRaceDefinedListener} in order to learn when the set of competitors for the race displayed by the
|
||||
* player is known. The default implementations of the corresponding callback methods will simply unregister this object
|
||||
* as a listener for the respective callback, enters the knowledge gained in the object's fields and calls the
|
||||
* {@link #trigger} method each time (abstract in this class). Subclasses can and should do the following:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Redefine {@link #applyTo(RaceBoardPanel)} and call the {@code stopReceiving...} methods for those types of
|
||||
* events they don't need</li>
|
||||
* <li>Redefine specific callback methods in case more processing is required or canceling the listener is desired only
|
||||
* when certain preconditions are met</li>
|
||||
* <li>Implement the {@link #trigger} method to check if all information required has been received by now and then use
|
||||
* it to configure the {@link RaceBoard} and its components accordingly</li>
|
||||
* </ul>
|
||||
*
|
||||
* Note that the {@link #updatedLeaderboard(LeaderboardDTO)} method will typically be called several times in more or
|
||||
* less unpredictable order, asynchronously. Calling {@link Timer#setTime(long)} will trigger
|
||||
* {@link #updatedLeaderboard(LeaderboardDTO)} eventually, but in between, other callbacks to the same method
|
||||
* may occur, triggered by other, automatic adjustments or initialization of the {@link Timer}. To solve this
|
||||
* problem, subclasses may decide to use a separate {@link GetLeaderboardByNameAction} action and execute
|
||||
* it using the {@link #getLeaderboardPanel()}.{@link LeaderboardPanel#getExecutor() getExecutor()}. In the
|
||||
* dedicated callback the subclass can then be sure that the {@link LeaderboardDTO} received matches the
|
||||
* time previously set on the {@link Timer}.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractRaceBoardMode implements RaceBoardMode, RaceTimesInfoProviderListener, LeaderboardUpdateListener {
|
||||
private Timer timer;
|
||||
private RegattaAndRaceIdentifier raceIdentifier;
|
||||
private RaceTimePanel raceTimePanel;
|
||||
private LeaderboardPanel leaderboardPanel;
|
||||
private RaceBoardPanel raceBoardPanel;
|
||||
|
||||
private Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo;
|
||||
private RaceTimesInfoDTO raceTimesInfoForRace;
|
||||
private LeaderboardDTO leaderboard;
|
||||
private LeaderboardDTO leaderboardForSpecificTimePoint;
|
||||
private RaceColumnDTO raceColumn;
|
||||
|
||||
@Override
|
||||
public void applyTo(RaceBoardPanel raceBoardPanel) {
|
||||
this.raceBoardPanel = raceBoardPanel;
|
||||
this.raceTimePanel = raceBoardPanel.getRaceTimePanel();
|
||||
this.raceTimePanel.addRaceTimesInfoProviderListener(this);
|
||||
this.leaderboardPanel = raceBoardPanel.getLeaderboardPanel();
|
||||
this.leaderboardPanel.addLeaderboardUpdateListener(this);
|
||||
this.timer = raceBoardPanel.getTimer();
|
||||
this.raceIdentifier = raceBoardPanel.getSelectedRaceIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever new information of any sort has become available. Subclasses can use this
|
||||
* to decide whether everything they need has been received in order to carry out their actions.
|
||||
*/
|
||||
protected abstract void trigger();
|
||||
|
||||
protected Timer getTimer() {
|
||||
return timer;
|
||||
}
|
||||
|
||||
protected RegattaAndRaceIdentifier getRaceIdentifier() {
|
||||
return raceIdentifier;
|
||||
}
|
||||
|
||||
protected RaceTimePanel getRaceTimePanel() {
|
||||
return raceTimePanel;
|
||||
}
|
||||
|
||||
protected LeaderboardPanel getLeaderboardPanel() {
|
||||
return leaderboardPanel;
|
||||
}
|
||||
|
||||
protected RaceBoardPanel getRaceBoardPanel() {
|
||||
return raceBoardPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the {@link RaceTimePanel} has reacted to this update. We assume that now the timing for the race has
|
||||
* been received, and it should be clear by now whether we're talking about a live or a replay race. The
|
||||
* {@link #raceTimesInfo} field is set to the {@code raceTimesInfo} object received as parameter, the
|
||||
* {@link #raceTimesInfoForRace} field is set to the race times info specific to the race identified by
|
||||
* {@link #getRaceIdentifier()}.
|
||||
*/
|
||||
@Override
|
||||
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo,
|
||||
long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
|
||||
this.raceTimesInfo = raceTimesInfo;
|
||||
this.raceTimesInfoForRace = raceTimesInfo.get(getRaceIdentifier());
|
||||
trigger();
|
||||
}
|
||||
|
||||
protected void stopReceivingRaceTimesInfos() {
|
||||
raceTimePanel.removeRaceTimesInfoProviderListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops listening for leaderboard updates
|
||||
*/
|
||||
@Override
|
||||
public void updatedLeaderboard(LeaderboardDTO leaderboard) {
|
||||
this.leaderboard = leaderboard;
|
||||
trigger();
|
||||
}
|
||||
|
||||
protected void stopReceivingLeaderboard() {
|
||||
leaderboardPanel.removeLeaderboardUpdateListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the leaderboard named {@code leaderboardName} for {@code timePoint} with details for race column
|
||||
* {@code raceColumnName} and stores it in {@link #leaderboardForSpecificTimePoint}, then invokes {@link #trigger()}.
|
||||
* If a {@link #getLeaderboard()} has been received already, it is passed on in the call in order to reduce the
|
||||
* bandwidth required, based on a differential approach.
|
||||
*/
|
||||
protected void loadLeaderboardForSpecificTimePoint(String leaderboardName,
|
||||
String raceColumnName, Date timePoint) {
|
||||
final AsyncCallback<LeaderboardDTO> callback = new AsyncCallback<LeaderboardDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
GWT.log("Error trying to load leaderboard", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(LeaderboardDTO result) {
|
||||
leaderboardForSpecificTimePoint = result;
|
||||
trigger();
|
||||
}
|
||||
};
|
||||
final ArrayList<String> raceColumnNameAsList = new ArrayList<>();
|
||||
if (getRaceColumn() != null) {
|
||||
raceColumnNameAsList.add(getRaceColumn().getName());
|
||||
}
|
||||
final GetLeaderboardByNameAction getLeaderboardByNameAction = new GetLeaderboardByNameAction(
|
||||
getLeaderboardPanel().getSailingService(), getLeaderboardPanel().getLeaderboard().name,
|
||||
getTimer().getTime(), raceColumnNameAsList, /* addOverallDetails */ false,
|
||||
getLeaderboard(), /* fillTotalPointsUncorrected */ false,
|
||||
/* timerToAdjustOffsetIn */ getTimer(), /* errorReporter */ null, StringMessages.INSTANCE);
|
||||
getLeaderboardPanel().getExecutor().execute(getLeaderboardByNameAction, LeaderboardPanel.LOAD_LEADERBOARD_DATA_CATEGORY, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void currentRaceSelected(RaceIdentifier raceIdentifier, RaceColumnDTO raceColumn) {
|
||||
this.raceColumn = raceColumn;
|
||||
trigger();
|
||||
}
|
||||
|
||||
protected Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> getRaceTimesInfo() {
|
||||
return raceTimesInfo;
|
||||
}
|
||||
|
||||
protected RaceTimesInfoDTO getRaceTimesInfoForRace() {
|
||||
return raceTimesInfoForRace;
|
||||
}
|
||||
|
||||
protected LeaderboardDTO getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
protected LeaderboardDTO getLeaderboardForSpecificTimePoint() {
|
||||
return leaderboardForSpecificTimePoint;
|
||||
}
|
||||
|
||||
protected RaceColumnDTO getRaceColumn() {
|
||||
return raceColumn;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayModes;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayStates;
|
||||
|
||||
/**
|
||||
* This mode best applies to non-live "replay" races. It sets the time to the "end of race" time point and makes sure
|
||||
* the race column in the leaderboard is expanded. The timer is put into {@link PlayStates#Paused} mode.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class FullAnalysisMode extends AbstractRaceBoardMode {
|
||||
private boolean leaderboardSettingsAdjusted;
|
||||
private boolean timerAdjusted;
|
||||
|
||||
/**
|
||||
* Listening for race times info continues until information about the end of the race has been received. The leaderboard
|
||||
* settings are adjusted as soon as a valid leaderboard has been received.
|
||||
*/
|
||||
@Override
|
||||
protected void trigger() {
|
||||
if (!leaderboardSettingsAdjusted && getLeaderboard() != null) {
|
||||
leaderboardSettingsAdjusted = true;
|
||||
// it's important to first unregister the listener before updateSettings is called because
|
||||
// updateSettings will trigger another leaderboard load, leading to an endless recursion otherwise
|
||||
stopReceivingLeaderboard();
|
||||
adjustLeaderboardSettings();
|
||||
}
|
||||
if (!timerAdjusted && getRaceTimesInfoForRace() != null && getRaceTimesInfoForRace().endOfRace != null) {
|
||||
timerAdjusted = true;
|
||||
stopReceivingRaceTimesInfos();
|
||||
if (getTimer().getPlayMode() == PlayModes.Live) {
|
||||
getTimer().setPlayMode(PlayModes.Replay);
|
||||
}
|
||||
getTimer().setTime(getRaceTimesInfoForRace().endOfRace.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustLeaderboardSettings() {
|
||||
final LeaderboardSettings existingSettings = getLeaderboardPanel().getSettings();
|
||||
final List<DetailType> raceDetailsToShow = new ArrayList<>(existingSettings.getRaceDetailsToShow());
|
||||
raceDetailsToShow.add(DetailType.RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
|
||||
raceDetailsToShow.add(DetailType.RACE_DISTANCE_TRAVELED);
|
||||
raceDetailsToShow.add(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS);
|
||||
final LeaderboardSettings newSettings = new LeaderboardSettings(existingSettings.getManeuverDetailsToShow(),
|
||||
existingSettings.getLegDetailsToShow(),
|
||||
raceDetailsToShow, existingSettings.getOverallDetailsToShow(), existingSettings.getNamesOfRaceColumnsToShow(),
|
||||
existingSettings.getNamesOfRacesToShow(),
|
||||
existingSettings.getNumberOfLastRacesToShow(), /* auto-expand pre-selected race */ true,
|
||||
existingSettings.getDelayBetweenAutoAdvancesInMilliseconds(),
|
||||
existingSettings.getNameOfRaceToSort(), existingSettings.isSortAscending(),
|
||||
existingSettings.isUpdateUponPlayStateChange(),
|
||||
existingSettings.getActiveRaceColumnSelectionStrategy(),
|
||||
existingSettings.isShowAddedScores(),
|
||||
existingSettings.isShowOverallColumnWithNumberOfRacesCompletedPerCompetitor(),
|
||||
existingSettings.isShowCompetitorSailIdColumn(),
|
||||
existingSettings.isShowCompetitorFullNameColumn());
|
||||
getLeaderboardPanel().updateSettings(newSettings);
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayModes;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayStates;
|
||||
|
||||
/**
|
||||
* Puts the race viewer into player mode, setting the timer to 10s before start and into {@link PlayStates#Playing} state if it's
|
||||
* not a live race where auto-play is started anyway.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class PlayerMode extends AbstractRaceBoardMode {
|
||||
private final Duration DURATION_BEFORE_START_TO_SET_TIMER_TO_FOR_REPLAY_RACES = Duration.ONE_SECOND.times(10);
|
||||
|
||||
private boolean adjustedLeaderboardSettings;
|
||||
|
||||
private boolean timerAdjusted;
|
||||
|
||||
private void adjustLeaderboardSettings() {
|
||||
final LeaderboardSettings existingSettings = getLeaderboardPanel().getSettings();
|
||||
final List<DetailType> raceDetailsToShow = new ArrayList<>(existingSettings.getRaceDetailsToShow());
|
||||
raceDetailsToShow.add(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS);
|
||||
raceDetailsToShow.add(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS);
|
||||
final LeaderboardSettings newSettings = new LeaderboardSettings(existingSettings.getManeuverDetailsToShow(),
|
||||
existingSettings.getLegDetailsToShow(),
|
||||
raceDetailsToShow, existingSettings.getOverallDetailsToShow(), existingSettings.getNamesOfRaceColumnsToShow(),
|
||||
existingSettings.getNamesOfRacesToShow(),
|
||||
existingSettings.getNumberOfLastRacesToShow(), /* auto-expand pre-selected race */ true,
|
||||
existingSettings.getDelayBetweenAutoAdvancesInMilliseconds(),
|
||||
existingSettings.getNameOfRaceToSort(), existingSettings.isSortAscending(),
|
||||
existingSettings.isUpdateUponPlayStateChange(),
|
||||
existingSettings.getActiveRaceColumnSelectionStrategy(),
|
||||
existingSettings.isShowAddedScores(),
|
||||
existingSettings.isShowOverallColumnWithNumberOfRacesCompletedPerCompetitor(),
|
||||
existingSettings.isShowCompetitorSailIdColumn(),
|
||||
existingSettings.isShowCompetitorFullNameColumn());
|
||||
getLeaderboardPanel().updateSettings(newSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void trigger() {
|
||||
if (getTimer().getPlayMode() == PlayModes.Live) {
|
||||
stopReceivingRaceTimesInfos(); // this trigger wouldn't be stopped otherwise
|
||||
}
|
||||
if (!adjustedLeaderboardSettings && getLeaderboard() != null) {
|
||||
adjustedLeaderboardSettings = true;
|
||||
// it's important to first unregister the listener before updateSettings is called because
|
||||
// updateSettings will trigger another leaderboard load, leading to an endless recursion otherwise
|
||||
stopReceivingLeaderboard();
|
||||
adjustLeaderboardSettings();
|
||||
}
|
||||
if (!timerAdjusted && getTimer().getPlayMode() != PlayModes.Live && getRaceTimesInfoForRace() != null && getRaceTimesInfoForRace().startOfRace != null) {
|
||||
timerAdjusted = true;
|
||||
getTimer().setTime(new MillisecondsTimePoint(getRaceTimesInfoForRace().startOfRace).minus(DURATION_BEFORE_START_TO_SET_TIMER_TO_FOR_REPLAY_RACES).asMillis());
|
||||
getTimer().play();
|
||||
// we've done our adjustments; remove listener and let go
|
||||
stopReceivingRaceTimesInfos();
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
-4
@@ -38,6 +38,11 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
|
||||
private static final String PARAM_LEADERBOARD_GROUP_NAME = "leaderboardGroupName";
|
||||
private static final String PARAM_EVENT_ID = "eventId";
|
||||
|
||||
/**
|
||||
* Controls the predefined mode into which to switch or configure the race viewer.
|
||||
*/
|
||||
private static final String PARAM_MODE = "mode";
|
||||
|
||||
private String regattaName;
|
||||
private String raceName;
|
||||
private String leaderboardName;
|
||||
@@ -53,6 +58,19 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
|
||||
// read mandatory parameters
|
||||
regattaName = Window.Location.getParameter(PARAM_REGATTA_NAME);
|
||||
raceName = Window.Location.getParameter(PARAM_RACE_NAME);
|
||||
final String modeName = Window.Location.getParameter(PARAM_MODE);
|
||||
RaceBoardMode mode;
|
||||
if (modeName == null) {
|
||||
mode = null;
|
||||
} else {
|
||||
try {
|
||||
mode = RaceBoardModes.valueOf(modeName).getMode();
|
||||
} catch (IllegalArgumentException e) {
|
||||
GWT.log("Couldn't resolve RaceBoard mode " + modeName);
|
||||
mode = null;
|
||||
}
|
||||
}
|
||||
final RaceBoardMode finalMode = mode;
|
||||
String leaderboardNameParamValue = Window.Location.getParameter(PARAM_LEADERBOARD_NAME);
|
||||
String leaderboardGroupNameParamValue = Window.Location.getParameter(PARAM_LEADERBOARD_GROUP_NAME);
|
||||
if (leaderboardNameParamValue != null && !leaderboardNameParamValue.isEmpty()) {
|
||||
@@ -109,8 +127,10 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
|
||||
createErrorPage("Could not obtain a race with name " + raceName + " for a regatta with name " + regattaName);
|
||||
return;
|
||||
}
|
||||
|
||||
createPerspectivePage(raceboardData, perspectiveSettings, showChartMarkEditMediaButtonsAndVideo);
|
||||
final RaceBoardPanel raceBoardPanel = createPerspectivePage(raceboardData, perspectiveSettings, showChartMarkEditMediaButtonsAndVideo);
|
||||
if (finalMode != null) {
|
||||
finalMode.applyTo(raceBoardPanel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,7 +149,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
|
||||
vp.add(new Label(message));
|
||||
}
|
||||
|
||||
private void createPerspectivePage(RaceboardDataDTO raceboardData, RaceBoardPerspectiveSettings perspectiveSettings,
|
||||
private RaceBoardPanel createPerspectivePage(RaceboardDataDTO raceboardData, RaceBoardPerspectiveSettings perspectiveSettings,
|
||||
boolean showChartMarkEditMediaButtonsAndVideo) {
|
||||
selectedRace = raceboardData.getRace();
|
||||
Window.setTitle(selectedRace.getName());
|
||||
@@ -151,7 +171,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
|
||||
raceboardData.getCompetitorAndTheirBoats(), timer, selectedRace.getRaceIdentifier(), leaderboardName,
|
||||
leaderboardGroupName, eventId, RaceBoardEntryPoint.this, getStringMessages(), userAgent,
|
||||
raceTimesInfoProvider, showChartMarkEditMediaButtonsAndVideo);
|
||||
|
||||
RootLayoutPanel.get().add(raceBoardPerspective.getEntryWidget());
|
||||
return raceBoardPerspective;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
|
||||
/**
|
||||
* The {@link RaceBoardEntryPoint} implements a versatile race viewer perspective that comes with a leaderboard, charts
|
||||
* and a central map component. Through various options, this viewer and its components can be configured in various
|
||||
* ways, making it a powerful and flexible tool. In order to simplify usage for specific anticipated scenarios,
|
||||
* a {@link RaceBoardMode} implements a strategy for pre-configuring the various settings and component states
|
||||
* in a way useful for that particular scenario. For example, a "start analysis" mode would adjust the
|
||||
* {@link LeaderboardSettings} such that the columns making relevant statements about the start are shown
|
||||
* whereas others are suppressed; the timer would be set to the time of the race start, and the competitor chart
|
||||
* would be shown, with speed over ground as the metric selected and the top three boats selected.<p>
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface RaceBoardMode {
|
||||
/**
|
||||
* Applies this mode to the {@code raceBoardPanel}, making all adjustments necessary to the perspective, its
|
||||
* components and their settings to put the panel into this mode.
|
||||
* <p>
|
||||
*
|
||||
* Implementations in this same package can use the package-protected (default-scoped) methods of
|
||||
* {@link RaceBoardPanel} to access the timer and the components that constitute the panel, such as
|
||||
* {@link RaceBoardPanel#getLeaderboardPanel()}, {@link RaceBoardPanel#getMap()} or
|
||||
* {@link RaceBoardPanel#getTimer()}.
|
||||
*/
|
||||
void applyTo(RaceBoardPanel raceBoardPanel);
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceCompetitorSet.CompetitorsForRaceDefinedListener;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public abstract class RaceBoardModeWithPerRaceCompetitors extends AbstractRaceBoardMode implements CompetitorsForRaceDefinedListener {
|
||||
private Iterable<CompetitorDTO> competitorsInRace;
|
||||
|
||||
abstract protected void updateCompetitorSelection();
|
||||
|
||||
@Override
|
||||
public void applyTo(RaceBoardPanel raceBoardPanel) {
|
||||
super.applyTo(raceBoardPanel);
|
||||
raceBoardPanel.getMap().addCompetitorsForRaceDefinedListener(this);
|
||||
}
|
||||
|
||||
protected void stopReceivingCompetitorsInRace() {
|
||||
getRaceBoardPanel().getMap().removeCompetitorsForRaceDefinedListener(this);
|
||||
}
|
||||
|
||||
protected void updateCompetitorSelection(final int howManyTopCompetitorsInRaceToSelect, LeaderboardDTO leaderboard) {
|
||||
if (leaderboard != null) {
|
||||
final List<CompetitorDTO> competitorsFromBestToWorstInColumn = leaderboard.getCompetitorsFromBestToWorst(getRaceColumn());
|
||||
final Set<CompetitorDTO> competitorsToSelect = new HashSet<>();
|
||||
int numberOfSelectedCompetitors = 0;
|
||||
for (int i=0; numberOfSelectedCompetitors<howManyTopCompetitorsInRaceToSelect && i<competitorsFromBestToWorstInColumn.size(); i++) {
|
||||
if (getCompetitorsInRace() == null || Util.contains(getCompetitorsInRace(), competitorsFromBestToWorstInColumn.get(i))) {
|
||||
competitorsToSelect.add(competitorsFromBestToWorstInColumn.get(i));
|
||||
numberOfSelectedCompetitors++;
|
||||
}
|
||||
}
|
||||
getRaceBoardPanel().getCompetitorSelectionProvider().setSelection(competitorsToSelect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorsForRaceDefined(Iterable<CompetitorDTO> competitorsInRace) {
|
||||
this.competitorsInRace = competitorsInRace;
|
||||
trigger();
|
||||
}
|
||||
|
||||
protected Iterable<CompetitorDTO> getCompetitorsInRace() {
|
||||
return competitorsInRace;
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
public enum RaceBoardModes {
|
||||
PLAYER(new PlayerMode()), FULL_ANALYSIS(new FullAnalysisMode()), START_ANALYSIS(new StartAnalysisMode()), WINNING_LANES(new WinningLanesMode());
|
||||
|
||||
private RaceBoardModes(RaceBoardMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public RaceBoardMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
private final RaceBoardMode mode;
|
||||
}
|
||||
+37
-9
@@ -415,6 +415,38 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite<RaceBoardPerspe
|
||||
componentViewer.forceLayout();
|
||||
}
|
||||
|
||||
LeaderboardPanel getLeaderboardPanel() {
|
||||
return leaderboardPanel;
|
||||
}
|
||||
|
||||
MultiCompetitorRaceChart getCompetitorChart() {
|
||||
return competitorChart;
|
||||
}
|
||||
|
||||
WindChart getWindChart() {
|
||||
return windChart;
|
||||
}
|
||||
|
||||
RaceTimePanel getRaceTimePanel() {
|
||||
return racetimePanel;
|
||||
}
|
||||
|
||||
Timer getTimer() {
|
||||
return timer;
|
||||
}
|
||||
|
||||
RaceMap getMap() {
|
||||
return raceMap;
|
||||
}
|
||||
|
||||
RegattaAndRaceIdentifier getSelectedRaceIdentifier() {
|
||||
return selectedRaceIdentifier;
|
||||
}
|
||||
|
||||
CompetitorSelectionProvider getCompetitorSelectionProvider() {
|
||||
return competitorSelectionProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the collapsable panel for the leaderboard open or close, if in <code>CASCADE</code> view mode.<br />
|
||||
* Displays or hides the leaderboard, if in <code>ONESCREEN</code> view mode.<br /><br />
|
||||
@@ -451,10 +483,6 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite<RaceBoardPerspe
|
||||
setComponentVisible(leaderboardAndMapViewer, competitorChart, visible);
|
||||
}
|
||||
|
||||
public RaceTimePanel getTimePanel() {
|
||||
return racetimePanel;
|
||||
}
|
||||
|
||||
protected SailingServiceAsync getSailingService() {
|
||||
return sailingService;
|
||||
}
|
||||
@@ -475,11 +503,11 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite<RaceBoardPerspe
|
||||
public void updatedLeaderboard(LeaderboardDTO leaderboard) {
|
||||
leaderboardAndMapViewer.setLeftComponentWidth(leaderboardPanel.getContentPanel().getOffsetWidth());
|
||||
if (editMarkPassingPanel != null) {
|
||||
editMarkPassingPanel.setLeaderboard(leaderboard);
|
||||
editMarkPassingPanel.setLeaderboard(leaderboard);
|
||||
}
|
||||
if (editMarkPositionPanel != null) {
|
||||
editMarkPositionPanel.setLeaderboard(leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -560,12 +588,12 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite<RaceBoardPerspe
|
||||
}
|
||||
|
||||
private void manageTimePanelToggleButton(boolean advanceTimePanelEnabled) {
|
||||
final Button toggleButton = getTimePanel().getAdvancedToggleButton();
|
||||
final Button toggleButton = getRaceTimePanel().getAdvancedToggleButton();
|
||||
if (advanceTimePanelEnabled) {
|
||||
toggleButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
boolean advancedModeShown = getTimePanel().toggleAdvancedMode();
|
||||
boolean advancedModeShown = getRaceTimePanel().toggleAdvancedMode();
|
||||
if (advancedModeShown) {
|
||||
dockPanel.setWidgetSize(timePanelWrapper, TIMEPANEL_EXPANDED_HEIGHT);
|
||||
toggleButton.removeStyleDependentName("Closed");
|
||||
@@ -585,7 +613,7 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite<RaceBoardPerspe
|
||||
private ResizableFlowPanel createTimePanelLayoutWrapper() {
|
||||
ResizableFlowPanel timeLineInnerBgPanel = new ResizableFlowPanel();
|
||||
timeLineInnerBgPanel.addStyleName("timeLineInnerBgPanel");
|
||||
timeLineInnerBgPanel.add(getTimePanel());
|
||||
timeLineInnerBgPanel.add(getRaceTimePanel());
|
||||
|
||||
ResizableFlowPanel timeLineInnerPanel = new ResizableFlowPanel();
|
||||
timeLineInnerPanel.add(timeLineInnerBgPanel);
|
||||
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.maps.client.events.idle.IdleMapEvent;
|
||||
import com.google.gwt.maps.client.events.idle.IdleMapHandler;
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.gwt.ui.client.shared.charts.ChartSettings;
|
||||
import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChart;
|
||||
import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChartSettings;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayModes;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayStates;
|
||||
|
||||
/**
|
||||
* The start analysis mode makes the competitor chart visible and sets it to speed over ground; the
|
||||
* {@link LeaderboardSettings} are adjusted such that no leg columns but only start parameters are
|
||||
* shown. The top three starters are selected when the leaderboard has been updated after setting
|
||||
* the timer to a few seconds after the start. The {@link PlayStates#Paused} is used for the timer.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class StartAnalysisMode extends RaceBoardModeWithPerRaceCompetitors {
|
||||
private static final Duration DURATION_AFTER_START_TO_SET_TIMER_TO_FOR_START_ANALYSIS = Duration.ONE_SECOND.times(10);
|
||||
private static final Duration DURATION_BEFORE_START_TO_INCLUDE_IN_CHART_TIME_RANGE = Duration.ONE_SECOND.times(30);
|
||||
private static final Duration DURATION_AFTER_START_TO_INCLUDE_IN_CHART_TIME_RANGE = Duration.ONE_SECOND.times(30);
|
||||
|
||||
private MultiCompetitorRaceChart competitorChart;
|
||||
|
||||
private boolean leaderboardSettingsAdjusted;
|
||||
|
||||
private boolean competitorSelectionUpdated;
|
||||
private boolean timerAdjusted;
|
||||
private boolean mapSettingsAndTimeZoomAdjusted;
|
||||
|
||||
@Override
|
||||
public void applyTo(RaceBoardPanel raceBoardPanel) {
|
||||
super.applyTo(raceBoardPanel);
|
||||
this.competitorChart = raceBoardPanel.getCompetitorChart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCompetitorSelection() {
|
||||
updateCompetitorSelection(/* howManyTopCompetitorsInRaceToSelect */ 3, getLeaderboardForSpecificTimePoint());
|
||||
}
|
||||
|
||||
private void adjustMapSettings() {
|
||||
final RaceMapSettings existingMapSettings = getRaceBoardPanel().getMap().getSettings();
|
||||
final RaceMapSettings newMapSettings = new RaceMapSettings(
|
||||
new RaceMapZoomSettings(Collections.singleton(ZoomTypes.BOATS), /* zoomToSelected */ false),
|
||||
existingMapSettings.getHelpLinesSettings(),
|
||||
existingMapSettings.getTransparentHoverlines(),
|
||||
existingMapSettings.getHoverlineStrokeWeight(),
|
||||
existingMapSettings.getTailLengthInMilliseconds(),
|
||||
/* existingMapSettings.isWindUp() */ true,
|
||||
existingMapSettings.getBuoyZoneRadiusInMeters(),
|
||||
existingMapSettings.isShowOnlySelectedCompetitors(),
|
||||
existingMapSettings.isShowSelectedCompetitorsInfo(),
|
||||
existingMapSettings.isShowWindStreamletColors(),
|
||||
existingMapSettings.isShowWindStreamletOverlay(),
|
||||
existingMapSettings.isShowSimulationOverlay(),
|
||||
existingMapSettings.isShowMapControls(),
|
||||
existingMapSettings.getManeuverTypesToShow(),
|
||||
existingMapSettings.isShowDouglasPeuckerPoints());
|
||||
// try to update the settings once; the problem is the "wind up" display; it changes pan/zoom
|
||||
// which is a major source of instability for the map. Going twice in the map idle event handler
|
||||
// to ensure the settings are really applied.
|
||||
final Object[] registration = new Object[1];
|
||||
registration[0] = getRaceBoardPanel().getMap().getMap().addIdleHandler(new IdleMapHandler() {
|
||||
@Override
|
||||
public void onEvent(IdleMapEvent event) {
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
getRaceBoardPanel().getMap().updateSettings(newMapSettings);
|
||||
}
|
||||
});
|
||||
((HandlerRegistration) registration[0]).removeHandler();
|
||||
}
|
||||
});
|
||||
getRaceBoardPanel().getMap().updateSettings(newMapSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void trigger() {
|
||||
if (!leaderboardSettingsAdjusted && getLeaderboard() != null) {
|
||||
leaderboardSettingsAdjusted = true;
|
||||
stopReceivingLeaderboard();
|
||||
adjustLeaderboardSettings();
|
||||
}
|
||||
if (!timerAdjusted && getRaceTimesInfoForRace() != null && getRaceTimesInfoForRace().startOfRace != null) {
|
||||
timerAdjusted = true;
|
||||
// we've done our adjustments; remove listener and let go
|
||||
stopReceivingRaceTimesInfos();
|
||||
// make sure we're no longer in live/playing mode/state; the start analysis is supposed to be a "frozen" display at first
|
||||
if (getTimer().getPlayMode() == PlayModes.Live) {
|
||||
getTimer().setPlayMode(PlayModes.Replay);
|
||||
}
|
||||
getTimer().pause();
|
||||
// the following call will always trigger a leaderboard load and therefore a callback
|
||||
// to updatedLeaderboard; therefore, updatedLeaderboard can decide when it's time to
|
||||
// trigger the chart display and the map settings application
|
||||
getTimer().setTime(new MillisecondsTimePoint(getRaceTimesInfoForRace().startOfRace).plus(DURATION_AFTER_START_TO_SET_TIMER_TO_FOR_START_ANALYSIS).asMillis());
|
||||
// no need to do anything if we don't have the timing info yet; after obtaining the timing
|
||||
// info we can start waiting for the simulation overlay and then adjust the map settings and,
|
||||
// if available, show the competitor chart
|
||||
if (!mapSettingsAndTimeZoomAdjusted) {
|
||||
mapSettingsAndTimeZoomAdjusted = true;
|
||||
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
|
||||
@Override
|
||||
public boolean execute() {
|
||||
// keep trying in 500ms steps until the simulation overlay is found; this way, changing the competitor chart
|
||||
// settings is largely more successful
|
||||
final boolean simulationOverlayFound = getRaceBoardPanel().getMap().getSimulationOverlay() != null;
|
||||
if (simulationOverlayFound) {
|
||||
if (isCompetitorChartEnabled()) {
|
||||
getRaceBoardPanel().setCompetitorChartVisible(true);
|
||||
final MultiCompetitorRaceChartSettings newCompetitorChartSettings = new MultiCompetitorRaceChartSettings(
|
||||
new ChartSettings(/* stepSizeInMillis */ 1000), DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS,
|
||||
/* no second series */ null);
|
||||
competitorChart.updateSettings(newCompetitorChartSettings);
|
||||
getRaceTimePanel().getTimeRangeProvider().setTimeZoom(
|
||||
new MillisecondsTimePoint(getRaceTimesInfoForRace().startOfRace).minus(DURATION_BEFORE_START_TO_INCLUDE_IN_CHART_TIME_RANGE).asDate(),
|
||||
new MillisecondsTimePoint(getRaceTimesInfoForRace().startOfRace).plus(DURATION_AFTER_START_TO_INCLUDE_IN_CHART_TIME_RANGE).asDate());
|
||||
}
|
||||
adjustMapSettings();
|
||||
}
|
||||
return !simulationOverlayFound;
|
||||
}
|
||||
}, /* delay in milliseconds */ 500);
|
||||
}
|
||||
}
|
||||
if (getLeaderboardForSpecificTimePoint() == null &&
|
||||
getRaceColumn() != null && getLeaderboard() != null
|
||||
&& timerAdjusted) {
|
||||
loadLeaderboardForSpecificTimePoint(getLeaderboard().name, getRaceColumn().getName(), getTimer().getTime());
|
||||
}
|
||||
if (!competitorSelectionUpdated && getLeaderboardForSpecificTimePoint() != null && getCompetitorsInRace() != null) {
|
||||
competitorSelectionUpdated = true;
|
||||
stopReceivingCompetitorsInRace();
|
||||
updateCompetitorSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustLeaderboardSettings() {
|
||||
final LeaderboardSettings existingSettings = getLeaderboardPanel().getSettings();
|
||||
final List<DetailType> raceDetailsToShow = new ArrayList<>(existingSettings.getRaceDetailsToShow());
|
||||
raceDetailsToShow.add(DetailType.RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START);
|
||||
raceDetailsToShow.add(DetailType.RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START);
|
||||
raceDetailsToShow.add(DetailType.DISTANCE_TO_START_AT_RACE_START);
|
||||
raceDetailsToShow.add(DetailType.DISTANCE_TO_START_LINE);
|
||||
raceDetailsToShow.add(DetailType.DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_PASSING_START_IN_METERS);
|
||||
raceDetailsToShow.add(DetailType.SPEED_OVER_GROUND_AT_RACE_START);
|
||||
raceDetailsToShow.add(DetailType.SPEED_OVER_GROUND_WHEN_PASSING_START);
|
||||
raceDetailsToShow.add(DetailType.START_TACK);
|
||||
raceDetailsToShow.add(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS);
|
||||
raceDetailsToShow.remove(DetailType.DISPLAY_LEGS);
|
||||
final LeaderboardSettings newSettings = new LeaderboardSettings(existingSettings.getManeuverDetailsToShow(),
|
||||
existingSettings.getLegDetailsToShow(),
|
||||
raceDetailsToShow, existingSettings.getOverallDetailsToShow(), existingSettings.getNamesOfRaceColumnsToShow(),
|
||||
existingSettings.getNamesOfRacesToShow(),
|
||||
existingSettings.getNumberOfLastRacesToShow(), /* auto-expand pre-selected race */ true,
|
||||
existingSettings.getDelayBetweenAutoAdvancesInMilliseconds(),
|
||||
existingSettings.getNameOfRaceToSort(), existingSettings.isSortAscending(),
|
||||
existingSettings.isUpdateUponPlayStateChange(),
|
||||
existingSettings.getActiveRaceColumnSelectionStrategy(),
|
||||
existingSettings.isShowAddedScores(),
|
||||
existingSettings.isShowOverallColumnWithNumberOfRacesCompletedPerCompetitor(),
|
||||
existingSettings.isShowCompetitorSailIdColumn(),
|
||||
existingSettings.isShowCompetitorFullNameColumn());
|
||||
getLeaderboardPanel().updateSettings(newSettings);
|
||||
}
|
||||
|
||||
private boolean isCompetitorChartEnabled() {
|
||||
return competitorChart != null;
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayModes;
|
||||
|
||||
/**
|
||||
* Puts the race viewer in a mode where the user can see what may be called the "Winning Lanes." For this,
|
||||
* the timer is set to the point in time when the first competitor finishes the race, or, for live races,
|
||||
* to the current point in time. The tail length is chosen such that it covers the full track of the
|
||||
* competitor farthest ahead.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
|
||||
private Duration tailLength;
|
||||
|
||||
private boolean adjustedLeaderboardSettings;
|
||||
|
||||
private boolean adjustedCompetitorSelection;
|
||||
|
||||
@Override
|
||||
protected void updateCompetitorSelection() {
|
||||
final int howManyCompetitorsToSelect = getHowManyCompetitorsToSelect(getLeaderboardPanel().getCompetitors(getRaceIdentifier()));
|
||||
updateCompetitorSelection(howManyCompetitorsToSelect, getLeaderboardForSpecificTimePoint());
|
||||
}
|
||||
|
||||
private void adjustLeaderboardSettings() {
|
||||
final LeaderboardSettings existingSettings = getLeaderboardPanel().getSettings();
|
||||
final List<DetailType> raceDetailsToShow = new ArrayList<>(existingSettings.getRaceDetailsToShow());
|
||||
raceDetailsToShow.add(DetailType.RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR_IN_METERS);
|
||||
raceDetailsToShow.add(DetailType.RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR_IN_METERS);
|
||||
raceDetailsToShow.add(DetailType.RACE_DISTANCE_TRAVELED);
|
||||
raceDetailsToShow.add(DetailType.RACE_TIME_TRAVELED);
|
||||
raceDetailsToShow.remove(DetailType.DISPLAY_LEGS);
|
||||
final LeaderboardSettings newSettings = new LeaderboardSettings(existingSettings.getManeuverDetailsToShow(),
|
||||
existingSettings.getLegDetailsToShow(),
|
||||
raceDetailsToShow, existingSettings.getOverallDetailsToShow(), existingSettings.getNamesOfRaceColumnsToShow(),
|
||||
existingSettings.getNamesOfRacesToShow(),
|
||||
existingSettings.getNumberOfLastRacesToShow(), /* auto-expand pre-selected race */ true,
|
||||
existingSettings.getDelayBetweenAutoAdvancesInMilliseconds(),
|
||||
existingSettings.getNameOfRaceToSort(), existingSettings.isSortAscending(),
|
||||
existingSettings.isUpdateUponPlayStateChange(),
|
||||
existingSettings.getActiveRaceColumnSelectionStrategy(),
|
||||
existingSettings.isShowAddedScores(),
|
||||
existingSettings.isShowOverallColumnWithNumberOfRacesCompletedPerCompetitor(),
|
||||
existingSettings.isShowCompetitorSailIdColumn(),
|
||||
existingSettings.isShowCompetitorFullNameColumn());
|
||||
getLeaderboardPanel().updateSettings(newSettings);
|
||||
}
|
||||
|
||||
private void adjustMapSettings() {
|
||||
final RaceMapSettings existingMapSettings = getRaceBoardPanel().getMap().getSettings();
|
||||
final RaceMapSettings newMapSettings = new RaceMapSettings(existingMapSettings.getZoomSettings(),
|
||||
existingMapSettings.getHelpLinesSettings(),
|
||||
existingMapSettings.getTransparentHoverlines(),
|
||||
existingMapSettings.getHoverlineStrokeWeight(),
|
||||
tailLength.asMillis(),
|
||||
/* existingMapSettings.isWindUp() */ true,
|
||||
existingMapSettings.getBuoyZoneRadiusInMeters(),
|
||||
/* existingMapSettings.isShowOnlySelectedCompetitors() */ true, // show the top n competitors and their tails quickly
|
||||
existingMapSettings.isShowSelectedCompetitorsInfo(),
|
||||
existingMapSettings.isShowWindStreamletColors(),
|
||||
existingMapSettings.isShowWindStreamletOverlay(),
|
||||
existingMapSettings.isShowSimulationOverlay(),
|
||||
existingMapSettings.isShowMapControls(),
|
||||
existingMapSettings.getManeuverTypesToShow(),
|
||||
existingMapSettings.isShowDouglasPeuckerPoints());
|
||||
getRaceBoardPanel().getMap().updateSettings(newMapSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the set of competitors in the leaderboard, determines how many competitors to select for the "winning lanes"
|
||||
* view. The number is determined to be at least one tenth of the number of competitors, but at least one if there are
|
||||
* one or more competitors.
|
||||
*/
|
||||
private int getHowManyCompetitorsToSelect(Iterable<CompetitorDTO> competitors) {
|
||||
final int numberOfCompetitors = Util.size(competitors);
|
||||
return numberOfCompetitors==0 ? 0 : numberOfCompetitors<=4 ? 1 : numberOfCompetitors <=9 ? 2 : 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void trigger() {
|
||||
final Date startOfRace;
|
||||
if (getRaceTimesInfoForRace() != null && (startOfRace=getRaceTimesInfoForRace().startOfRace) != null) {
|
||||
if (getTimer().getPlayMode() == PlayModes.Live) {
|
||||
// adjust tail length such that for the leading boat the tail is shown since the start time point
|
||||
tailLength = new MillisecondsTimePoint(startOfRace).until(getTimer().getLiveTimePoint());
|
||||
} else {
|
||||
final List<MarkPassingTimesDTO> markPassingTimes = getRaceTimesInfoForRace().getMarkPassingTimes();
|
||||
final Date firstPassingOfLastWaypointPassed = markPassingTimes == null || markPassingTimes.isEmpty() ? null :
|
||||
markPassingTimes.get(markPassingTimes.size()-1).firstPassingDate;
|
||||
final Date endOfRace = getRaceTimesInfoForRace().endOfRace;
|
||||
final Date end = firstPassingOfLastWaypointPassed != null ? firstPassingOfLastWaypointPassed :
|
||||
endOfRace != null ? endOfRace : getRaceTimesInfoForRace().endOfTracking;
|
||||
if (end != null) {
|
||||
tailLength = new MillisecondsTimePoint(startOfRace).until(new MillisecondsTimePoint(end));
|
||||
getTimer().setTime(end.getTime());
|
||||
}
|
||||
}
|
||||
// we've done our adjustments; remove listener and let go
|
||||
stopReceivingRaceTimesInfos();
|
||||
}
|
||||
if (!adjustedLeaderboardSettings && getLeaderboard() != null) {
|
||||
adjustedLeaderboardSettings = true;
|
||||
// it's important to first unregister the listener before updateSettings is called because
|
||||
// updateSettings will trigger another leaderboard load, leading to an endless recursion otherwise
|
||||
stopReceivingLeaderboard();
|
||||
adjustLeaderboardSettings();
|
||||
}
|
||||
if (adjustedLeaderboardSettings && tailLength != null) {
|
||||
adjustMapSettings();
|
||||
}
|
||||
if (getLeaderboardForSpecificTimePoint() == null && tailLength != null && getLeaderboard() != null && getRaceColumn() != null) {
|
||||
loadLeaderboardForSpecificTimePoint(getLeaderboard().name, getRaceColumn().getName(), getTimer().getTime());
|
||||
}
|
||||
if (!adjustedCompetitorSelection && getLeaderboardForSpecificTimePoint() != null && getCompetitorsInRace() != null) {
|
||||
stopReceivingCompetitorsInRace();
|
||||
adjustedCompetitorSelection = true;
|
||||
updateCompetitorSelection();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -459,6 +459,7 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
import com.sap.sse.common.mail.MailException;
|
||||
@@ -2948,7 +2949,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Theres currently no support for the enum value '" + dataType
|
||||
throw new UnsupportedOperationException("There is currently no support for the enum value '" + dataType
|
||||
+ "' in this method.");
|
||||
}
|
||||
return result;
|
||||
@@ -2966,8 +2967,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
TimePoint newestEvent = trackedRace.getTimePointOfNewestEvent();
|
||||
final TimePoint startTime = from == null ? trackedRace.getStartOfTracking() : new MillisecondsTimePoint(from);
|
||||
final TimePoint endTime = (to == null || to.after(newestEvent.asDate())) ? newestEvent : new MillisecondsTimePoint(to);
|
||||
final long adjustedStepSizeInMillis = startTime==null || endTime == null ? Long.MAX_VALUE :
|
||||
Math.max(stepSizeInMillis, Math.abs(startTime.until(endTime).asMillis())/SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY);
|
||||
final long adjustedStepSizeInMillis = (long) Math.max((double) stepSizeInMillis, startTime.until(endTime).divide(new MillisecondsDurationImpl(stepSizeInMillis)));
|
||||
result = new CompetitorsRaceDataDTO(detailType, startTime==null?null:startTime.asDate(), endTime==null?null:endTime.asDate());
|
||||
final int MAX_CACHE_SIZE = SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY;
|
||||
final ConcurrentHashMap<TimePoint, WindLegTypeAndLegBearingCache> cachesByTimePoint = new ConcurrentHashMap<>();
|
||||
|
||||
+19
@@ -6,6 +6,25 @@
|
||||
<div class="innerContent">
|
||||
<h5 class="articleSubheadline">July 2016</h5>
|
||||
<ul class="bulletList">
|
||||
<li>If you want to analyze a race, the navigation slightly changed. The button, which is shown for tracked
|
||||
races won't lead you to the race board directly, but provides a small menu. There you can choose from
|
||||
several pre-defined analysis, which will launch the race board with respective configurations:
|
||||
<ul>
|
||||
<li>Replay/Watch live: Launches race board in play mode starting at race start, if race is already
|
||||
finished (Replay) or at the actual time, if the race is currently live (Watch live)
|
||||
</li>
|
||||
<li>Race analysis: Shows the race results by setting the timer to the end of the race.
|
||||
<i>This option is only available, if the race is already finished.</i>
|
||||
</li>
|
||||
<li>Start analysis: Shows the race start 10 sec after start and shows the speed over ground (SOG) of
|
||||
the best starters within the competitor chart (zoomed to start).
|
||||
<i>This option is only available, if the race is already started.</i>
|
||||
</li>
|
||||
<li>Winning lanes: Shows the full lanes of the best competitor, if race is already finished or the of
|
||||
leading competitors if the race is currently live.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>The leaderboard now has a new measure value called "Ride height", which shows the ride height on
|
||||
foils of a competitor, if respective data is available (currently ESS only). This information can
|
||||
also be shown in the competitor chart on the RaceBaord page.
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.util.Set;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
/**
|
||||
* Manages a timer and can auto-advance it at a given acceleration/deceleration rate, with a given delay compared to
|
||||
@@ -392,5 +394,9 @@ public class Timer {
|
||||
public Date getLiveTimePointAsDate() {
|
||||
return new Date(getLiveTimePointInMillis());
|
||||
}
|
||||
|
||||
public TimePoint getLiveTimePoint() {
|
||||
return new MillisecondsTimePoint(getLiveTimePointInMillis());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# Patches to GWT Highcharts Wrapper API
|
||||
|
||||
## Show reset zoom button
|
||||
Added method to `org.moxieapps.gwt.highcharts.client.BaseChart` to provide highcharts functionality in Java API:
|
||||
```
|
||||
/**
|
||||
* Patch, to provide highcharts functionality in Java API.
|
||||
*/
|
||||
public native void showResetZoom() /*-{
|
||||
var chart = this.@org.moxieapps.gwt.highcharts.client.BaseChart::chart;
|
||||
if (chart) chart.showResetZoom();
|
||||
}-*/;
|
||||
```
|
||||
|
||||
## Other changes
|
||||
Some other change in the following classes are not documented yet:
|
||||
- `org.moxieapps.gwt.highcharts.client.BaseChart`
|
||||
- `org.moxieapps.gwt.highcharts.client.Series`
|
||||
+69
-10
@@ -16,22 +16,73 @@
|
||||
|
||||
package org.moxieapps.gwt.highcharts.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.moxieapps.gwt.highcharts.client.events.AxisSetExtremesEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartClickEventHandler;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartLoadEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartLoadEventHandler;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartRedrawEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartRedrawEventHandler;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEventHandler;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointLegendItemClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointMouseOutEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointMouseOverEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointRemoveEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointSelectEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointUnselectEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.PointUpdateEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesCheckboxClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesHideEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesLegendItemClickEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesMouseOutEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesMouseOverEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.SeriesShowEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.DataLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.LegendLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.StackLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.AreaPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.AreaRangePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.AreaSplinePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.AreaSplineRangePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.BarPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.BoxPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.BubblePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.CandlestickPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.ColumnPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.ColumnRangePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.ErrorBarPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.FunnelPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.GaugePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.Marker;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.OHLCPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.PiePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.PlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.ScatterPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.SeriesPlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.SplinePlotOptions;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.WaterfallPlotOptions;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.core.client.JsArray;
|
||||
import com.google.gwt.core.client.JsArrayString;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.dom.client.Document;
|
||||
import com.google.gwt.json.client.*;
|
||||
import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONBoolean;
|
||||
import com.google.gwt.json.client.JSONNull;
|
||||
import com.google.gwt.json.client.JSONNumber;
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.google.gwt.json.client.JSONString;
|
||||
import com.google.gwt.json.client.JSONValue;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import org.moxieapps.gwt.highcharts.client.events.*;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.DataLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.LegendLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.StackLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The common base class for both {@link Chart} types as well as {@link StockChart} types.
|
||||
@@ -2986,5 +3037,13 @@ public abstract class BaseChart<T> extends Widget {
|
||||
private static native void nativeSetTitle(JavaScriptObject chart, JavaScriptObject title, JavaScriptObject subTitle) /*-{
|
||||
chart.setTitle(title, subTitle);
|
||||
}-*/;
|
||||
|
||||
/**
|
||||
* Patch, to provide highcharts functionality in Java API.
|
||||
*/
|
||||
public native void showResetZoom() /*-{
|
||||
var chart = this.@org.moxieapps.gwt.highcharts.client.BaseChart::chart;
|
||||
if (chart) chart.showResetZoom();
|
||||
}-*/;
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user