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; 030 031 import static javax.swing.GroupLayout.Alignment.BASELINE; 032 import static javax.swing.GroupLayout.Alignment.LEADING; 033 import static javax.swing.GroupLayout.Alignment.TRAILING; 034 import static javax.swing.GroupLayout.DEFAULT_SIZE; 035 import static javax.swing.GroupLayout.PREFERRED_SIZE; 036 import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 037 038 import java.awt.CardLayout; 039 import java.awt.Color; 040 import java.awt.Component; 041 import java.awt.Container; 042 import java.awt.Dimension; 043 import java.awt.Font; 044 import java.awt.Graphics; 045 import java.awt.Graphics2D; 046 import java.awt.Insets; 047 import java.awt.RenderingHints; 048 import java.awt.event.ActionEvent; 049 import java.awt.event.ActionListener; 050 import java.beans.PropertyChangeEvent; 051 import java.beans.PropertyChangeListener; 052 import java.net.URL; 053 import java.text.DecimalFormat; 054 import java.util.ArrayList; 055 import java.util.Arrays; 056 import java.util.Collections; 057 import java.util.Enumeration; 058 import java.util.Hashtable; 059 import java.util.LinkedHashSet; 060 import java.util.List; 061 import java.util.Map; 062 import java.util.Set; 063 import java.util.TimeZone; 064 import java.util.Vector; 065 066 import javax.swing.BorderFactory; 067 import javax.swing.DefaultListCellRenderer; 068 import javax.swing.DefaultListModel; 069 import javax.swing.ImageIcon; 070 import javax.swing.JButton; 071 import javax.swing.JCheckBox; 072 import javax.swing.JComboBox; 073 import javax.swing.JComponent; 074 import javax.swing.JLabel; 075 import javax.swing.JList; 076 import javax.swing.JPanel; 077 import javax.swing.JRadioButton; 078 import javax.swing.JScrollPane; 079 import javax.swing.JTextField; 080 import javax.swing.ListSelectionModel; 081 import javax.swing.SwingUtilities; 082 import javax.swing.border.BevelBorder; 083 import javax.swing.event.ListSelectionEvent; 084 import javax.swing.event.ListSelectionListener; 085 086 import org.bushe.swing.event.annotation.AnnotationProcessor; 087 import org.bushe.swing.event.annotation.EventSubscriber; 088 import org.slf4j.Logger; 089 import org.slf4j.LoggerFactory; 090 import org.w3c.dom.Element; 091 import org.w3c.dom.NodeList; 092 093 import ucar.unidata.data.DataUtil; 094 import ucar.unidata.idv.ControlDescriptor; 095 import ucar.unidata.idv.DisplayControl; 096 import ucar.unidata.idv.IdvConstants; 097 import ucar.unidata.idv.IdvObjectStore; 098 import ucar.unidata.idv.IdvPreferenceManager; 099 import ucar.unidata.idv.IntegratedDataViewer; 100 import ucar.unidata.idv.MapViewManager; 101 import ucar.unidata.idv.ViewManager; 102 import ucar.unidata.idv.control.DisplayControlImpl; 103 import ucar.unidata.ui.CheckboxCategoryPanel; 104 import ucar.unidata.ui.FontSelector; 105 import ucar.unidata.ui.HelpTipDialog; 106 import ucar.unidata.ui.XmlUi; 107 import ucar.unidata.util.GuiUtils; 108 import ucar.unidata.util.IOUtil; 109 import ucar.unidata.util.LogUtil; 110 import ucar.unidata.util.Misc; 111 import ucar.unidata.util.Msg; 112 import ucar.unidata.util.ObjectListener; 113 import ucar.unidata.util.StringUtil; 114 import ucar.unidata.xml.PreferenceManager; 115 import ucar.unidata.xml.XmlObjectStore; 116 import ucar.unidata.xml.XmlUtil; 117 import ucar.visad.UtcDate; 118 import visad.DateTime; 119 import visad.Unit; 120 import edu.wisc.ssec.mcidasv.servermanager.EntryStore; 121 import edu.wisc.ssec.mcidasv.servermanager.AddePreferences; 122 import edu.wisc.ssec.mcidasv.servermanager.AddePreferences.AddePrefConglomeration; 123 import edu.wisc.ssec.mcidasv.startupmanager.Platform; 124 import edu.wisc.ssec.mcidasv.startupmanager.StartupManager; 125 import edu.wisc.ssec.mcidasv.ui.McvToolbarEditor; 126 import edu.wisc.ssec.mcidasv.ui.UIManager; 127 import edu.wisc.ssec.mcidasv.util.CollectionHelpers; 128 import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 129 import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 130 import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Prefer; 131 132 /** 133 * <p>An extension of {@link ucar.unidata.idv.IdvPreferenceManager} that uses 134 * a JList instead of tabs to lay out the various PreferenceManagers.</p> 135 * 136 * @author McIDAS-V Dev Team 137 */ 138 public class McIdasPreferenceManager extends IdvPreferenceManager implements ListSelectionListener, Constants { 139 140 /** Logger object. */ 141 private static final Logger logger = LoggerFactory.getLogger(McIdasPreferenceManager.class); 142 143 /** 144 * <p>Controls how the preference panel list is displayed. Want to modify 145 * the preferences UI in some way? PREF_PANELS is your friend. Think of 146 * it like a really brain-dead SQLite.</p> 147 * 148 * <p>Each row is a panel, and <b>must</b> consist of three columns: 149 * <ol start="0"> 150 * <li>Name of the panel.</li> 151 * <li>Path to the icon associated with the panel.</li> 152 * <li>The panel's {@literal "help ID."}</li> 153 * </ol> 154 * The {@link JList} in the preferences window will order the panels based 155 * upon {@code PREF_PANELS}. 156 * </p> 157 */ 158 public static final String[][] PREF_PANELS = { 159 { Constants.PREF_LIST_GENERAL, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/mcidasv-round32.png", "idv.tools.preferences.generalpreferences" }, 160 { Constants.PREF_LIST_VIEW, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/tab-new32.png", "idv.tools.preferences.displaywindowpreferences" }, 161 { Constants.PREF_LIST_TOOLBAR, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/application-x-executable32.png", "idv.tools.preferences.toolbarpreferences" }, 162 { Constants.PREF_LIST_DATA_CHOOSERS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/preferences-desktop-remote-desktop32.png", "idv.tools.preferences.datapreferences" }, 163 { Constants.PREF_LIST_ADDE_SERVERS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/applications-internet32.png", "idv.tools.preferences.serverpreferences" }, 164 { Constants.PREF_LIST_AVAILABLE_DISPLAYS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/video-display32.png", "idv.tools.preferences.availabledisplayspreferences" }, 165 { Constants.PREF_LIST_NAV_CONTROLS, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/input-mouse32.png", "idv.tools.preferences.navigationpreferences" }, 166 { Constants.PREF_LIST_FORMATS_DATA,"/edu/wisc/ssec/mcidasv/resources/icons/prefs/preferences-desktop-theme32.png", "idv.tools.preferences.formatpreferences" }, 167 { Constants.PREF_LIST_ADVANCED, "/edu/wisc/ssec/mcidasv/resources/icons/prefs/applications-internet32.png", "idv.tools.preferences.advancedpreferences" } 168 }; 169 170 /** Desired rendering hints with their desired values. */ 171 public static final Object[][] RENDER_HINTS = { 172 { RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON }, 173 { RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY }, 174 { RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON } 175 }; 176 177 /** Options for bundle loading */ 178 public static final String[] loadComboOptions = { 179 "Create new window(s)", 180 "Merge with active tab(s)", 181 "Add new tab(s) to current window", 182 "Replace session" 183 }; 184 185 /** 186 * @return The rendering hints to use, as determined by RENDER_HINTS. 187 */ 188 public static RenderingHints getRenderingHints() { 189 RenderingHints hints = new RenderingHints(null); 190 for (int i = 0; i < RENDER_HINTS.length; i++) { 191 hints.put(RENDER_HINTS[i][0], RENDER_HINTS[i][1]); 192 } 193 return hints; 194 } 195 196 /** Help McV remember the last preference panel the user selected. */ 197 private static final String LAST_PREF_PANEL = "mcv.prefs.lastpanel"; 198 199 private static final String LEGEND_TEMPLATE_DATA = "%datasourcename% - %displayname%"; 200 private static final String DISPLAY_LIST_TEMPLATE_DATA = "%datasourcename% - %displayname% " + UtcDate.MACRO_TIMESTAMP; 201 private static final String TEMPLATE_IMAGEDISPLAY = "%longname% " + UtcDate.MACRO_TIMESTAMP; 202 203 private static final String TEMPLATE_NO_DATA = "%displayname%"; 204 205 /** test value for formatting */ 206 private static double latlonValue = -104.56284; 207 208 /** Decimal format */ 209 private static DecimalFormat latlonFormat = new DecimalFormat(); 210 211 /** Provide some default values for the lat-lon preference drop down. */ 212 private static final Set<String> defaultLatLonFormats = CollectionHelpers.set("##0","##0.0","##0.0#","##0.0##","0.0","0.00","0.000"); 213 214 private static final Set<String> probeFormatsList = CollectionHelpers.set(DisplayControl.DEFAULT_PROBEFORMAT, "%rawvalue% [%rawunit%]", "%value%", "%rawvalue%", "%value% <i>%unit%</i>"); 215 216 /** 217 * Replacing the "incoming" IDV preference tab names with whatever's in 218 * this map. 219 */ 220 private static final Map<String, String> replaceMap = 221 CollectionHelpers.zipMap( 222 CollectionHelpers.arr("Toolbar", "View"), 223 CollectionHelpers.arr(Constants.PREF_LIST_TOOLBAR, Constants.PREF_LIST_VIEW)); 224 225 /** Path to the McV choosers.xml */ 226 private static final String MCV_CHOOSERS = "/edu/wisc/ssec/mcidasv/resources/choosers.xml"; 227 228 /** 229 * Maps the {@literal "name"} of a panel to the actual thing holding the 230 * PreferenceManager. 231 */ 232 private final Map<String, Container> prefMap = CollectionHelpers.concurrentMap(); 233 234 /** Maps the name of a panel to an icon. */ 235 private final Map<String, ImageIcon> iconCache = CollectionHelpers.concurrentMap(); 236 237 /** 238 * A table of the different preference managers that'll wind up in the 239 * list. 240 */ 241 private final Map<String, PreferenceManager> managerMap = CollectionHelpers.concurrentMap(); 242 243 /** 244 * Each PreferenceManager has associated data contained in this table. 245 * TODO: bug Unidata about getting IdvPreferenceManager's dataList protected 246 */ 247 private final Map<String, Object> dataMap = CollectionHelpers.concurrentMap(); 248 249 private final Set<String> labelSet = new LinkedHashSet<String>(); 250 251 /** 252 * The list that'll contain all the names of the different 253 * PreferenceManagers 254 */ 255 private JList labelList; 256 257 /** The "M" in the MVC for JLists. Contains all the list data. */ 258 private DefaultListModel listModel; 259 260 /** Handle scrolling like a pro. */ 261 private JScrollPane listScrollPane; 262 263 /** Holds the main preference pane */ 264 private JPanel mainPane; 265 266 /** Holds the buttons at the bottom */ 267 private JPanel buttonPane; 268 269 /** Date formats */ 270 private final Set<String> dateFormats = CollectionHelpers.set( 271 DEFAULT_DATE_FORMAT, "MM/dd/yy HH:mm z", "dd.MM.yy HH:mm z", 272 "yyyy-MM-dd", "EEE, MMM dd yyyy HH:mm z", "HH:mm:ss", "HH:mm", 273 "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd'T'HH:mm:ssZ"); 274 275 /** Is this a Unix-style platform? */ 276 private boolean isUnixLike = false; 277 278 /** Is this a Windows platform? */ 279 private boolean isWindows = false; 280 281 /** The toolbar editor */ 282 private McvToolbarEditor toolbarEditor; 283 284 /** */ 285 private String userDirectory; 286 287 /** */ 288 private String userPrefs; 289 290 /** */ 291 private String defaultPrefs; 292 293 /** 294 * Prep as much as possible for displaying the preference window: load up 295 * icons and create some of the window features. 296 * 297 * @param idv Reference to the supreme IDV object. 298 */ 299 public McIdasPreferenceManager(IntegratedDataViewer idv) { 300 super(idv); 301 AnnotationProcessor.process(this); 302 init(); 303 304 for (int i = 0; i < PREF_PANELS.length; i++) { 305 URL url = getClass().getResource(PREF_PANELS[i][1]); 306 iconCache.put(PREF_PANELS[i][0], new ImageIcon(url)); 307 } 308 309 setEmptyPref("idv.displaylist.template.data", DISPLAY_LIST_TEMPLATE_DATA); 310 setEmptyPref("idv.displaylist.template.nodata", TEMPLATE_NO_DATA); 311 setEmptyPref("idv.displaylist.template.imagedisplay", TEMPLATE_IMAGEDISPLAY); 312 setEmptyPref("idv.legendlabel.template.data", LEGEND_TEMPLATE_DATA); 313 setEmptyPref("idv.legendlabel.template.nodata", TEMPLATE_NO_DATA); 314 } 315 316 private boolean setEmptyPref(final String id, final String val) { 317 IdvObjectStore store = getIdv().getStore(); 318 if (store.get(id, (String)null) == null) { 319 store.put(id, val); 320 return true; 321 } 322 return false; 323 } 324 325 /** 326 * Overridden so McIDAS-V can direct users to specific help sections for 327 * each preference panel. 328 */ 329 @Override public void actionPerformed(ActionEvent event) { 330 String cmd = event.getActionCommand(); 331 if (!GuiUtils.CMD_HELP.equals(cmd) || labelList == null) { 332 super.actionPerformed(event); 333 return; 334 } 335 336 int selectedIndex = labelList.getSelectedIndex(); 337 getIdvUIManager().showHelp(PREF_PANELS[selectedIndex][2]); 338 } 339 340 public void replaceServerPrefPanel(final JPanel panel) { 341 String name = "SERVER MANAGER"; 342 mainPane.add(name, panel); 343 ((CardLayout)mainPane.getLayout()).show(mainPane, name); 344 } 345 346 @EventSubscriber(eventClass=EntryStore.Event.class) 347 public void replaceServerPreferences(EntryStore.Event evt) { 348 EntryStore remoteAddeStore = ((McIDASV)getIdv()).getServerManager(); 349 AddePreferences prefs = new AddePreferences(remoteAddeStore); 350 AddePrefConglomeration eww = prefs.buildPanel((McIDASV)getIdv()); 351 String name = "SERVER MANAGER"; 352 // mainPane.add(name, eww.getEntryPanel()); 353 // ((CardLayout)mainPane.getLayout()).show(mainPane, name); 354 } 355 356 /** 357 * Add a PreferenceManager to the list of things that should be shown in 358 * the preference dialog. 359 * 360 * @param tabLabel The label (or name) of the PreferenceManager. 361 * @param description Not used. 362 * @param listener The actual PreferenceManager. 363 * @param panel The container holding all of the PreferenceManager stuff. 364 * @param data Data passed to the preference manager. 365 */ 366 @Override public void add(String tabLabel, String description, 367 PreferenceManager listener, Container panel, Object data) { 368 369 // if there is an alternate name for tabLabel, find and use it. 370 if (replaceMap.containsKey(tabLabel) == true) { 371 tabLabel = replaceMap.get(tabLabel); 372 } 373 374 if (prefMap.containsKey(tabLabel) == true) { 375 return; 376 } 377 378 // figure out the last panel that was selected. 379 int selected = getIdv().getObjectStore().get(LAST_PREF_PANEL, 0); 380 if (selected < 0 || selected >= PREF_PANELS.length) { 381 logger.warn("attempted to select an invalid preference panel: {}", selected); 382 selected = 0; 383 } 384 String selectedPanel = PREF_PANELS[selected][0]; 385 386 panel.setPreferredSize(null); 387 388 Msg.translateTree(panel); 389 390 managerMap.put(tabLabel, listener); 391 if (data == null) { 392 dataMap.put(tabLabel, new Hashtable()); 393 } else { 394 dataMap.put(tabLabel, data); 395 } 396 prefMap.put(tabLabel, panel); 397 398 if (labelSet.add(tabLabel)) { 399 JLabel label = new JLabel(); 400 label.setText(tabLabel); 401 label.setIcon(iconCache.get(tabLabel)); 402 listModel.addElement(label); 403 404 labelList.setSelectedIndex(selected); 405 mainPane.add(tabLabel, panel); 406 if (selectedPanel.equals(tabLabel)) { 407 ((CardLayout)mainPane.getLayout()).show(mainPane, tabLabel); 408 } 409 } 410 411 mainPane.repaint(); 412 } 413 414 /** 415 * Apply the preferences (taken straight from IDV). 416 * TODO: bug Unidata about making managers and dataList protected instead of private 417 * 418 * @return Whether or not each of the preference managers applied properly. 419 */ 420 @Override public boolean apply() { 421 try { 422 for (String id : labelSet) { 423 PreferenceManager manager = managerMap.get(id); 424 manager.applyPreference(getStore(), dataMap.get(id)); 425 } 426 fixDisplayListFont(); 427 getStore().save(); 428 return true; 429 } catch (Exception exc) { 430 LogUtil.logException("Error applying preferences", exc); 431 return false; 432 } 433 } 434 435 // For some reason the display list font can have a size of zero if your 436 // new font size didn't change after starting the prefs panel. 437 private void fixDisplayListFont() { 438 IdvObjectStore s = getStore(); 439 Font f = s.get(ViewManager.PREF_DISPLAYLISTFONT, FontSelector.DEFAULT_FONT); 440 if (f.getSize() == 0) { 441 f = f.deriveFont(8f); 442 s.put(ViewManager.PREF_DISPLAYLISTFONT, f); 443 } 444 } 445 446 /** 447 * Select a list item and its corresponding panel that both live within the 448 * preference window JList. 449 * 450 * @param labelName The "name" of the JLabel within the JList. 451 */ 452 public void selectListItem(String labelName) { 453 show(); 454 toFront(); 455 456 for (int i = 0; i < listModel.getSize(); i++) { 457 String labelText = ((JLabel)listModel.get(i)).getText(); 458 if (StringUtil.stringMatch(labelText, labelName)) { 459 // persist across restarts 460 getIdv().getObjectStore().put(LAST_PREF_PANEL, i); 461 labelList.setSelectedIndex(i); 462 return; 463 } 464 } 465 } 466 467 /** 468 * Wrapper so that IDV code can still select which preference pane to show. 469 * 470 * @param tabNameToShow The name of the pane to be shown. Regular 471 * expressions are supported. 472 */ 473 public void showTab(String tabNameToShow) { 474 selectListItem(tabNameToShow); 475 } 476 477 /** 478 * Handle the user clicking around. 479 * 480 * @param e The event to be handled! Use your imagination! 481 */ 482 public void valueChanged(ListSelectionEvent e) { 483 if (e.getValueIsAdjusting() == false) { 484 String name = getSelectedName(); 485 ((CardLayout)mainPane.getLayout()).show(mainPane, name); 486 } 487 } 488 489 /** 490 * Returns the container the corresponds to the currently selected label in 491 * the JList. Also stores the selected panel so that the next time a user 492 * tries to open the preferences they will start off in the panel they last 493 * selected. 494 * 495 * @return The current container. 496 */ 497 private Container getSelectedPanel() { 498 // make sure the selected panel persists across restarts 499 getIdv().getObjectStore().put(LAST_PREF_PANEL, labelList.getSelectedIndex()); 500 String key = ((JLabel)listModel.getElementAt(labelList.getSelectedIndex())).getText(); 501 if (key.equals(Constants.PREF_LIST_NAV_CONTROLS)) { 502 return makeEventPanel(); 503 } 504 return prefMap.get(key); 505 } 506 507 private Container getSelectedPanel(final String name) { 508 if (Constants.PREF_LIST_NAV_CONTROLS.equals(name)) { 509 return makeEventPanel(); 510 } else if (prefMap.containsKey(name)) { 511 return prefMap.get(name); 512 } else { 513 return null; 514 } 515 } 516 517 /** 518 * Returns the container the corresponds to the currently selected label in 519 * the JList. Also stores the selected panel so that the next time a user 520 * tries to open the preferences they will start off in the panel they last 521 * selected. 522 * 523 * @return The current container. 524 */ 525 private String getSelectedName() { 526 // make sure the selected panel persists across restarts 527 getIdv().getObjectStore().put(LAST_PREF_PANEL, labelList.getSelectedIndex()); 528 String key = ((JLabel)listModel.getElementAt(labelList.getSelectedIndex())).getText(); 529 return key; 530 } 531 532 /** 533 * Perform the GUI initialization for the preference dialog. 534 */ 535 public void init() { 536 listModel = new DefaultListModel(); 537 labelList = new JList(listModel); 538 539 labelList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 540 labelList.setCellRenderer(new IconCellRenderer()); 541 labelList.addListSelectionListener(new ListSelectionListener() { 542 public void valueChanged(ListSelectionEvent e) { 543 if (e.getValueIsAdjusting() == false) { 544 String name = getSelectedName(); 545 if (Constants.PREF_LIST_NAV_CONTROLS.equals(name)) { 546 mainPane.add(name, makeEventPanel()); 547 mainPane.validate(); 548 } 549 ((CardLayout)mainPane.getLayout()).show(mainPane, name); 550 } 551 } 552 }); 553 554 listScrollPane = new JScrollPane(labelList); 555 listScrollPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); 556 557 mainPane = new JPanel(new CardLayout()); 558 mainPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); 559 mainPane.addPropertyChangeListener(new PropertyChangeListener() { 560 public void propertyChange(PropertyChangeEvent e) { 561 // System.err.println("prop change: prop="+e.getPropertyName()+" old="+e.getOldValue()+" new="+e.getNewValue()); 562 String p = e.getPropertyName(); 563 if (!"Frame.active".equals(p) && !"ancestor".equals(p)) { 564 return; 565 } 566 567 Object v = e.getNewValue(); 568 boolean okay = false; 569 if (v instanceof Boolean) { 570 okay = ((Boolean)v).booleanValue(); 571 } else if (v instanceof JPanel) { 572 okay = true; 573 } else { 574 okay = false; 575 } 576 577 if (okay) { 578 if (getSelectedName().equals(Constants.PREF_LIST_NAV_CONTROLS)) { 579 mainPane.add(Constants.PREF_LIST_NAV_CONTROLS, makeEventPanel()); 580 mainPane.validate(); 581 ((CardLayout)mainPane.getLayout()).show(mainPane, Constants.PREF_LIST_NAV_CONTROLS); 582 } 583 } 584 } 585 }); 586 587 JPanel buttons = GuiUtils.makeApplyOkHelpCancelButtons(this); 588 buttonPane = McVGuiUtils.makePrettyButtons(buttons); 589 590 contents = new JPanel(); 591 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(contents); 592 contents.setLayout(layout); 593 layout.setHorizontalGroup( 594 layout.createParallelGroup(LEADING) 595 .addGroup(layout.createSequentialGroup() 596 .addComponent(listScrollPane, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 597 .addPreferredGap(RELATED) 598 .addComponent(mainPane, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 599 .addComponent(buttonPane, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 600 ); 601 layout.setVerticalGroup( 602 layout.createParallelGroup(LEADING) 603 .addGroup(layout.createSequentialGroup() 604 .addGroup(layout.createParallelGroup(TRAILING) 605 .addComponent(mainPane, LEADING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 606 .addComponent(listScrollPane, LEADING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 607 .addPreferredGap(RELATED) 608 .addComponent(buttonPane, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) 609 ); 610 } 611 612 /** 613 * Initialize the preference dialog. Leave most of the heavy lifting to 614 * the IDV, except for creating the server manager. 615 */ 616 protected void initPreferences() { 617 // General/McIDAS-V 618 addMcVPreferences(); 619 620 // View/Display Window 621 addDisplayWindowPreferences(); 622 623 // Toolbar/Toolbar Options 624 addToolbarPreferences(); 625 626 // Available Choosers/Data Sources 627 addChooserPreferences(); 628 629 // ADDE Servers 630 addServerPreferences(); 631 632 // Available Displays/Display Types 633 addDisplayPreferences(); 634 635 // Navigation/Navigation Controls 636 addNavigationPreferences(); 637 638 // Formats & Data 639 addFormatDataPreferences(); 640 641 // Advanced 642 if (!labelSet.contains(Constants.PREF_LIST_ADVANCED)) { 643 // due to issue with MemoryOption.getTextComponent, we don't 644 // want to do this again if Advanced tab is already built. 645 // (the heap size text field will disappear on second opening 646 // of McV preferences window!) 647 addAdvancedPreferences(); 648 } 649 } 650 651 /** 652 * Build a {@link AddePreferences} panel {@literal "around"} the 653 * server manager {@link EntryStore}. 654 * 655 * @see McIDASV#getServerManager() 656 */ 657 public void addServerPreferences() { 658 EntryStore remoteAddeStore = ((McIDASV)getIdv()).getServerManager(); 659 AddePreferences prefs = new AddePreferences(remoteAddeStore); 660 prefs.addPanel(this); 661 } 662 663 /** 664 * Create the navigation preference panel 665 */ 666 public void addNavigationPreferences() { 667 PreferenceManager navigationManager = new PreferenceManager() { 668 public void applyPreference(XmlObjectStore theStore, Object data) { 669 // System.err.println("applying nav prefs"); 670 } 671 }; 672 this.add(Constants.PREF_LIST_NAV_CONTROLS, "", navigationManager, makeEventPanel(), new Hashtable()); 673 } 674 675 /** 676 * Create the toolbar preference panel 677 */ 678 public void addToolbarPreferences() { 679 if (toolbarEditor == null) { 680 toolbarEditor = 681 new McvToolbarEditor((UIManager)getIdv().getIdvUIManager()); 682 } 683 684 PreferenceManager toolbarManager = new PreferenceManager() { 685 public void applyPreference(XmlObjectStore s, Object d) { 686 if (toolbarEditor.anyChanges() == true) { 687 toolbarEditor.doApply(); 688 UIManager mngr = (UIManager)getIdv().getIdvUIManager(); 689 mngr.setCurrentToolbars(toolbarEditor); 690 } 691 } 692 }; 693 this.add("Toolbar", "Toolbar icons", toolbarManager, 694 toolbarEditor.getContents(), toolbarEditor); 695 } 696 697 /** 698 * Make a checkbox preference panel 699 * 700 * @param objects Holds (Label, preference id, Boolean default value). 701 * If preference id is null then just show the label. If the entry is only length 702 * 2 (i.e., no value) then default to true. 703 * @param widgets The map to store the id to widget 704 * @param store Where to look up the preference value 705 * 706 * @return The created panel 707 */ 708 @SuppressWarnings("unchecked") // idv-style. 709 public static JPanel makePrefPanel(final Object[][] objects, final Hashtable widgets, final XmlObjectStore store) { 710 List<JComponent> comps = CollectionHelpers.arrList(); 711 for (int i = 0; i < objects.length; i++) { 712 final String name = (String)objects[i][0]; 713 final String id = (String)objects[i][1]; 714 final boolean value = ((objects[i].length > 2) ? ((Boolean) objects[i][2]).booleanValue() : true); 715 716 if (id == null) { 717 if (i > 0) { 718 comps.add(new JLabel(" ")); 719 } 720 comps.add(new JLabel(name)); 721 continue; 722 } 723 724 final JCheckBox cb = new JCheckBox(name, store.get(id, value)); 725 cb.addPropertyChangeListener(new PropertyChangeListener() { 726 public void propertyChange(final PropertyChangeEvent e) { 727 SwingUtilities.invokeLater(new Runnable() { 728 public void run() { 729 boolean internalSel = store.get(id, value); 730 731 cb.setSelected(store.get(id, value)); 732 } 733 }); 734 } 735 }); 736 if (objects[i].length > 3) { 737 cb.setToolTipText(objects[i][3].toString()); 738 } 739 widgets.put(id, cb); 740 comps.add(cb); 741 } 742 return GuiUtils.top(GuiUtils.vbox(comps)); 743 } 744 745 public void addAdvancedPreferences() { 746 Hashtable<String, Component> widgets = new Hashtable<String, Component>(); 747 748 McIDASV mcv = (McIDASV)getIdv(); 749 750 // Build the threads panel 751 Vector threadRenderList = new Vector(); 752 for(int i = 1;i <= Runtime.getRuntime().availableProcessors();i++) { 753 threadRenderList.add(new Integer(i)); 754 } 755 Integer threadRenderMax = new Integer(mcv.getMaxRenderThreadCount()); 756 final JComboBox threadRenderComboBox = McVGuiUtils.makeComboBox(threadRenderList, threadRenderMax); 757 widgets.put(PREF_THREADS_RENDER, threadRenderComboBox); 758 759 Vector threadReadList = new Vector(); 760 for(int i = 1; i <= 12; i++) { 761 threadReadList.add(new Integer(i)); 762 } 763 Integer threadReadMax = new Integer(mcv.getMaxDataThreadCount()); 764 final JComboBox threadReadComboBox = McVGuiUtils.makeComboBox(threadReadList, threadReadMax); 765 widgets.put(PREF_THREADS_DATA, threadReadComboBox); 766 767 JPanel threadsPanel = McVGuiUtils.topBottom( 768 McVGuiUtils.makeLabeledComponent("Rendering:", threadRenderComboBox), 769 McVGuiUtils.makeLabeledComponent("Reading:", threadReadComboBox), 770 Prefer.NEITHER); 771 threadsPanel.setBorder(BorderFactory.createTitledBorder("Java Threads")); 772 773 // Build the startup options panel 774 final StartupManager startup = StartupManager.getInstance(); 775 Platform platform = startup.getPlatform(); 776 platform.setUserDirectory( 777 mcv.getObjectStore().getUserDirectory().toString()); 778 platform.setAvailableMemory( 779 mcv.getStateManager().getProperty(Constants.PROP_SYSMEM, "0")); 780 JPanel smPanel = startup.getAdvancedPanel(true); 781 List<JPanel> stuff = Collections.singletonList(smPanel); 782 783 PreferenceManager advancedManager = new PreferenceManager() { 784 public void applyPreference(XmlObjectStore theStore, Object data) { 785 IdvPreferenceManager.applyWidgets((Hashtable)data, theStore); 786 startup.handleApply(); 787 } 788 }; 789 790 JPanel outerPanel = new JPanel(); 791 792 // Outer panel layout 793 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(outerPanel); 794 outerPanel.setLayout(layout); 795 layout.setHorizontalGroup( 796 layout.createParallelGroup(LEADING) 797 .addGroup(layout.createSequentialGroup() 798 .addContainerGap() 799 .addGroup(layout.createParallelGroup(LEADING) 800 .addComponent(smPanel, TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 801 .addComponent(threadsPanel, TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 802 .addContainerGap()) 803 ); 804 layout.setVerticalGroup( 805 layout.createParallelGroup(LEADING) 806 .addGroup(layout.createSequentialGroup() 807 .addContainerGap() 808 .addComponent(smPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 809 .addGap(GAP_UNRELATED) 810 .addComponent(threadsPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 811 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 812 ); 813 814 this.add(Constants.PREF_LIST_ADVANCED, "complicated stuff dude", 815 advancedManager, outerPanel, widgets); 816 } 817 818 /** 819 * Add in the user preference tab for the controls to show 820 */ 821 protected void addDisplayPreferences() { 822 McIDASV mcv = (McIDASV)getIdv(); 823 cbxToCdMap = new Hashtable<JCheckBox, ControlDescriptor>(); 824 List<JPanel> compList = new ArrayList<JPanel>(); 825 List<ControlDescriptor> controlDescriptors = 826 getIdv().getAllControlDescriptors(); 827 828 final List<CheckboxCategoryPanel> catPanels = 829 new ArrayList<CheckboxCategoryPanel>(); 830 831 final Hashtable<String, CheckboxCategoryPanel> catMap = 832 new Hashtable<String, CheckboxCategoryPanel>(); 833 834 for (ControlDescriptor cd : controlDescriptors) { 835 836 final String displayCategory = cd.getDisplayCategory(); 837 838 CheckboxCategoryPanel catPanel = 839 (CheckboxCategoryPanel) catMap.get(displayCategory); 840 841 if (catPanel == null) { 842 catPanel = new CheckboxCategoryPanel(displayCategory, false); 843 catPanels.add(catPanel); 844 catMap.put(displayCategory, catPanel); 845 compList.add(catPanel.getTopPanel()); 846 compList.add(catPanel); 847 } 848 849 JCheckBox cbx = 850 new JCheckBox(cd.getLabel(), shouldShowControl(cd, true)); 851 cbx.setToolTipText(cd.getDescription()); 852 cbxToCdMap.put(cbx, cd); 853 catPanel.addItem(cbx); 854 catPanel.add(GuiUtils.inset(cbx, new Insets(0, 20, 0, 0))); 855 } 856 857 for (CheckboxCategoryPanel cbcp : catPanels) { 858 cbcp.checkVisCbx(); 859 } 860 861 final JButton allOn = new JButton("All on"); 862 allOn.addActionListener(new ActionListener() { 863 public void actionPerformed(ActionEvent ae) { 864 for (CheckboxCategoryPanel cbcp : catPanels) { 865 cbcp.toggleAll(true); 866 } 867 } 868 }); 869 final JButton allOff = new JButton("All off"); 870 allOff.addActionListener(new ActionListener() { 871 public void actionPerformed(ActionEvent ae) { 872 for (CheckboxCategoryPanel cbcp : catPanels) { 873 cbcp.toggleAll(false); 874 } 875 } 876 }); 877 878 Boolean controlsAll = 879 (Boolean)mcv.getPreference(PROP_CONTROLDESCRIPTORS_ALL, Boolean.TRUE); 880 final JRadioButton useAllBtn = new JRadioButton("Use all displays", 881 controlsAll.booleanValue()); 882 final JRadioButton useTheseBtn = 883 new JRadioButton("Use selected displays:", 884 !controlsAll.booleanValue()); 885 GuiUtils.buttonGroup(useAllBtn, useTheseBtn); 886 887 final JPanel cbPanel = GuiUtils.top(GuiUtils.vbox(compList)); 888 889 JScrollPane cbScroller = new JScrollPane(cbPanel); 890 cbScroller.getVerticalScrollBar().setUnitIncrement(10); 891 cbScroller.setPreferredSize(new Dimension(300, 300)); 892 893 JComponent exportComp = 894 GuiUtils.right(GuiUtils.makeButton("Export to Plugin", this, 895 "exportControlsToPlugin")); 896 897 JComponent cbComp = GuiUtils.centerBottom(cbScroller, exportComp); 898 899 JPanel bottomPanel = 900 GuiUtils.leftCenter( 901 GuiUtils.inset( 902 GuiUtils.top(GuiUtils.vbox(allOn, allOff)), 903 4), new Msg.SkipPanel( 904 GuiUtils.hgrid( 905 Misc.newList(cbComp, GuiUtils.filler()), 0))); 906 907 JPanel controlsPanel = 908 GuiUtils.inset(GuiUtils.topCenter(GuiUtils.hbox(useAllBtn, 909 useTheseBtn), bottomPanel), 6); 910 911 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 912 useAllBtn.addActionListener(new ActionListener() { 913 public void actionPerformed(ActionEvent ae) { 914 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 915 allOn.setEnabled(!useAllBtn.isSelected()); 916 allOff.setEnabled(!useAllBtn.isSelected()); 917 } 918 }); 919 920 useTheseBtn.addActionListener(new ActionListener() { 921 public void actionPerformed(ActionEvent ae) { 922 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 923 allOn.setEnabled(!useAllBtn.isSelected()); 924 allOff.setEnabled(!useAllBtn.isSelected()); 925 } 926 }); 927 928 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 929 930 allOn.setEnabled(!useAllBtn.isSelected()); 931 932 allOff.setEnabled(!useAllBtn.isSelected()); 933 934 PreferenceManager controlsManager = new PreferenceManager() { 935 public void applyPreference(XmlObjectStore theStore, Object data) { 936 controlDescriptorsToShow = new Hashtable(); 937 938 Hashtable<JCheckBox, ControlDescriptor> table = (Hashtable)data; 939 940 List<ControlDescriptor> controlDescriptors = getIdv().getAllControlDescriptors(); 941 942 for (Enumeration keys = table.keys(); keys.hasMoreElements(); ) { 943 JCheckBox cbx = (JCheckBox) keys.nextElement(); 944 ControlDescriptor cd = (ControlDescriptor)table.get(cbx); 945 controlDescriptorsToShow.put(cd.getControlId(), Boolean.valueOf(cbx.isSelected())); 946 } 947 948 showAllControls = useAllBtn.isSelected(); 949 950 theStore.put(PROP_CONTROLDESCRIPTORS, controlDescriptorsToShow); 951 theStore.put(PROP_CONTROLDESCRIPTORS_ALL, Boolean.valueOf(showAllControls)); 952 } 953 }; 954 955 this.add(Constants.PREF_LIST_AVAILABLE_DISPLAYS, 956 "What displays should be available in the user interface?", 957 controlsManager, controlsPanel, cbxToCdMap); 958 } 959 960 protected void addDisplayWindowPreferences() { 961 962 Hashtable<String, JCheckBox> widgets = new Hashtable<String, JCheckBox>(); 963 MapViewManager mappy = new MapViewManager(getIdv()); 964 965 Object[][] legendObjects = { 966 { "Show Side Legend", MapViewManager.PREF_SHOWSIDELEGEND, Boolean.valueOf(mappy.getShowSideLegend()) }, 967 { "Show Bottom Legend", MapViewManager.PREF_SHOWBOTTOMLEGEND, Boolean.valueOf(mappy.getShowBottomLegend()) } 968 }; 969 JPanel legendPanel = makePrefPanel(legendObjects, widgets, getStore()); 970 legendPanel.setBorder(BorderFactory.createTitledBorder("Legends")); 971 972 Object[][] navigationObjects = { 973 { "Show Earth Navigation Panel", MapViewManager.PREF_SHOWEARTHNAVPANEL, Boolean.valueOf(mappy.getShowEarthNavPanel()) }, 974 { "Show Viewpoint Toolbar", MapViewManager.PREF_SHOWTOOLBAR + "perspective" }, 975 { "Show Zoom/Pan Toolbar", MapViewManager.PREF_SHOWTOOLBAR + "zoompan" }, 976 { "Show Undo/Redo Toolbar", MapViewManager.PREF_SHOWTOOLBAR + "undoredo" } 977 }; 978 JPanel navigationPanel = makePrefPanel(navigationObjects, widgets, getStore()); 979 navigationPanel.setBorder(BorderFactory.createTitledBorder("Navigation Toolbars")); 980 981 Object[][] panelObjects = { 982 { "Show Globe Background", MapViewManager.PREF_SHOWGLOBEBACKGROUND, Boolean.valueOf(getStore().get(MapViewManager.PREF_SHOWGLOBEBACKGROUND, false)) }, 983 { "Show Wireframe Box", MapViewManager.PREF_WIREFRAME, Boolean.valueOf(mappy.getWireframe()) }, 984 { "Show Cursor Readout", MapViewManager.PREF_SHOWCURSOR, Boolean.valueOf(mappy.getShowCursor()) }, 985 { "Clip View At Box", MapViewManager.PREF_3DCLIP, Boolean.valueOf(mappy.getClipping()) }, 986 { "Show Layer List in Panel", MapViewManager.PREF_SHOWDISPLAYLIST, Boolean.valueOf(mappy.getShowDisplayList()) }, 987 { "Show Times In Panel", MapViewManager.PREF_ANIREADOUT, Boolean.valueOf(mappy.getAniReadout()) }, 988 { "Show Map Display Scales", MapViewManager.PREF_SHOWSCALES, Boolean.valueOf(mappy.getLabelsVisible()) }, 989 { "Show Transect Display Scales", MapViewManager.PREF_SHOWTRANSECTSCALES, Boolean.valueOf(mappy.getTransectLabelsVisible()) }, 990 { "Show \"Please Wait\" Message", MapViewManager.PREF_WAITMSG, Boolean.valueOf(mappy.getWaitMessageVisible()) }, 991 { "Reset Projection With New Data", MapViewManager.PREF_PROJ_USEFROMDATA } 992 }; 993 JPanel panelPanel = makePrefPanel(panelObjects, widgets, getStore()); 994 panelPanel.setBorder(BorderFactory.createTitledBorder("Panel Configuration")); 995 996 final JComponent[] globeBg = 997 GuiUtils.makeColorSwatchWidget(mappy.getGlobeBackgroundColorToUse(), 998 "Set Globe Background Color"); 999 final JComponent[] bgComps = 1000 GuiUtils.makeColorSwatchWidget(getStore().get(MapViewManager.PREF_BGCOLOR, 1001 mappy.getBackground()), "Set Background Color"); 1002 final JComponent[] fgComps = 1003 GuiUtils.makeColorSwatchWidget(getStore().get(MapViewManager.PREF_FGCOLOR, 1004 mappy.getForeground()), "Set Foreground Color"); 1005 final JComponent[] border = 1006 GuiUtils.makeColorSwatchWidget(getStore().get(MapViewManager.PREF_BORDERCOLOR, 1007 Constants.MCV_BLUE_DARK), "Set Selected Panel Border Color"); 1008 1009 JPanel colorPanel = GuiUtils.vbox( 1010 GuiUtils.hbox( 1011 McVGuiUtils.makeLabelRight("Globe Background:", Width.ONEHALF), 1012 GuiUtils.left(globeBg[0]), 1013 GAP_RELATED 1014 ), 1015 GuiUtils.hbox( 1016 McVGuiUtils.makeLabelRight("Background:", Width.ONEHALF), 1017 GuiUtils.left(bgComps[0]), 1018 GAP_RELATED 1019 ), 1020 GuiUtils.hbox( 1021 McVGuiUtils.makeLabelRight("Foreground:", Width.ONEHALF), 1022 GuiUtils.left(fgComps[0]), 1023 GAP_RELATED 1024 ), 1025 GuiUtils.hbox( 1026 McVGuiUtils.makeLabelRight("Selected Panel:", Width.ONEHALF), 1027 GuiUtils.left(border[0]), 1028 GAP_RELATED 1029 ) 1030 ); 1031 1032 colorPanel.setBorder(BorderFactory.createTitledBorder("Color Scheme")); 1033 1034 final FontSelector fontSelector = new FontSelector(FontSelector.COMBOBOX_UI, false, false); 1035 Font f = getStore().get(MapViewManager.PREF_DISPLAYLISTFONT, mappy.getDisplayListFont()); 1036 fontSelector.setFont(f); 1037 final GuiUtils.ColorSwatch dlColorWidget = 1038 new GuiUtils.ColorSwatch(getStore().get(MapViewManager.PREF_DISPLAYLISTCOLOR, 1039 mappy.getDisplayListColor()), "Set Display List Color"); 1040 1041 JPanel fontPanel = GuiUtils.vbox( 1042 GuiUtils.hbox( 1043 McVGuiUtils.makeLabelRight("Font:", Width.ONEHALF), 1044 GuiUtils.left(fontSelector.getComponent()), 1045 GAP_RELATED 1046 ), 1047 GuiUtils.hbox( 1048 McVGuiUtils.makeLabelRight("Color:", Width.ONEHALF), 1049 GuiUtils.left(GuiUtils.hbox(dlColorWidget, dlColorWidget.getClearButton(), GAP_RELATED)), 1050 GAP_RELATED 1051 ) 1052 ); 1053 fontPanel.setBorder(BorderFactory.createTitledBorder("Layer List Properties")); 1054 1055 final JComboBox projBox = new JComboBox(); 1056 GuiUtils.setListData(projBox, mappy.getProjectionList().toArray()); 1057 Object defaultProj = mappy.getDefaultProjection(); 1058 if (defaultProj != null) projBox.setSelectedItem(defaultProj); 1059 JPanel projPanel = GuiUtils.left(projBox); 1060 projPanel.setBorder(BorderFactory.createTitledBorder("Default Projection")); 1061 1062 JPanel outerPanel = new JPanel(); 1063 1064 // Outer panel layout 1065 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(outerPanel); 1066 outerPanel.setLayout(layout); 1067 layout.setHorizontalGroup( 1068 layout.createParallelGroup(LEADING) 1069 .addGroup(layout.createSequentialGroup() 1070 .addContainerGap() 1071 .addGroup(layout.createParallelGroup(LEADING) 1072 .addComponent(navigationPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1073 .addComponent(panelPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1074 .addGap(GAP_RELATED) 1075 .addGroup(layout.createParallelGroup(LEADING) 1076 .addComponent(colorPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1077 .addComponent(legendPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1078 .addComponent(fontPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1079 .addComponent(projPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1080 .addContainerGap()) 1081 ); 1082 layout.setVerticalGroup( 1083 layout.createParallelGroup(LEADING) 1084 .addGroup(layout.createSequentialGroup() 1085 .addContainerGap() 1086 .addGroup(layout.createParallelGroup(LEADING, false) 1087 .addComponent(navigationPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1088 .addComponent(legendPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1089 .addPreferredGap(RELATED) 1090 .addGroup(layout.createParallelGroup(LEADING, false) 1091 .addGroup(layout.createSequentialGroup() 1092 .addComponent(colorPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 1093 .addPreferredGap(RELATED) 1094 .addComponent(fontPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 1095 .addPreferredGap(RELATED) 1096 .addComponent(projPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) 1097 .addComponent(panelPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1098 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1099 ); 1100 1101 PreferenceManager miscManager = new PreferenceManager() { 1102 @SuppressWarnings("unchecked") // applyWidgets called the same way the IDV does it. 1103 public void applyPreference(XmlObjectStore theStore, Object data) { 1104 IdvPreferenceManager.applyWidgets((Hashtable)data, theStore); 1105 theStore.put(MapViewManager.PREF_PROJ_DFLT, projBox.getSelectedItem()); 1106 theStore.put(MapViewManager.PREF_BGCOLOR, bgComps[0].getBackground()); 1107 theStore.put(MapViewManager.PREF_FGCOLOR, fgComps[0].getBackground()); 1108 theStore.put(MapViewManager.PREF_BORDERCOLOR, border[0].getBackground()); 1109 theStore.put(MapViewManager.PREF_DISPLAYLISTFONT, fontSelector.getFont()); 1110 theStore.put(MapViewManager.PREF_DISPLAYLISTCOLOR, dlColorWidget.getSwatchColor()); 1111 theStore.put(MapViewManager.PREF_GLOBEBACKGROUND, globeBg[0].getBackground()); 1112 ViewManager.setHighlightBorder(border[0].getBackground()); 1113 } 1114 }; 1115 1116 this.add(Constants.PREF_LIST_VIEW, "Display Window Preferences", miscManager, outerPanel, widgets); 1117 } 1118 1119 /** 1120 * Creates and adds the basic preference panel. 1121 */ 1122 protected void addMcVPreferences() { 1123 1124 Hashtable<String, Component> widgets = new Hashtable<String, Component>(); 1125 McIDASV mcv = (McIDASV)getIdv(); 1126 StateManager sm = (edu.wisc.ssec.mcidasv.StateManager)mcv.getStateManager(); 1127 1128 PreferenceManager basicManager = new PreferenceManager() { 1129 @SuppressWarnings("unchecked") // IDV-style call to applyWidgets. 1130 public void applyPreference(XmlObjectStore theStore, Object data) { 1131 applyWidgets((Hashtable)data, theStore); 1132 getIdv().getIdvUIManager().setDateFormat(); 1133 getIdv().initCacheManager(); 1134 applyEventPreferences(theStore); 1135 } 1136 }; 1137 1138 boolean isPrerelease = sm.getIsPrerelease(); 1139 Object[][] generalObjects = { 1140 { "Show Help Tips on start", HelpTipDialog.PREF_HELPTIPSHOW }, 1141 { "Show Data Explorer on start", PREF_SHOWDASHBOARD, Boolean.TRUE }, 1142 { "Check for new version and notice on start", Constants.PREF_VERSION_CHECK, Boolean.TRUE }, 1143 { "Include prereleases in version check", Constants.PREF_PRERELEASE_CHECK, isPrerelease }, 1144 { "Confirm before exiting", PREF_SHOWQUITCONFIRM }, 1145 { "Automatically save default layout at exit", Constants.PREF_AUTO_SAVE_DEFAULT_LAYOUT, Boolean.FALSE }, 1146 { "Save visibility of Data Explorer", Constants.PREF_SAVE_DASHBOARD_VIZ, Boolean.FALSE }, 1147 { "Confirm removal of all data sources", PREF_CONFIRM_REMOVE_DATA, Boolean.TRUE }, 1148 { "Confirm removal of all layers", PREF_CONFIRM_REMOVE_LAYERS, Boolean.TRUE }, 1149 { "Confirm removal of all layers and data sources", PREF_CONFIRM_REMOVE_BOTH, Boolean.TRUE }, 1150 }; 1151 final IdvObjectStore store = getStore(); 1152 JPanel generalPanel = makePrefPanel(generalObjects, widgets, store); 1153 generalPanel.setBorder(BorderFactory.createTitledBorder("General")); 1154 1155 // Turn what used to be a set of checkboxes into a corresponding menu selection 1156 // The options have to be checkboxes in the widget collection 1157 // That way "applyWidgets" will work as expected 1158 boolean shouldRemove = store.get(PREF_OPEN_REMOVE, false); 1159 boolean shouldMerge = store.get(PREF_OPEN_MERGE, false); 1160 final JCheckBox shouldRemoveCbx = new JCheckBox("You shouldn't see this", shouldRemove); 1161 final JCheckBox shouldMergeCbx = new JCheckBox("You shouldn't see this", shouldMerge); 1162 widgets.put(PREF_OPEN_REMOVE, shouldRemoveCbx); 1163 widgets.put(PREF_OPEN_MERGE, shouldMergeCbx); 1164 1165 final JComboBox loadComboBox = new JComboBox(loadComboOptions); 1166 loadComboBox.addActionListener(new ActionListener() { 1167 public void actionPerformed(ActionEvent e) { 1168 switch (((JComboBox)e.getSource()).getSelectedIndex()) { 1169 case 0: 1170 shouldRemoveCbx.setSelected(false); 1171 shouldMergeCbx.setSelected(false); 1172 break; 1173 case 1: 1174 shouldRemoveCbx.setSelected(true); 1175 shouldMergeCbx.setSelected(false); 1176 break; 1177 case 2: 1178 shouldRemoveCbx.setSelected(false); 1179 shouldMergeCbx.setSelected(true); 1180 break; 1181 case 3: 1182 shouldRemoveCbx.setSelected(true); 1183 shouldMergeCbx.setSelected(true); 1184 break; 1185 } 1186 } 1187 }); 1188 1189 // update the bundle loading options upon visibility changes. 1190 loadComboBox.addPropertyChangeListener(new PropertyChangeListener() { 1191 public void propertyChange(final PropertyChangeEvent e) { 1192 String prop = e.getPropertyName(); 1193 if (!"ancestor".equals(prop) && !"Frame.active".equals(prop)) { 1194 return; 1195 } 1196 1197 boolean remove = store.get(PREF_OPEN_REMOVE, false); 1198 boolean merge = store.get(PREF_OPEN_MERGE, false); 1199 1200 if (!remove) { 1201 if (!merge) { 1202 loadComboBox.setSelectedIndex(0); 1203 } else { 1204 loadComboBox.setSelectedIndex(2); 1205 } 1206 } 1207 else { 1208 if (!merge) { 1209 loadComboBox.setSelectedIndex(1); 1210 } else { 1211 loadComboBox.setSelectedIndex(3); 1212 } 1213 } 1214 } 1215 }); 1216 1217 if (!shouldRemove) { 1218 if (!shouldMerge) { 1219 loadComboBox.setSelectedIndex(0); 1220 } else { 1221 loadComboBox.setSelectedIndex(2); 1222 } 1223 } 1224 else { 1225 if (!shouldMerge) { 1226 loadComboBox.setSelectedIndex(1); 1227 } else { 1228 loadComboBox.setSelectedIndex(3); 1229 } 1230 } 1231 1232 Object[][] bundleObjects = { 1233 { "Prompt when opening bundles", PREF_OPEN_ASK }, 1234 { "Prompt for location for zipped data", PREF_ZIDV_ASK } 1235 }; 1236 JPanel bundlePanelInner = makePrefPanel(bundleObjects, widgets, getStore()); 1237 JPanel bundlePanel = GuiUtils.topCenter(loadComboBox, bundlePanelInner); 1238 bundlePanel.setBorder(BorderFactory.createTitledBorder("When Opening a Bundle")); 1239 1240 Object[][] layerObjects = { 1241 { "Show windows when they are created", PREF_SHOWCONTROLWINDOW }, 1242 { "Use fast rendering", PREF_FAST_RENDER, Boolean.FALSE, "<html>Turn this on for better performance at the risk of having funky displays</html>" }, 1243 { "Auto-select data when loading a template", IdvConstants.PREF_AUTOSELECTDATA, Boolean.FALSE, "<html>When loading a display template should the data be automatically selected</html>" }, 1244 }; 1245 JPanel layerPanel = makePrefPanel(layerObjects, widgets, getStore()); 1246 layerPanel.setBorder(BorderFactory.createTitledBorder("Layer Controls")); 1247 1248 Object[][] layerclosedObjects = { 1249 { "Remove the display", DisplayControl.PREF_REMOVEONWINDOWCLOSE, Boolean.FALSE }, 1250 { "Remove standalone displays", DisplayControl.PREF_STANDALONE_REMOVEONCLOSE, Boolean.FALSE } 1251 }; 1252 JPanel layerclosedPanel = makePrefPanel(layerclosedObjects, widgets, getStore()); 1253 layerclosedPanel.setBorder(BorderFactory.createTitledBorder("When Layer Control Window is Closed")); 1254 1255 JPanel outerPanel = new JPanel(); 1256 1257 // Outer panel layout 1258 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(outerPanel); 1259 outerPanel.setLayout(layout); 1260 layout.setHorizontalGroup( 1261 layout.createParallelGroup(LEADING) 1262 .addGroup(layout.createSequentialGroup() 1263 .addContainerGap() 1264 .addGroup(layout.createParallelGroup(TRAILING) 1265 .addComponent(generalPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1266 .addComponent(layerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1267 .addGap(GAP_RELATED) 1268 .addGroup(layout.createParallelGroup(LEADING) 1269 .addComponent(bundlePanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1270 .addComponent(layerclosedPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1271 .addContainerGap()) 1272 ); 1273 layout.setVerticalGroup( 1274 layout.createParallelGroup(LEADING) 1275 .addGroup(layout.createSequentialGroup() 1276 .addContainerGap() 1277 .addGroup(layout.createParallelGroup(LEADING, false) 1278 .addComponent(bundlePanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1279 .addComponent(generalPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1280 .addPreferredGap(RELATED) 1281 .addGroup(layout.createParallelGroup(LEADING, false) 1282 .addComponent(layerclosedPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1283 .addComponent(layerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1284 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1285 ); 1286 1287 this.add(Constants.PREF_LIST_GENERAL, "General Preferences", basicManager, outerPanel, widgets); 1288 } 1289 1290 /** 1291 * <p>This determines whether the IDV should do a remove display and data 1292 * before a bundle is loaded. It returns a 2 element boolean array. The 1293 * first element is whether the open should take place at all. The second 1294 * element determines whether displays and data should be removed before 1295 * the load.</p> 1296 * 1297 * <p>Overridden by McIDAS-V so that we can ask the user whether or not we 1298 * should limit the number of new windows a bundle can create.</p> 1299 * 1300 * @param name Bundle name - may be null. 1301 * 1302 * @return Element 0: did user hit cancel; Element 1: Should remove data 1303 * and displays; Element 2: limit new windows. 1304 * 1305 * @see IdvPreferenceManager#getDoRemoveBeforeOpening(String) 1306 */ 1307 @Override public boolean[] getDoRemoveBeforeOpening(String name) { 1308 IdvObjectStore store = getStore(); 1309 boolean shouldAsk = store.get(PREF_OPEN_ASK, true); 1310 boolean shouldRemove = store.get(PREF_OPEN_REMOVE, false); 1311 boolean shouldMerge = store.get(PREF_OPEN_MERGE, false); 1312 1313 if (shouldAsk) { 1314 JComboBox loadComboBox = new JComboBox(loadComboOptions); 1315 JCheckBox preferenceCbx = new JCheckBox("Save as default preference", true); 1316 JCheckBox askCbx = new JCheckBox("Don't show this window again", false); 1317 1318 if (!shouldRemove) { 1319 if (!shouldMerge) { 1320 loadComboBox.setSelectedIndex(0); 1321 } else { 1322 loadComboBox.setSelectedIndex(2); 1323 } 1324 } 1325 else { 1326 if (!shouldMerge) { 1327 loadComboBox.setSelectedIndex(1); 1328 } else { 1329 loadComboBox.setSelectedIndex(3); 1330 } 1331 } 1332 1333 JPanel inner = new JPanel(); 1334 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(inner); 1335 inner.setLayout(layout); 1336 layout.setHorizontalGroup( 1337 layout.createParallelGroup(LEADING) 1338 .addGroup(layout.createSequentialGroup() 1339 .addContainerGap() 1340 .addGroup(layout.createParallelGroup(LEADING) 1341 .addComponent(loadComboBox, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1342 .addComponent(preferenceCbx) 1343 .addComponent(askCbx)) 1344 .addContainerGap()) 1345 ); 1346 layout.setVerticalGroup( 1347 layout.createParallelGroup(LEADING) 1348 .addGroup(layout.createSequentialGroup() 1349 .addContainerGap() 1350 .addComponent(loadComboBox, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 1351 .addPreferredGap(RELATED) 1352 .addComponent(preferenceCbx) 1353 .addPreferredGap(RELATED) 1354 .addComponent(askCbx) 1355 .addContainerGap()) 1356 ); 1357 1358 if (!GuiUtils.showOkCancelDialog(null, "Open bundle", inner, null)) { 1359 return new boolean[] { false, false, false }; 1360 } 1361 1362 switch (loadComboBox.getSelectedIndex()) { 1363 case 0: // new windows 1364 shouldRemove = false; 1365 shouldMerge = false; 1366 break; 1367 case 1: // merge with existing tabs 1368 shouldRemove = true; 1369 shouldMerge = false; 1370 break; 1371 case 2: // add new tab(s) to current 1372 shouldRemove = false; 1373 shouldMerge = true; 1374 break; 1375 case 3: // replace session 1376 shouldRemove = true; 1377 shouldMerge = true; 1378 break; 1379 } 1380 1381 // Save these as default preference if the user wants to 1382 if (preferenceCbx.isSelected()) { 1383 store.put(PREF_OPEN_REMOVE, shouldRemove); 1384 store.put(PREF_OPEN_MERGE, shouldMerge); 1385 } 1386 store.put(PREF_OPEN_ASK, !askCbx.isSelected()); 1387 } 1388 return new boolean[] { true, shouldRemove, shouldMerge }; 1389 } 1390 1391 /** 1392 * Creates and adds the formats and data preference panel. 1393 */ 1394 protected void addFormatDataPreferences() { 1395 Hashtable<String, Component> widgets = new Hashtable<String, Component>(); 1396 1397 JPanel formatPanel = new JPanel(); 1398 formatPanel.setBorder(BorderFactory.createTitledBorder("Formats")); 1399 1400 // Date stuff 1401 JLabel dateLabel = McVGuiUtils.makeLabelRight("Date Format:", Width.ONEHALF); 1402 1403 String dateFormat = getStore().get(PREF_DATE_FORMAT, DEFAULT_DATE_FORMAT); 1404 1405 if (!dateFormats.contains(dateFormat)) { 1406 dateFormats.add(dateFormat); 1407 } 1408 1409 final JComboBox dateComboBox = McVGuiUtils.makeComboBox(dateFormats, dateFormat, Width.DOUBLE); 1410 widgets.put(PREF_DATE_FORMAT, dateComboBox); 1411 1412 JComponent dateHelpButton = getIdv().makeHelpButton("idv.tools.preferences.dateformat"); 1413 1414 JLabel dateExLabel = new JLabel(""); 1415 1416 // Time stuff 1417 JLabel timeLabel = McVGuiUtils.makeLabelRight("Time Zone:", Width.ONEHALF); 1418 1419 String timeString = getStore().get(PREF_TIMEZONE, DEFAULT_TIMEZONE); 1420 String[] zoneStrings = TimeZone.getAvailableIDs(); 1421 Arrays.sort(zoneStrings); 1422 1423 final JComboBox timeComboBox = McVGuiUtils.makeComboBox(zoneStrings, timeString, Width.DOUBLE); 1424 widgets.put(PREF_TIMEZONE, timeComboBox); 1425 1426 JComponent timeHelpButton = getIdv().makeHelpButton("idv.tools.preferences.dateformat"); 1427 1428 JLabel timeExLabel = new JLabel(""); 1429 1430 try { 1431 dateExLabel.setText("ex: " + new DateTime().toString()); 1432 } catch (Exception ve) { 1433 dateExLabel.setText("Can't format date: " + ve); 1434 } 1435 1436 ObjectListener timeLabelListener = new ObjectListener(dateExLabel) { 1437 public void actionPerformed(ActionEvent ae) { 1438 JLabel label = (JLabel) theObject; 1439 String format = dateComboBox.getSelectedItem().toString(); 1440 String zone = timeComboBox.getSelectedItem().toString(); 1441 try { 1442 TimeZone tz = TimeZone.getTimeZone(zone); 1443 // hack to make it the DateTime default 1444 if (format.equals(DEFAULT_DATE_FORMAT)) { 1445 if (zone.equals(DEFAULT_TIMEZONE)) { 1446 format = DateTime.DEFAULT_TIME_FORMAT + "'Z'"; 1447 } 1448 } 1449 label.setText("ex: " + new DateTime().formattedString(format, tz)); 1450 } catch (Exception ve) { 1451 label.setText("Invalid format or time zone"); 1452 LogUtil.userMessage("Invalid format or time zone"); 1453 } 1454 } 1455 }; 1456 dateComboBox.addActionListener(timeLabelListener); 1457 timeComboBox.addActionListener(timeLabelListener); 1458 1459 // Lat/Lon stuff 1460 JLabel latlonLabel = McVGuiUtils.makeLabelRight("Lat/Lon Format:", Width.ONEHALF); 1461 1462 String latlonFormatString = getStore().get(PREF_LATLON_FORMAT, "##0.0"); 1463 JComboBox latlonComboBox = McVGuiUtils.makeComboBox(defaultLatLonFormats, latlonFormatString, Width.DOUBLE); 1464 widgets.put(PREF_LATLON_FORMAT, latlonComboBox); 1465 1466 JComponent latlonHelpButton = getIdv().makeHelpButton("idv.tools.preferences.latlonformat"); 1467 1468 JLabel latlonExLabel = new JLabel(""); 1469 1470 try { 1471 latlonFormat.applyPattern(latlonFormatString); 1472 latlonExLabel.setText("ex: " + latlonFormat.format(latlonValue)); 1473 } catch (IllegalArgumentException iae) { 1474 latlonExLabel.setText("Bad format: " + latlonFormatString); 1475 } 1476 latlonComboBox.addActionListener(new ObjectListener(latlonExLabel) { 1477 public void actionPerformed(final ActionEvent ae) { 1478 JLabel label = (JLabel)theObject; 1479 JComboBox box = (JComboBox)ae.getSource(); 1480 String pattern = box.getSelectedItem().toString(); 1481 try { 1482 latlonFormat.applyPattern(pattern); 1483 label.setText("ex: " + latlonFormat.format(latlonValue)); 1484 } catch (IllegalArgumentException iae) { 1485 label.setText("bad pattern: " + pattern); 1486 LogUtil.userMessage("Bad format:" + pattern); 1487 } 1488 } 1489 }); 1490 1491 // Probe stuff 1492 JLabel probeLabel = McVGuiUtils.makeLabelRight("Probe Format:", Width.ONEHALF); 1493 1494 String probeFormat = getStore().get(DisplayControl.PREF_PROBEFORMAT, DisplayControl.DEFAULT_PROBEFORMAT); 1495 // List probeFormatsList = Misc.newList(DisplayControl.DEFAULT_PROBEFORMAT, 1496 // "%rawvalue% [%rawunit%]", "%value%", "%rawvalue%", "%value% <i>%unit%</i>"); 1497 JComboBox probeComboBox = McVGuiUtils.makeComboBox(probeFormatsList, probeFormat, Width.DOUBLE); 1498 widgets.put(DisplayControl.PREF_PROBEFORMAT, probeComboBox); 1499 1500 JComponent probeHelpButton = getIdv().makeHelpButton("idv.tools.preferences.probeformat"); 1501 1502 // Distance stuff 1503 JLabel distanceLabel = McVGuiUtils.makeLabelRight("Distance Unit:", Width.ONEHALF); 1504 1505 Unit distanceUnit = null; 1506 try { 1507 distanceUnit = ucar.visad.Util.parseUnit(getStore().get(PREF_DISTANCEUNIT, "km")); 1508 } catch (Exception exc) {} 1509 JComboBox distanceComboBox = getIdv().getDisplayConventions().makeUnitBox(distanceUnit, null); 1510 McVGuiUtils.setComponentWidth(distanceComboBox, Width.DOUBLE); 1511 widgets.put(PREF_DISTANCEUNIT, distanceComboBox); 1512 1513 // Format panel layout 1514 javax.swing.GroupLayout formatLayout = new javax.swing.GroupLayout(formatPanel); 1515 formatPanel.setLayout(formatLayout); 1516 formatLayout.setHorizontalGroup( 1517 formatLayout.createParallelGroup(LEADING) 1518 .addGroup(formatLayout.createSequentialGroup() 1519 .addContainerGap() 1520 .addGroup(formatLayout.createParallelGroup(LEADING) 1521 .addGroup(formatLayout.createSequentialGroup() 1522 .addComponent(dateLabel) 1523 .addGap(GAP_RELATED) 1524 .addComponent(dateComboBox) 1525 .addGap(GAP_RELATED) 1526 .addComponent(dateHelpButton) 1527 .addGap(GAP_RELATED) 1528 .addComponent(dateExLabel)) 1529 .addGroup(formatLayout.createSequentialGroup() 1530 .addComponent(timeLabel) 1531 .addGap(GAP_RELATED) 1532 .addComponent(timeComboBox)) 1533 .addGroup(formatLayout.createSequentialGroup() 1534 .addComponent(latlonLabel) 1535 .addGap(GAP_RELATED) 1536 .addComponent(latlonComboBox) 1537 .addGap(GAP_RELATED) 1538 .addComponent(latlonHelpButton) 1539 .addGap(GAP_RELATED) 1540 .addComponent(latlonExLabel)) 1541 .addGroup(formatLayout.createSequentialGroup() 1542 .addComponent(probeLabel) 1543 .addGap(GAP_RELATED) 1544 .addComponent(probeComboBox) 1545 .addGap(GAP_RELATED) 1546 .addComponent(probeHelpButton)) 1547 .addGroup(formatLayout.createSequentialGroup() 1548 .addComponent(distanceLabel) 1549 .addGap(GAP_RELATED) 1550 .addComponent(distanceComboBox))) 1551 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1552 ); 1553 formatLayout.setVerticalGroup( 1554 formatLayout.createParallelGroup(LEADING) 1555 .addGroup(formatLayout.createSequentialGroup() 1556 .addGroup(formatLayout.createParallelGroup(BASELINE) 1557 .addComponent(dateComboBox) 1558 .addComponent(dateLabel) 1559 .addComponent(dateHelpButton) 1560 .addComponent(dateExLabel)) 1561 .addPreferredGap(RELATED) 1562 .addGroup(formatLayout.createParallelGroup(BASELINE) 1563 .addComponent(timeComboBox) 1564 .addComponent(timeLabel)) 1565 .addPreferredGap(RELATED) 1566 .addGroup(formatLayout.createParallelGroup(BASELINE) 1567 .addComponent(latlonComboBox) 1568 .addComponent(latlonLabel) 1569 .addComponent(latlonHelpButton) 1570 .addComponent(latlonExLabel)) 1571 .addPreferredGap(RELATED) 1572 .addGroup(formatLayout.createParallelGroup(BASELINE) 1573 .addComponent(probeComboBox) 1574 .addComponent(probeLabel) 1575 .addComponent(probeHelpButton)) 1576 .addPreferredGap(RELATED) 1577 .addGroup(formatLayout.createParallelGroup(BASELINE) 1578 .addComponent(distanceComboBox) 1579 .addComponent(distanceLabel)) 1580 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1581 ); 1582 1583 JPanel dataPanel = new JPanel(); 1584 dataPanel.setBorder(BorderFactory.createTitledBorder("Data")); 1585 1586 // Sampling stuff 1587 JLabel sampleLabel = McVGuiUtils.makeLabelRight("Sampling Mode:", Width.ONEHALF); 1588 1589 String sampleValue = getStore().get(PREF_SAMPLINGMODE, DisplayControlImpl.WEIGHTED_AVERAGE); 1590 JRadioButton sampleWA = new JRadioButton(DisplayControlImpl.WEIGHTED_AVERAGE, 1591 sampleValue.equals(DisplayControlImpl.WEIGHTED_AVERAGE)); 1592 1593 sampleWA.setToolTipText("Use a weighted average sampling"); 1594 JRadioButton sampleNN = new JRadioButton(DisplayControlImpl.NEAREST_NEIGHBOR, 1595 sampleValue.equals(DisplayControlImpl.NEAREST_NEIGHBOR)); 1596 1597 sampleNN.setToolTipText("Use a nearest neighbor sampling"); 1598 GuiUtils.buttonGroup(sampleWA, sampleNN); 1599 widgets.put("WEIGHTED_AVERAGE", sampleWA); 1600 widgets.put("NEAREST_NEIGHBOR", sampleNN); 1601 1602 // Pressure stuff 1603 JLabel verticalLabel = McVGuiUtils.makeLabelRight("Pressure to Height:", Width.ONEHALF); 1604 1605 String verticalValue = getStore().get(PREF_VERTICALCS, DataUtil.STD_ATMOSPHERE); 1606 JRadioButton verticalSA = new JRadioButton("Standard Atmosphere", verticalValue.equals(DataUtil.STD_ATMOSPHERE)); 1607 verticalSA.setToolTipText("Use a standard atmosphere height approximation"); 1608 JRadioButton verticalV5D = new JRadioButton("Vis5D", verticalValue.equals(DataUtil.VIS5D_VERTICALCS)); 1609 verticalV5D.setToolTipText("Use the Vis5D vertical transformation"); 1610 GuiUtils.buttonGroup(verticalSA, verticalV5D); 1611 widgets.put(DataUtil.STD_ATMOSPHERE, verticalSA); 1612 widgets.put(DataUtil.VIS5D_VERTICALCS, verticalV5D); 1613 1614 // Caching stuff 1615 JLabel cacheLabel = McVGuiUtils.makeLabelRight("Caching:", Width.ONEHALF); 1616 1617 JCheckBox cacheCheckBox = new JCheckBox("Cache Data in Memory", getStore().get(PREF_DOCACHE, true)); 1618 widgets.put(PREF_DOCACHE, cacheCheckBox); 1619 1620 JLabel cacheEmptyLabel = McVGuiUtils.makeLabelRight("", Width.ONEHALF); 1621 1622 JTextField cacheTextField = McVGuiUtils.makeTextField(Misc.format(getStore().get(PREF_CACHESIZE, 20.0))); 1623 JComponent cacheTextFieldComponent = GuiUtils.hbox(new JLabel("Disk Cache Size: "), cacheTextField, new JLabel(" megabytes")); 1624 widgets.put(PREF_CACHESIZE, cacheTextField); 1625 1626 // Image stuff 1627 JLabel imageLabel = McVGuiUtils.makeLabelRight("Max Image Size:", Width.ONEHALF); 1628 1629 JTextField imageField = McVGuiUtils.makeTextField(Misc.format(getStore().get(PREF_MAXIMAGESIZE, -1))); 1630 JComponent imageFieldComponent = GuiUtils.hbox(imageField, new JLabel(" pixels (-1 = no limit)")); 1631 widgets.put(PREF_MAXIMAGESIZE, imageField); 1632 1633 // Grid stuff 1634 JLabel gridLabel = McVGuiUtils.makeLabelRight("Grid Threshold:", Width.ONEHALF); 1635 1636 JTextField gridField = McVGuiUtils.makeTextField(Misc.format(getStore().get(PREF_FIELD_CACHETHRESHOLD, 1000000.))); 1637 JComponent gridFieldComponent = GuiUtils.hbox(gridField, new JLabel(" bytes (Cache grids larger than this to disk)")); 1638 widgets.put(PREF_FIELD_CACHETHRESHOLD, gridField); 1639 1640 // Data panel layout 1641 javax.swing.GroupLayout dataLayout = new javax.swing.GroupLayout(dataPanel); 1642 dataPanel.setLayout(dataLayout); 1643 dataLayout.setHorizontalGroup( 1644 dataLayout.createParallelGroup(LEADING) 1645 .addGroup(dataLayout.createSequentialGroup() 1646 .addContainerGap() 1647 .addGroup(dataLayout.createParallelGroup(LEADING) 1648 .addGroup(dataLayout.createSequentialGroup() 1649 .addComponent(sampleLabel) 1650 .addGap(GAP_RELATED) 1651 .addComponent(sampleWA) 1652 .addGap(GAP_RELATED) 1653 .addComponent(sampleNN)) 1654 .addGroup(dataLayout.createSequentialGroup() 1655 .addComponent(verticalLabel) 1656 .addGap(GAP_RELATED) 1657 .addComponent(verticalSA) 1658 .addGap(GAP_RELATED) 1659 .addComponent(verticalV5D)) 1660 .addGroup(dataLayout.createSequentialGroup() 1661 .addComponent(cacheLabel) 1662 .addGap(GAP_RELATED) 1663 .addComponent(cacheCheckBox)) 1664 .addGroup(dataLayout.createSequentialGroup() 1665 .addComponent(cacheEmptyLabel) 1666 .addGap(GAP_RELATED) 1667 .addComponent(cacheTextFieldComponent)) 1668 .addGroup(dataLayout.createSequentialGroup() 1669 .addComponent(imageLabel) 1670 .addGap(GAP_RELATED) 1671 .addComponent(imageFieldComponent)) 1672 .addGroup(dataLayout.createSequentialGroup() 1673 .addComponent(gridLabel) 1674 .addGap(GAP_RELATED) 1675 .addComponent(gridFieldComponent))) 1676 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1677 ); 1678 dataLayout.setVerticalGroup( 1679 dataLayout.createParallelGroup(LEADING) 1680 .addGroup(dataLayout.createSequentialGroup() 1681 .addGroup(dataLayout.createParallelGroup(BASELINE) 1682 .addComponent(sampleLabel) 1683 .addComponent(sampleWA) 1684 .addComponent(sampleNN)) 1685 .addPreferredGap(RELATED) 1686 .addGroup(dataLayout.createParallelGroup(BASELINE) 1687 .addComponent(verticalLabel) 1688 .addComponent(verticalSA) 1689 .addComponent(verticalV5D)) 1690 .addPreferredGap(RELATED) 1691 .addGroup(dataLayout.createParallelGroup(BASELINE) 1692 .addComponent(cacheLabel) 1693 .addComponent(cacheCheckBox)) 1694 .addPreferredGap(RELATED) 1695 .addGroup(dataLayout.createParallelGroup(BASELINE) 1696 .addComponent(cacheEmptyLabel) 1697 .addComponent(cacheTextFieldComponent)) 1698 .addPreferredGap(RELATED) 1699 .addGroup(dataLayout.createParallelGroup(BASELINE) 1700 .addComponent(imageLabel) 1701 .addComponent(imageFieldComponent)) 1702 .addPreferredGap(RELATED) 1703 .addGroup(dataLayout.createParallelGroup(BASELINE) 1704 .addComponent(gridLabel) 1705 .addComponent(gridFieldComponent)) 1706 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1707 ); 1708 1709 JPanel outerPanel = new JPanel(); 1710 1711 // Outer panel layout 1712 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(outerPanel); 1713 outerPanel.setLayout(layout); 1714 layout.setHorizontalGroup( 1715 layout.createParallelGroup(LEADING) 1716 .addGroup(layout.createSequentialGroup() 1717 .addContainerGap() 1718 .addGroup(layout.createParallelGroup(LEADING) 1719 .addComponent(formatPanel, TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1720 .addComponent(dataPanel, TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 1721 .addContainerGap()) 1722 ); 1723 layout.setVerticalGroup( 1724 layout.createParallelGroup(LEADING) 1725 .addGroup(layout.createSequentialGroup() 1726 .addContainerGap() 1727 .addComponent(formatPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 1728 .addGap(GAP_UNRELATED) 1729 .addComponent(dataPanel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) 1730 .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) 1731 ); 1732 1733 PreferenceManager formatsManager = new PreferenceManager() { 1734 public void applyPreference(XmlObjectStore theStore, Object data) { 1735 IdvPreferenceManager.applyWidgets((Hashtable)data, theStore); 1736 1737 // if we ever need to add formats and data prefs, here's where 1738 // they get saved off (unless we override applyWidgets). 1739 } 1740 }; 1741 1742 this.add(Constants.PREF_LIST_FORMATS_DATA, "", formatsManager, outerPanel, widgets); 1743 } 1744 1745 /** 1746 * Add in the user preference tab for the choosers to show. 1747 */ 1748 protected void addChooserPreferences() { 1749 Hashtable<String, JCheckBox> choosersData = new Hashtable<String, JCheckBox>(); 1750 List<JPanel> compList = new ArrayList<JPanel>(); 1751 1752 Boolean choosersAll = 1753 (Boolean) getIdv().getPreference(PROP_CHOOSERS_ALL, Boolean.TRUE); 1754 1755 final List<String[]> choosers = getChooserData(); 1756 1757 final List<JCheckBox> choosersList = new ArrayList<JCheckBox>(); 1758 1759 final JRadioButton useAllBtn = new JRadioButton("Use all data sources", 1760 choosersAll.booleanValue()); 1761 final JRadioButton useTheseBtn = 1762 new JRadioButton("Use selected data sources:", 1763 !choosersAll.booleanValue()); 1764 1765 GuiUtils.buttonGroup(useAllBtn, useTheseBtn); 1766 1767 final List<CheckboxCategoryPanel> chooserPanels = 1768 new ArrayList<CheckboxCategoryPanel>(); 1769 1770 final Hashtable<String, CheckboxCategoryPanel> chooserMap = 1771 new Hashtable<String, CheckboxCategoryPanel>(); 1772 1773 // create the checkbox + chooser name that'll show up in the preference 1774 // panel. 1775 for (String[] cs : choosers) { 1776 final String chooserCategory = getChooserCategory(cs[1]); 1777 String chooserShortName = getChooserShortName(cs[1]); 1778 1779 CheckboxCategoryPanel chooserPanel = 1780 (CheckboxCategoryPanel) chooserMap.get(chooserCategory); 1781 1782 if (chooserPanel == null) { 1783 chooserPanel = new CheckboxCategoryPanel(chooserCategory, false); 1784 chooserPanels.add(chooserPanel); 1785 chooserMap.put(chooserCategory, chooserPanel); 1786 compList.add(chooserPanel.getTopPanel()); 1787 compList.add(chooserPanel); 1788 } 1789 1790 JCheckBox cbx = new JCheckBox(chooserShortName, shouldShowChooser(cs[0], true)); 1791 choosersData.put(cs[0], cbx); 1792 chooserPanel.addItem(cbx); 1793 chooserPanel.add(GuiUtils.inset(cbx, new Insets(0, 20, 0, 0))); 1794 } 1795 1796 for (CheckboxCategoryPanel cbcp : chooserPanels) { 1797 cbcp.checkVisCbx(); 1798 } 1799 1800 // handle the user opting to enable all choosers. 1801 final JButton allOn = new JButton("All on"); 1802 allOn.addActionListener(new ActionListener() { 1803 public void actionPerformed(ActionEvent ae) { 1804 for (CheckboxCategoryPanel cbcp : chooserPanels) { 1805 cbcp.toggleAll(true); 1806 } 1807 } 1808 }); 1809 1810 // handle the user opting to disable all choosers. 1811 final JButton allOff = new JButton("All off"); 1812 allOff.addActionListener(new ActionListener() { 1813 public void actionPerformed(ActionEvent ae) { 1814 for (CheckboxCategoryPanel cbcp : chooserPanels) { 1815 cbcp.toggleAll(false); 1816 } 1817 } 1818 }); 1819 1820 final JPanel cbPanel = GuiUtils.top(GuiUtils.vbox(compList)); 1821 1822 JScrollPane cbScroller = new JScrollPane(cbPanel); 1823 cbScroller.getVerticalScrollBar().setUnitIncrement(10); 1824 cbScroller.setPreferredSize(new Dimension(300, 300)); 1825 1826 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 1827 GuiUtils.enableTree(allOn, !useAllBtn.isSelected()); 1828 GuiUtils.enableTree(allOff, !useAllBtn.isSelected()); 1829 1830 JPanel widgetPanel = 1831 GuiUtils.topCenter( 1832 GuiUtils.hbox(useAllBtn, useTheseBtn), 1833 GuiUtils.leftCenter( 1834 GuiUtils.inset( 1835 GuiUtils.top(GuiUtils.vbox(allOn, allOff)), 1836 4), cbScroller)); 1837 JPanel choosersPanel = 1838 GuiUtils.topCenter( 1839 GuiUtils.inset( 1840 new JLabel("Note: This will take effect the next run"), 1841 4), widgetPanel); 1842 choosersPanel = GuiUtils.inset(GuiUtils.left(choosersPanel), 6); 1843 useAllBtn.addActionListener(new ActionListener() { 1844 public void actionPerformed(ActionEvent ae) { 1845 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 1846 GuiUtils.enableTree(allOn, !useAllBtn.isSelected()); 1847 GuiUtils.enableTree(allOff, !useAllBtn.isSelected()); 1848 1849 } 1850 }); 1851 useTheseBtn.addActionListener(new ActionListener() { 1852 public void actionPerformed(ActionEvent ae) { 1853 GuiUtils.enableTree(cbPanel, !useAllBtn.isSelected()); 1854 GuiUtils.enableTree(allOn, !useAllBtn.isSelected()); 1855 GuiUtils.enableTree(allOff, !useAllBtn.isSelected()); 1856 } 1857 }); 1858 1859 PreferenceManager choosersManager = new PreferenceManager() { 1860 public void applyPreference(XmlObjectStore theStore, Object data) { 1861 1862 Hashtable<String, Boolean> newToShow = new Hashtable<String, Boolean>(); 1863 1864 Hashtable table = (Hashtable)data; 1865 for (Enumeration keys = table.keys(); keys.hasMoreElements(); ) { 1866 String chooserId = (String) keys.nextElement(); 1867 JCheckBox chooserCB = (JCheckBox) table.get(chooserId); 1868 newToShow.put(chooserId, Boolean.valueOf(chooserCB.isSelected())); 1869 } 1870 1871 choosersToShow = newToShow; 1872 theStore.put(PROP_CHOOSERS_ALL, Boolean.valueOf(useAllBtn.isSelected())); 1873 theStore.put(PROP_CHOOSERS, choosersToShow); 1874 } 1875 }; 1876 this.add(Constants.PREF_LIST_DATA_CHOOSERS, 1877 "What data sources should be shown in the user interface?", 1878 choosersManager, choosersPanel, choosersData); 1879 } 1880 1881 /** 1882 * <p>Return a list that contains a bunch of arrays of two strings.</p> 1883 * 1884 * <p>The first item in one of the arrays is the chooser id, and the second 1885 * item is the "name" of the chooser. The name is formed by working through 1886 * choosers.xml and concatenating each panel's category and title.</p> 1887 * 1888 * @return A list of chooser ids and names. 1889 */ 1890 private final List<String[]> getChooserData() { 1891 List<String[]> choosers = new ArrayList<String[]>(); 1892 String tempString; 1893 1894 try { 1895 // get the root element so we can iterate through 1896 final String xml = 1897 IOUtil.readContents(MCV_CHOOSERS, McIdasPreferenceManager.class); 1898 1899 final Element root = XmlUtil.getRoot(xml); 1900 if (root == null) { 1901 return null; 1902 } 1903 // grab all the children, which should be panels. 1904 final NodeList nodeList = XmlUtil.getElements(root); 1905 for (int i = 0; i < nodeList.getLength(); i++) { 1906 1907 final Element item = (Element)nodeList.item(i); 1908 1909 if (item.getTagName().equals(XmlUi.TAG_PANEL) || item.getTagName().equals("chooser")) { 1910 1911 // form the name of the chooser. 1912 final String title = 1913 XmlUtil.getAttribute(item, XmlUi.ATTR_TITLE, ""); 1914 1915 final String cat = 1916 XmlUtil.getAttribute(item, XmlUi.ATTR_CATEGORY, ""); 1917 1918 if (cat.equals("")) { 1919 tempString = title; 1920 } else { 1921 tempString = cat + ">" + title; 1922 } 1923 1924 final NodeList children = XmlUtil.getElements(item); 1925 1926 if (item.getTagName().equals("chooser")) { 1927 final String id = 1928 XmlUtil.getAttribute(item, XmlUi.ATTR_ID, ""); 1929 String[] tmp = {id, tempString}; 1930 choosers.add(tmp); 1931 } 1932 else { 1933 for (int j = 0; j < children.getLength(); j++) { 1934 final Element child = (Element)children.item(j); 1935 1936 // form the id of the chooser and add it to the list. 1937 if (child.getTagName().equals("chooser")) { 1938 final String id = 1939 XmlUtil.getAttribute(child, XmlUi.ATTR_ID, ""); 1940 String[] tmp = {id, tempString}; 1941 choosers.add(tmp); 1942 } 1943 } 1944 } 1945 } 1946 } 1947 } catch (Exception e) { 1948 e.printStackTrace(); 1949 } 1950 return choosers; 1951 } 1952 1953 /** 1954 * Parse the full chooser name for a category. 1955 * 1956 * @param chooserName Name of a chooser. Cannot be {@code null}. 1957 * 1958 * @return {@literal "Category"} associated with {@code chooserName} or 1959 * {@literal "Other"} if no category is available. 1960 */ 1961 private String getChooserCategory(String chooserName) { 1962 String chooserCategory = "Other"; 1963 int indexSep = chooserName.indexOf('>'); 1964 if (indexSep >= 0) { 1965 chooserCategory = chooserName.substring(0, indexSep); 1966 } 1967 return chooserCategory; 1968 } 1969 1970 /** 1971 * Parse the full chooser name for a short name. 1972 * 1973 * @param chooserName Name of a chooser. Cannot be {@code null}. 1974 * 1975 * @return The {@literal "short name"} of {@code chooserName}. 1976 */ 1977 private String getChooserShortName(String chooserName) { 1978 String chooserShortName = chooserName; 1979 int indexSep = chooserName.indexOf('>'); 1980 if (indexSep >= 0 && chooserName.length() > indexSep + 1) { 1981 chooserShortName = 1982 chooserName.substring(indexSep + 1, chooserName.length()); 1983 } 1984 return chooserShortName; 1985 } 1986 1987 public class IconCellRenderer extends DefaultListCellRenderer { 1988 1989 /** 1990 * Extends the default list cell renderer to use icons in addition to 1991 * the typical text. 1992 */ 1993 public Component getListCellRendererComponent(JList list, Object value, 1994 int index, boolean isSelected, boolean cellHasFocus) { 1995 1996 super.getListCellRendererComponent(list, value, index, isSelected, 1997 cellHasFocus); 1998 1999 if (value instanceof JLabel) { 2000 setText(((JLabel)value).getText()); 2001 setIcon(((JLabel)value).getIcon()); 2002 } 2003 2004 return this; 2005 } 2006 2007 /** 2008 * I wear some pretty fancy pants, so you'd better believe that I'm 2009 * going to enable fancy-pants text antialiasing. 2010 * 2011 * @param g The graphics object that we'll use as a base. 2012 */ 2013 protected void paintComponent(Graphics g) { 2014 Graphics2D g2d = (Graphics2D)g; 2015 g2d.setRenderingHints(getRenderingHints()); 2016 super.paintComponent(g2d); 2017 } 2018 } 2019 } 2020