-
Notifications
You must be signed in to change notification settings - Fork 23
/
FormControl.java
274 lines (247 loc) · 8.73 KB
/
FormControl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
package uk.ac.starlink.topcat.plot2;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import uk.ac.starlink.topcat.ActionForwarder;
import uk.ac.starlink.topcat.AuxWindow;
import uk.ac.starlink.topcat.RowSubset;
import uk.ac.starlink.topcat.TopcatModel;
import uk.ac.starlink.ttools.plot.Style;
import uk.ac.starlink.ttools.plot2.DataGeom;
import uk.ac.starlink.ttools.plot2.PlotLayer;
import uk.ac.starlink.ttools.plot2.Plotter;
import uk.ac.starlink.ttools.plot2.ReportMap;
import uk.ac.starlink.ttools.plot2.config.ConfigKey;
import uk.ac.starlink.ttools.plot2.config.ConfigMap;
import uk.ac.starlink.ttools.plot2.data.DataSpec;
/**
* Control for providing coordinate and configuration information
* additional to base position coords and config.
* Combining the information gathered from this control with
* base config and coords provides enough to generate a PlotLayer.
*
* @author Mark Taylor
* @since 15 Mar 2013
*/
public abstract class FormControl implements Control {
private final ActionForwarder forwarder_;
private final Configger baseConfigger_;
private SubsetConfigManager subManager_;
private FormStylePanel stylePanel_;
private JComponent panel_;
private ConfigStyler styler_;
private ReportPanel reportPanel_;
/**
* Constructor.
*
* @param baseConfigger provides global configuration info
*/
protected FormControl( Configger baseConfigger ) {
forwarder_ = new ActionForwarder();
baseConfigger_ = baseConfigger;
}
/**
* Returns the panel into which the user enters additional coordinate
* information required for this control, if any.
*
* @return coordinate entry panel
*/
protected abstract JComponent getCoordPanel();
/**
* Returns the Plotter object which generates plot layers from the
* information provided by this control
*
* @return plotter
*/
protected abstract Plotter<?> getPlotter();
/**
* Returns the keys defining the additional configuration required
* by this control.
*
* @return config keys
*/
protected abstract ConfigKey[] getConfigKeys();
public JComponent getPanel() {
if ( panel_ == null ) {
panel_ = new JPanel( new BorderLayout() );
panel_.add( getCoordPanel(), BorderLayout.NORTH );
if ( hasReports() ) {
reportPanel_ = new ReportPanel();
reportPanel_.setBorder( AuxWindow
.makeTitledBorder( "Report" ) );
panel_.add( reportPanel_, BorderLayout.SOUTH );
}
}
return panel_;
}
/**
* Returns this component's ConfigStyler.
*
* @return config styler
*/
private synchronized ConfigStyler getStyler() {
/* Constructed lazily because it needs the component. */
if ( styler_ == null ) {
styler_ = new ConfigStyler( getPanel() );
}
return styler_;
}
/**
* Returns the data and metadata for the additional coordinates
* entered by the user in this control.
* If these constitute insufficient information to generate a plot
* (not all required coords have been filled in), null is returned.
*
* @return extra coordinate information, or null if incomplete
*/
public abstract GuiCoordContent[] getExtraCoordContents();
/**
* Returns the additional configuration entered by the user in
* this control.
*
* @return extra config information
*/
public abstract ConfigMap getExtraConfig();
/**
* Configures this control for use with a given TopcatModel.
* The subset manager is supplied as well to provide subset-specific
* configuration defaults.
*
* @param tcModel topcat model
* @param subManager subset manager with info about the row subsets
* for <code>tcModel</code>
*/
public void setTable( TopcatModel tcModel,
SubsetConfigManager subManager ) {
JComponent panel = getPanel();
/* Clear out an old style panel if there was one. */
if ( stylePanel_ != null ) {
stylePanel_.removeActionListener( forwarder_ );
panel.remove( stylePanel_ );
}
/* Add a new style panel if the table is non-null. */
if ( tcModel != null ) {
Factory<Plotter> plotterFact = new Factory<Plotter>() {
public Plotter getItem() {
return FormControl.this.getPlotter();
}
};
/* If any of the config keys are supplied by the base configger,
* don't acquire them from the layer style panel. */
List<ConfigKey> klist = new ArrayList<ConfigKey>();
klist.addAll( Arrays.asList( getConfigKeys() ) );
klist.removeAll( baseConfigger_.getConfig().keySet() );
ConfigKey[] keys = klist.toArray( new ConfigKey[ 0 ] );
FormStylePanel sp =
new FormStylePanel( keys, baseConfigger_, plotterFact,
subManager, tcModel );
if ( stylePanel_ != null ) {
sp.configureFrom( stylePanel_ );
}
stylePanel_ = sp;
stylePanel_.addActionListener( forwarder_ );
panel.add( stylePanel_, BorderLayout.CENTER );
}
else {
stylePanel_ = null;
}
/* Install the subset manager and table. */
subManager_ = subManager;
setTable( tcModel );
}
/**
* Performs implementation-specific configuration of this control
* for a given TopcatModel.
*
* @param tcModel new topcat model to install
*/
protected abstract void setTable( TopcatModel tcModel );
/**
* Returns the style panel currently in use.
*
* @return style panel
*/
public FormStylePanel getStylePanel() {
return stylePanel_;
}
/**
* Creates a plot layer given the current state of this control and
* some additional information.
*
* @param geom data position geometry
* @param dataSpec data specification, which must contain any data
* required by this control's extra coords and be
* set up for the given subset
* @param subset row subset in the current table for which the
* layer is to be plotted
* @return new plot layer, may be null in case of incorrect GUI config
*/
public PlotLayer createLayer( DataGeom geom, DataSpec dataSpec,
RowSubset subset ) {
ConfigMap config = stylePanel_.getConfig( subset );
config.putAll( getExtraConfig() );
return getStyler().createLayer( getPlotter(), geom, dataSpec, config );
}
/**
* Returns an object which will forward actions to listeners registered
* with this panel.
*
* @return action forwarder
*/
public ActionListener getActionForwarder() {
return forwarder_;
}
/**
* Adds a listener to be messaged when the state of this control
* changes in a way which might affect the plot layer it would create.
*
* @param listener listener to add
*/
public void addActionListener( ActionListener listener ) {
forwarder_.addActionListener( listener );
}
/**
* Removes a previously added listener.
*
* @param listener to remove
*/
public void removeActionListener( ActionListener listener ) {
forwarder_.removeActionListener( listener );
}
public String getControlLabel() {
return getPlotter().getPlotterName();
}
public Icon getControlIcon() {
return getPlotter().getPlotterIcon();
}
/**
* Indicates whether this control is willing to accept plot reports.
*
* @return true if it's OK to call <code>submitReports</code>
*/
public boolean hasReports() {
return getPlotter().hasReports();
}
/**
* Accepts plot reports generated by plotting layers.
* The supplied map is indexed by RowSubset, and should contain
* only general-interest entries which relate to plots generated
* by this control.
*
* @param reports map of row subsets to plot reports
*/
public void submitReports( Map<RowSubset,ReportMap> reports ) {
if ( reportPanel_ != null ) {
reportPanel_.submitReports( reports );
}
else {
throw new UnsupportedOperationException();
}
}
}