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 }