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 import java.awt.Component;
032 import java.awt.Container;
033 import java.awt.event.ActionEvent;
034 import java.awt.event.ActionListener;
035 import java.beans.PropertyChangeEvent;
036 import java.beans.PropertyChangeListener;
037 import java.io.File;
038 import java.util.ArrayList;
039 import java.util.Collections;
040 import java.util.Vector;
041
042 import javax.swing.JComboBox;
043 import javax.swing.JFileChooser;
044 import javax.swing.JLabel;
045 import javax.swing.JPanel;
046 import javax.swing.filechooser.FileFilter;
047
048 import org.w3c.dom.Element;
049
050 import ucar.unidata.idv.chooser.IdvChooserManager;
051 import ucar.unidata.util.GuiUtils;
052 import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
053
054 public class HRITChooser extends FileChooser {
055
056 private static final long serialVersionUID = 1L;
057
058 private HRITFilter hf = null;
059
060 private JLabel channelLabel = McVGuiUtils.makeLabelRight("Data Channel:");
061
062 /**
063 * Create the chooser with the given manager and xml
064 *
065 * @param mgr The manager
066 * @param root The xml
067 *
068 */
069
070 public HRITChooser(IdvChooserManager mgr, Element root) {
071 super(mgr, root);
072 }
073
074 /**
075 * Make the file chooser
076 *
077 * @param path the initial path
078 *
079 * @return the file chooser
080 */
081
082 protected JFileChooser doMakeFileChooser(String path) {
083 return new HRITFileChooser(path);
084 }
085
086 protected Vector<String> getAvailableHRITTypes(String path) {
087 if (path == null) path = ".";
088
089 ArrayList<String> al = new ArrayList<String>();
090 Vector<String> v = new Vector<String>();
091 File f = new File(path);
092 File [] files = null;
093 if (f.isDirectory()) {
094 files = f.listFiles(
095 new java.io.FileFilter() {
096 public boolean accept(File f) {
097 if ((f.getName().endsWith("__")) && (f.getName().matches(".*MSG[2-3].*"))) {
098 return true;
099 } else {
100 return false;
101 }
102 }
103 }
104 );
105 }
106 if (files != null) {
107 for (int i = 0; i < files.length; i++) {
108 String channelStr = files[i].getName().substring(26, 32);
109 if (channelStr.equals("______")) continue;
110 channelStr = channelStr.replace("___", "");
111 if (! al.contains(channelStr)) {
112 al.add(channelStr);
113 }
114 }
115 }
116 Collections.sort(al);
117 for (int i = 0; i < al.size(); i++) {
118 v.add(al.get(i));
119 }
120 return v;
121 }
122
123 public class ImageTypeChooser extends JComboBox implements ActionListener, PropertyChangeListener {
124
125 private static final long serialVersionUID = 1L;
126 JFileChooser jfc = null;
127
128 public ImageTypeChooser(JFileChooser fc, String path) {
129 jfc = fc;
130 Vector<String> availableTypes = getAvailableHRITTypes(path);
131 if (availableTypes.size() == 1 && availableTypes.get(0) == ".") {
132 availableTypes.removeAllElements();
133 }
134 reloadComboBox(availableTypes);
135 addActionListener(this);
136 McVGuiUtils.setComponentWidth(this, McVGuiUtils.Width.DOUBLE);
137 }
138
139 public void actionPerformed(ActionEvent e) {
140 JComboBox cb = (JComboBox) e.getSource();
141 String newFilter = (String) cb.getSelectedItem();
142 HRITFilter hFilter = (HRITFilter) jfc.getFileFilter();
143 hFilter.setExtraFilter(newFilter);
144 jfc.rescanCurrentDirectory();
145 }
146
147 public void reloadComboBox(Vector<String> v) {
148 removeAllItems();
149 if (v != null) {
150 for (int i = 0; i < v.size(); i++) {
151 addItem(v.get(i));
152 }
153 }
154 if (v == null || v.size() == 0) {
155 setEnabled(false);
156 channelLabel.setEnabled(false);
157 }
158 else {
159 setEnabled(true);
160 channelLabel.setEnabled(true);
161 }
162 }
163
164 public void propertyChange(PropertyChangeEvent e) {
165 String prop = e.getPropertyName();
166
167 // If the directory changed, reload the combo box with new image type choices.
168 if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
169 Vector<String> availableTypes = getAvailableHRITTypes(jfc.getCurrentDirectory().getPath());
170 reloadComboBox(availableTypes);
171 }
172
173 }
174
175 }
176
177 /* HRITFilter */
178 public class HRITFilter extends FileFilter {
179
180 String extraFilter = null;
181
182 public HRITFilter(String extraFilter) {
183 super();
184 if (extraFilter != null) {
185 this.extraFilter = extraFilter;
186 }
187 }
188
189 // Accept all directories and all HRIT files.
190 public boolean accept(File f) {
191
192 if (f.isDirectory()) {
193 return true;
194 }
195
196 // XXX TJJ - at present, we are ONLY allowing MSG2 and MSG3 segment data files
197 // through the filter which have already been Wavelet decompressed
198 // (i.e., they end with __ and not C_ )
199 String fileName = f.getName();
200 if ((fileName.endsWith("__")) && (fileName.matches(".*MSG[2-3].*")) && (fileName.length() >= 58)) {
201 if (extraFilter != null) {
202 if (fileName.contains(extraFilter)) {
203 return true;
204 } else {
205 return false;
206 }
207 }
208 } else {
209 return false;
210 }
211 return false;
212
213 }
214
215 // The description of this filter
216 public String getDescription() {
217 return "HRIT Data";
218 }
219
220 // change the additional filter string
221 public void setExtraFilter(String newFilter) {
222 if (newFilter != null) {
223 extraFilter = newFilter;
224 //seenPatterns.clear();
225 }
226 }
227
228 }
229
230 /**
231 * HRITFileChooser, an extension of JFileChooser
232 *
233 * @author Tommy Jasmin
234 */
235
236 public class HRITFileChooser extends JFileChooser {
237
238 /**
239 * default for serializable class
240 */
241 private static final long serialVersionUID = 1L;
242
243 /**
244 * Create the file chooser
245 *
246 * @param path the initial path
247 */
248
249 public HRITFileChooser(String path) {
250 super(path);
251 setControlButtonsAreShown(false);
252 setMultiSelectionEnabled(false);
253 setAcceptAllFileFilterUsed(false);
254 processChildren(this);
255 }
256
257 private void processChildren(Container c) {
258 Component [] components = c.getComponents();
259 if (components != null) {
260 // loop through all components, looking for the JLabel children of
261 // components we want to remove
262 for (int i = 0; i < components.length; i++) {
263 if (components[i] instanceof JLabel) {
264 String text = ((JLabel) components[i]).getText();
265 if (text.equals("File Name:")) {
266 hideChildren((Container) components[i].getParent());
267 continue;
268 }
269 if (text.equals("Files of Type:")) {
270 hideChildren((Container) components[i].getParent());
271 continue;
272 }
273 }
274 // now check this component for any children
275 processChildren((Container) components[i]);
276 }
277 }
278 }
279
280 private void hideChildren(Container c) {
281 Component [] components = c.getComponents();
282 for (int i = 0; i < components.length; i++) {
283 components[i].setVisible(false);
284 }
285 c.setVisible(false);
286 }
287
288 /**
289 * Approve the selection
290 */
291
292 public void approveSelection() {
293 HRITChooser.this.doLoad();
294 }
295
296 /**
297 * Cancel the selection
298 */
299
300 public void cancelSelection() {
301 closeChooser();
302 }
303
304 /**
305 * Set the selected files
306 *
307 * @param selectedFiles the selected files
308 */
309
310 public void setSelectedFiles(File[] selectedFiles) {
311 String channelStr = null;
312 String timeStr = null;
313 if (selectedFiles != null) {
314 for (int i = 0; i < selectedFiles.length; i++) {
315 if (! selectedFiles[i].isDirectory()) {
316 if (selectedFiles[i].getName().length() >= 58) {
317 channelStr = selectedFiles[i].getName().substring(26, 32);
318 timeStr = selectedFiles[i].getName().substring(46, 58);
319 }
320 }
321 }
322 }
323 File curDir = getCurrentDirectory();
324 File [] fileList = curDir.listFiles();
325 String tmpChannel = null;
326 String tmpTime = null;
327 ArrayList<File> matches = new ArrayList<File>();
328 for (int i = 0; i < fileList.length; i++) {
329 if ((fileList[i].getName().endsWith("__")) &&
330 (fileList[i].getName().matches(".*MSG[2-3].*")) &&
331 (fileList[i].getName().length() >= 58)) {
332 tmpChannel = fileList[i].getName().substring(26, 32);
333 tmpTime = fileList[i].getName().substring(46, 58);
334 if ((tmpChannel.equals(channelStr)) && (tmpTime.equals(timeStr))) {
335 matches.add(fileList[i]);
336 }
337 }
338 }
339 Collections.sort(matches);
340
341 // make new file array from ArrayList matches
342 File [] fileSet = new File[matches.size()];
343 for (int i = 0; i < matches.size(); i++) {
344 fileSet[i] = (File) matches.get(i);
345 }
346
347 super.setSelectedFiles(fileSet);
348 setHaveData( !((selectedFiles == null)
349 || (selectedFiles.length == 0)));
350 }
351 }
352
353 /**
354 * Handle the selection of the set of files
355 *
356 * @param files The files the user chose
357 * @param directory The directory they chose them from
358 * @return True if the file was successful
359 * @throws Exception
360 */
361
362 protected boolean selectFilesInner(File[] files, File directory)
363 throws Exception {
364 if ((files == null) || (files.length == 0)) {
365 userMessage("Please select a file");
366 return false;
367 }
368
369 // only allow selection of files that make sense as a "set"
370 // for now, that means all part of single image for a single channel
371 String channelStr = files[0].getName().substring(26, 32);
372 String timeStr = files[0].getName().substring(46, 58);
373 int prvSegment = -1;
374 int curSegment = -1;
375 for (int i = 0; i < files.length; i++) {
376 try {
377 curSegment = Integer.parseInt(files[i].getName().substring(40, 42));
378 } catch (NumberFormatException nfe) {
379 userMessage("Problem determining image segment number for file: " + files[i].getName());
380 return false;
381 }
382 if (!files[i].getName().substring(26, 32).equals(channelStr)) {
383 userMessage("Selected data must be for a single channel and time");
384 return false;
385 }
386 if (!files[i].getName().substring(46, 58).equals(timeStr)) {
387 userMessage("Selected data must be for a single channel and time");
388 return false;
389 }
390 if (prvSegment >= 0) {
391 if (curSegment != (prvSegment + 1)) {
392 userMessage("Selected data must be a contiguous set of image segment files");
393 return false;
394 }
395 }
396 prvSegment = curSegment;
397 }
398
399 // XXX TJJ - until HRITAdapter can handle the fact that HRV data can
400 // alter geographic coverage in mid-transmission, we deal with this by
401 // only allowing display of HRV segments one at a time.
402
403 // commenting out for now - will deal with it in field selector window
404 /* if (files.length > 1) {
405 int hrvCount = 0;
406 for (int i = 0; i < files.length; i++) {
407 if (files[i].getName().contains("HRV")) {
408 hrvCount++;
409 }
410 if (hrvCount > 1) {
411 userMessage("At present, HRV data can only be displayed one file at a time");
412 return false;
413 }
414 }
415 }*/
416
417 return super.selectFilesInner(files, directory);
418 }
419
420 /**
421 * Get the bottom panel for the chooser
422 * @return the bottom panel
423 */
424
425 protected JPanel getBottomPanel() {
426 // If we don't have a fileChooser yet, this won't do any good
427 // This happens when Unidata's FileChooser is instantiated
428 // We instantiate ours right after that
429 if (fileChooser == null) {
430 return null;
431 }
432
433 ImageTypeChooser itc = new ImageTypeChooser(fileChooser, path);
434 fileChooser.addPropertyChangeListener(itc);
435 JPanel bottomPanel = GuiUtils.left(itc);
436 bottomPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
437
438 return McVGuiUtils.makeLabeledComponent(channelLabel, itc);
439 }
440
441 /**
442 * Get the center panel for the chooser
443 * @return the center panel
444 */
445
446 protected JPanel getCenterPanel() {
447 JPanel centerPanel = super.getCenterPanel();
448
449 fileChooser.setAcceptAllFileFilterUsed(false);
450
451 // see what HRIT data is available in this directory,
452 Vector<String> availableTypes = getAvailableHRITTypes(path);
453 String extraFilter = null;
454 if ((availableTypes != null) && (availableTypes.size() > 0)) {
455 extraFilter = (String) availableTypes.get(0);
456 }
457
458 hf = new HRITFilter(extraFilter);
459 fileChooser.setFileFilter(hf);
460
461 return centerPanel;
462 }
463
464 }