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