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