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