View Javadoc
1   /*
2    * Tethys: GUI Utilities
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.tethys.core.chart;
18  
19  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
20  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimalFormatter;
21  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
22  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
23  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
24  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
25  import io.github.tonywasher.joceanus.tethys.api.chart.TethysUIAreaChart;
26  import io.github.tonywasher.joceanus.tethys.core.base.TethysUICoreComponent;
27  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
28  
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.LinkedHashMap;
32  import java.util.Map;
33  
34  /**
35   * Area Chart.
36   * <p>
37   * The EventProvider fires the following events.
38   * <ul>
39   *    <li>TethysUIEvent.PRESSED is fired when a series is selected
40   * </ul>
41   */
42  public abstract class TethysUICoreAreaChart
43          extends TethysUICoreComponent
44          implements TethysUIAreaChart {
45      /**
46       * The angle for labels.
47       */
48      protected static final int LABEL_ANGLE = -45;
49  
50      /**
51       * The formatter.
52       */
53      private final OceanusDecimalFormatter theFormatter;
54  
55      /**
56       * The id.
57       */
58      private final Integer theId;
59  
60      /**
61       * The Event Manager.
62       */
63      private final OceanusEventManager<TethysUIEvent> theEventManager;
64  
65      /**
66       * The sectionMap.
67       */
68      private final Map<String, TethysUIAreaChartSeries> theSeriesMap;
69  
70      /**
71       * Constructor.
72       *
73       * @param pFactory the Gui Factory
74       */
75      protected TethysUICoreAreaChart(final TethysUICoreFactory<?> pFactory) {
76          /* Build standard fields */
77          theId = pFactory.getNextId();
78          theEventManager = new OceanusEventManager<>();
79          theFormatter = pFactory.getDataFormatter().getDecimalFormatter();
80  
81          /* Create the section map */
82          theSeriesMap = new HashMap<>();
83      }
84  
85      @Override
86      public Integer getId() {
87          return theId;
88      }
89  
90      @Override
91      public OceanusEventRegistrar<TethysUIEvent> getEventRegistrar() {
92          return theEventManager.getEventRegistrar();
93      }
94  
95      /**
96       * Obtain the formatter.
97       *
98       * @return the formatter
99       */
100     protected OceanusDecimalFormatter getFormatter() {
101         return theFormatter;
102     }
103 
104     @Override
105     public void updateAreaChart(final TethysUIAreaChartData pData) {
106         /* clear the data */
107         resetData();
108 
109         /* Iterate through the sections */
110         final Iterator<TethysUIAreaChartSeries> myIterator = pData.seriesIterator();
111         while (myIterator.hasNext()) {
112             final TethysUIAreaChartSeries myBase = myIterator.next();
113             final String myKey = myBase.getName();
114             theSeriesMap.put(myKey, myBase);
115 
116             /* Iterate through the sections */
117             final Iterator<TethysUIAreaChartDataPoint> myPointIterator = myBase.pointIterator();
118             while (myPointIterator.hasNext()) {
119                 final TethysUIAreaChartDataPoint myPoint = myPointIterator.next();
120 
121                 /* Add the section */
122                 createPoint(myKey, myPoint);
123             }
124         }
125     }
126 
127     /**
128      * Reset chart data.
129      */
130     protected void resetData() {
131         /* Clear existing data  */
132         theSeriesMap.clear();
133     }
134 
135     /**
136      * Add chart point.
137      *
138      * @param pName  the name of the series
139      * @param pPoint the point to add
140      */
141     protected abstract void createPoint(String pName,
142                                         TethysUIAreaChartDataPoint pPoint);
143 
144     /**
145      * Obtain tooltip for series.
146      *
147      * @param pName  the series name
148      * @param pValue the value
149      * @return the tooltip
150      */
151     protected String getToolTip(final String pName,
152                                 final OceanusMoney pValue) {
153         return pName + " = " + theFormatter.formatMoney(pValue);
154     }
155 
156     /**
157      * handle selection.
158      *
159      * @param pName the series name
160      */
161     protected void selectSeries(final String pName) {
162         final TethysUIAreaChartSeries mySeries = theSeriesMap.get(pName);
163         theEventManager.fireEvent(TethysUIEvent.PRESSED, mySeries);
164     }
165 
166     /**
167      * AreaChart Data.
168      */
169     public static final class TethysUICoreAreaChartData
170             implements TethysUIAreaChartData {
171         /**
172          * The XAxis default label.
173          */
174         static final String XAXIS_LABEL = "Date";
175 
176         /**
177          * The XAxis default label.
178          */
179         static final String YAXIS_LABEL = "Value";
180 
181         /**
182          * The SeriesMap.
183          */
184         private final Map<String, TethysUIAreaChartSeries> theSeriesMap;
185 
186         /**
187          * The Chart Title.
188          */
189         private final String theTitle;
190 
191         /**
192          * The Chart XAxisLabel.
193          */
194         private String theXAxisLabel;
195 
196         /**
197          * The Chart YAxisLabel.
198          */
199         private String theYAxisLabel;
200 
201         /**
202          * Constructor.
203          *
204          * @param pTitle the title
205          */
206         TethysUICoreAreaChartData(final String pTitle) {
207             this(pTitle, XAXIS_LABEL, YAXIS_LABEL);
208         }
209 
210         /**
211          * Constructor.
212          *
213          * @param pTitle      the title
214          * @param pXAxisLabel the XAxis label
215          * @param pYAxisLabel the YAxis label
216          */
217         private TethysUICoreAreaChartData(final String pTitle,
218                                           final String pXAxisLabel,
219                                           final String pYAxisLabel) {
220             /* Store parameters */
221             theTitle = pTitle;
222             theXAxisLabel = pXAxisLabel;
223             theYAxisLabel = pYAxisLabel;
224 
225             /* Create map */
226             theSeriesMap = new LinkedHashMap<>();
227         }
228 
229         @Override
230         public TethysUIAreaChartData setXAxisLabel(final String pLabel) {
231             theXAxisLabel = pLabel;
232             return this;
233         }
234 
235         @Override
236         public TethysUIAreaChartData setYAxisLabel(final String pLabel) {
237             theYAxisLabel = pLabel;
238             return this;
239         }
240 
241         @Override
242         public String getTitle() {
243             return theTitle;
244         }
245 
246         @Override
247         public String getXAxisLabel() {
248             return theXAxisLabel;
249         }
250 
251         @Override
252         public String getYAxisLabel() {
253             return theYAxisLabel;
254         }
255 
256         @Override
257         public Iterator<TethysUIAreaChartSeries> seriesIterator() {
258             return theSeriesMap.values().iterator();
259         }
260 
261         @Override
262         public TethysUIAreaChartSeries createSeries(final String pName,
263                                                     final Object pSource) {
264             final TethysUIAreaChartSeries mySeries = new TethysUICoreAreaChartSeries(pName, pSource);
265             theSeriesMap.put(pName, mySeries);
266             return mySeries;
267         }
268     }
269 
270     /**
271      * The Series definition.
272      */
273     public static final class TethysUICoreAreaChartSeries
274             implements TethysUIAreaChartSeries {
275         /**
276          * The name of the series.
277          */
278         private final String theName;
279 
280         /**
281          * The source of the series.
282          */
283         private final Object theSource;
284 
285         /**
286          * The pointMap of the series.
287          */
288         private final Map<OceanusDate, TethysUIAreaChartDataPoint> thePointMap;
289 
290         /**
291          * Constructor.
292          *
293          * @param pName   the name
294          * @param pSource the source
295          */
296         TethysUICoreAreaChartSeries(final String pName,
297                                     final Object pSource) {
298             theName = pName;
299             theSource = pSource;
300             thePointMap = new HashMap<>();
301         }
302 
303         @Override
304         public void addPoint(final OceanusDate pDate,
305                              final OceanusMoney pValue) {
306             thePointMap.put(pDate, new TethysUICoreAreaChartDataPoint(this, pDate, pValue));
307         }
308 
309         @Override
310         public String getName() {
311             return theName;
312         }
313 
314         @Override
315         public Iterator<TethysUIAreaChartDataPoint> pointIterator() {
316             return thePointMap.values().iterator();
317         }
318 
319         @Override
320         public Object getSource() {
321             return theSource;
322         }
323     }
324 
325     /**
326      * The Data Point definition.
327      */
328     public static final class TethysUICoreAreaChartDataPoint
329             implements TethysUIAreaChartDataPoint {
330         /**
331          * The series of the point.
332          */
333         private final TethysUIAreaChartSeries theSeries;
334 
335         /**
336          * The date of the point.
337          */
338         private final OceanusDate theDate;
339 
340         /**
341          * The value of the point.
342          */
343         private final OceanusMoney theValue;
344 
345         /**
346          * Constructor.
347          *
348          * @param pSeries the series
349          * @param pDate   the date
350          * @param pValue  the value
351          */
352         TethysUICoreAreaChartDataPoint(final TethysUIAreaChartSeries pSeries,
353                                        final OceanusDate pDate,
354                                        final OceanusMoney pValue) {
355             theSeries = pSeries;
356             theDate = pDate;
357             theValue = pValue;
358         }
359 
360         @Override
361         public TethysUIAreaChartSeries getSeries() {
362             return theSeries;
363         }
364 
365         @Override
366         public OceanusDate getDate() {
367             return theDate;
368         }
369 
370         @Override
371         public OceanusMoney getValue() {
372             return theValue;
373         }
374     }
375 }