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