001 /*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2013
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 *
010 * All Rights Reserved
011 *
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.
014 *
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 *
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023 * GNU Lesser Public License for more details.
024 *
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program. If not, see http://www.gnu.org/licenses.
027 */
028
029 package edu.wisc.ssec.mcidasv.chooser;
030
031
032 import ucar.unidata.idv.*;
033
034 import ucar.unidata.ui.ChooserList;
035 import ucar.unidata.ui.ChooserPanel;
036
037 import java.awt.*;
038 import java.awt.event.*;
039
040 import java.util.Vector;
041
042 import java.beans.*;
043
044 import javax.swing.*;
045 import javax.swing.border.*;
046 import javax.swing.event.*;
047
048 import ucar.unidata.util.GuiUtils;
049 import ucar.unidata.util.Misc;
050 import ucar.unidata.util.PreferenceList;
051
052 /**
053 *
054 * @author Unidata IDV Development Team
055 * @version $Revision$
056 */
057 public abstract class FrameChooser extends ChooserPanel {
058
059 /** Property for new data selection */
060 public static String NEW_SELECTION = "FrameChooser.NEW_SELECTION";
061
062 /** Have connected */
063 protected static final int STATE_CONNECTED = 2;
064
065 /** flag for ignoring combobox changes */
066 protected boolean ignoreStateChangedEvents = false;
067
068 /**
069 * Public keys for frame numbers, request, and data name.
070 */
071 public final static String FRAME_NUMBERS_KEY = "frame numbers";
072 public final static String DATA_NAME_KEY = "data name";
073 public final static String REQUEST_HOST = "host";
074 public final static String REQUEST_PORT = "port";
075 public final static String REQUEST_KEY = "key";
076
077 /** Used to synchronize access to widgets (eg: disabling, setting state, etc). */
078 protected Object WIDGET_MUTEX = new Object();
079
080 /** frames list */
081 private ChooserList framesList;
082
083 /** Keep track of when are are doing a frame loop */
084 private boolean doLoop = false;
085
086 /** Frame loop radio button */
087 private JRadioButton loopRB;
088
089 /** Refresh current frame radio button */
090 private JRadioButton curRB;
091
092 /**
093 * Create me.
094 */
095 public FrameChooser() {}
096
097 /**
098 * Handle when the user presses the update button
099 *
100 * @throws Exception _more_
101 */
102 public void handleUpdate() throws Exception {}
103
104 /**
105 * Handle when the user presses the update button
106 */
107 public void handleUpdateFromThread() {
108 showWaitCursor();
109 try {
110 handleUpdate();
111 } catch (Exception exc) {
112 }
113 showNormalCursor();
114 }
115
116 /**
117 * Update the selector. Call handleUpdate in a thread
118 */
119 public final void doUpdate() {
120 Misc.run(this, "handleUpdateFromThread");
121 }
122
123 /**
124 * Handle the event
125 *
126 * @param ae The event
127 */
128 public void actionPerformed(ActionEvent ae) {
129 String cmd = ae.getActionCommand();
130 super.actionPerformed(ae);
131 }
132
133 /**
134 * Disable/enable any components that depend on the server.
135 * Try to update the status labelwith what we know here.
136 */
137 protected void updateStatus() {
138 setHaveData(getGoodToGo());
139 }
140
141 /**
142 * Are there any times in the times list.
143 *
144 * @return Do we have any times at all.
145 */
146 protected boolean haveAnyTimes() {
147 return framesList.getModel().getSize() > 0;
148 }
149
150 /**
151 * Are there more than one times in the times list.
152 *
153 * @return Do we have a series.
154 */
155 protected boolean haveASeries() {
156 Object[] selectedTimes = getTimesList().getSelectedValues();
157 return selectedTimes.length > 1;
158 }
159
160 /**
161 * Create (if needed) and return the list that shows frames.
162 *
163 * @return The frames list.
164 */
165 public ChooserList getTimesList() {
166 if (framesList == null) {
167 framesList = new ChooserList();
168 framesList.setVisibleRowCount(getTimesListSize());
169 framesList.addListSelectionListener(new ListSelectionListener() {
170 public void valueChanged(ListSelectionEvent e) {
171 updateStatus();
172 }
173 });
174 }
175 return framesList;
176 }
177
178 /**
179 * Get the size of the times list
180 *
181 * @return the times list size
182 */
183 protected int getTimesListSize() {
184 return 6;
185 }
186
187 /**
188 * Clear all times in the times list.
189 */
190 protected void clearFramesList() {
191 getTimesList().setListData(new Vector());
192 }
193
194 /**
195 * Do what needs to be done to read in the times. Subclasses
196 * need to implement this.
197 */
198 protected abstract void readFrames();
199
200 /**
201 * Are we all set to load data.
202 *
203 * @return All set to load.
204 */
205 protected boolean getGoodToGo() {
206 if ( !haveFrameSelected()) {
207 return false;
208 }
209 return true;
210 }
211
212 /**
213 * Create the current frame / frame loop selector
214 *
215 * @return the image list panel
216 */
217 protected JPanel makeFramesPanel() {
218
219 getTimesList().addListSelectionListener(new ListSelectionListener() {
220 public void valueChanged(ListSelectionEvent e) {
221 if ( !getDoFrameLoop()) {
222 return;
223 }
224 }
225 });
226
227 ChangeListener listener = new ChangeListener() {
228 public void stateChanged(ChangeEvent ae) {
229 if (loopRB.isSelected() == getDoFrameLoop()) {
230 return;
231 }
232 doLoop = loopRB.isSelected();
233 if (doLoop && !haveAnyTimes()) {
234 readFrames();
235 } else {
236 updateStatus();
237 }
238 enableWidgets();
239 }
240 };
241
242 loopRB = new JRadioButton("Select frames", getDoFrameLoop());
243 loopRB.addChangeListener(listener);
244 curRB = new JRadioButton("Refresh current frame", !getDoFrameLoop());
245 curRB.addChangeListener(listener);
246 GuiUtils.buttonGroup(loopRB, curRB);
247 JPanel panel = GuiUtils.doLayout(new Component[] {
248 curRB, loopRB,
249 new JLabel(" "),getTimesList().getScroller()
250 }, 2, GuiUtils.WT_N, GuiUtils.WT_NY);
251 return GuiUtils.wrap(panel);
252 }
253
254 /**
255 * Are there any frames selected.
256 *
257 * @return Any frames selected.
258 */
259 protected boolean haveFrameSelected() {
260 return !getDoFrameLoop() || getTimesList().haveDataSelected();
261 }
262
263 /**
264 * Do we do a frame loop or refresh current frame
265 *
266 * @return Do we do frame loop
267 */
268 protected boolean getDoFrameLoop() {
269 return doLoop;
270 }
271
272 /**
273 * Set whether we do a frame loop or refresh current frame
274 *
275 * @param yesorno true to do frame loop
276 */
277 protected void setDoFrameLoop(boolean yesorno) {
278 doLoop = yesorno;
279 // Should this be in
280 if (curRB != null) {
281 curRB.setSelected(yesorno);
282 }
283 }
284
285 /**
286 * Did the user select current frame?
287 *
288 * @return Should we load current frame
289 */
290 protected boolean getDoCurrentFrame() {
291 return !getDoFrameLoop();
292 }
293
294 /**
295 * Enable or disable the GUI widgets based on what has been
296 * selected.
297 */
298 protected void enableWidgets() {
299 getTimesList().setEnabled(getDoFrameLoop());
300 }
301 }