diff --git a/java/com.googlecode.java-diff-utils.test/META-INF/MANIFEST.MF b/java/com.googlecode.java-diff-utils.test/META-INF/MANIFEST.MF
index 788a54e61a3..6164a87122b 100755
--- a/java/com.googlecode.java-diff-utils.test/META-INF/MANIFEST.MF
+++ b/java/com.googlecode.java-diff-utils.test/META-INF/MANIFEST.MF
@@ -5,7 +5,7 @@ Bundle-SymbolicName: com.googlecode.java-diff-utils.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: GOOGLECODE
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Require-Bundle: com.googlecode.java-diff-utils;bundle-version="1.3.0"
+Fragment-Host: com.googlecode.java-diff-utils
Bundle-ClassPath: test/,
.
Import-Package: junit.framework;version="4.8.1"
diff --git a/java/com.sap.sailing.declination.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.declination.test/META-INF/MANIFEST.MF
index 09f8c0245d4..016d976855e 100755
--- a/java/com.sap.sailing.declination.test/META-INF/MANIFEST.MF
+++ b/java/com.sap.sailing.declination.test/META-INF/MANIFEST.MF
@@ -5,9 +5,7 @@ Bundle-SymbolicName: com.sap.sailing.declination.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Require-Bundle: com.sap.sailing.declination,
- com.sap.sailing.domain,
- com.sap.sailing.domain.common
+Fragment-Host: com.sap.sailing.declination
Import-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.impl,
com.sap.sailing.domain.common.quadtree,
diff --git a/java/com.sap.sailing.declination/META-INF/MANIFEST.MF b/java/com.sap.sailing.declination/META-INF/MANIFEST.MF
index 115624cf7c9..88760480fec 100755
--- a/java/com.sap.sailing.declination/META-INF/MANIFEST.MF
+++ b/java/com.sap.sailing.declination/META-INF/MANIFEST.MF
@@ -8,8 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.domain.common
-Export-Package: com.sap.sailing.declination,
- com.sap.sailing.declination.impl;x-friends:="com.sap.sailing.declination.test"
+Export-Package: com.sap.sailing.declination
Import-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.impl,
com.sap.sailing.domain.common.quadtree
diff --git a/java/com.sap.sailing.domain.persistence.test/.classpath b/java/com.sap.sailing.domain.persistence.test/.classpath
new file mode 100644
index 00000000000..e8ea977a694
--- /dev/null
+++ b/java/com.sap.sailing.domain.persistence.test/.classpath
@@ -0,0 +1,7 @@
+
+null string which may have length 0
+ * @return a string that can be used as a key in a MongoDB key-value pair and that can be decoded again using
+ * {@link #unescapeDollarAndDot(String)}.
+ */
+ public static String escapeDollarAndDot(String key) {
+ String result = key.replace("%", "%25").replace("+", "%2B");
+ if (result.length() > 0 && result.charAt(0) == '$') {
+ result = "%24"+result.substring(1);
+ }
+ return result.replace(".", "%2E");
+ }
+
+ /**
+ * @see #escapeDollarAndDot(String)
+ * @param key
+ * a non-null string which may have length 0 and that was returned by
+ * {@link #escapeDollarAndDot(String)}.
+ * @return the string originally passed to {@link #escapeDollarAndDot(String)}
+ */
+ public static String unescapeDollarAndDot(String escapedKey) {
+ try {
+ return URLDecoder.decode(escapedKey, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("How come this VM doesn't know UTF-8?");
+ }
+ }
+
+}
diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF
index 1e083c875a3..0f56fbee484 100755
--- a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF
+++ b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF
@@ -5,9 +5,8 @@ Bundle-SymbolicName: com.sap.sailing.domain.swisstimingadapter.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Require-Bundle: com.sap.sailing.domain.swisstimingadapter.persistence,
- com.sap.sailing.domain.swisstimingadapter,
- com.sap.sailing.domain,
+Fragment-Host: com.sap.sailing.domain.swisstimingadapter
+Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.udpconnector,
com.mongodb.driver;bundle-version="2.6.2",
com.sap.sailing.mongodb,
@@ -15,7 +14,8 @@ Require-Bundle: com.sap.sailing.domain.swisstimingadapter.persistence,
com.sap.sailing.server,
com.sap.sailing.domain.common,
com.sap.sailing.domain.persistence,
- com.sap.sailing.domain.tractracadapter
+ com.sap.sailing.domain.tractracadapter,
+ com.sap.sailing.domain.swisstimingadapter.persistence;bundle-version="1.0.0"
Bundle-ClassPath: resources/,
.
Import-Package: com.sap.sailing.server,
diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java
index 8cc00d2489d..9407c4f4b3a 100644
--- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java
+++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/classes/services/MessageFileServiceImpl.java
@@ -51,7 +51,7 @@ public class MessageFileServiceImpl implements MessageFileService {
private final DateFormat timeFormat;
public MessageFileServiceImpl() {
- dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
timeFormat = new SimpleDateFormat("HH:mm:ss");
}
diff --git a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF
index 17af4b97bf0..18bb4067e06 100755
--- a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF
+++ b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF
@@ -10,5 +10,4 @@ Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.udpconnector,
com.googlecode.java-diff-utils;bundle-version="1.3.0",
com.sap.sailing.domain.common
-Export-Package: com.sap.sailing.domain.swisstimingadapter,
- com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.domain.swisstimingadapter.test"
+Export-Package: com.sap.sailing.domain.swisstimingadapter
diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java
index df03e0967d5..67cc92e6585 100755
--- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java
+++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java
@@ -126,7 +126,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
public SailMasterConnectorImpl(String host, int port, RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException {
super();
this.messageLoader = messageLoader;
- dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
idsOfTrackedRaces = new HashSet
| Coupe Nationale 5O5 Societe des Regates Rochelaises 08/07/2011 au 11/07/2011 |
BOGACKI Morten KYC/DYC QUIRK Michael RPEYC C N MESCHERS PINNELL Ian HISC C V ST QUENTIN BART Cedric CNB SMITH Andy NOTTS COUNTY SC HOLZAPFEL Alexander ALLEMAGNE LEWNS Chris WHITSTABLE HOFFMANNBUHL Nikolas STETTEN BACHKLUB DETSCHEN Rene CNB C V SEINE-PORT RUS GRANDE-BRETAGNE C V SEINE-PORT C N CANET PERPIGNAN STAUFFER Florian CLUB DE VOILE DE NEUCHATEL S N P H Y C ILE DE FRANCE S R FECAMP C V BORDEAUX DEANE Roger ROCK SC C V SEINE-PORT TURNBULL Stuart BURTON SAILING CLUB C.V.M.L GUY Hubert ABYC C N DE SCIEZ HOURIET Catherine YCG BLAYE NAUTIQUE Y C Grenoble Chara C V SEINE-PORT C N FERRET DE PAUW Geert BELGIQUE WEDGE Martin RTYC MILTON Alastair HELENSBURGH SC AC ALSACE LORRAINE LES VOILES D ANTIBES C .V. de PARIS JACOT Valéry CERCLE DE VOILE DE NEUCHATEL S R ROCHELAISES Y C Grenoble Chara PIACQUADIO Giacinto YACHTING CLUB CERN VANDERSTEN Philippe SNEH WIND 14 C V ARCACHON C V SEINE-PORT C V ST QUENTIN CV LAC 3 PROVINCES S R ROCHELAISES C.V.M.L USAM VOILE Y C Grenoble Chara C .V. de PARIS EV ROCHELAISE Y C BEAULIEU BERRY Jim GRANDE-BRETAGNE S N O NANTES C.V.M.L C.V.M.L Y.C.DINARD S N O NANTES S R ROCHELAISES C V ANGERS C.V.M.L FEVERHAKE Jurgen YCSB C N HAUTE SEINE C.V.M.L C N T LACYDON C.V.M.L AC ALSACE LORRAINE S N O NANTES S R ROCHELAISES C V ANGOULEME U N P CAP BRETON USAM VOILE KALF Mark HOLLANDERgs Ident Concurrents P Ret P tot c.1 c.2 c.3 c.4 c.5 c.6 c.7 c.8 Club / Pays 1 GER 9070
JESS Holger 9.00 12.00 3
3.001
1.001
1.001
1.001
1.001
1.003
3.001
1.00 2 AUS 9036
REFFOLD Simon 20.00 44.00 2
2.003
3.003
3.0024
24.004
4.002
2.002
2.004
4.00 3 FRA 9067
27.00 41.00 4
4.002
2.0014
14.002
2.005
5.004
4.007
7.003
3.00
S R ROCHELAISES 4 GBR 9032
PUINELL Ian 44.00 58.00 1
1.004
4.007
7.008
8.003
3.0014
14.0014
14.007
7.00 5 FRA 8902
52.00 67.00 12
12.005
5.006
6.009
9.009
9.005
5.006
6.0015
15.00
S R HAVRE 6 SUI 8543
GROB Laurent 55.00 74.00 10
10.006
6.002
2.0019
19.0010
10.0012
12.005
5.0010
10.00 7 GBR 9012
NEEDHAM Tim 60.00 80.00 5
5.008
8.0020
20.0018
18.008
8.003
3.001
1.0017
17.00 8 GER 8975
WORM Stefan 60.00 74.00 11
11.007
7.009
9.005
5.0013
13.007
7.008
8.0014
14.00 9 GBR 9057
PARSONS Oan 64.00 140.00 9
9.009
9.0010
10.004
4.0014
14.009
9.009
9.00DNF
76.00 10 DEN 8958
BUHL Henrik 72.00 102.00 7
7.00DPI
30.005
5.0013
13.007
7.008
8.0024
24.008
8.00 11 SUI 8569
HOLLINGER Lionel 74.00 94.00 6
6.0016
16.0019
19.0020
20.006
6.006
6.0010
10.0011
11.00 12 FRA 8900
96.00 125.00 18
18.0013
13.004
4.007
7.0026
26.0029
29.0019
19.009
9.00
C V SEINE-PORT 13 GBR 8935
LAFORTUNE Geraud 97.00 116.00 15
15.0012
12.0016
16.0014
14.0012
12.0015
15.0013
13.0019
19.00
C V SEINE-PORT 14 FRA 8752
98.00 132.00 34
34.0017
17.008
8.003
3.0023
23.0024
24.0021
21.002
2.00
C V SEINE-PORT 15 FRA 8515
98.00 124.00 14
14.0011
11.0022
22.0017
17.0011
11.0011
11.0012
12.0026
26.00
C N CANET PERPIGNAN 16 SUI 8954
JACOT Philippe 118.00 194.00 DNF
76.00DNF
76.0011
11.0010
10.002
2.0010
10.004
4.005
5.00 17 FRA 8948
144.00 220.00 8
8.0014
14.0032
32.0040
40.0021
21.0018
18.0011
11.00DNC
76.00
S N P H 18 FRA 8870
144.00 193.00 19
19.0034
34.0012
12.0022
22.0017
17.0019
19.0049
49.0021
21.00
Y C Grenoble Chara 19 FRA 9044
146.00 180.00 24
24.0022
22.0025
25.006
6.0022
22.0034
34.0029
29.0018
18.00
S R FECAMP 20 FRA 8869
147.00 182.00 20
20.0027
27.0029
29.0033
33.0016
16.0016
16.0035
35.006
6.00
C V BORDEAUX 21 GBR 8881
TURNER Dave 147.00 188.00 17
17.0041
41.0013
13.0025
25.0015
15.0037
37.0015
15.0025
25.00 22 FRA 8716
150.00 226.00 DNF
76.0010
10.0015
15.0011
11.0019
19.0028
28.0051
51.0016
16.00
C V ST QUENTIN 23 GBR 8905
LUNN Jason 151.00 196.00 35
35.0021
21.0017
17.0045
45.0020
20.0017
17.0017
17.0024
24.00 24 FRA 8961
163.00 199.00 21
21.0019
19.0028
28.0015
15.0036
36.0030
30.0020
20.0030
30.00
S N P H 25 GER 9026
DETAPPE Xavier 165.00 241.00 13
13.00DPI
38.00RDG
26.00RDG
26.0018
18.0013
13.00DNF
76.0031
31.00
A S CHEMINOTS ROCH 26 FRA 8909
170.00 207.00 22
22.0025
25.0035
35.0037
37.0028
28.0020
20.0027
27.0013
13.00
AC ALSACE LORRAINE 27 SUI 9060
DONZE Gil 181.00 238.00 32
32.0035
35.0023
23.0012
12.0035
35.0057
57.0032
32.0012
12.00 28 FRA 8908
182.00 215.00 30
30.0028
28.0018
18.0032
32.0033
33.0025
25.0022
22.0027
27.00
Y C C 29 FRA 9024
185.00 221.00 36
36.0020
20.0021
21.0016
16.0029
29.0035
35.0031
31.0033
33.00
Y C Grenoble Chara 30 FRA 9010
188.00 246.00 28
28.0018
18.0031
31.0058
58.0024
24.0026
26.0026
26.0035
35.00
C N HAUTE SEINE 31 FRA 9068
189.00 234.00 45
45.0026
26.0044
44.0029
29.0027
27.0022
22.0018
18.0023
23.00
C N FERRET 32 BEL 9066
JOURQUIN Koen 195.00 246.00 16
16.0031
31.0041
41.0051
51.0025
25.0031
31.0023
23.0028
28.00 33 GBR 8925
ALLEN Scott 209.00 285.00 23
23.0024
24.0030
30.0036
36.0032
32.0023
23.00DNF
76.0041
41.00 34 GBR 8749
MILTON Laurence 213.00 265.00 31
31.0042
42.0039
39.0021
21.0043
43.0021
21.0016
16.0052
52.00 35 FRA 7941
217.00 293.00 25
25.0030
30.00DSQ
76.0023
23.0037
37.0040
40.0042
42.0020
20.00
AC ALSACE LORRAINE 36 FRA 8729
224.00 269.00 29
29.0029
29.0038
38.0041
41.0030
30.0045
45.0028
28.0029
29.00
Y C BEAULIEU 37 FRA 8885
248.00 302.00 39
39.0039
39.0026
26.0031
31.0041
41.0054
54.0033
33.0039
39.00
S N O NANTES 38 SUI 8614
BATTAGLIA Corsin 250.00 326.00 50
50.00DNS
76.0024
24.0035
35.0031
31.0032
32.0056
56.0022
22.00 39 FRA 8486
252.00 308.00 26
26.0033
33.0046
46.0056
56.0040
40.0033
33.0036
36.0038
38.00
C V A N NANTES 40 FRA 8427
255.00 298.00 37
37.0037
37.0040
40.0030
30.0039
39.0036
36.0043
43.0036
36.00
S A LYONNAIS 41 ITA 8671
MESSINA Anrea 280.00 339.00 42
42.0032
32.0043
43.0034
34.0059
59.0053
53.0034
34.0042
42.00 42 BEL 9
GENNART Genevieve 295.00 371.00 40
40.0047
47.0036
36.0039
39.0044
44.0048
48.0041
41.00DNC
76.00 43 FRA 8567
298.00 374.00 47
47.0045
45.0058
58.0062
62.0034
34.0027
27.0025
25.00DNF
76.00
WIND 14 44 FRA 8565
301.00 377.00 48
48.0036
36.0027
27.0027
27.0048
48.0039
39.00DNF
76.00DNC
76.00
C V ARCACHON 45 FRA 8800
301.00 350.00 49
49.0046
46.0033
33.0043
43.0047
47.0049
49.0039
39.0044
44.00
C V SEINE-PORT 46 FRA 8899
308.00 384.00 41
41.0038
38.0045
45.0038
38.0064
64.0050
50.00DNF
76.0032
32.00
C V SEINE-PORT 47 FRA 8695
308.00 384.00 61
61.0044
44.0034
34.0042
42.0042
42.0047
47.0038
38.00DNC
76.00
DAUPHINS WIND JOCON. 48 FRA 8
317.00 382.00 33
33.0054
54.0063
63.0065
65.0038
38.0041
41.0040
40.0048
48.00
EV ROCHELAISE 49 FRA 8699
333.00 394.00 38
38.0049
49.0061
61.0048
48.0051
51.0051
51.0050
50.0046
46.00
C.V.M.L 50 FRA 9050
342.00 418.00 54
54.0051
51.0062
62.0055
55.0046
46.0044
44.0030
30.00DNF
76.00
USAM VOILE 51 FRA 8711
342.00 396.00 46
46.0043
43.0052
52.0050
50.0052
52.0052
52.0054
54.0047
47.00
Y C Grenoble Chara 52 FRA 8980
347.00 409.00 62
62.0048
48.0042
42.0047
47.0062
62.0055
55.0053
53.0040
40.00
C V SEINE-PORT 53 FRA 8187
352.00 428.00 DNF
76.0040
40.0054
54.0044
44.0049
49.0046
46.00DNF
76.0043
43.00
G S LA ROCHELLE 54 FRA 8773
362.00 418.00 55
55.0055
55.0048
48.0054
54.0055
55.0056
56.0046
46.0049
49.00
YC POINTE ROUGE 55 GBR 8907
BARNES David 375.00 451.00 27
27.00DNF
76.0047
47.0057
57.0054
54.0038
38.00DNF
76.00DNF
76.00 56 FRA 8949
380.00 456.00 DNF
76.00DNS
76.0037
37.0028
28.0068
68.0058
58.00DNS
76.0037
37.00
S N O NANTES 57 FRA 8704
381.00 457.00 44
44.00DNF
76.0049
49.0026
26.00DNF
76.00DNS
76.00DNF
76.0034
34.00
C.V.M.L 58 FRA 8623
396.00 472.00 DNF
76.00DNS
76.0056
56.0052
52.00DNF
76.0043
43.0048
48.0045
45.00
Y C CAVALAIRE 59 FRA 8826
407.00 483.00 52
52.00DNF
76.0051
51.0061
61.0060
60.0060
60.0047
47.00DNF
76.00
Y.C.DINARD 60 FRA 8431
417.00 493.00 58
58.0053
53.0066
66.0063
63.0065
65.0068
68.0044
44.00DNF
76.00
S N O NANTES 61 FRA 8366
421.00 497.00 DNF
76.00DNS
76.0068
68.0069
69.0053
53.0042
42.0037
37.00DNC
76.00
S R ROCHELAISES 62 FRA 9033
426.00 502.00 59
59.00DNF
76.0050
50.0053
53.0050
50.0062
62.00DNS
76.00DNF
76.00
S N P H 63 FRA 8880
428.00 504.00 57
57.0050
50.0069
69.0070
70.0061
61.00DNF
76.0045
45.00DNF
76.00
C .V. de PARIS 64 GER 8052
NEHRENBERG Anne 435.00 511.00 56
56.0052
52.0055
55.0066
66.0066
66.0064
64.00DNF
76.00DNF
76.00 65 FRA 8748
441.00 517.00 51
51.00DPI
71.0070
70.0073
73.0058
58.0066
66.0052
52.00DNF
76.00
C N HAUTE SEINE 66 FRA 8564
453.00 529.00 DNF
76.00DNS
76.0065
65.0049
49.0070
70.0067
67.00DNF
76.0050
50.00
C .V. de PARIS 67 FRA 8362
460.00 536.00 53
53.00DNF
76.0057
57.0046
46.00DNF
76.00DNF
76.00DNS
76.00DNC
76.00
S N DE SANARY 68 FRA 8705
461.00 537.00 43
43.00DNF
76.0053
53.0068
68.0069
69.00DNF
76.00DNS
76.00DNF
76.00
C.V.M.L 69 FRA 9019
469.00 545.00 DNF
76.00DNS
76.0059
59.0060
60.0057
57.0065
65.00DNS
76.00DNF
76.00
AC ALSACE LORRAINE 70 FRA 8676
469.00 545.00 DNC
76.00DNF
76.0060
60.0059
59.0063
63.0059
59.00DNF
76.00DNF
76.00
S N O NANTES 71 FRA 898
475.00 551.00 60
60.00DNS
76.0064
64.0067
67.0056
56.00DNF
76.00DNS
76.00DNF
76.00
S N O NANTES 72 FRA 8401
479.00 555.00 DNF
76.00DNF
76.0071
71.0071
71.0071
71.0063
63.00DNS
76.0051
51.00
V LACANAU GUYENNE 73 FRA 8541
492.00 568.00 DNF
76.00DNF
76.0067
67.00DPI
76.0045
45.00DNF
76.00DNS
76.00DNF
76.00
U N P CAP BRETON 74 FRA 8717
500.00 576.00 DNF
76.00DNC
76.00DNF
76.00DNF
76.0072
72.0069
69.0055
55.00DNF
76.00
USAM VOILE 75 NED 8287
KALF Mak 500.00 576.00 DNF
76.00DNS
76.0072
72.0072
72.0067
67.0061
61.00DNF
76.00DNC
76.00
LORBER Yves DESFORGES Roland
Président du Comité de Course
Président du Jury
The attribute which is used for the debug id.
+ */ + public static final String DEBUG_ID_ATTRIBUTE = "selenium-id"; //$NON-NLS-1$ + + /** + *The prefix which is used for the debug id.
+ */ + public static final String DEBUG_ID_PREFIX = ""; //$NON-NLS-1$ + + private DialogBox errorDialogBox; + private HTML serverResponseLabel; + private Button dialogCloseButton; + protected StringMessages stringMessages; + protected UserAgentDetails userAgent; + + /** + * Create a remote service proxy to talk to the server-side sailing service. + */ + protected final SailingServiceAsync sailingService = GWT.create(SailingService.class); + + /** + * Create a remote service proxy to talk to the server-side media service. + */ + protected final MediaServiceAsync mediaService = GWT.create(MediaService.class); + + /** + * Create a remote service proxy to talk to the server-side user management service. + */ + protected final UserManagementServiceAsync userManagementService = GWT.create(UserManagementService.class); + + /** + * The message displayed to the user when the server cannot be reached or + * returns an error. + */ + private static final String SERVER_ERROR = "An error occurred while " //$NON-NLS-1$ + + "attempting to contact the server. Please check your network " + "connection and try again."; //$NON-NLS-1$ //$NON-NLS-2$ + + @Override + public final void onModuleLoad() { + if(DebugInfo.isDebugIdEnabled()) { + PendingAjaxCallBundle bundle = GWT.create(PendingAjaxCallBundle.class); + TextResource script = bundle.ajaxSemaphoreJS(); + JavaScriptInjector.inject(script.getText()); + + DebugInfo.setDebugIdAttribute(DEBUG_ID_ATTRIBUTE, false); + DebugInfo.setDebugIdPrefix(DEBUG_ID_PREFIX); + } + + doOnModuleLoad(); + + if(DebugInfo.isDebugIdEnabled()) { + PendingAjaxCallMarker.decrementPendingAjaxCalls(MarkedAsyncCallback.CATEGORY_GLOBAL); + } + } + + protected void doOnModuleLoad() { + stringMessages = GWT.create(StringMessages.class); + errorDialogBox = createErrorDialog(); /* TODO: Make this more generic (e.g. make it support all kinds of messages) */ + userAgent = new UserAgentDetails(Window.Navigator.getUserAgent()); + + ServiceDefTarget sailingServiceDef = (ServiceDefTarget) sailingService; + ServiceDefTarget mediaServiceDef = (ServiceDefTarget) mediaService; + ServiceDefTarget userManagementServiceDef = (ServiceDefTarget) userManagementService; + String moduleBaseURL = GWT.getModuleBaseURL(); + String baseURL = moduleBaseURL.substring(0, moduleBaseURL.lastIndexOf('/', moduleBaseURL.length()-2)+1); + sailingServiceDef.setServiceEntryPoint(baseURL + "sailing"); + mediaServiceDef.setServiceEntryPoint(baseURL + "media"); + userManagementServiceDef.setServiceEntryPoint(baseURL + "usermanagement"); + } + + @Override + public void reportError(String message) { + errorDialogBox.setText(message); + serverResponseLabel.addStyleName("serverResponseLabelError"); //$NON-NLS-1$ + serverResponseLabel.setHTML(SERVER_ERROR); + errorDialogBox.center(); + dialogCloseButton.setFocus(true); + } + + @Override + public void reportError(String message, boolean silentMode) { + if (silentMode) { + Window.setStatus(message); + } else { + reportError(message); + } + } + + @Override + public boolean isSmallWidth() { + int width = Window.getClientWidth(); + return width <= 720; + } + + public void createErrorPage(String message) { + LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(stringMessages, this); + logoAndTitlePanel.addStyleName("LogoAndTitlePanel"); + RootPanel.get().add(logoAndTitlePanel); + RootPanel.get().add(new Label(message)); + } + + private DialogBox createErrorDialog() { + // Create the popup dialog box + final DialogBox myErrorDialogBox = new DialogBox(); + myErrorDialogBox.setText("Remote Procedure Call"); //$NON-NLS-1$ + myErrorDialogBox.setAnimationEnabled(true); + dialogCloseButton = new Button("Close"); //$NON-NLS-1$ + // We can set the id of a widget by accessing its Element + dialogCloseButton.getElement().setId("closeButton"); //$NON-NLS-1$ + final Label textToServerLabel = new Label(); + serverResponseLabel = new HTML(); + VerticalPanel dialogVPanel = new VerticalPanel(); + dialogVPanel.add(new HTML("Error communicating with server")); //$NON-NLS-1$ + dialogVPanel.add(textToServerLabel); + dialogVPanel.add(new HTML("T, 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.
- * Subclasses can specify a widget to show in the dialog to capture properties specific to the result type T by
- * overriding the {@link #getAdditionalWidget()} method.
- *
- * @author Axel Uhl (d043530)
- */
-public abstract class DataEntryDialognull in case the valueToValidate is valid; a user-readable error message otherwise
- */
- String getErrorMessage(T valueToValidate);
- }
-
- public static interface DialogCallbacknull, no validation of data entered is performed; otherwise,
- * data validation is triggered upon any noticeable change in any of the elements constructed by
- * {@link #createCheckbox(String)}, {@link #createTextBox(String)}, etc.
- * @param callback
- * will be called when the dialog if {@link AsyncCallback#onFailure(Throwable) cancelled} or
- * {@link AsyncCallback#onSuccess(Object) confirmed}
- */
- public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
- Validatornull, no validation of data entered is performed; otherwise,
- * data validation is triggered upon any noticeable change in any of the elements constructed by
- * {@link #createCheckbox(String)}, {@link #createTextBox(String)}, etc.
- * @param callback
- * will be called when the dialog if {@link AsyncCallback#onFailure(Throwable) cancelled} or
- * {@link AsyncCallback#onSuccess(Object) confirmed}
- */
- public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
- Validatornull is permissible
- */
- public TextBox createTextBox(String initialValue) {
- TextBox textBox = new TextBox();
- textBox.setText(initialValue == null ? "" : initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(textBox);
- textBox.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), textBox);
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textBox);
- return textBox;
- }
-
- /**
- * Creates a text area with a key-up listener attached which ensures the value is updated after each
- * key-up event and the entire dialog is {@link #validate() validated} in this case.
- *
- * @param initialValue Initial value to show in text area; null is permissible
- */
- public TextArea createTextArea(String initialValue) {
- TextArea textArea = new TextArea();
- textArea.setText(initialValue == null ? "" : initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(textArea);
- textArea.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent arg0) {
- validate();
- }
- });
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textArea);
- return textArea;
- }
-
- /**
- * Creates a box for a long value with a key-up listener attached which ensures the value is updated after each
- * key-up event and the entire dialog is {@link #validate() validated} in this case.
- *
- * @param initialValue initial value to show in the long box; null is permissible
- */
- public LongBox createLongBox(long initialValue, int visibleLength) {
- LongBox longBox = new LongBox();
- longBox.setVisibleLength(visibleLength);
- longBox.setValue(initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(longBox);
- longBox.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), longBox);
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), longBox);
- return longBox;
- }
-
- public DoubleBox createDoubleBox(double initialValue, int visibleLength) {
- return createDoubleBoxInternal(initialValue, visibleLength);
- }
-
- public DoubleBox createDoubleBox(int visibleLength) {
- return createDoubleBoxInternal(null, visibleLength);
- }
-
- private DoubleBox createDoubleBoxInternal(Double initialValue, int visibleLength) {
- DoubleBox doubleBox = new DoubleBox();
- doubleBox.setVisibleLength(visibleLength);
- doubleBox.setValue(initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(doubleBox);
- doubleBox.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), doubleBox);
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), doubleBox);
- return doubleBox;
- }
-
- public DateBox createDateBox(long initialTimeInMs, int visibleLength) {
- return createDateBoxInternal(new Date(initialTimeInMs), visibleLength);
- }
-
- public DateBox createDateBox(int visibleLength) {
- return createDateBoxInternal(null, visibleLength);
- }
-
- private DateBox createDateBoxInternal(Date initialDate, int visibleLength) {
- DateBox textBox = new DateBox();
- textBox.getTextBox().setVisibleLength(visibleLength);
- textBox.setValue(initialDate);
- AbstractEntryPoint.addFocusUponKeyUpToggler(textBox.getTextBox());
- textBox.getTextBox().addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), textBox.getTextBox());
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textBox.getTextBox());
- return textBox;
- }
-
- /**
- * Creates a box for a integer value with a key-up listener attached which ensures the value is updated after each
- * key-up event and the entire dialog is {@link #validate() validated} in this case.
- *
- * @param initialValue initial value to show in the integer box; null is permissible
- */
- public IntegerBox createIntegerBox(int initialValue, int visibleLength) {
- IntegerBox intBox = new IntegerBox();
- intBox.setVisibleLength(visibleLength);
- intBox.setValue(initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(intBox);
- intBox.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), intBox);
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), intBox);
- return intBox;
- }
-
- public LongBox createLongBoxWithOptionalValue(Long initialValue, int visibleLength) {
- LongBox longBox = new LongBox();
- longBox.setVisibleLength(visibleLength);
- longBox.setValue(initialValue);
- AbstractEntryPoint.addFocusUponKeyUpToggler(longBox);
- longBox.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(ChangeEvent event) {
- validate();
- }
- });
- AbstractEntryPoint.linkEnterToButton(getOkButton(), longBox);
- AbstractEntryPoint.linkEscapeToButton(getCancelButton(), longBox);
- return longBox;
- }
-
- public Label createHeadlineLabel(String headlineText) {
- Label headlineLabel = new Label(headlineText);
- headlineLabel.getElement().getStyle().setFontWeight(FontWeight.BOLD);
- headlineLabel.getElement().getStyle().setPaddingTop(1, Unit.EM);
- return headlineLabel;
- }
-
- public FlowPanel createHeadline(String headlineText, boolean regularHeadline) {
- FlowPanel headlinePanel = new FlowPanel();
- Label headlineLabel = new Label(headlineText);
- if (regularHeadline) {
- headlinePanel.addStyleName("dialogInnerHeadline");
- } else {
- headlinePanel.addStyleName("dialogInnerHeadlineOther");
- }
- headlinePanel.add(headlineLabel);
- return headlinePanel;
- }
-
- public CheckBox createCheckbox(String checkboxLabel) {
- CheckBox result = new CheckBox(checkboxLabel);
- result.setWordWrap(false);
- result.addValueChangeHandler(new ValueChangeHandlernull is
- * returned, no additional widget will be displayed. This is the default behavior of this default implementation.
- */
- protected Widget getAdditionalWidget() {
- return null;
- }
-
- protected Button getOkButton() {
- return okButton;
- }
-
- protected Button getCancelButton() {
- return cancelButton;
- }
-
- /**
- * status label can be used to display status information within the dialog to the user
- */
- protected Label getStatusLabel() {
- return statusLabel;
- }
-
- public void show() {
- Widget additionalWidget = getAdditionalWidget();
- if (additionalWidget != null) {
- panelForAdditionalWidget.add(additionalWidget);
- }
- validate();
- dateEntryDialog.center();
- }
-
-}
+package com.sap.sailing.gwt.ui.client;
+
+import java.util.Date;
+
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.FontWeight;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.DialogBox;
+import com.google.gwt.user.client.ui.DoubleBox;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HasVerticalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.IntegerBox;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.LongBox;
+import com.google.gwt.user.client.ui.RadioButton;
+import com.google.gwt.user.client.ui.TextArea;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.datepicker.client.DateBox;
+
+/**
+ * An abstract data entry dialog class, capturing data of type T, 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.
+ * Subclasses can specify a widget to show in the dialog to capture properties specific to the result type T by
+ * overriding the {@link #getAdditionalWidget()} method.
+ *
+ * @author Axel Uhl (d043530)
+ */
+public abstract class DataEntryDialognull in case the valueToValidate is valid; a user-readable error message otherwise
+ */
+ String getErrorMessage(T valueToValidate);
+ }
+
+ public static interface DialogCallbacknull, no validation of data entered is performed; otherwise,
+ * data validation is triggered upon any noticeable change in any of the elements constructed by
+ * {@link #createCheckbox(String)}, {@link #createTextBox(String)}, etc.
+ * @param callback
+ * will be called when the dialog if {@link AsyncCallback#onFailure(Throwable) cancelled} or
+ * {@link AsyncCallback#onSuccess(Object) confirmed}
+ */
+ public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
+ Validatornull, no validation of data entered is performed; otherwise,
+ * data validation is triggered upon any noticeable change in any of the elements constructed by
+ * {@link #createCheckbox(String)}, {@link #createTextBox(String)}, etc.
+ * @param callback
+ * will be called when the dialog if {@link AsyncCallback#onFailure(Throwable) cancelled} or
+ * {@link AsyncCallback#onSuccess(Object) confirmed}
+ */
+ public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
+ Validatornull is permissible
+ */
+ public TextBox createTextBox(String initialValue) {
+ TextBox textBox = new TextBox();
+ textBox.setText(initialValue == null ? "" : initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(textBox);
+ textBox.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), textBox);
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textBox);
+ return textBox;
+ }
+
+ /**
+ * Creates a text area with a key-up listener attached which ensures the value is updated after each
+ * key-up event and the entire dialog is {@link #validate() validated} in this case.
+ *
+ * @param initialValue Initial value to show in text area; null is permissible
+ */
+ public TextArea createTextArea(String initialValue) {
+ TextArea textArea = new TextArea();
+ textArea.setText(initialValue == null ? "" : initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(textArea);
+ textArea.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent arg0) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textArea);
+ return textArea;
+ }
+
+ /**
+ * Creates a box for a long value with a key-up listener attached which ensures the value is updated after each
+ * key-up event and the entire dialog is {@link #validate() validated} in this case.
+ *
+ * @param initialValue initial value to show in the long box; null is permissible
+ */
+ public LongBox createLongBox(long initialValue, int visibleLength) {
+ LongBox longBox = new LongBox();
+ longBox.setVisibleLength(visibleLength);
+ longBox.setValue(initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(longBox);
+ longBox.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), longBox);
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), longBox);
+ return longBox;
+ }
+
+ public DoubleBox createDoubleBox(double initialValue, int visibleLength) {
+ return createDoubleBoxInternal(initialValue, visibleLength);
+ }
+
+ public DoubleBox createDoubleBox(int visibleLength) {
+ return createDoubleBoxInternal(null, visibleLength);
+ }
+
+ private DoubleBox createDoubleBoxInternal(Double initialValue, int visibleLength) {
+ DoubleBox doubleBox = new DoubleBox();
+ doubleBox.setVisibleLength(visibleLength);
+ doubleBox.setValue(initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(doubleBox);
+ doubleBox.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), doubleBox);
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), doubleBox);
+ return doubleBox;
+ }
+
+ public DateBox createDateBox(long initialTimeInMs, int visibleLength) {
+ return createDateBoxInternal(new Date(initialTimeInMs), visibleLength);
+ }
+
+ public DateBox createDateBox(int visibleLength) {
+ return createDateBoxInternal(null, visibleLength);
+ }
+
+ private DateBox createDateBoxInternal(Date initialDate, int visibleLength) {
+ DateBox textBox = new DateBox();
+ textBox.getTextBox().setVisibleLength(visibleLength);
+ textBox.setValue(initialDate);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(textBox.getTextBox());
+ textBox.getTextBox().addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), textBox.getTextBox());
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textBox.getTextBox());
+ return textBox;
+ }
+
+ /**
+ * Creates a box for a integer value with a key-up listener attached which ensures the value is updated after each
+ * key-up event and the entire dialog is {@link #validate() validated} in this case.
+ *
+ * @param initialValue initial value to show in the integer box; null is permissible
+ */
+ public IntegerBox createIntegerBox(int initialValue, int visibleLength) {
+ IntegerBox intBox = new IntegerBox();
+ intBox.setVisibleLength(visibleLength);
+ intBox.setValue(initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(intBox);
+ intBox.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), intBox);
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), intBox);
+ return intBox;
+ }
+
+ public LongBox createLongBoxWithOptionalValue(Long initialValue, int visibleLength) {
+ LongBox longBox = new LongBox();
+ longBox.setVisibleLength(visibleLength);
+ longBox.setValue(initialValue);
+ AbstractEntryPoint.addFocusUponKeyUpToggler(longBox);
+ longBox.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(ChangeEvent event) {
+ validate();
+ }
+ });
+ AbstractEntryPoint.linkEnterToButton(getOkButton(), longBox);
+ AbstractEntryPoint.linkEscapeToButton(getCancelButton(), longBox);
+ return longBox;
+ }
+
+ public Label createHeadlineLabel(String headlineText) {
+ Label headlineLabel = new Label(headlineText);
+ headlineLabel.getElement().getStyle().setFontWeight(FontWeight.BOLD);
+ headlineLabel.getElement().getStyle().setPaddingTop(1, Unit.EM);
+ return headlineLabel;
+ }
+
+ public FlowPanel createHeadline(String headlineText, boolean regularHeadline) {
+ FlowPanel headlinePanel = new FlowPanel();
+ Label headlineLabel = new Label(headlineText);
+ if (regularHeadline) {
+ headlinePanel.addStyleName("dialogInnerHeadline");
+ } else {
+ headlinePanel.addStyleName("dialogInnerHeadlineOther");
+ }
+ headlinePanel.add(headlineLabel);
+ return headlinePanel;
+ }
+
+ public CheckBox createCheckbox(String checkboxLabel) {
+ CheckBox result = new CheckBox(checkboxLabel);
+ result.setWordWrap(false);
+ result.addValueChangeHandler(new ValueChangeHandlernull is
+ * returned, no additional widget will be displayed. This is the default behavior of this default implementation.
+ */
+ protected Widget getAdditionalWidget() {
+ return null;
+ }
+
+ protected Button getOkButton() {
+ return okButton;
+ }
+
+ protected Button getCancelButton() {
+ return cancelButton;
+ }
+
+ /**
+ * status label can be used to display status information within the dialog to the user
+ */
+ protected Label getStatusLabel() {
+ return statusLabel;
+ }
+
+ protected void setCursor(Style.Cursor cursor) {
+ dateEntryDialog.getElement().getStyle().setCursor(cursor);
+ }
+
+ public void show() {
+ Widget additionalWidget = getAdditionalWidget();
+ if (additionalWidget != null) {
+ panelForAdditionalWidget.add(additionalWidget);
+ }
+ validate();
+ dateEntryDialog.center();
+ }
+
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java
index 263f92bb5f1..7fd61f58c36 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java
@@ -1,10 +1,14 @@
package com.sap.sailing.gwt.ui.client;
+import com.google.gwt.core.shared.GWT;
import com.google.gwt.i18n.client.NumberFormat;
import com.sap.sailing.domain.common.DetailType;
public class DetailTypeFormatter {
- public static String format(DetailType detailType, StringMessages stringMessages) {
+
+ private static final StringMessages stringMessages = GWT.create(StringMessages.class);
+
+ public static String format(DetailType detailType) {
switch (detailType) {
case DISTANCE_TRAVELED:
return stringMessages.distanceInMeters();
@@ -82,6 +86,104 @@ public class DetailTypeFormatter {
}
return null;
}
+
+ /**
+ * Returns the unit of the given {@link DetailType}, like 'm', 'kts' or an empty string, if the detail type has no
+ * unit.Utility class to inject JavaScript in the default document.
+ * + * @author + * D049941 + */ public class JavaScriptInjector { private static HeadElement head; + /** + *Injects the given JavaScript code in the head of the default document. To inject the code a script element is + * created and appended to the head element of the document.
+ * + * @param javascript + * The JavaScript code to inject. + */ public static void inject(String javascript) { HeadElement head = getHead(); ScriptElement element = createScriptElement(); @@ -19,17 +32,17 @@ public class JavaScriptInjector { private static ScriptElement createScriptElement() { Document document = Document.get(); ScriptElement script = document.createScriptElement(); - script.setAttribute("type", "text/javascript"); + script.setAttribute("type", "text/javascript"); //$NON-NLS-1$ //$NON-NLS-2$ return script; } private static HeadElement getHead() { - if (head == null) { + if (JavaScriptInjector.head == null) { Document document = Document.get(); - NodeListAbstract base class for asynchronous remote procedure calls which should be marked as pending until they complete. + * Such calls will be marked using a counter, which is necessary in UI tests to be able able to tell exactly when an + * asynchronous request has finished. With this counter a test which triggers a request (which can cause additional + * request) can wait until the requests have finished. It's guaranteed that the counter is decremented no matter if + * the call was successful or not.
+ * + *Note: Since the counter for pending Ajax requests is incremented as soon as an instance of this class is created + * you must not create instances which are not used or assigned to an field!
+ * + * @paramThe key for the category of global requests. The key for the global category is just an empty string.
+ */ + public static final String CATEGORY_GLOBAL = ""; //$NON-NLS-1$ + private String category; + + /** + *Creates a marked asynchronous remote procedure call for the global category.
+ */ public MarkedAsyncCallback() { - PendingAjaxCallMarker.incrementPendingAjaxCalls(); + this(CATEGORY_GLOBAL); } + /** + *Creates a marked asynchronous remote procedure call for the given category. As soon as the asynchronous remote + * procedure call is created, the counter for pending Ajax calls for the given category is incremented.
+ * + * @param category + * The category of the asynchronous remote procedure call. + */ + public MarkedAsyncCallback(String category) { + this.category = category; + + if(DebugInfo.isDebugIdEnabled()) { + PendingAjaxCallMarker.incrementPendingAjaxCalls(this.category); + } + } + + /** + *Called when the asynchronous call fails to complete normally. The concrete handling of the failure has to be + * implemented in {@link #handleFailure(Throwable)}. It's guaranteed that the counter for the pending requests is + * decremented.
+ * + * @param cause + * The failure encountered while executing the remote procedure call. + */ @Override public final void onFailure(Throwable cause) { try { handleFailure(cause); } finally { - //if(DebugInfo.isDebugIdEnabled()) - PendingAjaxCallMarker.decrementPendingAjaxCalls(); + if(DebugInfo.isDebugIdEnabled()) { + PendingAjaxCallMarker.decrementPendingAjaxCalls(this.category); + } } } + /** + *Called when the asynchronous call completes successfully. The concrete handling of the result has to be + * implemented in {@link #handleSuccess(Object)}. It's guaranteed that the counter for the pending requests is + * decremented.
+ * + * @param result + * The return value of the remote produced call. + */ @Override public final void onSuccess(T result) { try { handleSuccess(result); } finally { - //if(DebugInfo.isDebugIdEnabled()) - PendingAjaxCallMarker.decrementPendingAjaxCalls(); + if(DebugInfo.isDebugIdEnabled()) { + PendingAjaxCallMarker.decrementPendingAjaxCalls(this.category); + } } } + /** + *Called when the asynchronous call fails to complete normally.
+ * + * @param cause + * The failure encountered while executing the remote procedure call. + */ protected abstract void handleFailure(Throwable cause); + /** + *Called when the asynchronous call completes successfully.
+ * + * @param result + * The return value of the remote produced call. + */ protected abstract void handleSuccess(T result); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaPlayer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaPlayer.java new file mode 100644 index 00000000000..6886390d0c9 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaPlayer.java @@ -0,0 +1,31 @@ +package com.sap.sailing.gwt.ui.client; + +import java.util.Date; + +import com.sap.sailing.gwt.ui.shared.media.MediaTrack; + +public interface MediaPlayer { + + boolean isPaused(); + + void pause(); + + void play(); + + void alignTime(Date raceTime); + + MediaTrack getMediaTrack(); + + double getDuration(); + + void setTime(double mediaTime); + + double getTime(); + + void setPlaybackSpeed(double newPlaySpeedFactor); + + void setMuted(boolean isToBeMuted); + + void destroy(); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaService.java new file mode 100644 index 00000000000..0fbf01bccb7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/MediaService.java @@ -0,0 +1,29 @@ +package com.sap.sailing.gwt.ui.client; + +import java.util.Collection; + +import com.google.gwt.user.client.rpc.RemoteService; +import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.gwt.ui.shared.media.MediaTrack; + +@RemoteServiceRelativePath("media") +public interface MediaService extends RemoteService { + + CollectionThe client bundle for the resource "ajax-semaphore.js" which is needed for the execution of UI tests.
+ * + * @author + * D049941 + */ public interface PendingAjaxCallBundle extends ClientBundle { + /** + *Returns the JavaScript for the counter of pending Ajax requests. The counter is used in UI tests to be able + * to tell exactly when an asynchronous request has finished.
+ * + * @return + * The JavaScript for the counter of pending Ajax requests. + */ @Source("ajax-semaphore.js") TextResource ajaxSemaphoreJS(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PendingAjaxCallMarker.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PendingAjaxCallMarker.java index 06299b3c430..cfbab574a9e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PendingAjaxCallMarker.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PendingAjaxCallMarker.java @@ -1,20 +1,38 @@ package com.sap.sailing.gwt.ui.client; +/** + *Utility class to mark pending Ajax requests.
+ * + * @author + * D049941 + */ public class PendingAjaxCallMarker { - public static native void decrementPendingAjaxCalls() /*-{ + /** + *Decrements the counter for pending Ajax request of the given category.
+ * + * @param category + * The category of the Ajax request. + */ + public static native void decrementPendingAjaxCalls(String category) /*-{ try { if (($wnd.PENDING_AJAX_CALLS) && (typeof $wnd.PENDING_AJAX_CALLS.decrementPendingCalls === "function")) { - $wnd.PENDING_AJAX_CALLS.decrementPendingCalls(); + $wnd.PENDING_AJAX_CALLS.decrementPendingCalls(category); } } catch (exception) { // Do error handling } }-*/; - - public static native void incrementPendingAjaxCalls() /*-{ + + /** + *Increments the counter for pending Ajax request of the given category.
+ * + * @param category + * The category of the Ajax request. + */ + public static native void incrementPendingAjaxCalls(String category) /*-{ try { if (($wnd.PENDING_AJAX_CALLS) && (typeof $wnd.PENDING_AJAX_CALLS.incrementPendingCalls === "function")) { - $wnd.PENDING_AJAX_CALLS.incrementPendingCalls(); + $wnd.PENDING_AJAX_CALLS.incrementPendingCalls(category); } } catch (exception) { // Do error handling @@ -22,6 +40,6 @@ public class PendingAjaxCallMarker { }-*/; private PendingAjaxCallMarker() { - super(); + // Utility class } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PlayStateListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PlayStateListener.java index 8479ada2bfc..1d5e2cbc5c0 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PlayStateListener.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/PlayStateListener.java @@ -1,14 +1,16 @@ -package com.sap.sailing.gwt.ui.client; - -import com.sap.sailing.gwt.ui.client.Timer.PlayModes; -import com.sap.sailing.gwt.ui.client.Timer.PlayStates; - -public interface PlayStateListener { - /** - * Called by a timer where this listener is registered when a timer's play state has changed. - * - * @param isPlaying - *true if the timer is now automatically updating its time
- */
- void playStateChanged(PlayStates playState, PlayModes playMode);
-}
+package com.sap.sailing.gwt.ui.client;
+
+import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
+import com.sap.sailing.gwt.ui.client.Timer.PlayStates;
+
+public interface PlayStateListener {
+ /**
+ * Called by a timer where this listener is registered when a timer's play state has changed.
+ *
+ * @param isPlaying
+ * true if the timer is now automatically updating its time
+ */
+ void playStateChanged(PlayStates playState, PlayModes playMode);
+
+ void playSpeedFactorChanged(double newPlaySpeedFactor);
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
index 28ebe3ee06a..bec7e3e6aa1 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
@@ -1,452 +1,461 @@
-package com.sap.sailing.gwt.ui.client;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface StringMessages extends Messages {
- String helloWorld();
- String kielWeel2011();
- String stgAccount();
- String tracTracEvents();
- String swissTimingEvents();
- String trackedBefore();
- String listRaces();
- String wind();
- String windPanelLabel();
- String refresh();
- String remove();
- String windSource();
- String dampeningInterval();
- String map();
- String race();
- String races();
- String tracked();
- String time();
- String playSpeed();
- String playSpeedHelp();
- String playModeLive();
- String playModeReplay();
- String timeDelay();
- String timeDelayHelp();
- String speedInKnots();
- String fromDeg();
- String noRacesYet();
- String total();
- String carry();
- String competitor();
- String competitors();
- String defaultLeaderboard();
- String noSuchLeaderboard();
- String leaderboardConfiguration();
- String newDotDotDot();
- String editScores();
- String columnNamesInSelectedLeaderboard();
- String addDotDotDot();
- String renameDotDotDot();
- String trackedRaceConnectedToSelectedRaceName();
- String linkToColumn();
- String unlink();
- String leaderboardName();
- String cancel();
- String pleaseEnterAName();
- String discardRacesFromHowManyStartedRacesOn();
- String leaderboardWithThisNameAlreadyExists();
- String discardThresholdsMustBeNumeric();
- String discardThresholdsMustBeAscending();
- String discarding();
- String startingFromNumberOfRaces();
- String renameLeaderboard();
- String addColumnToLeaderboard();
- String pleaseEnterNameForNewRaceColumn();
- String ok();
- String medalRace();
- String renameRace();
- String openSelectedLeaderboard();
- String rank();
- String totalRank();
- String collapse();
- String expand();
- String leg();
- String distanceInMeters();
- String distanceInMetersUnit();
- String averageSpeedInKnots();
- String averageSpeedInKnotsUnit();
- String rankGain();
- String sapSailingAnalytics();
- String leaderboard();
- String leaderboards();
- String leaderboardSettings();
- String settings();
- String selectAtLeastOneLegDetail();
- String currentSpeedOverGroundInKnots();
- String currentSpeedOverGroundInKnotsUnit();
- String estimatedTimeToNextWaypointInSeconds();
- String estimatedTimeToNextWaypointInSecondsUnit();
- String gapToLeaderInSeconds();
- String gapToLeaderInSecondsUnit();
- String velocityMadeGoodInKnots();
- String velocityMadeGoodInKnotsUnit();
- String windwardDistanceToGoInMeters();
- String windwardDistanceToLeaderInMeters();
- String windwardDistanceToGoInMetersUnit();
- String name();
- String leaveEmptyForDefault();
- String trackNewEvent();
- String trackableRaces();
- String trackWind();
- String regattaName();
- String eventName();
- String event();
- String startTime();
- String regatta();
- String regattas();
- String startTracking();
- String stopTracking();
- String connections();
- String historyOfConnections();
- String defineNewConnection();
- String trackedRaces();
- String canSendRequests();
- String connectAndReadRaces();
- String trackSettings();
- String ports();
- String liveData();
- String storedData();
- String uris();
- String jsonUrl();
- String livePort();
- String storedPort();
- String liveUri();
- String storedUri();
- String eventsConnectedTo();
- String hostname();
- String declinationCheckbox();
- String raceStartTrackingColumn();
- String pauseAutomaticRefresh();
- String autoRefresh();
- String delayInSeconds();
- String delayBetweenAutoAdvances();
- String delayMustBeNonNegative();
- String chooseUpdateIntervalOfAtLeastOneSecond();
- String errorSettingWindForRace();
- String errorFetchingWindInformationForRace();
- String errorWhileTryingToSetWindSourceForRace();
- String inEvent();
- String to();
- String showEstimatedWind();
- String timing();
- String raceDetailsToShow();
- String legDetailsToShow();
- String columnMoveUp();
- String columnMoveDown();
- String port();
- String raceStartTimeColumn();
- String showOnlySelectedCompetitors();
- String showSelectedCompetitorsInfo();
- String lengthInSeconds();
- String selectedRaces();
- String stressTest();
- String numberOfManeuvers();
- String tacks();
- String jibes();
- String penaltyCircles();
- String medalRaceIsNull();
- String maneuverTypes();
- String configuration();
- String chooseChart();
- String distanceTraveled();
- String velocityMadeGoodLong();
- String speedOverGroundLong();
- String gapToLeaderLong();
- String pointsToLoad();
- String speed();
- String distance();
- String in();
- String secondsUnit();
- String metersUnit();
- String failedToLoadRaceData();
- String close();
- String compareCompetitors();
- String description();
- String sailNumber();
- String country();
- String no3LetterCodes();
- String add();
- String delete();
- String showCharts();
- String raceWithThisNameAlreadyExists();
- String raceWithThisNameAlreadyExistsInRegatta();
- String headUp();
- String bearAway();
- String tack();
- String jibe();
- String penaltyCircle();
- String markPassing();
- String mark();
- String otherManeuver();
- String douglasPeuckerPoints();
- String filterRacesByName();
- String actionEdit();
- String actionEditScores();
- String actionOpenBrowser();
- String actionRemove();
- String actionEditRaces();
- String actionRaceEdit();
- String actionRaceUnlink();
- String actionRaceRemove();
- String filterLeaderboardsByName();
- String windwardDistanceToLeader();
- String actions();
- String islinked();
- String yes();
- String no();
- String hoverOverAPoint();
- String noSelection();
- String raceIsKnownToStartUpwind();
- String events();
- String settingsForComponent(String localizedComponentName);
- String noEventsFound();
- String noEventSelected();
- String noLeaderboardsFound();
- String searchEvents();
- String location();
- String from();
- String until();
- String onlyLiveEvents();
- String locationNotAvailable();
- String startDateNotAvailable();
- String startDate();
- String unknownManeuver();
- String tailLengthMustBePositive();
- String failedToLoadRaceInformation(String message);
- String competitorPassedMarkAtDate(String competitorName, String markName, String dateTime);
- String valueForCompetitorAt(String competitorName, String dateTime, String valueWithUnit);
- String reallyRemoveRace(String string);
- String showDetails();
- String hideLeaderboard();
- String hideLeaderboards();
- String showLeaderboard();
- String hideRaces();
- String showMap();
- String hideMap();
- String noLeaderboardSelected();
- String leaderboardGroups();
- String filterLeaderboardGroupsByName();
- String createNewLeaderboardGroup();
- String leaderboardGroupConfiguration();
- String legs();
- String currentLeg();
- String leaderboardGroup();
- String pleaseEnterNonEmptyDescription();
- String groupWithThisNameAlreadyExists();
- String detailsOfLeaderboardGroup();
- String edit();
- String save();
- String abort();
- String noLeaderboardGroupWithNameFound(String groupName);
- String overview();
- String welcomeToSailingAnalytics();
- String welcomeToSailingAnalyticsBody();
- String home();
- String clickAndDragToZoomIn();
- String windSpeed();
- String allTimesInUTC();
- String autoZoomTo();
- String autoZoomToBoats();
- String autoZoomToBuoys();
- String autoZoomOff();
- String autoZoomToTails();
- String autoZoomToWindSensors();
- String autoZoomSelectedCompetitors();
- String bearing();
- String zoom();
- String stepSizeMustBeGreaterThanNull();
- String stepSizeInSeconds();
- String refreshInterval();
- String refreshIntervalMustBeGreaterThanXSeconds(String seconds);
- String competitorCharts();
- String selectAtLeastOneCompetitor();
- String directionChange();
- String speedChange();
- String degreesShort();
- String untracked();
- String delayForLiveMode();
- String notAvailable();
- String details();
- String noGroupSelected();
- String combinedWindSourceTypeName();
- String courseBasedWindSourceTypeName();
- String trackBasedEstimationWindSourceTypeName();
- String expeditionWindSourceTypeName();
- String webWindSourceTypeName();
- String clickChartToSetTime();
- String position();
- String windSourcesUsed();
- String errorTryingToUpdateWindSourcesToExclude(String raceName, String message);
- String feedback();
- String startStopPlaying();
- String backToLive();
- String slowPlaySpeedDown();
- String speedPlaySpeedUp();
- String showHideComponent(String localizedShortName);
- String degreesBoatToTheWind();
- String racesInLeaderboard();
- String leaderboardsInGroup();
- String replication();
- String errorFetchingReplicaData(String message);
- String averageCrossTrackErrorInMeters();
- String enterMaster();
- String errorStartingReplication(String hostname, String exchangeName, String message);
- String helpLines();
- String startLine();
- String finishLine();
- String advantageLine();
- String courseMiddleLine();
- String messagingPortNumber();
- String servletPortNumber();
- String registeredAt(String string);
- String replicatingFromMaster(String hostname, int jmsPort, int servletPort);
- String showWindSpeedSeries();
- String showWindDirectionSeries();
- String fleet();
- String boatClass();
- String setDelayToLive();
- String pleaseEnterNonEmptyVenue();
- String eventWithThisNameAlreadyExists();
- String venue();
- String pleaseSelectABoatClass();
- String regattaWithThisNameAlreadyExists();
- String seriesWithThisNameAlreadyExists();
- String fleetWithThisNameAlreadyExists();
- String fleets();
- String series();
- String splitFleet();
- String color();
- String medalSeries();
- String noColor();
- String pleaseSelectARegatta();
- String addFleet();
- String doYouReallyWantToRemoveRegatta(String name);
- String errorLoadingScoreCorrectionProviders(String message);
- String selectResultListToImportFrom();
- String of();
- String errorObtainingScoreCorrections(String scoreCorrectionProviderName, String eventName, String boatClassName,
- String string, String message);
- String assignRaceNumbersToRaceColumns();
- String importOfficialResults();
- String selectAll();
- String apply();
- String successfullyUpdatedScores();
- String errorUpdatingScoresForLeaderboard(String leaderboardName, String message);
- String maneuverTypesToShowWhenCompetitorIsClicked();
- String simulateWithStartTimeNow();
- String boatClassDoesNotMatchSelectedRegatta(String boatClass, String regattaName);
- String regattaExistForSelectedBoatClass();
- String reload();
- String addRegatta();
- String exchangeName();
- String course();
- String courseLayout();
- String buoy();
- String gate();
- String buoys();
- String waypoint();
- String showAllCompetitors();
- String boatTails();
- String maximalCount();
- String maxVisibleCompetitorsCountMustBePositive();
- String fregResultImportUrls();
- String errorRefreshingFregUrlList(String message);
- String successfullyUpdatedFregUrls();
- String errorRemovingFregUrls(String message);
- String pleaseEnterNonEmptyUrl();
- String addFragUrl();
- String errorAddingFragUrl(String message);
- String errorTryingToObtainLeaderboardContents(String message);
- String lastScoreUpdate();
- String warningBrowserUnsupported();
- String newMark();
- String controlPoint();
- String errorUpdatingRaceCourse(String message);
- String successfullyUpdatedCourse();
- String selectOneMarkOrTwoMarksForGate();
- String errorTryingToObtainTheMarksOfTheRace(String message);
- String errorTryingToObtainRaceCourse(String message);
- String insertWaypointBeforeSelected();
- String insertWaypointAfterSelected();
- String scoringSchemeLowPointSystem();
- String scoringSchemeHighPointSystem();
- String scoringSystem();
- String createFlexibleLeaderboard();
- String createRegattaLeaderboard();
- String editFlexibleLeaderboard();
- String editRegattaLeaderboard();
- String noRegatta();
- String useOverallLeaderboard();
- String overallStandings();
- String scoringSchemeHighPointEssOverall();
- String scoringSchemeHighPointLastBreaksTie();
- String type();
- String actionAddRaces();
- String racesWithNamePrefix();
- String maximumSpeedOverGroundInKnots();
- String totalTimeSailedDownwindInSeconds();
- String totalTimeSailedUpwindInSeconds();
- String totalTimeSailedReachingInSeconds();
- String totalTimeSailedInSeconds();
- String overallDetailsToShow();
- String hhmmssUnit();
- String actionAddWindData();
- String valueMustBeBetweenMinMax(String name, String minValue, String maxValue);
- String optional();
- String pleaseEnterAValue();
- String latitude();
- String longitude();
- String actionAddEvent();
- String publicationUrl();
- String suppress();
- String isPublic();
- String unsuppress();
- String suppressedCompetitors();
- String pleaseSelectASeries();
- String pleaseSelectARace();
- String displayGroupsInReverseOrder();
- String actionConfigureUrl();
- String configureLeaderboardUrlDescription();
- String embedded();
- String additionalUrlSettings();
- String restrictToSingleSelectedRace();
- String expandSelectedRace();
- String showRaceDetails();
- String numberOfRaces();
- String numberOfRacesMustBeNonNegativeNumber();
- String chooseTheWayYouSelectRaces();
- String selectFromAllRaces();
- String selectANumberOfRaces();
- String numberOfLastNRaces();
- String expandLastRace();
- String factor();
- String errorUpdatingIsMedalRace(String message);
- String maneuverLoss();
- String averageManeuverLossInMeters();
- String averageTackLossInMeters();
- String averageJibeLossInMeters();
- String shape();
- String pattern();
- String legend();
- String live();
- String swissTimingArchiveConnector();
- String errorFetchingRankingChartData(String message);
- String loadingCompetitorData();
- String rankNAfterRace(long l, String string);
- String afterRace();
- String showRankChart();
- String overallLeaderboardSelection();
- String showOverallLeaderboardOnSamePage();
- String errorTryingToObtainOverallLeaderboards(String message);
- String finished();
- String passedTo(String name);
- String gapChangeSinceLegStartInSeconds();
- String sideToWhichMarkAtLegStartWasRounded();
- String raceIsLive(String raceName);
- String racesAreLive(String raceNames);
-}
+package com.sap.sailing.gwt.ui.client;
+
+import com.google.gwt.i18n.client.Messages;
+
+public interface StringMessages extends Messages {
+ String helloWorld();
+ String kielWeel2011();
+ String stgAccount();
+ String tracTracEvents();
+ String swissTimingEvents();
+ String trackedBefore();
+ String listRaces();
+ String wind();
+ String windPanelLabel();
+ String refresh();
+ String remove();
+ String windSource();
+ String dampeningInterval();
+ String map();
+ String race();
+ String races();
+ String tracked();
+ String time();
+ String playSpeed();
+ String playSpeedHelp();
+ String playModeLive();
+ String playModeReplay();
+ String timeDelay();
+ String timeDelayHelp();
+ String speedInKnots();
+ String fromDeg();
+ String noRacesYet();
+ String total();
+ String carry();
+ String competitor();
+ String competitors();
+ String defaultLeaderboard();
+ String noSuchLeaderboard();
+ String leaderboardConfiguration();
+ String newDotDotDot();
+ String editScores();
+ String columnNamesInSelectedLeaderboard();
+ String addDotDotDot();
+ String renameDotDotDot();
+ String trackedRaceConnectedToSelectedRaceName();
+ String linkToColumn();
+ String unlink();
+ String leaderboardName();
+ String cancel();
+ String pleaseEnterAName();
+ String discardRacesFromHowManyStartedRacesOn();
+ String leaderboardWithThisNameAlreadyExists();
+ String discardThresholdsMustBeNumeric();
+ String discardThresholdsMustBeAscending();
+ String discarding();
+ String startingFromNumberOfRaces();
+ String renameLeaderboard();
+ String addColumnToLeaderboard();
+ String pleaseEnterNameForNewRaceColumn();
+ String ok();
+ String medalRace();
+ String renameRace();
+ String openSelectedLeaderboard();
+ String rank();
+ String totalRank();
+ String collapse();
+ String expand();
+ String leg();
+ String distanceInMeters();
+ String distanceInMetersUnit();
+ String averageSpeedInKnots();
+ String averageSpeedInKnotsUnit();
+ String rankGain();
+ String sapSailingAnalytics();
+ String leaderboard();
+ String leaderboards();
+ String leaderboardSettings();
+ String settings();
+ String selectAtLeastOneLegDetail();
+ String currentSpeedOverGroundInKnots();
+ String currentSpeedOverGroundInKnotsUnit();
+ String estimatedTimeToNextWaypointInSeconds();
+ String estimatedTimeToNextWaypointInSecondsUnit();
+ String gapToLeaderInSeconds();
+ String gapToLeaderInSecondsUnit();
+ String velocityMadeGoodInKnots();
+ String velocityMadeGoodInKnotsUnit();
+ String windwardDistanceToGoInMeters();
+ String windwardDistanceToLeaderInMeters();
+ String windwardDistanceToGoInMetersUnit();
+ String name();
+ String leaveEmptyForDefault();
+ String trackNewEvent();
+ String trackableRaces();
+ String trackWind();
+ String regattaName();
+ String eventName();
+ String event();
+ String startTime();
+ String regatta();
+ String regattas();
+ String startTracking();
+ String stopTracking();
+ String connections();
+ String historyOfConnections();
+ String defineNewConnection();
+ String trackedRaces();
+ String canSendRequests();
+ String connectAndReadRaces();
+ String trackSettings();
+ String ports();
+ String liveData();
+ String storedData();
+ String uris();
+ String jsonUrl();
+ String livePort();
+ String storedPort();
+ String liveUri();
+ String storedUri();
+ String eventsConnectedTo();
+ String hostname();
+ String declinationCheckbox();
+ String raceStartTrackingColumn();
+ String pauseAutomaticRefresh();
+ String autoRefresh();
+ String delayInSeconds();
+ String delayBetweenAutoAdvances();
+ String delayMustBeNonNegative();
+ String chooseUpdateIntervalOfAtLeastOneSecond();
+ String errorSettingWindForRace();
+ String errorFetchingWindInformationForRace();
+ String errorWhileTryingToSetWindSourceForRace();
+ String inEvent();
+ String to();
+ String showEstimatedWind();
+ String timing();
+ String raceDetailsToShow();
+ String legDetailsToShow();
+ String columnMoveUp();
+ String columnMoveDown();
+ String port();
+ String raceStartTimeColumn();
+ String showOnlySelectedCompetitors();
+ String showSelectedCompetitorsInfo();
+ String lengthInSeconds();
+ String selectedRaces();
+ String stressTest();
+ String numberOfManeuvers();
+ String tacks();
+ String jibes();
+ String penaltyCircles();
+ String medalRaceIsNull();
+ String maneuverTypes();
+ String configuration();
+ String chooseChart();
+ String distanceTraveled();
+ String velocityMadeGoodLong();
+ String speedOverGroundLong();
+ String gapToLeaderLong();
+ String pointsToLoad();
+ String speed();
+ String distance();
+ String in();
+ String secondsUnit();
+ String metersUnit();
+ String failedToLoadRaceData();
+ String close();
+ String compareCompetitors();
+ String description();
+ String sailNumber();
+ String country();
+ String no3LetterCodes();
+ String add();
+ String delete();
+ String showCharts();
+ String raceWithThisNameAlreadyExists();
+ String raceWithThisNameAlreadyExistsInRegatta();
+ String headUp();
+ String bearAway();
+ String tack();
+ String jibe();
+ String penaltyCircle();
+ String markPassing();
+ String mark();
+ String otherManeuver();
+ String douglasPeuckerPoints();
+ String filterRacesByName();
+ String actionEdit();
+ String actionEditScores();
+ String actionOpenBrowser();
+ String actionRemove();
+ String actionEditRaces();
+ String actionRaceEdit();
+ String actionRaceUnlink();
+ String actionRaceRemove();
+ String filterLeaderboardsByName();
+ String windwardDistanceToLeader();
+ String actions();
+ String islinked();
+ String yes();
+ String no();
+ String hoverOverAPoint();
+ String noSelection();
+ String raceIsKnownToStartUpwind();
+ String events();
+ String settingsForComponent(String localizedComponentName);
+ String noEventsFound();
+ String noEventSelected();
+ String noLeaderboardsFound();
+ String searchEvents();
+ String location();
+ String from();
+ String until();
+ String onlyLiveEvents();
+ String locationNotAvailable();
+ String startDateNotAvailable();
+ String startDate();
+ String unknownManeuver();
+ String tailLengthMustBePositive();
+ String failedToLoadRaceInformation(String message);
+ String competitorPassedMarkAtDate(String competitorName, String markName, String dateTime);
+ String valueForCompetitorAt(String competitorName, String dateTime, String valueWithUnit);
+ String reallyRemoveRace(String string);
+ String showDetails();
+ String hideLeaderboard();
+ String hideLeaderboards();
+ String showLeaderboard();
+ String hideRaces();
+ String showMap();
+ String hideMap();
+ String noLeaderboardSelected();
+ String leaderboardGroups();
+ String filterLeaderboardGroupsByName();
+ String createNewLeaderboardGroup();
+ String leaderboardGroupConfiguration();
+ String legs();
+ String currentLeg();
+ String leaderboardGroup();
+ String pleaseEnterNonEmptyDescription();
+ String groupWithThisNameAlreadyExists();
+ String detailsOfLeaderboardGroup();
+ String edit();
+ String save();
+ String abort();
+ String noLeaderboardGroupWithNameFound(String groupName);
+ String overview();
+ String welcomeToSailingAnalytics();
+ String welcomeToSailingAnalyticsBody();
+ String home();
+ String clickAndDragToZoomIn();
+ String windSpeed();
+ String allTimesInUTC();
+ String autoZoomTo();
+ String autoZoomToBoats();
+ String autoZoomToBuoys();
+ String autoZoomOff();
+ String autoZoomToTails();
+ String autoZoomToWindSensors();
+ String autoZoomSelectedCompetitors();
+ String bearing();
+ String zoom();
+ String stepSizeMustBeGreaterThanNull();
+ String stepSizeInSeconds();
+ String refreshInterval();
+ String refreshIntervalMustBeGreaterThanXSeconds(String seconds);
+ String competitorCharts();
+ String selectAtLeastOneCompetitor();
+ String directionChange();
+ String speedChange();
+ String degreesShort();
+ String untracked();
+ String delayForLiveMode();
+ String notAvailable();
+ String details();
+ String noGroupSelected();
+ String combinedWindSourceTypeName();
+ String courseBasedWindSourceTypeName();
+ String trackBasedEstimationWindSourceTypeName();
+ String expeditionWindSourceTypeName();
+ String webWindSourceTypeName();
+ String clickChartToSetTime();
+ String position();
+ String windSourcesUsed();
+ String errorTryingToUpdateWindSourcesToExclude(String raceName, String message);
+ String feedback();
+ String startStopPlaying();
+ String backToLive();
+ String slowPlaySpeedDown();
+ String speedPlaySpeedUp();
+ String showHideComponent(String localizedShortName);
+ String degreesBoatToTheWind();
+ String racesInLeaderboard();
+ String leaderboardsInGroup();
+ String replication();
+ String errorFetchingReplicaData(String message);
+ String averageCrossTrackErrorInMeters();
+ String enterMaster();
+ String errorStartingReplication(String hostname, String exchangeName, String message);
+ String helpLines();
+ String startLine();
+ String finishLine();
+ String advantageLine();
+ String courseMiddleLine();
+ String messagingPortNumber();
+ String servletPortNumber();
+ String registeredAt(String string);
+ String replicatingFromMaster(String hostname, int jmsPort, int servletPort);
+ String showWindSpeedSeries();
+ String showWindDirectionSeries();
+ String fleet();
+ String boatClass();
+ String setDelayToLive();
+ String pleaseEnterNonEmptyVenue();
+ String eventWithThisNameAlreadyExists();
+ String venue();
+ String pleaseSelectABoatClass();
+ String regattaWithThisNameAlreadyExists();
+ String seriesWithThisNameAlreadyExists();
+ String fleetWithThisNameAlreadyExists();
+ String fleets();
+ String series();
+ String splitFleet();
+ String color();
+ String medalSeries();
+ String noColor();
+ String pleaseSelectARegatta();
+ String addFleet();
+ String doYouReallyWantToRemoveRegatta(String name);
+ String errorLoadingScoreCorrectionProviders(String message);
+ String selectResultListToImportFrom();
+ String of();
+ String errorObtainingScoreCorrections(String scoreCorrectionProviderName, String eventName, String boatClassName,
+ String string, String message);
+ String assignRaceNumbersToRaceColumns();
+ String importOfficialResults();
+ String selectAll();
+ String apply();
+ String successfullyUpdatedScores();
+ String errorUpdatingScoresForLeaderboard(String leaderboardName, String message);
+ String maneuverTypesToShowWhenCompetitorIsClicked();
+ String simulateWithStartTimeNow();
+ String boatClassDoesNotMatchSelectedRegatta(String boatClass, String regattaName);
+ String regattaExistForSelectedBoatClass();
+ String reload();
+ String addRegatta();
+ String exchangeName();
+ String course();
+ String courseLayout();
+ String buoy();
+ String gate();
+ String buoys();
+ String waypoint();
+ String showAllCompetitors();
+ String boatTails();
+ String maximalCount();
+ String maxVisibleCompetitorsCountMustBePositive();
+ String fregResultImportUrls();
+ String errorRefreshingFregUrlList(String message);
+ String successfullyUpdatedFregUrls();
+ String errorRemovingFregUrls(String message);
+ String pleaseEnterNonEmptyUrl();
+ String addFragUrl();
+ String errorAddingFragUrl(String message);
+ String errorTryingToObtainLeaderboardContents(String message);
+ String lastScoreUpdate();
+ String warningBrowserUnsupported();
+ String newMark();
+ String controlPoint();
+ String errorUpdatingRaceCourse(String message);
+ String successfullyUpdatedCourse();
+ String selectOneMarkOrTwoMarksForGate();
+ String errorTryingToObtainTheMarksOfTheRace(String message);
+ String errorTryingToObtainRaceCourse(String message);
+ String insertWaypointBeforeSelected();
+ String insertWaypointAfterSelected();
+ String scoringSchemeLowPointSystem();
+ String scoringSchemeHighPointSystem();
+ String scoringSystem();
+ String createFlexibleLeaderboard();
+ String createRegattaLeaderboard();
+ String editFlexibleLeaderboard();
+ String editRegattaLeaderboard();
+ String noRegatta();
+ String useOverallLeaderboard();
+ String overallStandings();
+ String scoringSchemeHighPointEssOverall();
+ String scoringSchemeHighPointLastBreaksTie();
+ String type();
+ String actionAddRaces();
+ String racesWithNamePrefix();
+ String maximumSpeedOverGroundInKnots();
+ String totalTimeSailedDownwindInSeconds();
+ String totalTimeSailedUpwindInSeconds();
+ String totalTimeSailedReachingInSeconds();
+ String totalTimeSailedInSeconds();
+ String overallDetailsToShow();
+ String hhmmssUnit();
+ String actionAddWindData();
+ String valueMustBeBetweenMinMax(String name, String minValue, String maxValue);
+ String optional();
+ String pleaseEnterAValue();
+ String latitude();
+ String longitude();
+ String actionAddEvent();
+ String publicationUrl();
+ String suppress();
+ String isPublic();
+ String unsuppress();
+ String suppressedCompetitors();
+ String pleaseSelectASeries();
+ String pleaseSelectARace();
+ String displayGroupsInReverseOrder();
+ String actionConfigureUrl();
+ String configureLeaderboardUrlDescription();
+ String embedded();
+ String mediaPanel();
+ String url();
+ String mimeType();
+ String title();
+ String reallyRemoveMediaTrack(String mediaTrackTitle);
+ String duration();
+ String addMediaTrack();
+ String addYoutubeTrack();
+ String youtubeId();
+ String additionalUrlSettings();
+ String restrictToSingleSelectedRace();
+ String expandSelectedRace();
+ String showRaceDetails();
+ String numberOfRaces();
+ String numberOfRacesMustBeNonNegativeNumber();
+ String chooseTheWayYouSelectRaces();
+ String selectFromAllRaces();
+ String selectANumberOfRaces();
+ String numberOfLastNRaces();
+ String expandLastRace();
+ String factor();
+ String errorUpdatingIsMedalRace(String message);
+ String maneuverLoss();
+ String averageManeuverLossInMeters();
+ String averageTackLossInMeters();
+ String averageJibeLossInMeters();
+ String shape();
+ String pattern();
+ String legend();
+ String live();
+ String swissTimingArchiveConnector();
+ String errorFetchingRankingChartData(String message);
+ String loadingCompetitorData();
+ String rankNAfterRace(long l, String string);
+ String afterRace();
+ String showRankChart();
+ String overallLeaderboardSelection();
+ String showOverallLeaderboardOnSamePage();
+ String errorTryingToObtainOverallLeaderboards(String message);
+ String finished();
+ String passedTo(String name);
+ String gapChangeSinceLegStartInSeconds();
+ String sideToWhichMarkAtLegStartWasRounded();
+ String raceIsLive(String raceName);
+ String racesAreLive(String raceNames);
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
index 6ab441629d0..3bd92fd18fa 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
@@ -408,6 +408,15 @@ isPublic=Is public
suppress=Suppress
unsuppress=Unsuppress
suppressedCompetitors=Suppressed Competitors
+mediaPanel=Audio & Video
+url=URL
+mimeType=MIME Type
+title=Title
+duration=Duration (h:mm:ss.ms)
+addMediaTrack=Add Audio/Video
+addYoutubeTrack=Add Youtube
+youtubeId=Youtube Id
+reallyRemoveMediaTrack=Do you really want to remove media track ''{0}''?
pleaseSelectASeries=Please select a series
pleaseSelectARace=Please select a race
displayGroupsInReverseOrder=Display groups in reverse order
@@ -449,4 +458,4 @@ passedTo=passed to {0}
gapChangeSinceLegStartInSeconds=Gap Change
sideToWhichMarkAtLegStartWasRounded=Mark rounded to
raceIsLive=Race {0} is live
-racesAreLive=Races {0} are live
+racesAreLive=Races {0} are live
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
index a694852f740..160baa7424e 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
@@ -409,6 +409,15 @@ isPublic=Öffentlich zugänglich
suppress=Entfernen
unsuppress=Wieder hinzufügen
suppressedCompetitors=Unterdrückte Wettkampfteilnehmer
+mediaPanel=Audio & Video
+url=URL
+mimeType=MIME Type
+title=Titel
+duration=Dauer (h:mm:ss.ms)
+addMediaTrack=Audio/Video hinzufügen
+addYoutubeTrack=Youtube hinzufügen
+youtubeId=Youtube Id
+reallyRemoveMediaTrack=Möchten Sie ''{0}'' wirklich entfernen?
pleaseSelectASeries=Bitte wählen Sie eine Serie aus
pleaseSelectARace=Bitte wählen Sie ein Rennen aus
displayGroupsInReverseOrder=Zeige die Gruppen in umgekehrter Reihenfolge
@@ -445,9 +454,9 @@ showRankChart=Rang-Diagramm anzeigen
overallLeaderboardSelection=Gesamtergebnisse
showOverallLeaderboardOnSamePage=Gesamtergebnisse auf derselben Seite anzeigen
errorTryingToObtainOverallLeaderboards=Fehler beim Laden der Gesamtergebnisse: {0}
-finished=beendet
+finished=beendet
passedTo=an {0} gerundet
gapChangeSinceLegStartInSeconds=Gap Änderung
-sideToWhichMarkAtLegStartWasRounded=Tonne gerundet an
+sideToWhichMarkAtLegStartWasRounded=Tonne gerundet an
raceIsLive=Rennen {0} ist live
racesAreLive=Rennen {0} sind live
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java
index 16337004786..4d962fc9260 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/TimePanel.java
@@ -1,497 +1,502 @@
-package com.sap.sailing.gwt.ui.client;
-
-import java.util.Date;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.IntegerBox;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RequiresResize;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
-import com.sap.sailing.gwt.ui.client.Timer.PlayStates;
-import com.sap.sailing.gwt.ui.shared.components.Component;
-import com.sap.sailing.gwt.ui.shared.components.SettingsDialog;
-import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
-import com.sap.sailing.gwt.ui.shared.controls.slider.SliderBar;
-import com.sap.sailing.gwt.ui.shared.controls.slider.TimeSlider;
-
-public class TimePanelnull
- * @param max must not be null
- */
- public void setMinMax(Date min, Date max, boolean fireEvent) {
- assert min != null && max != null;
-
- boolean changed = false;
- if (!max.equals(timeRangeProvider.getToTime())) {
- changed = true;
- timeSlider.setMaxValue(new Double(max.getTime()), fireEvent);
- }
- if (!min.equals(timeRangeProvider.getFromTime())) {
- changed = true;
- timeSlider.setMinValue(new Double(min.getTime()), fireEvent);
- if (timeSlider.getCurrentValue() == null) {
- timeSlider.setCurrentValue(new Double(min.getTime()), fireEvent);
- }
- }
- if (changed) {
- if(!timeRangeProvider.isZoomed()) {
- timeRangeProvider.setTimeRange(min, max, this);
- }
-
- int numSteps = timeSlider.getElement().getClientWidth();
- if (numSteps > 0) {
- timeSlider.setStepSize(numSteps, fireEvent);
- } else {
- timeSlider.setStepSize(1000, fireEvent);
- }
- }
- }
-
- public void resetTimeSlider() {
- timeSlider.clearMarkers();
- timeSlider.redraw();
- }
-
- @Override
- public void playStateChanged(PlayStates playState, PlayModes playMode) {
- boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
- setLiveGenerallyPossible(liveModeToBeMadePossible);
- setJumpToLiveEnablement(liveModeToBeMadePossible && playMode != PlayModes.Live);
- switch (playState) {
- case Playing:
- playPauseButton.getElement().addClassName("playPauseButtonPause");
- if (playMode == PlayModes.Live) {
- playModeImage.setResource(playModeLiveActiveImg);
- } else {
- playModeImage.setResource(playModeReplayActiveImg);
- }
- break;
- case Paused:
- playPauseButton.getElement().removeClassName("playPauseButtonPause");
- case Stopped:
- playPauseButton.getElement().removeClassName("playPauseButtonPause");
- playModeImage.setResource(playModeInactiveImg);
- break;
- }
-
- switch (playMode) {
- case Live:
- playModeLabel.setText(stringMessages.playModeLive());
- timeDelayLabel.setText(stringMessages.timeDelay() + ": " + timer.getCurrentDelayInMillis() / 1000 + " s");
- timeDelayLabel.setVisible(true);
- timeSlider.setEnabled(true);
- playSpeedBox.setEnabled(false);
- slowDownButton.setEnabled(false);
- speedUpButton.setEnabled(false);
- break;
- case Replay:
- timeDelayLabel.setVisible(false);
- timeDelayLabel.setText("");
- playModeLabel.setText(stringMessages.playModeReplay());
- timeSlider.setEnabled(true);
- playSpeedBox.setEnabled(true);
- slowDownButton.setEnabled(true);
- speedUpButton.setEnabled(true);
- break;
- }
- }
-
- @Override
- public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
- }
-
- @Override
- public void onTimeZoomReset() {
- }
-
- @Override
- public void onTimeRangeChanged(Date fromTime, Date toTime) {
- }
-
- protected boolean isLiveModeToBeMadePossible() {
- return false;
- }
-
- /**
- * Enables the {@link #backToLivePlayButton} if and only if enabled is true.
- */
- protected void setJumpToLiveEnablement(boolean enabled) {
- backToLivePlayButton.setEnabled(enabled);
- }
-
- /**
- * Iff possible, makes the {@link #backToLivePlayButton} button visible.
- */
- protected void setLiveGenerallyPossible(boolean possible) {
- backToLivePlayButton.setVisible(possible);
- }
-
- @SuppressWarnings("unchecked")
- public T getSettings() {
- TimePanelSettings result = new TimePanelSettings();
- result.setDelayToLivePlayInSeconds(timer.getLivePlayDelayInMillis()/1000);
- result.setRefreshInterval(timer.getRefreshInterval());
- return (T) result;
- }
-
- @Override
- public Widget getEntryWidget() {
- return this;
- }
-
- @Override
- public boolean hasSettings() {
- return true;
- }
-
- @Override
- public SettingsDialogComponentnull
+ * @param max must not be null
+ */
+ public void setMinMax(Date min, Date max, boolean fireEvent) {
+ assert min != null && max != null;
+
+ boolean changed = false;
+ if (!max.equals(timeRangeProvider.getToTime())) {
+ changed = true;
+ timeSlider.setMaxValue(new Double(max.getTime()), fireEvent);
+ }
+ if (!min.equals(timeRangeProvider.getFromTime())) {
+ changed = true;
+ timeSlider.setMinValue(new Double(min.getTime()), fireEvent);
+ if (timeSlider.getCurrentValue() == null) {
+ timeSlider.setCurrentValue(new Double(min.getTime()), fireEvent);
+ }
+ }
+ if (changed) {
+ if(!timeRangeProvider.isZoomed()) {
+ timeRangeProvider.setTimeRange(min, max, this);
+ }
+
+ int numSteps = timeSlider.getElement().getClientWidth();
+ if (numSteps > 0) {
+ timeSlider.setStepSize(numSteps, fireEvent);
+ } else {
+ timeSlider.setStepSize(1000, fireEvent);
+ }
+ }
+ }
+
+ public void resetTimeSlider() {
+ timeSlider.clearMarkers();
+ timeSlider.redraw();
+ }
+
+ @Override
+ public void playStateChanged(PlayStates playState, PlayModes playMode) {
+ boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
+ setLiveGenerallyPossible(liveModeToBeMadePossible);
+ setJumpToLiveEnablement(liveModeToBeMadePossible && playMode != PlayModes.Live);
+ switch (playState) {
+ case Playing:
+ playPauseButton.getElement().addClassName("playPauseButtonPause");
+ if (playMode == PlayModes.Live) {
+ playModeImage.setResource(playModeLiveActiveImg);
+ } else {
+ playModeImage.setResource(playModeReplayActiveImg);
+ }
+ break;
+ case Paused:
+ playPauseButton.getElement().removeClassName("playPauseButtonPause");
+ case Stopped:
+ playPauseButton.getElement().removeClassName("playPauseButtonPause");
+ playModeImage.setResource(playModeInactiveImg);
+ break;
+ }
+
+ switch (playMode) {
+ case Live:
+ playModeLabel.setText(stringMessages.playModeLive());
+ timeDelayLabel.setText(stringMessages.timeDelay() + ": " + timer.getCurrentDelayInMillis() / 1000 + " s");
+ timeDelayLabel.setVisible(true);
+ timeSlider.setEnabled(true);
+ playSpeedBox.setEnabled(false);
+ slowDownButton.setEnabled(false);
+ speedUpButton.setEnabled(false);
+ break;
+ case Replay:
+ timeDelayLabel.setVisible(false);
+ timeDelayLabel.setText("");
+ playModeLabel.setText(stringMessages.playModeReplay());
+ timeSlider.setEnabled(true);
+ playSpeedBox.setEnabled(true);
+ slowDownButton.setEnabled(true);
+ speedUpButton.setEnabled(true);
+ break;
+ }
+ }
+
+ @Override
+ public void playSpeedFactorChanged(double newPlaySpeedFactor) {
+ // nothing to do
+ }
+
+ @Override
+ public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
+ }
+
+ @Override
+ public void onTimeZoomReset() {
+ }
+
+ @Override
+ public void onTimeRangeChanged(Date fromTime, Date toTime) {
+ }
+
+ protected boolean isLiveModeToBeMadePossible() {
+ return false;
+ }
+
+ /**
+ * Enables the {@link #backToLivePlayButton} if and only if enabled is true.
+ */
+ protected void setJumpToLiveEnablement(boolean enabled) {
+ backToLivePlayButton.setEnabled(enabled);
+ }
+
+ /**
+ * Iff possible, makes the {@link #backToLivePlayButton} button visible.
+ */
+ protected void setLiveGenerallyPossible(boolean possible) {
+ backToLivePlayButton.setVisible(possible);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getSettings() {
+ TimePanelSettings result = new TimePanelSettings();
+ result.setDelayToLivePlayInSeconds(timer.getLivePlayDelayInMillis()/1000);
+ result.setRefreshInterval(timer.getRefreshInterval());
+ return (T) result;
+ }
+
+ @Override
+ public Widget getEntryWidget() {
+ return this;
+ }
+
+ @Override
+ public boolean hasSettings() {
+ return true;
+ }
+
+ @Override
+ public SettingsDialogComponentPlaying, an auto-refreshing command is running with {@link #refreshInterval}
- * as its refresh interval.
- */
- private PlayStates playState;
-
- /**
- * The current play mode of the timer: live or replay. In live mode the timer will adjust to now-delay each time it
- * refreshes. In replay mode it will advance time by the refresh interval times the play speed factor.
- */
- private PlayModes playMode;
-
- /**
- * The refresh interval in milliseconds for auto-updating this timer
- */
- private long refreshInterval;
-
- /**
- * Set to true if the refreshInterval changed while {@link #playing}. This forces the auto-refreshing command
- * to re-schedule itself with the new interval, then terminate.
- */
- private boolean refreshIntervalChanged;
-
- /**
- * Factor by which the timer runs faster than real time. 1.0 means real-time, 2.0 means twice as fast as real time, and so on.
- * Applies only if the timer is in replay mode.
- */
- private double playSpeedFactor;
-
- /**
- * Set to true to enable the timer to advance the max time automatically if the current time gets greater than the max time
- */
- private boolean autoAdvance;
-
- /**
- * The timer can run in two different modes: Live and Replay
- * 'Live' means the timer is used for a real time event
- * 'Replay' means the timer is used for an already finished event in the past
- */
- public enum PlayModes { Live, Replay };
-
- public enum PlayStates { Stopped, Playing, Paused };
-
- /**
- * The timer is created in stopped state, using "now" as its current time, 1.0 as its {@link #playSpeedFactor play speed factor} and
- * 1 second (1000ms) as the {@link #refreshInterval delay between automatic updates} should the timer be
- * {@link #resume() started}.
- */
- public Timer(PlayModes playMode) {
- this(playMode, 1000);
- }
-
- /**
- * The timer is created in stopped state, using "now" as its current time, 1.0 as its {@link #playSpeedFactor
- * acceleration factor} and delayBetweenAutoAdvancesInMilliseconds as the
- * {@link #refreshInterval delay between automatic updates} should the timer be
- * {@link #resume() started}. The {@link #livePlayDelayInMillis} is set to zero seconds.
- */
- public Timer(PlayModes playMode, long refreshInterval) {
- this.refreshInterval = refreshInterval;
- time = new Date();
- timeListeners = new HashSetfalse if not already
- * paused, and registered {@link PlayStateListener}s will be notified. If the play mode was live, it'll be set to
- * replay.
- */
- public void pause() {
- if (playState == PlayStates.Playing) {
- playState = PlayStates.Paused; // this will cause the repeating command to stop executing
- for (PlayStateListener playStateListener : playStateListeners) {
- playStateListener.playStateChanged(playState, playMode);
- }
- setPlayMode(PlayModes.Replay);
- }
- }
-
- /**
- * Puts the timer into the stopped state. If it was in live mode, puts it into replay mode.
- */
- public void stop() {
- if (playState == PlayStates.Playing) {
- playState = PlayStates.Stopped;
- for (PlayStateListener playStateListener : playStateListeners) {
- playStateListener.playStateChanged(playState, playMode);
- }
- setPlayMode(PlayModes.Replay);
- }
- }
-
- public void play() {
- if (playState != PlayStates.Playing) {
- playState = PlayStates.Playing;
- if (playMode == PlayModes.Live) {
- setTime(System.currentTimeMillis()-livePlayDelayInMillis);
- }
- if (autoAdvance) {
- startAutoAdvance();
- }
- for (PlayStateListener playStateListener : playStateListeners) {
- playStateListener.playStateChanged(playState, playMode);
- }
- }
- }
-
- private void startAutoAdvance() {
- RepeatingCommand command = new RepeatingCommand() {
- @Override
- public boolean execute() {
- if (time != null && playState == PlayStates.Playing) {
- long newTime = time.getTime();
- if (playMode == PlayModes.Replay) {
- newTime += (long) playSpeedFactor * refreshInterval;
- } else {
- // play mode is Live; quantize to make cache hits more likely
- newTime = quantizeTimeStamp(System.currentTimeMillis() - getLivePlayDelayInMillis());
- }
- setTime(newTime);
- }
- if (refreshIntervalChanged) {
- refreshIntervalChanged = false;
- scheduleAdvancerCommand(this);
- return false; // stop this command; use the newly-scheduled one instead that uses the new frequency
- } else {
- return playState == PlayStates.Playing ? true: false;
- }
- }
-
- };
- scheduleAdvancerCommand(command);
- }
-
- /**
- * In {@link PlayModes#Live live mode}, time stamps are quantized to make it more likely for the back-end to achieve
- * a cache hit. Quantization is controlled by the {@link #LIVE_CLOCK_QUANTUM} constant.
- */
- private long quantizeTimeStamp(long millis) {
- return millis - (millis % LIVE_CLOCK_QUANTUM);
- }
-
- private void scheduleAdvancerCommand(RepeatingCommand command) {
- Scheduler.get().scheduleFixedPeriod(command, (int) refreshInterval);
- }
-
- public void setLivePlayDelayInMillis(long delayInMilliseconds) {
- if (this.livePlayDelayInMillis != delayInMilliseconds) {
- this.livePlayDelayInMillis = delayInMilliseconds;
- if (getPlayMode() == PlayModes.Live) {
- setTime(new Date().getTime() - delayInMilliseconds);
- }
- }
- }
-
- /**
- * Tells how much the timer is currently behind "now." Note that this is not the same as asking
- * {@link #getLivePlayDelayInMillis()} which tells the delay that will be established if the timer is put
- * into live mode.
- */
- public long getCurrentDelayInMillis() {
- return System.currentTimeMillis() - getTime().getTime();
- }
-
- public long getLivePlayDelayInMillis() {
- return livePlayDelayInMillis;
- }
-
- public PlayStates getPlayState() {
- return playState;
- }
-
- public PlayModes getPlayMode() {
- return playMode;
- }
-
- public boolean isAutoAdvance() {
- return autoAdvance;
- }
-
- public void setAutoAdvance(boolean autoAdvance) {
- this.autoAdvance = autoAdvance;
- }
-}
+package com.sap.sailing.gwt.ui.client;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.RepeatingCommand;
+
+/**
+ * Manages a timer and can auto-advance it at a given acceleration/deceleration rate, with a given delay compared to
+ * real time. It can be {@link #pause() paused} and {@link #resume() resumed}. It can be in one of two play modes:
+ * {@link PlayModes#Live} and {@link PlayModes#Replay}. In live play mode the timer is always in state {@link PlayStates#Playing}
+ * and adjusts the time to now-{@link #livePlayDelayInMillis}. As soon as it's paused or stopped it enters
+ * {@link PlayModes#Replay}. By entering {@link PlayModes#Live} with {@link #setPlayMode(PlayModes)}, the timer starts
+ * playing right away.
+ *
+ * @author Axel Uhl (d043530)
+ *
+ */
+public class Timer {
+ /**
+ * Used by {@link #quantizeTimeStamp(long)}; currently set to 1s (1000ms)
+ */
+ private static final long LIVE_CLOCK_QUANTUM = 1000;
+
+ /**
+ * The time point represented by this timer
+ */
+ private Date time;
+
+ /**
+ * The time delay to the current point in time in millisseconds which
+ * will only be used in {@link PlayModes#Live} play mode.
+ */
+ private long livePlayDelayInMillis;
+
+ /**
+ * Listeners interested in changes of {@link #time}
+ */
+ private final SetPlaying, an auto-refreshing command is running with {@link #refreshInterval}
+ * as its refresh interval.
+ */
+ private PlayStates playState;
+
+ /**
+ * The current play mode of the timer: live or replay. In live mode the timer will adjust to now-delay each time it
+ * refreshes. In replay mode it will advance time by the refresh interval times the play speed factor.
+ */
+ private PlayModes playMode;
+
+ /**
+ * The refresh interval in milliseconds for auto-updating this timer
+ */
+ private long refreshInterval;
+
+ /**
+ * Set to true if the refreshInterval changed while {@link #playing}. This forces the auto-refreshing command
+ * to re-schedule itself with the new interval, then terminate.
+ */
+ private boolean refreshIntervalChanged;
+
+ /**
+ * Factor by which the timer runs faster than real time. 1.0 means real-time, 2.0 means twice as fast as real time, and so on.
+ * Applies only if the timer is in replay mode.
+ */
+ private double playSpeedFactor;
+
+ /**
+ * Set to true to enable the timer to advance the max time automatically if the current time gets greater than the max time
+ */
+ private boolean autoAdvance;
+
+ /**
+ * The timer can run in two different modes: Live and Replay
+ * 'Live' means the timer is used for a real time event
+ * 'Replay' means the timer is used for an already finished event in the past
+ */
+ public enum PlayModes { Live, Replay };
+
+ public enum PlayStates { Stopped, Playing, Paused };
+
+ /**
+ * The timer is created in stopped state, using "now" as its current time, 1.0 as its {@link #playSpeedFactor play speed factor} and
+ * 1 second (1000ms) as the {@link #refreshInterval delay between automatic updates} should the timer be
+ * {@link #resume() started}.
+ */
+ public Timer(PlayModes playMode) {
+ this(playMode, 1000);
+ }
+
+ /**
+ * The timer is created in stopped state, using "now" as its current time, 1.0 as its {@link #playSpeedFactor
+ * acceleration factor} and delayBetweenAutoAdvancesInMilliseconds as the
+ * {@link #refreshInterval delay between automatic updates} should the timer be
+ * {@link #resume() started}. The {@link #livePlayDelayInMillis} is set to zero seconds.
+ */
+ public Timer(PlayModes playMode, long refreshInterval) {
+ this.refreshInterval = refreshInterval;
+ time = new Date();
+ timeListeners = new HashSetfalse if not already
+ * paused, and registered {@link PlayStateListener}s will be notified. If the play mode was live, it'll be set to
+ * replay.
+ */
+ public void pause() {
+ if (playState == PlayStates.Playing) {
+ playState = PlayStates.Paused; // this will cause the repeating command to stop executing
+ for (PlayStateListener playStateListener : playStateListeners) {
+ playStateListener.playStateChanged(playState, playMode);
+ }
+ setPlayMode(PlayModes.Replay);
+ }
+ }
+
+ /**
+ * Puts the timer into the stopped state. If it was in live mode, puts it into replay mode.
+ */
+ public void stop() {
+ if (playState == PlayStates.Playing) {
+ playState = PlayStates.Stopped;
+ for (PlayStateListener playStateListener : playStateListeners) {
+ playStateListener.playStateChanged(playState, playMode);
+ }
+ setPlayMode(PlayModes.Replay);
+ }
+ }
+
+ public void play() {
+ if (playState != PlayStates.Playing) {
+ playState = PlayStates.Playing;
+ if (playMode == PlayModes.Live) {
+ setTime(System.currentTimeMillis()-livePlayDelayInMillis);
+ }
+ if (autoAdvance) {
+ startAutoAdvance();
+ }
+ for (PlayStateListener playStateListener : playStateListeners) {
+ playStateListener.playStateChanged(playState, playMode);
+ }
+ }
+ }
+
+ private void startAutoAdvance() {
+ RepeatingCommand command = new RepeatingCommand() {
+ @Override
+ public boolean execute() {
+ if (time != null && playState == PlayStates.Playing) {
+ long newTime = time.getTime();
+ if (playMode == PlayModes.Replay) {
+ newTime += (long) playSpeedFactor * refreshInterval;
+ } else {
+ // play mode is Live; quantize to make cache hits more likely
+ newTime = quantizeTimeStamp(System.currentTimeMillis() - getLivePlayDelayInMillis());
+ }
+ setTime(newTime);
+ }
+ if (refreshIntervalChanged) {
+ refreshIntervalChanged = false;
+ scheduleAdvancerCommand(this);
+ return false; // stop this command; use the newly-scheduled one instead that uses the new frequency
+ } else {
+ return playState == PlayStates.Playing ? true: false;
+ }
+ }
+
+ };
+ scheduleAdvancerCommand(command);
+ }
+
+ /**
+ * In {@link PlayModes#Live live mode}, time stamps are quantized to make it more likely for the back-end to achieve
+ * a cache hit. Quantization is controlled by the {@link #LIVE_CLOCK_QUANTUM} constant.
+ */
+ private long quantizeTimeStamp(long millis) {
+ return millis - (millis % LIVE_CLOCK_QUANTUM);
+ }
+
+ private void scheduleAdvancerCommand(RepeatingCommand command) {
+ Scheduler.get().scheduleFixedPeriod(command, (int) refreshInterval);
+ }
+
+ public void setLivePlayDelayInMillis(long delayInMilliseconds) {
+ if (this.livePlayDelayInMillis != delayInMilliseconds) {
+ this.livePlayDelayInMillis = delayInMilliseconds;
+ if (getPlayMode() == PlayModes.Live) {
+ setTime(new Date().getTime() - delayInMilliseconds);
+ }
+ }
+ }
+
+ /**
+ * Tells how much the timer is currently behind "now." Note that this is not the same as asking
+ * {@link #getLivePlayDelayInMillis()} which tells the delay that will be established if the timer is put
+ * into live mode.
+ */
+ public long getCurrentDelayInMillis() {
+ return System.currentTimeMillis() - getTime().getTime();
+ }
+
+ public long getLivePlayDelayInMillis() {
+ return livePlayDelayInMillis;
+ }
+
+ public PlayStates getPlayState() {
+ return playState;
+ }
+
+ public PlayModes getPlayMode() {
+ return playMode;
+ }
+
+ public boolean isAutoAdvance() {
+ return autoAdvance;
+ }
+
+ public void setAutoAdvance(boolean autoAdvance) {
+ this.autoAdvance = autoAdvance;
+ }
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleLegDetailColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleLegDetailColumn.java
index ff307c25481..17bd506d5c9 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleLegDetailColumn.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/FormattedDoubleLegDetailColumn.java
@@ -4,7 +4,9 @@ import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.SortingOrder;
+import com.sap.sailing.gwt.ui.client.DetailTypeFormatter;
import com.sap.sailing.gwt.ui.client.NumberFormatterFactory;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
@@ -12,6 +14,20 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
public class FormattedDoubleLegDetailColumn extends LegDetailColumn
- *
- * The implementation by and large uses the {@link LeaderboardSettingsDialogComponent}'s widget and adds to it a checkbox
- * for driving the {@link #PARAM_EMBEDDED} field.
- *
- * @see LeaderboardEntryPoint#getUrl(String, LeaderboardSettings, boolean)
- */
- public static DataEntryDialog
+ *
+ * The implementation by and large uses the {@link LeaderboardSettingsDialogComponent}'s widget and adds to it a checkbox
+ * for driving the {@link #PARAM_EMBEDDED} field.
+ *
+ * @see LeaderboardEntryPoint#getUrl(String, LeaderboardSettings, boolean)
+ */
+ public static DataEntryDialog
- *
- * Precondition: {@link #timer} is not
- *
- * On the other hand, a {@link LeaderboardRowDTO} has {@link LeaderboardEntryDTO}, keyed by race column name. The
- * entry DTOs, in turn, store the {@link RaceIdentifier} of the race in which the respective competitor achieved the
- * score.
- *
- *
- * With this information it is possible to identify the competitors who participated in a particular tracked race,
- * as identified through the settings and embedded mode
- * as specified by the parameters.
- */
- public static String getUrl(String leaderboardName, LeaderboardUrlSettings settings) {
- StringBuilder overallDetails = new StringBuilder();
- for (DetailType overallDetail : settings.getLeaderboardSettings().getOverallDetailsToShow()) {
- overallDetails.append('&');
- overallDetails.append(PARAM_OVERALL_DETAIL);
- overallDetails.append('=');
- overallDetails.append(overallDetail.name());
- }
- StringBuilder legDetails = new StringBuilder();
- for (DetailType legDetail : settings.getLeaderboardSettings().getLegDetailsToShow()) {
- legDetails.append('&');
- legDetails.append(PARAM_LEG_DETAIL);
- legDetails.append('=');
- legDetails.append(legDetail.name());
- }
- StringBuilder raceDetails = new StringBuilder();
- for (DetailType raceDetail : settings.getLeaderboardSettings().getRaceDetailsToShow()) {
- raceDetails.append('&');
- raceDetails.append(PARAM_RACE_DETAIL);
- raceDetails.append('=');
- raceDetails.append(raceDetail.name());
- }
- StringBuilder maneuverDetails = new StringBuilder();
- for (DetailType maneuverDetail : settings.getLeaderboardSettings().getManeuverDetailsToShow()) {
- maneuverDetails.append('&');
- maneuverDetails.append(PARAM_MANEUVER_DETAIL);
- maneuverDetails.append('=');
- maneuverDetails.append(maneuverDetail.name());
- }
- String debugParam = Window.Location.getParameter("gwt.codesvr");
- String link = URLFactory.INSTANCE.encode("/gwt/Leaderboard.html?name=" + leaderboardName
- + (settings.isShowRaceDetails() ? "&"+PARAM_SHOW_RACE_DETAILS+"=true" : "")
- + (settings.isEmbedded() ? "&"+PARAM_EMBEDDED+"=true" : "")
- + (settings.getLeaderboardSettings().isShowOverallLeaderboardsOnSamePage() ? "&"+PARAM_SHOW_OVERALL_LEADERBOARDS_ON_SAME_PAGE+"=true" : "")
- + (settings.getLeaderboardSettings().getDelayInMilliseconds() == null &&
- settings.getLeaderboardSettings().getDelayInMilliseconds() != 0 ? "" :
- "&"+PARAM_DELAY_TO_LIVE_MILLIS+"="+settings.getLeaderboardSettings().getDelayInMilliseconds())
- + (!settings.isAutoRefresh() || (settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds() == null &&
- settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds() != 0) ? "" :
- "&"+PARAM_REFRESH_INTERVAL_MILLIS+"="+settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds())
- + legDetails.toString()
- + raceDetails.toString()
- + overallDetails.toString()
- + maneuverDetails.toString()
- + (settings.isAutoExpandLastRaceColumn() ? "&"+PARAM_AUTO_EXPAND_LAST_RACE_COLUMN+"=true" : "")
- + (settings.getLeaderboardSettings().getNumberOfLastRacesToShow() == null ? "" :
- "&"+PARAM_NAME_LAST_N+"="+settings.getLeaderboardSettings().getNumberOfLastRacesToShow())
- + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
- return link;
- }
-}
+package com.sap.sailing.gwt.ui.leaderboard;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.sap.sailing.domain.common.DetailType;
+import com.sap.sailing.domain.common.RaceIdentifier;
+import com.sap.sailing.domain.common.RegattaNameAndRaceName;
+import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
+import com.sap.sailing.gwt.ui.client.AbstractEntryPoint;
+import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
+import com.sap.sailing.gwt.ui.client.DataEntryDialog;
+import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
+import com.sap.sailing.gwt.ui.client.StringMessages;
+import com.sap.sailing.gwt.ui.client.Timer;
+import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
+import com.sap.sailing.gwt.ui.client.URLFactory;
+import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
+import com.sap.sailing.gwt.ui.raceboard.GlobalNavigationPanel;
+import com.sap.sailing.gwt.ui.shared.AbstractLeaderboardDTO;
+
+
+public class LeaderboardEntryPoint extends AbstractEntryPoint {
+ private static final Logger logger = Logger.getLogger(LeaderboardEntryPoint.class.getName());
+ private static final String PARAM_LEADERBOARD_GROUP_NAME = "leaderboardGroupName";
+ private static final String PARAM_EMBEDDED = "embedded";
+ private static final String PARAM_SHOW_RACE_DETAILS = "showRaceDetails";
+ private static final String PARAM_RACE_NAME = "raceName";
+ private static final String PARAM_RACE_DETAIL = "raceDetail";
+ private static final String PARAM_OVERALL_DETAIL = "overallDetail";
+ private static final String PARAM_LEG_DETAIL = "legDetail";
+ private static final String PARAM_MANEUVER_DETAIL = "maneuverDetail";
+ private static final String PARAM_AUTO_EXPAND_PRESELECTED_RACE = "autoExpandPreselectedRace";
+ private static final String PARAM_AUTO_EXPAND_LAST_RACE_COLUMN = "autoExpandLastRaceColumn";
+ private static final String PARAM_REGATTA_NAME = "regattaName";
+ private static final String PARAM_REFRESH_INTERVAL_MILLIS = "refreshIntervalMillis";
+ private static final String PARAM_SHOW_OVERALL_LEADERBOARDS_ON_SAME_PAGE = "showOverallLeaderboardsOnSamePage";
+ private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis";
+
+ /**
+ * Lets the client choose a different race column selection which displays only up to the last N races with N being the integer
+ * number specified by the parameter.
+ */
+ private static final String PARAM_NAME_LAST_N = "lastN";
+ private String leaderboardName;
+ private String leaderboardGroupName;
+ private GlobalNavigationPanel globalNavigationPanel;
+
+ @Override
+ protected void doOnModuleLoad() {
+ super.doOnModuleLoad();
+ final boolean showRaceDetails = Window.Location.getParameter(PARAM_SHOW_RACE_DETAILS) != null
+ && Window.Location.getParameter(PARAM_SHOW_RACE_DETAILS).equalsIgnoreCase("true");
+ final boolean embedded = Window.Location.getParameter(PARAM_EMBEDDED) != null
+ && Window.Location.getParameter(PARAM_EMBEDDED).equalsIgnoreCase("true");
+ final long delayToLiveMillis = Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS) != null ?
+ Long.valueOf(Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS)) : 5000l; // default 5s
+ sailingService.getLeaderboardNames(new AsyncCallback>() {
+ @Override
+ public void onSuccess(List
settings and embedded mode
+ * as specified by the parameters.
+ */
+ public static String getUrl(String leaderboardName, LeaderboardUrlSettings settings) {
+ StringBuilder overallDetails = new StringBuilder();
+ for (DetailType overallDetail : settings.getLeaderboardSettings().getOverallDetailsToShow()) {
+ overallDetails.append('&');
+ overallDetails.append(PARAM_OVERALL_DETAIL);
+ overallDetails.append('=');
+ overallDetails.append(overallDetail.name());
+ }
+ StringBuilder legDetails = new StringBuilder();
+ for (DetailType legDetail : settings.getLeaderboardSettings().getLegDetailsToShow()) {
+ legDetails.append('&');
+ legDetails.append(PARAM_LEG_DETAIL);
+ legDetails.append('=');
+ legDetails.append(legDetail.name());
+ }
+ StringBuilder raceDetails = new StringBuilder();
+ for (DetailType raceDetail : settings.getLeaderboardSettings().getRaceDetailsToShow()) {
+ raceDetails.append('&');
+ raceDetails.append(PARAM_RACE_DETAIL);
+ raceDetails.append('=');
+ raceDetails.append(raceDetail.name());
+ }
+ StringBuilder maneuverDetails = new StringBuilder();
+ for (DetailType maneuverDetail : settings.getLeaderboardSettings().getManeuverDetailsToShow()) {
+ maneuverDetails.append('&');
+ maneuverDetails.append(PARAM_MANEUVER_DETAIL);
+ maneuverDetails.append('=');
+ maneuverDetails.append(maneuverDetail.name());
+ }
+ String debugParam = Window.Location.getParameter("gwt.codesvr");
+ String link = URLFactory.INSTANCE.encode("/gwt/Leaderboard.html?name=" + leaderboardName
+ + (settings.isShowRaceDetails() ? "&"+PARAM_SHOW_RACE_DETAILS+"=true" : "")
+ + (settings.isEmbedded() ? "&"+PARAM_EMBEDDED+"=true" : "")
+ + (settings.getLeaderboardSettings().isShowOverallLeaderboardsOnSamePage() ? "&"+PARAM_SHOW_OVERALL_LEADERBOARDS_ON_SAME_PAGE+"=true" : "")
+ + (settings.getLeaderboardSettings().getDelayInMilliseconds() == null &&
+ settings.getLeaderboardSettings().getDelayInMilliseconds() != 0 ? "" :
+ "&"+PARAM_DELAY_TO_LIVE_MILLIS+"="+settings.getLeaderboardSettings().getDelayInMilliseconds())
+ + (!settings.isAutoRefresh() || (settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds() == null &&
+ settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds() != 0) ? "" :
+ "&"+PARAM_REFRESH_INTERVAL_MILLIS+"="+settings.getLeaderboardSettings().getDelayBetweenAutoAdvancesInMilliseconds())
+ + legDetails.toString()
+ + raceDetails.toString()
+ + overallDetails.toString()
+ + maneuverDetails.toString()
+ + (settings.isAutoExpandLastRaceColumn() ? "&"+PARAM_AUTO_EXPAND_LAST_RACE_COLUMN+"=true" : "")
+ + (settings.getLeaderboardSettings().getNumberOfLastRacesToShow() == null ? "" :
+ "&"+PARAM_NAME_LAST_N+"="+settings.getLeaderboardSettings().getNumberOfLastRacesToShow())
+ + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
+ return link;
+ }
+}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java
old mode 100644
new mode 100755
index b7d117d0cc0..0345bea5bb8
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java
@@ -1,2365 +1,2356 @@
-package com.sap.sailing.gwt.ui.leaderboard;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.gwt.cell.client.Cell;
-import com.google.gwt.cell.client.Cell.Context;
-import com.google.gwt.cell.client.CompositeCell;
-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.dom.client.Style.FontWeight;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.NumberFormat;
-import com.google.gwt.resources.client.ImageResource;
-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.cellview.client.Column;
-import com.google.gwt.user.cellview.client.Header;
-import com.google.gwt.user.cellview.client.TextHeader;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.DockPanel;
-import com.google.gwt.user.client.ui.FlowPanel;
-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.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.view.client.ListDataProvider;
-import com.google.gwt.view.client.MultiSelectionModel;
-import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SelectionChangeEvent.Handler;
-import com.google.gwt.view.client.SelectionModel;
-import com.sap.sailing.domain.common.DetailType;
-import com.sap.sailing.domain.common.InvertibleComparator;
-import com.sap.sailing.domain.common.MaxPointsReason;
-import com.sap.sailing.domain.common.RaceIdentifier;
-import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
-import com.sap.sailing.domain.common.SortingOrder;
-import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
-import com.sap.sailing.domain.common.impl.Util;
-import com.sap.sailing.domain.common.impl.Util.Pair;
-import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
-import com.sap.sailing.gwt.ui.actions.GetLeaderboardByNameAction;
-import com.sap.sailing.gwt.ui.client.Collator;
-import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
-import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
-import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
-import com.sap.sailing.gwt.ui.client.ErrorReporter;
-import com.sap.sailing.gwt.ui.client.FlagImageResolver;
-import com.sap.sailing.gwt.ui.client.PlayStateListener;
-import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
-import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
-import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
-import com.sap.sailing.gwt.ui.client.StringMessages;
-import com.sap.sailing.gwt.ui.client.TimeListener;
-import com.sap.sailing.gwt.ui.client.Timer;
-import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
-import com.sap.sailing.gwt.ui.client.Timer.PlayStates;
-import com.sap.sailing.gwt.ui.client.UserAgentDetails;
-import com.sap.sailing.gwt.ui.leaderboard.LegDetailColumn.LegDetailField;
-import com.sap.sailing.gwt.ui.shared.AbstractLeaderboardDTO;
-import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
-import com.sap.sailing.gwt.ui.shared.FleetDTO;
-import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
-import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
-import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
-import com.sap.sailing.gwt.ui.shared.LegEntryDTO;
-import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
-import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
-import com.sap.sailing.gwt.ui.shared.components.Component;
-import com.sap.sailing.gwt.ui.shared.components.IsEmbeddableComponent;
-import com.sap.sailing.gwt.ui.shared.components.SettingsDialog;
-import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
-import com.sap.sailing.gwt.ui.shared.panels.BusyIndicator;
-import com.sap.sailing.gwt.ui.shared.panels.SimpleBusyIndicator;
-
-/**
- * A leaderboard essentially consists of a table widget that in its columns displays the entries.
- *
- * @author Axel Uhl (D043530)
- *
- */
-public class LeaderboardPanel extends FormPanel implements TimeListener, PlayStateListener,
- Componentnull, all leaderboard columns added by updating the leaderboard from the server are
- * automatically added to the table. Otherwise, only the column whose
- * {@link RaceColumnDTO#getRaceIdentifier(String) race identifier} matches the value of this attribute will be
- * added.
- */
- private final RaceIdentifier preSelectedRace;
-
- private final VerticalPanel contentPanel;
-
- /**
- * Used to display one or more overall leaderboards if selected. See also
- * {@link LeaderboardSettings#isShowOverallLeaderboardsOnSamePage()}. Always contained by the {@link #contentPanel} at the
- * right position, but may be empty.
- */
- private final VerticalPanel overallLeaderboardsPanel;
-
- /**
- * The leaderboard panels displayed in {@link #overallLeaderboardsPanel}.
- */
- private final Listnull string identifying a valid race by name that is represented in this
- * leaderboard panel then sort by it. Otherwise, default sorting will default to the overall rank column.
- */
- private String raceNameForDefaultSorting;
-
- /**
- * Can be used to disallow users to drill into the race details.
- */
- private final boolean showRaceDetails;
-
- /**
- * The {@link LastNRacesColumnSelection} column selection strategy requires a {@link RaceTimesInfoProvider}. This can either be injected
- * by passing a non-null object of that type to the constructor, or such an object is created and remembered in this
- * attribute when required the first time.
- */
- private RaceTimesInfoProvider raceTimesInfoProvider;
-
- private final UserAgentDetails userAgent;
-
- private class SettingsClickHandler implements ClickHandler {
- private final StringMessages stringMessages;
-
- private SettingsClickHandler(StringMessages stringMessages) {
- this.stringMessages = stringMessages;
- }
-
- @Override
- public void onClick(ClickEvent event) {
- new SettingsDialog>() {
- @Override
- public void onFailure(Throwable caught) {
- getErrorReporter().reportError(
- stringMessages.errorTryingToObtainOverallLeaderboards(caught.getMessage()));
- }
-
- @Override
- public void onSuccess(List
null
- */
- private RaceTimesInfoProvider getRaceTimesInfoProvider() {
- if (raceTimesInfoProvider == null) {
- final List
- * total points | maxPointsReason
- * -------------------------------+-----------------------------+-----------------------
- * not discarded, no maxPoints | bold | none
- * not discarded, maxPoints | bold | transparent
- * discarded, no maxPoints | transparent, strike-through | none
- * discarded, maxPoints | transparent, strike-through | transparent, strike-through
- *
- */
- @Override
- public void render(Context context, LeaderboardRowDTO object, SafeHtmlBuilder html) {
- LeaderboardEntryDTO entry = object.fieldsByRaceColumnName.get(getRaceColumnName());
- if (entry != null) {
- boolean isLive = isLive(entry.fleet);
-
- String textColor = isLive ? IS_LIVE_TEXT_COLOR : DEFAULT_TEXT_COLOR;
- String totalPointsAsText = entry.totalPoints == null ? "" : scoreFormat.format(entry.totalPoints);
- String netPointsAsText = entry.netPoints == null ? "" : scoreFormat.format(entry.netPoints);
-
- if (entry.fleet != null && entry.fleet.getColor() != null) {
- html.append(raceColumnTemplate.cellFrameWithTextColorAndFleetBorder(textColor, entry.fleet.getColor().getAsHtml()));
- } else {
- html.append(raceColumnTemplate.cellFrameWithTextColor(textColor));
- }
-
- // don't show points if max points / penalty
- if (entry.reasonForMaxPoints == null || entry.reasonForMaxPoints == MaxPointsReason.NONE) {
- if (!entry.discarded) {
- html.appendHtmlConstant("");
- html.appendHtmlConstant(totalPointsAsText);
- html.appendHtmlConstant("");
- } else {
- html.appendHtmlConstant(" ");
- html.appendHtmlConstant(netPointsAsText);
- html.appendHtmlConstant("");
- }
- } else {
- html.appendHtmlConstant(" ");
- if (entry.discarded) {
- html.appendHtmlConstant("");
- }
- html.appendEscaped(entry.reasonForMaxPoints == MaxPointsReason.NONE ? "" : entry.reasonForMaxPoints.name());
- if (entry.discarded) {
- html.appendHtmlConstant("");
- }
- html.appendHtmlConstant("");
- }
- html.appendHtmlConstant("null-padded, if {@link #getLegColumn(int)} asks for a column index
- * not yet existing. It is important to remember the columns because column removal happens based on identity.
- */
- private final Listcolumn to the right end of the {@link #getLeaderboardTable() leaderboard table} and sets
- * the column style according to the {@link SortableColumn#getColumnStyle() column's style definition}.
- */
- protected void addColumn(SortableColumncolumnIndex from the {@link #getLeaderboardTable() leaderboard
- * table} and fixes the column styles again (see {@link #addColumnStyles(int)}).
- */
- protected void removeColumn(int columnIndex) {
- Columnleaderboard to {@link #leaderboard} and updates the UI accordingly. Also updates the min/max
- * values on the columns.
- */
- protected void updateLeaderboard(LeaderboardDTO leaderboard) {
- if (leaderboard != null) {
- Collectionleaderboard. These are all {@link AbstractLeaderboardDTO#rows
- * rows} in case {@link #preSelectedRace} is null, or only the rows of the competitors who scored in
- * the race identified by {@link #preSelectedRace} otherwise.
- */
- private Collectionrace parameter.
- *
- * @return all competitors for which the {@link #getLeaderboard() leaderboard} has an entry whose
- * {@link LeaderboardEntryDTO#race} equals race
- */
- private IterableindexOfFirstOverallDetailsColumn and are in the order
- * defined by {@link #getAvailableOverallDetailColumnTypes()}.
- *
- * @param indexOfFirstOverallDetailsColumn
- * tells the column index for the first overall details column
- */
- private void adjustOverallDetailColumns(LeaderboardDTO leaderboard, int indexOfFirstOverallDetailsColumn) {
- Listlistposth race in the table or -1 if no such race column was found, e.g., in case the column
- * needs to be inserted as the last race in the table
- */
- private int getColumnPositionToInsert(RaceColumnDTO race, int listpos) {
- int raceColumnCounter = 0;
- int noRaceColumnCounter = 0;
- boolean raceColumnFound = false;
- for (int leaderboardPosition = 0; !raceColumnFound
- && leaderboardPosition < getLeaderboardTable().getColumnCount(); leaderboardPosition++) {
- Column