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.startupmanager;
030
031 import java.awt.BorderLayout;
032 import java.awt.Component;
033 import java.awt.Container;
034 import java.awt.Dimension;
035 import java.awt.FlowLayout;
036 import java.awt.Graphics;
037 import java.awt.Graphics2D;
038 import java.awt.RenderingHints;
039 import java.awt.event.ActionEvent;
040 import java.awt.event.ActionListener;
041 import java.io.File;
042 import java.io.FileInputStream;
043 import java.io.FileOutputStream;
044 import java.io.IOException;
045 import java.io.InputStream;
046 import java.io.OutputStream;
047 import java.util.List;
048 import java.util.Properties;
049
050 import javax.swing.BorderFactory;
051 import javax.swing.DefaultListCellRenderer;
052 import javax.swing.DefaultListModel;
053 import javax.swing.ImageIcon;
054 import javax.swing.JButton;
055 import javax.swing.JCheckBox;
056 import javax.swing.JComboBox;
057 import javax.swing.JFrame;
058 import javax.swing.JLabel;
059 import javax.swing.JList;
060 import javax.swing.JPanel;
061 import javax.swing.JScrollPane;
062 import javax.swing.JSplitPane;
063 import javax.swing.JTree;
064 import javax.swing.ListModel;
065 import javax.swing.ListSelectionModel;
066 import javax.swing.SwingConstants;
067 import javax.swing.event.ListSelectionEvent;
068 import javax.swing.event.ListSelectionListener;
069 import javax.swing.tree.DefaultMutableTreeNode;
070 import javax.swing.tree.DefaultTreeCellRenderer;
071
072 import ucar.unidata.ui.Help;
073 import ucar.unidata.util.GuiUtils;
074 import ucar.unidata.util.LogUtil;
075 import ucar.unidata.util.StringUtil;
076 import edu.wisc.ssec.mcidasv.ArgumentManager;
077 import edu.wisc.ssec.mcidasv.Constants;
078 import edu.wisc.ssec.mcidasv.startupmanager.options.BooleanOption;
079 import edu.wisc.ssec.mcidasv.startupmanager.options.DirectoryOption;
080 import edu.wisc.ssec.mcidasv.startupmanager.options.LoggerLevelOption;
081 import edu.wisc.ssec.mcidasv.startupmanager.options.MemoryOption;
082 import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster;
083 import edu.wisc.ssec.mcidasv.startupmanager.options.TextOption;
084 import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
085
086 // using an enum to enforce singleton-ness is a hack, but it's been pretty
087 // effective. OptionMaster is used in a similar way. The remaining enums are
088 // used in the more traditional fashion.
089 public class StartupManager implements edu.wisc.ssec.mcidasv.Constants {
090
091 // TODO(jon): replace
092 public static final String[][] PREF_PANELS = {
093 { Constants.PREF_LIST_GENERAL, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/mcidasv-round32.png" },
094 { Constants.PREF_LIST_VIEW, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/tab-new32.png" },
095 { Constants.PREF_LIST_TOOLBAR, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/application-x-executable32.png" },
096 { Constants.PREF_LIST_DATA_CHOOSERS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/preferences-desktop-remote-desktop32.png" },
097 { Constants.PREF_LIST_ADDE_SERVERS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/applications-internet32.png" },
098 { Constants.PREF_LIST_AVAILABLE_DISPLAYS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/video-display32.png" },
099 { Constants.PREF_LIST_NAV_CONTROLS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/input-mouse32.png" },
100 { Constants.PREF_LIST_FORMATS_DATA,"/edu/wisc/ssec/mcidasv/resources/icons/prefs/preferences-desktop-theme32.png" },
101 { Constants.PREF_LIST_ADVANCED, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/applications-internet32.png" },
102 };
103
104 // TODO(jon): replace
105 public static final Object[][] RENDER_HINTS = {
106 { RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON },
107 { RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY },
108 { RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON },
109 };
110
111 /** usage message */
112 public static final String USAGE_MESSAGE =
113 "Usage: runMcV-Prefs <args>";
114
115 /** Path to the McIDAS-V help set within {@literal mcv_userguide.jar}. */
116 private static final String HELP_PATH = "/docs/userguide";
117
118 /** ID of the startup prefs help page. */
119 private static final String HELP_TARGET = "idv.tools.preferences.advancedpreferences";
120
121 /** The type of platform as reported by {@link #determinePlatform()}. */
122 private final Platform platform = determinePlatform();
123
124 /** Cached copy of the application rendering hints. */
125 public static final RenderingHints HINTS = getRenderingHints();
126
127 /** Contains the list of the different preference panels. */
128 private final JList panelList = new JList(new DefaultListModel());
129
130 /** Panel containing the startup options. */
131 private JPanel ADVANCED_PANEL;
132
133 /**
134 * Panel to use for all other preference panels while running startup
135 * manager.
136 */
137 private JPanel BAD_CHOICE_PANEL;
138
139 /** Contains the various buttons (Apply, Ok, Help, Cancel). */
140 private JPanel COMMAND_ROW_PANEL;
141
142 private static StartupManager instance;
143
144 private StartupManager() {
145
146 }
147
148 public static StartupManager getInstance() {
149 if (instance == null) {
150 instance = new StartupManager();
151 }
152 return instance;
153 }
154
155 /**
156 * Creates and returns the rendering hints for the GUI.
157 * Built from {@link #RENDER_HINTS}
158 *
159 * @return Hints to use when displaying the GUI.
160 */
161 public static RenderingHints getRenderingHints() {
162 RenderingHints hints = new RenderingHints(null);
163 for (int i = 0; i < RENDER_HINTS.length; i++)
164 hints.put(RENDER_HINTS[i][0], RENDER_HINTS[i][1]);
165 return hints;
166 }
167
168 /**
169 * Figures out the type of platform. Queries the "os.name"
170 * system property to determine the platform type.
171 *
172 * @return {@link Platform#UNIXLIKE} or {@link Platform#WINDOWS}.
173 */
174 private Platform determinePlatform() {
175 String os = System.getProperty("os.name");
176 if (os == null) {
177 throw new RuntimeException();
178 }
179 if (os.startsWith("Windows")) {
180 return Platform.WINDOWS;
181 } else {
182 return Platform.UNIXLIKE;
183 }
184 }
185
186 /**
187 * Returns either {@link Platform#UNIXLIKE} or
188 * {@link Platform#WINDOWS}.
189 *
190 * @return The platform as determined by {@link #determinePlatform()}.
191 */
192 public Platform getPlatform() {
193 return platform;
194 }
195
196 /**
197 * Saves the changes to the preferences and quits. Unlike the other button
198 * handling methods, this one is public. This was done so that the advanced
199 * preferences (within McIDAS-V) can force an update to the startup prefs.
200 */
201 public void handleApply() {
202 OptionMaster.getInstance().writeStartup();
203 }
204
205 /**
206 * Saves the preference changes.
207 */
208 protected void handleOk() {
209 OptionMaster.getInstance().writeStartup();
210 System.exit(0);
211 }
212
213 /**
214 * Shows the startup preferences help page.
215 */
216 protected void handleHelp() {
217 Help.setTopDir(HELP_PATH);
218 Help.getDefaultHelp().gotoTarget(HELP_TARGET);
219 }
220
221 /**
222 * Simply quits the program.
223 */
224 protected void handleCancel() {
225 System.exit(0);
226 }
227
228 /**
229 * Returns the preferences panel that corresponds with the user's
230 * {@code JList} selection.
231 *
232 * <p>In the context of the startup manager, this means that any
233 * {@code JList} selection <i>other than</i> {@literal "Advanced"} will
234 * return the results of {@link #getUnavailablePanel()}. Otherwise the
235 * results of {@link #getAdvancedPanel(boolean)} will be returned.
236 *
237 * @return Either the advanced preferences panel or an
238 * {@literal "unavailable"}, depending upon the user's selection.
239 */
240 private Container getSelectedPanel() {
241 ListModel listModel = panelList.getModel();
242 int index = panelList.getSelectedIndex();
243 if (index == -1) {
244 return getAdvancedPanel(true);
245 }
246 String key = ((JLabel)listModel.getElementAt(index)).getText();
247 if (Constants.PREF_LIST_ADVANCED.equals(key)) {
248 return getUnavailablePanel();
249 }
250 return getAdvancedPanel(true);
251 }
252
253 /**
254 * Creates and returns a dummy panel.
255 *
256 * @return Panel containing only a note about
257 * "options unavailable."
258 */
259 private JPanel buildUnavailablePanel() {
260 JPanel panel = new JPanel();
261 panel.add(new JLabel("These options are unavailable in this context"));
262 return panel;
263 }
264
265 /**
266 * Creates and returns the advanced preferences panel.
267 *
268 * @return Panel with all of the various startup options.
269 */
270 private JPanel buildAdvancedPanel() {
271 OptionMaster optMaster = OptionMaster.getInstance();
272 MemoryOption heapSize = optMaster.getMemoryOption("HEAP_SIZE");
273 BooleanOption jogl = optMaster.getBooleanOption("JOGL_TOGL");
274 BooleanOption use3d = optMaster.getBooleanOption("USE_3DSTUFF");
275 BooleanOption defaultBundle = optMaster.getBooleanOption("DEFAULT_LAYOUT");
276 BooleanOption useDirect3d = optMaster.getBooleanOption("D3DREND");
277 BooleanOption useCmsCollector = optMaster.getBooleanOption("USE_CMSGC");
278 BooleanOption useNpot = optMaster.getBooleanOption("USE_NPOT");
279 BooleanOption useGeometryByRef = optMaster.getBooleanOption("USE_GEOBYREF");
280 BooleanOption useImageByRef = optMaster.getBooleanOption("USE_IMAGEBYREF");
281 DirectoryOption startupBundle = optMaster.getDirectoryOption("STARTUP_BUNDLE");
282 // TextOption jvmArgs = optMaster.getTextOption("JVM_ARGS");
283 LoggerLevelOption logLevel = optMaster.getLoggerLevelOption("LOG_LEVEL");
284
285 JPanel startupPanel = new JPanel();
286 startupPanel.setBorder(BorderFactory.createTitledBorder("Startup Options"));
287
288 // Build the memory panel
289 JPanel heapPanel = McVGuiUtils.makeLabeledComponent(heapSize.getLabel()+":", heapSize.getComponent());
290
291 // Build the 3D panel
292 JCheckBox use3dCheckBox = use3d.getComponent();
293 use3dCheckBox.setText(use3d.getLabel());
294 final JCheckBox joglCheckBox = jogl.getComponent();
295 joglCheckBox.setText(jogl.getLabel());
296 final JCheckBox direct3dBox = useDirect3d.getComponent();
297 direct3dBox.setText(useDirect3d.getLabel());
298
299 JPanel internalPanel = McVGuiUtils.topCenterBottom(use3dCheckBox, joglCheckBox, direct3dBox);
300 JPanel j3dPanel = McVGuiUtils.makeLabeledComponent("3D:", internalPanel);
301
302 // Build the bundle panel
303 JPanel startupBundlePanel = startupBundle.getComponent();
304 JCheckBox defaultBundleCheckBox = defaultBundle.getComponent();
305 defaultBundleCheckBox.setText(defaultBundle.getLabel());
306 JPanel bundlePanel = McVGuiUtils.makeLabeledComponent(startupBundle.getLabel()+":",
307 McVGuiUtils.topBottom(startupBundlePanel, defaultBundleCheckBox, McVGuiUtils.Prefer.TOP));
308
309 JCheckBox useCmsCollectorCheckBox = useCmsCollector.getComponent();
310 useCmsCollectorCheckBox.setText(useCmsCollector.getLabel());
311
312 JCheckBox useGeometryByRefCheckBox = useGeometryByRef.getComponent();
313 useGeometryByRefCheckBox.setText(useGeometryByRef.getLabel());
314
315 JCheckBox useImageByRefCheckBox = useImageByRef.getComponent();
316 useImageByRefCheckBox.setText(useImageByRef.getLabel());
317
318 JCheckBox useNpotCheckBox = useNpot.getComponent();
319 useNpotCheckBox.setText(useNpot.getLabel());
320
321 JComboBox logLevelComboBox = logLevel.getComponent();
322
323 JPanel logLevelPanel = McVGuiUtils.makeLabeledComponent(logLevel.getLabel()+":", logLevelComboBox);
324
325 JPanel miscPanel = McVGuiUtils.makeLabeledComponent("Misc:", useCmsCollectorCheckBox);
326
327 Component[] visadComponents = new Component[] {
328 useGeometryByRefCheckBox,
329 useImageByRefCheckBox,
330 useNpotCheckBox
331 };
332
333 JPanel visadPanel = McVGuiUtils.makeLabeledComponent("VisAD:", McVGuiUtils.vertical(visadComponents));
334
335 javax.swing.GroupLayout panelLayout = new javax.swing.GroupLayout(startupPanel);
336 startupPanel.setLayout(panelLayout);
337 panelLayout.setHorizontalGroup(
338 panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
339 .addComponent(heapPanel)
340 .addComponent(j3dPanel)
341 .addComponent(bundlePanel)
342 .addComponent(visadPanel)
343 .addComponent(miscPanel)
344 .addComponent(logLevelPanel)
345 );
346 panelLayout.setVerticalGroup(
347 panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
348 .addGroup(panelLayout.createSequentialGroup()
349 .addComponent(heapPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
350 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
351 .addComponent(bundlePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
352 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
353 .addComponent(j3dPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
354 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
355 .addComponent(visadPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
356 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
357 .addComponent(logLevelPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
358 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
359 .addComponent(miscPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
360 )
361 );
362 return startupPanel;
363 }
364
365 /**
366 * Builds and returns a {@link JPanel} containing the various buttons that
367 * control the startup manager. These buttons offer identical
368 * functionality to those built by the IDV's preference manager code.
369 *
370 * @return A {@code JPanel} containing the following types of buttons:
371 * {@link ApplyButton}, {@link OkButton}, {@link HelpButton},
372 * and {@link CancelButton}.
373 *
374 * @see GuiUtils#makeApplyOkHelpCancelButtons(ActionListener)
375 */
376 private JPanel buildCommandRow() {
377 JPanel panel = new JPanel(new FlowLayout());
378 // Apply doesn't really mean anything in standalone mode...
379 // panel.add(new ApplyButton());
380 panel.add(new OkButton());
381 panel.add(new HelpButton());
382 panel.add(new CancelButton());
383 panel = McVGuiUtils.makePrettyButtons(panel);
384 return panel;
385 }
386
387 /**
388 * Returns the advanced preferences panel. Differs from the
389 * {@link #buildAdvancedPanel()} in that a panel isn't created, unless
390 * {@code forceBuild} is {@code true}.
391 *
392 * @param forceBuild Always rebuilds the advanced panel if {@code true}.
393 *
394 * @return Panel containing the startup options.
395 */
396 public JPanel getAdvancedPanel(final boolean forceBuild) {
397 if (forceBuild || ADVANCED_PANEL == null) {
398 OptionMaster.getInstance().readStartup();
399 ADVANCED_PANEL = buildAdvancedPanel();
400 }
401 return ADVANCED_PANEL;
402 }
403
404 public JPanel getUnavailablePanel() {
405 if (BAD_CHOICE_PANEL == null) {
406 BAD_CHOICE_PANEL = buildUnavailablePanel();
407 }
408 return BAD_CHOICE_PANEL;
409 }
410
411 /**
412 * Returns a panel containing the Apply/Ok/Help/Cancel buttons.
413 *
414 * @return Panel containing the the command row.
415 */
416 public JPanel getCommandRow() {
417 if (COMMAND_ROW_PANEL == null) {
418 COMMAND_ROW_PANEL = buildCommandRow();
419 }
420 return COMMAND_ROW_PANEL;
421 }
422
423 /**
424 * Build and display the startup manager window.
425 */
426 protected void createDisplay() {
427 DefaultListModel listModel = (DefaultListModel)panelList.getModel();
428
429 for (int i = 0; i < PREF_PANELS.length; i++) {
430 ImageIcon icon = new ImageIcon(getClass().getResource(PREF_PANELS[i][1]));
431 JLabel label = new JLabel(PREF_PANELS[i][0], icon, SwingConstants.LEADING);
432 listModel.addElement(label);
433 }
434
435 JScrollPane scroller = new JScrollPane(panelList);
436 final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
437 splitPane.setResizeWeight(0.0);
438 splitPane.setLeftComponent(scroller);
439 scroller.setMinimumSize(new Dimension(166, 319));
440
441 panelList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
442 panelList.setSelectedIndex(PREF_PANELS.length - 1);
443 panelList.setVisibleRowCount(PREF_PANELS.length);
444 panelList.setCellRenderer(new IconCellRenderer());
445
446 panelList.addListSelectionListener(new ListSelectionListener() {
447 public void valueChanged(final ListSelectionEvent e) {
448 if (!e.getValueIsAdjusting()) {
449 splitPane.setRightComponent(getSelectedPanel());
450 }
451 }
452 });
453
454 splitPane.setRightComponent(getSelectedPanel());
455
456 JFrame frame = new JFrame("User Preferences");
457 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
458 frame.getContentPane().add(splitPane);
459 frame.getContentPane().add(getCommandRow(), BorderLayout.PAGE_END);
460
461 frame.pack();
462 frame.setVisible(true);
463 }
464
465 /**
466 * Copies a file.
467 *
468 * @param src The file to copy.
469 * @param dst The path to the copy of {@code src}.
470 *
471 * @throws IOException If there was a problem while attempting to copy.
472 */
473 public void copy(final File src, final File dst) throws IOException {
474 InputStream in = new FileInputStream(src);
475 OutputStream out = new FileOutputStream(dst);
476
477 byte[] buf = new byte[1024];
478 int length;
479
480 while ((length = in.read(buf)) > 0) {
481 out.write(buf, 0, length);
482 }
483 in.close();
484 out.close();
485 }
486
487 public static class TreeCellRenderer extends DefaultTreeCellRenderer {
488 @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
489 super.getTreeCellRendererComponent(tree, value, sel, expanded,
490 leaf, row, hasFocus);
491
492 DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
493
494 File f = (File)node.getUserObject();
495 String path = f.getPath();
496
497 if (f.isDirectory()) {
498 setToolTipText("Bundle Directory: " + path);
499 } else if (ArgumentManager.isZippedBundle(path)) {
500 setToolTipText("Zipped Bundle: " + path);
501 } else if (ArgumentManager.isXmlBundle(path)) {
502 setToolTipText("XML Bundle: " + path);
503 } else {
504 setToolTipText("Unknown file type: " + path);
505 }
506 setText(f.getName().replace(f.getParent(), ""));
507 return this;
508 }
509 }
510
511 public static class IconCellRenderer extends DefaultListCellRenderer {
512 @Override public Component getListCellRendererComponent(JList list,
513 Object value, int index, boolean isSelected, boolean cellHasFocus)
514 {
515 super.getListCellRendererComponent(list, value, index, isSelected,
516 cellHasFocus);
517
518 if (value instanceof JLabel) {
519 setText(((JLabel)value).getText());
520 setIcon(((JLabel)value).getIcon());
521 }
522
523 return this;
524 }
525
526 @Override protected void paintComponent(Graphics g) {
527 Graphics2D g2d = (Graphics2D)g;
528 g2d.setRenderingHints(StartupManager.HINTS);
529 super.paintComponent(g2d);
530 }
531 }
532
533 private static abstract class CommandButton extends JButton
534 implements ActionListener
535 {
536 public CommandButton(final String label) {
537 super(label);
538 McVGuiUtils.setComponentWidth(this);
539 addActionListener(this);
540 }
541
542 @Override public void paintComponent(Graphics g) {
543 Graphics2D g2d = (Graphics2D)g;
544 g2d.setRenderingHints(StartupManager.HINTS);
545 super.paintComponent(g2d);
546 }
547
548 abstract public void actionPerformed(final ActionEvent e);
549 }
550
551 private static class ApplyButton extends CommandButton {
552 public ApplyButton() {
553 super("Apply");
554 }
555 public void actionPerformed(final ActionEvent e) {
556 StartupManager.getInstance().handleApply();
557 }
558 }
559
560 private static class OkButton extends CommandButton {
561 public OkButton() {
562 super("OK");
563 }
564 public void actionPerformed(final ActionEvent e) {
565 StartupManager.getInstance().handleOk();
566 }
567 }
568
569 private static class HelpButton extends CommandButton {
570 public HelpButton() {
571 super("Help");
572 }
573 public void actionPerformed(final ActionEvent e) {
574 StartupManager.getInstance().handleHelp();
575 }
576 }
577
578 private static class CancelButton extends CommandButton {
579 public CancelButton() {
580 super("Cancel");
581 }
582 public void actionPerformed(final ActionEvent e) {
583 StartupManager.getInstance().handleCancel();
584 }
585 }
586
587 public static Properties getDefaultProperties() {
588 Properties props = new Properties();
589 String osName = System.getProperty("os.name");
590 if (osName.startsWith("Mac OS X")) {
591 props.setProperty("userpath", String.format("%s%s%s%s%s", System.getProperty("user.home"), File.separator, "Documents", File.separator, Constants.USER_DIRECTORY_NAME));
592 } else {
593 props.setProperty("userpath", String.format("%s%s%s", System.getProperty("user.home"), File.separator, Constants.USER_DIRECTORY_NAME));
594 }
595 props.setProperty(Constants.PROP_SYSMEM, "0");
596 return props;
597 }
598
599 /**
600 * Extract any command-line properties and their corresponding values.
601 *
602 * <p>May print out usage information if a badly formatted
603 * {@literal "property=value"} pair is encountered, or when an unknown
604 * argument is found (depending on value of the {@code ignoreUnknown}
605 * parameter).
606 *
607 * <p><b>NOTE:</b> {@code null} is not a permitted value for any parameter.
608 *
609 * @param ignoreUnknown Whether or not to handle unknown arguments.
610 * @param fromStartupManager Whether or not this call originated from
611 * {@code startupmanager.jar}.
612 * @param args Array containing command-line arguments.
613 * @param defaults Default parameter values.
614 *
615 * @return Command-line arguments as a collection of property identifiers
616 * and values.
617 */
618 public static Properties getArgs(final boolean ignoreUnknown,
619 final boolean fromStartupManager, final String[] args,
620 final Properties defaults)
621 {
622 Properties props = new Properties(defaults);
623 for (int i = 0; i < args.length; i++) {
624
625 // handle property definitions
626 if (args[i].startsWith("-D")) {
627 List<String> l = StringUtil.split(args[i].substring(2), "=");
628 if (l.size() == 2) {
629 props.setProperty(l.get(0), l.get(1));
630 } else {
631 usage("Invalid property:" + args[i]);
632 }
633 }
634
635 // handle userpath changes
636 else if (ARG_USERPATH.equals(args[i]) && (i+1) < args.length) {
637 props.setProperty("userpath", args[++i]);
638 }
639
640 // handle help requests
641 else if (ARG_HELP.equals(args[i]) && (fromStartupManager)) {
642 System.err.println(USAGE_MESSAGE);
643 System.err.println(getUsageMessage());
644 System.exit(1);
645 }
646
647 // bail out for unknown args, unless we don't care!
648 else if (!ignoreUnknown){
649 usage("Unknown argument: " + args[i]);
650 }
651 }
652 return props;
653 }
654
655 public static int getMaximumHeapSize() {
656 int sysmem = StartupManager.getInstance().getPlatform().getAvailableMemory();
657 if (sysmem > Constants.MAX_MEMORY_32BIT &&
658 System.getProperty("os.arch").indexOf("64") < 0) {
659 return Constants.MAX_MEMORY_32BIT;
660 }
661 return sysmem;
662 }
663
664 /**
665 * Print out the command line usage message and exit. Taken entirely from
666 * {@link ucar.unidata.idv.ArgsManager}.
667 *
668 * @param err The usage message
669 */
670 private static void usage(final String err) {
671 String msg = USAGE_MESSAGE;
672 msg = msg + "\n" + getUsageMessage();
673 LogUtil.userErrorMessage(err + "\n" + msg);
674 System.exit(1);
675 }
676
677 /**
678 * Return the command line usage message.
679 *
680 * @return The usage message
681 */
682 protected static String getUsageMessage() {
683 return "\t"+ARG_HELP+" (this message)\n"+
684 "\t"+ARG_USERPATH+" <user directory to use>\n"+
685 "\t-Dpropertyname=value (Define the property value)\n";
686 }
687
688 /**
689 * Applies the command line arguments to the startup preferences. This function
690 * is mostly useful because it allows us to supply an arbitrary {@code args} array,
691 * link in {@link edu.wisc.ssec.mcidasv.McIDASV#main(String[])}.
692 *
693 * @param ignoreUnknown If {@code true} ignore any parameters that do not
694 * apply to the startup manager. If {@code false} the non-applicable
695 * parameters should signify an error.
696 * @param fromStartupManager Whether or not this call originated from the
697 * startup manager (rather than preferences).
698 * @param args Incoming command line arguments. Cannot be {@code null}.
699 *
700 * @throws NullPointerException if {@code args} is null.
701 *
702 * @see #getArgs(boolean, boolean, String[], Properties)
703 */
704 public static void applyArgs(final boolean ignoreUnknown, final boolean fromStartupManager, final String[] args) {
705 if (args == null) {
706 throw new NullPointerException("Arguments list cannot be null");
707 }
708 StartupManager sm = StartupManager.getInstance();
709 Platform platform = sm.getPlatform();
710
711 Properties props = getArgs(ignoreUnknown, fromStartupManager, args, getDefaultProperties());
712 platform.setUserDirectory(props.getProperty("userpath"));
713 platform.setAvailableMemory(props.getProperty(Constants.PROP_SYSMEM));
714 }
715
716 public static void main(String[] args) {
717 applyArgs(false, true, args);
718 StartupManager.getInstance().createDisplay();
719 }
720 }