Merge branch 'gwt' into xcelsius

This commit is contained in:
Axel Uhl committed 2011-09-19 21:08:49 +02:00
commit f787a655df
19 files changed
+363 -56

No files matched your search

@@ -17,8 +17,8 @@ import com.google.gwt.user.client.ui.VerticalPanel;
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
* and message.
* An abstract data entry dialog class, capturing data of type <code>T</code>, with generic OK/Cancel buttons, title and
* message. Subclasses may override the {@link #show()} method to set the focus on their favorable initial entry field.
*
* @author Axel Uhl (d043530)
*/
@@ -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);
}
}
@@ -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.EditTextCell;
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.ClickHandler;
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.client.rpc.AsyncCallback;
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.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
@@ -42,7 +45,7 @@ import com.sap.sailing.gwt.ui.shared.Pair;
* @author Axel Uhl (D043530)
*
*/
public class LeaderboardPanel extends FormPanel {
public class LeaderboardPanel extends FormPanel implements LegDetailSelectionProvider {
private final SailingServiceAsync sailingService;
/**
@@ -66,6 +69,15 @@ public class LeaderboardPanel extends FormPanel {
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> {
protected CompetitorColumn() {
@@ -168,7 +180,7 @@ public class LeaderboardPanel extends FormPanel {
@Override
public Header<SafeHtml> getHeader() {
return new SortableExpandableColumnHeader(/* title */ raceName,
/* iconURL */ medalRace ? "/images/medal.png" : null,
/* iconURL */ medalRace ? "/images/medal_small.png" : null,
LeaderboardPanel.this, this, stringConstants);
}
}
@@ -210,7 +222,7 @@ public class LeaderboardPanel extends FormPanel {
int legCount = getLeaderboard().getLegCount(getRaceName());
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
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;
}
@@ -312,8 +324,13 @@ public class LeaderboardPanel extends FormPanel {
this.setLeaderboardName(leaderboardName);
this.errorReporter = errorReporter;
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();
leaderboardTable = new CellTable<LeaderboardRowDAO>(/* pageSize */ 100);
CellTable.Resources resources = GWT.create(LeaderboardTableResources.class);
leaderboardTable = new CellTable<LeaderboardRowDAO>(/* pageSize */ 100, resources);
getLeaderboardTable().setWidth("100%");
getLeaderboardTable().setSelectionModel(new MultiSelectionModel<LeaderboardRowDAO>() {});
setData(new ListDataProvider<LeaderboardRowDAO>());
@@ -322,21 +339,33 @@ public class LeaderboardPanel extends FormPanel {
getLeaderboardTable().addColumnSortHandler(listHandler);
loadCompleteLeaderboard(getLeaderboardDisplayDate());
VerticalPanel vp = new VerticalPanel();
HorizontalPanel hp = new HorizontalPanel();
hp.setSpacing(10);
vp.setSpacing(15);
Anchor sapLogo = new Anchor(new SafeHtmlBuilder().appendHtmlConstant("<img class=\"linkNoBorder\" src=\"/images/sap_66_transparent.png\"/>").toSafeHtml());
sapLogo.setHref("http://www.sap.com");
hp.add(sapLogo);
hp.add(new Label(leaderboardName));
Button refreshButton = new Button(stringConstants.refresh());
hp.add(refreshButton);
refreshButton.addClickHandler(new ClickHandler() {
vp.add(sapLogo);
DockPanel dockPanel = new DockPanel();
dockPanel.setWidth("100%");
dockPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
Label leaderboardLabel = new Label(stringConstants.leaderboard()+" "+leaderboardName.toUpperCase());
leaderboardLabel.addStyleName("boldLabel");
dockPanel.add(leaderboardLabel, DockPanel.WEST);
ClickHandler refreshHandler = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
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());
setWidget(vp);
}
@@ -582,4 +611,26 @@ public class LeaderboardPanel extends FormPanel {
private void setData(ListDataProvider<LeaderboardRowDAO> 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();
}
}
}
}
@@ -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;
}
@@ -8,6 +8,7 @@ import com.google.gwt.cell.client.TextCell;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.cellview.client.Header;
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.LeaderboardRowDAO;
import com.sap.sailing.gwt.ui.shared.LegEntryDAO;
@@ -23,6 +24,7 @@ public class LegColumn extends ExpandableSortableColumn<String> {
private final String raceName;
private final int legIndex;
private final StringConstants stringConstants;
private final LegDetailSelectionProvider legDetailSelectionProvider;
private abstract class AbstractLegDetailField<T> implements LegDetailField<T> {
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());
setHorizontalAlignment(ALIGN_RIGHT);
this.raceName = raceName;
this.legIndex = legIndex;
this.stringConstants = stringConstants;
this.legDetailSelectionProvider = legDetailSelectionProvider;
}
private int getLegIndex() {
@@ -129,9 +133,19 @@ public class LegColumn extends ExpandableSortableColumn<String> {
protected List<SortableColumn<LeaderboardRowDAO, ?>> createExpansionColumns() {
List<SortableColumn<LeaderboardRowDAO, ?>> result = new ArrayList<SortableColumn<LeaderboardRowDAO,?>>();
try {
for (LegDetailColumnType type : legDetailSelectionProvider.getLegDetailsToShow()) {
switch (type) {
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;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -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;
}
}
@@ -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();
}
@@ -0,0 +1,6 @@
package com.sap.sailing.gwt.ui.client;
public interface ModifiableLegDetailSelectionProvider extends LegDetailSelectionProvider {
void select(LegDetailColumnType type);
void deselect(LegDetailColumnType type);
}
@@ -48,6 +48,25 @@ public class SortableExpandableColumnHeader extends Header<SafeHtml> {
private static <T> Cell<SafeHtml> constructCell(final String title, final String iconURL, boolean isExpansionEnabled,
final LeaderboardPanel leaderboardPanel, final ExpandableSortableColumn<?> column, final StringConstants stringConstants) {
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 (iconURL != null) {
cells.add(new HasCell<SafeHtml, String>() {
@@ -79,40 +98,9 @@ public class SortableExpandableColumnHeader extends Header<SafeHtml> {
}
@Override
public SafeHtml getValue(SafeHtml object) {
return new SafeHtmlBuilder().appendEscaped(title).toSafeHtml();
return new SafeHtmlBuilder().appendHtmlConstant("&nbsp;").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) {
/**
* Redefining this method because when a table column is sorted, GWT wraps a div element
@@ -66,4 +66,5 @@ public interface StringConstants extends Constants {
String averageSpeedInKnots();
String rankGain();
String sapSailingAnalytics();
String leaderboard();
}
@@ -22,7 +22,7 @@ delayHelp=Leave empty to replay at arbitrary times; enter seconds (e.g., "60" fo
speedInKnots=Speed (kn)
fromDeg=From (deg)
noRacesYet=No Races Yet
total=Total
total=\u03A3
carry=Accumulated
competitor=Competitor
defaultLeaderboard=Default Leaderboard
@@ -61,3 +61,4 @@ distanceInMeters=Distance/m
averageSpeedInKnots=Average Speed/kts
rankGain=Rank Gain
sapSailingAnalytics=SAP Sailing Analytics
leaderboard=LEADERBOARD
@@ -1,5 +1,10 @@
/** Add css rules here for your application. */
* {
font-family: Arial;
font-size: 12px;
}
/** Example rules used by the template application (remove for your app) */
h1 {
@@ -44,3 +49,23 @@ h1 {
.linkNoBorder {
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>
<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 -->
<!-- -->
@@ -25,6 +20,12 @@
<!-- 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>
<!-- -->
<!-- Consider inlining CSS to reduce the number of requested files -->
<!-- -->
<link type="text/css" rel="stylesheet" href="Leaderboard.css">
</head>
<!-- -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

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="useCustomFeatures" 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>