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 static javax.swing.GroupLayout.DEFAULT_SIZE;
032    import static javax.swing.GroupLayout.PREFERRED_SIZE;
033    import static javax.swing.GroupLayout.Alignment.BASELINE;
034    import static javax.swing.GroupLayout.Alignment.LEADING;
035    import static javax.swing.GroupLayout.Alignment.TRAILING;
036    import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
037    import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
038    
039    import java.awt.Color;
040    import java.awt.Component;
041    import java.awt.Dimension;
042    
043    import javax.swing.GroupLayout;
044    import javax.swing.JButton;
045    import javax.swing.JComponent;
046    import javax.swing.JLabel;
047    import javax.swing.JPanel;
048    import javax.swing.JScrollPane;
049    import javax.swing.JTextField;
050    
051    import org.w3c.dom.Element;
052    
053    import ucar.unidata.idv.chooser.IdvChooserManager;
054    import ucar.unidata.util.GuiUtils;
055    import ucar.unidata.xml.XmlUtil;
056    import edu.wisc.ssec.mcidasv.Constants;
057    import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
058    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position;
059    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor;
060    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width;
061    
062    
063    /**
064     * A chooser class for selecting Raob data.
065     * Mostly just a wrapper around a
066     *  {@link ucar.unidata.view.sounding.SoundingSelector}
067     * that does most of the work
068     *
069     * @author IDV development team
070     * @version $Revision$Date: 2011/03/24 16:06:31 $
071     */
072    
073    
074    public class RaobChooser extends ucar.unidata.idv.chooser.RaobChooser implements Constants {
075        
076        /**
077         * Construct a <code>RaobChooser</code> using the manager
078         * and the root XML that defines this object.
079         *
080         * @param mgr  <code>IdvChooserManager</code> that controls this chooser.
081         * @param root root element of the XML that defines this object
082         */
083        public RaobChooser(IdvChooserManager mgr, Element root) {
084            super(mgr, root);
085        }
086            
087        /**
088         * Make the contents
089         *
090         * @return  the contents
091         */
092        protected JPanel doMakeInnerPanel(JPanel fromPanel) {
093    
094            // Get the station panel
095            Component[] fromComps = fromPanel.getComponents();
096            
097            if (fromComps.length != 2 ||
098                    !(fromComps[0] instanceof JPanel) ||
099                    !(fromComps[1] instanceof JPanel)
100            ) return fromPanel;
101            JComponent stationPanel = (JPanel)fromComps[1];
102            // TODO: Yup, these are magic dimension numbers
103            stationPanel.setPreferredSize(new Dimension(300, 252));
104            Color bgcolor = stationPanel.getBackground();
105    
106            // Get the times panel
107            Component[] panels = ((JPanel)fromComps[0]).getComponents();
108            if (panels.length < 1 ||
109                    !(panels[0] instanceof JPanel)
110            ) return fromPanel;
111            panels = ((JPanel)panels[0]).getComponents();
112            if (panels.length != 4 ||
113                    !(panels[0] instanceof JLabel) ||
114                    !(panels[1] instanceof JScrollPane) ||
115                    !(panels[2] instanceof JLabel) ||
116                    !(panels[3] instanceof JScrollPane)
117            ) return fromPanel;
118            
119            JScrollPane availablePanel = (JScrollPane)panels[1];
120            // TODO: Yup, these are magic dimension numbers
121            availablePanel.setPreferredSize(new Dimension(180, 50));
122            availablePanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Available"));
123            availablePanel.setBackground(bgcolor);
124            JScrollPane selectedPanel = (JScrollPane)panels[3];
125            // TODO: Yup, these are magic dimension numbers
126            selectedPanel.setPreferredSize(new Dimension(170, 50));
127            selectedPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Selected"));
128            selectedPanel.setBackground(bgcolor);
129            
130            // Make the container panel
131            JPanel timesPanel = new JPanel();
132            
133            GroupLayout timesLayout = new GroupLayout(timesPanel);
134            timesPanel.setLayout(timesLayout);
135            timesLayout.setHorizontalGroup(
136                    timesLayout.createParallelGroup(LEADING)
137                .addGroup(timesLayout.createSequentialGroup()
138                    .addComponent(availablePanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
139                    .addGap(GAP_RELATED)
140                    .addComponent(selectedPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
141                    )
142            );
143            timesLayout.setVerticalGroup(
144                    timesLayout.createParallelGroup(LEADING)
145                .addGroup(timesLayout.createSequentialGroup()
146                    .addGroup(timesLayout.createParallelGroup(TRAILING)
147                        .addComponent(selectedPanel, LEADING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
148                        .addComponent(availablePanel, LEADING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
149                        )
150            );
151            
152            // TODO: Yup, these are magic dimension numbers
153            JComponent temp = new JPanel();
154            temp.setPreferredSize(new Dimension(150, 150));
155            temp.setBorder(javax.swing.BorderFactory.createEtchedBorder());
156            McVGuiUtils.setComponentHeight(timesPanel, temp);
157    
158            JPanel myPanel = new JPanel();
159            
160            JLabel descriptorLabelStatic = McVGuiUtils.makeLabelRight("Soundings:");
161            JLabel descriptorString = new JLabel("Upper air mandatory and significant levels");
162            McVGuiUtils.setLabelBold(descriptorString, true);
163            
164            JLabel stationLabel = McVGuiUtils.makeLabelRight("Stations:");
165            
166            JLabel timesLabel = McVGuiUtils.makeLabelRight("");
167                    
168            GroupLayout layout = new GroupLayout(myPanel);
169            myPanel.setLayout(layout);
170            layout.setHorizontalGroup(
171                layout.createParallelGroup(LEADING)
172                .addGroup(layout.createSequentialGroup()
173                    .addGroup(layout.createParallelGroup(LEADING)
174                        .addGroup(layout.createSequentialGroup()
175                            .addComponent(descriptorLabelStatic)
176                            .addGap(GAP_RELATED)
177                            .addComponent(descriptorString))
178                        .addGroup(layout.createSequentialGroup()
179                            .addComponent(stationLabel)
180                            .addGap(GAP_RELATED)
181                            .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
182                        .addGroup(layout.createSequentialGroup()
183                            .addComponent(timesLabel)
184                            .addGap(GAP_RELATED)
185                            .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))
186            );
187            layout.setVerticalGroup(
188                layout.createParallelGroup(LEADING)
189                .addGroup(layout.createSequentialGroup()
190                    .addGroup(layout.createParallelGroup(BASELINE)
191                        .addComponent(descriptorLabelStatic)
192                        .addComponent(descriptorString))
193                    .addPreferredGap(RELATED)
194                    .addGroup(layout.createParallelGroup(LEADING)
195                        .addComponent(stationLabel)
196                        .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
197                    .addPreferredGap(RELATED)
198                    .addGroup(layout.createParallelGroup(LEADING)
199                        .addComponent(timesLabel)
200                        .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
201                    .addPreferredGap(RELATED))
202            );
203            
204            return myPanel;
205        }
206        
207        private JLabel statusLabel = new JLabel("Status");
208    
209        @Override
210        public void setStatus(String statusString, String foo) {
211            if (statusString == null)
212                statusString = "";
213            statusLabel.setText(statusString);
214        }
215    
216        /**
217         * Make the GUI
218         *
219         * @return The GUI
220         */
221        protected JComponent doMakeContents() {
222            Element chooserNode = getXmlNode();
223            XmlUtil.setAttributes(chooserNode, new String[] { ATTR_SHOWSERVER, "false" });
224            JComponent parentContents = super.doMakeContents();
225    
226            // Pull apart the panels
227            // Expected:
228            // Top: file chooser
229            // Center: sounding selector
230            // Bottom: chooser buttons
231            // This takes a bit of digging--some of the components are really buried!
232            Component[] parentComps = parentContents.getComponents();
233            
234            // Dig down through all the GuiUtils parents
235            parentComps = ((JComponent)parentComps[0]).getComponents();
236            parentComps = ((JComponent)parentComps[0]).getComponents();
237            parentComps = ((JComponent)parentComps[0]).getComponents();
238            
239            if (parentComps.length != 3 ||
240                    !(parentComps[0] instanceof JPanel) ||
241                    !(parentComps[1] instanceof JPanel) ||
242                    !(parentComps[2] instanceof JPanel)
243            ) return parentContents;
244            
245            // Assign sounding selector file picker to typeComponent
246            JPanel topPanel = (JPanel)parentComps[0];
247            Component[] panels = topPanel.getComponents();
248            if (panels.length < 1 ||
249                    !(panels[0] instanceof JPanel)
250            ) return parentContents;
251            panels = ((JPanel)panels[0]).getComponents();
252            if (panels.length != 2 ||
253                    !(panels[0] instanceof JPanel) ||
254                    !(panels[1] instanceof JPanel)
255            ) return parentContents;
256            panels = ((JPanel)panels[0]).getComponents();
257            if (panels.length != 2 ||
258                    !(panels[0] instanceof JLabel) ||
259                    !(panels[1] instanceof JPanel)
260            ) return parentContents;
261            panels = ((JPanel)panels[1]).getComponents();
262            if (panels.length != 2 ||
263                    !(panels[0] instanceof JTextField) ||
264                    !(panels[1] instanceof JButton)
265            ) return parentContents;
266            JTextField fileComponent = (JTextField)panels[0];
267            JButton fileButton = (JButton)panels[1];
268            McVGuiUtils.setButtonImage(fileButton, ICON_OPEN_SMALL);
269            McVGuiUtils.setComponentWidth(fileButton, Width.DOUBLE);
270            McVGuiUtils.setComponentHeight(fileComponent, fileButton);
271    
272            // Rearrange the sounding selector and assign it to innerPanel
273            JPanel innerPanel = doMakeInnerPanel((JPanel)parentComps[1]);
274    
275            // Assign sounding selector loadButton to the chooser
276            JPanel bottomPanel = (JPanel)parentComps[2];
277            Component[] buttons = bottomPanel.getComponents();
278                    
279            // Dig down through all the GuiUtils parents
280            buttons = ((JPanel)buttons[1]).getComponents();
281            buttons = ((JPanel)buttons[1]).getComponents();
282            buttons = ((JPanel)buttons[0]).getComponents();
283            buttons = ((JPanel)buttons[0]).getComponents();
284    
285            for (Component button : buttons) {
286                if (button instanceof JButton &&
287                        ((JButton)button).getText() == getLoadCommandName()) {
288                    loadButton = (JButton)button;
289                    break;
290                }
291            }
292            if (loadButton==null) return parentContents;
293            
294            statusLabel.setEnabled(false);
295            setStatus("Status unavailable");
296    
297            // Start building the whole thing here
298            JPanel outerPanel = new JPanel();
299    
300            JLabel fileLabel = McVGuiUtils.makeLabelRight("File:");
301    
302            JLabel statusLabelLabel = McVGuiUtils.makeLabelRight("");
303    
304            McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT);
305            McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS);
306    
307            JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help");
308            helpButton.setActionCommand(GuiUtils.CMD_HELP);
309            helpButton.addActionListener(this);
310    
311            JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh");
312            refreshButton.setActionCommand(GuiUtils.CMD_UPDATE);
313            refreshButton.addActionListener(this);
314    
315            McVGuiUtils.setButtonImage(loadButton, ICON_ACCEPT_SMALL);
316            McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE);
317    
318            GroupLayout layout = new GroupLayout(outerPanel);
319            outerPanel.setLayout(layout);
320            layout.setHorizontalGroup(
321                    layout.createParallelGroup(LEADING)
322                    .addGroup(TRAILING, layout.createSequentialGroup()
323                            .addGroup(layout.createParallelGroup(TRAILING)
324                                    .addGroup(layout.createSequentialGroup()
325                                            .addContainerGap()
326                                            .addComponent(helpButton)
327                                            .addGap(GAP_RELATED)
328                                            .addComponent(refreshButton)
329                                            .addPreferredGap(RELATED)
330                                            .addComponent(loadButton))
331                                            .addGroup(LEADING, layout.createSequentialGroup()
332                                                    .addContainerGap()
333                                                    .addGroup(layout.createParallelGroup(LEADING)
334                                                            .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
335                                                            .addGroup(layout.createSequentialGroup()
336                                                                    .addComponent(fileLabel)
337                                                                    .addGap(GAP_RELATED)
338                                                                    .addComponent(fileComponent)
339                                                                    .addGap(GAP_UNRELATED)
340                                                                    .addComponent(fileButton))
341                                                                    .addGroup(layout.createSequentialGroup()
342                                                                            .addComponent(statusLabelLabel)
343                                                                            .addGap(GAP_RELATED)
344                                                                            .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)))))
345                                                                            .addContainerGap())
346            );
347            layout.setVerticalGroup(
348                    layout.createParallelGroup(LEADING)
349                    .addGroup(layout.createSequentialGroup()
350                            .addContainerGap()
351                            .addGroup(layout.createParallelGroup(BASELINE)
352                                    .addComponent(fileLabel)
353                                    .addComponent(fileComponent)
354                                    .addComponent(fileButton))
355                                    .addPreferredGap(UNRELATED)
356                                    .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
357                                    .addPreferredGap(UNRELATED)
358                                    .addGroup(layout.createParallelGroup(BASELINE)
359                                            .addComponent(statusLabelLabel)
360                                            .addComponent(statusLabel))
361                                            .addPreferredGap(UNRELATED)
362                                            .addGroup(layout.createParallelGroup(BASELINE)
363                                                    .addComponent(loadButton)
364                                                    .addComponent(refreshButton)
365                                                    .addComponent(helpButton))
366                                                    .addContainerGap())
367            );
368    
369            return outerPanel;
370            
371        }
372    
373    }
374