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.swing.chart;
18  
19  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
20  import io.github.tonywasher.joceanus.tethys.core.chart.TethysUICoreBarChart;
21  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
22  import io.github.tonywasher.joceanus.tethys.swing.base.TethysUISwingNode;
23  import org.jfree.chart.ChartFactory;
24  import org.jfree.chart.ChartMouseEvent;
25  import org.jfree.chart.ChartMouseListener;
26  import org.jfree.chart.ChartPanel;
27  import org.jfree.chart.JFreeChart;
28  import org.jfree.chart.axis.CategoryAxis;
29  import org.jfree.chart.axis.NumberAxis;
30  import org.jfree.chart.entity.CategoryItemEntity;
31  import org.jfree.chart.entity.ChartEntity;
32  import org.jfree.chart.plot.CategoryPlot;
33  import org.jfree.chart.plot.PlotOrientation;
34  import org.jfree.chart.renderer.category.CategoryItemRenderer;
35  import org.jfree.chart.util.HexNumberFormat;
36  import org.jfree.data.category.DefaultCategoryDataset;
37  
38  import java.io.Serial;
39  import java.text.FieldPosition;
40  
41  /**
42   * Swing BarChart.
43   */
44  public class TethysUISwingBarChart
45          extends TethysUICoreBarChart {
46      /**
47       * The Node.
48       */
49      private final TethysUISwingNode theNode;
50  
51      /**
52       * The dataSet.
53       */
54      private final DefaultCategoryDataset theDataSet;
55  
56      /**
57       * The chart.
58       */
59      private final JFreeChart theChart;
60  
61      /**
62       * The panel.
63       */
64      private final ChartPanel thePanel;
65  
66      /**
67       * Constructor.
68       *
69       * @param pFactory the Gui Factory
70       */
71      TethysUISwingBarChart(final TethysUICoreFactory<?> pFactory) {
72          /* Initialise underlying class */
73          super(pFactory);
74  
75          /* Create the dataSet */
76          theDataSet = new DefaultCategoryDataset();
77  
78          /* Create the chart */
79          theChart = ChartFactory.createStackedBarChart(
80                  null,
81                  null,
82                  null,
83                  theDataSet,
84                  PlotOrientation.VERTICAL,
85                  true,
86                  true,
87                  false);
88          final CategoryPlot myPlot = (CategoryPlot) theChart.getPlot();
89          final CategoryItemRenderer myRenderer = myPlot.getRenderer();
90          myRenderer.setDefaultToolTipGenerator((pDataset, pSeries, pItem) -> {
91              final String myKey = pDataset.getRowKey(pSeries) + ":" + pDataset.getColumnKey(pItem);
92              return getToolTip(myKey);
93          });
94          final NumberAxis myYAxis = (NumberAxis) myPlot.getRangeAxis();
95          myYAxis.setNumberFormatOverride(new MoneyFormat());
96  
97          /* Create the panel */
98          thePanel = new ChartPanel(theChart);
99          thePanel.setOpaque(true);
100         thePanel.addChartMouseListener(new ChartMouseListener() {
101             @Override
102             public void chartMouseMoved(final ChartMouseEvent e) {
103                 /* NoOp */
104             }
105 
106             @Override
107             public void chartMouseClicked(final ChartMouseEvent e) {
108                 final ChartEntity entity = e.getEntity();
109                 if (entity instanceof CategoryItemEntity section) {
110                     selectSection(section.getRowKey() + ":" + section.getColumnKey());
111                 }
112             }
113         });
114 
115         /* Create the node */
116         theNode = new TethysUISwingNode(thePanel);
117     }
118 
119     @Override
120     public TethysUISwingNode getNode() {
121         return theNode;
122     }
123 
124     @Override
125     public void setVisible(final boolean pVisible) {
126         theNode.setVisible(pVisible);
127     }
128 
129     @Override
130     public void setEnabled(final boolean pEnabled) {
131         thePanel.setEnabled(pEnabled);
132     }
133 
134     @Override
135     public void setPreferredWidth(final Integer pWidth) {
136         theNode.setPreferredWidth(pWidth);
137     }
138 
139     @Override
140     public void setPreferredHeight(final Integer pHeight) {
141         theNode.setPreferredHeight(pHeight);
142     }
143 
144     @Override
145     public void updateBarChart(final TethysUIBarChartData pData) {
146         /* Update underlying data */
147         super.updateBarChart(pData);
148 
149         /* Set the chart title and Axis labels */
150         theChart.setTitle(pData.getTitle());
151         final CategoryPlot myPlot = (CategoryPlot) theChart.getPlot();
152         final CategoryAxis myXAxis = myPlot.getDomainAxis();
153         myXAxis.setLabel(pData.getXAxisLabel());
154         final NumberAxis myYAxis = (NumberAxis) myPlot.getRangeAxis();
155         myYAxis.setLabel(pData.getYAxisLabel());
156 
157         /* Declare changes */
158         theChart.fireChartChanged();
159     }
160 
161     @Override
162     protected void resetData() {
163         /* Clear existing data  */
164         theDataSet.clear();
165 
166         /* Clear underlying data  */
167         super.resetData();
168     }
169 
170     @Override
171     protected void createSection(final String pName,
172                                  final TethysUIBarChartDataSection pSection) {
173         /* Create section */
174         theDataSet.addValue(pSection.getValue().doubleValue(), pName, pSection.getReference());
175 
176         /* Add to underlying data  */
177         super.createSection(pName, pSection);
178     }
179 
180     /**
181      * Money Format class.
182      */
183     private final class MoneyFormat extends HexNumberFormat {
184         @Serial
185         private static final long serialVersionUID = -1151614975043008941L;
186 
187         @Override
188         public StringBuffer format(final double pValue,
189                                    final StringBuffer pBuffer,
190                                    final FieldPosition pLoc) {
191             final OceanusMoney myMoney = new OceanusMoney(Double.toString(pValue));
192             return new StringBuffer(getFormatter().formatMoney(myMoney));
193         }
194     }
195 }