001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.Container; 008import java.awt.Font; 009import java.awt.GridBagLayout; 010import java.awt.event.MouseWheelEvent; 011import java.awt.event.MouseWheelListener; 012import java.util.ArrayList; 013import java.util.Collection; 014import java.util.HashSet; 015import java.util.Iterator; 016import java.util.LinkedList; 017import java.util.List; 018import java.util.Set; 019 020import javax.swing.BorderFactory; 021import javax.swing.Icon; 022import javax.swing.ImageIcon; 023import javax.swing.JLabel; 024import javax.swing.JOptionPane; 025import javax.swing.JPanel; 026import javax.swing.JScrollPane; 027import javax.swing.JTabbedPane; 028import javax.swing.event.ChangeEvent; 029import javax.swing.event.ChangeListener; 030 031import org.openstreetmap.josm.actions.ExpertToggleAction; 032import org.openstreetmap.josm.actions.ExpertToggleAction.ExpertModeChangeListener; 033import org.openstreetmap.josm.actions.RestartAction; 034import org.openstreetmap.josm.gui.HelpAwareOptionPane; 035import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; 036import org.openstreetmap.josm.gui.MainApplication; 037import org.openstreetmap.josm.gui.preferences.advanced.AdvancedPreference; 038import org.openstreetmap.josm.gui.preferences.audio.AudioPreference; 039import org.openstreetmap.josm.gui.preferences.display.ColorPreference; 040import org.openstreetmap.josm.gui.preferences.display.DisplayPreference; 041import org.openstreetmap.josm.gui.preferences.display.DrawingPreference; 042import org.openstreetmap.josm.gui.preferences.display.LafPreference; 043import org.openstreetmap.josm.gui.preferences.display.LanguagePreference; 044import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference; 045import org.openstreetmap.josm.gui.preferences.map.BackupPreference; 046import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference; 047import org.openstreetmap.josm.gui.preferences.map.MapPreference; 048import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference; 049import org.openstreetmap.josm.gui.preferences.plugin.PluginPreference; 050import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference; 051import org.openstreetmap.josm.gui.preferences.remotecontrol.RemoteControlPreference; 052import org.openstreetmap.josm.gui.preferences.server.AuthenticationPreference; 053import org.openstreetmap.josm.gui.preferences.server.OverpassServerPreference; 054import org.openstreetmap.josm.gui.preferences.server.ProxyPreference; 055import org.openstreetmap.josm.gui.preferences.server.ServerAccessPreference; 056import org.openstreetmap.josm.gui.preferences.shortcut.ShortcutPreference; 057import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference; 058import org.openstreetmap.josm.gui.preferences.validator.ValidatorTagCheckerRulesPreference; 059import org.openstreetmap.josm.gui.preferences.validator.ValidatorTestsPreference; 060import org.openstreetmap.josm.gui.util.GuiHelper; 061import org.openstreetmap.josm.plugins.PluginDownloadTask; 062import org.openstreetmap.josm.plugins.PluginHandler; 063import org.openstreetmap.josm.plugins.PluginInformation; 064import org.openstreetmap.josm.tools.CheckParameterUtil; 065import org.openstreetmap.josm.tools.GBC; 066import org.openstreetmap.josm.tools.ImageProvider; 067import org.openstreetmap.josm.tools.Logging; 068import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler; 069 070/** 071 * The preference settings. 072 * 073 * @author imi 074 */ 075public final class PreferenceTabbedPane extends JTabbedPane implements MouseWheelListener, ExpertModeChangeListener, ChangeListener { 076 077 private final class PluginDownloadAfterTask implements Runnable { 078 private final PluginPreference preference; 079 private final PluginDownloadTask task; 080 private final Set<PluginInformation> toDownload; 081 082 private PluginDownloadAfterTask(PluginPreference preference, PluginDownloadTask task, 083 Set<PluginInformation> toDownload) { 084 this.preference = preference; 085 this.task = task; 086 this.toDownload = toDownload; 087 } 088 089 @Override 090 public void run() { 091 boolean requiresRestart = false; 092 093 for (PreferenceSetting setting : settingsInitialized) { 094 if (setting.ok()) { 095 requiresRestart = true; 096 } 097 } 098 099 // build the messages. We only display one message, including the status information from the plugin download task 100 // and - if necessary - a hint to restart JOSM 101 // 102 StringBuilder sb = new StringBuilder(); 103 sb.append("<html>"); 104 if (task != null && !task.isCanceled()) { 105 PluginHandler.refreshLocalUpdatedPluginInfo(task.getDownloadedPlugins()); 106 sb.append(PluginPreference.buildDownloadSummary(task)); 107 } 108 if (requiresRestart) { 109 sb.append(tr("You have to restart JOSM for some settings to take effect.")); 110 sb.append("<br/><br/>"); 111 sb.append(tr("Would you like to restart now?")); 112 } 113 sb.append("</html>"); 114 115 // display the message, if necessary 116 // 117 if (requiresRestart) { 118 final ButtonSpec[] options = RestartAction.getButtonSpecs(); 119 if (0 == HelpAwareOptionPane.showOptionDialog( 120 MainApplication.getMainFrame(), 121 sb.toString(), 122 tr("Restart"), 123 JOptionPane.INFORMATION_MESSAGE, 124 null, /* no special icon */ 125 options, 126 options[0], 127 null /* no special help */ 128 )) { 129 MainApplication.getMenu().restart.actionPerformed(null); 130 } 131 } else if (task != null && !task.isCanceled()) { 132 JOptionPane.showMessageDialog( 133 MainApplication.getMainFrame(), 134 sb.toString(), 135 tr("Warning"), 136 JOptionPane.WARNING_MESSAGE 137 ); 138 } 139 140 // load the plugins that can be loaded at runtime 141 List<PluginInformation> newPlugins = preference.getNewlyActivatedPlugins(); 142 if (newPlugins != null) { 143 Collection<PluginInformation> downloadedPlugins = null; 144 if (task != null && !task.isCanceled()) { 145 downloadedPlugins = task.getDownloadedPlugins(); 146 } 147 List<PluginInformation> toLoad = new ArrayList<>(); 148 for (PluginInformation pi : newPlugins) { 149 if (toDownload.contains(pi) && downloadedPlugins != null && !downloadedPlugins.contains(pi)) { 150 continue; // failed download 151 } 152 if (pi.canloadatruntime) { 153 toLoad.add(pi); 154 } 155 } 156 // check if plugin dependences can also be loaded 157 Collection<PluginInformation> allPlugins = new HashSet<>(toLoad); 158 allPlugins.addAll(PluginHandler.getPlugins()); 159 boolean removed; 160 do { 161 removed = false; 162 Iterator<PluginInformation> it = toLoad.iterator(); 163 while (it.hasNext()) { 164 if (!PluginHandler.checkRequiredPluginsPreconditions(null, allPlugins, it.next(), requiresRestart)) { 165 it.remove(); 166 removed = true; 167 } 168 } 169 } while (removed); 170 171 if (!toLoad.isEmpty()) { 172 PluginHandler.loadPlugins(PreferenceTabbedPane.this, toLoad, null); 173 } 174 } 175 176 if (MainApplication.getMainFrame() != null) { 177 MainApplication.getMainFrame().repaint(); 178 } 179 } 180 } 181 182 /** 183 * Allows PreferenceSettings to do validation of entered values when ok was pressed. 184 * If data is invalid then event can return false to cancel closing of preferences dialog. 185 * @since 10600 (functional interface) 186 */ 187 @FunctionalInterface 188 public interface ValidationListener { 189 /** 190 * 191 * @return True if preferences can be saved 192 */ 193 boolean validatePreferences(); 194 } 195 196 private interface PreferenceTab { 197 TabPreferenceSetting getTabPreferenceSetting(); 198 199 Component getComponent(); 200 } 201 202 public static final class PreferencePanel extends JPanel implements PreferenceTab { 203 private final transient TabPreferenceSetting preferenceSetting; 204 205 private PreferencePanel(TabPreferenceSetting preferenceSetting) { 206 super(new GridBagLayout()); 207 CheckParameterUtil.ensureParameterNotNull(preferenceSetting); 208 this.preferenceSetting = preferenceSetting; 209 buildPanel(); 210 } 211 212 private void buildPanel() { 213 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 214 add(new JLabel(preferenceSetting.getTitle()), GBC.eol().insets(0, 5, 0, 10).anchor(GBC.NORTHWEST)); 215 216 JLabel descLabel = new JLabel("<html>"+preferenceSetting.getDescription()+"</html>"); 217 descLabel.setFont(descLabel.getFont().deriveFont(Font.ITALIC)); 218 add(descLabel, GBC.eol().insets(5, 0, 5, 20).fill(GBC.HORIZONTAL)); 219 } 220 221 @Override 222 public TabPreferenceSetting getTabPreferenceSetting() { 223 return preferenceSetting; 224 } 225 226 @Override 227 public Component getComponent() { 228 return this; 229 } 230 } 231 232 public static final class PreferenceScrollPane extends JScrollPane implements PreferenceTab { 233 private final transient TabPreferenceSetting preferenceSetting; 234 235 private PreferenceScrollPane(Component view, TabPreferenceSetting preferenceSetting) { 236 super(view); 237 this.preferenceSetting = preferenceSetting; 238 } 239 240 private PreferenceScrollPane(PreferencePanel preferencePanel) { 241 this(preferencePanel.getComponent(), preferencePanel.getTabPreferenceSetting()); 242 } 243 244 @Override 245 public TabPreferenceSetting getTabPreferenceSetting() { 246 return preferenceSetting; 247 } 248 249 @Override 250 public Component getComponent() { 251 return this; 252 } 253 } 254 255 // all created tabs 256 private final transient List<PreferenceTab> tabs = new ArrayList<>(); 257 private static final Collection<PreferenceSettingFactory> SETTINGS_FACTORIES = new LinkedList<>(); 258 private static final PreferenceSettingFactory ADVANCED_PREFERENCE_FACTORY = new AdvancedPreference.Factory(); 259 private final transient List<PreferenceSetting> settings = new ArrayList<>(); 260 261 // distinct list of tabs that have been initialized (we do not initialize tabs until they are displayed to speed up dialog startup) 262 private final transient List<PreferenceSetting> settingsInitialized = new ArrayList<>(); 263 264 final transient List<ValidationListener> validationListeners = new ArrayList<>(); 265 266 /** 267 * Add validation listener to currently open preferences dialog. Calling to removeValidationListener is not necessary, all listeners will 268 * be automatically removed when dialog is closed 269 * @param validationListener validation listener to add 270 */ 271 public void addValidationListener(ValidationListener validationListener) { 272 validationListeners.add(validationListener); 273 } 274 275 /** 276 * Construct a PreferencePanel for the preference settings. Layout is GridBagLayout 277 * and a centered title label and the description are added. 278 * @param caller Preference settings, that display a top level tab 279 * @return The created panel ready to add other controls. 280 */ 281 public PreferencePanel createPreferenceTab(TabPreferenceSetting caller) { 282 return createPreferenceTab(caller, false); 283 } 284 285 /** 286 * Construct a PreferencePanel for the preference settings. Layout is GridBagLayout 287 * and a centered title label and the description are added. 288 * @param caller Preference settings, that display a top level tab 289 * @param inScrollPane if <code>true</code> the added tab will show scroll bars 290 * if the panel content is larger than the available space 291 * @return The created panel ready to add other controls. 292 */ 293 public PreferencePanel createPreferenceTab(TabPreferenceSetting caller, boolean inScrollPane) { 294 CheckParameterUtil.ensureParameterNotNull(caller, "caller"); 295 PreferencePanel p = new PreferencePanel(caller); 296 297 PreferenceTab tab = p; 298 if (inScrollPane) { 299 PreferenceScrollPane sp = new PreferenceScrollPane(p); 300 tab = sp; 301 } 302 tabs.add(tab); 303 return p; 304 } 305 306 @FunctionalInterface 307 private interface TabIdentifier { 308 boolean identify(TabPreferenceSetting tps, Object param); 309 } 310 311 private void selectTabBy(TabIdentifier method, Object param) { 312 for (int i = 0; i < getTabCount(); i++) { 313 Component c = getComponentAt(i); 314 if (c instanceof PreferenceTab) { 315 PreferenceTab tab = (PreferenceTab) c; 316 if (method.identify(tab.getTabPreferenceSetting(), param)) { 317 setSelectedIndex(i); 318 return; 319 } 320 } 321 } 322 } 323 324 public void selectTabByName(String name) { 325 selectTabBy((tps, name1) -> name1 != null && tps != null && tps.getIconName() != null && name1.equals(tps.getIconName()), name); 326 } 327 328 public void selectTabByPref(Class<? extends TabPreferenceSetting> clazz) { 329 selectTabBy((tps, clazz1) -> tps.getClass().isAssignableFrom((Class<?>) clazz1), clazz); 330 } 331 332 public boolean selectSubTabByPref(Class<? extends SubPreferenceSetting> clazz) { 333 for (PreferenceSetting setting : settings) { 334 if (clazz.isInstance(setting)) { 335 final SubPreferenceSetting sub = (SubPreferenceSetting) setting; 336 final TabPreferenceSetting tab = sub.getTabPreferenceSetting(this); 337 selectTabBy((tps, unused) -> tps.equals(tab), null); 338 return tab.selectSubTab(sub); 339 } 340 } 341 return false; 342 } 343 344 /** 345 * Returns the {@code DisplayPreference} object. 346 * @return the {@code DisplayPreference} object. 347 */ 348 public DisplayPreference getDisplayPreference() { 349 return getSetting(DisplayPreference.class); 350 } 351 352 /** 353 * Returns the {@code MapPreference} object. 354 * @return the {@code MapPreference} object. 355 */ 356 public MapPreference getMapPreference() { 357 return getSetting(MapPreference.class); 358 } 359 360 /** 361 * Returns the {@code PluginPreference} object. 362 * @return the {@code PluginPreference} object. 363 */ 364 public PluginPreference getPluginPreference() { 365 return getSetting(PluginPreference.class); 366 } 367 368 /** 369 * Returns the {@code ImageryPreference} object. 370 * @return the {@code ImageryPreference} object. 371 */ 372 public ImageryPreference getImageryPreference() { 373 return getSetting(ImageryPreference.class); 374 } 375 376 /** 377 * Returns the {@code ShortcutPreference} object. 378 * @return the {@code ShortcutPreference} object. 379 */ 380 public ShortcutPreference getShortcutPreference() { 381 return getSetting(ShortcutPreference.class); 382 } 383 384 /** 385 * Returns the {@code ServerAccessPreference} object. 386 * @return the {@code ServerAccessPreference} object. 387 * @since 6523 388 */ 389 public ServerAccessPreference getServerPreference() { 390 return getSetting(ServerAccessPreference.class); 391 } 392 393 /** 394 * Returns the {@code ValidatorPreference} object. 395 * @return the {@code ValidatorPreference} object. 396 * @since 6665 397 */ 398 public ValidatorPreference getValidatorPreference() { 399 return getSetting(ValidatorPreference.class); 400 } 401 402 /** 403 * Saves preferences. 404 */ 405 public void savePreferences() { 406 // create a task for downloading plugins if the user has activated, yet not downloaded, new plugins 407 final PluginPreference preference = getPluginPreference(); 408 if (preference != null) { 409 final Set<PluginInformation> toDownload = preference.getPluginsScheduledForUpdateOrDownload(); 410 final PluginDownloadTask task; 411 if (toDownload != null && !toDownload.isEmpty()) { 412 task = new PluginDownloadTask(this, toDownload, tr("Download plugins")); 413 } else { 414 task = null; 415 } 416 417 // this is the task which will run *after* the plugins are downloaded 418 final Runnable continuation = new PluginDownloadAfterTask(preference, task, toDownload); 419 420 if (task != null) { 421 // if we have to launch a plugin download task we do it asynchronously, followed 422 // by the remaining "save preferences" activities run on the Swing EDT. 423 MainApplication.worker.submit(task); 424 MainApplication.worker.submit(() -> GuiHelper.runInEDT(continuation)); 425 } else { 426 // no need for asynchronous activities. Simply run the remaining "save preference" 427 // activities on this thread (we are already on the Swing EDT 428 continuation.run(); 429 } 430 } 431 } 432 433 /** 434 * If the dialog is closed with Ok, the preferences will be stored to the preferences- 435 * file, otherwise no change of the file happens. 436 */ 437 public PreferenceTabbedPane() { 438 super(JTabbedPane.LEFT, JTabbedPane.SCROLL_TAB_LAYOUT); 439 super.addMouseWheelListener(this); 440 super.getModel().addChangeListener(this); 441 ExpertToggleAction.addExpertModeChangeListener(this); 442 } 443 444 public void buildGui() { 445 Collection<PreferenceSettingFactory> factories = new ArrayList<>(SETTINGS_FACTORIES); 446 factories.addAll(PluginHandler.getPreferenceSetting()); 447 factories.add(ADVANCED_PREFERENCE_FACTORY); 448 449 for (PreferenceSettingFactory factory : factories) { 450 if (factory != null) { 451 PreferenceSetting setting = factory.createPreferenceSetting(); 452 if (setting != null) { 453 settings.add(setting); 454 } 455 } 456 } 457 addGUITabs(false); 458 } 459 460 private void addGUITabsForSetting(Icon icon, TabPreferenceSetting tps) { 461 for (PreferenceTab tab : tabs) { 462 if (tab.getTabPreferenceSetting().equals(tps)) { 463 insertGUITabsForSetting(icon, tps, getTabCount()); 464 } 465 } 466 } 467 468 private int insertGUITabsForSetting(Icon icon, TabPreferenceSetting tps, int index) { 469 int position = index; 470 for (PreferenceTab tab : tabs) { 471 if (tab.getTabPreferenceSetting().equals(tps)) { 472 insertTab(null, icon, tab.getComponent(), tps.getTooltip(), position++); 473 } 474 } 475 return position - 1; 476 } 477 478 private void addGUITabs(boolean clear) { 479 boolean expert = ExpertToggleAction.isExpert(); 480 Component sel = getSelectedComponent(); 481 if (clear) { 482 removeAll(); 483 } 484 // Inspect each tab setting 485 for (PreferenceSetting setting : settings) { 486 if (setting instanceof TabPreferenceSetting) { 487 TabPreferenceSetting tps = (TabPreferenceSetting) setting; 488 if (expert || !tps.isExpert()) { 489 // Get icon 490 String iconName = tps.getIconName(); 491 ImageIcon icon = null; 492 493 if (iconName != null && !iconName.isEmpty()) { 494 icon = ImageProvider.get("preferences", iconName, ImageProvider.ImageSizes.SETTINGS_TAB); 495 } 496 if (settingsInitialized.contains(tps)) { 497 // If it has been initialized, add corresponding tab(s) 498 addGUITabsForSetting(icon, tps); 499 } else { 500 // If it has not been initialized, create an empty tab with only icon and tooltip 501 addTab(null, icon, new PreferencePanel(tps), tps.getTooltip()); 502 } 503 } 504 } else if (!(setting instanceof SubPreferenceSetting)) { 505 Logging.warn("Ignoring preferences "+setting); 506 } 507 } 508 if (sel != null) { 509 int index = indexOfComponent(sel); 510 if (index > -1) { 511 setSelectedIndex(index); 512 } 513 } 514 } 515 516 @Override 517 public void expertChanged(boolean isExpert) { 518 addGUITabs(true); 519 } 520 521 public List<PreferenceSetting> getSettings() { 522 return settings; 523 } 524 525 @SuppressWarnings("unchecked") 526 public <T> T getSetting(Class<? extends T> clazz) { 527 for (PreferenceSetting setting:settings) { 528 if (clazz.isAssignableFrom(setting.getClass())) 529 return (T) setting; 530 } 531 return null; 532 } 533 534 static { 535 // order is important! 536 SETTINGS_FACTORIES.add(new DisplayPreference.Factory()); 537 SETTINGS_FACTORIES.add(new DrawingPreference.Factory()); 538 SETTINGS_FACTORIES.add(new ColorPreference.Factory()); 539 SETTINGS_FACTORIES.add(new LafPreference.Factory()); 540 SETTINGS_FACTORIES.add(new LanguagePreference.Factory()); 541 SETTINGS_FACTORIES.add(new ServerAccessPreference.Factory()); 542 SETTINGS_FACTORIES.add(new AuthenticationPreference.Factory()); 543 SETTINGS_FACTORIES.add(new ProxyPreference.Factory()); 544 SETTINGS_FACTORIES.add(new OverpassServerPreference.Factory()); 545 SETTINGS_FACTORIES.add(new MapPreference.Factory()); 546 SETTINGS_FACTORIES.add(new ProjectionPreference.Factory()); 547 SETTINGS_FACTORIES.add(new MapPaintPreference.Factory()); 548 SETTINGS_FACTORIES.add(new TaggingPresetPreference.Factory()); 549 SETTINGS_FACTORIES.add(new BackupPreference.Factory()); 550 SETTINGS_FACTORIES.add(new PluginPreference.Factory()); 551 SETTINGS_FACTORIES.add(MainApplication.getToolbar()); 552 SETTINGS_FACTORIES.add(new AudioPreference.Factory()); 553 SETTINGS_FACTORIES.add(new ShortcutPreference.Factory()); 554 SETTINGS_FACTORIES.add(new ValidatorPreference.Factory()); 555 SETTINGS_FACTORIES.add(new ValidatorTestsPreference.Factory()); 556 SETTINGS_FACTORIES.add(new ValidatorTagCheckerRulesPreference.Factory()); 557 SETTINGS_FACTORIES.add(new RemoteControlPreference.Factory()); 558 SETTINGS_FACTORIES.add(new ImageryPreference.Factory()); 559 } 560 561 /** 562 * This mouse wheel listener reacts when a scroll is carried out over the 563 * tab strip and scrolls one tab/down or up, selecting it immediately. 564 */ 565 @Override 566 public void mouseWheelMoved(MouseWheelEvent wev) { 567 // Ensure the cursor is over the tab strip 568 if (super.indexAtLocation(wev.getPoint().x, wev.getPoint().y) < 0) 569 return; 570 571 // Get currently selected tab 572 int newTab = super.getSelectedIndex() + wev.getWheelRotation(); 573 574 // Ensure the new tab index is sound 575 newTab = newTab < 0 ? 0 : newTab; 576 newTab = newTab >= super.getTabCount() ? super.getTabCount() - 1 : newTab; 577 578 // select new tab 579 super.setSelectedIndex(newTab); 580 } 581 582 @Override 583 public void stateChanged(ChangeEvent e) { 584 int index = getSelectedIndex(); 585 Component sel = getSelectedComponent(); 586 if (index > -1 && sel instanceof PreferenceTab) { 587 PreferenceTab tab = (PreferenceTab) sel; 588 TabPreferenceSetting preferenceSettings = tab.getTabPreferenceSetting(); 589 if (!settingsInitialized.contains(preferenceSettings)) { 590 try { 591 getModel().removeChangeListener(this); 592 preferenceSettings.addGui(this); 593 // Add GUI for sub preferences 594 for (PreferenceSetting setting : settings) { 595 if (setting instanceof SubPreferenceSetting) { 596 addSubPreferenceSetting(preferenceSettings, (SubPreferenceSetting) setting); 597 } 598 } 599 Icon icon = getIconAt(index); 600 remove(index); 601 if (index <= insertGUITabsForSetting(icon, preferenceSettings, index)) { 602 setSelectedIndex(index); 603 } 604 } catch (SecurityException ex) { 605 Logging.error(ex); 606 } catch (RuntimeException ex) { // NOPMD 607 // allow to change most settings even if e.g. a plugin fails 608 BugReportExceptionHandler.handleException(ex); 609 } finally { 610 settingsInitialized.add(preferenceSettings); 611 getModel().addChangeListener(this); 612 } 613 } 614 Container ancestor = getTopLevelAncestor(); 615 if (ancestor instanceof PreferenceDialog) { 616 ((PreferenceDialog) ancestor).setHelpContext(preferenceSettings.getHelpContext()); 617 } 618 } 619 } 620 621 private void addSubPreferenceSetting(TabPreferenceSetting preferenceSettings, SubPreferenceSetting sps) { 622 if (sps.getTabPreferenceSetting(this) == preferenceSettings) { 623 try { 624 sps.addGui(this); 625 } catch (SecurityException ex) { 626 Logging.error(ex); 627 } catch (RuntimeException ex) { // NOPMD 628 BugReportExceptionHandler.handleException(ex); 629 } finally { 630 settingsInitialized.add(sps); 631 } 632 } 633 } 634}