diff options
Diffstat (limited to 'platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java')
-rw-r--r-- | platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java new file mode 100644 index 000000000000..c38bf6ff2033 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java @@ -0,0 +1,330 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.options.newEditor; + +import com.intellij.CommonBundle; +import com.intellij.ide.ui.search.SearchUtil; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.help.HelpManager; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableGroup; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.Disposer; +import com.intellij.ui.Gray; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.JBColor; +import com.intellij.ui.border.CustomLineBorder; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author Konstantin Bulenkov + */ +public class IdeSettingsDialog extends DialogWrapper implements DataProvider { + private Project myProject; + private ConfigurableGroup[] myGroups; + private Configurable myPreselected; + private OptionsEditor myEditor; + + private ApplyAction myApplyAction; + public static final String DIMENSION_KEY = "OptionsEditor"; + @NonNls static final String LAST_SELECTED_CONFIGURABLE = "options.lastSelected"; + + /** + * This constructor should be eliminated after the new modality approach + * will have been checked. See a {@code Registry} key ide.perProjectModality + * + * @deprecated + */ + public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, + @Nullable Configurable preselectedConfigurable, boolean applicationModalIfPossible) { + super(project, true, applicationModalIfPossible); + init(project, groups, preselectedConfigurable != null ? preselectedConfigurable : findLastSavedConfigurable(groups, project)); + } + + /** + * This constructor should be eliminated after the new modality approach + * will have been checked. See a {@code Registry} key ide.perProjectModality + * + * @deprecated + */ + public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, + @NotNull String preselectedConfigurableDisplayName, boolean applicationModalIfPossible) { + super(project, true, applicationModalIfPossible); + init(project, groups, getPreselectedByDisplayName(groups, preselectedConfigurableDisplayName, project)); + } + + public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, @Nullable Configurable preselectedConfigurable) { + super(project, true); + init(project, groups, preselectedConfigurable != null ? preselectedConfigurable : findLastSavedConfigurable(groups, project)); + } + + public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, @NotNull String preselectedConfigurableDisplayName) { + super(project, true); + init(project, groups, getPreselectedByDisplayName(groups, preselectedConfigurableDisplayName, project)); + } + + @Nullable + @Override + protected Border createContentPaneBorder() { + return IdeBorderFactory.createEmptyBorder(0); + } + + private void init(final Project project, final ConfigurableGroup[] groups, @Nullable final Configurable preselected) { + myProject = project; + myGroups = groups; + myPreselected = preselected; + + setTitle(CommonBundle.settingsTitle()); + + init(); + } + + @Nullable + private static Configurable getPreselectedByDisplayName(final ConfigurableGroup[] groups, final String preselectedConfigurableDisplayName, + final Project project) { + Configurable result = findPreselectedByDisplayName(preselectedConfigurableDisplayName, groups); + + return result == null ? findLastSavedConfigurable(groups, project) : result; + } + + @Override + public boolean isTypeAheadEnabled() { + return true; + } + + @Nullable + @Override + protected JComponent createSouthPanel() { + final JComponent panel = super.createSouthPanel(); + CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)), 1, 0, 0, 0); + panel.setBorder(new CompoundBorder(line, new EmptyBorder(8, 12, 8, 12))); + return panel; + } + + protected JComponent createCenterPanel() { + myEditor = new OptionsEditor(myProject, myGroups, myPreselected); + myEditor.getContext().addColleague(new OptionsEditorColleague.Adapter() { + @Override + public ActionCallback onModifiedAdded(final Configurable configurable) { + updateStatus(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback onModifiedRemoved(final Configurable configurable) { + updateStatus(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback onErrorsChanged() { + updateStatus(); + return new ActionCallback.Done(); + } + }); + Disposer.register(myDisposable, myEditor); + return myEditor; + } + + public boolean updateStatus() { + myApplyAction.setEnabled(myEditor.canApply()); + + final Map<Configurable, ConfigurationException> errors = myEditor.getContext().getErrors(); + if (errors.size() == 0) { + setErrorText(null); + } + else { + String text = "Changes were not applied because of an error"; + + final String errorMessage = getErrorMessage(errors); + if (errorMessage != null) { + text += "<br>" + errorMessage; + } + + setErrorText(text); + } + + return errors.size() == 0; + } + + @Nullable + private static String getErrorMessage(final Map<Configurable, ConfigurationException> errors) { + final Collection<ConfigurationException> values = errors.values(); + final ConfigurationException[] exceptions = values.toArray(new ConfigurationException[values.size()]); + if (exceptions.length > 0) { + return exceptions[0].getMessage(); + } + return null; + } + + @Override + protected String getDimensionServiceKey() { + return DIMENSION_KEY; + } + + @Override + protected void doOKAction() { + myEditor.flushModifications(); + + if (myEditor.canApply()) { + myEditor.apply(); + if (!updateStatus()) return; + } + + saveCurrentConfigurable(); + + ApplicationManager.getApplication().saveAll(); + + super.doOKAction(); + } + + + private void saveCurrentConfigurable() { + final Configurable current = myEditor.getContext().getCurrentConfigurable(); + if (current == null) return; + + final PropertiesComponent props = PropertiesComponent.getInstance(myProject); + + if (current instanceof SearchableConfigurable) { + props.setValue(LAST_SELECTED_CONFIGURABLE, ((SearchableConfigurable)current).getId()); + } + else { + props.setValue(LAST_SELECTED_CONFIGURABLE, current.getClass().getName()); + } + } + + @Nullable + private static Configurable findLastSavedConfigurable(ConfigurableGroup[] groups, final Project project) { + final String id = PropertiesComponent.getInstance(project).getValue(LAST_SELECTED_CONFIGURABLE); + if (id == null) return null; + + return findConfigurableInGroups(id, groups); + } + + @Nullable + private static Configurable findConfigurableInGroups(String id, Configurable.Composite... groups) { + // avoid unnecessary group expand: check top-level configurables in all groups before looking at children + for (Configurable.Composite group : groups) { + final Configurable[] configurables = group.getConfigurables(); + for (Configurable c : configurables) { + if (c instanceof SearchableConfigurable && id.equals(((SearchableConfigurable)c).getId())) { + return c; + } + else if (id.equals(c.getClass().getName())) { + return c; + } + } + } + for (Configurable.Composite group : groups) { + final Configurable[] configurables = group.getConfigurables(); + for (Configurable c : configurables) { + if (c instanceof Configurable.Composite) { + Configurable result = findConfigurableInGroups(id, (Configurable.Composite)c); + if (result != null) { + return result; + } + } + } + } + return null; + } + + @Nullable + private static Configurable findPreselectedByDisplayName(final String preselectedConfigurableDisplayName, ConfigurableGroup[] groups) { + final List<Configurable> all = SearchUtil.expand(groups); + for (Configurable each : all) { + if (preselectedConfigurableDisplayName.equals(each.getDisplayName())) return each; + } + return null; + } + + @Override + public void doCancelAction(final AWTEvent source) { + if (source instanceof KeyEvent || source instanceof ActionEvent) { + if (myEditor.getContext().isHoldingFilter()) { + myEditor.clearFilter(); + return; + } + } + + super.doCancelAction(source); + } + + @Override + public void doCancelAction() { + saveCurrentConfigurable(); + super.doCancelAction(); + } + + @NotNull + @Override + protected Action[] createActions() { + myApplyAction = new ApplyAction(); + return new Action[]{getOKAction(), getCancelAction(), myApplyAction, getHelpAction()}; + } + + @Override + protected void doHelpAction() { + final String topic = myEditor.getHelpTopic(); + if (topic != null) { + HelpManager.getInstance().invokeHelp(topic); + } + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myEditor.getPreferredFocusedComponent(); + } + + public Object getData(@NonNls String dataId) { + if (OptionsEditor.KEY.is(dataId)) { + return myEditor; + } + return null; + } + + private class ApplyAction extends AbstractAction { + public ApplyAction() { + super(CommonBundle.getApplyButtonText()); + setEnabled(false); + } + + public void actionPerformed(final ActionEvent e) { + myEditor.apply(); + myEditor.revalidate(); + myEditor.repaint(); + } + } +} |