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