I am trying to create a chart program using a view model. Using JGoodies to bind data was relatively simple for simple types such as strings or numbers. But I canβt figure out how to use it on a hash map.
I will try to explain how the diagram works and what is my problem:
The chart consists of DataSeries, DataSeries consists of DataPoints. I want to have a data model and be able to use different views in the same model (for example, a histogram, a pie chart, ...). Each of them consists of three classes.
For instance:
DataPointModel: contains the data model (value, label, category) DataPointViewModel: extends the JMoodies PresentationModel. wraps a DataPointModel and preserves view properties such as font and color. DataPoint: an abstract class that extends JComponent. Different views must subclass and implement their own ui.
Linking and creating a data model was easy, but I don't know how to bind a data series model.
package at.onscreen.chart; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.PropertyVetoException; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; public class DataSeriesModel { public static String PROPERTY_DATAPOINT = "dataPoint"; public static String PROPERTY_DATAPOINTS = "dataPoints"; public static String PROPERTY_LABEL = "label"; public static String PROPERTY_MAXVALUE = "maxValue"; private HashMap<String, DataPoint> dataPoints; private String label; private Double maxValue; private PropertyChangeSupport propertyChangeSupport; public DataSeriesModel() { this.maxValue = Double.valueOf(0); this.dataPoints = new HashMap<String, DataPoint>(); this.propertyChangeSupport = new PropertyChangeSupport(this); } public DataSeriesModel(String label) { this.dataPoints = new HashMap<String, DataPoint>(); this.maxValue = Double.valueOf(0); this.label = label; this.propertyChangeSupport = new PropertyChangeSupport(this); } public DataSeriesModel(String label, DataPoint[] dataPoints) { this.dataPoints = new HashMap<String, DataPoint>(); this.propertyChangeSupport = new PropertyChangeSupport(this); this.maxValue = Double.valueOf(0); this.label = label; for (int i = 0; i < dataPoints.length; i++) { this.addDataPoint(dataPoints[i]); } } public DataSeriesModel(String label, Collection<DataPoint> dataPoints) { this.dataPoints = new HashMap<String, DataPoint>(); this.propertyChangeSupport = new PropertyChangeSupport(this); this.maxValue = Double.valueOf(0); this.label = label; for (Iterator<DataPoint> it = dataPoints.iterator(); it.hasNext();) { this.addDataPoint(it.next()); } } public void addDataPoint(DataPoint dataPoint) { String category = dataPoint.getCategory(); DataPoint oldDataPoint = this.getDataPoint(category); this.dataPoints.put(category, dataPoint); this.setMaxValue(Math.max(this.maxValue, dataPoint.getValue())); this.propertyChangeSupport.firePropertyChange(PROPERTY_DATAPOINT, oldDataPoint, dataPoint); } public DataPoint getDataPoint(String category) { return this.dataPoints.get(category); } public void removeDataPoint(String category) { DataPoint dataPoint = this.getDataPoint(category); this.dataPoints.remove(category); if (dataPoint != null) { if (dataPoint.getValue() == this.getMaxValue()) { Double maxValue = Double.valueOf(0); for (Iterator<DataPoint> it = this.iterator(); it.hasNext();) { DataPoint itDataPoint = it.next(); maxValue = Math.max(itDataPoint.getValue(), maxValue); } this.setMaxValue(maxValue); } } this.propertyChangeSupport.firePropertyChange(PROPERTY_DATAPOINT, dataPoint, null); } public void removeAll() { this.setMaxValue(Double.valueOf(0)); this.dataPoints.clear(); this.propertyChangeSupport.firePropertyChange(PROPERTY_DATAPOINTS, this.getDataPoints(), null); } public Double getMaxValue() { return this.maxValue; } protected void setMaxValue(Double maxValue) { Double oldMaxValue = this.getMaxValue(); this.maxValue = maxValue; this.propertyChangeSupport.firePropertyChange(PROPERTY_MAXVALUE, oldMaxValue, maxValue); } public boolean contains(String category) { return this.dataPoints.containsKey(category); } public String getLabel() { return this.label; } public Iterator<DataPoint> iterator() { return this.dataPoints.values().iterator(); } public Collection<DataPoint> getDataPoints() { return this.dataPoints.values(); } public int getSize() { return this.dataPoints.size(); } public void addPropertyChangeListener(PropertyChangeListener listener) { this.propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { this.propertyChangeSupport.removePropertyChangeListener(listener); } } package at.onscreen.chart; import java.beans.PropertyVetoException; import java.util.Collection; import java.util.Iterator; import com.jgoodies.binding.PresentationModel; public class DataSeriesViewModel extends PresentationModel<DataSeriesModel> { public DataSeriesViewModel() { super(new DataSeriesModel()); } public DataSeriesViewModel(String label) { super(new DataSeriesModel(label)); } public DataSeriesViewModel(String label, DataPoint[] dataPoints) { super(new DataSeriesModel(label, dataPoints)); } public DataSeriesViewModel(String label, Collection<DataPoint> dataPoints) { super(new DataSeriesModel(label, dataPoints)); } public DataSeriesViewModel(DataSeriesModel model) { super(model); } public void addDataPoint(DataPoint dataPoint) { this.getBean().addDataPoint(dataPoint); } public boolean contains(String category) { return this.getBean().contains(category); } public DataPoint getDataPoint(String category) { return this.getBean().getDataPoint(category); } public Collection<DataPoint> getDataPoints() { return this.getBean().getDataPoints(); } public String getLabel() { return this.getBean().getLabel(); } public Double getMaxValue() { return this.getBean().getMaxValue(); } public int getSize() { return this.getBean().getSize(); } public Iterator<DataPoint> iterator() { return this.getBean().iterator(); } public void removeAll() { this.getBean().removeAll(); } public void removeDataPoint(String category) { this.getBean().removeDataPoint(category); } } package at.onscreen.chart; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.util.Collection; import java.util.Iterator; import javax.swing.JComponent; public abstract class DataSeries extends JComponent implements PropertyChangeListener { private DataSeriesViewModel model; public DataSeries() { this.model = new DataSeriesViewModel(); this.model.addPropertyChangeListener(this); this.createComponents(); } public DataSeries(String label) { this.model = new DataSeriesViewModel(label); this.model.addPropertyChangeListener(this); this.createComponents(); } public DataSeries(String label, DataPoint[] dataPoints) { this.model = new DataSeriesViewModel(label, dataPoints); this.model.addPropertyChangeListener(this); this.createComponents(); } public DataSeries(String label, Collection<DataPoint> dataPoints) { this.model = new DataSeriesViewModel(label, dataPoints); this.model.addPropertyChangeListener(this); this.createComponents(); } public DataSeries(DataSeriesViewModel model) { this.model = model; this.model.addPropertyChangeListener(this); this.createComponents(); } protected abstract void createComponents(); @Override public void propertyChange(PropertyChangeEvent evt) { this.repaint(); } public void addDataPoint(DataPoint dataPoint) { this.model.addDataPoint(dataPoint); } public boolean contains(String category) { return this.model.contains(category); } public DataPoint getDataPoint(String category) { return this.model.getDataPoint(category); } public Collection<DataPoint> getDataPoints() { return this.model.getDataPoints(); } public String getLabel() { return this.model.getLabel(); } public Double getMaxValue() { return this.model.getMaxValue(); } public int getDataPointCount() { return this.model.getSize(); } public Iterator<DataPoint> iterator() { return this.model.iterator(); } public void removeAll() { this.model.removeAll(); } public void removeDataPoint(String category) { this.model.removeDataPoint(category); } public DataSeriesViewModel getViewModel() { return this.model; } public DataSeriesModel getModel() { return this.model.getBean(); } } package at.onscreen.chart.builder; import java.util.Collection; import net.miginfocom.swing.MigLayout; import at.onscreen.chart.DataPoint; import at.onscreen.chart.DataSeries; import at.onscreen.chart.DataSeriesViewModel; public class BuilderDataSeries extends DataSeries { public BuilderDataSeries() { super(); } public BuilderDataSeries(String label) { super(label); } public BuilderDataSeries(String label, DataPoint[] dataPoints) { super(label, dataPoints); } public BuilderDataSeries(String label, Collection<DataPoint> dataPoints) { super(label, dataPoints); } public BuilderDataSeries(DataSeriesViewModel model) { super(model); } @Override protected void createComponents() { this.setLayout(new MigLayout()); } } package at.onscreen.chart.builder; import javax.swing.JFormattedTextField; import javax.swing.JTextField; import at.onscreen.chart.DataPoint; import at.onscreen.chart.DataPointModel; import at.onscreen.chart.DataPointViewModel; import at.onscreen.chart.ValueFormat; import com.jgoodies.binding.adapter.BasicComponentFactory; import com.jgoodies.binding.beans.BeanAdapter; public class BuilderDataPoint extends DataPoint { public BuilderDataPoint() { super(); } public BuilderDataPoint(String category) { super(category); } public BuilderDataPoint(Double value, String label, String category) { super(value, label, category); } public BuilderDataPoint(DataPointViewModel model) { super(model); } @Override protected void createComponents() { BeanAdapter<DataPointModel> beanAdapter = new BeanAdapter<DataPointModel>(this.getModel(), true); ValueFormat format = new ValueFormat(); JFormattedTextField value = BasicComponentFactory.createFormattedTextField(beanAdapter.getValueModel(DataPointModel.PROPERTY_VALUE), format); this.add(value, "w 80, growx, wrap"); JTextField label = BasicComponentFactory.createTextField(beanAdapter.getValueModel(DataPointModel.PROPERTY_LABEL)); this.add(label, "growx, wrap"); JTextField category = BasicComponentFactory.createTextField(beanAdapter.getValueModel(DataPointModel.PROPERTY_CATEGORY)); this.add(category, "growx, wrap"); } }
To summarize: I need to know how to associate a hash map property with a JComponent.components property. JGoodies, in my opinion, is not very well documented, I searched the Internet for a long time, but I did not find a solution to my problem.
I hope you help me.