summaryrefslogtreecommitdiff
path: root/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
diff options
context:
space:
mode:
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.java330
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();
+ }
+ }
+}