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 }