diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigator.java index 5d082e74c68..246f81a8305 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigator.java @@ -2,5 +2,5 @@ package com.sap.sailing.gwt.autoplay.client.app; public interface PlaceNavigator { void goToStart(); - void goToPlayer(String eventUuidAsString, String leaderboardIdAsNameString); + void goToPlayer(String eventUuidAsString, String leaderboardIdAsNameString, String leaderboardZoom); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigatorImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigatorImpl.java index 34df61ac363..69b512a8328 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigatorImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/PlaceNavigatorImpl.java @@ -18,8 +18,8 @@ public class PlaceNavigatorImpl implements PlaceNavigator { } @Override - public void goToPlayer(String eventUuidAsString, String leaderboardIdAsNameString) { - PlayerPlace playerPlace = new PlayerPlace(eventUuidAsString, leaderboardIdAsNameString); + public void goToPlayer(String eventUuidAsString, String leaderboardIdAsNameString, String leaderboardZoom) { + PlayerPlace playerPlace = new PlayerPlace(eventUuidAsString, leaderboardIdAsNameString, String.valueOf(leaderboardZoom)); placeController.goTo(playerPlace); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java index 2ddc9370f22..aefe9d6055c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java @@ -6,15 +6,23 @@ import java.util.Date; import java.util.List; import java.util.Map; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.dom.client.Style.FontWeight; +import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.TextAlign; +import com.google.gwt.event.logical.shared.ResizeEvent; +import com.google.gwt.event.logical.shared.ResizeHandler; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.gwt.autoplay.client.shared.header.SAPHeader; +import com.sap.sailing.gwt.common.client.CSS3Util; import com.sap.sailing.gwt.common.client.i18n.TextMessages; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.ErrorReporter; @@ -57,6 +65,7 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { private LeaderboardDTO leaderboard; private final String leaderboardName; private final String leaderboardGroupName; + private final String leaderboardZoom; private LeaderboardSettings leaderboardSettings; // raceboard related attributes @@ -65,15 +74,18 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { private boolean showWindChart; private final RaceBoardViewConfiguration raceboardViewConfig; private final PlayerView playerView; + private final int SAP_HEADER_HEIGHT = 80; + private Widget currentContentWidget; public AutoPlayController(SailingServiceAsync sailingService, MediaServiceAsync mediaService, - ErrorReporter errorReporter, String leaderboardGroupName, String leaderboardName, UserAgentDetails userAgent, + ErrorReporter errorReporter, String leaderboardGroupName, String leaderboardName, final String leaderboardZoom, UserAgentDetails userAgent, long delayToLiveInMillis, boolean showRaceDetails, RaceBoardViewConfiguration raceboardViewConfig, PlayerView playerView) { this.raceboardViewConfig = raceboardViewConfig; this.sailingService = sailingService; this.mediaService = mediaService; this.errorReporter = errorReporter; this.leaderboardName = leaderboardName; + this.leaderboardZoom = leaderboardZoom; this.leaderboardGroupName = leaderboardGroupName; this.userAgent = userAgent; this.showRaceDetails = showRaceDetails; @@ -95,6 +107,15 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, errorReporter, new ArrayList(), 3000l); raceTimesInfoProvider.addRaceTimesInfoProviderListener(this); + + Window.addResizeHandler(new ResizeHandler() { + @Override + public void onResize(ResizeEvent event) { + if(leaderboardZoom != null && leaderboardZoom.equalsIgnoreCase("auto")) { + autoZoomContentWidget(); + } + } + }); } private LeaderboardPanel createLeaderboardPanel(String leaderboardGroupName, String leaderboardName, boolean showRaceDetails) { @@ -112,7 +133,8 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { updateRaceTimesInfoProvider(); } }; - leaderboardPanel.getContentWidget().getElement().getStyle().setProperty("margin", "0 auto"); +// leaderboardPanel.getContentWidget().getElement().getStyle().setProperty("margin", "0 auto"); + leaderboardPanel.getContentWidget().getElement().getStyle().setPosition(Position.ABSOLUTE); leaderboardPanel.getContentWidget().getElement().getStyle().setFontWeight(FontWeight.BOLD); return leaderboardPanel; } @@ -148,10 +170,26 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { playerView.clearDockPanel(); SAPHeader sapHeader = new SAPHeader(TextMessages.INSTANCE.leaderboard() + ": " + leaderboardName); - playerView.getDockPanel().addNorth(sapHeader, 80); + playerView.getDockPanel().addNorth(sapHeader, SAP_HEADER_HEIGHT); LeaderboardPanel leaderboardPanel = createLeaderboardPanel(leaderboardGroupName, leaderboardName, showRaceDetails); ScrollPanel leaderboardContentPanel = new ScrollPanel(); + + currentContentWidget = leaderboardPanel.getContentWidget(); + + if(leaderboardZoom != null) { + if(leaderboardZoom.equalsIgnoreCase("auto")) { + autoZoomContentWidget(); + } else { + try { + Double zoom = Double.valueOf(leaderboardZoom); + scaleContentWidget(SAP_HEADER_HEIGHT, currentContentWidget, zoom); + } catch (NumberFormatException e) { + // do nothing + } + } + } + leaderboardContentPanel.getElement().getStyle().setTextAlign(TextAlign.CENTER); leaderboardContentPanel.add(leaderboardPanel); playerView.getDockPanel().add(leaderboardContentPanel); @@ -161,7 +199,55 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { leaderboardTimer.setPlayMode(PlayModes.Live); } } + + private void autoZoomContentWidget() { + if(currentContentWidget != null) { + Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() { + public boolean execute () { + boolean invokeAgain = true; + if(currentContentWidget.getOffsetHeight() > 10) { + scaleContentWidget(SAP_HEADER_HEIGHT, currentContentWidget); + invokeAgain = false; + } + return invokeAgain; + } + }, 1000); + } + } + + private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor, double diffX) { + if(scaleFactor > 0.0) { + CSS3Util.setProperty(contentWidget.getElement().getStyle(), + "transform", "translateX(" + diffX / 2.0 + "px) scale(" + scaleFactor + ")"); + CSS3Util.setProperty(contentWidget.getElement().getStyle(), "transformOrigin", "0 0"); + } + } + + private void scaleContentWidget(int headerHeight, Widget contentWidget, double scaleFactor) { + int clientWidth = Window.getClientWidth(); + int contentWidth = contentWidget.getOffsetWidth(); + + double diffX = clientWidth - contentWidth * scaleFactor; + + scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX); + } + private void scaleContentWidget(int headerHeight, Widget contentWidget) { + int clientWidth = Window.getClientWidth(); + int clientHeight = Window.getClientHeight() - headerHeight; + + int contentWidth = contentWidget.getOffsetWidth(); + int contentHeight = contentWidget.getOffsetHeight(); + + double scaleFactorX = clientWidth / (double) contentWidth; + double scaleFactorY = clientHeight / (double) contentHeight; + + Double scaleFactor = scaleFactorX > scaleFactorY ? scaleFactorY : scaleFactorX; + double diffX = clientWidth - contentWidth * scaleFactor; + + scaleContentWidget(headerHeight, contentWidget, scaleFactor, diffX); + } + private void showRaceBoard() { if (activeTvView != AutoPlayModes.Raceboard) { playerView.clearDockPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerActivity.java index cb9140f48f2..c409e36bd88 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerActivity.java @@ -45,8 +45,8 @@ public class PlayerActivity extends AbstractActivity implements ErrorReporter { panel.setWidget(view.asWidget()); autoPlayController = new AutoPlayController(clientFactory.getSailingService(), clientFactory.getMediaService(), - PlayerActivity.this, /*leaderboardGroupName*/ "" , playerPlace.getLeaderboardIdAsNameString(), userAgent, delayToLiveMillis, - showRaceDetails, readRaceboardConfiguration, view); + PlayerActivity.this, /*leaderboardGroupName*/ "" , playerPlace.getLeaderboardIdAsNameString(), playerPlace.getLeaderboardZoomAsString(), + userAgent, delayToLiveMillis, showRaceDetails, readRaceboardConfiguration, view); autoPlayController.updatePlayMode(AutoPlayModes.Leaderboard); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerPlace.java index cd3d46d17ef..ecf03b2d1ce 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/PlayerPlace.java @@ -6,20 +6,24 @@ import com.sap.sailing.gwt.common.client.AbstractBasePlace; public class PlayerPlace extends AbstractBasePlace { private final String eventUuidAsString; private final String leaderboardIdAsNameString; + private final String leaderboardZoomAsString; private final static String PARAM_EVENTID = "eventId"; private final static String PARAM_LEADEROARD_NAME = "leaderboardName"; + private final static String PARAM_LEADEROARD_ZOOM = "leaderboardZoom"; public PlayerPlace(String url) { super(url); eventUuidAsString = getParameter(PARAM_EVENTID); leaderboardIdAsNameString = getParameter(PARAM_LEADEROARD_NAME); + leaderboardZoomAsString = getParameter(PARAM_LEADEROARD_ZOOM); } - public PlayerPlace(String eventUuidAsString, String leaderboardIdAsNameString) { - super(PARAM_EVENTID, eventUuidAsString, PARAM_LEADEROARD_NAME, leaderboardIdAsNameString); + public PlayerPlace(String eventUuidAsString, String leaderboardIdAsNameString, String leaderboardZoomAsString) { + super(PARAM_EVENTID, eventUuidAsString, PARAM_LEADEROARD_NAME, leaderboardIdAsNameString, PARAM_LEADEROARD_ZOOM, leaderboardZoomAsString); this.eventUuidAsString = eventUuidAsString; this.leaderboardIdAsNameString = leaderboardIdAsNameString; + this.leaderboardZoomAsString = leaderboardZoomAsString; } public String getEventUuidAsString() { @@ -30,6 +34,10 @@ public class PlayerPlace extends AbstractBasePlace { return leaderboardIdAsNameString; } + public String getLeaderboardZoomAsString() { + return leaderboardZoomAsString; + } + public static class Tokenizer implements PlaceTokenizer { @Override public String getToken(PlayerPlace place) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.java index b2f524e3594..46bcc4bce1d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.java @@ -8,12 +8,15 @@ import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.autoplay.client.app.PlaceNavigator; import com.sap.sailing.gwt.common.client.SharedResources; @@ -29,8 +32,12 @@ public class DesktopStartView extends Composite implements StartView { @UiField(provided=true) ListBox eventSelectionBox; @UiField(provided=true) ListBox leaderboardSelectionBox; + @UiField CheckBox leaderboardAutoZoomBox; + @UiField TextBox leaderboardZoomBox; @UiField Button startAutoPlayButton; @UiField DivElement leaderboardSelectionDiv; + @UiField DivElement leaderboardZoomDiv; + @UiField DivElement leaderboardAutoZoomDiv; private final PlaceNavigator navigator; private final List events; @@ -44,7 +51,10 @@ public class DesktopStartView extends Composite implements StartView { leaderboardSelectionBox = new ListBox(false); initWidget(uiBinder.createAndBindUi(this)); - + + leaderboardAutoZoomBox.setValue(true); + leaderboardZoomBox.setEnabled(false); + leaderboardSelectionDiv.getStyle().setVisibility(Visibility.HIDDEN); startAutoPlayButton.setEnabled(false); startAutoPlayButton.addStyleName(SharedResources.INSTANCE.mainCss().buttoninactive()); @@ -92,11 +102,21 @@ public class DesktopStartView extends Composite implements StartView { void startAutoPlayClicked(ClickEvent event) { EventDTO selectedEvent = getSelectedEvent(); String selectedLeaderboardName = getSelectedLeaderboardName(); + String leaderboardZoom = getLeaderboardZoom(); if(selectedEvent != null && selectedLeaderboardName != null) { - navigator.goToPlayer(selectedEvent.id.toString(), selectedLeaderboardName); + navigator.goToPlayer(selectedEvent.id.toString(), selectedLeaderboardName, leaderboardZoom); } } + @UiHandler("leaderboardAutoZoomBox") + public void onLeaderboardAutoZoomClicked(ValueChangeEvent ev) { + leaderboardZoomBox.setEnabled(!leaderboardAutoZoomBox.getValue()); + } + + private String getLeaderboardZoom() { + return leaderboardAutoZoomBox.getValue() == true ? "auto" : String.valueOf(leaderboardZoomBox.getValue()); + } + private String getSelectedLeaderboardName() { String result = null; int selectedIndex = leaderboardSelectionBox.getSelectedIndex(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.ui.xml index c424e8a7a8d..be6ee10b254 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/start/DesktopStartView.ui.xml @@ -27,6 +27,22 @@ +
+
+ Leaderboard Auto-Zoom: +
+
+ +
+
+
+
+ Leaderboard Zoom-Factor: +
+
+ +
+
  diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/CSS3Util.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/CSS3Util.java new file mode 100644 index 00000000000..b90e0bf3f92 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/CSS3Util.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.common.client; + +import com.google.gwt.dom.client.Style; + +public class CSS3Util { + public static void setProperty(Style style, String baseCamelCasePropertyName, String value) { + for (String browserTypePrefix : getBrowserTypePrefixes()) { + style.setProperty(getBrowserSpecificPropertyName(browserTypePrefix, baseCamelCasePropertyName), value); + } + } + + public static void setDashedProperty(Style style, String baseCamelCasePropertyName, String value) { + for (String browserTypePrefix : getBrowserTypePrefixes()) { + style.setProperty(getBrowserSpecificDashedPropertyName(browserTypePrefix, baseCamelCasePropertyName), value); + } + } + + /** + * @return the prefixes required for new CSS3-style elements such as "transition" or "@keyframe", including the + * empty string, "moz" and "webkit" as well as others + */ + private static String[] getBrowserTypePrefixes() { + return new String[] { "", /* Firefox */ "moz", /* IE */ "ms", /* Opera */ "o", /* Chrome and Mobile */ "webkit" }; + } + + /** + * Converts something like "transformOrigin" to "-browserType-transform-origin" + * + * @param browserType + * a browser type string as received from {@link #getBrowserTypePrefixes()}. If empty or null, the + * original property name is returned unchanged + * @param camelCaseString + * the original camel-cased property name, such as "transformOrigin" + */ + public static String getBrowserSpecificDashedPropertyName(String browserType, String camelCaseString) { + StringBuilder result = new StringBuilder(); + if (browserType != null && !browserType.isEmpty()) { + result.append('-'); + result.append(browserType); + result.append('-'); + } + for (int i=0; i