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