001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2024
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 https://www.gnu.org/licenses/.
027 */
028
029package edu.wisc.ssec.mcidasv.chooser;
030
031import static javax.swing.GroupLayout.DEFAULT_SIZE;
032import static javax.swing.GroupLayout.PREFERRED_SIZE;
033import static javax.swing.GroupLayout.Alignment.BASELINE;
034import static javax.swing.GroupLayout.Alignment.LEADING;
035import static javax.swing.GroupLayout.Alignment.TRAILING;
036import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
037import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
038
039import java.awt.Color;
040import java.awt.Component;
041import java.awt.Dimension;
042
043import javax.swing.GroupLayout;
044import javax.swing.JButton;
045import javax.swing.JComponent;
046import javax.swing.JLabel;
047import javax.swing.JPanel;
048import javax.swing.JScrollPane;
049import javax.swing.JTextField;
050
051import org.w3c.dom.Element;
052
053import ucar.unidata.idv.chooser.IdvChooserManager;
054import ucar.unidata.util.GuiUtils;
055import ucar.unidata.xml.XmlUtil;
056import edu.wisc.ssec.mcidasv.Constants;
057import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
058import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position;
059import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor;
060import 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
074public class RaobChooser extends ucar.unidata.idv.chooser.RaobChooser implements Constants {
075    
076    /**
077     * Construct a {@code RaobChooser} using the manager
078     * and the root XML that defines this object.
079     *
080     * @param mgr  {@code IdvChooserManager} 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