From e57591ef5e71a3a90a610749cf67c6fe3a577714 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Thu, 2 Jan 2025 18:06:12 +0100 Subject: [PATCH 01/10] feat: add Java API to set Chart mode property --- .../examples/timeline/AreaSplineRange.java | 3 +- .../charts/examples/timeline/Candlestick.java | 3 +- .../charts/examples/timeline/ColumnRange.java | 3 +- .../timeline/CompareMultipleSeries.java | 3 +- .../charts/examples/timeline/OHLC.java | 3 +- .../charts/examples/timeline/Spline.java | 3 +- .../vaadin/flow/component/charts/Chart.java | 67 +++++++++++----- .../flow/component/charts/ChartMode.java | 79 +++++++++++++++++++ 8 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java index e6d86dcc18f..379a41bdb8f 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -36,7 +37,7 @@ public void initDemo() { } configuration.setSeries(dataSeries); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java index 54e7c246976..e64dfb512c0 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -52,7 +53,7 @@ public void initDemo() { rangeSelector.setSelected(4); configuration.setRangeSelector(rangeSelector); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java index cb3f06ad1de..650b7c863b6 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -37,7 +38,7 @@ public void initDemo() { rangeSelector.setSelected(2); configuration.setRangeSelector(rangeSelector); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java index 2cfc9bbf017..1e1b99a649d 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.Compare; @@ -29,7 +30,7 @@ public class CompareMultipleSeries extends AbstractChartExample { @Override public void initDemo() { final Chart chart = new Chart(); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); Configuration configuration = chart.getConfiguration(); configuration.getTitle().setText("AAPL Stock Price"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java index 993082a3875..be503ff5b60 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -52,7 +53,7 @@ public void initDemo() { rangeSelector.setSelected(1); configuration.setRangeSelector(rangeSelector); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java index d9d5c70afcc..4be93854595 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -22,7 +23,7 @@ public class Spline extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.SPLINE); - chart.setTimeline(true); + chart.setMode(ChartMode.TIMELINE); Configuration configuration = chart.getConfiguration(); configuration.getTitle().setText("AAPL Stock Price"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java index 53b4be42794..b0c4cd09f5f 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java @@ -60,7 +60,6 @@ import com.vaadin.flow.component.charts.model.DataSeriesItem; import com.vaadin.flow.component.charts.model.DrilldownCallback; import com.vaadin.flow.component.charts.model.DrilldownCallback.DrilldownDetails; -import com.vaadin.flow.component.charts.model.PlotOptionsTimeline; import com.vaadin.flow.component.charts.model.Series; import com.vaadin.flow.component.charts.util.ChartSerialization; import com.vaadin.flow.component.dependency.JsModule; @@ -105,6 +104,9 @@ public class Chart extends Component implements HasStyle, HasSize, HasTheme { ChartType.PIE, ChartType.GAUGE, ChartType.SOLIDGAUGE, ChartType.PYRAMID, ChartType.FUNNEL, ChartType.ORGANIZATION); + private final static List GANTT_SUPPORTED = Arrays + .asList(ChartType.GANTT, ChartType.XRANGE); + private DrillCallbackHandler drillCallbackHandler; private DrilldownCallback drilldownCallback; @@ -192,7 +194,7 @@ public void drawChart() { * @see #getConfiguration() */ public void drawChart(boolean resetConfiguration) { - validateTimelineAndConfiguration(); + validateChartMode(); final JsonObject configurationNode = getJsonFactory() .parse(ChartSerialization.toJSON(configuration)); @@ -201,32 +203,49 @@ public void drawChart(boolean resetConfiguration) { resetConfiguration); } + private void validateChartMode() { + validateTimelineAndConfiguration(); + validateGanttAndConfiguration(); + } + /** - * Determines if the chart is in timeline mode or in normal mode. The - * following chart types do not support timeline mode: - * - * Enabling timeline mode in these unsupported chart types results in an - * IllegalArgumentException - *

- * Note: for Timeline chart type see {@link ChartType.TIMELINE} and - * {@link PlotOptionsTimeline}. + * Determines if the chart is in timeline mode or in normal mode. For more + * information see {@link ChartMode#TIMELINE}. * * @param timeline * true for timeline chart + * @deprecated Use {@link #setMode(ChartMode)} instead */ public void setTimeline(Boolean timeline) { - getElement().setProperty("timeline", timeline); + setMode(timeline ? ChartMode.TIMELINE : ChartMode.NORMAL); + } + + /** + * The chart mode configures how data is presented in the chart. You can + * specify whether the chart will be rendered as a normal chart, a timeline + * chart or a gantt chart. + *

+ * For more information on modes and their limitations see + * {@link ChartMode}. + * + * @param mode + * the mode to set + */ + public void setMode(ChartMode mode) { + getElement().setProperty("mode", + mode == null ? null : mode.getModeName()); + } + + /** + * @see #setMode(ChartMode) + */ + public ChartMode getMode() { + final String mode = getElement().getProperty("mode"); + return mode == null ? ChartMode.NORMAL : ChartMode.getForName(mode); } private void validateTimelineAndConfiguration() { - if (getElement().getProperty("timeline", false)) { + if (getMode().equals(ChartMode.TIMELINE)) { final ChartType type = getConfiguration().getChart().getType(); if (TIMELINE_NOT_SUPPORTED.contains(type)) { throw new IllegalArgumentException( @@ -236,6 +255,16 @@ private void validateTimelineAndConfiguration() { } } + private void validateGanttAndConfiguration() { + if (getMode().equals(ChartMode.GANTT)) { + final ChartType type = getConfiguration().getChart().getType(); + if (!GANTT_SUPPORTED.contains(type)) { + throw new IllegalArgumentException( + "Gantt is not supported for chart type '" + type + "'"); + } + } + } + /** * The series or point visibility is toggled by default if user clicks the * legend item that corresponds to the series or point. Calling diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java new file mode 100644 index 00000000000..d2cd8b5d66f --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java @@ -0,0 +1,79 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts; + +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.PlotOptionsTimeline; + +/** + * The ChartMode configures how the data is presented in the chart. + */ +public enum ChartMode { + + /** + * Normal chart mode, for any series type (see {@link ChartType}). + */ + NORMAL("normal"), + + /** + * Chart timeline mode: the chart allows selecting different time ranges for + * which to display the chart data, as well as navigating between such + * ranges. The following chart types do not support timeline mode: + *

+ * Enabling timeline mode in these unsupported chart types results in an + * IllegalArgumentException + *

+ * Note: for Timeline chart type see {@link ChartType#TIMELINE} and + * {@link PlotOptionsTimeline}. + */ + TIMELINE("timeline"), + + /** + * Gantt chart mode: the chart series data will be presented as a Gantt + * chart. Only the following chart series types are supported while in Gantt + * chart mode: + *

+ * Enabling Gantt chart mode with unsupported chart types results in an + * IllegalArgumentException + *

+ * Note: for Gantt chart type see + * {@link com.vaadin.flow.component.charts.model.ChartType#GANTT} and + * {@link com.vaadin.flow.component.charts.model.PlotOptionsGantt}. + */ + GANTT("gantt"); + + private final String mode; + + ChartMode(String mode) { + this.mode = mode; + } + + public String getModeName() { + return mode; + } + + public static ChartMode getForName(String name) { + for (ChartMode mode : values()) { + if (mode.getModeName().equals(name)) { + return mode; + } + } + return ChartMode.NORMAL; + } +} From 70cc3513551f5801747fe07970ef37808c0b91e7 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Fri, 3 Jan 2025 09:53:37 +0100 Subject: [PATCH 02/10] fix: create missing ChartType --- .../java/com/vaadin/flow/component/charts/model/ChartType.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartType.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartType.java index 78ed15ebddd..e7e2b610c3d 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartType.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartType.java @@ -152,6 +152,8 @@ public class ChartType implements ChartEnum { */ public static final ChartType XRANGE = new ChartType("xrange"); + public static final ChartType GANTT = new ChartType("gantt"); + public static ChartType getDefault() { return ChartType.LINE; } From 627d2fff648098a559f7917462c6acbdeea729ac Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Fri, 3 Jan 2025 09:58:56 +0100 Subject: [PATCH 03/10] feat: improve charts to support Gantt specific API --- .../frontend/images/avatar1.png | Bin 0 -> 31828 bytes .../examples/gantt/GanttCustomDataLabels.java | 131 +++ .../examples/gantt/GanttCustomXAxis.java | 176 ++++ .../examples/gantt/GanttLeftAxisAsTable.java | 172 ++++ .../gantt/GanttProcessManagement.java | 217 +++++ .../gantt/GanttProgressIndicator.java | 71 ++ .../gantt/GanttResourceManagement.java | 164 ++++ .../gantt/GanttUsingXRangeSeries.java | 72 ++ .../examples/gantt/GanttWithNavigation.java | 93 ++ .../flow/component/charts/model/AxisGrid.java | 111 +++ .../charts/model/ChartConnectors.java | 55 ++ .../component/charts/model/Completed.java | 67 ++ .../component/charts/model/Configuration.java | 30 +- .../charts/model/ConnectorStyle.java | 133 +++ .../component/charts/model/DataLabels.java | 18 + .../component/charts/model/GanttSeries.java | 116 +++ .../charts/model/GanttSeriesItem.java | 347 +++++++ .../model/GanttSeriesItemDependency.java | 40 + .../flow/component/charts/model/Marker.java | 47 + .../charts/model/PathfinderType.java | 46 + .../charts/model/PlotOptionsGantt.java | 891 ++++++++++++++++++ .../component/charts/model/Scrollbar.java | 15 + .../model/SeriesConnectorAnimation.java | 34 + .../charts/model/SeriesConnectors.java | 27 + .../flow/component/charts/model/XAxis.java | 146 +++ .../flow/component/charts/model/YAxis.java | 119 +++ .../charts/model/style/PlotOptionsStyle.java | 18 + 27 files changed, 3354 insertions(+), 2 deletions(-) create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomDataLabels.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea2f7ac739d1abf5159382c25d55678c94bc710 GIT binary patch literal 31828 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 for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.DataLabels; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.HorizontalAlign; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; + +@SuppressWarnings("unused") +public class GanttCustomDataLabels extends AbstractChartExample { + + private static final Instant TODAY = Instant.now() + .truncatedTo(ChronoUnit.DAYS); + + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + + configuration.setTitle("Highcharts Gantt Chart"); + configuration.setSubTitle("With custom symbols in data labels"); + configuration.setTooltip(new Tooltip(true)); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setMinPadding(0.05); + xAxis.setMaxPadding(0.05); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setCategories("Prototyping", "Development", "Testing"); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + final GanttSeries projectDevelopmentSeries = createProjectDevelopmentSeries(); + PlotOptionsGantt seriesPlotOptions = new PlotOptionsGantt(); + var dataLabels = new ArrayList(); + + var assigneeLabel = new DataLabels(true); + assigneeLabel.setAlign(HorizontalAlign.LEFT); + assigneeLabel.setFormat("{point.custom.assignee}"); + dataLabels.add(assigneeLabel); + + var avatarLabel = new DataLabels(true); + avatarLabel.setAlign(HorizontalAlign.LEFT); + avatarLabel.setUseHTML(true); + avatarLabel.setFormat( + "

" + + " " + + "
"); + dataLabels.add(avatarLabel); + + seriesPlotOptions.setDataLabels(dataLabels); + projectDevelopmentSeries.setPlotOptions(seriesPlotOptions); + configuration.addSeries(projectDevelopmentSeries); + + add(chart); + } + + private GanttSeries createProjectDevelopmentSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Project 1"); + + GanttSeriesItem item; + + item = new GanttSeriesItem(0, todayPlus(1), todayPlus(3)); + item.setCustom(new TaskCustomData("JonArild")); + series.add(item); + + item = new GanttSeriesItem(1, todayPlus(2), todayPlus(5)); + item.setCustom(new TaskCustomData("Oystein")); + series.add(item); + + item = new GanttSeriesItem(2, todayPlus(5), todayPlus(7)); + item.setCustom(new TaskCustomData("Torstein")); + series.add(item); + + item = new GanttSeriesItem(1, todayPlus(8), todayPlus(16)); + item.setCustom(new TaskCustomData("JonArild")); + series.add(item); + + item = new GanttSeriesItem(2, todayPlus(10), todayPlus(23)); + item.setCustom(new TaskCustomData("Torstein")); + series.add(item); + + return series; + } + + private Instant todayPlus(int days) { + return TODAY.plus(days, ChronoUnit.DAYS); + } + + @SuppressWarnings("unused") + static class TaskCustomData extends AbstractConfigurationObject { + private String assignee; + + public TaskCustomData(String assignee) { + this.assignee = assignee; + } + + public String getAssignee() { + return assignee; + } + + public void setAssignee(String assignee) { + this.assignee = assignee; + } + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java new file mode 100644 index 00000000000..ba03233a3c9 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java @@ -0,0 +1,176 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; +import com.vaadin.flow.component.charts.model.AxisGrid; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.HorizontalAlign; +import com.vaadin.flow.component.charts.model.Labels; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.TimeUnit; +import com.vaadin.flow.component.charts.model.TimeUnitMultiples; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; +import com.vaadin.flow.component.charts.model.style.Style; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttCustomXAxis extends AbstractChartExample { + + private static final Instant TODAY = Instant.now() + .truncatedTo(ChronoUnit.DAYS); + + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + configuration.getChart().setHeight("330"); + + configuration.setTitle("Custom XAxis Demo"); + configuration.setSubTitle("Showing years, months and week numbers"); + configuration.setTooltip(new Tooltip(true)); + + configureYearsMonthsWeeksOnXAxis(configuration); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setCategories("Prototyping", "Development", "Testing"); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + final GanttSeries projectDevelopmentSeries = createProjectDevelopmentSeries(); + configuration.addSeries(projectDevelopmentSeries); + + add(chart); + } + + private void configureYearsMonthsWeeksOnXAxis(Configuration configuration) { + configureWeeksAxis(configuration); + configureMonthsAxis(configuration); + configureYearsAxis(configuration); + } + + private void configureWeeksAxis(Configuration configuration) { + XAxis axis = new XAxis(); + configuration.addxAxis(axis); + + axis.setMinPadding(0.02); + axis.setMaxPadding(0.02); + axis.setUnits(new TimeUnitMultiples(TimeUnit.WEEK, 1)); + + final Labels labels = new Labels(); + labels.setPadding(1); + labels.setAlign(HorizontalAlign.LEFT); + var style = new Style(); + style.setFontSize("8px"); + labels.setStyle(style); + axis.setLabels(labels); + + axis.setGrid(new AxisGrid()); + axis.getGrid().setCellHeight(20); + } + + private void configureMonthsAxis(Configuration configuration) { + XAxis axis = new XAxis(); + configuration.addxAxis(axis); + axis.setTickInterval(1000 * 60 * 60 * 24 * 30L); + axis.setUnits(new TimeUnitMultiples(TimeUnit.MONTH, 1)); + + final Labels labels = new Labels(); + labels.setAlign(HorizontalAlign.LEFT); + var style = new Style(); + style.setFontSize("8px"); + labels.setStyle(style); + axis.setLabels(labels); + + axis.setGrid(new AxisGrid()); + axis.getGrid().setCellHeight(20); + } + + private void configureYearsAxis(Configuration configuration) { + XAxis axis = new XAxis(); + configuration.addxAxis(axis); + axis.setTickInterval(1000 * 60 * 60 * 24 * 365L); + axis.setUnits(new TimeUnitMultiples(TimeUnit.YEAR, 1)); + + final Labels labels = new Labels(); + labels.setAlign(HorizontalAlign.LEFT); + var style = new Style(); + style.setFontSize("8px"); + labels.setStyle(style); + axis.setLabels(labels); + + axis.setGrid(new AxisGrid()); + axis.getGrid().setCellHeight(20); + } + + private GanttSeries createProjectDevelopmentSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Project 1"); + + GanttSeriesItem item; + + item = new GanttSeriesItem(0, startOfYearPlus(1), startOfYearPlus(3)); + item.setCustom(new TaskCustomData("JonArild")); + series.add(item); + + item = new GanttSeriesItem(1, startOfYearPlus(4), startOfYearPlus(5)); + item.setCustom(new TaskCustomData("Oystein")); + series.add(item); + + item = new GanttSeriesItem(1, startOfYearPlus(8), startOfYearPlus(10)); + item.setCustom(new TaskCustomData("JonArild")); + series.add(item); + + item = new GanttSeriesItem(2, startOfYearPlus(5), startOfYearPlus(7)); + item.setCustom(new TaskCustomData("Torstein")); + series.add(item); + + item = new GanttSeriesItem(2, startOfYearPlus(9), startOfYearPlus(11)); + item.setCustom(new TaskCustomData("Torstein")); + series.add(item); + + return series; + } + + private Instant startOfYearPlus(int months) { + return TODAY.plus(months * 30L, ChronoUnit.DAYS); + } + + @SuppressWarnings("unused") + static class TaskCustomData extends AbstractConfigurationObject { + private String assignee; + + public TaskCustomData(String assignee) { + this.assignee = assignee; + } + + public String getAssignee() { + return assignee; + } + + public void setAssignee(String assignee) { + this.assignee = assignee; + } + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java new file mode 100644 index 00000000000..f8d11ce331a --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java @@ -0,0 +1,172 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; +import com.vaadin.flow.component.charts.model.AxisGrid; +import com.vaadin.flow.component.charts.model.AxisType; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.Labels; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttLeftAxisAsTable extends AbstractChartExample { + + private static final Instant TODAY = Instant.now() + .truncatedTo(ChronoUnit.DAYS); + + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + configuration.setTitle("Gantt Chart - Left Axis as Table"); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setTickPixelInterval(70); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setType(AxisType.CATEGORY); + + AxisGrid grid = new AxisGrid(); + grid.setEnabled(true); + grid.setColumns(List.of(createProjectColumn(), createAssigneeColumn(), + createEstDaysColumn(), createStartDateColumn(), + createEndDateColumn())); + yAxis.setGrid(grid); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + final GanttSeries projectDevelopmentSeries = createProjectDevelopmentSeries(); + PlotOptionsGantt seriesPlotOptions = new PlotOptionsGantt(); + projectDevelopmentSeries.setPlotOptions(seriesPlotOptions); + configuration.addSeries(projectDevelopmentSeries); + + add(chart); + } + + private XAxis createProjectColumn() { + XAxis column = new XAxis(); + column.setTitle("Project1"); + final Labels label = new Labels(); + label.setFormat("{point.name}"); + column.setLabels(label); + return column; + } + + private XAxis createAssigneeColumn() { + XAxis column = new XAxis(); + column.setTitle("Assignee"); + final Labels label = new Labels(); + label.setFormat("{point.custom.assignee}"); + column.setLabels(label); + return column; + } + + private XAxis createEstDaysColumn() { + XAxis column = new XAxis(); + column.setTitle("Est. Days"); + final Labels label = new Labels(); + label.setUseHTML(true); + label.setFormatter( + "function () { var point = this.point,days = (1000 * 60 * 60 * 24)," + + " number = (point.x2 - point.x) / days; " + + " return '
' + Math.round(number * 100) / 100 + '
'; }"); + column.setLabels(label); + return column; + } + + private XAxis createStartDateColumn() { + XAxis column = new XAxis(); + column.setTitle("Start Date"); + final Labels label = new Labels(); + label.setFormat("{point.start:%e. %b}"); + column.setLabels(label); + return column; + } + + private XAxis createEndDateColumn() { + XAxis column = new XAxis(); + column.setTitle("End Date"); + column.setOffset(30); + final Labels label = new Labels(); + label.setFormat("{point.end:%e. %b}"); + column.setLabels(label); + return column; + } + + private GanttSeries createProjectDevelopmentSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Project 1"); + + GanttSeriesItem item; + + item = new GanttSeriesItem("Start prototype", todayPlus(1), + todayPlus(3)); + item.setY(0); + item.setCustom(new TaskCustomData("Richards")); + series.add(item); + + item = new GanttSeriesItem("Develop", todayPlus(2), todayPlus(5)); + item.setY(1); + item.setCustom(new TaskCustomData("Oystein")); + series.add(item); + + item = new GanttSeriesItem("Test prototype", todayPlus(5), + todayPlus(7)); + item.setY(2); + item.setCustom(new TaskCustomData("Torstein")); + series.add(item); + + item = new GanttSeriesItem("Run acceptance tests", todayPlus(8), + todayPlus(12)); + item.setY(3); + item.setCustom(new TaskCustomData("Halliburton")); + series.add(item); + + return series; + } + + private Instant todayPlus(int days) { + return TODAY.plus(days, ChronoUnit.DAYS); + } + + @SuppressWarnings("unused") + static class TaskCustomData extends AbstractConfigurationObject { + private String assignee; + + public TaskCustomData(String assignee) { + this.assignee = assignee; + } + + public String getAssignee() { + return assignee; + } + + public void setAssignee(String assignee) { + this.assignee = assignee; + } + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java new file mode 100644 index 00000000000..b3502e3a6ce --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java @@ -0,0 +1,217 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; +import com.vaadin.flow.component.charts.model.ChartConnectors; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Completed; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.DashStyle; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.GanttSeriesItemDependency; +import com.vaadin.flow.component.charts.model.PlotLine; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.style.SolidColor; + +@SuppressWarnings("unused") +public class GanttProcessManagement extends AbstractChartExample { + private static final Instant TODAY = Instant.now() + .truncatedTo(ChronoUnit.DAYS); + + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + configuration.setTitle("Gantt Project Management"); + ChartConnectors connectors = new ChartConnectors(); + connectors.setDashStyle(DashStyle.SHORTDASH); + configuration.setConnectors(connectors); + + Tooltip tooltip = new Tooltip(); + tooltip.setPointFormat( + "{point.name}
Start: {point.start:%e. %b}
End: {point.end:%e. %b}
Owner: {point.custom.owner}"); + configuration.setTooltip(tooltip); + + XAxis xAxis = configuration.getxAxis(); + PlotLine dateIndicator = new PlotLine(); + dateIndicator.setDashStyle(DashStyle.DASH); + xAxis.setCurrentDateIndicator(dateIndicator); + xAxis.setMin(todayPlus(-3)); + xAxis.setMax(todayPlus(18)); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + configuration.addSeries(createOfficesSeries()); + configuration.addSeries(createNewProductLaunchSeries()); + + chart.addPointClickListener(event -> { + var name = ((GanttSeries) event.getSeries()) + .get(event.getItemIndex()).getName(); + System.out.println("Clicked on " + name); + }); + + add(chart); + } + + private GanttSeries createNewProductLaunchSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Product"); + + GanttSeriesItem item; + + item = new GanttSeriesItem(); + item.setName("New product launch"); + item.setId("new_product"); + item.setCustom(new TaskCustomData("Peter")); + series.add(item); + + item = new GanttSeriesItem("Development", todayPlus(-1), todayPlus(11)); + item.setId("development"); + item.setCompleted(new Completed(0.6, SolidColor.ORANGE)); + item.setCustom(new TaskCustomData("Susan")); + item.setParent("new_product"); + series.add(item); + + item = new GanttSeriesItem(); + item.setName("Beta"); + item.setStart(todayPlus(12)); + item.setId("beta"); + item.addDependency(new GanttSeriesItemDependency("development")); + item.setMilestone(true); + item.setCustom(new TaskCustomData("Peter")); + item.setParent("new_product"); + series.add(item); + + item = new GanttSeriesItem("Final development", todayPlus(13), + todayPlus(17)); + item.setId("finalize"); + item.addDependency(new GanttSeriesItemDependency("beta")); + item.setParent("new_product"); + series.add(item); + + item = new GanttSeriesItem(); + item.setName("Launch"); + item.setStart(todayPlus(17).plus(12, ChronoUnit.HOURS)); + item.addDependency(new GanttSeriesItemDependency("finalize")); + item.setMilestone(true); + item.setCustom(new TaskCustomData("Peter")); + item.setParent("new_product"); + series.add(item); + + return series; + } + + private GanttSeries createOfficesSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Offices"); + + GanttSeriesItem item; + + item = new GanttSeriesItem(); + item.setName("New offices"); + item.setId("new_offices"); + item.setCustom(new TaskCustomData("Peter")); + series.add(item); + + item = new GanttSeriesItem("Prepare office building", todayPlus(-2), + todayPlus(6)); + item.setId("prepare_building"); + item.setCustom(new TaskCustomData("Linda")); + item.setCompleted(0.2); + item.setParent("new_offices"); + series.add(item); + + item = new GanttSeriesItem("Inspect building", todayPlus(4), + todayPlus(8)); + item.setId("inspect_building"); + item.setParent("new_offices"); + item.setCustom(new TaskCustomData("Ivy")); + series.add(item); + + item = new GanttSeriesItem("Passed inspection", todayPlus(9), + todayPlus(9)); + item.setId("passed_inspection"); + item.addDependency("prepare_building"); + item.addDependency("inspect_building"); + item.setParent("new_offices"); + item.setMilestone(true); + item.setCustom(new TaskCustomData("Peter")); + series.add(item); + + item = new GanttSeriesItem(); + item.setName("Relocate"); + item.setId("relocate"); + item.addDependency(new GanttSeriesItemDependency("passed_inspection")); + item.setParent("new_offices"); + item.setCustom(new TaskCustomData("Josh")); + series.add(item); + + item = new GanttSeriesItem("Relocate staff", todayPlus(10), + todayPlus(11)); + item.setId("relocate_staff"); + item.setParent("relocate"); + item.setCustom(new TaskCustomData("Mark")); + series.add(item); + + item = new GanttSeriesItem("Relocate test facility", todayPlus(11), + todayPlus(13)); + item.setId("relocate_test_facility"); + item.addDependency(new GanttSeriesItemDependency("relocate_staff")); + item.setParent("relocate"); + item.setCustom(new TaskCustomData("Anne")); + series.add(item); + + item = new GanttSeriesItem("Relocate cantina", todayPlus(11), + todayPlus(14)); + item.setId("relocate_cantina"); + final GanttSeriesItemDependency relocateStaff = new GanttSeriesItemDependency( + "relocate_staff"); + relocateStaff.setDashStyle(DashStyle.SOLID); + item.addDependency(relocateStaff); + item.setParent("relocate"); + series.add(item); + + return series; + } + + private Instant todayPlus(int days) { + return TODAY.plus(days, ChronoUnit.DAYS); + } + + @SuppressWarnings("unused") + static class TaskCustomData extends AbstractConfigurationObject { + private String owner; + + public TaskCustomData(String owner) { + this.owner = owner; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + } + +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java new file mode 100644 index 00000000000..b6143f24b64 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java @@ -0,0 +1,71 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Completed; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.style.SolidColor; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttProgressIndicator extends AbstractChartExample { + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + + configuration.setTitle("Gantt Chart with Progress Indicators"); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setMin(Instant.parse("2014-10-17T00:00:00Z")); + xAxis.setMax(Instant.parse("2014-10-30T00:00:00Z")); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + GanttSeries series = new GanttSeries(); + series.setName("Project 1"); + final GanttSeriesItem startPrototype = new GanttSeriesItem( + "Start prototype", Instant.parse("2014-10-18T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z")); + startPrototype.setCompleted(0.25); + series.add(startPrototype); + + series.add(new GanttSeriesItem("Test prototype", + Instant.parse("2014-10-27T00:00:00Z"), + Instant.parse("2014-10-29T00:00:00Z"))); + + final GanttSeriesItem develop = new GanttSeriesItem("Develop", + Instant.parse("2014-10-20T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z")); + develop.setCompleted(new Completed(0.12, SolidColor.ORANGE)); + series.add(develop); + + series.add(new GanttSeriesItem("Run acceptance tests", + Instant.parse("2014-10-23T00:00:00Z"), + Instant.parse("2014-10-26T00:00:00Z"))); + + configuration.addSeries(series); + + add(chart); + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java new file mode 100644 index 00000000000..8174a9d4018 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java @@ -0,0 +1,164 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; +import com.vaadin.flow.component.charts.model.AxisType; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttResourceManagement extends AbstractChartExample { + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + var rentalData = getRentalData(); + + final Configuration configuration = chart.getConfiguration(); + + configuration.setTitle("Car Rental Schedule"); + + Tooltip tooltip = new Tooltip(); + tooltip.setPointFormat( + "Rented To: {point.custom.rentedTo}
From: {point.start:%e. %b}
To: {point.end:%e. %b}"); + configuration.setTooltip(tooltip); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setCurrentDateIndicator(true); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setType(AxisType.CATEGORY); + rentalData.forEach(car -> yAxis.addCategory(car.model)); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + for (int i = 0; i < rentalData.size(); i++) { + CarRental car = rentalData.get(i); + GanttSeries series = new GanttSeries(); + series.setName(car.model); + for (CarRentalDeal deal : car.deals) { + GanttSeriesItem item = new GanttSeriesItem(i, deal.from, + deal.to); + item.setId("deal-" + i); + item.setCustom(new TaskCustomData(deal.rentedTo)); + series.add(item); + } + configuration.addSeries(series); + } + + add(chart); + } + + private List getRentalData() { + var today = Instant.now().truncatedTo(ChronoUnit.DAYS); + return List.of( + new CarRental("Nissan Leaf") + .addDeal(new CarRentalDeal("Lisa Star", + plusDays(today, -1), plusDays(today, 2))) + .addDeal(new CarRentalDeal("Shane Long", + plusDays(today, -3), plusDays(today, -2))) + .addDeal(new CarRentalDeal("Jack Coleman", + plusDays(today, 5), plusDays(today, 6))), + new CarRental("Jaguar E-type") + .addDeal(new CarRentalDeal("Martin Hammond", + plusDays(today, -2), plusDays(today, 1))) + .addDeal(new CarRentalDeal("Linda Jackson", + plusDays(today, -2), plusDays(today, 1))) + .addDeal(new CarRentalDeal("Robert Sailor", + plusDays(today, 2), plusDays(today, 6))), + new CarRental("Volvo V60") + .addDeal(new CarRentalDeal("Mona Ricci", today, + plusDays(today, 3))) + .addDeal(new CarRentalDeal("Jane Dockerman", + plusDays(today, 3), plusDays(today, 4))) + .addDeal(new CarRentalDeal("Bob Shurro", + plusDays(today, 6), plusDays(today, 8))), + new CarRental("Volkswagen Golf") + .addDeal(new CarRentalDeal("Hailie Marshall", + plusDays(today, -1), plusDays(today, 1))) + .addDeal(new CarRentalDeal("Morgan Nicholson", + plusDays(today, -3), plusDays(today, -2))) + .addDeal(new CarRentalDeal("William Harriet", + plusDays(today, 2), plusDays(today, 3))), + new CarRental("Peugeot 208") + .addDeal(new CarRentalDeal("Harry Peterson", + plusDays(today, -1), plusDays(today, 2))) + .addDeal(new CarRentalDeal("Emma Wilson", + plusDays(today, 3), plusDays(today, 4))) + .addDeal(new CarRentalDeal("Ron Donald", + plusDays(today, 5), plusDays(today, 6)))); + } + + private Instant plusDays(Instant date, int days) { + return date.plus(days, ChronoUnit.DAYS); + } + + static class CarRental { + private final String model; + private final List deals = new ArrayList<>(); + + public CarRental(String model) { + this.model = model; + } + + public CarRental addDeal(CarRentalDeal deal) { + deals.add(deal); + return this; + } + } + + static class CarRentalDeal { + private final String rentedTo; + private final Instant from; + private final Instant to; + + public CarRentalDeal(String rentedTo, Instant from, Instant to) { + this.rentedTo = rentedTo; + this.from = from; + this.to = to; + } + } + + @SuppressWarnings("unused") + static class TaskCustomData extends AbstractConfigurationObject { + private String rentedTo; + + public TaskCustomData(String rentedTo) { + this.rentedTo = rentedTo; + } + + public String getRentedTo() { + return rentedTo; + } + + public void setRentedTo(String rentedTo) { + this.rentedTo = rentedTo; + } + } + +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java new file mode 100644 index 00000000000..c0975bbcfdc --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java @@ -0,0 +1,72 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.DataSeries; +import com.vaadin.flow.component.charts.model.DataSeriesItemXrange; +import com.vaadin.flow.component.charts.model.PlotOptionsXrange; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttUsingXRangeSeries extends AbstractChartExample { + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.XRANGE); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + + configuration.setTitle("Gantt Chart using XRANGE series"); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setMin(Instant.parse("2014-10-17T00:00:00Z")); + xAxis.setMax(Instant.parse("2014-10-30T00:00:00Z")); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setCategories("Start prototype", "Test prototype", "Develop", + "Run acceptance tests"); + + PlotOptionsXrange plotOptionsXrange = new PlotOptionsXrange(); + configuration.setPlotOptions(plotOptionsXrange); + + DataSeries series = new DataSeries(); + series.setName("Project 1"); + final DataSeriesItemXrange startPrototype = new DataSeriesItemXrange( + Instant.parse("2014-10-18T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z"), 0); + series.add(startPrototype); + + series.add( + new DataSeriesItemXrange(Instant.parse("2014-10-27T00:00:00Z"), + Instant.parse("2014-10-29T00:00:00Z"), 1)); + + final DataSeriesItemXrange develop = new DataSeriesItemXrange( + Instant.parse("2014-10-20T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z"), 2); + series.add(develop); + + series.add( + new DataSeriesItemXrange(Instant.parse("2014-10-23T00:00:00Z"), + Instant.parse("2014-10-26T00:00:00Z"), 3)); + + configuration.addSeries(series); + + add(chart); + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java new file mode 100644 index 00000000000..74e8bdc9ee8 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java @@ -0,0 +1,93 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Completed; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.Navigator; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.YAxis; +import com.vaadin.flow.component.charts.model.style.SolidColor; + +@SuppressWarnings("unused") +public class GanttWithNavigation extends AbstractChartExample { + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + chart.setMode(ChartMode.GANTT); + + final Configuration configuration = chart.getConfiguration(); + + configuration.setTitle("Gantt Chart with Navigation"); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setUniqueNames(true); + + configureNavigator(configuration); + + configuration.getScrollbar().setEnabled(true); + + configuration.getRangeSelector().setEnabled(true); + configuration.getRangeSelector().setSelected(0); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + configuration.setPlotOptions(plotOptionsGantt); + + final GanttSeries series = createProjectManagementSeries(); + configuration.addSeries(series); + + add(chart); + } + + private GanttSeries createProjectManagementSeries() { + GanttSeries series = new GanttSeries(); + series.setName("Project 1"); + final GanttSeriesItem startPrototype = new GanttSeriesItem( + "Start prototype", Instant.parse("2013-10-18T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z")); + startPrototype.setCompleted(0.25); + series.add(startPrototype); + + series.add(new GanttSeriesItem("Test prototype", + Instant.parse("2014-02-27T00:00:00Z"), + Instant.parse("2014-10-29T00:00:00Z"))); + + final GanttSeriesItem develop = new GanttSeriesItem("Develop", + Instant.parse("2014-10-20T00:00:00Z"), + Instant.parse("2014-10-25T00:00:00Z")); + develop.setCompleted(new Completed(0.12, SolidColor.ORANGE)); + series.add(develop); + + series.add(new GanttSeriesItem("Run acceptance tests", + Instant.parse("2014-10-23T00:00:00Z"), + Instant.parse("2014-10-26T00:00:00Z"))); + return series; + } + + private void configureNavigator(Configuration configuration) { + final Navigator navigator = configuration.getNavigator(); + navigator.setEnabled(true); + final PlotOptionsGantt navigatorPlotOptions = new PlotOptionsGantt(); + navigatorPlotOptions.setPointPadding(0.2); + navigator.setSeries(navigatorPlotOptions); + final YAxis navigatorYAxis = navigator.getYAxis(); + navigatorYAxis.setMin(0); + navigatorYAxis.setMax(3); + navigatorYAxis.setReversed(true); + navigatorYAxis.setCategories(); + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java new file mode 100644 index 00000000000..fb13635604e --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java @@ -0,0 +1,111 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import java.util.List; + +import com.vaadin.flow.component.charts.model.style.Color; + +@SuppressWarnings("unused") +public class AxisGrid extends AbstractConfigurationObject { + + private Color borderColor; + private Number borderWidth; + private Number cellHeight; + private List columns; + private Boolean enabled; + + /** + * @see #setBorderColor(Color) + */ + public Color getBorderColor() { + return borderColor; + } + + /** + * Set border color for the label grid lines. Defaults to undefined. + */ + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + /** + * @see #setBorderWidth(Number) + */ + public Number getBorderWidth() { + return borderWidth; + } + + /** + * Set border width of the label grid lines. Defaults to 1. + */ + public void setBorderWidth(Number borderWidth) { + this.borderWidth = borderWidth; + } + + /** + * @see #setCellHeight(Number) + */ + public Number getCellHeight() { + return cellHeight; + } + + /** + * Set cell height for grid axis labels. By default this is calculated from + * font size. This option only applies to horizontal axes. Defaults to + * undefined. + */ + public void setCellHeight(Number cellHeight) { + this.cellHeight = cellHeight; + } + + /** + * @see #setColumns(List) + */ + public List getColumns() { + return columns; + } + + /** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be + * set here. Defaults to undefined. + */ + public void setColumns(List columns) { + this.columns = columns; + } + + /** + * Add a new column to the grid. See {@link #setColumns(List)} + * + * @param column + * A column to be added + */ + public void addColumn(XAxis column) { + if (columns == null) { + columns = new java.util.ArrayList<>(); + } + columns.add(column); + } + + /** + * @see #setEnabled(Boolean) + */ + public Boolean getEnabled() { + return enabled; + } + + /** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * Defaults to true. + */ + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java new file mode 100644 index 00000000000..79a58d68e99 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java @@ -0,0 +1,55 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +/** + * A configuration object to configure style of connectors (dependencies) + * between two points in a Gantt chart. + */ +@SuppressWarnings("unused") +public class ChartConnectors extends ConnectorStyle { + + private Number algorithmMargin; + private Boolean enabled; + + /** + * @see #setAlgorithmMargin(Number) + */ + public Number getAlgorithmMargin() { + return algorithmMargin; + } + + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the chart. + * These algorithms use this margin to determine how close lines can be to + * an obstacle. The default is to compute this automatically from the size + * of the obstacles in the chart. To draw connecting lines close to existing + * points, set this to a low number. For more space around existing points, + * set this number higher. + */ + public void setAlgorithmMargin(Number algorithmMargin) { + this.algorithmMargin = algorithmMargin; + } + + /** + * @see #setEnabled(Boolean) + */ + public Boolean getEnabled() { + return enabled; + } + + /** + * Enable connectors for this chart. Requires Highcharts Gantt. Defaults to + * true. + */ + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java new file mode 100644 index 00000000000..83d5ec77d44 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java @@ -0,0 +1,67 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import com.vaadin.flow.component.charts.model.style.Color; + +/** + * Progress indicator, how much of the task completed + */ +@SuppressWarnings("unused") +public class Completed extends AbstractConfigurationObject { + + private Number amount; + private Color fill; + + public Completed() { + } + + public Completed(Number amount) { + this.amount = amount; + } + + public Completed(Number amount, Color fill) { + this.amount = amount; + this.fill = fill; + } + + /** + * @see #setAmount(Number) + */ + public Number getAmount() { + return amount; + } + + /** + * The amount of the progress indicator, ranging from 0 (not started) to 1 + * (finished). Defaults to 0. + * + * @param amount + */ + public void setAmount(Number amount) { + this.amount = amount; + } + + /** + * @see #setFill(Color) + */ + public Color getFill() { + return fill; + } + + /** + * The fill of the progress indicator. Defaults to a darkened variety of the + * main color. The value will be ignored if the chart is in Styled mode. + * + * @param fill + */ + public void setFill(Color fill) { + this.fill = fill; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java index b010a9b147e..f588ee19086 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.events.internal.AxisRescaledEvent; import com.vaadin.flow.component.charts.events.internal.ConfigurationChangeListener; import com.vaadin.flow.component.charts.events.internal.DataAddedEvent; @@ -61,6 +62,7 @@ public class Configuration extends AbstractConfigurationObject private Navigator navigator; private Time time; private List annotations; + private ChartConnectors connectors; @JsonIgnore private final List changeListeners = new ArrayList<>(); @@ -687,8 +689,8 @@ public void addPane(Pane pane) { /** * Set settings for range selector. *

- * This is only valid if the chart is configured to use timeline. See - * {@link com.vaadin.flow.component.charts.Chart#setTimeline(Boolean)}} + * This is only valid if the chart is configured to use timeline mode. See + * {@link com.vaadin.flow.component.charts.Chart#setMode(ChartMode)}} * * @param rangeSelector * @see RangeSelector @@ -1180,4 +1182,28 @@ private AnnotationItem getLabelsAnnotation() { } return annotations.get(0); } + + /** + * @see #setConnectors(ChartConnectors) + */ + public ChartConnectors getConnectors() { + return connectors; + } + + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. In Gantt charts, the connectors are used + * to draw dependencies between tasks. + * + * Values set here serve as the default values for all connectors in the + * chart. Individual style for a connector can be set on each point + * dependency (see {@link GanttSeriesItemDependency}). + * + * @param connectors + */ + public void setConnectors(ChartConnectors connectors) { + this.connectors = connectors; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java new file mode 100644 index 00000000000..c7e549c34f0 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java @@ -0,0 +1,133 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import com.vaadin.flow.component.charts.model.style.Color; + +/** + * A configuration object to configure style of connectors (dependencies) + * between two points in a Gantt chart. + */ +@SuppressWarnings("unused") +public class ConnectorStyle extends AbstractConfigurationObject { + + private DashStyle dashStyle; + private Marker endMarker; + private Color lineColor; + private Number lineWidth; + private Marker marker; + private Marker startMarker; + private PathfinderType type; + + /** + * @see #setDashStyle(DashStyle) + */ + public DashStyle getDashStyle() { + return dashStyle; + } + + /** + * Set the default dash style for this chart's connecting lines. Defaults to + * solid. + */ + public void setDashStyle(DashStyle dashStyle) { + this.dashStyle = dashStyle; + } + + /** + * @see #setEndMarker(Marker) + */ + public Marker getEndMarker() { + return endMarker; + } + + /** + * Marker options specific to the end markers for this chart's Pathfinder + * connectors. Overrides the generic marker options. + */ + public void setEndMarker(Marker endMarker) { + this.endMarker = endMarker; + } + + /** + * @see #setLineColor(Color) + */ + public Color getLineColor() { + return lineColor; + } + + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + */ + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + /** + * @see #setLineWidth(Number) + */ + public Number getLineWidth() { + return lineWidth; + } + + /** + * Set the default pixel width for this chart's Pathfinder connecting lines. + * Defaults to 1. + */ + public void setLineWidth(Number lineWidth) { + this.lineWidth = lineWidth; + } + + /** + * @see #setMarker(Marker) + */ + public Marker getMarker() { + return marker; + } + + /** + * Marker options for this chart's Pathfinder connectors. Note that this + * option is overridden by the startMarker and endMarker options. + */ + public void setMarker(Marker marker) { + this.marker = marker; + } + + /** + * @see #setStartMarker(Marker) + */ + public Marker getStartMarker() { + return startMarker; + } + + /** + * Marker options specific to the start markers for this chart's Pathfinder + * connectors. Overrides the generic marker options. + */ + public void setStartMarker(Marker startMarker) { + this.startMarker = startMarker; + } + + /** + * @see #setType(PathfinderType) + */ + public PathfinderType getType() { + return type; + } + + /** + * Set the default pathfinder algorithm to use for this chart. + * + * @see PathfinderType + */ + public void setType(PathfinderType type) { + this.type = type; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DataLabels.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DataLabels.java index f4143648624..b52094de8ae 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DataLabels.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DataLabels.java @@ -58,6 +58,7 @@ public class DataLabels extends AbstractDataLabels { private Number connectorWidth; private Number distance; private Boolean softConnector; + private HorizontalAlign position; public DataLabels() { } @@ -598,4 +599,21 @@ public Boolean getSoftConnector() { public void setSoftConnector(Boolean softConnector) { this.softConnector = softConnector; } + + /** + * @see #setPosition(HorizontalAlign) + */ + public HorizontalAlign getPosition() { + return position; + } + + /** + * Aligns data labels relative to points. If center alignment is not + * possible, it defaults to right. Defaults to "center". + * + * @param position + */ + public void setPosition(HorizontalAlign position) { + this.position = position; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java new file mode 100644 index 00000000000..8d9f4663016 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java @@ -0,0 +1,116 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * A series of tasks to be used in the Gantt chart. Each task (represented by + * {@link GanttSeriesItem}) has a start and an end date. + */ +@SuppressWarnings("unused") +public class GanttSeries extends AbstractSeries { + + private List data = new ArrayList<>(); + + public GanttSeries() { + } + + /** + * Constructs a GanttSeries with the given name + * + * @param name + * The name of this series. + */ + public GanttSeries(String name) { + super(name); + } + + /** + * Constructs a GanttSeries with the given name and data + * + * @param name + * The name of this series + * @param data + * The data of this series + */ + public GanttSeries(String name, Collection data) { + this(name); + setData(data); + } + + /** + * Return an unmodifiable copy of the items in this series. + * + * @return + * @see #setData(Collection) + */ + public Collection getData() { + return Collections.unmodifiableCollection(data); + } + + /** + * Set the list of {@link GanttSeriesItem} in this series. + * + * @param data + */ + public void setData(Collection data) { + this.data = new LinkedList<>(data); + } + + /** + * Remove all items in the series. + */ + public void clearSeries() { + data.clear(); + } + + /** + * Add given item to the series + * + * @param item + */ + public void add(GanttSeriesItem item) { + data.add(item); + } + + /** + * Add all the given items to the series + * + * @param items + */ + public void addAll(GanttSeriesItem... items) { + data.addAll(Arrays.asList(items)); + } + + /** + * Returns {@link GanttSeriesItem} at given index + * + * @param index + * @return the Item + * @throws IndexOutOfBoundsException + * if data series don't have item at given index + */ + public GanttSeriesItem get(int index) { + return data.get(index); + } + + /** + * @return the number of data items in the series + */ + public int size() { + return data.size(); + } + +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java new file mode 100644 index 00000000000..bf73b5da0ff --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java @@ -0,0 +1,347 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.flow.component.charts.model.style.Color; +import com.vaadin.flow.component.charts.util.Util; + +/** + * Data for the {@link GanttSeries}. Represents one task in the Gantt chart. + */ +@SuppressWarnings("unused") +public class GanttSeriesItem extends AbstractConfigurationObject { + + private Boolean collapsed; + private Color color; + private Number colorIndex; + private Completed completed; + private AbstractConfigurationObject custom; + private List dependency; + private String description; + private Number end; + private String id; + private Number labelrank; + private Boolean milestone; + private String name; + private String parent; + private Number start; + private Number y; + + public GanttSeriesItem() { + } + + public GanttSeriesItem(String name, Instant start, Instant end) { + setName(name); + setStart(start); + setEnd(end); + } + + public GanttSeriesItem(Number y, Instant start, Instant end) { + setY(y); + setStart(start); + setEnd(end); + } + + /** + * @see #setColorIndex(Number) + */ + public Number getColorIndex() { + return colorIndex; + } + + /** + * A specific color index to use for the point, so its graphic + * representations are given the class name + * highcharts-color-{n}. In styled + * mode this will change the color of the graphic. In non-styled mode, + * the color by is set by the fill attribute, so the change in + * class name won't have a visual effect by default. + *

+ */ + public void setColorIndex(Number colorIndex) { + this.colorIndex = colorIndex; + } + + /** + * @see #setCollapsed(Boolean) + */ + public Boolean getCollapsed() { + return collapsed; + } + + /** + * Whether the grid node belonging to this point should start as collapsed. + * Used in axes of type treegrid. Defaults to false. + * + * @param collapsed + */ + public void setCollapsed(Boolean collapsed) { + this.collapsed = collapsed; + } + + /** + * @see #setColor(Color) + */ + public Color getColor() { + return color; + } + + /** + * Sets the individual color for the point. Defaults to null. This might not + * work for all chart types. In styled mode, the color option doesn't take + * effect. Instead, use colorIndex. + * + * @param color + * Color of the point. + */ + public void setColor(Color color) { + this.color = color; + } + + /** + * @see #setCompleted(Completed) + */ + public Completed getCompleted() { + return completed; + } + + /** + * Progress indicator of how much of the task is completed. + * + * @param completed + */ + public void setCompleted(Completed completed) { + this.completed = completed; + } + + /** + * Progress indicator of how much of the task is completed. + * + * @param completed + */ + public void setCompleted(Number completed) { + if (this.completed == null) { + this.completed = new Completed(); + } + + this.completed.setAmount(completed); + } + + /** + * @see #setDependencies(List) + */ + public List getDependencies() { + return dependency; + } + + /** + * Dependencies on another tasks (points) in the Gantt chart. + * + * @see #addDependency(GanttSeriesItemDependency) + * @see #addDependency(String) + */ + public void setDependencies(List dependencies) { + this.dependency = dependencies; + } + + /** + * Adds a dependency on another task. + * + * @param dependency + * The dependency configuration object, allowing to specify + * further connecting options between the points. + */ + public void addDependency(GanttSeriesItemDependency dependency) { + if (this.dependency == null) { + this.dependency = new ArrayList<>(); + } + this.dependency.add(dependency); + } + + /** + * Adds a dependency on another task. + * + * @param to + * The ID of the point (task) that this point depends on in Gantt + * charts + */ + public void addDependency(String to) { + addDependency(new GanttSeriesItemDependency(to)); + } + + /** + * @see #setEnd(Instant) + */ + public Number getEnd() { + return end; + } + + /** + * The end time of a task. + * + * @param end + */ + public void setEnd(Instant end) { + this.end = Util.toHighchartsTS(end); + } + + /** + * @see #setMilestone(Boolean) + */ + public Boolean getMilestone() { + return milestone; + } + + /** + * Whether this point is a milestone. If so, only the start option is + * handled, while end is ignored. Defaults to false. + * + * @param milestone + */ + public void setMilestone(Boolean milestone) { + this.milestone = milestone; + } + + /** + * @see #setParent(String) + */ + public String getParent() { + return parent; + } + + /** + * The ID of the parent point (task) of this point in Gantt charts. Defaults + * to null + * + * @param parent + */ + public void setParent(String parent) { + this.parent = parent; + } + + /** + * @see #setStart(Instant) + */ + public Number getStart() { + return start; + } + + /** + * The start time of a task. + * + * @param start + */ + public void setStart(Instant start) { + this.start = Util.toHighchartsTS(start); + } + + /** + * @see #setY(Number) + */ + public Number getY() { + return y; + } + + /** + * The Y value of a task. + * + * @param y + */ + public void setY(Number y) { + this.y = y; + } + + /** + * @see #setDescription(String) + */ + public String getDescription() { + return description; + } + + /** + *

+ * A description of the point to add to the screen reader information about + * the point. + *

+ */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @see #setId(String) + */ + public String getId() { + return id; + } + + /** + * An id for the point. + */ + public void setId(String id) { + this.id = id; + } + + /** + * @see #setLabelrank(Number) + */ + public Number getLabelrank() { + return labelrank; + } + + /** + *

+ * The rank for this point's data label in case of collision. If two data + * labels are about to overlap, only the one with the highest + * labelrank will be drawn. + *

+ */ + public void setLabelrank(Number labelrank) { + this.labelrank = labelrank; + } + + /** + * @see #setName(String) + */ + public String getName() { + return name; + } + + /** + * The name of a task. If a treegrid y-axis is used (default in Gantt + * charts), this will be picked up automatically, and used to calculate the + * y-value. + */ + public void setName(String name) { + this.name = name; + } + + /** + * See also {@link #setCustom(AbstractConfigurationObject)} + */ + public AbstractConfigurationObject getCustom() { + return custom; + } + + /** + * A reserved subspace to store options and values for customized + * functionality. Here you can add additional data for your own event + * callbacks and formatter callbacks. + * + * @param custom + */ + public void setCustom(AbstractConfigurationObject custom) { + this.custom = custom; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java new file mode 100644 index 00000000000..21449ef5fa9 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java @@ -0,0 +1,40 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +/** + * A configuration object to express dependencies between tasks in a Gantt + * chart. + */ +@SuppressWarnings("unused") +public class GanttSeriesItemDependency extends ConnectorStyle { + + private String to; + + public GanttSeriesItemDependency() { + } + + public GanttSeriesItemDependency(String to) { + this.to = to; + } + + /** + * @see #setTo(String) + */ + public String getTo() { + return to; + } + + /** + * The ID of the point to connect to. + */ + public void setTo(String to) { + this.to = to; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java index 4070f0e6bcf..5cf9ec629f9 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java @@ -26,6 +26,9 @@ public class Marker extends AbstractConfigurationObject { private States states; private Number width; private MarkerSymbol symbol; + private HorizontalAlign align; + private VerticalAlign verticalAlign; + private Boolean inside; public Marker() { } @@ -173,4 +176,48 @@ public MarkerSymbol getSymbol() { public void setSymbol(MarkerSymbol symbol) { this.symbol = symbol; } + + /** + * @see #setAlign(HorizontalAlign) + */ + public HorizontalAlign getAlign() { + return align; + } + + /** + * Horizontal alignment of the markers relative to the points. Defaults to + * "center" + */ + public void setAlign(HorizontalAlign align) { + this.align = align; + } + + /** + * @see #setVerticalAlign(VerticalAlign) + */ + public VerticalAlign getVerticalAlign() { + return verticalAlign; + } + + /** + * Vertical alignment of the markers relative to the points. Defaults to + * "middle" + */ + public void setVerticalAlign(VerticalAlign verticalAlign) { + this.verticalAlign = verticalAlign; + } + + /** + * @see #setInside(Boolean) + */ + public Boolean getInside() { + return inside; + } + + /** + * Whether to draw the markers inside the points. Defaults to false. + */ + public void setInside(Boolean inside) { + this.inside = inside; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java new file mode 100644 index 00000000000..145fd7a8a70 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java @@ -0,0 +1,46 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +/** + * Pathfinder algorithm to use for chart that can connect two points (e.g. + * series items_. + */ +public enum PathfinderType implements ChartEnum { + + /** + * Draws a straight line between the connecting points. Does not avoid other + * points when drawing. + */ + STRAIGHT("straight"), + + /** + * Finds a path between the points using right angles only. Takes only + * starting/ending points into account, and will not avoid other points. + */ + SIMPLE_CONNECT("simpleConnect"), + + /** + * Finds a path between the points using right angles only. Will attempt to + * avoid other points, but its focus is performance over accuracy. Works + * well with less dense datasets. + */ + FAST_AVOID("fastAvoid"); + + PathfinderType(String type) { + this.type = type; + } + + private final String type; + + @Override + public String toString() { + return type; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java new file mode 100644 index 00000000000..15610cf114b --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java @@ -0,0 +1,891 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.vaadin.flow.component.charts.model.style.Color; + +/** + * Options for the gantt series type. + */ +@SuppressWarnings("unused") +public class PlotOptionsGantt extends AbstractPlotOptions { + + private Boolean allowPointSelect; + private Boolean animation; + private Number animationLimit; + private Color borderColor; + private Number borderRadius; + private Number borderWidth; + private Boolean centerInCategory; + private String className; + private Boolean clip; + private Color color; + private Boolean colorByPoint; + private Number colorIndex; + private ArrayList colors; + private SeriesConnectors connectors; + private Cursor cursor; + private AbstractConfigurationObject custom; + private DashStyle dashStyle; + private ArrayList dataLabels; + private String description; + private Boolean enableMouseTracking; + private Boolean grouping; + private Number groupPadding; + private ArrayList keys; + private String linkedTo; + private Number maxPointWidth; + private Number minPointLength; + private Number opacity; + private PartialFill partialFill; + private String _fn_pointDescriptionFormatter; + private Number pointPadding; + private Number pointWidth; + private Boolean selected; + private Boolean shadow; + private Boolean showCheckbox; + private Boolean showInLegend; + private Boolean skipKeyboardNavigation; + private States states; + private Boolean stickyTracking; + private SeriesTooltip tooltip; + private Number turboThreshold; + private Boolean visible; + + public PlotOptionsGantt() { + } + + @Override + public ChartType getChartType() { + return ChartType.GANTT; + } + + /** + * @see #setAllowPointSelect(Boolean) + */ + public Boolean getAllowPointSelect() { + return allowPointSelect; + } + + /** + * Allow this series' points to be selected by clicking on the markers, bars + * or pie slices. + *

+ * Defaults to: false + */ + public void setAllowPointSelect(Boolean allowPointSelect) { + this.allowPointSelect = allowPointSelect; + } + + /** + * @see #setAnimation(Boolean) + */ + public Boolean getAnimation() { + return animation; + } + + /** + * Enable or disable the initial animation when a series is displayed. + * Please note that this option only applies to the initial animation of the + * series itself. For other animations, see + * {@link ChartModel#setAnimation(Boolean)} + */ + public void setAnimation(Boolean animation) { + this.animation = animation; + } + + /** + * @see #setAnimationLimit(Number) + */ + public Number getAnimationLimit() { + return animationLimit; + } + + /** + * For some series, there is a limit that shuts down initial animation by + * default when the total number of points in the chart is too high. For + * example, for a column chart and its derivatives, animation doesn't run if + * there is more than 250 points totally. To disable this cap, set + * animationLimit to Infinity. + */ + public void setAnimationLimit(Number animationLimit) { + this.animationLimit = animationLimit; + } + + /** + * @see #setBorderColor(Color) + */ + public Color getBorderColor() { + return borderColor; + } + + /** + *

+ * The color of the border surrounding each column or bar. + *

+ * + *

+ * In styled mode, the border stroke can be set with the + * .highcharts-point rule. + *

+ *

+ * Defaults to: #ffffff + */ + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + /** + * @see #setBorderRadius(Number) + */ + public Number getBorderRadius() { + return borderRadius; + } + + /** + * The corner radius of the border surrounding each column or bar. + *

+ * Defaults to: 0 + */ + public void setBorderRadius(Number borderRadius) { + this.borderRadius = borderRadius; + } + + /** + * @see #setBorderWidth(Number) + */ + public Number getBorderWidth() { + return borderWidth; + } + + /** + *

+ * The width of the border surrounding each column or bar. + *

+ * + *

+ * In styled mode, the stroke width can be set with the + * .highcharts-point rule. + *

+ *

+ * Defaults to: 1 + */ + public void setBorderWidth(Number borderWidth) { + this.borderWidth = borderWidth; + } + + /** + * @see #setClassName(String) + */ + public String getClassName() { + return className; + } + + /** + * A class name to apply to the series' graphical elements. + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * @see #setColor(Color) + */ + public Color getColor() { + return color; + } + + /** + *

+ * The main color or the series. In line type series it applies to the line + * and the point markers unless otherwise specified. In bar type series it + * applies to the bars unless a color is specified per point. The default + * value is pulled from the options.colors array. + *

+ * + *

+ * In styled mode, the color can be defined by the + * colorIndex option. Also, the + * series color can be set with the .highcharts-series, + * .highcharts-color-{n}, + * .highcharts-{type}-series or + * .highcharts-series-{n} class, or individual classes given by + * the className option. + *

+ */ + public void setColor(Color color) { + this.color = color; + } + + /** + * @see #setColorByPoint(Boolean) + */ + public Boolean getColorByPoint() { + return colorByPoint; + } + + /** + * When using automatic point colors pulled from the + * options.colors collection, this option determines whether + * the chart should receive one color per series or one color per point. + *

+ * Defaults to: false + */ + public void setColorByPoint(Boolean colorByPoint) { + this.colorByPoint = colorByPoint; + } + + /** + * @see #setColorIndex(Number) + */ + public Number getColorIndex() { + return colorIndex; + } + + /** + * Styled mode only. A specific color index to use for the series, so + * its graphic representations are given the class name + * highcharts-color-{n}. + */ + public void setColorIndex(Number colorIndex) { + this.colorIndex = colorIndex; + } + + /** + * @see #setColors(Color...) + */ + public Color[] getColors() { + if (colors == null) { + return new Color[] {}; + } + Color[] arr = new Color[colors.size()]; + colors.toArray(arr); + return arr; + } + + /** + * A series specific or series type specific color set to apply instead of + * the global colors when + * colorByPoint is true. + */ + public void setColors(Color... colors) { + this.colors = new ArrayList<>(Arrays.asList(colors)); + } + + /** + * Adds color to the colors array + * + * @param color + * to add + * @see #setColors(Color...) + */ + public void addColor(Color color) { + if (this.colors == null) { + this.colors = new ArrayList<>(); + } + this.colors.add(color); + } + + /** + * Removes first occurrence of color in colors array + * + * @param color + * to remove + * @see #setColors(Color...) + */ + public void removeColor(Color color) { + this.colors.remove(color); + } + + /** + * @see #setCursor(Cursor) + */ + public Cursor getCursor() { + return cursor; + } + + /** + * You can set the cursor to "pointer" if you have click events attached to + * the series, to signal to the user that the points and lines can be + * clicked. + */ + public void setCursor(Cursor cursor) { + this.cursor = cursor; + } + + /** + * @see #setDataLabels(ArrayList) + */ + public ArrayList getDataLabels() { + if (dataLabels == null) { + dataLabels = new ArrayList<>(); + } + return dataLabels; + } + + /** + *

+ * Options for the series data labels, appearing next to each data point. + *

+ * + *

+ * In styled mode, the data labels can be styled wtih the + * .highcharts-data-label-box and + * .highcharts-data-label class names (see example). + *

+ */ + public void setDataLabels(ArrayList dataLabels) { + this.dataLabels = dataLabels; + } + + /** + * @see #setDescription(String) + */ + public String getDescription() { + return description; + } + + /** + *

+ * Requires Accessibility module + *

+ *

+ * A description of the series to add to the screen reader information about + * the series. + *

+ *

+ * Defaults to: undefined + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @see #setEnableMouseTracking(Boolean) + */ + public Boolean getEnableMouseTracking() { + return enableMouseTracking; + } + + /** + * Enable or disable the mouse tracking for a specific series. This includes + * point tooltips and click events on graphs and points. For large datasets + * it improves performance. + *

+ * Defaults to: true + */ + public void setEnableMouseTracking(Boolean enableMouseTracking) { + this.enableMouseTracking = enableMouseTracking; + } + + /** + * @see #setGroupPadding(Number) + */ + public Number getGroupPadding() { + return groupPadding; + } + + /** + * Padding between each value groups, in x axis units. + *

+ * Defaults to: 0.2 + */ + public void setGroupPadding(Number groupPadding) { + this.groupPadding = groupPadding; + } + + /** + * @see #setGrouping(Boolean) + */ + public Boolean getGrouping() { + return grouping; + } + + /** + * Whether to group non-stacked columns or to let them render independent of + * each other. Non-grouped columns will be laid out individually and overlap + * each other. + *

+ * Defaults to: true + */ + public void setGrouping(Boolean grouping) { + this.grouping = grouping; + } + + /** + * @see #setKeys(String...) + */ + public String[] getKeys() { + if (keys == null) { + return new String[] {}; + } + String[] arr = new String[keys.size()]; + keys.toArray(arr); + return arr; + } + + /** + * An array specifying which option maps to which key in the data point + * array. This makes it convenient to work with unstructured data arrays + * from different sources. + */ + public void setKeys(String... keys) { + this.keys = new ArrayList<>(Arrays.asList(keys)); + } + + /** + * Adds key to the keys array + * + * @param key + * to add + * @see #setKeys(String...) + */ + public void addKey(String key) { + if (this.keys == null) { + this.keys = new ArrayList<>(); + } + this.keys.add(key); + } + + /** + * Removes first occurrence of key in keys array + * + * @param key + * to remove + * @see #setKeys(String...) + */ + public void removeKey(String key) { + this.keys.remove(key); + } + + /** + * @see #setLinkedTo(String) + */ + public String getLinkedTo() { + return linkedTo; + } + + /** + * The id of another series to link to. + * Additionally, the value can be ":previous" to link to the previous + * series. When two series are linked, only the first one appears in the + * legend. Toggling the visibility of this also toggles the linked series. + */ + public void setLinkedTo(String linkedTo) { + this.linkedTo = linkedTo; + } + + /** + * @see #setMaxPointWidth(Number) + */ + public Number getMaxPointWidth() { + return maxPointWidth; + } + + /** + * The maximum allowed pixel width for a column, translated to the height of + * a bar in a bar chart. This prevents the columns from becoming too wide + * when there is a small number of points in the chart. + *

+ * Defaults to: null + */ + public void setMaxPointWidth(Number maxPointWidth) { + this.maxPointWidth = maxPointWidth; + } + + /** + * @see #setMinPointLength(Number) + */ + public Number getMinPointLength() { + return minPointLength; + } + + /** + * The minimal height for a column or width for a bar. By default, 0 values + * are not shown. To visualize a 0 (or close to zero) point, set the minimal + * point length to a pixel value like 3. In stacked column charts, + * minPointLength might not be respected for tightly packed values. + *

+ * Defaults to: 0 + */ + public void setMinPointLength(Number minPointLength) { + this.minPointLength = minPointLength; + } + + public String getPointDescriptionFormatter() { + return _fn_pointDescriptionFormatter; + } + + public void setPointDescriptionFormatter( + String _fn_pointDescriptionFormatter) { + this._fn_pointDescriptionFormatter = _fn_pointDescriptionFormatter; + } + + /** + * @see #setPointPadding(Number) + */ + public Number getPointPadding() { + return pointPadding; + } + + /** + * Padding between each column or bar, in x axis units. + *

+ * Defaults to: 0.1 + */ + public void setPointPadding(Number pointPadding) { + this.pointPadding = pointPadding; + } + + /** + * @see #setPointWidth(Number) + */ + public Number getPointWidth() { + return pointWidth; + } + + /** + * A pixel value specifying a fixed width for each column or bar. When + * null, the width is calculated from the + * pointPadding and groupPadding. + */ + public void setPointWidth(Number pointWidth) { + this.pointWidth = pointWidth; + } + + /** + * @see #setSelected(Boolean) + */ + public Boolean getSelected() { + return selected; + } + + /** + * Whether to select the series initially. If showCheckbox is + * true, the checkbox next to the series name will be checked for a selected + * series. + *

+ * Defaults to: false + */ + public void setSelected(Boolean selected) { + this.selected = selected; + } + + /** + * @see #setShadow(Boolean) + */ + public Boolean getShadow() { + return shadow; + } + + /** + * Whether to apply a drop shadow to the graph line. Since 2.3 the shadow + * can be an object configuration containing color, + * offsetX, offsetY, opacity and + * width. + *

+ * Defaults to: false + */ + public void setShadow(Boolean shadow) { + this.shadow = shadow; + } + + /** + * @see #setShowCheckbox(Boolean) + */ + public Boolean getShowCheckbox() { + return showCheckbox; + } + + /** + * If true, a checkbox is displayed next to the legend item to allow + * selecting the series. The state of the checkbox is determined by the + * selected option. + *

+ * Defaults to: false + */ + public void setShowCheckbox(Boolean showCheckbox) { + this.showCheckbox = showCheckbox; + } + + /** + * @see #setShowInLegend(Boolean) + */ + public Boolean getShowInLegend() { + return showInLegend; + } + + /** + * Whether to display this particular series or series type in the legend. + * The default value is true for standalone series, + * false for linked series. + *

+ * Defaults to: true + */ + public void setShowInLegend(Boolean showInLegend) { + this.showInLegend = showInLegend; + } + + /** + * @see #setSkipKeyboardNavigation(Boolean) + */ + public Boolean getSkipKeyboardNavigation() { + return skipKeyboardNavigation; + } + + /** + * If set to True, the accessibility module will skip past the + * points in this series for keyboard navigation. + */ + public void setSkipKeyboardNavigation(Boolean skipKeyboardNavigation) { + this.skipKeyboardNavigation = skipKeyboardNavigation; + } + + /** + * @see #setStates(States) + */ + public States getStates() { + if (states == null) { + states = new States(); + } + return states; + } + + /** + * A wrapper object for all the series options in specific states. + */ + public void setStates(States states) { + this.states = states; + } + + /** + * @see #setStickyTracking(Boolean) + */ + public Boolean getStickyTracking() { + return stickyTracking; + } + + /** + * Sticky tracking of mouse events. When true, the mouseOut + * event on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the mouseOut + * event on a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * stickyTracking is false and tooltip.shared is + * false, the tooltip will be hidden when moving the mouse between series. + * Defaults to true for line and area type series, but to false for columns, + * pies etc. + *

+ * Defaults to: true + */ + public void setStickyTracking(Boolean stickyTracking) { + this.stickyTracking = stickyTracking; + } + + /** + * @see #setTooltip(SeriesTooltip) + */ + public SeriesTooltip getTooltip() { + if (tooltip == null) { + tooltip = new SeriesTooltip(); + } + return tooltip; + } + + /** + * A configuration object for the tooltip rendering of each single series. + * Properties are inherited from tooltip, but only + * the following properties can be defined on a series level. + */ + public void setTooltip(SeriesTooltip tooltip) { + this.tooltip = tooltip; + } + + /** + * @see #setTurboThreshold(Number) + */ + public Number getTurboThreshold() { + return turboThreshold; + } + + /** + * When a series contains a data array that is longer than this, only one + * dimensional arrays of numbers, or two dimensional arrays with x and y + * values are allowed. Also, only the first point is tested, and the rest + * are assumed to be the same format. This saves expensive data checking and + * indexing in long series. Set it to 0 disable. + *

+ * Defaults to: 1000 + */ + public void setTurboThreshold(Number turboThreshold) { + this.turboThreshold = turboThreshold; + } + + /** + * @see #setVisible(Boolean) + */ + public Boolean getVisible() { + return visible; + } + + /** + * Set the initial visibility of the series. + *

+ * Defaults to: true + */ + public void setVisible(Boolean visible) { + this.visible = visible; + } + + /** + * @see #setCenterInCategory(Boolean) + */ + public Boolean getCenterInCategory() { + return centerInCategory; + } + + /** + * When true, the columns will center in the category, ignoring null or + * missing points. When false, space will be reserved for null or missing + * points. + *

+ * Defaults to false. + */ + public void setCenterInCategory(Boolean centerInCategory) { + this.centerInCategory = centerInCategory; + } + + /** + * @see #setClip(Boolean) + */ + public Boolean getClip() { + return clip; + } + + /** + * Disable this option to allow series rendering in the whole plotting area. + *

+ * Note: Clipping should be always enabled when zoomType is set + */ + public void setClip(Boolean clip) { + this.clip = clip; + } + + /** + * @see #setDashStyle(DashStyle) + */ + public DashStyle getDashStyle() { + return dashStyle; + } + + /** + * A name for the dash style to use for the graph. Applies only to series + * type having a graph, like line, spline, + * area and scatter in case it has a + * lineWidth. The value for the dashStyle include: + *

    + *
  • Solid
  • + *
  • ShortDash
  • + *
  • ShortDot
  • + *
  • ShortDashDot
  • + *
  • ShortDashDotDot
  • + *
  • Dot
  • + *
  • Dash
  • + *
  • LongDash
  • + *
  • DashDot
  • + *
  • LongDashDot
  • + *
  • LongDashDotDot
  • + *
+ *

+ * Defaults to: Solid + */ + public void setDashStyle(DashStyle dashStyle) { + this.dashStyle = dashStyle; + } + + /** + * @see #setOpacity(Number) + */ + public Number getOpacity() { + return opacity; + } + + /** + * Opacity of a series parts: line, fill (e.g. area) and dataLabels. + *

+ * Defaults to 1. + */ + public void setOpacity(Number opacity) { + this.opacity = opacity; + } + + /** + * @see #setPartialFill(PartialFill) + */ + public PartialFill getPartialFill() { + if (partialFill == null) { + partialFill = new PartialFill(); + } + return partialFill; + } + + /** + * Partial fill configuration for series points, typically used to visualize + * how much of a task is performed. + */ + public void setPartialFill(PartialFill partialFill) { + this.partialFill = partialFill; + } + + /** + * @see #setConnectors(SeriesConnectors) + */ + public SeriesConnectors getConnectors() { + return connectors; + } + + /** + * Override Pathfinder connector options for a series. Requires Highcharts + * Gantt to be loaded. + */ + public void setConnectors(SeriesConnectors connectors) { + this.connectors = connectors; + } + + /** + * See also {@link #setCustom(AbstractConfigurationObject)} + */ + public AbstractConfigurationObject getCustom() { + return custom; + } + + /** + * A reserved subspace to store options and values for customized + * functionality. Here you can add additional data for your own event + * callbacks and formatter callbacks. + */ + public void setCustom(AbstractConfigurationObject custom) { + this.custom = custom; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Scrollbar.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Scrollbar.java index e9813c0ebe9..0fe24ab1a44 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Scrollbar.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Scrollbar.java @@ -48,6 +48,7 @@ public class Scrollbar extends AbstractConfigurationObject { private Color trackBackgroundColor; private Color trackBorderColor; private Number trackBorderRadius; + private Number trackBorderWidth; private Number zIndex; private Number height; @@ -396,4 +397,18 @@ public Number getHeight() { public void setHeight(Number height) { this.height = height; } + + /** + * @see #setTrackBorderWidth(Number) + */ + public Number getTrackBorderWidth() { + return trackBorderWidth; + } + + /** + * The width of the border of the scrollbar track. Defaults to 1. + */ + public void setTrackBorderWidth(Number trackBorderWidth) { + this.trackBorderWidth = trackBorderWidth; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java new file mode 100644 index 00000000000..c539dc6cff2 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java @@ -0,0 +1,34 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +/** + * Animation of Gantt series connector + */ +@SuppressWarnings("unused") +public class SeriesConnectorAnimation extends AbstractConfigurationObject { + + private Boolean reversed; + + /** + * @see #setReversed(Boolean) + */ + public Boolean getReversed() { + return reversed; + } + + /** + * Defaults to true. + * + * @param reversed + */ + public void setReversed(Boolean reversed) { + this.reversed = reversed; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java new file mode 100644 index 00000000000..892a34ac84e --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java @@ -0,0 +1,27 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +/** + * A configuration object to override Pathfinder connector options for a series. + * Requires Highcharts Gantt. + */ +@SuppressWarnings("unused") +public class SeriesConnectors extends ConnectorStyle { + + private SeriesConnectorAnimation animation; + + public SeriesConnectorAnimation getAnimation() { + return animation; + } + + public void setAnimation(SeriesConnectorAnimation animation) { + this.animation = animation; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java index df17c4abffa..89846fa5ad9 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java @@ -26,6 +26,7 @@ */ public class XAxis extends Axis { + private Boolean alignTicks; private Boolean allowDecimals; private Color alternateGridColor; private Breaks[] breaks; @@ -33,10 +34,12 @@ public class XAxis extends Axis { private Number ceiling; private String className; private Crosshair crosshair; + private PlotLine currentDateIndicator; private DateTimeLabelFormats dateTimeLabelFormats; private String description; private Boolean endOnTick; private Number floor; + private AxisGrid grid; private Color gridLineColor; private DashStyle gridLineDashStyle; private Number gridLineWidth; @@ -46,6 +49,8 @@ public class XAxis extends Axis { private Color lineColor; private Number lineWidth; private Number linkedTo; + private Number margin; + private Number maxRange; private Number maxPadding; private Number minPadding; private Number minRange; @@ -57,9 +62,11 @@ public class XAxis extends Axis { private String minorTickInterval; private Number minorTickLength; private TickPosition minorTickPosition; + private Boolean minorTicks; private Number minorTickWidth; private Number offset; private Boolean opposite; + private Boolean panningEnabled; private ArrayList plotBands; private ArrayList plotLines; private Boolean reversed; @@ -1517,4 +1524,143 @@ public void setTitle(String title) { public void setLinkedTo(XAxis axis) { linkedTo = axis.getAxisIndex(); } + + /** + * @see #setCurrentDateIndicator(PlotLine) + */ + public PlotLine getCurrentDateIndicator() { + return currentDateIndicator; + } + + /** + * Show an indicator on the axis for the current date and time. + * + * @param currentDateIndicator + */ + public void setCurrentDateIndicator(Boolean currentDateIndicator) { + if (currentDateIndicator) { + this.currentDateIndicator = new PlotLine(); + } else { + this.currentDateIndicator = null; + } + } + + /** + * Show an indicator on the axis for the current date and time. + * + * @param currentDateIndicator + */ + public void setCurrentDateIndicator(PlotLine currentDateIndicator) { + this.currentDateIndicator = currentDateIndicator; + } + + /** + * @see #setGrid(AxisGrid) + */ + public AxisGrid getGrid() { + return grid; + } + + /** + * Set grid options for the axis labels. Relevant only for Highcharts Gantt. + */ + public void setGrid(AxisGrid grid) { + this.grid = grid; + } + + /** + * @see #setAlignTicks(Boolean) + */ + public Boolean getAlignTicks() { + return alignTicks; + } + + /** + * When using multiple axis, the ticks of two or more opposite axes will + * automatically be aligned by adding ticks to the axis or axes with the + * least ticks, as if tickAmount were specified. This can be prevented by + * setting alignTicks to false. If the grid lines look messy, it's a good + * idea to hide them for the secondary axis by setting gridLineWidth to 0. + * If startOnTick or endOnTick in an Axis options are set to false, then the + * alignTicks will be disabled for the Axis. Disabled for logarithmic axes. + * Defaults to true. + * + * @param alignTicks + */ + public void setAlignTicks(Boolean alignTicks) { + this.alignTicks = alignTicks; + } + + /** + * @see #setMargin(Number) + */ + public Number getMargin() { + return margin; + } + + /** + * If there are multiple axes on the same side of the chart, the pixel + * margin between the axes. Defaults to 0 on vertical axes, 15 on horizontal + * axes. + * + * @param margin + */ + public void setMargin(Number margin) { + this.margin = margin; + } + + /** + * @see #setMaxRange(Number) + */ + public Number getMaxRange() { + return maxRange; + } + + /** + * Maximum range which can be set using the navigator's handles. Opposite of + * {@link #setMinRange(Number)} + * + * @param maxRange + */ + public void setMaxRange(Number maxRange) { + this.maxRange = maxRange; + } + + /** + * @see #setPanningEnabled(Boolean) + */ + public Boolean getPanningEnabled() { + return panningEnabled; + } + + /** + * Whether to pan axis. If chart.panning is enabled, the option allows to + * disable panning on an individual axis. Defaults to true. + * + * @param panningEnabled + */ + public void setPanningEnabled(Boolean panningEnabled) { + this.panningEnabled = panningEnabled; + } + + /** + * @see #setMinorTicks(Boolean) + */ + public Boolean getMinorTicks() { + return minorTicks; + } + + /** + * Enable or disable minor ticks. Unless minorTickInterval is set, the tick + * interval is calculated as a fifth of the tickInterval. On a logarithmic + * axis, minor ticks are laid out based on a best guess, attempting to enter + * approximately 5 minor ticks between each major tick. Prior to v6.0.0, + * ticks were unabled in auto layout by setting minorTickInterval to "auto". + * Defaults to false. + * + * @param minorTicks + */ + public void setMinorTicks(Boolean minorTicks) { + this.minorTicks = minorTicks; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java index 2b42f2c1cdb..998b6a2229d 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java @@ -25,6 +25,7 @@ */ public class YAxis extends Axis { + private Boolean alignTicks; private Boolean allowDecimals; private Color alternateGridColor; private Number angle; @@ -37,6 +38,7 @@ public class YAxis extends Axis { private String description; private Boolean endOnTick; private Number floor; + private AxisGrid grid; private Color gridLineColor; private DashStyle gridLineDashStyle; private String gridLineInterpolation; @@ -47,8 +49,10 @@ public class YAxis extends Axis { private Color lineColor; private Number lineWidth; private Number linkedTo; + private Number margin; private Color maxColor; private Number maxPadding; + private Number maxRange; private Color minColor; private Number minPadding; private Number minRange; @@ -60,6 +64,7 @@ public class YAxis extends Axis { private String minorTickInterval; private Number minorTickLength; private TickPosition minorTickPosition; + private Boolean minorTicks; private Number minorTickWidth; private Number offset; private Boolean opposite; @@ -75,6 +80,7 @@ public class YAxis extends Axis { private StackLabels stackLabels; private Number startOfWeek; private Boolean startOnTick; + private Number staticScale; private Number tickAmount; private Color tickColor; private Number tickInterval; @@ -1686,4 +1692,117 @@ public void addStop(Stop stop) { public void removeStop(Stop stop) { this.stops.remove(stop); } + + /** + * @see #setGrid(AxisGrid) + */ + public AxisGrid getGrid() { + return grid; + } + + /** + * Set grid options for the axis labels. Relevant only for Highcharts Gantt. + */ + public void setGrid(AxisGrid grid) { + this.grid = grid; + } + + /** + * @see #setAlignTicks(Boolean) + */ + public Boolean getAlignTicks() { + return alignTicks; + } + + /** + * When using multiple axis, the ticks of two or more opposite axes will + * automatically be aligned by adding ticks to the axis or axes with the + * least ticks, as if tickAmount were specified. This can be prevented by + * setting alignTicks to false. If the grid lines look messy, it's a good + * idea to hide them for the secondary axis by setting gridLineWidth to 0. + * If startOnTick or endOnTick in an Axis options are set to false, then the + * alignTicks will be disabled for the Axis. Disabled for logarithmic axes. + * Defaults to true. + * + * @param alignTicks + */ + public void setAlignTicks(Boolean alignTicks) { + this.alignTicks = alignTicks; + } + + /** + * @see #setMargin(Number) + */ + public Number getMargin() { + return margin; + } + + /** + * If there are multiple axes on the same side of the chart, the pixel + * margin between the axes. Defaults to 0 on vertical axes, 15 on horizontal + * axes. + * + * @param margin + */ + public void setMargin(Number margin) { + this.margin = margin; + } + + /** + * @see #setMaxRange(Number) + */ + public Number getMaxRange() { + return maxRange; + } + + /** + * Maximum range which can be set using the navigator's handles. Opposite of + * {@link #setMinRange(Number)} + * + * @param maxRange + */ + public void setMaxRange(Number maxRange) { + this.maxRange = maxRange; + } + + /** + * @see #setMinorTicks(Boolean) + */ + public Boolean getMinorTicks() { + return minorTicks; + } + + /** + * Enable or disable minor ticks. Unless minorTickInterval is set, the tick + * interval is calculated as a fifth of the tickInterval. On a logarithmic + * axis, minor ticks are laid out based on a best guess, attempting to enter + * approximately 5 minor ticks between each major tick. Prior to v6.0.0, + * ticks were unabled in auto layout by setting minorTickInterval to "auto". + * Defaults to false. + * + * @param minorTicks + */ + public void setMinorTicks(Boolean minorTicks) { + this.minorTicks = minorTicks; + } + + /** + * @see #setStaticScale(Number) + */ + public Number getStaticScale() { + return staticScale; + } + + /** + * For vertical axes only. Setting the static scale ensures that each tick + * unit is translated into a fixed pixel height. For example, setting the + * static scale to 24 results in each Y axis category taking up 24 pixels, + * and the height of the chart adjusts. Adding or removing items will make + * the chart resize. Defaults to 50. + * + * @param staticScale + */ + public void setStaticScale(Number staticScale) { + this.staticScale = staticScale; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/style/PlotOptionsStyle.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/style/PlotOptionsStyle.java index d786711ffd7..170a3109e15 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/style/PlotOptionsStyle.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/style/PlotOptionsStyle.java @@ -24,6 +24,7 @@ import com.vaadin.flow.component.charts.model.PlotOptionsErrorbar; import com.vaadin.flow.component.charts.model.PlotOptionsFlags; import com.vaadin.flow.component.charts.model.PlotOptionsFunnel; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; import com.vaadin.flow.component.charts.model.PlotOptionsGauge; import com.vaadin.flow.component.charts.model.PlotOptionsHeatmap; import com.vaadin.flow.component.charts.model.PlotOptionsLine; @@ -76,6 +77,7 @@ public class PlotOptionsStyle extends AbstractConfigurationObject { private PlotOptionsTreemap treemap = new PlotOptionsTreemap(); private PlotOptionsWaterfall waterfall = new PlotOptionsWaterfall(); private PlotOptionsXrange xrange = new PlotOptionsXrange(); + private PlotOptionsGantt gantt = new PlotOptionsGantt(); /** * @see #setBar(PlotOptionsBar) @@ -543,4 +545,20 @@ public void setXrange(PlotOptionsXrange xrange) { this.xrange = xrange; } + /** + * @see #setGantt(PlotOptionsGantt) + */ + public PlotOptionsGantt getGantt() { + return gantt; + } + + /** + * Sets the style options for {@link ChartType#GANTT} charts + * + * @param gantt + */ + public void setGantt(PlotOptionsGantt gantt) { + this.gantt = gantt; + } + } From 0bcf1b1fb43b692cb3af5c28d776d402584fe2a5 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Wed, 8 Jan 2025 16:35:09 +0100 Subject: [PATCH 04/10] Revert "feat: add Java API to set Chart mode property" This reverts commit e57591ef5e71a3a90a610749cf67c6fe3a577714. --- .../examples/timeline/AreaSplineRange.java | 3 +- .../charts/examples/timeline/Candlestick.java | 3 +- .../charts/examples/timeline/ColumnRange.java | 3 +- .../timeline/CompareMultipleSeries.java | 3 +- .../charts/examples/timeline/OHLC.java | 3 +- .../charts/examples/timeline/Spline.java | 3 +- .../vaadin/flow/component/charts/Chart.java | 67 +++++----------- .../flow/component/charts/ChartMode.java | 79 ------------------- 8 files changed, 25 insertions(+), 139 deletions(-) delete mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java index 9afd43804d2..8cbb7a98d6a 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/AreaSplineRange.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -37,7 +36,7 @@ public void initDemo() { } configuration.setSeries(dataSeries); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java index c96d43b69e8..e7726073011 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -53,7 +52,7 @@ public void initDemo() { rangeSelector.setSelected(4); configuration.setRangeSelector(rangeSelector); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java index d7f5c503d7e..a1fe1c894b7 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/ColumnRange.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -38,7 +37,7 @@ public void initDemo() { rangeSelector.setSelected(2); configuration.setRangeSelector(rangeSelector); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java index 32043b6754d..d3279b32c62 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/CompareMultipleSeries.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.Compare; @@ -30,7 +29,7 @@ public class CompareMultipleSeries extends AbstractChartExample { @Override public void initDemo() { final Chart chart = new Chart(); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); Configuration configuration = chart.getConfiguration(); configuration.getTitle().setText("AAPL Stock Price"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java index 63de5b381a5..3d0662e6679 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/OHLC.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -53,7 +52,7 @@ public void initDemo() { rangeSelector.setSelected(1); configuration.setRangeSelector(rangeSelector); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); add(chart); } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java index 0aabf190119..f8d4d5d5e5d 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Spline.java @@ -9,7 +9,6 @@ package com.vaadin.flow.component.charts.examples.timeline; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.timeline.util.StockPrices; import com.vaadin.flow.component.charts.model.ChartType; @@ -23,7 +22,7 @@ public class Spline extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.SPLINE); - chart.setMode(ChartMode.TIMELINE); + chart.setTimeline(true); Configuration configuration = chart.getConfiguration(); configuration.getTitle().setText("AAPL Stock Price"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java index 633f18f8a65..6d634f7ffb7 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java @@ -60,6 +60,7 @@ import com.vaadin.flow.component.charts.model.DataSeriesItem; import com.vaadin.flow.component.charts.model.DrilldownCallback; import com.vaadin.flow.component.charts.model.DrilldownCallback.DrilldownDetails; +import com.vaadin.flow.component.charts.model.PlotOptionsTimeline; import com.vaadin.flow.component.charts.model.Series; import com.vaadin.flow.component.charts.util.ChartSerialization; import com.vaadin.flow.component.dependency.JsModule; @@ -104,9 +105,6 @@ public class Chart extends Component implements HasStyle, HasSize, HasTheme { ChartType.PIE, ChartType.GAUGE, ChartType.SOLIDGAUGE, ChartType.PYRAMID, ChartType.FUNNEL, ChartType.ORGANIZATION); - private final static List GANTT_SUPPORTED = Arrays - .asList(ChartType.GANTT, ChartType.XRANGE); - private DrillCallbackHandler drillCallbackHandler; private DrilldownCallback drilldownCallback; @@ -194,7 +192,7 @@ public void drawChart() { * @see #getConfiguration() */ public void drawChart(boolean resetConfiguration) { - validateChartMode(); + validateTimelineAndConfiguration(); final JsonObject configurationNode = getJsonFactory() .parse(ChartSerialization.toJSON(configuration)); @@ -203,49 +201,32 @@ public void drawChart(boolean resetConfiguration) { resetConfiguration); } - private void validateChartMode() { - validateTimelineAndConfiguration(); - validateGanttAndConfiguration(); - } - /** - * Determines if the chart is in timeline mode or in normal mode. For more - * information see {@link ChartMode#TIMELINE}. + * Determines if the chart is in timeline mode or in normal mode. The + * following chart types do not support timeline mode: + *

    + *
  • ChartType.PIE
  • + *
  • ChartType.GAUGE
  • + *
  • ChartType.SOLIDGAUGE
  • + *
  • ChartType.PYRAMID
  • + *
  • ChartType.FUNNEL
  • + *
  • ChartType.ORGANIZATION
  • + *
+ * Enabling timeline mode in these unsupported chart types results in an + * IllegalArgumentException + *

+ * Note: for Timeline chart type see {@link ChartType.TIMELINE} and + * {@link PlotOptionsTimeline}. * * @param timeline * true for timeline chart - * @deprecated Use {@link #setMode(ChartMode)} instead */ public void setTimeline(Boolean timeline) { - setMode(timeline ? ChartMode.TIMELINE : ChartMode.NORMAL); - } - - /** - * The chart mode configures how data is presented in the chart. You can - * specify whether the chart will be rendered as a normal chart, a timeline - * chart or a gantt chart. - *

- * For more information on modes and their limitations see - * {@link ChartMode}. - * - * @param mode - * the mode to set - */ - public void setMode(ChartMode mode) { - getElement().setProperty("mode", - mode == null ? null : mode.getModeName()); - } - - /** - * @see #setMode(ChartMode) - */ - public ChartMode getMode() { - final String mode = getElement().getProperty("mode"); - return mode == null ? ChartMode.NORMAL : ChartMode.getForName(mode); + getElement().setProperty("timeline", timeline); } private void validateTimelineAndConfiguration() { - if (getMode().equals(ChartMode.TIMELINE)) { + if (getElement().getProperty("timeline", false)) { final ChartType type = getConfiguration().getChart().getType(); if (TIMELINE_NOT_SUPPORTED.contains(type)) { throw new IllegalArgumentException( @@ -255,16 +236,6 @@ private void validateTimelineAndConfiguration() { } } - private void validateGanttAndConfiguration() { - if (getMode().equals(ChartMode.GANTT)) { - final ChartType type = getConfiguration().getChart().getType(); - if (!GANTT_SUPPORTED.contains(type)) { - throw new IllegalArgumentException( - "Gantt is not supported for chart type '" + type + "'"); - } - } - } - /** * The series or point visibility is toggled by default if user clicks the * legend item that corresponds to the series or point. Calling diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java deleted file mode 100644 index d2cd8b5d66f..00000000000 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/ChartMode.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright 2000-2024 Vaadin Ltd. - * - * This program is available under Vaadin Commercial License and Service Terms. - * - * See {@literal } for the full - * license. - */ -package com.vaadin.flow.component.charts; - -import com.vaadin.flow.component.charts.model.ChartType; -import com.vaadin.flow.component.charts.model.PlotOptionsTimeline; - -/** - * The ChartMode configures how the data is presented in the chart. - */ -public enum ChartMode { - - /** - * Normal chart mode, for any series type (see {@link ChartType}). - */ - NORMAL("normal"), - - /** - * Chart timeline mode: the chart allows selecting different time ranges for - * which to display the chart data, as well as navigating between such - * ranges. The following chart types do not support timeline mode: - *

    - *
  • ChartType.PIE
  • - *
  • ChartType.GAUGE
  • - *
  • ChartType.SOLIDGAUGE
  • - *
  • ChartType.PYRAMID
  • - *
  • ChartType.FUNNEL
  • - *
  • ChartType.ORGANIZATION
  • - *
- * Enabling timeline mode in these unsupported chart types results in an - * IllegalArgumentException - *

- * Note: for Timeline chart type see {@link ChartType#TIMELINE} and - * {@link PlotOptionsTimeline}. - */ - TIMELINE("timeline"), - - /** - * Gantt chart mode: the chart series data will be presented as a Gantt - * chart. Only the following chart series types are supported while in Gantt - * chart mode: - *

    - *
  • ChartType.GANTT
  • - *
  • ChartType.XRANGE
  • - *
- * Enabling Gantt chart mode with unsupported chart types results in an - * IllegalArgumentException - *

- * Note: for Gantt chart type see - * {@link com.vaadin.flow.component.charts.model.ChartType#GANTT} and - * {@link com.vaadin.flow.component.charts.model.PlotOptionsGantt}. - */ - GANTT("gantt"); - - private final String mode; - - ChartMode(String mode) { - this.mode = mode; - } - - public String getModeName() { - return mode; - } - - public static ChartMode getForName(String name) { - for (ChartMode mode : values()) { - if (mode.getModeName().equals(name)) { - return mode; - } - } - return ChartMode.NORMAL; - } -} From 8673a54df6645108da61cce734bc7facdac3d06f Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Wed, 8 Jan 2025 17:13:29 +0100 Subject: [PATCH 05/10] feat: make "timeline" and "gantt chart type" an invalid combination --- .../src/main/java/com/vaadin/flow/component/charts/Chart.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java index 6d634f7ffb7..1ba9d933659 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java @@ -103,7 +103,8 @@ public class Chart extends Component implements HasStyle, HasSize, HasTheme { private final static List TIMELINE_NOT_SUPPORTED = Arrays.asList( ChartType.PIE, ChartType.GAUGE, ChartType.SOLIDGAUGE, - ChartType.PYRAMID, ChartType.FUNNEL, ChartType.ORGANIZATION); + ChartType.PYRAMID, ChartType.FUNNEL, ChartType.ORGANIZATION, + ChartType.GANTT); private DrillCallbackHandler drillCallbackHandler; @@ -211,6 +212,7 @@ public void drawChart(boolean resetConfiguration) { *

  • ChartType.PYRAMID
  • *
  • ChartType.FUNNEL
  • *
  • ChartType.ORGANIZATION
  • + *
  • ChartType.GANTT
  • * * Enabling timeline mode in these unsupported chart types results in an * IllegalArgumentException From 582e1aa83c58d998596d7b35c5e9c352447364f1 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Wed, 8 Jan 2025 18:03:29 +0100 Subject: [PATCH 06/10] fix: fix compilation errors after chart mode has been removed --- .../examples/gantt/GanttCustomDataLabels.java | 4 +- .../examples/gantt/GanttCustomXAxis.java | 4 +- .../examples/gantt/GanttLeftAxisAsTable.java | 4 +- .../gantt/GanttProcessManagement.java | 4 +- .../gantt/GanttProgressIndicator.java | 4 +- .../gantt/GanttResourceManagement.java | 4 +- .../gantt/GanttUsingXRangeSeries.java | 72 ------------------- .../examples/gantt/GanttWithNavigation.java | 7 +- .../flow/component/charts/model/AxisGrid.java | 2 +- .../charts/model/ChartConnectors.java | 2 +- .../component/charts/model/Completed.java | 2 +- .../component/charts/model/Configuration.java | 2 - .../charts/model/ConnectorStyle.java | 2 +- .../component/charts/model/GanttSeries.java | 2 +- .../charts/model/GanttSeriesItem.java | 2 +- .../model/GanttSeriesItemDependency.java | 2 +- .../charts/model/PathfinderType.java | 2 +- .../charts/model/PlotOptionsGantt.java | 2 +- .../model/SeriesConnectorAnimation.java | 2 +- .../charts/model/SeriesConnectors.java | 2 +- 20 files changed, 18 insertions(+), 109 deletions(-) delete mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomDataLabels.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomDataLabels.java index 1e63882c364..8df62021cd3 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomDataLabels.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomDataLabels.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -13,7 +13,6 @@ import java.util.ArrayList; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; import com.vaadin.flow.component.charts.model.ChartType; @@ -36,7 +35,6 @@ public class GanttCustomDataLabels extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java index ba03233a3c9..33f5ef78d15 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttCustomXAxis.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -12,7 +12,6 @@ import java.time.temporal.ChronoUnit; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.SkipFromDemo; import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; @@ -41,7 +40,6 @@ public class GanttCustomXAxis extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); configuration.getChart().setHeight("330"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java index f8d11ce331a..3a05f946675 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttLeftAxisAsTable.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -13,7 +13,6 @@ import java.util.List; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.SkipFromDemo; import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; @@ -38,7 +37,6 @@ public class GanttLeftAxisAsTable extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); configuration.setTitle("Gantt Chart - Left Axis as Table"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java index b3502e3a6ce..9c33bf45e7a 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProcessManagement.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -12,7 +12,6 @@ import java.time.temporal.ChronoUnit; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; import com.vaadin.flow.component.charts.model.ChartConnectors; @@ -37,7 +36,6 @@ public class GanttProcessManagement extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); configuration.setTitle("Gantt Project Management"); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java index b6143f24b64..967646bac5e 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttProgressIndicator.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -11,7 +11,6 @@ import java.time.Instant; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.SkipFromDemo; import com.vaadin.flow.component.charts.model.ChartType; @@ -29,7 +28,6 @@ public class GanttProgressIndicator extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java index 8174a9d4018..0af21efa829 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttResourceManagement.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -14,7 +14,6 @@ import java.util.List; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.examples.SkipFromDemo; import com.vaadin.flow.component.charts.model.AbstractConfigurationObject; @@ -34,7 +33,6 @@ public class GanttResourceManagement extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); var rentalData = getRentalData(); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java deleted file mode 100644 index c0975bbcfdc..00000000000 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttUsingXRangeSeries.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2000-2024 Vaadin Ltd. - * - * This program is available under Vaadin Commercial License and Service Terms. - * - * See {@literal } for the full - * license. - */ -package com.vaadin.flow.component.charts.examples.gantt; - -import java.time.Instant; - -import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; -import com.vaadin.flow.component.charts.examples.AbstractChartExample; -import com.vaadin.flow.component.charts.examples.SkipFromDemo; -import com.vaadin.flow.component.charts.model.ChartType; -import com.vaadin.flow.component.charts.model.Configuration; -import com.vaadin.flow.component.charts.model.DataSeries; -import com.vaadin.flow.component.charts.model.DataSeriesItemXrange; -import com.vaadin.flow.component.charts.model.PlotOptionsXrange; -import com.vaadin.flow.component.charts.model.XAxis; -import com.vaadin.flow.component.charts.model.YAxis; - -@SuppressWarnings("unused") -@SkipFromDemo -public class GanttUsingXRangeSeries extends AbstractChartExample { - @Override - public void initDemo() { - Chart chart = new Chart(ChartType.XRANGE); - chart.setMode(ChartMode.GANTT); - - final Configuration configuration = chart.getConfiguration(); - - configuration.setTitle("Gantt Chart using XRANGE series"); - - XAxis xAxis = configuration.getxAxis(); - xAxis.setMin(Instant.parse("2014-10-17T00:00:00Z")); - xAxis.setMax(Instant.parse("2014-10-30T00:00:00Z")); - - YAxis yAxis = configuration.getyAxis(); - yAxis.setCategories("Start prototype", "Test prototype", "Develop", - "Run acceptance tests"); - - PlotOptionsXrange plotOptionsXrange = new PlotOptionsXrange(); - configuration.setPlotOptions(plotOptionsXrange); - - DataSeries series = new DataSeries(); - series.setName("Project 1"); - final DataSeriesItemXrange startPrototype = new DataSeriesItemXrange( - Instant.parse("2014-10-18T00:00:00Z"), - Instant.parse("2014-10-25T00:00:00Z"), 0); - series.add(startPrototype); - - series.add( - new DataSeriesItemXrange(Instant.parse("2014-10-27T00:00:00Z"), - Instant.parse("2014-10-29T00:00:00Z"), 1)); - - final DataSeriesItemXrange develop = new DataSeriesItemXrange( - Instant.parse("2014-10-20T00:00:00Z"), - Instant.parse("2014-10-25T00:00:00Z"), 2); - series.add(develop); - - series.add( - new DataSeriesItemXrange(Instant.parse("2014-10-23T00:00:00Z"), - Instant.parse("2014-10-26T00:00:00Z"), 3)); - - configuration.addSeries(series); - - add(chart); - } -} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java index 74e8bdc9ee8..b6baa6196e7 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttWithNavigation.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * @@ -11,7 +11,6 @@ import java.time.Instant; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.examples.AbstractChartExample; import com.vaadin.flow.component.charts.model.ChartType; import com.vaadin.flow.component.charts.model.Completed; @@ -28,7 +27,6 @@ public class GanttWithNavigation extends AbstractChartExample { @Override public void initDemo() { Chart chart = new Chart(ChartType.GANTT); - chart.setMode(ChartMode.GANTT); final Configuration configuration = chart.getConfiguration(); @@ -81,9 +79,6 @@ private GanttSeries createProjectManagementSeries() { private void configureNavigator(Configuration configuration) { final Navigator navigator = configuration.getNavigator(); navigator.setEnabled(true); - final PlotOptionsGantt navigatorPlotOptions = new PlotOptionsGantt(); - navigatorPlotOptions.setPointPadding(0.2); - navigator.setSeries(navigatorPlotOptions); final YAxis navigatorYAxis = navigator.getYAxis(); navigatorYAxis.setMin(0); navigatorYAxis.setMax(3); diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java index fb13635604e..3e04d3a16bb 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AxisGrid.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java index 79a58d68e99..422da30bdae 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ChartConnectors.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java index 83d5ec77d44..4c59b4698ed 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Completed.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java index 7347fa1a41a..066c61da637 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Configuration.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.vaadin.flow.component.charts.Chart; -import com.vaadin.flow.component.charts.ChartMode; import com.vaadin.flow.component.charts.events.internal.AxisRescaledEvent; import com.vaadin.flow.component.charts.events.internal.ConfigurationChangeListener; import com.vaadin.flow.component.charts.events.internal.DataAddedEvent; @@ -690,7 +689,6 @@ public void addPane(Pane pane) { * Set settings for range selector. *

    * This is only valid if the chart is configured to use timeline mode. See - * {@link com.vaadin.flow.component.charts.Chart#setMode(ChartMode)}} * * @param rangeSelector * @see RangeSelector diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java index c7e549c34f0..a36b1b4e2fe 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/ConnectorStyle.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java index 8d9f4663016..044007facc4 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeries.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java index bf73b5da0ff..aa23ba8d21a 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItem.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java index 21449ef5fa9..edee1931219 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GanttSeriesItemDependency.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java index 145fd7a8a70..a018235295f 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java index 15610cf114b..d60d1441b3f 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java index c539dc6cff2..f1b899ead90 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectorAnimation.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java index 892a34ac84e..900d7d10a09 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/SeriesConnectors.java @@ -1,5 +1,5 @@ /** - * Copyright 2000-2024 Vaadin Ltd. + * Copyright 2000-2025 Vaadin Ltd. * * This program is available under Vaadin Commercial License and Service Terms. * From f1bb20cf1d47961ca20833a44cc7a2cece35fec6 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Thu, 9 Jan 2025 08:19:51 +0100 Subject: [PATCH 07/10] chore: remove unused image --- .../frontend/images/avatar1.png | Bin 31828 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/frontend/images/avatar1.png deleted file mode 100644 index 2ea2f7ac739d1abf5159382c25d55678c94bc710..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31828 zcmeEt^Iww7G`Ii&5GX0iYXblj0saWUvA`!2McU2a zABc;#f*epXK(__}NI*$m_MwOAW*T;qZpZ1h?eS4XLujTp*+;m2b{@wYOC?K^$Tz&F zPj55B!-6KW-%JV)Pr|~mFv>evYo6SGBS>*u7Q#8R3Rl)a7#_`eKcBz$b+2RbQS2f#=F={Wc-(+~m#+VluO{_Qy#fXc-BuPOh(>;HS!?TcE- zyNDVjd_9%9#jP@YHR1{Rt1gxwE7e9_H@3~xb6+=ON=+>VEn_Kn7uH>0tzvUC)RccQ zpdoXr0vCcpE@OCY0Q5AbOxV!N__OcPo$^kiXtHDA%M z%98efhLKheba{Yl;sl)kg;GH&6hs$SjG8J8=N$~!l_QKZNG1fj%n6_cH0(V5q30Z+ zh+6ueRfGY<+JGjNE@D3m{Q_KBog#sl9GS`xAb=~`m7o`bStIG%6QZPvN(B32QeiCB~wwTQV zU(=;{@VsvX-yWq@RKb(X^KaS9Lgc`W1LZJBK~n7mkm*4>oT{1J78cNjX$r7~ee46C zHhat=2La<3(pOHV{?R36>-eCJ1Kq-UJ&JxfT?F2a#-naf78e1Q80e}p{2hKEa}a1J z=SU#3SPxh*cf;!6CyKf0@>^qY-OrxhJ4hu5#GEJ$%=ZBtzqo**KurK(lBYogD&j7@ z3Q(LXlcqoi9*UzdEV%$QLYP0a7m5iGQiSrws-Oeqd*t$Rz}+lx-$sns5P}Zqo+9SI zgAVi%mz5s}pO-y&=|L_JNqvD}B_;`m#KZ_Zg(v5O2IV-nCGp^9ZXi{1+M`L4Os}I5 zOpIVpUbzP8%7O;LQ>c2rLgf|HQGul@prL$I0!j}s%S@Q8#uvk=kxcqch+@H;**W-X zk3)u`)kQ+1IAG=6YZW z5J#yukA`ET6w{hcj?L6D|)rb0%kZIy%~*5Dk`+5IP=60wLx!*t1N8ye|0enGGEs z;6Rd*!aW zxB&CRo%jANDGV$12<0xKxC=2NBk-U0RQIB9Zh-gxiSXslbh#i{1MC9 z;B#=T7idFT0+h1^@Nr!=0fgV%G9%FbF>0qW-$#h0g+;41RkD^K9o5Hy#A)E9x#EUA z?Ic63v?jeyBEWRU%_Q|RDpLkq==MrZ^8amr9S0D)z|0*%0lE@D5bT+V0fOaw+;58InXeF8YIqC;?i!RAEJOLkF zrs%<5hbbk-Ib%==$6dgD#QeDRN)SM9W>~4{hf-P@a>=Ah8bDBi0dbBaBM`(boImoS zXl!;HdOHdw@G-dE%y55SMiB!a~PL`pP|sz85E#gDETiw}!zNYXCgzm&EYxh1NHQT`AU@K=jMr z7`8e~3{-bKe^z!!mQvRDfQ3w;HA|Tc0?rwNXUz38FI|eO2gLlejT>Ez|5Jxm7Y)Gk zN7$a1P1b|kCKMlc5!8yhTLxw|t;$N+GY}~;u~UQkceo2uf$yG@@_}pIi8GcPnd%+G zZ5B#_yGYjJ2_N;>0>wWdcRhKP>g{wReuN7Y|5S%vbpe1|Xfv51C+lPQZ9}O*F&NL# z@t}{;Qqo#FmP}3PW3D$7J7lN{E}{AHsI1Zj9lCpk{aUVesx&F0A%Tl zV-J3q$8^o+{Kz`$!Yhi2>@CsQ}JC!x)_uwlO84dJ~RH?vB7| z8{=C{JlY;BeqT#}h0oobpjD&(dZ4jJ|0QF-$|#lOW*+0Hfb8#f?V6JdzpuP34i-2xIj z7MR!}^@wpYSdCE8u*t1b0G?c7EnBoIZGfzYJt_#o=EA&rjqyKUI~Sp`<1k-_O7iZ+ z#9@SR7IPB1GJ&lrz}ALB*0QOS^<^m6_YI>kqK72*Rt7p$pzYZWJf;vt#pB*Zv0)zp zLnrLd-|>hhJIiXsoH9p@F7F=^qQNyv(HXoI5cF$isG8WLyT^|&&@ITX7=NRRa!MGG zTii4tqXiAeanz~hS%8?p?ZRQk)Z^>?1uucXyyS8LK37H_vU!^l!`6H16m&UNC8(jG zGIejQyD+5uw}|^Mvd+z8ckZ|vuU=9-NPOdfpN+eo0Zzi}KbsPyfW<`r`XkDEB8i}{ zRX$`3kQ?Kgx+~>>GBlz+R-2bi-{S<1dqkC3-Bn(_uRSOqB-8p<(^odQFp=^5kU?fJJR+FzC^`iiIQI(qb<#N*OCs7 z&M|IYe8m_XuVHpi6G{KnvW#<TY8CuHPT%2<~d+{;W3JqiHQ1c9pjOvjOQA40k=~(t$xGniJ+_x z+7Ly-pnxJ?n&}{p##g4sh`V>!3>;tnD%Bqk=C8QJ@o%xm zIp$b|A3IJD`;-ZAk~B136tVOq4eQDk0k%vUPv%%YJ@ z-x`=H9>6DrI9oQ{l_+R3@ml5X|GC3eAEb1Wj(M(DCDxWSD%V?o^Mv(b@P%VnW2;jbXz4O9*}fpyPMu!Rw97s#^gMVkHfm| z?J+W8cAMuS!Hu|0m>+aWU*1&@ZEfbPj()=#)P4UpogppA?++dxDQmLb@J}Xo_L~i@ zcV*ElM|^OY<9@LFi6Pm5I>kmUaHkg>84P}F-U`WV>Al>+xT{L{9Fw^cIn;6M2MncU zJqnM^3O<8LMF#Iv(jKw|nc0CF!9D%)A8ASq>ygc`tkq7WPW2?1`Lq1F zSocAr;*+RvzP%rY_J(}Qlt#q)?|o$F9pxj}e^jU&_UCg+ji7V-st%0;1_|S#Q!cxS zf#G<|9jHO295_wn1;R(-wVZq54xEE&8^7nSo~go+qj`(7g3QuSv+mHY%H@GF#6(O& zQ@bEni^2D#@{POngEK5>F^iJH`DwH7pg#BhBE2{BjdOcxMmrt1I;Y$xOOJCUlJryw zuX+kaDOap*-?cQ4qt(C1l>X3#QDd*XN95-`8Ev=>r9NoF=Q>Ur>bu)zOh08BhFDV4 z)E*pX5jxAW^)G@O0S2N+jPl;l4O0jH9}#W?N@_0LcAI2 z6mQdSs+ovCe=^muneBhy6wGiuIQv?+W;<5{d6gziXx}!?dG%+XXDW!C50v*M+_$A} z(+fVWE_4HX&~`P~o-jAp&-=Sj&ZR$^j^PmWK110lm@YOV4;*LS9hf$4AQHFIZyzCjWY{M9 zTA_DI^cT$x<%7}6!AA{gFF6vZ?XAglLjPpYuE`B4dU*)#etq?(E>Sm#&z6?Ds2of( zTaC0jk8DP}uD(eBlx$$rSr@YWTR_(%NvRL{?4*;upov%F9VIn-R(1XH-|%hkV*jR-qFZ$BTjd`c>aZS5ZdYO;bLuX?mr(SRnl;kPfzUW`^HC4-wK-{2qD|}&SE}5@yEISqU<8*<;K5~4 ziGt<1fBakLsq%dt3L_yfW>Hi}M30@{e!w*N724~sDdctZN#U^FD!o(Z>nIfP&rj`) z9DZr^D)~sNL3x)z^m*|Q|BZm$9^1hmUA=UhiXYJ58wlyYV}uHnIz^@jtWvGTpe#>i zw?;8NLV`WTAO6MxvL3L-b@toM`pni;y*!%!>0(+l(dlW1v`6GA=mYgfosw?Fuld#W+RwRo*8|$PN_5>;f6E+6HD!nDE$hf z0XJ94U3){aL4tvMWE0)1aJ?0zM5o|T;>m%z2vHKs)Z~?%G@S$(g8^#e)fZcD6x!KzH<~X8!X0M0U4tfdv(mk)5HZ zoj0rd`{2%IU1V&Aqq^tTeA3R5kbMyvlIpvVRbX&u*lj4C$lm(Ngz5(V_zH6G@_3)E z_GtHG38NYLYg4;NRD*v503yaImCQoVUD~|2ZE*%$Q`ier(fdSPL2q5D>Iu(CLyGY) zr}LA0>}Xk5&IQcY!=;-RBT0jUR`TCqTTO!fFfYyL3a{LFsWF+dJHKz(_FZQTBQ3z` zN;cQYU*q0{pPD~FZ12kRI7k$wnGtfTJ>y;XOH{3hv+G>=Y_fna7?Uu&7w~uHoJK z{lhb}uk9$Pr)O!C&;(l=`dbQv(PTyf5J8320iSFK}Arc>PU)o zK^@!DC9E`;7nc{d!l&w=?H9w2Wh7~2|4=LXf|Kw4 zND>GA*I~aQrj!KE1F!XB&h76~&yzN}2xqS|*;Fhe!6Lf;6~H`c=Qu7NdeOZW8Q&fV+@qjXkrtUon7xf^Ttc#JRIs3#?d_1aVm5G)oDwXa*byh6uFAK+92%Z zsl5VLPxkvb=!M)B(S$YbI^!?a*XE~sYP=ROWL2K^rGdS^K}Ns@93bA@YyI6}^ej8u zahFG><^oX))h|q{d9jLm@?B+Y^~OE)ZNwAlbNC4s+;XDAKrbMKwHv%>jY zt|8^*7Iy%DErNcB2=&RB1L-m_CUkaxWD*ubJyn#piGvXKevWe|i2&7w)(-nlVz7yo#bCbDHZ-h`Ym?ZY#>_(@2nFd50coRaG_#1_;g%>`8`yG ziqGDv^tPhmf1Z*OfU5)xn?$W~HhKH%gHV<3d6)nUuqeY~C-)pk1?e&v#tDmF;#M45ShuNt?9}Z)9^6|O&9~qKLYs@?oprMDSiR^gzEY{kQ zUTwS==8IM*oz3})ga3SF%Zh5jJZj*BH$*;fFh&uZb3eNTObP>D?Vhtw1o~#b7NG*C zR14+tWT)j z3R^jVz)qS>$BEh0y{0DVtv{tN3Z8z2AYOgM65AObcL;L|p@vqmPvU6LJl^L1 z{*%_>l1%F-j99N`CK~6&)8n|Z5>XZO;b8drm|MKXuQ=Vk1}k(`qTvG!Bl5KY@@lxc zdb|-st7aP;khAVw&FTp@*qM!3(6FSyM%ifaf>KE^-9 zwi0`ouPp!s;%3>1-p?)3dR4or+VF)d*jNGsuuy$174=kArvJGN)`xrvSR=*QeO6UW|H0RG) z@K8f}=UzIJXQy#1H~BHevo9`SQ`kYNPhGB3ZOIl|#N3)dt!8!;f zmFtTp1O5;0vc}}e^e;)S+v>6@`ApSb^8oUc;_0T8K6UCi>6|*$05Z%rTtuwsN7W^5 z?#9u@{`5CV34+I(8JF)3VdqDz0cS@%3{nqbQs=~r^I44!a*V!58+yT*r^EF|XE++p zl*h0vOI7m;(t=7&EI_-`9(ESxtnwCGHW|x*;VCGz?DQ6p&=0{B8!|IJprpJEioeE- zSRzWglQapVR>ul|rP&RE5`Am-?Jui2*d3)oFtMYCRC0nbNMEWI;Q#2@lYCBT41_|H zUwK73w*`l8lxDEs9l4B00OgKyk#ew0wxiN${VM9E-9D8+L?mY_TjyQ4hXZ%2v+NiW zzt3_t?n9zJEvx&=-RmU8;GMe(U6)^zGfc(AcAAzgYfdo$c|QypO-i#b+Pn0eR$CCn zA46d%q24ugqiBmy#=GdL!^^^F8PBdKRrZUW&4wIH?zQ6HN}Z03AxA#Z!Y5#rt}7Y$ zeWw}3i4p)p36+wxC_M{gaiT~sn?eSjb@c$USr+CQ&mW%*eeDK|x|Al<4|4aem{;c` zO2v#nCpJGDsheEz^%*@->&l%p;J!*FR}~{>evB1bbIt@U_x!7B{IDf|h=cC#>)#Ci zK{~+>i?#=g&JVYW3?8Y!BF&9`9lkQWus-eBn(Qn~?A;GG)rQ1bp`P%#X3*Dce7pmJYcK17s3@p0`Ur z0NSsc-R#|U7WE6suB%L*CWh25eEBm&jEr!n^>|6=e2l9pa~f^t9={Rwl8VgxR}0Px zqqEoDvyltF43E=ghLA7kxA$Czw2q^u_g=A%!dHiRBNMN66lz3rJ+70=`kUy15AP-8 zXh=de(hR7t8m;AUe@*TJyN`7C7a}>YB{Mo3eK338WC?6S5j>ep?5uswW6Rfjzg{?^ zw$k6+S)FpBCck`NY?#PE%_SWi_jF*7Kctu5^l|aMrn$N+AWl9{e{acENc!KWh)n)ZbE=5rcrQ>SI^8UT!M_uY_3a2h3 zE)SyF%~JQ|F+r+YQ^BTPa zC+?(lBQ0#vnQp(UCSFToAsI@eFKU<=K6A$MRv)IMfi3EZzP#3?y}TcAdZdfumEUO{_%Mb| z)7@Vs8U*q?81RCA2aSuk&tI`)#tsVu5xrZ0?ES43mFIWcX=#Pa_t24Yp#y?&1)%+) zezng{c}F!$0@rH#DWJ6(a(kO`sEw7u51x?g}3}^Tn>mJ%4e#WLj0KL|ezajT4aVGk+q` zv|69i@>60PE{`ZWRS0@6z9&HceJBw60i_Vy9o_fa zx!S>n3WA#p!5DLVEOvCVq?^?z-y_&3W{-p5FA8TYfA(_CSCsAUU4t;T0A3&v-%u_> z6ZHtQ-aj--YbBHUcs{%}h!panRJ7Vk(er3#h47%1LUiMdxsnZ~S{mK-kP>hDia14% z6C1U9&TLKr(i6PNsYKlvrpm*=d1rAvUX;GKQvBj$e|76*pUyKm+Zl)58d#_&x3RiW z_KDd!^BUm{ui>+C7+N!%q!Z*9XsY_*C*{bLdb&5}?7CCGDifu@$=p3= zhbmtFskl{7I0I>CA?TeU(7JxP`Hq#>4uX23g=duokgclvHTw?9+gzRc^D`-EE6Gv)PwmBRb(wcI2j2DBmX{>dVWSLg-KDz+nc>V_k_t@ekfcV| zdkei`l3w!1(Y59;7*-AztbvANZ&+R%XJK@9Bc)2IARxRLWWuqaimBe>U^Bo!#<$nT`gM?n970niR+_FtMF?wWuU1h!n z)6xjey{|5RG&yP@;A(t#pPT$z%Uv-nRs=vs$7i?-Syy4r-Niq4uA74 zVz#MeDY~7vP1y9PGy0J<{LSwH_^ZD^pZE8x$Wf-pFuFfAKa|G;KHO!$2Yd5rV(d(z zye~#1;Ujiv9ruU0^$%Cc#IB6fTyUWEI=pJVlD}s}HzO|i&{&aYj*uYD$Nx2dKEu%a z2s&pDYUfGWi+})Z|BD??D8&pF5PCElXfmbh!0~$O#3IY^RfTnw?i%EmU;W9i_^@q7 zmqn6!Jiy;EO4^_%q2H_~;nf)3*y3tS7=l{T5+VM&9jUf2VDKK=9et;j~>Kr@iTW-a`-q%{WoNuopd7jMLcjEw-rLUGs?CZHcs-_C?NDap1 zQK%=-AQ_5uD2g;Mx{UHNoJzp5LtF0J=6wA^;>S)*c$i!}wUyoQ8}rm#iy`HinEmBq z*r0v-lNNp_3KQeK-Y;XT0KwX(rJ~Nj>!9U`nc-t;*Nb!*a`GDa$$Oo@sZxHw=Duz0 z(4Pnwb%r2e;t1`a3jvafP-+0fJB|C%+QWGM*IPHPZpwJYQOgMJ@zK;XmuXq%O|!hS zCx9v&oWQ%j3goe$ZW-NK?Y&x@-Tt{sh^H0HNWn!>TRvm*VBr15`7c-ll^7Cq-L;FtG<}((sKpN`axy1a8dq#(8!t@SA#04=N5ZNt zx^sb8qqxnDD*A$oO!K#EwuU8uJfi#(B3X=&)9&k}Wj*yOa;@yu=XZc$qx6xo36E3o z(mD>8yQPgBTK4Rd(%qYHCi;FgY|8>T; zS=L?Qw|(SRxgNt_+zfkqXGe`r1hdSt4Gqw$u^rpmz1e5iduw;UWv;>%cyT;(vP__4 z=6Iw%`IQ;)H(^+7AkC59mFTgl+>BT@Ptefwgsu(!E}t=bwz5PK0AuFWhx-G18sp2D-Nbh`i%f&wGKVsolK*}r^ zL=$3|HTEeBC$DEZZ{2{Ir(Tv;CNyY|&wOWk*(4VX@2zJhz!Kfz`EC-@_^zSxz1IfZ zVT6HoVO!h9T!{1IvFa?HqNsb3zMO!+bbZ|~JN-+_ry9vA_r*Q&!DdGQu67Rumdq!%EPg*Ym@Jyd zollm7wUb7cpHnJ8CwAjoOvfRJi+!cz*~F5w)Z0b#+6N-@2h~5uU|w;t_XyeU5lV*o zI_;oh7+-_Oz6-eyOnnML@z{LDxTcOJ`iFCYSfTU$(WM5Y$3K0#*7ubF1Wmh;*gI*t z&(HS>D_+c~SFH7wD#w&gmREzslwEYgF6v!>pgvl>VKRfIi!dIL!hyi${zl9i>%M^gvWL`qp zRLfPh$lODQ2gv2vGwE?4Z}@o|d%8>dbB$geJC8S*C+91jfEVW#qXXY?jv>r%Sam?E zO>#w$K^FSa&0$iXKBL*$#*BhTy)mWV0w7z6pk*uQiUfjMogfsx$;ECcM{eYD z*EPPX$p$l2a&Ab5{P3#=S)A7s^<+KU)Buw&VL6loSpaIc6V{;*ZS>J~SoI!%P(IP1 z3HasmM|g_g-Dek|v+791~!M5(YAzPT!iqir3E_#TdN(yyr8f1zBe;Ej zhp*C;0zfQ3CD71pQNmSye@bIG^m%INEd&v~X!m}0FmY1KEwH)tg-Rzc9D>j&)lxSY z+4Nyg;p7!*Vzo5}P-2qT26xF8K7o-gv0{2N_|ep6Uf5y}B_Sb|9rjZfW2Y*_f3ka_ zfJ3o444`e74S-|IDM-@%3kke#zqC>dM0e zSET{>PD66(TO!(8nmc%C0UnF@ek>Pnf@y=#!K140jvdZukNv{&JtEPMwGJ8$u$#93 zuztUQ>v>08FXKo0R+aN3-(#j+27?OY49q)~JlLRTv}%4dMCTFs&Dk82{%@La5xIG} zkE|7Fn~6>5Lk@j4Dw+$JWcW0%AtB=XM!e{{<&{o#NECGtC^(Z3Bo3SB1BF{Kz~5SL z^>^y7C^*>aR(87YMfxDWwm$8CyE&+xZtGkfxcUCh|Mfk5ZClO0&huk4k#XU4ks&T( zpC+3nk^AaCZ?bk`O_?Cg-^6BgEtIE$2uuW~xLmA-zruF2yL5vRDyoa-Qa*uuSx~~k zg4Lt)%t^2!3A&0R(}DXEVrHUgFb%%K0J+HZ=}vG1ZKXdXPbqMqXc$g_w%>E>y|~rk zE7h>nLISiIij#QZ)9CC1X72ve0^&XO{Ct5|7m8RU_jkQq+ zMh|`_K-wz{KPd1&+w~>;dN`(9hzqnnRR0;-gO9-03xr=XN?UTa;4uJ*&3!so>q>>h zj_5{n#V5qx8y&nxScvEeh1cgwJO>-Um@ES+z?ES%`qtN;Czkbn(tshUV6Nt<{33=wwkBuurhEP!A;>{n*qQjZEJU?o1R6H zoXI3huS)L>CV-i#_m$9It}idsObY32KpT_t5eeh6ihYB1U^At6A80=mp}{}zcCzxhuZKO#F>0-9kn-k(~6!qE3qgG?e zn6eBeSjgmj*!E2;;}u-*DYacITO=7Z`ZH+iKPrxyL8?5Twq zJSfnb3p@zU4*v zxWF`j&x|&rQR>qz*E@_G{*d;@zTeyvoj&*aO^Zk`Ajs61rGW{KJx{nRLx1r%(W}a& z(c(Gz@#oV|drz@M3Sp=`Ev54$*{k*f+K}^*XBkiJgW2dq^Hp?s%~*d}SY=tcGu`ZL zyy-WSQ*`9Z{+wRRS>E^IGZeQHmw!Yzsb1Co!i#Hk|3e70veRRGe~*32a@YD*5#Feu zM?t>zW?RC-Ij8osBP05sU>8Df7aDzp|A5;Y<|&gW%D$976W!Yl<9%emA%cq@Dtt7t zFU6|zAhARJb6$nLG$T<^amt+EiIvqs)cx3nVjI2@r6vHO-dj^&Z3H1%mB{NO7}WZm zGr%J0-r-R{WKVl@)nSY@3fx0qK61IfU&q16N+Cq}KGB>jiazu0M!F|)fLvp!wU#2J zzBsF0XLdUr5DV4ul`;*sc69^b*|_e~&9}&|yZ8%XxqJI%&DP%`ztWd>t2cf%`TbXY zQ}r@mnx)$*S*ENRgU28gwWDXibACg=5+yh$5)$V64zXN+`*1P*9j)Wg&v(`U2D^oW z{T*x)W#-dwT#`*cqE(sp~ z#L$8K(y)8WA~U;m#hT13IL6=n?u{)N$xPJ|#AE`-e)@BT?3HF0L-w`zFCoY<<&WOz z+N$cq&(GIb25C1<3T8q(-{f2|XN*zRJ-1+WZSJHJd~`#1BCxdJAS=s<*7jdu8;*RI z{X7Oip5#1s74y3MSg-?o)wo&xoC{om;ZkO~fdj&JFVqiUXeZ0@avP4aQn0*F z8$bJv%D-KLjQezR9wOX4kP@FI$4X1Mw$;PBMZa|PzWVle;MbH$xs}Z1npuoUqGA7t z78Pibg|;6m6U~Mj>U9O7hhHseDjW6e{`hUhM@4rL+AK;ciKwJu*5{81W)QN{Qa^&A zot%%#-8oQjplwQ5K!U8%M%(SgLinLTF-)*h%hOq@U8XhSzW5Y2(AG26HJt@8iAr4& zK7D4u_K{3XzDI^PyKPrIQ5TbMdAp~busxv9YG1z{*7d%egZ&(g$KvM(l4MBv(S4%H zHi2A;kkfdg5_$$YyI|4p5{PDF2D4h}En4%=52>3l;OF9|)gN{Jg~)53ThWabiU!o+ zNpwaEka47B;QYdx(P-Mzv%$~Mi? z9~)3U@as%ND1X^Cf98MKpH|W`+BL_j^8OAkH%tO?p`-J2AZJ@JOFEMjD8hv{ zCE66hYc|>Yf=S><3Al^m0nF6Ge>L!}@gE9i{mAap*LRxl6T$@1qRsS^7gefXUiPKL zY3MWpNY!}SflRajZs-}-z$?ESvmQm^RI8>Km`J~`71aTLMT7MMNRph`H^tw~hTU8g zQrATt?1Ql>Nk3U3B>tQ~A9t>0CY$r7dOy=P;qjo@?r4$z>%LQJ0XmO=NDjO0BCLp@ z(==V1RN{TDEhw~A!nzeadEoh?9BjVe_?;q+^BwSRn&Q49iROUliAK-lf79Z^*VE*32kix6!2)@9pi+EE_FNlQj>{3(k?rxH~(y zj@tH2G#Gs}AOU53d~;zDRaE%$3%Oko+1K4M4S)M{FYlrnhV;;FyK-;VtvRo{p(*Vhbkif#A5o`W zXt_Au8ob|f2WaCI0nkp$Ib+2-Ie+l#nSsFiFBMd7_V+g{!b5@?Y%L0fX=fq7qSb~Q zD5^1X_dv}sWU4mI9V@g_gHCBc`e~q!cF*H9q1j6`Ax7LoyF1RVhW68J@ma>VHAV&e zK&$OT2aHGv)JGAd!8DqHF%?#OocX%SHXjRrW9>tK#p)0^dMGE^{s*=zvTA8!byX{C zao`+?npG+$)Q|B`C7$lWxw}xVm@? zynDt`kr5>XT&3#yIO$K@AC%XDc4yU3daEff1X}tn3{G)?7Sht+uLjQ*le~tBl$L&m zgmN`%zUZ0sL1DMek`&-`Y@6xOO2y{tZvnd~lUF^;9inglR?9wyHW`#%AXY!r#YbzF z#_K2$60jzi>TfW1xLksY=IYxEs>6=q>EUPxATaJ(OB4VyOb^NFv`7}OpC@I%_D8Xl z2U(a3VPU>4bSyd~_-jUI8+ooyg9A(X|DFpa5%Vqwe0#IJQgg!w(Di6$SW&Q?pOd_Q z&hS&_T~P6Wy%Y9LMOf>o?De^MG$2<|XsVMMEX6*_=r#OMd;==1M$TlvKjprME$5RS z8MV2g_UE(1$J$&iNt16Ygos)`wLjA-uKG6%C>!>(il*%Q@6^dAO|wR!m!K=s%&?_k z@%H@w?Pb(~tCdAx1!22m!p9FYI$KE4z#1RmSFAUC+*YyR$A>{scX2$wt$?t{+tkc1 z#}JS)Fv#=Z=-{JOGyM`yd6_ks?R{pYpHFr^_27fn{DC1t4z^Xc-oFykE|7yrrUs#o zW$%AD#*b}02hf@sb`&fPAkOZsP z&QmOltOu)r!&4hUp@%6w(yyv!I@%Jf0YPi6TeO1-&N4+kI;_d|eOF{ye^5h2^@#OC z^-fqk8vF3n$Kf^1^A|s3UIubUQ3{+-=ZjBM<7*20mwl4QW}Esvy*6=EBwMfhRl+CJ z!BgN>xhI9f$u&X%(X_MVVYz6}NKWMREgT6Nz{1q>%ctVvXahr-%%5!VH%HlP> zt>^uHVGB1+A1=RHp;H);Du3YA(Sf6Z6`Hp>AFfJ&4SOL^Dn%kmm)f651xjhHQ{?u% zplbTzyVX3!Z!$TZ;vk}NJJ-8{6qSjWRh(iiM&x%dZrYja-0D5OJ|21~!IveQQ$k8G z#ql^p67^{Bg&p@vt0MK2_jc^)Om0TQsc6-Pi-!)(Vy~(~)8NydVjJzm9y2+?(^baD zeth&mRu+Iy_^EmJ+9RSJ7@nRsa_*6PE0PDxvD0jM4#*}(!QyFf%?CAO3H2;zIy zVDa4fBNm*Cyhfm(mr4?fq3iTe*VlQ%TIROCDy>H)E_0c6RS2ghN zHC}e{WyHOAM*Gj7d@+GQjj4ls{gW_B0BkGI50!u1orKJYfxz7}O}kc#5RP4{+-cWJ zYFk@$i(c?9%}*SX$r6EdM#&$inu-MAXEa)NttKPNHc<%|g6fZ0Ki&CZ-#JB%EQ@c= zd5}kb*1Zx&Fw?EF%{%7s&YgA@TSI>}!71a7`&@ks1=f3-VapB*N~ND%cD$UT(&JkI zcxB_a$jGo9;VtLuH2?dwkL@R?kFLcvGq0tJu9+OJ?asGDYOiIaJIOtk8oh+hJBT7_ zNoJv77+~wB&^P>TZL~~|f4GQoV{DxWrsD;9*?wKft3xmwv*TQ8rQrYGw(;c~H&rfx zVZx4Vo2~a3eT^$-vB8|n0Qj5HyH(kTPk7G%vmyKAzD=d44*7LkQ$@Q=G>rc#^I~s> zeWL{0z7+iVCsW%$=)UCInCDTtUzc2sY#o_iX|>wuLNrREM+B-)jV%Ne+wPF}Yh!iXoOsP|SYamZvKW zU@BAFhQ+6aS@f0h`O=gnruxtAGjADdt}zhVz+(4r6*G? zX(}HV4a`;eU%>!?gtpY8TrpD#K_}wE?fL{+eo$|8&5>?e2Llm-^5c|uEjUt?kQpHK zf(FG7ori<>`J}3BG3ep@T$TTp#OVy+*9T{l+-~J9)PH{+CF0ayHn%v={n~#74Nc%) zXzvn{Bn4TqrsCuOfKQ8mI^M z`^{grcjc^_gd6$mc!GWyf=C+!kkEO;LNbqkT$#a=sbVt-k&pZ*aC>-xqpML8p?;Mo zE*5ta|A1j#0)TmkK+qV{a?hdz0%kbB%E`<7_!wxsQg4(9*5;p%URS?sZgn9pBS3TL z!AJ+iqf$LB)ygeSTsX`Pz;-JnP$Yh0;xpJh*No5fNpF~_uEvmHj3i2GVpQtnGGTA5 zSi=7+*&kf7LuO79<)7xCXyOGrL!n~(L)BgYoMr6OYre~l*K$)^ECZ!Q2HCF@j$&sa z{=u$?zf^C5VA>c1gUyq#&?=>Wxd32>G+b@z(XL~6-{OlA=1!i?i%$TeL&Q>$d9l}q zQMz}@(xQ-?HV0@gl~Ll99C>BN-D}KYxCsM!Y`6%mM=TLTIlzK!nkfKxlc1&_`M9VEW6xjpvnntK z?K1T>cR*G?z7Gp%^V;EX;<{yP9u=$}EXCpH$yH4s3QhvJ;6_^3WPUfmrd5BKmE#zd|%mt3>PJyTDt_vG(hI|5-KF5m}9 zI`4gkV@zQ$44(BA+A`UZZ`q$+v6wJirNadYkk1X@&Q|j-Uz)$a>|JMCZ0cdJ z6v4FvuXL8cGRVLxd^N@K5agAfmT1jAzqp$W|KHVMEBpECgPmbr`NCC+oj&l)E2Bod z4|eh9u$f^?bZL$atRIQ^qQ99D6VVNtN!xmZm};NzU>I<^)-$$PwN2MCh{I!?1Jn~< ze8NWUOn4-joi0rOY%K?MP5LEGu2L@@$p4(KRt?Pvp_oMhEW73pWPxsKL4- zE+;`>ja$(6qTuc^yzH!yeuH;$K49I`Cyi>8D)#jJP&)tm@DH0un}1>p{U#K7f_L}d z68b7#6(iJkqCM);Jl9ut{EN$bn^pEyA|SAilNwA7FqHf+miL6ex#2qoleM@9F`c?< zV4+qM)W_PjN0g($^GKK0g$0FzTU2z9r>WsIE0HQAyJ?(>gXaB7b2k_2?RsH9;C8MP z>*NcWx`H*oAqe}!%_qeT>~Wu8zMC1G=ri5Ofwos!_c+j!rU!g8N+ku+graW}s5YZZ z$$dg61Pea^Z}MDSQSlLU3p_?Nneu>ijP+mP`dm#c|9sxwErF7YkYd$->O4_YyVL6+ zI3f#znxulaV@?+9jhdfEze%3(ZCAHO5AT#$U_KPh2f%iJ{XZg@y06 zGLfjn;5ojYR;}I9l?Shf%#-93$Y0<7bmzhaRJsnH!bUu*6(FgfFX|8ZrA;e}697zl)6PI_c<*m_;*1G`81vMesD&6|BD6VAm8=T@4}iK0 z{OG)GSb(RbUKew-(EDv z1h1DQ9ohpJcK45`CI1GpaQ6Q%Bu!dpYweDXqSh-2Qocvto6ZCxuaNX)L)~MiZMsA# z4~qssSo&b^WkbM)`|aO?`@|CgAg_ipzZfzeUJv!(m*}Ac2gJS*Gc-!Tuad-@JZlIg zbD;Tn%RXS5CmRM{Hgo9&H`Cf9(y;5_iDP~`r+*2Uq-wO%V)ZCY4tIUa4+I)ajl&Ri zltlf%s5)6AVNh;-a&^mP>-D!w;LNT6g{&M+>R3Q6YB=m7Pm6 zP7#;1s9j7nf_v-%@Zq=eCO%maIxE`-tnClMV$WYg`u~A42@$s={sC5V7>)#V9&-CY zkVOywPgP$X7gf{#y-O~=h_p0FclT1#3L+)lozl6aOM{e@goL!Tf`D{)NC*f>cQ?F; z`+4r)=Xw1T&(4`MGuJh9u5X;cz$G?t9&b+k-ma{pa}aCyqpJFH2pGySk9f(d?e69KT%b6M2EZeqIj6dUt6B+^)Nh^Zr4z}p zPbhtDF!`G+7_157d)#c!=xiexm=`KwnIEhFe+B3N%K`r>ICu6}D}ZQHc-Cc+;au`o zb%r3QZSuH)qZ^aYQ2zE|$DAc8Kp`UPo*3|?Xc5z__wg)ziq}j&vMd2WT+yif*0>-O zHCV_57>b5!E(Qn`bkw93zO!af?%N2jJQ6xBoSN;TQa~s;TNM^Z<=G5=h0Pw5_9o@W z=ua=G{mpmktkNhkzMX$$ze>E6y@g@+Q^r1x5XwV;5IJ!B~-8U=hh zJvFZ-`bZNBqV8k~5wz5w#)T@0!a($w>x}5Q-{sX`0n{*~_g^a%fk%4&JrY-9GGi`a zN8vz94&9Z^m>DMarfAUV^=;3)w;6Opz#}O6;!?Y+kKH`oq`&}S)O&A3aD{gOhZ6iK$l(~Ti| zEsxi_7htV$6>{&)0?kA|R^cC!tp4c|A3Ffa`q91FyA~O!u3YH0RC+ks6PG{%91jqh zPyUJjKX-W|?WF)<;?`L|xjXkm@tjOgv^0=5J4>*{K?!f zVszDeB2k%fv(x?GXtO^ao5<3N-8qo>JBh69QB(D0BytTT)zRYQ{UgBrw|2P`#>Zp; zdX_Hp`GWxs(@I||$O&|0(04;YC5ubggNUc0!Zy`omY#u7$Q|Mi8Oa<;_A5=yR9gvY zKr2<rg@J-t@ie*~C6zLcD?-w=3juJzHVjr?R@LjWSxh+Ga zt#;5JQyf6)>g(xs-aQ&9mELQZ)V;(<0w~&_Gr#7~-n@MJ>n%A4Dk#(hBaIA-LH&_K z<%t;v`M>wocd zb0^&ZzcadF`q2mY)A!{Ya~Lq%&AgwNmzspa3E9c#8SAN1}II zoI7UyrrL)3q&`Vmnr11XNRY;)`P2dr$Cuymxa!$9hJgu5_WhrGWZnDwZB;r^EpH7E z=eZ~Y)Qye-vje_vWJXe>bY6B~x%P|xPyTxOz|wlWKh+V!SW{#D`-3yUui*ZN=P}bW znr!gs@bgU-3Fe%rm23hEWl2*Z5A~%!RWx`jy*WWF?O-&T3_*wTF^R?GR`zbPfkHj@ z`jPj3ar@rhJ3VLgCtSLHcfms?>^_;hbbA9F2x!)}i1uQ+WULE# z$q64+B12hO5JhF=SGJzf<~+K`1r0?drfJ6u;J<_F=%r*)Qs-*Mi-D4iC-+T?Q>M5| zj!xvi%4KOBQ=|9<8{)N6-}^OV#m}n4K%pfc=A6`2xy~z%rb7dAoCI2Rf!mgKFRZ3^ zwZD2^!yw(=!%5N2E=ob|lZ38tLAjtnzr(PlC0(E5Mn`Gn>|{lgOj}%A-zqHO` znZIw{aqTm&q5q^{{Zi!7j;;Qq^YH<(wV^x>V$(YRx4gn^>=gZMeF`0l@#=2*)255sGCO8^utY!dGa_UvzvV1H}c3@)*6Wh}gBuu=g zw6y_?S5qYA8eEHLn44gTwhi;qjbFO93sC_vfyj_Dw{BAXBl~PVmcv zg`roUn$7dIJV~68Q8$Uu7Wzl8)hEK3EP2tNW;b*(LhZv1P?cX zv3qLnv(Q&eRZMGPh1oG@Cg|wj($cn&1yRM_9SVBB;ji}(LJ~I5#3B+7;)rGc`i=5R1+ly5*UC#)S2;!` z6r>9PFSCZ*Aq&MRZ50b0-7%Y0x_4~v8%#pY=sG_z zlm%;~u;cVu{$OhGn$`>LCwQ9+S@c@|va*uAV7S_Y9RAVvcI+4y-aj03P6rGz(vk52 zu_I=H_GMZr{i2@3RqGJtMO9?YMK(DqWYGX2y?tS$%f9OkJYeHNR4d=SNVUp$ulCWe z&YqHgD`AmF{r^%UD_;6o#Ua6JH`u7;Py^tN>YEVy0o^F2PmL#^4{;{Iq|c!9q6*AUM^sqISDm=A?NP!`OT_kz5F3d%v+5pQ;bv{y8;# zH}o#(DgB_ID>7)zUEqI7wBGAk$qqK4V2;a{wWI4P7pj+a?g{>k$S9@dQL!L(QG2dN zXj#CDg5^g2ujxcQt$;Q*TlIP#5sqFqVD#J!l>TM%a!71{Mu zId+DhdZSKvSKuu`-O)K2g7~1duUTC9>}Q&gHbN<++BXTvL5TJ+?f>%AHR_#GlR!sr zGzMlgBOkIw#~sg?Y-f39Xbc&_D3#?=6`BmIDivb*J19xZz;lwbt zn`$Z9@2T-E5vutnXB&;pcddmG;9(w3Qn_RNRiF<_YGCeamcss1Yji`d`vBiBE zZa7F*=aL}m^N#c(Y~ct6Vr!IAj!m=x0d?M^>Qh9w`f95FF^?@68mj&OMFt(J6c{*w zkW**rYLt8Gl&D{JV3>mylm)?PrOpcd4H#`Lw^Z+Ul1sqnO)Yk$|AroZhY0hv1eF=K zYSsyW5dH-vfZR^An6UHlm6qdS?5cUPxO_d^sq`MnGQiSPT(*7 zIv%E!gH#{|Eu4%$qF^~t`~(JE;jaB@Lo`2*Uff$gugB5B-JiE ziH}N>2x_|)=$B^c#l?41?P|maA)3>u$Q1ls4ay&wTw3tw=n^Oac^~3sNz}E~3!Vb6 zJ|ddVVUS7pbeJI=#wdM*N5yLOB@CVHvo1)=zYnkxGNWt?hJa+7-kN9&Xpl!52?Xd^ zrz9^Se{Ly2M~E9B7+49H6h52In6zYp+oQ{|=l~!hew92Qm2wabBI-u-#j;p7`t;V8 zaCY{|QV|mfy5|aLivPi=8F~Z@PnaCQ&>C_*4u{vlarHS^CiA$VX$$Dr?#ymj1#_ID z&Gy?LsG@%kG)!VzjtluLF2_CS*N-r$+ZvoS##F}#Ho;H~^m-goK*8}mKnFOtl*)$1bF2@Tmtygwh@~`No5K z8;}uS&(WWqEgsq0isPr@Ks~ml)tcX*axl)P2EcrVtViiu9oF66S!r}g_ZJX^hi}Z8 zsMmub>CykuYW3czl#d0IUAFm~-@kiB&TqDLYv6BtapZJ9EjKL83Wo`{H@fo7x%bBX zwuk4m?4jYGt`r|oNd}jR-lOeAwwwOrT=S^tsusew+;>3zC)MjFL&TbR*N(Y06rRYm zr8+&2A`^^v%-Eri_~!hP0^Gh^9;N>#!C^?85VSdqj0pY)-Sw6>@ z)jk6icS!XeMB!5l=qxOIu)h*}&;*9^a@`74=>~z#jeY{(cV~1>F1$Z;DJYc`ZES4x z&}m0cxRfoBWp!9uX*Ph@LkgMxnk5O(oWMF78Kjr>3^27UD!b@meKL%fL~8FkX#4{X zuFO5FzmkfAWZ$S`+nG5u$;FOJ!0s0-GEo;19osnH?N*pe>AiENAB(3{Ny9i zfZL@_juf?ecu5dCS?MmQ>idl`4gCQ&wY78kto=<&xDCk|M+5;Savc(xE2_4%(p&=@ z=Iu8qnA$q?B^;5xKuS&YB30Z*U~uCT9vo}-ebLwKKsFG@R72kgAUGIV{6KA!4ih#y zv-=}CVMlfbOdF228dXt>5p8*)p(v&d$aKG-v0IfZUIR>Y5A@DNBLi8xK;MAWd7>*V zfWlH_qy4$MSV(dA`gL;dIXlit6TShsYYZ9p>A9R?9!MtOS5UA_4|`PX^>rhKtde+u zCV!i6{6Z7d1C9Wg?L0H&t;T+;vjabN+LUhU(IG7R|LT=l!=`uiu*7nZbG6s}H*CNN zeZltVBEHiyj)py{jdWBZVTBwC;_`<`HiJ8Fy-h85Vvz~<2j(c#xkwZ!pO%jdLv!)? zFjd-!?BsuZE@tmpz@=_Z+^mV*N} z&*rlHncV)uaz;Nsdxn5OvVxJBZRRVOrrmq9Imuu%XX!h!!io5_*H<6(@Q%8>Rm#MS zKc^q$4w^j!L;0j0Dc|!@yx&Q^DN0rABLRV68%1l$oj7*vRU`RkP{PiOS_hljaR(ef z+1ELH7*VuV6e3aDeDE9>5fj#s3XSK8|CNQ~7oU4~(ROiaXhj9)aI|<8tcZR{7B}?3 zT;M961}gvMue0KKk)Xn*4xj{wy3_aq7lvK4+`D*lMRM5Y6#@cvqwtVaOB+aL6Vw7| zRR6KP_(YcI68jlsx?i$Mx|6qP)vEAaChz$GL~N8FOdV~Nf(r9Pe&X=Tw$`<^Yy7fg z&n9;-Q%3P7B`hKC3m~xOKpD!~JQx-NY8bfK44fpA^rs~WZxd}QK7)dvua8~N)C`yg zoye(tQ1^N)jSrmfXN&px6H?tiB}iNg8E%s{0y78&uY zp%#t2fpPoM-BC`d?7L@iC6$*chqy&(82zgslYT z2(O+a;<>aA0is%yJyDZF|Cb^sYFg!knobvGI-hZJ`ga@TB2AEfgujS(epEhYd6%LA zWQ;nmJ^3XLR%d0?w-WotF_A=v7CLb7^DVry{-qtW`-!rbB+VAC`{EZ|SjZF*f!D`q z2&cS!&Mn&=h1zk^>Yyhq6Ti+wq9~);m~BK?<9)Z1`?u2HN8m!;q+SL?uFb=l8Z@U- zR-JCEpC8f<$ytP8#G)dKQV&G@2rvd8`1begEGW-@pN(q%cwD%AIMm1O4hKrRvx_;f zppgJfHDhbvr!{*ILpMhZ$S}34%-Up{_SLNSH;Eb7Pb_xBI-2~qJ1a}Qmtf$j0?zrj zxt9mOvs}KHL*lw}`(j-Hl)!u(6W$vqM)iENv@trl!(IU(5c&4wHv$L~JI6p$UEcW|*Oh1tUP|1#IuF8l zUOC)=RMouS7S4o1;6OcwMsVI8QO}FxThB1K&*!EkUJY11En)o9-`MCY=@BhOu4DJ%U>00F*uepIys0KowLOW^a_<&N~Ie$3r4#@|vWgZA}-%680!#?6h0Y`*}DE;7On2hq+WkQA@zqphiCWZ+yy z?Lbly581(rCk`qoc*s-J9O&iKz4>RS)a#$LW3c85X0WhA&q>eiUm+gM6rRI#&X)NQ z3Jj*^oweFCepgXCTkFI5;V3H_j9TG=PLVP}S%`-re#IaETCALS^w{mt5(|QYRnfL~ zer)+ec>?FMcV}vr6D}UyRDaY<&E>!YHou3(J~*x9%BOgLt~@Hdfc2icj0Y*DXSj0G zykES0cEN{($6RToOL5EXDgQ(W1lv^{|JM!%v4N`bV>t*YHn*+oS)s$33T4TS|4R7Y zdoN88QjEOay>mGll3bGtN_!>uRF8Z>GL?`zb2=lfp!W1=u&-ld zxLW2Y5JnFw*ShZ200^-S15g$I!D`n*JeymnTMh=P!xX10?*zfP#px~HT zkFT`kFd=c7_1gQUfs!WZC^;I zPQcKTf^Apo|29AX14ukt&q`ArDYjJ|4ycB2Pag~Mduk(Wzd-O!*`ddGc&#qK20p83 z@wvW}gdyo%AVB=Y$Ez$qL<-b!qp`kbrN(+}g`Jm3kCd=N#a4mKxq~~<+-J!fiaehQwrt?GVJS=hNaynHB=XL)=)#FKe^66(T*1X-Kw$} z+>Y6?aY18Ymw`6+X8|dSY=#AwwzccMm_Q8WA?NaI0INQ7_E+R42<)}lcz!C8%>BQ9 zQ8!u*Rmp$`V)J4$vX_~Bb#X%g@S3Pqa5$d^2-9z?HT>8_0BVkFKO_N+bg1?N^UU7j zA1~Gu#*tQQoy+nS%1lv!P(yoBlaZ(Ki>XBq@L@G1?1<2Of zX@$)p&E4sg`A@fyy+%L9)C`NhFC&{gOQ^5Ep$x7ft|-IEE?NjV0dNVvzqkJ-uG?#C zly_<&e*?Q8& z*_n&egY*R8@CynJHwThXgvC2$S}@9=HsCDpp5qFa{GJ=f=zSfQY=P7LL&yq%T+Avq z1mps$B=)mf*wE zZpu;~lt54szJN#b*E)=cv#V54zl$L?s4plJQ~p9qiH5SU#gjjgaqZ3=Gk<-op}N=Hes78))H8JcBPGS&l5e7`PztrjF6-304(NemPK!bwNt zx1(84!@ECWvyvv(uWOheKer+RfCI)w1!XCK4V)Xzr1r0)jhDCc&BU30;n$=jv&jHB z)qUpDadNVBcW@Gy-8)le3lK)8UK3J4-~fodhmLTIc%yBKOdFZHk~3yTp55Z^>VA|! zlB)&4U~dcfqMMxO%IfSSeLQo*nFqs>s6Q$y9!g;UGt5NroNH6o&nGP8Zo7&*pFWA$ z#Fx1<+5QGWaMQjw*VVb*9jx2y-?ToQt{Jx|CjzS>639(9%%u!zAS44syQaXV-qI}J zpI-#m3xJDkaviQ*3^}NcnfDdj;^I!=Lx9;<`a_F57b7t$0D;ex#LP3zZZl`_1LkwK zScsX1cC^5oB+izz=7|@EK5t(AKKr>mfDX7)+78qE`)jM1Q*TYLj4-<`7PAMlIj|4L=U{!zO(IvQhQe08%#v_aU%y)Y~G0^SWdzF=SF{yab zJem+>@_KrmuRil+-0VX9;;g&Q@Dm3>h??qhpSC|s>PsI4Nx6HhXmx|{&=^KqZo^L) zfpP$oMtL6@E2zD5aL6J0_O`2MKjY@CoBua8AX5~`1+aaeesfh1xbs`$6?i~M;)Z@e z$K{dc@`gnTZ<-k@>|{%1zkK4<;xDz-8Fp>xbCTyEI zk$)B(+>RUuX$oW#%jCbh?jx}4KXPSDOa!7>_b^iwC?^2U8EX2^yR=@VmGya`%gQ@s zIin#R8t(z^n&jTQiLMrqUfdxDLsjh27rcNx)xLc1_>_P6Lh9kd)Z zFzWs$0D6+G2Kb{q{(==Y(|iLv@D|#t&DM{W=P!RC0&XxO<;$1{5L-Qs0{4VJ3u*z+ z$oMqQwfff^w@@IdaZ%)-F0atnYZUZy#nZm z{Dcd%An702W1f0`8>hU(KhGvt{-S|sUUJOQ=5qeI9$7N<(L2x+11=?qloy`0V`-Gr zrCOe>_CKnbctxWrkA3@`FsAfZ-Q9_iVW9H2)6oXofDJ~gKw{4BC#?Jccz--bgyT2SUH&S!XdDz*Op^<(XPjXs*V1IqiEJ+!o z?HYB#4$zcR6YCL%UGK2oFk&`sl&r19BUfP`a}F0-o~am{(S+wl(c0c}EDiACxv&IuS2kd3DT%os>?#Od_Rj zZ+UY3FxNDm^QD6AmJBS{h;P4QOXfCZ_$K+3~sJHd@mgt~I8A@fG;u1Cq`Kp6O3 zS4K%C@WRvLr^hhy+ME16TCiYA8~u}vAmi$tQL?M-iY4i_wFj3UZ5tz!rppm^_(3#& z>z(?A+;FsZz7`bHX4)e!+n29@%RcWLgK?SkopO66Pq+;$e3Dur9G;Hl9OTA(fpfJO zLn6WJ@sQq&pQvCc!-?d<2Mzu5gTL~4!e4K?!tc^9XzhghbI_j`YJAY&hnV~{bmH(k3# zgaEWU_Dzc>XSd&>FtpP3xUc@}cZDDASG)Vj`qj3?S?X}&j%)Tat+=g>wP5o_|(Dcm{9N7~*D;EpO zbi1x|$50+)72VBzX5RJ2zG~_UjLu0OWNT`OJ}E|eKV{E3Ll(POMzI%>L?2qaF=x@f zjvHz*#BdFT8H+JTp{d(QmIuE-H@7t=UF@B8()+!Ide@aD6JU6eQYfG2 zM!cyN<_HXLHi4dRNB?hXM)xiIoFD4!H^eQ7$~`Bh-aWJF zr~=V_;y_QnZG4=-J}8c(U%zwp2(SA7!5rD8sWeifVh|%%TX@JMuIxL#!E(MQ)p}?v z3&PvFqNG?`e9KaCBuJ)Jk6iruhq9?4>kM8vnl#FeRCzI?UrG7S)5N1uyci8>n;hD` z76kmy!)GqGAbR8~CR?(zxlQBnWEausEyqw9P7C+TrIc3uJsQ70M`W0({;#|7oHX1;&Yvhpcjl9w+~rT=mP zd$six`aDjR`A(iFE>p;XEnp&8a8^h)6fIc8=L)ao&t6=`X7#z`6mgp*<^*qE5LXs& zW*ZK2J_+J}pT&0Q{lFk?5RS&rr=W9DE{n)a7i;R?u}JQ5A=R~hvr?jfJkD>{U0xr4 zBGX(*k`%XM7#3RwnWdQ_kA>+4{UJhE%Y!yz0`kngoU{ zm0}n@w*O6w``Z3?9c5v;(=nP6gAeNS5RyRjBZ6iWX_=dy87(y0AR8Ij`0FyrG}7uZ3=A8jWxNgku8OI3BRH;UJWVer-IW=8 zp&4IugFu`KvmnLq?R|f17AzA@EJ163e(n&o6MMb7NSaJ1#VkU$0O6phnaqUNX=+@# zbeEt~?O?e|QQC<46-a98YIa%nWp=h_kYtWxvM@0Va#52*e8Z}T&2o%Z8b7*l=XA<( zl>xII?5<>j7X3>LHEXfOC2s$4pE4fWFQTg^@|{>yPg{O!>X%ILd7#cH44(3y(3zeD zks^`VrF6uGqJACMBFf{}T_((uk;oR>0sTn|Lk8d4c& zBL`ROCo893=()KQJ;dEq7(FCj1Tve19R>kU$e3vMC4^45_4vJyd;{aos-sq4Qbc1X z0KbQ7E`ulbZ+l`H8!9Br2X5QK-n+3Ea_viyJSentqY1pmtb6-yBnqwFEjBrz4b^1A z@>>4eTylm4xmElyhzv4L$VU*ES!jAyH9~YRQ#rI}ZON2aBxy&z2^#gJ8HIghGcB5GpN zLtn3);eK3Z zV*6o3f>(FvXd!D=gTt~JOH_4x;s3iBrOaZq3<_5u)t~>+u)C1 zLn^c_XAHvWjLLBpwf&t^6nIj!pr_^HqVc(I0i8}|vk7WVJy(?je-*R{W1c)h_3tq4 z|FFio?%m&l!a>tc00%mN6#r7GKg1I|Yht=WtVpz~l}hj9JP)4Rr||9=!|u-=kTiJ062*7Dzp3iuCo zv!z0j_#H@$Rw{<8q}2<}O$khiX}Q$T01J`EBTTo< z=|0awIO%iZ$R1x^t++{AI=YC!Uo&hz=$<;&`LkY}B)>fgA*Q4{%8*-)=@)Skq2)w* zA??5-U{Znx)4e=_xzIRvET8)=*Ibn*s`Q7=sYD2JfBYgpP11`N9Jk&FN5~0tNEoVD zQR22H6g~vCL_z&;ml2V-CpsYG+z@wL~Q?!4)Q?` z*;&O(e)uBVM$o<#z0WwW9QzjW6cfnfIZRSav4stE9!|Q3nJp77bx-EZD08UHa)PMc z+Uh~%uE-49J;3Lt{7Vp@iS@uqJ#)}@iN)R34`>t zD7-uPQGq91p z1On{s@SI=;Zu^mm_t`VqKdKH@EML7-3jKx^B*;Ce{&ZR&ffgLIinaE2bmdRP#8Tu@ zl0ROQi!2=xa8rbw;!k(`RzrM$SEGL0y)Cn7NBel!=%AP+IB^!nDD~n`E~|^67F~Qk z@40>w!Qwd-GG`_pilNnizOTI(%Yqn9mME}bgL>S)--1Uhj0jcG+<^TcuhhKIhmgfP6 zHlrRuPKs}Z=JKoY%=)Y0;N0d9*-7|YDLKvx>{*S$wC$}jpYg=*@AjRrMzY=P zirK8ug1Zs^P;*Y0HCi4J-8YLIXLq;qpWa=Z-*39(=?cu2(fL$y0cQa=rN}R_27;we z-+MUDvsTq$ni<3=NcR1;IyqV-!zX0GL^O?zFVT6x{z8Spg4;RI|(?yfx- zIkl#iWi0-N>Er2peLg;3eH2y{>-L#7q#g^HpT8A?);LK+ah%UGGg*NyFjhv963cLO zAoO=1PkT-6w8e1&Ni23o=$YUJ^MjgtPLU+?$T4b$P z<+`OR91uooWU{Fk0-HT=vCOGocffiN|%4%4v%dtF8-;8`HiP5dwh>! z&ku?hZQ{QSk8Rc0eCxNnQ^2e3tjGL99_^b6ko*OIn7*MTok`QXSDJHlk1R0IPJYfh zl+ZJ&S`37~Q}=8iqbzd4XX&&2K$t@M2)xZ{lXEzBwYf_+!LI) zV;@^^iAxiFA@(h;jm+F{y=Q|i8ma=DbF4pw;T*cZUifJtJ6qvP%`X~38JFz(Y>iI ze6j)O<~ls38bMABqwZG>AA$b=dv{b*xBvlZ-;vW2Ys*?^_b>{u>C)$u+5pji`ZDBI z@613Qp7N_)8!j1WrV>366Nn@nshTeMTMc}7dYhj27M_t=LtAM-Untc-U1p3G#z}H} z74k}9CXBJb)3yEw;Sr4_f*Xqm6bC%*A)k~i5;wH698=`WV)gKNp)%)CL~UUzXWBh5 z;LIBBalCa8Qj0yG)n6Owtx@o?O!Nd^hCd!z+O>lq@!;jhz2XNN0z{3xb%EpYUgNxi zgY`S{wDrRGo3p{YSN@5sy1g^#V6{#yYHn_*Y7=&w*}EN<{*m{p8P%?t`o|wLG4Yvs ze&PX-ak)%d10DW3{6lFeL{z}3I%$qo$z4u-pLk8uy%ZS-MHs1J@`2jZqx|#s&L^*% z_s>pAiK}d(+A;7o41;S!7R1s+q^9&XN57BA}%3E+9?l_)wEclOkGAN3ZN(Y>QsF zHM~#|QEW0$Tw-9XeLB__(AQNIWc#I(R4ibQlRvJX6OTgJ=I)u(4ec0VBr47S#n3`j z$4}fCiNlRSs*MHqM(*hC8C}D?W?OBo`1$276ZnHt#-OyBzr)2MM}x1>g*Y#h+im?X zar4<*y0++E_~ql!2EmT$Vb@pw%M0i67kQxFMefo zh`7}zXlP}bGt8A%R|o5B84b}#FnuqrY-=~p@qD`7c;UkO&h==pbnGEu;-PLUBB5k> zL!kt)On+HK9AkuHdim}D>uhfwdpMR zkcS$9D!4~WLPq{Y((_5CzE~7?-IQku)kDQe1{a<1Tq%}-zy~Ha(*P6T1b5V~5EB-e z7G#hvU-CBc^1ESXfw*9~7{k zD4FIw@T)zE{GfIkDB1hKNf-G{AAK|t=c$~0P7xV);C+MC_{@xT4mOVX8^bsp9C!Yg zlr179E$8Yo4pRs2Q?L5pM`xs)sH)G+QX14oe^{nA2a$pXem;QK3j0^lD<=# Date: Fri, 10 Jan 2025 08:45:17 +0100 Subject: [PATCH 08/10] Update vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java Co-authored-by: Diego Cardoso --- .../com/vaadin/flow/component/charts/model/PathfinderType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java index a018235295f..fa9e0e72011 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PathfinderType.java @@ -10,7 +10,7 @@ /** * Pathfinder algorithm to use for chart that can connect two points (e.g. - * series items_. + * series items). */ public enum PathfinderType implements ChartEnum { From a99e811dad78f158d34d8a6deb6af4b632eaa1f8 Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Fri, 10 Jan 2025 08:59:27 +0100 Subject: [PATCH 09/10] docu: improve documentation for Gantt supported features --- .../vaadin/flow/component/charts/model/Marker.java | 11 ++++++----- .../com/vaadin/flow/component/charts/model/XAxis.java | 6 ++++-- .../com/vaadin/flow/component/charts/model/YAxis.java | 10 +++++----- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java index c9275489019..a82af05c8be 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/Marker.java @@ -185,8 +185,8 @@ public HorizontalAlign getAlign() { } /** - * Horizontal alignment of the markers relative to the points. Defaults to - * "center" + * Supported only in Gantt charts: Horizontal alignment of the markers + * relative to the points. Defaults to "center" */ public void setAlign(HorizontalAlign align) { this.align = align; @@ -200,8 +200,8 @@ public VerticalAlign getVerticalAlign() { } /** - * Vertical alignment of the markers relative to the points. Defaults to - * "middle" + * Supported only in Gantt charts: Vertical alignment of the markers + * relative to the points. Defaults to "middle" */ public void setVerticalAlign(VerticalAlign verticalAlign) { this.verticalAlign = verticalAlign; @@ -215,7 +215,8 @@ public Boolean getInside() { } /** - * Whether to draw the markers inside the points. Defaults to false. + * Supported only in Gantt charts: Whether to draw the markers inside the + * points. Defaults to false. */ public void setInside(Boolean inside) { this.inside = inside; diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java index a2c3a7e1751..6da1f8b9886 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/XAxis.java @@ -1533,7 +1533,8 @@ public PlotLine getCurrentDateIndicator() { } /** - * Show an indicator on the axis for the current date and time. + * Supported only in Gantt charts: Show an indicator on the axis for the + * current date and time. * * @param currentDateIndicator */ @@ -1546,7 +1547,8 @@ public void setCurrentDateIndicator(Boolean currentDateIndicator) { } /** - * Show an indicator on the axis for the current date and time. + * Supported only in Gantt charts: Show an indicator on the axis for the + * current date and time. * * @param currentDateIndicator */ diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java index d8b680a8718..678286b7a39 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/YAxis.java @@ -1794,11 +1794,11 @@ public Number getStaticScale() { } /** - * For vertical axes only. Setting the static scale ensures that each tick - * unit is translated into a fixed pixel height. For example, setting the - * static scale to 24 results in each Y axis category taking up 24 pixels, - * and the height of the chart adjusts. Adding or removing items will make - * the chart resize. Defaults to 50. + * Supported only in Gantt charts: For vertical axes only. Setting the + * static scale ensures that each tick unit is translated into a fixed pixel + * height. For example, setting the static scale to 24 results in each Y + * axis category taking up 24 pixels, and the height of the chart adjusts. + * Adding or removing items will make the chart resize. Defaults to 50. * * @param staticScale */ From 8fb0d4a4b355607a396dce95b1c67af92aaf282d Mon Sep 17 00:00:00 2001 From: Bretislav Wajtr Date: Fri, 10 Jan 2025 14:53:02 +0100 Subject: [PATCH 10/10] feat: add drag&drop support to Chart API --- .../examples/gantt/GanttInteractiveDemo.java | 184 +++++++++++ .../lineandscatter/LineDragAndDrop.java | 88 ++++++ .../vaadin/flow/component/charts/Chart.java | 30 ++ .../charts/events/PointDragEvent.java | 116 +++++++ .../charts/events/PointDragStartEvent.java | 118 +++++++ .../charts/events/PointDropEvent.java | 117 +++++++ .../component/charts/model/AreaOptions.java | 20 ++ .../flow/component/charts/model/DragDrop.java | 289 ++++++++++++++++++ .../component/charts/model/DragHandle.java | 140 +++++++++ .../flow/component/charts/model/GuideBox.java | 41 +++ .../charts/model/GuideBoxDefaultState.java | 118 +++++++ .../charts/model/PlotOptionsGantt.java | 28 ++ .../charts/model/PlotOptionsSeries.java | 28 ++ 13 files changed, 1317 insertions(+) create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttInteractiveDemo.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/lineandscatter/LineDragAndDrop.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragEvent.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragStartEvent.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDropEvent.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragDrop.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragHandle.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBox.java create mode 100644 vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBoxDefaultState.java diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttInteractiveDemo.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttInteractiveDemo.java new file mode 100644 index 00000000000..261942f8a0f --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/gantt/GanttInteractiveDemo.java @@ -0,0 +1,184 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.gantt; + +import java.time.Instant; +import java.util.ArrayList; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.AxisType; +import com.vaadin.flow.component.charts.model.ChartType; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.DataLabels; +import com.vaadin.flow.component.charts.model.DragDrop; +import com.vaadin.flow.component.charts.model.GanttSeries; +import com.vaadin.flow.component.charts.model.GanttSeriesItem; +import com.vaadin.flow.component.charts.model.HorizontalAlign; +import com.vaadin.flow.component.charts.model.PlotOptionsGantt; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.XAxis; +import com.vaadin.flow.component.charts.model.YAxis; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; + +@SuppressWarnings("unused") +@SkipFromDemo +public class GanttInteractiveDemo extends AbstractChartExample { + + private VerticalLayout logPane; + + @Override + public void initDemo() { + Chart chart = new Chart(ChartType.GANTT); + configureEvents(chart); + + final Configuration configuration = chart.getConfiguration(); + var tooltip = new Tooltip(true); + tooltip.setXDateFormat("%a %b %d, %H:%M"); + configuration.setTooltip(tooltip); + + configuration.setTitle("Interactive Gantt Chart"); + configuration.setSubTitle("Drag and drop points to edit"); + + XAxis xAxis = configuration.getxAxis(); + xAxis.setCurrentDateIndicator(true); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setType(AxisType.CATEGORY); + yAxis.setCategories("Tech", "Marketing", "Sales"); + yAxis.setMin(0); + yAxis.setMax(2); + + PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt(); + plotOptionsGantt.setAnimation(false); // Do not animate dependency + // connectors + configureDragAndDrop(plotOptionsGantt); + + plotOptionsGantt.setAllowPointSelect(true); + configuration.setPlotOptions(plotOptionsGantt); + + final GanttSeries series = createSeries(); + configureDataLabels(series); + configuration.addSeries(series); + + add(chart); + logPane = new VerticalLayout(); + logPane.setSpacing(false); + add(logPane); + } + + private void configureEvents(Chart chart) { + chart.addPointSelectListener(event -> { + final GanttSeriesItem ganttSeriesItem = ((GanttSeries) event.getSeries()) + .get(event.getItemIndex()); + var taskId = ganttSeriesItem.getId(); + logMessage("Task with id " + taskId + " was selected"); + }); + + chart.addPointUnselectListener(event -> { + final GanttSeriesItem ganttSeriesItem = ((GanttSeries) event.getSeries()) + .get(event.getItemIndex()); + var taskId = ganttSeriesItem.getId(); + logMessage("Task with id " + taskId + " was deselected"); + }); + + chart.addPointDragStartListener(event -> { + final GanttSeriesItem ganttSeriesItem = ((GanttSeries) event.getSeries()) + .get(event.getItemIndex()); + var taskId = ganttSeriesItem.getId(); + logMessage("Task with id " + taskId + " dragging started: " + event.getStart() + " - " + event.getEnd()); + }); + + chart.addPointDropListener(event -> { + final GanttSeriesItem ganttSeriesItem = ((GanttSeries) event.getSeries()) + .get(event.getItemIndex()); + var taskId = ganttSeriesItem.getId(); + logMessage("Task with id " + taskId + " was dropped: " + event.getStart() + " - " + event.getEnd()); + }); + } + + private void logMessage(String message) { + logPane.add(new Div(message)); + if (logPane.getComponentCount() > 10) { + logPane.remove(logPane.getComponentAt(0)); + } + } + + private void configureDataLabels(GanttSeries series) { + var plotOptions = new PlotOptionsGantt(); + var dataLabels = new ArrayList(); + var pointNameDataLabel = new DataLabels(true); + pointNameDataLabel.setAlign(HorizontalAlign.CENTER); + pointNameDataLabel.setFormat("{point.name}"); + dataLabels.add(pointNameDataLabel); + plotOptions.setDataLabels(dataLabels); + series.setPlotOptions(plotOptions); + } + + private void configureDragAndDrop(PlotOptionsGantt plotOptions) { + final DragDrop dragDrop = plotOptions.getDragDrop(); + dragDrop.setDraggableX(true); + dragDrop.setDraggableY(true); + dragDrop.setDragMinY(0); + dragDrop.setDragMaxY(2); + dragDrop.setDragPrecisionX(1000 * 60 * 60 * 8); // Snap to eight hours + } + + private GanttSeries createSeries() { + GanttSeries series = new GanttSeries(); + final GanttSeriesItem tech1 = new GanttSeriesItem(0, + Instant.parse("2014-10-18T00:00:00Z"), + Instant.parse("2014-10-20T00:00:00Z")); + tech1.setId("tech1"); + tech1.setName("Prototype"); + series.add(tech1); + + final GanttSeriesItem tech2 = new GanttSeriesItem(); + tech2.setMilestone(true); + tech2.setStart(Instant.parse("2014-10-22T00:00:00Z")); + tech2.setY(0); + tech2.setId("tech2"); + tech2.addDependency("tech1"); + tech1.setName("Prototype done"); + series.add(tech2); + + final GanttSeriesItem tech3 = new GanttSeriesItem(0, + Instant.parse("2014-10-24T00:00:00Z"), + Instant.parse("2014-10-27T00:00:00Z")); + tech3.setId("tech3"); + tech3.setName("Testing"); + tech3.addDependency("tech2"); + + series.add(tech3); + + final GanttSeriesItem marketing1 = new GanttSeriesItem(1, + Instant.parse("2014-10-20T00:00:00Z"), + Instant.parse("2014-10-23T00:00:00Z")); + marketing1.setId("marketing1"); + marketing1.setName("Product pages"); + series.add(marketing1); + + final GanttSeriesItem marketing2 = new GanttSeriesItem(1, + Instant.parse("2014-10-25T00:00:00Z"), + Instant.parse("2014-10-29T00:00:00Z")); + marketing2.setId("marketing2"); + marketing2.setName("Newsletter"); + series.add(marketing2); + + final GanttSeriesItem sales1 = new GanttSeriesItem(2, + Instant.parse("2014-10-23T00:00:00Z"), + Instant.parse("2014-10-26T00:00:00Z")); + sales1.setId("sales1"); + sales1.setName("Licensing"); + series.add(sales1); + return series; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/lineandscatter/LineDragAndDrop.java b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/lineandscatter/LineDragAndDrop.java new file mode 100644 index 00000000000..015874f09c0 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow-integration-tests/src/main/java/com/vaadin/flow/component/charts/examples/lineandscatter/LineDragAndDrop.java @@ -0,0 +1,88 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.examples.lineandscatter; + +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.examples.AbstractChartExample; +import com.vaadin.flow.component.charts.examples.SkipFromDemo; +import com.vaadin.flow.component.charts.model.Configuration; +import com.vaadin.flow.component.charts.model.DragDrop; +import com.vaadin.flow.component.charts.model.HorizontalAlign; +import com.vaadin.flow.component.charts.model.LayoutDirection; +import com.vaadin.flow.component.charts.model.Legend; +import com.vaadin.flow.component.charts.model.ListSeries; +import com.vaadin.flow.component.charts.model.PlotOptionsSeries; +import com.vaadin.flow.component.charts.model.Tooltip; +import com.vaadin.flow.component.charts.model.VerticalAlign; +import com.vaadin.flow.component.charts.model.YAxis; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; + +@SkipFromDemo +public class LineDragAndDrop extends AbstractChartExample { + private VerticalLayout logPane; + + @Override + public void initDemo() { + final Chart chart = new Chart(); + + Configuration configuration = chart.getConfiguration(); + configuration.setTooltip(new Tooltip()); + + configuration.setTitle("Solar Employment Growth by Sector, 2010-2016"); + configuration.setSubTitle("With the ability to drag and drop points"); + + YAxis yAxis = configuration.getyAxis(); + yAxis.setTitle("Number of Employees"); + + Legend legend = configuration.getLegend(); + legend.setLayout(LayoutDirection.VERTICAL); + legend.setVerticalAlign(VerticalAlign.MIDDLE); + legend.setAlign(HorizontalAlign.RIGHT); + + PlotOptionsSeries plotOptionsSeries = new PlotOptionsSeries(); + plotOptionsSeries.setPointStart(2010); + configureDragAndDrop(plotOptionsSeries); + configuration.setPlotOptions(plotOptionsSeries); + + configuration.addSeries(new ListSeries("Installation", 43934.5, 52503, + 57177, 69658, 97031, 119931, 137133, 154175)); + + add(chart); + configureEvents(chart); + + add(chart); + logPane = new VerticalLayout(); + logPane.setSpacing(false); + add(logPane); + } + + private void configureDragAndDrop(PlotOptionsSeries plotOptions) { + final DragDrop dragDrop = plotOptions.getDragDrop(); + dragDrop.setDraggableX(true); + dragDrop.setDraggableY(true); + } + + private void configureEvents(Chart chart) { + chart.addPointDragStartListener(event -> { + logMessage("Task with id " + event.getCategory() + " dragging started:" + event.getxValue() + ", " + event.getyValue()); + }); + + chart.addPointDropListener(event -> { + logMessage("Task with id " + event.getCategory() + " dropped:" + event.getxValue() + ", " + event.getyValue()); + }); + } + + private void logMessage(String message) { + logPane.add(new Div(message)); + if (logPane.getComponentCount() > 10) { + logPane.remove(logPane.getComponentAt(0)); + } + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java index 1ba9d933659..b9d54afbd10 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/Chart.java @@ -35,6 +35,9 @@ import com.vaadin.flow.component.charts.events.ChartSelectionEvent; import com.vaadin.flow.component.charts.events.DrilldownEvent; import com.vaadin.flow.component.charts.events.PointClickEvent; +import com.vaadin.flow.component.charts.events.PointDragEvent; +import com.vaadin.flow.component.charts.events.PointDragStartEvent; +import com.vaadin.flow.component.charts.events.PointDropEvent; import com.vaadin.flow.component.charts.events.PointLegendItemClickEvent; import com.vaadin.flow.component.charts.events.PointMouseOutEvent; import com.vaadin.flow.component.charts.events.PointMouseOverEvent; @@ -596,6 +599,33 @@ public Registration addPointUpdateListener( return addListener(PointUpdateEvent.class, listener); } + /** + * Adds a point drag start listener, which will be notified when starting to drag a point. + * @param listener + */ + public Registration addPointDragStartListener( + ComponentEventListener listener) { + return addListener(PointDragStartEvent.class, listener); + } + + /** + * Adds a point drop listener, which will be notified point is dropped. + * @param listener + */ + public Registration addPointDropListener( + ComponentEventListener listener) { + return addListener(PointDropEvent.class, listener); + } + + /** + * Adds a point drag listener, which will be notified while point is dragged. + * @param listener + */ + public Registration addPointDragListener( + ComponentEventListener listener) { + return addListener(PointDragEvent.class, listener); + } + /** * Adds a x axes extremes set listener, which will be notified when an x * axis extremes are set diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragEvent.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragEvent.java new file mode 100644 index 00000000000..d3c34d86b31 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragEvent.java @@ -0,0 +1,116 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.events; + +import java.time.Instant; + +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.util.Util; + +/** + * Fired while dragging a point. + */ +@DomEvent("point-drag") +public class PointDragEvent extends ComponentEvent implements HasItem { + + private final String category; + private final Instant start; + private final Instant end; + private final String parent; + private final Double x; + private final Double y; + private final int seriesIndex; + private final int pointIndex; + private final String pointId; + + public PointDragEvent(Chart source, boolean fromClient, + @EventData("event.detail.originalEvent.target.series.index") int seriesIndex, + @EventData("event.detail.originalEvent.target.index") int pointIndex, + @EventData("event.detail.originalEvent.target.id") String pointId, + @EventData("event.detail.originalEvent.target.category") String category, + @EventData("event.detail.originalEvent.target.start") Double start, + @EventData("event.detail.originalEvent.target.end") Double end, + @EventData("event.detail.originalEvent.target.parent") String parent, + @EventData("event.detail.originalEvent.target.x") Double x, + @EventData("event.detail.originalEvent.target.y") Double y) { + super(source, fromClient); + this.seriesIndex = seriesIndex; + this.pointIndex = pointIndex; + this.pointId = pointId; + this.category = category; + this.start = start != null ? Util.toServerInstant(start) : null; + this.end = end != null ? Util.toServerInstant(end) : null; + this.parent = parent; + this.x = x; + this.y = y; + } + + @Override + public String getCategory() { + return category; + } + + @Override + public int getItemIndex() { + return pointIndex; + } + + @Override + public String getItemId() { + return pointId; + } + + @Override + public int getSeriesItemIndex() { + return seriesIndex; + } + + /** + * @return Supported only in Gantt charts: Returns the start date of the point at the moment the Drag event + * was fired. + */ + public Instant getStart() { + return start; + } + + /** + * @return Supported only in Gantt charts: Returns the end date of the point at the moment the Drag event + * was fired. + */ + public Instant getEnd() { + return end; + } + + /** + * @return Returns the parent id of the point at the moment the Drag event + * was fired. + */ + public String getParent() { + return parent; + } + + /** + * @return Returns the x value of the point at the moment the dragging + * started. + */ + public Double getxValue() { + return x; + } + + /** + * @return Returns the y value of the point at the moment the dragging + * started. + */ + public Double getyValue() { + return y; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragStartEvent.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragStartEvent.java new file mode 100644 index 00000000000..34596dbc642 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDragStartEvent.java @@ -0,0 +1,118 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.events; + +import java.time.Instant; + +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.util.Util; + +/** + * Fired when starting to drag a point. + */ +@DomEvent("point-drag-start") +public class PointDragStartEvent extends ComponentEvent + implements HasItem { + + private final String category; + private final Instant start; + private final Instant end; + private final String parent; + private final Double x; + private final Double y; + private final int seriesIndex; + private final int pointIndex; + private final String pointId; + + public PointDragStartEvent(Chart source, boolean fromClient, + @EventData("event.detail.point.series.index") int seriesIndex, + @EventData("event.detail.point.index") int pointIndex, + @EventData("event.detail.point.id") String pointId, + @EventData("event.detail.point.category") String category, + @EventData("event.detail.point.start") Double start, + @EventData("event.detail.point.end") Double end, + @EventData("event.detail.point.parent") String parent, + @EventData("event.detail.point.x") Double x, + @EventData("event.detail.point.y") Double y) { + super(source, fromClient); + this.seriesIndex = seriesIndex; + this.pointIndex = pointIndex; + this.pointId = pointId; + this.category = category; + this.start = start != null ? Util.toServerInstant(start) : null; + this.end = end != null ? Util.toServerInstant(end) : null; + this.parent = parent; + this.x = x; + this.y = y; + } + + @Override + public String getCategory() { + return category; + } + + @Override + public int getItemIndex() { + return pointIndex; + } + + @Override + public String getItemId() { + return pointId; + } + + @Override + public int getSeriesItemIndex() { + return seriesIndex; + } + + /** + * @return Supported only in Gantt charts: Returns the start date of the point at the moment the dragging + * started. + */ + public Instant getStart() { + return start; + } + + /** + * @return Supported only in Gantt charts: Returns the end date of the point at the moment the dragging + * started. + */ + public Instant getEnd() { + return end; + } + + /** + * @return Returns the id of the point parent at the moment the dragging + * started. + */ + public String getParent() { + return parent; + } + + /** + * @return Returns the x value of the point at the moment the dragging + * started. + */ + public Double getxValue() { + return x; + } + + /** + * @return Returns the y value of the point at the moment the dragging + * started. + */ + public Double getyValue() { + return y; + } + +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDropEvent.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDropEvent.java new file mode 100644 index 00000000000..86c4dbb9b88 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/events/PointDropEvent.java @@ -0,0 +1,117 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.events; + +import java.time.Instant; + +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; +import com.vaadin.flow.component.charts.Chart; +import com.vaadin.flow.component.charts.util.Util; + +/** + * Fired when the point is dropped. + */ +@DomEvent("point-drop") +public class PointDropEvent extends ComponentEvent implements HasItem { + + private final String category; + private final Instant start; + private final Instant end; + private final String parent; + private final Double x; + private final Double y; + private final int seriesIndex; + private final int pointIndex; + private final String pointId; + + public PointDropEvent(Chart source, boolean fromClient, + @EventData("event.detail.originalEvent.target.series.index") int seriesIndex, + @EventData("event.detail.originalEvent.target.index") int pointIndex, + @EventData("event.detail.originalEvent.target.id") String pointId, + @EventData("event.detail.originalEvent.target.category") String category, + @EventData("event.detail.originalEvent.target.start") Double start, + @EventData("event.detail.originalEvent.target.end") Double end, + @EventData("event.detail.originalEvent.target.parent") String parent, + @EventData("event.detail.originalEvent.target.x") Double x, + @EventData("event.detail.originalEvent.target.y") Double y) { + super(source, fromClient); + this.seriesIndex = seriesIndex; + this.pointIndex = pointIndex; + this.pointId = pointId; + this.category = category; + this.start = start != null ? Util.toServerInstant(start) : null; + this.end = end != null ? Util.toServerInstant(end) : null; + this.parent = parent; + this.x = x; + this.y = y; + } + + @Override + public String getCategory() { + return category; + } + + @Override + public int getItemIndex() { + return pointIndex; + } + + @Override + public String getItemId() { + return pointId; + } + + @Override + public int getSeriesItemIndex() { + return seriesIndex; + } + + /** + * @return Supported only in Gantt charts: Returns the start date of the point at the moment the point was + * dropped. + */ + public Instant getStart() { + return start; + } + + /** + * @return Supported only in Gantt charts: Returns the end date of the point at the moment the point was + * dropped. + */ + public Instant getEnd() { + return end; + } + + /** + * @return Returns the parent id of the point at the moment the Drag event + * was fired. + */ + public String getParent() { + return parent; + } + + /** + * @return Returns the x value of the point at the moment the dragging + * started. + */ + public Double getxValue() { + return x; + } + + /** + * @return Returns the y value of the point at the moment the dragging + * started. + */ + public Double getyValue() { + return y; + } + +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AreaOptions.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AreaOptions.java index a891d28e840..dea4385435e 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AreaOptions.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/AreaOptions.java @@ -11,6 +11,8 @@ import java.time.Instant; import java.util.Date; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.charts.Chart; import com.vaadin.flow.component.charts.model.style.Color; public abstract class AreaOptions extends AbstractPlotOptions { @@ -764,4 +766,22 @@ public abstract void setNavigatorOptions( * @see #setPointStart(Number) */ public abstract void setPointStart(Instant instant); + + /** + * @see #setDragDrop(DragDrop) + */ + public abstract DragDrop getDragDrop(); + + /** + * The DragDrop options allows points to be moved around or modified in the + * chart. In addition to the options mentioned under the dragDrop API + * structure, the chart fires three events: dragStart, drag and drop. + * + * @see Chart#addPointDragStartListener(ComponentEventListener) + * @see Chart#addPointDragListener(ComponentEventListener) + * @see Chart#addPointDropListener(ComponentEventListener) + * @param dragDrop + */ + public abstract void setDragDrop(DragDrop dragDrop); + } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragDrop.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragDrop.java new file mode 100644 index 00000000000..cac3545e51c --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragDrop.java @@ -0,0 +1,289 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +@SuppressWarnings("unused") +public class DragDrop extends AbstractConfigurationObject { + + private Boolean draggableEnd; + private Boolean draggableStart; + private Boolean draggableX; + private Boolean draggableY; + private DragHandle dragHandle; + private Number dragMaxX; + private Number dragMaxY; + private Number dragMinX; + private Number dragMinY; + private Number dragPrecisionX; + private Number dragPrecisionY; + private Number dragSensitivity; + private String groupBy; + private GuideBox guideBox; + private Boolean liveRedraw; + + /** + * @see #setDraggableEnd(Boolean) + */ + public Boolean getDraggableEnd() { + return draggableEnd; + } + + /** + * Supported only in Gantt chart: Allow end value to be dragged + * individually. Defaults to true. + * + * @param draggableEnd + */ + public void setDraggableEnd(Boolean draggableEnd) { + this.draggableEnd = draggableEnd; + } + + /** + * @see #setDraggableStart(Boolean) + */ + public Boolean getDraggableStart() { + return draggableStart; + } + + /** + * Supported only in Gantt chart: Allow start value to be dragged + * individually. Defaults to true. + * + * @param draggableStart + */ + public void setDraggableStart(Boolean draggableStart) { + this.draggableStart = draggableStart; + } + + /** + * @see #setDraggableX(Boolean) + */ + public Boolean getDraggableX() { + return draggableX; + } + + /** + * Enable dragging in the X dimension. + * + * @param draggableX + */ + public void setDraggableX(Boolean draggableX) { + this.draggableX = draggableX; + } + + /** + * @see #setDraggableY(Boolean) + */ + public Boolean getDraggableY() { + return draggableY; + } + + /** + * Enable dragging in the Y dimension. Note that this is not supported for + * TreeGrid axes (the default axis type in Gantt charts). + * + * @param draggableY + */ + public void setDraggableY(Boolean draggableY) { + this.draggableY = draggableY; + } + + /** + * @see #setDragHandle(DragHandle) + */ + public DragHandle getDragHandle() { + if (dragHandle == null) { + dragHandle = new DragHandle(); + } + return dragHandle; + } + + /** + * Options for the drag handles. + * + * @param dragHandle + */ + public void setDragHandle(DragHandle dragHandle) { + this.dragHandle = dragHandle; + } + + /** + * @see #setDragMaxX(Number) + */ + public Number getDragMaxX() { + return dragMaxX; + } + + /** + * Set the maximum X value the points can be moved to. + * + * @param dragMaxX + */ + public void setDragMaxX(Number dragMaxX) { + this.dragMaxX = dragMaxX; + } + + /** + * @see #setDragMaxY(Number) + */ + public Number getDragMaxY() { + return dragMaxY; + } + + /** + * Set the maximum Y value the points can be moved to. + * + * @param dragMaxY + */ + public void setDragMaxY(Number dragMaxY) { + this.dragMaxY = dragMaxY; + } + + /** + * @see #setDragMinX(Number) + */ + public Number getDragMinX() { + return dragMinX; + } + + /** + * Set the minimum X value the points can be moved to. + * + * @param dragMinX + */ + public void setDragMinX(Number dragMinX) { + this.dragMinX = dragMinX; + } + + /** + * @see #setDragMinY(Number) + */ + public Number getDragMinY() { + return dragMinY; + } + + /** + * Set the minimum Y value the points can be moved to. + * + * @param dragMinY + */ + public void setDragMinY(Number dragMinY) { + this.dragMinY = dragMinY; + } + + /** + * @see #setDragPrecisionX(Number) + */ + public Number getDragPrecisionX() { + return dragPrecisionX; + } + + /** + * The X precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is + * 1. Defaults to 0. + * + * @param dragPrecisionX + */ + public void setDragPrecisionX(Number dragPrecisionX) { + this.dragPrecisionX = dragPrecisionX; + } + + /** + * @see #setDragPrecisionY(Number) + */ + public Number getDragPrecisionY() { + return dragPrecisionY; + } + + /** + * The Y precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is + * 1. Defaults to 0. + * + * @param dragPrecisionY + */ + public void setDragPrecisionY(Number dragPrecisionY) { + this.dragPrecisionY = dragPrecisionY; + } + + /** + * @see #setDragSensitivity(Number) + */ + public Number getDragSensitivity() { + return dragSensitivity; + } + + /** + * The amount of pixels to drag the pointer before it counts as a drag + * operation. This prevents drag/drop to fire when just clicking or + * selecting points. Defaults to 2. + * + * @param dragSensitivity + */ + public void setDragSensitivity(Number dragSensitivity) { + this.dragSensitivity = dragSensitivity; + } + + /** + * @see #setGroupBy(String) + */ + public String getGroupBy() { + return groupBy; + } + + /** + * Group the points by a property. Points with the same property value will + * be grouped together when moving. Defaults to undefined. + * + * @param groupBy + */ + public void setGroupBy(String groupBy) { + this.groupBy = groupBy; + } + + /** + * @see #setGuideBox(GuideBox) + */ + public GuideBox getGuideBox() { + if (guideBox == null) { + guideBox = new GuideBox(); + } + return guideBox; + } + + /** + * Style options for the guide box. The guide box has one state by default, + * the default state. Guide box is visible only when liveRedraw is false. + * + * @see #setLiveRedraw(Boolean) + * + * @param guideBox + */ + public void setGuideBox(GuideBox guideBox) { + this.guideBox = guideBox; + } + + /** + * @see #setLiveRedraw(Boolean) + */ + public Boolean getLiveRedraw() { + return liveRedraw; + } + + /** + * Update points as they are dragged. If false, a guide box is drawn to + * illustrate the new point size. Defaults to true. + * + * @param liveRedraw + */ + public void setLiveRedraw(Boolean liveRedraw) { + this.liveRedraw = liveRedraw; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragHandle.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragHandle.java new file mode 100644 index 00000000000..f96ddf71603 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/DragHandle.java @@ -0,0 +1,140 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import com.vaadin.flow.component.charts.model.style.Color; + +@SuppressWarnings("unused") +public class DragHandle extends AbstractConfigurationObject { + + private String className; + private Color color; + private String cursor; + private Color lineColor; + private Number lineWidth; + private String _fn_pathFormatter; + private Number zIndex; + + /** + * @see #setClassName(String) + */ + public String getClassName() { + return className; + } + + /** + * The class name of the drag handles. Defaults to highcharts-drag-handle. + * Defaults to highcharts-drag-handle. + * + * @param className + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * @see #setColor(Color) + */ + public Color getColor() { + return color; + } + + /** + * The fill color of the drag handles. Defaults to #fff. + * + * @param color + */ + public void setColor(Color color) { + this.color = color; + } + + /** + * @see #setCursor(String) + */ + public String getCursor() { + return cursor; + } + + /** + * The mouse cursor to use for the drag handles. By default this is + * intelligently switching between ew-resize and ns-resize depending on the + * direction the point is being dragged. + * + * @param cursor + */ + public void setCursor(String cursor) { + this.cursor = cursor; + } + + /** + * @see #setLineColor(Color) + */ + public Color getLineColor() { + return lineColor; + } + + /** + * The line color of the drag handles. Defaults to rgba(0, 0, 0, 0.6). + * + * @param lineColor + */ + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + /** + * @see #setLineWidth(Number) + */ + public Number getLineWidth() { + return lineWidth; + } + + /** + * The line width for the drag handles. Defaults to 1. + * + * @param lineWidth + */ + public void setLineWidth(Number lineWidth) { + this.lineWidth = lineWidth; + } + + /** + * @see #setzIndex(Number) + */ + public Number getzIndex() { + return zIndex; + } + + /** + * The z index for the drag handles. Defaults to 901. + * + * @param zIndex + */ + public void setzIndex(Number zIndex) { + this.zIndex = zIndex; + } + + /** + * @see #setPathFormatter(String) + */ + public String getPathFormatter() { + return _fn_pathFormatter; + } + + /** + * Function to define the SVG path to use for the drag handles. Takes the + * point as argument. Should return an SVG path in array format. The SVG + * path is automatically positioned on the point. + * + * @param _fn_pathFormatter + */ + public void setPathFormatter(String _fn_pathFormatter) { + this._fn_pathFormatter = _fn_pathFormatter; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBox.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBox.java new file mode 100644 index 00000000000..f387e1a0192 --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBox.java @@ -0,0 +1,41 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Style options for the guide box. The guide box has one state by default, the + * default state. + */ +@SuppressWarnings("unused") +public class GuideBox extends AbstractConfigurationObject { + + @JsonProperty("default") + private GuideBoxDefaultState defaultState; + + /** + * @see #setDefaultState(GuideBoxDefaultState) + */ + public GuideBoxDefaultState getDefaultState() { + if (defaultState == null) { + defaultState = new GuideBoxDefaultState(); + } + return defaultState; + } + + /** + * Style options for the guide box default state. + * + * @param defaultState + */ + public void setDefaultState(GuideBoxDefaultState defaultState) { + this.defaultState = defaultState; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBoxDefaultState.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBoxDefaultState.java new file mode 100644 index 00000000000..3a57d91735b --- /dev/null +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/GuideBoxDefaultState.java @@ -0,0 +1,118 @@ +/** + * Copyright 2000-2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.charts.model; + +import com.vaadin.flow.component.charts.model.style.Color; + +public class GuideBoxDefaultState extends AbstractConfigurationObject { + + private String className; + private Color color; + private String cursor; + private Color lineColor; + private Number lineWidth; + private Number zIndex; + + /** + * @see #setClassName(String) + */ + public String getClassName() { + return className; + } + + /** + * CSS class name of the guide box in this state. Defaults to + * highcharts-drag-box-default. Defaults to highcharts-drag-box-default. + * + * @param className + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * @see #setColor(Color) + */ + public Color getColor() { + return color; + } + + /** + * Guide box fill color. Defaults to rgba(0, 0, 0, 0.1). + * + * @param color + */ + public void setColor(Color color) { + this.color = color; + } + + /** + * @see #setCursor(String) + */ + public String getCursor() { + return cursor; + } + + /** + * Guide box cursor. Defaults to "move". + * + * @param cursor + */ + public void setCursor(String cursor) { + this.cursor = cursor; + } + + /** + * @see #setLineColor(Color) + */ + public Color getLineColor() { + return lineColor; + } + + /** + * Color of the border around the guide box. Defaults to #888. + * + * @param lineColor + */ + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + /** + * @see #setLineWidth(Number) + */ + public Number getLineWidth() { + return lineWidth; + } + + /** + * Width of the line around the guide box. Defaults to 1. + * + * @param lineWidth + */ + public void setLineWidth(Number lineWidth) { + this.lineWidth = lineWidth; + } + + /** + * @see #setzIndex(Number) + */ + public Number getzIndex() { + return zIndex; + } + + /** + * Guide box zIndex. Defaults to 900. + * + * @param zIndex + */ + public void setzIndex(Number zIndex) { + this.zIndex = zIndex; + } +} diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java index d60d1441b3f..4c5335c101f 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsGantt.java @@ -11,6 +11,8 @@ import java.util.ArrayList; import java.util.Arrays; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.charts.Chart; import com.vaadin.flow.component.charts.model.style.Color; /** @@ -38,6 +40,7 @@ public class PlotOptionsGantt extends AbstractPlotOptions { private DashStyle dashStyle; private ArrayList dataLabels; private String description; + private DragDrop dragDrop; private Boolean enableMouseTracking; private Boolean grouping; private Number groupPadding; @@ -888,4 +891,29 @@ public AbstractConfigurationObject getCustom() { public void setCustom(AbstractConfigurationObject custom) { this.custom = custom; } + + /** + * @see #setDragDrop(DragDrop) + */ + public DragDrop getDragDrop() { + if (this.dragDrop == null) { + this.dragDrop = new DragDrop(); + } + + return dragDrop; + } + + /** + * The DragDrop options allows points to be moved around or modified in the + * chart. In addition to the options mentioned under the dragDrop API + * structure, the chart fires three events: dragStart, drag and drop. + * + * @see Chart#addPointDragStartListener(ComponentEventListener) + * @see Chart#addPointDragListener(ComponentEventListener) + * @see Chart#addPointDropListener(ComponentEventListener) + * @param dragDrop + */ + public void setDragDrop(DragDrop dragDrop) { + this.dragDrop = dragDrop; + } } diff --git a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsSeries.java b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsSeries.java index 9e8451bca38..6f00432d0a0 100644 --- a/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsSeries.java +++ b/vaadin-charts-flow-parent/vaadin-charts-flow/src/main/java/com/vaadin/flow/component/charts/model/PlotOptionsSeries.java @@ -13,6 +13,8 @@ import java.util.Arrays; import java.util.Date; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.charts.Chart; import com.vaadin.flow.component.charts.model.style.Color; import com.vaadin.flow.component.charts.util.Util; @@ -39,6 +41,7 @@ public class PlotOptionsSeries extends AbstractPlotOptions { private DashStyle dashStyle; private DataLabels dataLabels; private String description; + private DragDrop dragDrop; private Boolean enableMouseTracking; private Boolean exposeElementToA11y; private Dimension findNearestPointBy; @@ -1310,4 +1313,29 @@ public void setPointStart(Date date) { public void setPointStart(Instant instant) { this.pointStart = Util.toHighchartsTS(instant); } + + /** + * @see #setDragDrop(DragDrop) + */ + public DragDrop getDragDrop() { + if (this.dragDrop == null) { + this.dragDrop = new DragDrop(); + } + + return dragDrop; + } + + /** + * The DragDrop options allows points to be moved around or modified in the + * chart. In addition to the options mentioned under the dragDrop API + * structure, the chart fires three events: dragStart, drag and drop. + * + * @see Chart#addPointDragStartListener(ComponentEventListener) + * @see Chart#addPointDragListener(ComponentEventListener) + * @see Chart#addPointDropListener(ComponentEventListener) + * @param dragDrop + */ + public void setDragDrop(DragDrop dragDrop) { + this.dragDrop = dragDrop; + } }