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