mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-16 10:48:47 +00:00
bug6150: each device has its statistics options
This commit is contained in:
+4
@@ -329,6 +329,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String position();
|
||||
String windSourcesUsed();
|
||||
String windStatisticsLines();
|
||||
String toAllSelected();
|
||||
String errorTryingToUpdateWindSourcesToExclude(String raceName, String message);
|
||||
String feedback();
|
||||
String startStopPlaying();
|
||||
@@ -354,6 +355,9 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String showWindAverageLine();
|
||||
String showWindMinLine();
|
||||
String showWindMaxLine();
|
||||
String windStatAvg();
|
||||
String windStatMin();
|
||||
String windStatMax();
|
||||
String fleet();
|
||||
String boat();
|
||||
String boatClass();
|
||||
|
||||
+4
@@ -359,6 +359,7 @@ clickChartToSetTime=Click on the chart to set the time
|
||||
position=Position
|
||||
windSourcesUsed=Wind Sources Used
|
||||
windStatisticsLines=Statistics Lines
|
||||
toAllSelected=To all selected
|
||||
errorTryingToUpdateWindSourcesToExclude=Error trying to update wind sources to exclude for race {0}: {1}
|
||||
feedback=Feedback
|
||||
startStopPlaying=Start/Stop playing
|
||||
@@ -390,6 +391,9 @@ showWindDirectionSeries=Show wind directions data
|
||||
showWindAverageLine=Show average line
|
||||
showWindMinLine=Show minimum line
|
||||
showWindMaxLine=Show maximum line
|
||||
windStatAvg=Avg
|
||||
windStatMin=Min
|
||||
windStatMax=Max
|
||||
fleet=Fleet
|
||||
boatClass=Boat Class
|
||||
setDelayToLive=Set delay to live
|
||||
|
||||
+4
@@ -357,6 +357,7 @@ clickChartToSetTime=Klicke auf das Diagramm um die Zeit zu setzen
|
||||
position=Position
|
||||
windSourcesUsed=Benutzte Windquellen
|
||||
windStatisticsLines=Statistiklinien
|
||||
toAllSelected=Für alle ausgewählten
|
||||
errorTryingToUpdateWindSourcesToExclude=Fehler beim Aktualisieren der auszuschließenden Windquellen für Rennen {0}: {1}
|
||||
feedback=Feedback
|
||||
startStopPlaying=Starten/Stoppen des abspielens
|
||||
@@ -388,6 +389,9 @@ showWindDirectionSeries=Daten für Windrichtung zeigen
|
||||
showWindAverageLine=Durchschnittslinie zeigen
|
||||
showWindMinLine=Minimumlinie zeigen
|
||||
showWindMaxLine=Maximumlinie zeigen
|
||||
windStatAvg=Avg
|
||||
windStatMin=Min
|
||||
windStatMax=Max
|
||||
fleet=Flotte
|
||||
boatClass=Bootsklasse
|
||||
setDelayToLive=Verzögerung zu ''Live'' setzen
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ public abstract class AbstractCompetitorLeaderboardChart<SettingsType extends Ge
|
||||
new Marker().setEnabled(true).setHoverState(
|
||||
new Marker().setEnabled(true).setRadius(4))).setShadow(false)
|
||||
.setHoverStateLineWidth(LINE_WIDTH));
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart);
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart, () -> {});
|
||||
chart.getXAxis().setType(Axis.Type.LINEAR);
|
||||
chart.getXAxis().setLabels(new XAxisLabels().setFormatter(new AxisLabelsFormatter() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ public abstract class AbstractCompetitorRaceChart<SettingsType extends ChartSett
|
||||
.setPlotBorderWidth(0)
|
||||
.setCredits(new Credits().setEnabled(false));
|
||||
chart.setStyleName(chartsCss.chartStyle());
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart);
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart, () -> {});
|
||||
|
||||
if (allowTimeAdjust) {
|
||||
chart.setClickEventHandler(new ChartClickEventHandler() {
|
||||
|
||||
+3
-1
@@ -18,7 +18,7 @@ public class ChartUtil {
|
||||
* added to the chart and hence visible. Otherwise, the checkbox won't initially be in sync with the series'
|
||||
* visibility state.
|
||||
*/
|
||||
static protected void useCheckboxesToShowAndHide(final Chart chart) {
|
||||
static protected void useCheckboxesToShowAndHide(final Chart chart, final Runnable onVisibilityChanged) {
|
||||
chart.setLegend(new Legend().setEnabled(true).setBorderWidth(0).setSymbolPadding(25)); // make room for checkbox
|
||||
chart.setSeriesPlotOptions(new SeriesPlotOptions().setShowCheckbox(true)
|
||||
.setSeriesCheckboxClickEventHandler(new SeriesCheckboxClickEventHandler() {
|
||||
@@ -27,6 +27,7 @@ public class ChartUtil {
|
||||
// we want to change the visiblity not the selection state, so own handler is necessary
|
||||
Series series = chart.getSeries(seriesCheckboxClickEvent.getSeriesId());
|
||||
series.setVisible(seriesCheckboxClickEvent.isChecked());
|
||||
onVisibilityChanged.run();
|
||||
return false; // don't toggle the select state of the series
|
||||
}
|
||||
}).setSeriesLegendItemClickEventHandler(new SeriesLegendItemClickEventHandler() {
|
||||
@@ -35,6 +36,7 @@ public class ChartUtil {
|
||||
Series series = chart.getSeries(seriesLegendItemClickEvent.getSeriesId());
|
||||
series.setVisible(!series.isVisible());
|
||||
series.select(series.isVisible());
|
||||
onVisibilityChanged.run();
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
+188
-101
@@ -20,6 +20,7 @@ import org.moxieapps.gwt.highcharts.client.PlotLine;
|
||||
import org.moxieapps.gwt.highcharts.client.PlotLine.DashStyle;
|
||||
import org.moxieapps.gwt.highcharts.client.Point;
|
||||
import org.moxieapps.gwt.highcharts.client.Series;
|
||||
import org.moxieapps.gwt.highcharts.client.Style;
|
||||
import org.moxieapps.gwt.highcharts.client.ToolTip;
|
||||
import org.moxieapps.gwt.highcharts.client.ToolTipData;
|
||||
import org.moxieapps.gwt.highcharts.client.ToolTipFormatter;
|
||||
@@ -29,6 +30,7 @@ import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEvent;
|
||||
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEventHandler;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsData;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsFormatter;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.PlotLineLabel;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.XAxisLabels;
|
||||
import org.moxieapps.gwt.highcharts.client.labels.YAxisLabels;
|
||||
import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions;
|
||||
@@ -79,20 +81,12 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
private final Map<WindSource, Point[]> windSourceDirectionPoints;
|
||||
private final Map<WindSource, Point[]> windSourceSpeedPoints;
|
||||
private Point firstPointOfFirstSeries;
|
||||
private PlotLine directionAveragePlotLine;
|
||||
private PlotLine directionMinPlotLine;
|
||||
private PlotLine directionMaxPlotLine;
|
||||
private PlotLine speedAveragePlotLine;
|
||||
private PlotLine speedMinPlotLine;
|
||||
private PlotLine speedMaxPlotLine;
|
||||
private double directionRunningAvg;
|
||||
private double directionRunningMin;
|
||||
private double directionRunningMax;
|
||||
private int directionPointCount;
|
||||
private double speedRunningAvg;
|
||||
private double speedRunningMin;
|
||||
private double speedRunningMax;
|
||||
private int speedPointCount;
|
||||
private final Map<WindSource, PlotLine> directionAvgPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
private final Map<WindSource, PlotLine> directionMinPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
private final Map<WindSource, PlotLine> directionMaxPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
private final Map<WindSource, PlotLine> speedAvgPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
private final Map<WindSource, PlotLine> speedMinPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
private final Map<WindSource, PlotLine> speedMaxPlotLines = new HashMap<WindSource, PlotLine>();
|
||||
|
||||
private Long timeOfEarliestRequestInMillis;
|
||||
private Long timeOfLatestRequestInMillis;
|
||||
@@ -147,7 +141,7 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
new Marker().setEnabled(true).setRadius(4))).setShadow(false)
|
||||
.setHoverStateLineWidth(LINE_WIDTH));
|
||||
chart.setStyleName(chartsCss.chartStyle());
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart);
|
||||
ChartUtil.useCheckboxesToShowAndHide(chart, this::updateStatPlotLines);
|
||||
final NumberFormat numberFormat = NumberFormat.getFormat("0");
|
||||
chart.setToolTip(new ToolTip().setEnabled(true).setFormatter(new ToolTipFormatter() {
|
||||
@Override
|
||||
@@ -195,12 +189,6 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
}
|
||||
}));
|
||||
timePlotLine = chart.getXAxis().createPlotLine().setColor("#656565").setWidth(1.5).setDashStyle(DashStyle.SOLID);
|
||||
directionAveragePlotLine = chart.getYAxis(0).createPlotLine().setColor("#2060C0").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
directionMinPlotLine = chart.getYAxis(0).createPlotLine().setColor("#20A020").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
directionMaxPlotLine = chart.getYAxis(0).createPlotLine().setColor("#C02020").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
speedAveragePlotLine = chart.getYAxis(1).createPlotLine().setColor("#2060C0").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
speedMinPlotLine = chart.getYAxis(1).createPlotLine().setColor("#20A020").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
speedMaxPlotLine = chart.getYAxis(1).createPlotLine().setColor("#C02020").setWidth(1.5).setDashStyle(DashStyle.SHORT_DASH);
|
||||
|
||||
chart.getYAxis(0).setAxisTitleText(stringMessages.fromDeg()).setStartOnTick(false)
|
||||
.setLabels(new YAxisLabels().setFormatter(new AxisLabelsFormatter() {
|
||||
@@ -396,9 +384,6 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
&& windSourceDirectionPoints.get(windSource).length != 0) {
|
||||
previousDirectionPoint = windSourceDirectionPoints.get(windSource)[windSourceDirectionPoints.get(windSource).length - 1];
|
||||
}
|
||||
if (!append) {
|
||||
resetStatAccumulators();
|
||||
}
|
||||
Point[] directionPoints = new Point[windTrackInfo.windFixes.size()];
|
||||
Point[] speedPoints = new Point[windTrackInfo.windFixes.size()];
|
||||
int currentPointIndex = 0;
|
||||
@@ -429,20 +414,8 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
}
|
||||
directionPoints[currentPointIndex] = newDirectionPoint;
|
||||
previousDirectionPoint = newDirectionPoint;
|
||||
final double dirVal = newDirectionPoint.getY().doubleValue();
|
||||
directionPointCount++;
|
||||
directionRunningAvg += (dirVal - directionRunningAvg) / directionPointCount;
|
||||
if (dirVal < directionRunningMin) { directionRunningMin = dirVal; }
|
||||
if (dirVal > directionRunningMax) { directionRunningMax = dirVal; }
|
||||
Point newSpeedPoint = new Point(wind.requestTimepoint, wind.dampenedTrueWindSpeedInKnots);
|
||||
speedPoints[currentPointIndex++] = newSpeedPoint;
|
||||
if (wind.dampenedTrueWindSpeedInKnots != null) {
|
||||
final double spdVal = wind.dampenedTrueWindSpeedInKnots;
|
||||
speedPointCount++;
|
||||
speedRunningAvg += (spdVal - speedRunningAvg) / speedPointCount;
|
||||
if (spdVal < speedRunningMin) { speedRunningMin = spdVal; }
|
||||
if (spdVal > speedRunningMax) { speedRunningMax = spdVal; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,7 +451,6 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
|
||||
timeOfEarliestRequestInMillis = newMinTimepoint;
|
||||
timeOfLatestRequestInMillis = newMaxTimepoint;
|
||||
updateStatPlotLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -506,25 +478,59 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
}
|
||||
settings.setShowWindDirectionsSeries(newSettings.isShowWindDirectionsSeries());
|
||||
settings.setWindDirectionSourcesToDisplay(newSettings.getWindDirectionSourcesToDisplay());
|
||||
|
||||
settings.setShowWindSpeedSeries(newSettings.isShowWindSpeedSeries());
|
||||
settings.setWindSpeedSourcesToDisplay(newSettings.getWindSpeedSourcesToDisplay());
|
||||
if (!oldWindSourceTypesToRequest.equals(getNamesOfWindSourceTypesOfWhichToDisplaySpeedOrDirection())) {
|
||||
clearCacheAndReload = true;
|
||||
}
|
||||
final boolean statLinesChanged = settings.isShowAverageLine() != newSettings.isShowAverageLine()
|
||||
|| settings.isShowMinLine() != newSettings.isShowMinLine()
|
||||
|| settings.isShowMaxLine() != newSettings.isShowMaxLine();
|
||||
settings.setShowAverageLine(newSettings.isShowAverageLine());
|
||||
settings.setShowMinLine(newSettings.isShowMinLine());
|
||||
settings.setShowMaxLine(newSettings.isShowMaxLine());
|
||||
final boolean dirAvgChanged = !settings.getDirectionAvgSources().equals(newSettings.getDirectionAvgSources());
|
||||
final boolean dirMinChanged = !settings.getDirectionMinSources().equals(newSettings.getDirectionMinSources());
|
||||
final boolean dirMaxChanged = !settings.getDirectionMaxSources().equals(newSettings.getDirectionMaxSources());
|
||||
final boolean spdAvgChanged = !settings.getSpeedAvgSources().equals(newSettings.getSpeedAvgSources());
|
||||
final boolean spdMinChanged = !settings.getSpeedMinSources().equals(newSettings.getSpeedMinSources());
|
||||
final boolean spdMaxChanged = !settings.getSpeedMaxSources().equals(newSettings.getSpeedMaxSources());
|
||||
settings.setDirectionAvgSources(newSettings.getDirectionAvgSources());
|
||||
settings.setDirectionMinSources(newSettings.getDirectionMinSources());
|
||||
settings.setDirectionMaxSources(newSettings.getDirectionMaxSources());
|
||||
settings.setDirectionAvgBulk(newSettings.isDirectionAvgBulk());
|
||||
settings.setDirectionMinBulk(newSettings.isDirectionMinBulk());
|
||||
settings.setDirectionMaxBulk(newSettings.isDirectionMaxBulk());
|
||||
settings.setSpeedAvgSources(newSettings.getSpeedAvgSources());
|
||||
settings.setSpeedMinSources(newSettings.getSpeedMinSources());
|
||||
settings.setSpeedMaxSources(newSettings.getSpeedMaxSources());
|
||||
settings.setSpeedAvgBulk(newSettings.isSpeedAvgBulk());
|
||||
settings.setSpeedMinBulk(newSettings.isSpeedMinBulk());
|
||||
settings.setSpeedMaxBulk(newSettings.isSpeedMaxBulk());
|
||||
if (clearCacheAndReload) {
|
||||
clearCacheAndReload();
|
||||
}
|
||||
if (statLinesChanged) {
|
||||
updateStatPlotLines();
|
||||
}
|
||||
updateVisibleSeries();
|
||||
if (!clearCacheAndReload) {
|
||||
if (dirAvgChanged) {
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionAvgSources(), directionAvgPlotLines, StatKind.AVG, true);
|
||||
}
|
||||
if (dirMinChanged) {
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionMinSources(), directionMinPlotLines, StatKind.MIN, true);
|
||||
}
|
||||
if (dirMaxChanged) {
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionMaxSources(), directionMaxPlotLines, StatKind.MAX, true);
|
||||
}
|
||||
if (spdAvgChanged) {
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedAvgSources(), speedAvgPlotLines, StatKind.AVG, false);
|
||||
}
|
||||
if (spdMinChanged) {
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedMinSources(), speedMinPlotLines, StatKind.MIN, false);
|
||||
}
|
||||
if (spdMaxChanged) {
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedMaxSources(), speedMaxPlotLines, StatKind.MAX, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearCacheAndReload() {
|
||||
@@ -533,21 +539,9 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
windSourceDirectionPoints.clear();
|
||||
windSourceSpeedPoints.clear();
|
||||
firstPointOfFirstSeries = null;
|
||||
resetStatAccumulators();
|
||||
loadData(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime(), /* append */false);
|
||||
}
|
||||
|
||||
private void resetStatAccumulators() {
|
||||
directionRunningAvg = 0;
|
||||
directionRunningMin = Double.MAX_VALUE;
|
||||
directionRunningMax = -Double.MAX_VALUE;
|
||||
directionPointCount = 0;
|
||||
speedRunningAvg = 0;
|
||||
speedRunningMin = Double.MAX_VALUE;
|
||||
speedRunningMax = -Double.MAX_VALUE;
|
||||
speedPointCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param append
|
||||
* if <code>true</code>, the results retrieved from the server will be appended to the wind chart instead
|
||||
@@ -574,6 +568,7 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
if (result != null) {
|
||||
updateChartSeries(result, append);
|
||||
updateVisibleSeries();
|
||||
updateStatPlotLines();
|
||||
} else {
|
||||
if (!append) {
|
||||
clearChart(); // no wind known for untracked race
|
||||
@@ -609,51 +604,143 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
removeStatPlotLines();
|
||||
}
|
||||
|
||||
/** Removes all six stat plot lines (avg/min/max for direction and speed) from the chart and clears the maps. */
|
||||
private void removeStatPlotLines() {
|
||||
chart.getYAxis(0).removePlotLine(directionAveragePlotLine);
|
||||
chart.getYAxis(0).removePlotLine(directionMinPlotLine);
|
||||
chart.getYAxis(0).removePlotLine(directionMaxPlotLine);
|
||||
chart.getYAxis(1).removePlotLine(speedAveragePlotLine);
|
||||
chart.getYAxis(1).removePlotLine(speedMinPlotLine);
|
||||
chart.getYAxis(1).removePlotLine(speedMaxPlotLine);
|
||||
for (final PlotLine pl : directionAvgPlotLines.values()) { chart.getYAxis(0).removePlotLine(pl); }
|
||||
for (final PlotLine pl : directionMinPlotLines.values()) { chart.getYAxis(0).removePlotLine(pl); }
|
||||
for (final PlotLine pl : directionMaxPlotLines.values()) { chart.getYAxis(0).removePlotLine(pl); }
|
||||
for (final PlotLine pl : speedAvgPlotLines.values()) { chart.getYAxis(1).removePlotLine(pl); }
|
||||
for (final PlotLine pl : speedMinPlotLines.values()) { chart.getYAxis(1).removePlotLine(pl); }
|
||||
for (final PlotLine pl : speedMaxPlotLines.values()) { chart.getYAxis(1).removePlotLine(pl); }
|
||||
directionAvgPlotLines.clear();
|
||||
directionMinPlotLines.clear();
|
||||
directionMaxPlotLines.clear();
|
||||
speedAvgPlotLines.clear();
|
||||
speedMinPlotLines.clear();
|
||||
speedMaxPlotLines.clear();
|
||||
}
|
||||
|
||||
/** Which statistic a plot line represents. */
|
||||
private enum StatKind { AVG, MIN, MAX }
|
||||
|
||||
/** Computes avg/min/max over a point array. Returns null if there are no valid points. */
|
||||
private static double[] computeStatValues(final Point[] points) {
|
||||
double sum = 0, min = Double.MAX_VALUE, max = -Double.MAX_VALUE;
|
||||
int count = 0;
|
||||
for (final Point p : points) {
|
||||
if (p != null && p.getY() != null) {
|
||||
final double v = p.getY().doubleValue();
|
||||
sum += v;
|
||||
if (v < min) { min = v; }
|
||||
if (v > max) { max = v; }
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
return null;
|
||||
}
|
||||
return new double[]{sum / count, min, max};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single stat plot line. Direction lines are dashed, speed lines are dotted.
|
||||
* Avg is drawn thicker than min/max. The label sits on the left for direction, right for speed.
|
||||
* The line color is a darkened version of the series color so it stands out from the main line.
|
||||
*/
|
||||
private PlotLine buildStatPlotLine(final int yAxisIndex, final String color, final double value,
|
||||
final StatKind kind, final boolean isDirection, final String labelText) {
|
||||
final DashStyle dashStyle = isDirection ? DashStyle.DASH : DashStyle.DOT;
|
||||
final double width = isDirection
|
||||
? (kind == StatKind.AVG ? 2 : 1.5)
|
||||
: (kind == StatKind.AVG ? 3 : 2);
|
||||
final PlotLineLabel.Align align = isDirection ? PlotLineLabel.Align.LEFT : PlotLineLabel.Align.RIGHT;
|
||||
final int labelX = isDirection ? 4 : -4;
|
||||
final String lineColor = darkenColor(color, 0.65);
|
||||
final PlotLine pl = chart.getYAxis(yAxisIndex).createPlotLine()
|
||||
.setColor(lineColor)
|
||||
.setWidth(width)
|
||||
.setDashStyle(dashStyle)
|
||||
.setZIndex(5)
|
||||
.setLabel(new PlotLineLabel()
|
||||
.setText(labelText)
|
||||
.setAlign(align)
|
||||
.setX(labelX)
|
||||
.setY(-4)
|
||||
.setStyle(new Style().setOption("fontSize", "11px").setOption("color", lineColor)));
|
||||
pl.setValue(value);
|
||||
return pl;
|
||||
}
|
||||
|
||||
/** Multiplies each RGB channel by factor to produce a darker shade of the given hex color. */
|
||||
private static String darkenColor(final String hex, final double factor) {
|
||||
final String h = hex.startsWith("#") ? hex.substring(1) : hex;
|
||||
final int r = (int) (Integer.parseInt(h.substring(0, 2), 16) * factor);
|
||||
final int g = (int) (Integer.parseInt(h.substring(2, 4), 16) * factor);
|
||||
final int b = (int) (Integer.parseInt(h.substring(4, 6), 16) * factor);
|
||||
return "#" + toHex2(r) + toHex2(g) + toHex2(b);
|
||||
}
|
||||
|
||||
private static String toHex2(final int v) {
|
||||
final String s = Integer.toHexString(v);
|
||||
return s.length() < 2 ? "0" + s : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraws the plot lines for one stat type (avg, min, or max) on one axis.
|
||||
* Removes the old lines first, then adds a new line for each visible source whose type
|
||||
* appears in enabledTypes. Called individually per stat so only the changed ones are redrawn.
|
||||
*/
|
||||
private void updateStatPlotLinesForStat(
|
||||
final Map<WindSource, Point[]> pointsMap,
|
||||
final Map<WindSource, Series> seriesMap,
|
||||
final int yAxisIndex,
|
||||
final Set<WindSourceType> enabledTypes,
|
||||
final Map<WindSource, PlotLine> plotLineMap,
|
||||
final StatKind kind,
|
||||
final boolean isDirection) {
|
||||
for (final PlotLine pl : plotLineMap.values()) {
|
||||
chart.getYAxis(yAxisIndex).removePlotLine(pl);
|
||||
}
|
||||
plotLineMap.clear();
|
||||
final NumberFormat fmt = NumberFormat.getFormat("0.#");
|
||||
for (final Map.Entry<WindSource, Point[]> entry : pointsMap.entrySet()) {
|
||||
final WindSource source = entry.getKey();
|
||||
final Series series = seriesMap.get(source);
|
||||
if (series != null && series.isVisible() && entry.getValue() != null
|
||||
&& enabledTypes.contains(source.getType())) {
|
||||
final double[] stats = computeStatValues(entry.getValue());
|
||||
if (stats != null) {
|
||||
final String color = colorMap.getColorByID(source).getAsHtml();
|
||||
final String sourceName = WindSourceTypeFormatter.format(source, stringMessages);
|
||||
final double statValue = kind == StatKind.AVG ? stats[0] : (kind == StatKind.MIN ? stats[1] : stats[2]);
|
||||
final String kindLabel = kind == StatKind.AVG ? stringMessages.windStatAvg()
|
||||
: (kind == StatKind.MIN ? stringMessages.windStatMin() : stringMessages.windStatMax());
|
||||
final String unit = isDirection ? stringMessages.degreesShort() : stringMessages.knotsUnit();
|
||||
final String labelText = kindLabel + " " + sourceName + ": " + fmt.format(statValue) + unit;
|
||||
final PlotLine pl = buildStatPlotLine(yAxisIndex, color, statValue, kind, isDirection, labelText);
|
||||
chart.getYAxis(yAxisIndex).addPlotLines(pl);
|
||||
plotLineMap.put(source, pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Redraws all six stat plot lines at once. Used when all of them need to refresh together —
|
||||
* after new data loads or when a legend series is toggled. When only one stat setting changes
|
||||
* in the dialog, updateStatPlotLinesForStat is called directly for just that one. */
|
||||
private void updateStatPlotLines() {
|
||||
removeStatPlotLines();
|
||||
final boolean showAvg = settings.isShowAverageLine();
|
||||
final boolean showMin = settings.isShowMinLine();
|
||||
final boolean showMax = settings.isShowMaxLine();
|
||||
if (!showAvg && !showMin && !showMax) {
|
||||
return;
|
||||
}
|
||||
if (directionPointCount > 0) {
|
||||
if (showAvg) {
|
||||
directionAveragePlotLine.setValue(directionRunningAvg);
|
||||
chart.getYAxis(0).addPlotLines(directionAveragePlotLine);
|
||||
}
|
||||
if (showMin) {
|
||||
directionMinPlotLine.setValue(directionRunningMin);
|
||||
chart.getYAxis(0).addPlotLines(directionMinPlotLine);
|
||||
}
|
||||
if (showMax) {
|
||||
directionMaxPlotLine.setValue(directionRunningMax);
|
||||
chart.getYAxis(0).addPlotLines(directionMaxPlotLine);
|
||||
}
|
||||
}
|
||||
if (speedPointCount > 0) {
|
||||
if (showAvg) {
|
||||
speedAveragePlotLine.setValue(speedRunningAvg);
|
||||
chart.getYAxis(1).addPlotLines(speedAveragePlotLine);
|
||||
}
|
||||
if (showMin) {
|
||||
speedMinPlotLine.setValue(speedRunningMin);
|
||||
chart.getYAxis(1).addPlotLines(speedMinPlotLine);
|
||||
}
|
||||
if (showMax) {
|
||||
speedMaxPlotLine.setValue(speedRunningMax);
|
||||
chart.getYAxis(1).addPlotLines(speedMaxPlotLine);
|
||||
}
|
||||
}
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionAvgSources(), directionAvgPlotLines, StatKind.AVG, true);
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionMinSources(), directionMinPlotLines, StatKind.MIN, true);
|
||||
updateStatPlotLinesForStat(windSourceDirectionPoints, windSourceDirectionSeries, 0,
|
||||
settings.getDirectionMaxSources(), directionMaxPlotLines, StatKind.MAX, true);
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedAvgSources(), speedAvgPlotLines, StatKind.AVG, false);
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedMinSources(), speedMinPlotLines, StatKind.MIN, false);
|
||||
updateStatPlotLinesForStat(windSourceSpeedPoints, windSourceSpeedSeries, 1,
|
||||
settings.getSpeedMaxSources(), speedMaxPlotLines, StatKind.MAX, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -792,7 +879,7 @@ public class WindChart extends AbstractRaceChart<WindChartSettings> implements R
|
||||
Set<WindSourceType> windDirectionSourcesToDisplay = new HashSet<>();
|
||||
windSpeedSourcesToDisplay.add(type);
|
||||
windDirectionSourcesToDisplay.add(type);
|
||||
WindChartSettings patched = new WindChartSettings(true, windSpeedSourcesToDisplay, true, windDirectionSourcesToDisplay, settings.getResolutionInMilliseconds(), settings.isShowAverageLine(), settings.isShowMinLine(), settings.isShowMaxLine());
|
||||
WindChartSettings patched = new WindChartSettings(true, windSpeedSourcesToDisplay, true, windDirectionSourcesToDisplay, settings.getResolutionInMilliseconds(), settings.getDirectionAvgSources(), settings.getDirectionMinSources(), settings.getDirectionMaxSources(), settings.isDirectionAvgBulk(), settings.isDirectionMinBulk(), settings.isDirectionMaxBulk(), settings.getSpeedAvgSources(), settings.getSpeedMinSources(), settings.getSpeedMaxSources(), settings.isSpeedAvgBulk(), settings.isSpeedMinBulk(), settings.isSpeedMaxBulk());
|
||||
updateSettings(patched);
|
||||
preselectFilter = windprovider;
|
||||
updateVisibleSeries();
|
||||
|
||||
+129
-32
@@ -22,49 +22,74 @@ public class WindChartSettings extends AbstractGenericSerializableSettings {
|
||||
|
||||
private BooleanSetting showWindSpeedSeries;
|
||||
private BooleanSetting showWindDirectionsSeries;
|
||||
private BooleanSetting showAverageLine;
|
||||
private BooleanSetting showMinLine;
|
||||
private BooleanSetting showMaxLine;
|
||||
|
||||
private EnumLinkedHashSetSetting<WindSourceType> directionAvgSources;
|
||||
private EnumLinkedHashSetSetting<WindSourceType> directionMinSources;
|
||||
private EnumLinkedHashSetSetting<WindSourceType> directionMaxSources;
|
||||
private BooleanSetting directionAvgBulk;
|
||||
private BooleanSetting directionMinBulk;
|
||||
private BooleanSetting directionMaxBulk;
|
||||
private EnumLinkedHashSetSetting<WindSourceType> speedAvgSources;
|
||||
private EnumLinkedHashSetSetting<WindSourceType> speedMinSources;
|
||||
private EnumLinkedHashSetSetting<WindSourceType> speedMaxSources;
|
||||
private BooleanSetting speedAvgBulk;
|
||||
private BooleanSetting speedMinBulk;
|
||||
private BooleanSetting speedMaxBulk;
|
||||
|
||||
@Override
|
||||
protected void addChildSettings() {
|
||||
Set<WindSourceType> defaultWindDirectionSourcesToDisplay = new LinkedHashSet<WindSourceType>();
|
||||
defaultWindDirectionSourcesToDisplay.add(WindSourceType.COMBINED);
|
||||
windDirectionSourcesToDisplay = new EnumLinkedHashSetSetting<>("windDirectionSourcesToDisplay", this, defaultWindDirectionSourcesToDisplay, WindSourceType::valueOf);
|
||||
|
||||
Set<WindSourceType> defaultWindSpeedSourcesToDisplay = new LinkedHashSet<>();
|
||||
defaultWindSpeedSourcesToDisplay.add(WindSourceType.COMBINED);
|
||||
windSpeedSourcesToDisplay = new EnumLinkedHashSetSetting<>("windSpeedSourcesToDisplay", this, defaultWindSpeedSourcesToDisplay, WindSourceType::valueOf);
|
||||
|
||||
resolutionInMilliseconds = new LongSetting("resolutionInMilliseconds", this, DEFAULT_RESOLUTION_IN_MILLISECONDS);
|
||||
showWindSpeedSeries = new BooleanSetting("showWindSpeedSeries", this, true);
|
||||
showWindDirectionsSeries = new BooleanSetting("showWindDirectionsSeries", this, true);
|
||||
showAverageLine = new BooleanSetting("showAverageLine", this, false);
|
||||
showMinLine = new BooleanSetting("showMinLine", this, false);
|
||||
showMaxLine = new BooleanSetting("showMaxLine", this, false);
|
||||
directionAvgSources = new EnumLinkedHashSetSetting<>("directionAvgSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
directionMinSources = new EnumLinkedHashSetSetting<>("directionMinSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
directionMaxSources = new EnumLinkedHashSetSetting<>("directionMaxSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
directionAvgBulk = new BooleanSetting("directionAvgBulk", this, false);
|
||||
directionMinBulk = new BooleanSetting("directionMinBulk", this, false);
|
||||
directionMaxBulk = new BooleanSetting("directionMaxBulk", this, false);
|
||||
speedAvgSources = new EnumLinkedHashSetSetting<>("speedAvgSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
speedMinSources = new EnumLinkedHashSetSetting<>("speedMinSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
speedMaxSources = new EnumLinkedHashSetSetting<>("speedMaxSources", this, new LinkedHashSet<WindSourceType>(), WindSourceType::valueOf);
|
||||
speedAvgBulk = new BooleanSetting("speedAvgBulk", this, false);
|
||||
speedMinBulk = new BooleanSetting("speedMinBulk", this, false);
|
||||
speedMaxBulk = new BooleanSetting("speedMaxBulk", this, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default settings
|
||||
*/
|
||||
public WindChartSettings() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public WindChartSettings(boolean showWindSpeedSeries, Set<WindSourceType> windSpeedSourcesToDisplay,
|
||||
boolean showWindDirectionsSeries, Set<WindSourceType> windDirectionSourcesToDisplay, long resolutionInMilliseconds,
|
||||
boolean showAverageLine, boolean showMinLine, boolean showMaxLine) {
|
||||
Set<WindSourceType> directionAvgSources, Set<WindSourceType> directionMinSources, Set<WindSourceType> directionMaxSources,
|
||||
boolean directionAvgBulk, boolean directionMinBulk, boolean directionMaxBulk,
|
||||
Set<WindSourceType> speedAvgSources, Set<WindSourceType> speedMinSources, Set<WindSourceType> speedMaxSources,
|
||||
boolean speedAvgBulk, boolean speedMinBulk, boolean speedMaxBulk) {
|
||||
this();
|
||||
this.showWindSpeedSeries.setValue(showWindSpeedSeries);
|
||||
this.windSpeedSourcesToDisplay.setValues(windSpeedSourcesToDisplay);
|
||||
this.showWindDirectionsSeries.setValue(showWindDirectionsSeries);
|
||||
this.windDirectionSourcesToDisplay.setValues(windDirectionSourcesToDisplay);
|
||||
this.resolutionInMilliseconds.setValue(resolutionInMilliseconds);
|
||||
this.showAverageLine.setValue(showAverageLine);
|
||||
this.showMinLine.setValue(showMinLine);
|
||||
this.showMaxLine.setValue(showMaxLine);
|
||||
this.directionAvgSources.setValues(directionAvgSources);
|
||||
this.directionMinSources.setValues(directionMinSources);
|
||||
this.directionMaxSources.setValues(directionMaxSources);
|
||||
this.directionAvgBulk.setValue(directionAvgBulk);
|
||||
this.directionMinBulk.setValue(directionMinBulk);
|
||||
this.directionMaxBulk.setValue(directionMaxBulk);
|
||||
this.speedAvgSources.setValues(speedAvgSources);
|
||||
this.speedMinSources.setValues(speedMinSources);
|
||||
this.speedMaxSources.setValues(speedMaxSources);
|
||||
this.speedAvgBulk.setValue(speedAvgBulk);
|
||||
this.speedMinBulk.setValue(speedMinBulk);
|
||||
this.speedMaxBulk.setValue(speedMaxBulk);
|
||||
}
|
||||
|
||||
|
||||
public Set<WindSourceType> getWindDirectionSourcesToDisplay() {
|
||||
return Util.asSet(windDirectionSourcesToDisplay.getValues());
|
||||
}
|
||||
@@ -98,38 +123,110 @@ public class WindChartSettings extends AbstractGenericSerializableSettings {
|
||||
}
|
||||
|
||||
public void setWindDirectionSourcesToDisplay(Set<WindSourceType> windDirectionSourcesToDisplay) {
|
||||
if(windDirectionSourcesToDisplay != null) {
|
||||
if (windDirectionSourcesToDisplay != null) {
|
||||
this.windDirectionSourcesToDisplay.setValues(windDirectionSourcesToDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWindSpeedSourcesToDisplay(Set<WindSourceType> windSpeedSourcesToDisplay) {
|
||||
if(windSpeedSourcesToDisplay != null) {
|
||||
if (windSpeedSourcesToDisplay != null) {
|
||||
this.windSpeedSourcesToDisplay.setValues(windSpeedSourcesToDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isShowAverageLine() {
|
||||
return showAverageLine.getValue();
|
||||
public Set<WindSourceType> getDirectionAvgSources() {
|
||||
return Util.asSet(directionAvgSources.getValues());
|
||||
}
|
||||
|
||||
public void setShowAverageLine(final boolean showAverageLine) {
|
||||
this.showAverageLine.setValue(showAverageLine);
|
||||
public void setDirectionAvgSources(final Set<WindSourceType> sources) {
|
||||
directionAvgSources.setValues(sources);
|
||||
}
|
||||
|
||||
public boolean isShowMinLine() {
|
||||
return showMinLine.getValue();
|
||||
public Set<WindSourceType> getDirectionMinSources() {
|
||||
return Util.asSet(directionMinSources.getValues());
|
||||
}
|
||||
|
||||
public void setShowMinLine(final boolean showMinLine) {
|
||||
this.showMinLine.setValue(showMinLine);
|
||||
public void setDirectionMinSources(final Set<WindSourceType> sources) {
|
||||
directionMinSources.setValues(sources);
|
||||
}
|
||||
|
||||
public boolean isShowMaxLine() {
|
||||
return showMaxLine.getValue();
|
||||
public Set<WindSourceType> getDirectionMaxSources() {
|
||||
return Util.asSet(directionMaxSources.getValues());
|
||||
}
|
||||
|
||||
public void setShowMaxLine(final boolean showMaxLine) {
|
||||
this.showMaxLine.setValue(showMaxLine);
|
||||
public void setDirectionMaxSources(final Set<WindSourceType> sources) {
|
||||
directionMaxSources.setValues(sources);
|
||||
}
|
||||
|
||||
public boolean isDirectionAvgBulk() {
|
||||
return directionAvgBulk.getValue();
|
||||
}
|
||||
|
||||
public void setDirectionAvgBulk(final boolean bulk) {
|
||||
directionAvgBulk.setValue(bulk);
|
||||
}
|
||||
|
||||
public boolean isDirectionMinBulk() {
|
||||
return directionMinBulk.getValue();
|
||||
}
|
||||
|
||||
public void setDirectionMinBulk(final boolean bulk) {
|
||||
directionMinBulk.setValue(bulk);
|
||||
}
|
||||
|
||||
public boolean isDirectionMaxBulk() {
|
||||
return directionMaxBulk.getValue();
|
||||
}
|
||||
|
||||
public void setDirectionMaxBulk(final boolean bulk) {
|
||||
directionMaxBulk.setValue(bulk);
|
||||
}
|
||||
|
||||
public Set<WindSourceType> getSpeedAvgSources() {
|
||||
return Util.asSet(speedAvgSources.getValues());
|
||||
}
|
||||
|
||||
public void setSpeedAvgSources(final Set<WindSourceType> sources) {
|
||||
speedAvgSources.setValues(sources);
|
||||
}
|
||||
|
||||
public Set<WindSourceType> getSpeedMinSources() {
|
||||
return Util.asSet(speedMinSources.getValues());
|
||||
}
|
||||
|
||||
public void setSpeedMinSources(final Set<WindSourceType> sources) {
|
||||
speedMinSources.setValues(sources);
|
||||
}
|
||||
|
||||
public Set<WindSourceType> getSpeedMaxSources() {
|
||||
return Util.asSet(speedMaxSources.getValues());
|
||||
}
|
||||
|
||||
public void setSpeedMaxSources(final Set<WindSourceType> sources) {
|
||||
speedMaxSources.setValues(sources);
|
||||
}
|
||||
|
||||
public boolean isSpeedAvgBulk() {
|
||||
return speedAvgBulk.getValue();
|
||||
}
|
||||
|
||||
public void setSpeedAvgBulk(final boolean bulk) {
|
||||
speedAvgBulk.setValue(bulk);
|
||||
}
|
||||
|
||||
public boolean isSpeedMinBulk() {
|
||||
return speedMinBulk.getValue();
|
||||
}
|
||||
|
||||
public void setSpeedMinBulk(final boolean bulk) {
|
||||
speedMinBulk.setValue(bulk);
|
||||
}
|
||||
|
||||
public boolean isSpeedMaxBulk() {
|
||||
return speedMaxBulk.getValue();
|
||||
}
|
||||
|
||||
public void setSpeedMaxBulk(final boolean bulk) {
|
||||
speedMaxBulk.setValue(bulk);
|
||||
}
|
||||
}
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
.statButton {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
background-color: #e8e8e8;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
margin: 1px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.statButton:hover {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.statButtonActive {
|
||||
color: #fff;
|
||||
background-color: #2060C0;
|
||||
border-color: #1a4a99;
|
||||
}
|
||||
|
||||
.statButtonActive:hover {
|
||||
background-color: #1a4a99;
|
||||
}
|
||||
|
||||
.statButtonIndeterminate {
|
||||
color: #fff;
|
||||
background-color: #7aa3e0;
|
||||
border-color: #5580c0;
|
||||
}
|
||||
|
||||
.statButtonIndeterminate:hover {
|
||||
background-color: #5580c0;
|
||||
}
|
||||
|
||||
.statButtonBulkActive {
|
||||
color: #fff;
|
||||
background-color: #F0AB00;
|
||||
border-color: #b07d00;
|
||||
}
|
||||
|
||||
.statButtonBulkActive:hover {
|
||||
background-color: #b07d00;
|
||||
}
|
||||
|
||||
.statButtonBulkIndeterminate {
|
||||
color: #fff;
|
||||
background-color: #f5cc55;
|
||||
border-color: #b07d00;
|
||||
}
|
||||
|
||||
.statButtonBulkIndeterminate:hover {
|
||||
background-color: #d4a800;
|
||||
}
|
||||
|
||||
.statButtonSectionDisabled {
|
||||
opacity: 0.35;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toAllSelectedLabel {
|
||||
padding-left: 4px;
|
||||
font-style: italic;
|
||||
color: #555;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sourceCheckboxIndent {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.accentCheckbox input[type="checkbox"] {
|
||||
accent-color: #F0AB00;
|
||||
}
|
||||
|
||||
.sectionDivider {
|
||||
border-left: 1px solid #cccccc;
|
||||
margin: 0 8px;
|
||||
}
|
||||
+380
-94
@@ -1,166 +1,453 @@
|
||||
package com.sap.sailing.gwt.ui.client.shared.charts;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.FlexTable;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.client.shared.charts.WindChartSettingsDialogCssResources.DialogCss;
|
||||
import com.sap.sse.gwt.client.controls.IntegerBox;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
|
||||
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
|
||||
|
||||
public class WindChartSettingsDialogComponent implements SettingsDialogComponent<WindChartSettings> {
|
||||
|
||||
private static final DialogCss CSS = WindChartSettingsDialogCssResources.INSTANCE.css();
|
||||
private static final Iterable<WindSourceType> ALL_SOURCE_TYPES = EnumSet.allOf(WindSourceType.class);
|
||||
|
||||
private enum StatState { OFF, ON, INDETERMINATE }
|
||||
|
||||
/**
|
||||
* A small clickable button-like label for toggling avg/min/max on or off.
|
||||
* Has three visual states: off (grey), on (colored), and indeterminate (used by bulk toggles
|
||||
* when only some sources have that stat enabled). Bulk toggles use a different color (yellow)
|
||||
* than per-source toggles (blue). When the section is disabled (show checkbox unchecked),
|
||||
* the button fades out to signal the selection is preserved but inactive.
|
||||
*/
|
||||
private static final class StatToggle {
|
||||
private final Label label;
|
||||
private StatState state;
|
||||
private final DialogCss css;
|
||||
private final boolean bulk;
|
||||
private boolean sectionDisabled;
|
||||
|
||||
StatToggle(final String text, final boolean initialOn, final DialogCss css, final boolean bulk) {
|
||||
this.css = css;
|
||||
this.bulk = bulk;
|
||||
css.ensureInjected();
|
||||
label = new Label(text);
|
||||
label.addStyleName(css.statButton());
|
||||
setState(initialOn ? StatState.ON : StatState.OFF);
|
||||
}
|
||||
|
||||
void setState(final StatState newState) {
|
||||
state = newState;
|
||||
label.removeStyleName(css.statButtonActive());
|
||||
label.removeStyleName(css.statButtonIndeterminate());
|
||||
label.removeStyleName(css.statButtonBulkActive());
|
||||
label.removeStyleName(css.statButtonBulkIndeterminate());
|
||||
if (state == StatState.ON) {
|
||||
label.addStyleName(bulk ? css.statButtonBulkActive() : css.statButtonActive());
|
||||
} else if (state == StatState.INDETERMINATE) {
|
||||
label.addStyleName(bulk ? css.statButtonBulkIndeterminate() : css.statButtonIndeterminate());
|
||||
}
|
||||
}
|
||||
|
||||
void setSectionDisabled(final boolean disabled) {
|
||||
sectionDisabled = disabled;
|
||||
if (sectionDisabled) {
|
||||
label.addStyleName(css.statButtonSectionDisabled());
|
||||
} else {
|
||||
label.removeStyleName(css.statButtonSectionDisabled());
|
||||
}
|
||||
}
|
||||
|
||||
void toggle() {
|
||||
setState(state == StatState.ON ? StatState.OFF : StatState.ON);
|
||||
}
|
||||
|
||||
boolean isOn() {
|
||||
return state == StatState.ON;
|
||||
}
|
||||
|
||||
Widget asWidget() {
|
||||
return label;
|
||||
}
|
||||
|
||||
void addClickHandler(final ClickHandler handler) {
|
||||
label.addClickHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private final WindChartSettings initialSettings;
|
||||
private IntegerBox resolutionInSecondsBox;
|
||||
private final Map<WindSourceType, CheckBox> windDirectionsCheckboxes;
|
||||
private final Map<WindSourceType, CheckBox> windSpeedCheckboxes;
|
||||
private CheckBox showWindSpeedSeriesCheckbox;
|
||||
private CheckBox showWindDirectionsSeriesCheckbox;
|
||||
private CheckBox showAverageLineCheckbox;
|
||||
private CheckBox showMinLineCheckbox;
|
||||
private CheckBox showMaxLineCheckbox;
|
||||
private CheckBox showWindSpeedSeriesCheckbox;
|
||||
private final Map<WindSourceType, CheckBox> windDirectionSourceCheckboxes = new LinkedHashMap<WindSourceType, CheckBox>();
|
||||
private final Map<WindSourceType, CheckBox> windSpeedSourceCheckboxes = new LinkedHashMap<WindSourceType, CheckBox>();
|
||||
private final Map<WindSourceType, StatToggle> dirAvgToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private final Map<WindSourceType, StatToggle> dirMinToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private final Map<WindSourceType, StatToggle> dirMaxToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private final Map<WindSourceType, StatToggle> spdAvgToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private final Map<WindSourceType, StatToggle> spdMinToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private final Map<WindSourceType, StatToggle> spdMaxToggles = new LinkedHashMap<WindSourceType, StatToggle>();
|
||||
private StatToggle dirBulkAvg;
|
||||
private StatToggle dirBulkMin;
|
||||
private StatToggle dirBulkMax;
|
||||
private StatToggle spdBulkAvg;
|
||||
private StatToggle spdBulkMin;
|
||||
private StatToggle spdBulkMax;
|
||||
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
public WindChartSettingsDialogComponent(WindChartSettings initialSettings, StringMessages stringMessages) {
|
||||
|
||||
public WindChartSettingsDialogComponent(final WindChartSettings initialSettings, final StringMessages stringMessages) {
|
||||
super();
|
||||
this.stringMessages = stringMessages;
|
||||
this.initialSettings = initialSettings;
|
||||
windDirectionsCheckboxes = new LinkedHashMap<WindSourceType, CheckBox>();
|
||||
windSpeedCheckboxes = new LinkedHashMap<WindSourceType, CheckBox>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
|
||||
VerticalPanel vp = new VerticalPanel();
|
||||
resolutionInSecondsBox = dialog.createIntegerBox((int) (initialSettings.getResolutionInMilliseconds()/1000), /* visibleLength */ 5);
|
||||
|
||||
HorizontalPanel hp = new HorizontalPanel();
|
||||
@Override
|
||||
public Widget getAdditionalWidget(final DataEntryDialog<?> dialog) {
|
||||
final VerticalPanel vp = new VerticalPanel();
|
||||
resolutionInSecondsBox = dialog.createIntegerBox((int) (initialSettings.getResolutionInMilliseconds() / 1000), 5);
|
||||
final HorizontalPanel hp = new HorizontalPanel();
|
||||
hp.add(new Label(stringMessages.stepSizeInSeconds() + ":"));
|
||||
hp.add(resolutionInSecondsBox);
|
||||
vp.add(hp);
|
||||
|
||||
Label createHeadlineLabel = dialog.createHeadlineLabel(stringMessages.windSourcesUsed());
|
||||
vp.add(createHeadlineLabel);
|
||||
final FlexTable dirTable = new FlexTable();
|
||||
dirTable.getElement().getStyle().setMarginLeft(15.0, Unit.PX);
|
||||
dirTable.setCellPadding(2);
|
||||
|
||||
Grid grid = new Grid(1,2);
|
||||
grid.setCellPadding(5);
|
||||
vp.add(grid);
|
||||
|
||||
VerticalPanel windDirectionSourcesPanel = new VerticalPanel();
|
||||
grid.setWidget(0, 0, windDirectionSourcesPanel);
|
||||
showWindDirectionsSeriesCheckbox = dialog.createCheckbox(stringMessages.showWindDirectionSeries());
|
||||
showWindDirectionsSeriesCheckbox.setTitle(stringMessages.showWindDirectionSeriesTooltip());
|
||||
showWindDirectionsSeriesCheckbox.setValue(initialSettings.isShowWindDirectionsSeries());
|
||||
showWindDirectionsSeriesCheckbox.addStyleName(CSS.accentCheckbox());
|
||||
dirTable.setWidget(0, 0, showWindDirectionsSeriesCheckbox);
|
||||
dirTable.getFlexCellFormatter().setColSpan(0, 0, 4);
|
||||
|
||||
VerticalPanel windSpeedSourcesPanel = new VerticalPanel();
|
||||
grid.setWidget(0, 1, windSpeedSourcesPanel);
|
||||
final StatToggle[] dirBulk = buildSourceSection(dialog, dirTable, 1,
|
||||
windDirectionSourceCheckboxes, dirAvgToggles, dirMinToggles, dirMaxToggles,
|
||||
initialSettings.getWindDirectionSourcesToDisplay(),
|
||||
initialSettings.getDirectionAvgSources(), initialSettings.getDirectionMinSources(), initialSettings.getDirectionMaxSources(),
|
||||
initialSettings.isDirectionAvgBulk(), initialSettings.isDirectionMinBulk(), initialSettings.isDirectionMaxBulk(),
|
||||
initialSettings.isShowWindDirectionsSeries(), true);
|
||||
dirBulkAvg = dirBulk[0];
|
||||
dirBulkMin = dirBulk[1];
|
||||
dirBulkMax = dirBulk[2];
|
||||
if (!initialSettings.isShowWindDirectionsSeries()) {
|
||||
setSectionTogglesDisabled(dirAvgToggles, dirMinToggles, dirMaxToggles, dirBulkAvg, dirBulkMin, dirBulkMax, true);
|
||||
}
|
||||
showWindDirectionsSeriesCheckbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
public void onValueChange(final ValueChangeEvent<Boolean> event) {
|
||||
final boolean enabled = event.getValue();
|
||||
for (final CheckBox cb : windDirectionSourceCheckboxes.values()) {
|
||||
cb.setEnabled(enabled);
|
||||
}
|
||||
setSectionTogglesDisabled(dirAvgToggles, dirMinToggles, dirMaxToggles, dirBulkAvg, dirBulkMin, dirBulkMax, !enabled);
|
||||
}
|
||||
});
|
||||
|
||||
final FlexTable spdTable = new FlexTable();
|
||||
spdTable.getElement().getStyle().setMarginLeft(8.0, Unit.PX);
|
||||
spdTable.setCellPadding(2);
|
||||
|
||||
showWindSpeedSeriesCheckbox = dialog.createCheckbox(stringMessages.showWindSpeedSeries());
|
||||
showWindSpeedSeriesCheckbox.setTitle(stringMessages.showWindSpeedSeriesTooltip());
|
||||
showWindSpeedSeriesCheckbox.setValue(initialSettings.isShowWindSpeedSeries());
|
||||
showWindSpeedSeriesCheckbox.addStyleName(CSS.accentCheckbox());
|
||||
spdTable.setWidget(0, 0, showWindSpeedSeriesCheckbox);
|
||||
spdTable.getFlexCellFormatter().setColSpan(0, 0, 4);
|
||||
|
||||
final StatToggle[] spdBulk = buildSourceSection(dialog, spdTable, 1,
|
||||
windSpeedSourceCheckboxes, spdAvgToggles, spdMinToggles, spdMaxToggles,
|
||||
initialSettings.getWindSpeedSourcesToDisplay(),
|
||||
initialSettings.getSpeedAvgSources(), initialSettings.getSpeedMinSources(), initialSettings.getSpeedMaxSources(),
|
||||
initialSettings.isSpeedAvgBulk(), initialSettings.isSpeedMinBulk(), initialSettings.isSpeedMaxBulk(),
|
||||
initialSettings.isShowWindSpeedSeries(), false);
|
||||
spdBulkAvg = spdBulk[0];
|
||||
spdBulkMin = spdBulk[1];
|
||||
spdBulkMax = spdBulk[2];
|
||||
if (!initialSettings.isShowWindSpeedSeries()) {
|
||||
setSectionTogglesDisabled(spdAvgToggles, spdMinToggles, spdMaxToggles, spdBulkAvg, spdBulkMin, spdBulkMax, true);
|
||||
}
|
||||
showWindSpeedSeriesCheckbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> event) {
|
||||
for (Map.Entry<WindSourceType, CheckBox> box : windSpeedCheckboxes.entrySet()) {
|
||||
box.getValue().setEnabled(event.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
windSpeedSourcesPanel.add(showWindSpeedSeriesCheckbox);
|
||||
showWindDirectionsSeriesCheckbox = dialog.createCheckbox(stringMessages.showWindDirectionSeries());
|
||||
showWindDirectionsSeriesCheckbox.setTitle(stringMessages.showWindDirectionSeriesTooltip());
|
||||
showWindDirectionsSeriesCheckbox.setValue(initialSettings.isShowWindDirectionsSeries());
|
||||
showWindDirectionsSeriesCheckbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> event) {
|
||||
for (Map.Entry<WindSourceType, CheckBox> box : windDirectionsCheckboxes.entrySet()) {
|
||||
box.getValue().setEnabled(event.getValue());
|
||||
public void onValueChange(final ValueChangeEvent<Boolean> event) {
|
||||
final boolean enabled = event.getValue();
|
||||
for (final CheckBox cb : windSpeedSourceCheckboxes.values()) {
|
||||
cb.setEnabled(enabled);
|
||||
}
|
||||
setSectionTogglesDisabled(spdAvgToggles, spdMinToggles, spdMaxToggles, spdBulkAvg, spdBulkMin, spdBulkMax, !enabled);
|
||||
}
|
||||
});
|
||||
|
||||
windDirectionSourcesPanel.add(showWindDirectionsSeriesCheckbox);
|
||||
final SimplePanel divider = new SimplePanel();
|
||||
divider.addStyleName(CSS.sectionDivider());
|
||||
|
||||
for (WindSourceType windSourceType : getWindSourceTypesToOffer()) {
|
||||
CheckBox checkbox = dialog.createCheckbox(WindSourceTypeFormatter.format(windSourceType, stringMessages));
|
||||
checkbox.setTitle(WindSourceTypeFormatter.tooltipFor(windSourceType, stringMessages));
|
||||
checkbox.setEnabled(initialSettings.isShowWindDirectionsSeries());
|
||||
windDirectionsCheckboxes.put(windSourceType, checkbox);
|
||||
checkbox.setValue(initialSettings.getWindDirectionSourcesToDisplay().contains(windSourceType));
|
||||
checkbox.getElement().getStyle().setMarginLeft(15.0, Unit.PX);
|
||||
windDirectionSourcesPanel.add(checkbox);
|
||||
}
|
||||
|
||||
for (WindSourceType windSourceType : getWindSourceTypesToOffer()) {
|
||||
CheckBox checkbox = dialog.createCheckbox(WindSourceTypeFormatter.format(windSourceType, stringMessages));
|
||||
checkbox.setTitle(WindSourceTypeFormatter.tooltipFor(windSourceType, stringMessages));
|
||||
checkbox.setEnabled(initialSettings.isShowWindSpeedSeries() && windSourceType.useSpeed());
|
||||
windSpeedCheckboxes.put(windSourceType, checkbox);
|
||||
checkbox.setValue(initialSettings.getWindSpeedSourcesToDisplay().contains(windSourceType));
|
||||
checkbox.getElement().getStyle().setMarginLeft(15.0, Unit.PX);
|
||||
windSpeedSourcesPanel.add(checkbox);
|
||||
}
|
||||
|
||||
vp.add(dialog.createHeadlineLabel(stringMessages.windStatisticsLines()));
|
||||
showAverageLineCheckbox = dialog.createCheckbox(stringMessages.showWindAverageLine());
|
||||
showAverageLineCheckbox.setTitle(stringMessages.showWindAverageLineTooltip());
|
||||
showAverageLineCheckbox.setValue(initialSettings.isShowAverageLine());
|
||||
vp.add(showAverageLineCheckbox);
|
||||
showMinLineCheckbox = dialog.createCheckbox(stringMessages.showWindMinLine());
|
||||
showMinLineCheckbox.setTitle(stringMessages.showWindMinLineTooltip());
|
||||
showMinLineCheckbox.setValue(initialSettings.isShowMinLine());
|
||||
vp.add(showMinLineCheckbox);
|
||||
showMaxLineCheckbox = dialog.createCheckbox(stringMessages.showWindMaxLine());
|
||||
showMaxLineCheckbox.setTitle(stringMessages.showWindMaxLineTooltip());
|
||||
showMaxLineCheckbox.setValue(initialSettings.isShowMaxLine());
|
||||
vp.add(showMaxLineCheckbox);
|
||||
final HorizontalPanel sectionsPanel = new HorizontalPanel();
|
||||
sectionsPanel.setVerticalAlignment(HorizontalPanel.ALIGN_TOP);
|
||||
sectionsPanel.add(dirTable);
|
||||
sectionsPanel.add(divider);
|
||||
sectionsPanel.add(spdTable);
|
||||
vp.add(sectionsPanel);
|
||||
return vp;
|
||||
}
|
||||
|
||||
private Iterable<WindSourceType> getWindSourceTypesToOffer() {
|
||||
final Set<WindSourceType> result = new HashSet<>();
|
||||
result.addAll(Arrays.asList(WindSourceType.values()));
|
||||
return result;
|
||||
/**
|
||||
* Dims or restores all stat toggles (both bulk and per-source) for a section.
|
||||
* Called when the "show wind direction/speed data" checkbox is toggled — the selection
|
||||
* is kept intact, just visually faded so it's clear it's not active right now.
|
||||
*/
|
||||
private void setSectionTogglesDisabled(
|
||||
final Map<WindSourceType, StatToggle> avgToggles,
|
||||
final Map<WindSourceType, StatToggle> minToggles,
|
||||
final Map<WindSourceType, StatToggle> maxToggles,
|
||||
final StatToggle bulkAvg, final StatToggle bulkMin, final StatToggle bulkMax,
|
||||
final boolean disabled) {
|
||||
bulkAvg.setSectionDisabled(disabled);
|
||||
bulkMin.setSectionDisabled(disabled);
|
||||
bulkMax.setSectionDisabled(disabled);
|
||||
for (final StatToggle t : avgToggles.values()) {
|
||||
t.setSectionDisabled(disabled);
|
||||
}
|
||||
for (final StatToggle t : minToggles.values()) {
|
||||
t.setSectionDisabled(disabled);
|
||||
}
|
||||
for (final StatToggle t : maxToggles.values()) {
|
||||
t.setSectionDisabled(disabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds one section of the settings table — either the direction or speed half.
|
||||
* Each section has a "to all selected" bulk row at the top, followed by one row per wind source.
|
||||
* Per-source avg/min/max buttons are hidden while the corresponding bulk button is on.
|
||||
* When a source is newly checked while a bulk button is on, that source inherits the bulk state.
|
||||
* Returns the three bulk toggles so the caller can wire them up to the show/hide checkbox.
|
||||
*/
|
||||
private StatToggle[] buildSourceSection(final DataEntryDialog<?> dialog, final FlexTable table, final int startRow,
|
||||
final Map<WindSourceType, CheckBox> sourceCheckboxes,
|
||||
final Map<WindSourceType, StatToggle> avgToggles,
|
||||
final Map<WindSourceType, StatToggle> minToggles,
|
||||
final Map<WindSourceType, StatToggle> maxToggles,
|
||||
final Set<WindSourceType> selectedSources,
|
||||
final Set<WindSourceType> avgSources,
|
||||
final Set<WindSourceType> minSources,
|
||||
final Set<WindSourceType> maxSources,
|
||||
final boolean initialBulkAvg, final boolean initialBulkMin, final boolean initialBulkMax,
|
||||
final boolean sectionEnabled,
|
||||
final boolean directionSection) {
|
||||
final StatToggle bulkAvg = new StatToggle(stringMessages.windStatAvg(), initialBulkAvg, CSS, true);
|
||||
final StatToggle bulkMin = new StatToggle(stringMessages.windStatMin(), initialBulkMin, CSS, true);
|
||||
final StatToggle bulkMax = new StatToggle(stringMessages.windStatMax(), initialBulkMax, CSS, true);
|
||||
|
||||
final Label toAllLabel = new Label(stringMessages.toAllSelected());
|
||||
toAllLabel.addStyleName(CSS.toAllSelectedLabel());
|
||||
table.setWidget(startRow, 0, toAllLabel);
|
||||
table.setWidget(startRow, 1, bulkAvg.asWidget());
|
||||
table.setWidget(startRow, 2, bulkMin.asWidget());
|
||||
table.setWidget(startRow, 3, bulkMax.asWidget());
|
||||
|
||||
int row = startRow + 1;
|
||||
for (final WindSourceType type : ALL_SOURCE_TYPES) {
|
||||
if (!directionSection && !type.useSpeed()) {
|
||||
continue;
|
||||
}
|
||||
final boolean sourceSelected = selectedSources.contains(type);
|
||||
final CheckBox sourceBox = dialog.createCheckbox(WindSourceTypeFormatter.format(type, stringMessages));
|
||||
sourceBox.setTitle(WindSourceTypeFormatter.tooltipFor(type, stringMessages));
|
||||
sourceBox.setValue(sourceSelected);
|
||||
sourceBox.setEnabled(sectionEnabled);
|
||||
sourceCheckboxes.put(type, sourceBox);
|
||||
|
||||
final StatToggle avgToggle = new StatToggle(stringMessages.windStatAvg(), avgSources.contains(type), CSS, false);
|
||||
final StatToggle minToggle = new StatToggle(stringMessages.windStatMin(), minSources.contains(type), CSS, false);
|
||||
final StatToggle maxToggle = new StatToggle(stringMessages.windStatMax(), maxSources.contains(type), CSS, false);
|
||||
avgToggle.asWidget().setVisible(sourceSelected && !bulkAvg.isOn());
|
||||
minToggle.asWidget().setVisible(sourceSelected && !bulkMin.isOn());
|
||||
maxToggle.asWidget().setVisible(sourceSelected && !bulkMax.isOn());
|
||||
avgToggles.put(type, avgToggle);
|
||||
minToggles.put(type, minToggle);
|
||||
maxToggles.put(type, maxToggle);
|
||||
|
||||
avgToggle.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
avgToggle.toggle();
|
||||
}
|
||||
});
|
||||
minToggle.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
minToggle.toggle();
|
||||
}
|
||||
});
|
||||
maxToggle.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
maxToggle.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
sourceBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
public void onValueChange(final ValueChangeEvent<Boolean> event) {
|
||||
final boolean checked = event.getValue();
|
||||
if (checked) {
|
||||
if (bulkAvg.isOn()) {
|
||||
avgToggle.setState(StatState.ON);
|
||||
}
|
||||
if (bulkMin.isOn()) {
|
||||
minToggle.setState(StatState.ON);
|
||||
}
|
||||
if (bulkMax.isOn()) {
|
||||
maxToggle.setState(StatState.ON);
|
||||
}
|
||||
}
|
||||
avgToggle.asWidget().setVisible(checked && !bulkAvg.isOn());
|
||||
minToggle.asWidget().setVisible(checked && !bulkMin.isOn());
|
||||
maxToggle.asWidget().setVisible(checked && !bulkMax.isOn());
|
||||
}
|
||||
});
|
||||
|
||||
table.getCellFormatter().addStyleName(row, 0, CSS.sourceCheckboxIndent());
|
||||
table.setWidget(row, 0, sourceBox);
|
||||
table.setWidget(row, 1, avgToggle.asWidget());
|
||||
table.setWidget(row, 2, minToggle.asWidget());
|
||||
table.setWidget(row, 3, maxToggle.asWidget());
|
||||
row++;
|
||||
}
|
||||
bulkAvg.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
bulkAvg.toggle();
|
||||
if (bulkAvg.isOn()) {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
avgToggles.get(e.getKey()).setState(StatState.ON);
|
||||
avgToggles.get(e.getKey()).asWidget().setVisible(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
avgToggles.get(e.getKey()).asWidget().setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
bulkMin.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
bulkMin.toggle();
|
||||
if (bulkMin.isOn()) {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
minToggles.get(e.getKey()).setState(StatState.ON);
|
||||
minToggles.get(e.getKey()).asWidget().setVisible(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
minToggles.get(e.getKey()).asWidget().setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
bulkMax.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
bulkMax.toggle();
|
||||
if (bulkMax.isOn()) {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
maxToggles.get(e.getKey()).setState(StatState.ON);
|
||||
maxToggles.get(e.getKey()).asWidget().setVisible(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
maxToggles.get(e.getKey()).asWidget().setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return new StatToggle[]{bulkAvg, bulkMin, bulkMax};
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindChartSettings getResult() {
|
||||
Set<WindSourceType> windDirectionSourcesToDisplay = new HashSet<WindSourceType>();
|
||||
for (Map.Entry<WindSourceType, CheckBox> e : windDirectionsCheckboxes.entrySet()) {
|
||||
final Set<WindSourceType> dirSources = new HashSet<WindSourceType>();
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : windDirectionSourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
windDirectionSourcesToDisplay.add(e.getKey());
|
||||
dirSources.add(e.getKey());
|
||||
}
|
||||
}
|
||||
Set<WindSourceType> windSpeedSourcesToDisplay = new HashSet<WindSourceType>();
|
||||
for (Map.Entry<WindSourceType, CheckBox> e : windSpeedCheckboxes.entrySet()) {
|
||||
final Set<WindSourceType> spdSources = new HashSet<WindSourceType>();
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : windSpeedSourceCheckboxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
windSpeedSourcesToDisplay.add(e.getKey());
|
||||
spdSources.add(e.getKey());
|
||||
}
|
||||
}
|
||||
return new WindChartSettings(showWindSpeedSeriesCheckbox.getValue(), windSpeedSourcesToDisplay,
|
||||
showWindDirectionsSeriesCheckbox.getValue(), windDirectionSourcesToDisplay,
|
||||
resolutionInSecondsBox.getValue() == null ? -1 : resolutionInSecondsBox.getValue()*1000,
|
||||
showAverageLineCheckbox.getValue(), showMinLineCheckbox.getValue(), showMaxLineCheckbox.getValue());
|
||||
return new WindChartSettings(
|
||||
showWindSpeedSeriesCheckbox.getValue(), spdSources,
|
||||
showWindDirectionsSeriesCheckbox.getValue(), dirSources,
|
||||
resolutionInSecondsBox.getValue() == null ? -1 : resolutionInSecondsBox.getValue() * 1000,
|
||||
collectEnabled(dirAvgToggles, dirBulkAvg, windDirectionSourceCheckboxes),
|
||||
collectEnabled(dirMinToggles, dirBulkMin, windDirectionSourceCheckboxes),
|
||||
collectEnabled(dirMaxToggles, dirBulkMax, windDirectionSourceCheckboxes),
|
||||
dirBulkAvg.isOn(), dirBulkMin.isOn(), dirBulkMax.isOn(),
|
||||
collectEnabled(spdAvgToggles, spdBulkAvg, windSpeedSourceCheckboxes),
|
||||
collectEnabled(spdMinToggles, spdBulkMin, windSpeedSourceCheckboxes),
|
||||
collectEnabled(spdMaxToggles, spdBulkMax, windSpeedSourceCheckboxes),
|
||||
spdBulkAvg.isOn(), spdBulkMin.isOn(), spdBulkMax.isOn());
|
||||
}
|
||||
|
||||
private Set<WindSourceType> collectEnabled(final Map<WindSourceType, StatToggle> statToggles,
|
||||
final StatToggle bulkToggle, final Map<WindSourceType, CheckBox> sourceBoxes) {
|
||||
final Set<WindSourceType> result = new HashSet<WindSourceType>();
|
||||
for (final Map.Entry<WindSourceType, CheckBox> e : sourceBoxes.entrySet()) {
|
||||
if (e.getValue().getValue()) {
|
||||
final boolean bulkActive = bulkToggle != null && bulkToggle.isOn();
|
||||
final StatToggle t = statToggles.get(e.getKey());
|
||||
if (bulkActive || (t != null && t.isOn())) {
|
||||
result.add(e.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Validator<WindChartSettings> getValidator() {
|
||||
return new Validator<WindChartSettings>() {
|
||||
@Override
|
||||
public String getErrorMessage(WindChartSettings valueToValidate) {
|
||||
public String getErrorMessage(final WindChartSettings valueToValidate) {
|
||||
String errorMessage = null;
|
||||
if (valueToValidate.getResolutionInMilliseconds() < 1) {
|
||||
errorMessage = stringMessages.stepSizeMustBeGreaterThanNull();
|
||||
@@ -172,7 +459,6 @@ public class WindChartSettingsDialogComponent implements SettingsDialogComponent
|
||||
|
||||
@Override
|
||||
public FocusWidget getFocusWidget() {
|
||||
return windDirectionsCheckboxes.values().iterator().next();
|
||||
return windDirectionSourceCheckboxes.values().iterator().next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.sap.sailing.gwt.ui.client.shared.charts;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
|
||||
public interface WindChartSettingsDialogCssResources extends ClientBundle {
|
||||
public static final WindChartSettingsDialogCssResources INSTANCE = GWT.create(WindChartSettingsDialogCssResources.class);
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/shared/charts/WindChartSettingsDialog.css")
|
||||
DialogCss css();
|
||||
|
||||
public interface DialogCss extends CssResource {
|
||||
String statButton();
|
||||
String statButtonActive();
|
||||
String statButtonIndeterminate();
|
||||
String statButtonBulkActive();
|
||||
String statButtonBulkIndeterminate();
|
||||
String statButtonSectionDisabled();
|
||||
String toAllSelectedLabel();
|
||||
String sourceCheckboxIndent();
|
||||
String accentCheckbox();
|
||||
String sectionDivider();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user