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