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