mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 05:11:04 +00:00
Merge branch 'gwt' into xcelsius
This commit is contained in:
commit
f787a655df
20 files changed
+368
-61
No files matched your search
+2
-2
@@ -17,8 +17,8 @@ import com.google.gwt.user.client.ui.VerticalPanel;
|
|||||||
import com.google.gwt.user.client.ui.Widget;
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract data entry dialog class, capturing data of type <code>T</code>, with generic OK/Cancel buttons, title
|
* An abstract data entry dialog class, capturing data of type <code>T</code>, with generic OK/Cancel buttons, title and
|
||||||
* and message.
|
* message. Subclasses may override the {@link #show()} method to set the focus on their favorable initial entry field.
|
||||||
*
|
*
|
||||||
* @author Axel Uhl (d043530)
|
* @author Axel Uhl (d043530)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package com.sap.sailing.gwt.ui.client;
|
||||||
|
|
||||||
|
import com.google.gwt.cell.client.AbstractCell;
|
||||||
|
import com.google.gwt.cell.client.ActionCell;
|
||||||
|
import com.google.gwt.cell.client.ActionCell.Delegate;
|
||||||
|
import com.google.gwt.cell.client.ValueUpdater;
|
||||||
|
import com.google.gwt.dom.client.Element;
|
||||||
|
import com.google.gwt.dom.client.EventTarget;
|
||||||
|
import com.google.gwt.dom.client.NativeEvent;
|
||||||
|
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||||
|
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||||
|
|
||||||
|
public class ExpandCollapseButtonCell extends AbstractCell<SafeHtml> {
|
||||||
|
|
||||||
|
|
||||||
|
private final SafeHtml html;
|
||||||
|
private final Delegate<SafeHtml> delegate;
|
||||||
|
private final ExpandableSortableColumn<?> column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@link ActionCell}.
|
||||||
|
*
|
||||||
|
* @param message the message to display on the button
|
||||||
|
* @param delegate the delegate that will handle events
|
||||||
|
*/
|
||||||
|
public ExpandCollapseButtonCell(ExpandableSortableColumn<?> column, Delegate<SafeHtml> delegate) {
|
||||||
|
super("click", "keydown");
|
||||||
|
this.column = column;
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.html = new SafeHtmlBuilder().appendHtmlConstant(
|
||||||
|
"<input class=\"valignMiddle\" type=\"image\" src=\"/images/"+(column.isExpanded()?"minus":"plus")+".png\" />").toSafeHtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBrowserEvent(Context context, Element parent, SafeHtml value,
|
||||||
|
NativeEvent event, ValueUpdater<SafeHtml> valueUpdater) {
|
||||||
|
column.suppressSortingOnce();
|
||||||
|
super.onBrowserEvent(context, parent, value, event, valueUpdater);
|
||||||
|
if ("click".equals(event.getType())) {
|
||||||
|
EventTarget eventTarget = event.getEventTarget();
|
||||||
|
if (!Element.is(eventTarget)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
|
||||||
|
// Ignore clicks that occur outside of the main element.
|
||||||
|
onEnterKeyDown(context, parent, value, event, valueUpdater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(Context context, SafeHtml value, SafeHtmlBuilder sb) {
|
||||||
|
sb.append(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEnterKeyDown(Context context, Element parent, SafeHtml value,
|
||||||
|
NativeEvent event, ValueUpdater<SafeHtml> valueUpdater) {
|
||||||
|
delegate.execute(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -153,7 +153,7 @@ public abstract class ExpandableSortableColumn<C> extends SortableColumn<Leaderb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to ensure that all data necessary to display the expanded data of this column is actually loaded.
|
* Called to ensure that all data necessary to display the expanded data of this column is actually loaded.
|
||||||
* If this is not yet the case, an asynchronous call to the server may be required that subclasses have to
|
* If this is not yet the case, an asynchronous call to the server may be required that subclasses have to
|
||||||
|
|||||||
+65
-14
@@ -12,6 +12,7 @@ import com.google.gwt.cell.client.Cell;
|
|||||||
import com.google.gwt.cell.client.Cell.Context;
|
import com.google.gwt.cell.client.Cell.Context;
|
||||||
import com.google.gwt.cell.client.EditTextCell;
|
import com.google.gwt.cell.client.EditTextCell;
|
||||||
import com.google.gwt.cell.client.TextCell;
|
import com.google.gwt.cell.client.TextCell;
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.event.dom.client.ClickEvent;
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
import com.google.gwt.event.dom.client.ClickHandler;
|
import com.google.gwt.event.dom.client.ClickHandler;
|
||||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||||
@@ -24,8 +25,10 @@ import com.google.gwt.user.cellview.client.Header;
|
|||||||
import com.google.gwt.user.cellview.client.TextHeader;
|
import com.google.gwt.user.cellview.client.TextHeader;
|
||||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
import com.google.gwt.user.client.ui.Anchor;
|
import com.google.gwt.user.client.ui.Anchor;
|
||||||
import com.google.gwt.user.client.ui.Button;
|
import com.google.gwt.user.client.ui.DockPanel;
|
||||||
import com.google.gwt.user.client.ui.FormPanel;
|
import com.google.gwt.user.client.ui.FormPanel;
|
||||||
|
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||||
|
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||||
import com.google.gwt.user.client.ui.Label;
|
import com.google.gwt.user.client.ui.Label;
|
||||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||||
@@ -42,7 +45,7 @@ import com.sap.sailing.gwt.ui.shared.Pair;
|
|||||||
* @author Axel Uhl (D043530)
|
* @author Axel Uhl (D043530)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class LeaderboardPanel extends FormPanel {
|
public class LeaderboardPanel extends FormPanel implements LegDetailSelectionProvider {
|
||||||
private final SailingServiceAsync sailingService;
|
private final SailingServiceAsync sailingService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,6 +68,15 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
private LeaderboardDAO leaderboard;
|
private LeaderboardDAO leaderboard;
|
||||||
|
|
||||||
private final RankColumn rankColumn;
|
private final RankColumn rankColumn;
|
||||||
|
|
||||||
|
private final List<LegDetailSelectionProvider.LegDetailColumnType> selectedLegDetails;
|
||||||
|
|
||||||
|
public interface LeaderboardTableResources extends CellTable.Resources {
|
||||||
|
interface TableStyle extends CellTable.Style{}
|
||||||
|
@Override
|
||||||
|
@Source ({CellTable.Style.DEFAULT_CSS, "LeaderboardTable.css"})
|
||||||
|
TableStyle cellTableStyle();
|
||||||
|
}
|
||||||
|
|
||||||
private class CompetitorColumn extends SortableColumn<LeaderboardRowDAO, String> {
|
private class CompetitorColumn extends SortableColumn<LeaderboardRowDAO, String> {
|
||||||
|
|
||||||
@@ -168,7 +180,7 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
@Override
|
@Override
|
||||||
public Header<SafeHtml> getHeader() {
|
public Header<SafeHtml> getHeader() {
|
||||||
return new SortableExpandableColumnHeader(/* title */ raceName,
|
return new SortableExpandableColumnHeader(/* title */ raceName,
|
||||||
/* iconURL */ medalRace ? "/images/medal.png" : null,
|
/* iconURL */ medalRace ? "/images/medal_small.png" : null,
|
||||||
LeaderboardPanel.this, this, stringConstants);
|
LeaderboardPanel.this, this, stringConstants);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +222,7 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
int legCount = getLeaderboard().getLegCount(getRaceName());
|
int legCount = getLeaderboard().getLegCount(getRaceName());
|
||||||
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
|
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
|
||||||
for (int i=0; i<legCount; i++) {
|
for (int i=0; i<legCount; i++) {
|
||||||
result.add(new LegColumn(LeaderboardPanel.this, getRaceName(), /* legIndex */ i, stringConstants));
|
result.add(new LegColumn(LeaderboardPanel.this, getRaceName(), /* legIndex */ i, stringConstants, LeaderboardPanel.this));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -312,8 +324,13 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
this.setLeaderboardName(leaderboardName);
|
this.setLeaderboardName(leaderboardName);
|
||||||
this.errorReporter = errorReporter;
|
this.errorReporter = errorReporter;
|
||||||
this.stringConstants = stringConstants;
|
this.stringConstants = stringConstants;
|
||||||
|
this.selectedLegDetails = new ArrayList<LegDetailSelectionProvider.LegDetailColumnType>();
|
||||||
|
this.selectedLegDetails.add(LegDetailColumnType.DISTANCE_TRAVELED);
|
||||||
|
this.selectedLegDetails.add(LegDetailColumnType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
|
||||||
|
this.selectedLegDetails.add(LegDetailColumnType.RANK_GAIN);
|
||||||
rankColumn = new RankColumn();
|
rankColumn = new RankColumn();
|
||||||
leaderboardTable = new CellTable<LeaderboardRowDAO>(/* pageSize */ 100);
|
CellTable.Resources resources = GWT.create(LeaderboardTableResources.class);
|
||||||
|
leaderboardTable = new CellTable<LeaderboardRowDAO>(/* pageSize */ 100, resources);
|
||||||
getLeaderboardTable().setWidth("100%");
|
getLeaderboardTable().setWidth("100%");
|
||||||
getLeaderboardTable().setSelectionModel(new MultiSelectionModel<LeaderboardRowDAO>() {});
|
getLeaderboardTable().setSelectionModel(new MultiSelectionModel<LeaderboardRowDAO>() {});
|
||||||
setData(new ListDataProvider<LeaderboardRowDAO>());
|
setData(new ListDataProvider<LeaderboardRowDAO>());
|
||||||
@@ -322,21 +339,33 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
getLeaderboardTable().addColumnSortHandler(listHandler);
|
getLeaderboardTable().addColumnSortHandler(listHandler);
|
||||||
loadCompleteLeaderboard(getLeaderboardDisplayDate());
|
loadCompleteLeaderboard(getLeaderboardDisplayDate());
|
||||||
VerticalPanel vp = new VerticalPanel();
|
VerticalPanel vp = new VerticalPanel();
|
||||||
HorizontalPanel hp = new HorizontalPanel();
|
vp.setSpacing(15);
|
||||||
hp.setSpacing(10);
|
|
||||||
Anchor sapLogo = new Anchor(new SafeHtmlBuilder().appendHtmlConstant("<img class=\"linkNoBorder\" src=\"/images/sap_66_transparent.png\"/>").toSafeHtml());
|
Anchor sapLogo = new Anchor(new SafeHtmlBuilder().appendHtmlConstant("<img class=\"linkNoBorder\" src=\"/images/sap_66_transparent.png\"/>").toSafeHtml());
|
||||||
sapLogo.setHref("http://www.sap.com");
|
sapLogo.setHref("http://www.sap.com");
|
||||||
hp.add(sapLogo);
|
vp.add(sapLogo);
|
||||||
hp.add(new Label(leaderboardName));
|
DockPanel dockPanel = new DockPanel();
|
||||||
Button refreshButton = new Button(stringConstants.refresh());
|
dockPanel.setWidth("100%");
|
||||||
hp.add(refreshButton);
|
dockPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
|
||||||
refreshButton.addClickHandler(new ClickHandler() {
|
Label leaderboardLabel = new Label(stringConstants.leaderboard()+" "+leaderboardName.toUpperCase());
|
||||||
|
leaderboardLabel.addStyleName("boldLabel");
|
||||||
|
dockPanel.add(leaderboardLabel, DockPanel.WEST);
|
||||||
|
ClickHandler refreshHandler = new ClickHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(ClickEvent event) {
|
public void onClick(ClickEvent event) {
|
||||||
loadCompleteLeaderboard(getLeaderboardDisplayDate());
|
loadCompleteLeaderboard(getLeaderboardDisplayDate());
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
vp.add(hp);
|
HorizontalPanel refreshPanel = new HorizontalPanel();
|
||||||
|
Anchor refresh = new Anchor(new SafeHtmlBuilder().appendHtmlConstant(stringConstants.refresh()).toSafeHtml());
|
||||||
|
refresh.addStyleName("boldAnchor");
|
||||||
|
dockPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
|
||||||
|
Anchor refreshLogo = new Anchor(new SafeHtmlBuilder().appendHtmlConstant("<img class=\"linkNoBorder\" src=\"/images/refresh_with_right_border.png\"/>").toSafeHtml());
|
||||||
|
refreshLogo.addClickHandler(refreshHandler);
|
||||||
|
refreshPanel.add(refreshLogo);
|
||||||
|
refreshPanel.add(refresh);
|
||||||
|
dockPanel.add(refreshPanel, DockPanel.EAST);
|
||||||
|
refresh.addClickHandler(refreshHandler);
|
||||||
|
vp.add(dockPanel);
|
||||||
vp.add(getLeaderboardTable());
|
vp.add(getLeaderboardTable());
|
||||||
setWidget(vp);
|
setWidget(vp);
|
||||||
}
|
}
|
||||||
@@ -582,4 +611,26 @@ public class LeaderboardPanel extends FormPanel {
|
|||||||
private void setData(ListDataProvider<LeaderboardRowDAO> data) {
|
private void setData(ListDataProvider<LeaderboardRowDAO> data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LegDetailColumnType> getLegDetailsToShow() {
|
||||||
|
return Collections.unmodifiableList(selectedLegDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After the leg detail selection has changed, updates the headers accordingly. This implementation
|
||||||
|
* chooses to collapse all expanded race columns and then expand them again (see {@link #toggleExpansion()}).
|
||||||
|
* This will re-establish their expansion structure while updating the leg detail columns accordingly.
|
||||||
|
*/
|
||||||
|
private void refreshHeaders() {
|
||||||
|
for (int i=0; i<getLeaderboardTable().getColumnCount(); i++) {
|
||||||
|
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(i);
|
||||||
|
if (c instanceof ExpandableSortableColumn<?> &&
|
||||||
|
((ExpandableSortableColumn<?>) c).isExpanded()) {
|
||||||
|
((ExpandableSortableColumn<?>) c).toggleExpansion();
|
||||||
|
((ExpandableSortableColumn<?>) c).toggleExpansion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Executable
+91
@@ -0,0 +1,91 @@
|
|||||||
|
.cellTableWidget {
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** v-align images in the table header
|
||||||
|
* grey background for table header
|
||||||
|
*/
|
||||||
|
.cellTableHeader {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
border-left: 1px solid #ffffff !important;
|
||||||
|
border-right: 1px solid #ffffff !important;
|
||||||
|
border-top: none !important;
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableFirstColumnHeader {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
border-left: none !important;
|
||||||
|
border-right: 1px solid #ffffff !important;
|
||||||
|
border-top: none !important;
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableLastColumnHeader {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
border-left: 1px solid #ffffff !important;
|
||||||
|
border-right: none !important;
|
||||||
|
border-top: none !important;
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableHeader > span > img:first-child {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableOddRow {
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableOddRowCell {
|
||||||
|
border-right: none;
|
||||||
|
border-left: none;
|
||||||
|
padding: 5px 5px 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableEvenRow {
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableEvenRowCell {
|
||||||
|
border-left: none !important;
|
||||||
|
border-right: none !important;
|
||||||
|
padding: 5px 5px 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableHoveredRow {
|
||||||
|
background-color: #e5f2f9;
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableSelectedRow {
|
||||||
|
color: #000000;
|
||||||
|
background-color: #e5f2f9;
|
||||||
|
border-right: 2px solid #21a0e4 !important;
|
||||||
|
border-left: 2px solid #21a0e4 !important;
|
||||||
|
border: 2px solid #21a0e4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableSelectedRow > td:FIRST-CHILD {
|
||||||
|
border-left: 2px solid #21a0e4 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableSelectedRow > td:LAST-CHILD {
|
||||||
|
border-right: 2px solid #21a0e4 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellTableSelectedRowCell {
|
||||||
|
boder-left: none;
|
||||||
|
boder-right: none;
|
||||||
|
border-top: 2px solid #21a0e4;
|
||||||
|
border-bottom: 2px solid #21a0e4;
|
||||||
|
}
|
||||||
+18
-4
@@ -8,6 +8,7 @@ import com.google.gwt.cell.client.TextCell;
|
|||||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||||
import com.google.gwt.user.cellview.client.Header;
|
import com.google.gwt.user.cellview.client.Header;
|
||||||
import com.sap.sailing.gwt.ui.client.LegDetailColumn.LegDetailField;
|
import com.sap.sailing.gwt.ui.client.LegDetailColumn.LegDetailField;
|
||||||
|
import com.sap.sailing.gwt.ui.client.LegDetailSelectionProvider.LegDetailColumnType;
|
||||||
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDAO;
|
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDAO;
|
||||||
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDAO;
|
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDAO;
|
||||||
import com.sap.sailing.gwt.ui.shared.LegEntryDAO;
|
import com.sap.sailing.gwt.ui.shared.LegEntryDAO;
|
||||||
@@ -23,6 +24,7 @@ public class LegColumn extends ExpandableSortableColumn<String> {
|
|||||||
private final String raceName;
|
private final String raceName;
|
||||||
private final int legIndex;
|
private final int legIndex;
|
||||||
private final StringConstants stringConstants;
|
private final StringConstants stringConstants;
|
||||||
|
private final LegDetailSelectionProvider legDetailSelectionProvider;
|
||||||
|
|
||||||
private abstract class AbstractLegDetailField<T> implements LegDetailField<T> {
|
private abstract class AbstractLegDetailField<T> implements LegDetailField<T> {
|
||||||
public T get(LeaderboardRowDAO row) {
|
public T get(LeaderboardRowDAO row) {
|
||||||
@@ -65,12 +67,14 @@ public class LegColumn extends ExpandableSortableColumn<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LegColumn(LeaderboardPanel leaderboardPanel, String raceName, int legIndex, StringConstants stringConstants) {
|
public LegColumn(LeaderboardPanel leaderboardPanel, String raceName, int legIndex, StringConstants stringConstants,
|
||||||
|
LegDetailSelectionProvider legDetailSelectionProvider) {
|
||||||
super(leaderboardPanel, /* expandable */ true /* all legs have details */, new TextCell());
|
super(leaderboardPanel, /* expandable */ true /* all legs have details */, new TextCell());
|
||||||
setHorizontalAlignment(ALIGN_RIGHT);
|
setHorizontalAlignment(ALIGN_RIGHT);
|
||||||
this.raceName = raceName;
|
this.raceName = raceName;
|
||||||
this.legIndex = legIndex;
|
this.legIndex = legIndex;
|
||||||
this.stringConstants = stringConstants;
|
this.stringConstants = stringConstants;
|
||||||
|
this.legDetailSelectionProvider = legDetailSelectionProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getLegIndex() {
|
private int getLegIndex() {
|
||||||
@@ -129,9 +133,19 @@ public class LegColumn extends ExpandableSortableColumn<String> {
|
|||||||
protected List<SortableColumn<LeaderboardRowDAO, ?>> createExpansionColumns() {
|
protected List<SortableColumn<LeaderboardRowDAO, ?>> createExpansionColumns() {
|
||||||
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
|
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
|
||||||
try {
|
try {
|
||||||
result.add(new FormattedDoubleLegDetailColumn(stringConstants.distanceInMeters(), new DistanceTraveledInMeters(), 1, getLeaderboardPanel().getLeaderboardTable()));
|
for (LegDetailColumnType type : legDetailSelectionProvider.getLegDetailsToShow()) {
|
||||||
result.add(new FormattedDoubleLegDetailColumn(stringConstants.averageSpeedInKnots(), new AverageSpeedOverGroundInKnots(), 2, getLeaderboardPanel().getLeaderboardTable()));
|
switch (type) {
|
||||||
result.add(new RankGainColumn(stringConstants.rankGain(), new RankGain(), getLeaderboardPanel().getLeaderboardTable()));
|
case DISTANCE_TRAVELED:
|
||||||
|
result.add(new FormattedDoubleLegDetailColumn(stringConstants.distanceInMeters(), new DistanceTraveledInMeters(), 1, getLeaderboardPanel().getLeaderboardTable()));
|
||||||
|
break;
|
||||||
|
case AVERAGE_SPEED_OVER_GROUND_IN_KNOTS:
|
||||||
|
result.add(new FormattedDoubleLegDetailColumn(stringConstants.averageSpeedInKnots(), new AverageSpeedOverGroundInKnots(), 2, getLeaderboardPanel().getLeaderboardTable()));
|
||||||
|
break;
|
||||||
|
case RANK_GAIN:
|
||||||
|
result.add(new RankGainColumn(stringConstants.rankGain(), new RankGain(), getLeaderboardPanel().getLeaderboardTable()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|||||||
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LegDetailSelectionPanel.java
Executable
+49
@@ -0,0 +1,49 @@
|
|||||||
|
package com.sap.sailing.gwt.ui.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
import com.google.gwt.user.client.ui.CheckBox;
|
||||||
|
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||||
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
import com.sap.sailing.gwt.ui.client.LegDetailSelectionProvider.LegDetailColumnType;
|
||||||
|
|
||||||
|
public class LegDetailSelectionPanel extends DataEntryDialog<List<LegDetailColumnType>> {
|
||||||
|
private final LegDetailSelectionProvider selectionProvider;
|
||||||
|
private final Map<LegDetailColumnType, CheckBox> checkboxes;
|
||||||
|
|
||||||
|
public LegDetailSelectionPanel(LegDetailSelectionProvider selectionProvider, String title,
|
||||||
|
String message, String okButtonName, String cancelButtonName,
|
||||||
|
com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator<List<LegDetailColumnType>> validator,
|
||||||
|
AsyncCallback<List<LegDetailColumnType>> callback) {
|
||||||
|
super(title, message, okButtonName, cancelButtonName, validator, callback);
|
||||||
|
this.selectionProvider = selectionProvider;
|
||||||
|
checkboxes = new HashMap<LegDetailSelectionProvider.LegDetailColumnType, CheckBox>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Widget getAdditionalWidget() {
|
||||||
|
List<LegDetailColumnType> currentSelection = selectionProvider.getLegDetailsToShow();
|
||||||
|
VerticalPanel vp = new VerticalPanel();
|
||||||
|
for (LegDetailColumnType type : LegDetailColumnType.values()) {
|
||||||
|
CheckBox checkbox = new CheckBox(type.toString(), currentSelection.contains(type));
|
||||||
|
checkboxes.put(type, checkbox);
|
||||||
|
vp.add(checkbox);
|
||||||
|
}
|
||||||
|
return vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<LegDetailColumnType> getResult() {
|
||||||
|
List<LegDetailColumnType> result = new ArrayList<LegDetailSelectionProvider.LegDetailColumnType>();
|
||||||
|
for (Map.Entry<LegDetailColumnType, CheckBox> entry : checkboxes.entrySet()) {
|
||||||
|
if (entry.getValue().getValue()) {
|
||||||
|
result.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package com.sap.sailing.gwt.ui.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user may select a set of detail columns to be displayed when a leg column is expanded.
|
||||||
|
* An instance of a class implementing this interface can tell which column types are requested
|
||||||
|
* to be displayed.
|
||||||
|
*
|
||||||
|
* @author Axel Uhl (D043530)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface LegDetailSelectionProvider {
|
||||||
|
static enum LegDetailColumnType {
|
||||||
|
DISTANCE_TRAVELED, AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RANK_GAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LegDetailColumnType> getLegDetailsToShow();
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package com.sap.sailing.gwt.ui.client;
|
||||||
|
|
||||||
|
public interface ModifiableLegDetailSelectionProvider extends LegDetailSelectionProvider {
|
||||||
|
void select(LegDetailColumnType type);
|
||||||
|
void deselect(LegDetailColumnType type);
|
||||||
|
}
|
||||||
+20
-32
@@ -48,6 +48,25 @@ public class SortableExpandableColumnHeader extends Header<SafeHtml> {
|
|||||||
private static <T> Cell<SafeHtml> constructCell(final String title, final String iconURL, boolean isExpansionEnabled,
|
private static <T> Cell<SafeHtml> constructCell(final String title, final String iconURL, boolean isExpansionEnabled,
|
||||||
final LeaderboardPanel leaderboardPanel, final ExpandableSortableColumn<?> column, final StringConstants stringConstants) {
|
final LeaderboardPanel leaderboardPanel, final ExpandableSortableColumn<?> column, final StringConstants stringConstants) {
|
||||||
final List<HasCell<SafeHtml, ?>> cells = new ArrayList<HasCell<SafeHtml, ?>>(3);
|
final List<HasCell<SafeHtml, ?>> cells = new ArrayList<HasCell<SafeHtml, ?>>(3);
|
||||||
|
// add the cell rendering the expand/collapse button:
|
||||||
|
if (isExpansionEnabled) {
|
||||||
|
cells.add(new HasCell<SafeHtml, SafeHtml>() {
|
||||||
|
@Override
|
||||||
|
public Cell<SafeHtml> getCell() {
|
||||||
|
return new ExpandCollapseButtonCell(column, new ExpandCollapseButtonAction(column));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldUpdater<SafeHtml, SafeHtml> getFieldUpdater() {
|
||||||
|
return null; // no updates possible in a header cell
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SafeHtml getValue(SafeHtml object) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// if it's a medal race, add the cell rendering the medal image
|
// if it's a medal race, add the cell rendering the medal image
|
||||||
if (iconURL != null) {
|
if (iconURL != null) {
|
||||||
cells.add(new HasCell<SafeHtml, String>() {
|
cells.add(new HasCell<SafeHtml, String>() {
|
||||||
@@ -79,40 +98,9 @@ public class SortableExpandableColumnHeader extends Header<SafeHtml> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public SafeHtml getValue(SafeHtml object) {
|
public SafeHtml getValue(SafeHtml object) {
|
||||||
return new SafeHtmlBuilder().appendEscaped(title).toSafeHtml();
|
return new SafeHtmlBuilder().appendHtmlConstant(" ").appendEscaped(title).toSafeHtml();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// add the cell rendering the expand/collapse button:
|
|
||||||
if (isExpansionEnabled) {
|
|
||||||
cells.add(new HasCell<SafeHtml, SafeHtml>() {
|
|
||||||
@Override
|
|
||||||
public Cell<SafeHtml> getCell() {
|
|
||||||
return new ActionCell<SafeHtml>(column.isExpanded() ? stringConstants.collapse() : stringConstants.expand(),
|
|
||||||
new ExpandCollapseButtonAction(column)) {
|
|
||||||
/**
|
|
||||||
* carry out event logic, hence call the delegate's execute(...) operation, then stop
|
|
||||||
* propagation to avoid the column being sorted when the expand button is pressed
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onBrowserEvent(Context context, Element parent, SafeHtml value, NativeEvent event,
|
|
||||||
ValueUpdater<SafeHtml> valueUpdater) {
|
|
||||||
column.suppressSortingOnce();
|
|
||||||
super.onBrowserEvent(context, parent, value, event, valueUpdater);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FieldUpdater<SafeHtml, SafeHtml> getFieldUpdater() {
|
|
||||||
return null; // no updates possible in a header cell
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SafeHtml getValue(SafeHtml object) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return new CompositeCell<SafeHtml>(cells) {
|
return new CompositeCell<SafeHtml>(cells) {
|
||||||
/**
|
/**
|
||||||
* Redefining this method because when a table column is sorted, GWT wraps a div element
|
* Redefining this method because when a table column is sorted, GWT wraps a div element
|
||||||
|
|||||||
+1
@@ -66,4 +66,5 @@ public interface StringConstants extends Constants {
|
|||||||
String averageSpeedInKnots();
|
String averageSpeedInKnots();
|
||||||
String rankGain();
|
String rankGain();
|
||||||
String sapSailingAnalytics();
|
String sapSailingAnalytics();
|
||||||
|
String leaderboard();
|
||||||
}
|
}
|
||||||
+3
-2
@@ -22,7 +22,7 @@ delayHelp=Leave empty to replay at arbitrary times; enter seconds (e.g., "60" fo
|
|||||||
speedInKnots=Speed (kn)
|
speedInKnots=Speed (kn)
|
||||||
fromDeg=From (deg)
|
fromDeg=From (deg)
|
||||||
noRacesYet=No Races Yet
|
noRacesYet=No Races Yet
|
||||||
total=Total
|
total=\u03A3
|
||||||
carry=Accumulated
|
carry=Accumulated
|
||||||
competitor=Competitor
|
competitor=Competitor
|
||||||
defaultLeaderboard=Default Leaderboard
|
defaultLeaderboard=Default Leaderboard
|
||||||
@@ -60,4 +60,5 @@ leg=Leg
|
|||||||
distanceInMeters=Distance/m
|
distanceInMeters=Distance/m
|
||||||
averageSpeedInKnots=Average Speed/kts
|
averageSpeedInKnots=Average Speed/kts
|
||||||
rankGain=Rank Gain
|
rankGain=Rank Gain
|
||||||
sapSailingAnalytics=SAP Sailing Analytics
|
sapSailingAnalytics=SAP Sailing Analytics
|
||||||
|
leaderboard=LEADERBOARD
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
/** Add css rules here for your application. */
|
/** Add css rules here for your application. */
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-family: Arial;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Example rules used by the template application (remove for your app) */
|
/** Example rules used by the template application (remove for your app) */
|
||||||
h1 {
|
h1 {
|
||||||
@@ -44,3 +49,23 @@ h1 {
|
|||||||
.linkNoBorder {
|
.linkNoBorder {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.refreshLink {
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valignMiddle {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boldLabel {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boldAnchor {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
@@ -9,11 +9,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
|
||||||
<!-- -->
|
|
||||||
<!-- Consider inlining CSS to reduce the number of requested files -->
|
|
||||||
<!-- -->
|
|
||||||
<link type="text/css" rel="stylesheet" href="Leaderboard.css">
|
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Any title is fine -->
|
<!-- Any title is fine -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -25,6 +20,12 @@
|
|||||||
<!-- be added before this line. -->
|
<!-- be added before this line. -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.Leaderboard/com.sap.sailing.gwt.ui.Leaderboard.nocache.js"></script>
|
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.Leaderboard/com.sap.sailing.gwt.ui.Leaderboard.nocache.js"></script>
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
<!-- Consider inlining CSS to reduce the number of requested files -->
|
||||||
|
<!-- -->
|
||||||
|
<link type="text/css" rel="stylesheet" href="Leaderboard.css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 906 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 971 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 980 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -24,5 +24,5 @@
|
|||||||
<booleanAttribute key="tracing" value="false"/>
|
<booleanAttribute key="tracing" value="false"/>
|
||||||
<booleanAttribute key="useCustomFeatures" value="false"/>
|
<booleanAttribute key="useCustomFeatures" value="false"/>
|
||||||
<booleanAttribute key="useDefaultConfigArea" value="false"/>
|
<booleanAttribute key="useDefaultConfigArea" value="false"/>
|
||||||
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils.test@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination.test@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb.test@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.server.test@default:default,com.sap.sailing.server@default:default,com.sap.ui.phoenix.resource-osgi@default:false,com.sap.ui.phoenix.resource-servlet@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default"/>
|
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils.test@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination.test@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.swisstimingadapter.test@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb.test@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.server.test@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.ui.phoenix.resource-osgi@default:false,com.sap.ui.phoenix.resource-servlet@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
Reference in new issue
Block a user