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