blob: 758aef6a906589f4ae58daef20d8fe8f604bb262 [file] [log] [blame]
/*
* 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.application.options;
import com.intellij.application.options.codeStyle.*;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
import com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;
public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent.Abstract implements OptionsContainingConfigurable {
private CodeStyleSchemesPanel myRootSchemesPanel;
private CodeStyleSchemesModel myModel;
private List<CodeStyleConfigurableWrapper> myPanels;
private boolean myResetCompleted = false;
private boolean myInitResetInvoked = false;
private boolean myRevertCompleted = false;
private boolean myApplyCompleted = false;
private final Project myProject;
private final LanguageSelector myLangSelector;
public CodeStyleSchemesConfigurable(Project project) {
myProject = project;
myLangSelector = new LanguageSelector();
}
@Override
public JComponent createComponent() {
myModel = ensureModel();
if (Registry.is("ide.new.settings.dialog")) {
return myPanels == null || myPanels.isEmpty() ? null : myPanels.get(0).createComponent();
}
return myRootSchemesPanel.getPanel();
}
@Override
public boolean hasOwnContent() {
return true;
}
@Override
public void disposeUIResources() {
if (myPanels != null) {
try {
super.disposeUIResources();
for (CodeStyleConfigurableWrapper panel : myPanels) {
panel.disposeUIResources();
}
}
finally {
myPanels = null;
myModel = null;
myRootSchemesPanel = null;
myResetCompleted = false;
myRevertCompleted = false;
myApplyCompleted = false;
myInitResetInvoked = false;
}
}
}
@Override
public synchronized void reset() {
if (!myInitResetInvoked) {
try {
if (!myResetCompleted) {
try {
resetImpl();
}
finally {
myResetCompleted = true;
}
}
}
finally {
myInitResetInvoked = true;
}
}
else {
revert();
}
}
private void resetImpl() {
if (myModel != null) {
myModel.reset();
}
if (myPanels != null) {
for (CodeStyleConfigurableWrapper panel : myPanels) {
panel.resetPanel();
}
}
}
public synchronized void resetFromChild() {
if (!myResetCompleted) {
try {
resetImpl();
}
finally {
myResetCompleted = true;
}
}
}
public void revert() {
if (myModel.isSchemeListModified() || isSomeSchemeModified()) {
myRevertCompleted = false;
}
if (!myRevertCompleted) {
try {
resetImpl();
}
finally {
myRevertCompleted = true;
}
}
}
private boolean isSomeSchemeModified() {
if (myPanels != null) {
for (CodeStyleConfigurableWrapper panel : myPanels) {
if (panel.isPanelModified()) return true;
}
}
return false;
}
@Override
public void apply() throws ConfigurationException {
if (!myApplyCompleted) {
try {
super.apply();
for (CodeStyleScheme scheme : new ArrayList<CodeStyleScheme>(myModel.getSchemes())) {
final boolean isDefaultModified = CodeStyleSchemesModel.cannotBeModified(scheme) && isSchemeModified(scheme);
if (isDefaultModified) {
CodeStyleScheme newscheme = myModel.createNewScheme(null, scheme);
CodeStyleSettings settingsWillBeModified = scheme.getCodeStyleSettings();
CodeStyleSettings notModifiedSettings = settingsWillBeModified.clone();
((CodeStyleSchemeImpl)scheme).setCodeStyleSettings(notModifiedSettings);
((CodeStyleSchemeImpl)newscheme).setCodeStyleSettings(settingsWillBeModified);
myModel.addScheme(newscheme, false);
if (myModel.getSelectedScheme() == scheme) {
myModel.selectScheme(newscheme, this);
}
}
}
for (CodeStyleConfigurableWrapper panel : myPanels) {
panel.applyPanel();
}
myModel.apply();
EditorFactory.getInstance().refreshAllEditors();
}
finally {
myApplyCompleted = true;
}
}
}
private boolean isSchemeModified(final CodeStyleScheme scheme) {
for (CodeStyleConfigurableWrapper panel : myPanels) {
if (panel.isPanelModified(scheme)) {
return true;
}
}
return false;
}
@Override
protected Configurable[] buildConfigurables() {
myPanels = new ArrayList<CodeStyleConfigurableWrapper>();
final List<CodeStyleSettingsProvider> providers =
Arrays.asList(Extensions.getExtensions(CodeStyleSettingsProvider.EXTENSION_POINT_NAME));
Collections.sort(providers, new Comparator<CodeStyleSettingsProvider>() {
@Override
public int compare(CodeStyleSettingsProvider p1, CodeStyleSettingsProvider p2) {
if (!p1.getPriority().equals(p2.getPriority())) {
return p1.getPriority().compareTo(p2.getPriority());
}
String name1 = p1.getConfigurableDisplayName();
if (name1 == null) name1 = "";
String name2 = p2.getConfigurableDisplayName();
if (name2 == null) name2 = "";
return name1.compareToIgnoreCase(name2);
}
});
for (final CodeStyleSettingsProvider provider : providers) {
if (provider.hasSettingsPage()) {
myPanels.add(new CodeStyleConfigurableWrapper(provider, new CodeStyleSettingsPanelFactory() {
@Override
public NewCodeStyleSettingsPanel createPanel(final CodeStyleScheme scheme) {
return new NewCodeStyleSettingsPanel(provider.createSettingsPage(scheme.getCodeStyleSettings(), ensureModel().getCloneSettings(scheme)));
}
}));
}
}
if (Registry.is("ide.new.settings.dialog")) {
int size = myPanels.size();
Configurable[] result = new Configurable[size > 0 ? size - 1 : 0];
for (int i = 0; i < result.length; i++) {
result[i] = myPanels.get(i + 1);
}
return result;
}
return myPanels.toArray(new Configurable[myPanels.size()]);
}
private CodeStyleSchemesModel ensureModel() {
if (myModel == null) {
myModel = new CodeStyleSchemesModel(myProject);
myRootSchemesPanel = new CodeStyleSchemesPanel(myModel);
myModel.addListener(new CodeStyleSettingsListener(){
@Override
public void currentSchemeChanged(final Object source) {
if (source != myRootSchemesPanel) {
myRootSchemesPanel.onSelectedSchemeChanged();
}
}
@Override
public void schemeListChanged() {
myRootSchemesPanel.resetSchemesCombo();
}
@Override
public void currentSettingsChanged() {
}
@Override
public void usePerProjectSettingsOptionChanged() {
myRootSchemesPanel.usePerProjectSettingsOptionChanged();
}
@Override
public void schemeChanged(final CodeStyleScheme scheme) {
//do nothing
}
});
}
return myModel;
}
@Override
public String getDisplayName() {
return "Code Style";
}
@Override
public String getHelpTopic() {
return "reference.settingsdialog.IDE.globalcodestyle";
}
public void selectPage(Class pageToSelect) {
//TODO lesya
//getActivePanel().selectTab(pageToSelect);
}
@Override
public boolean isModified() {
if (myModel != null) {
if (Registry.is("ide.new.settings.dialog")) {
if (myPanels != null && myPanels.size() > 0 && myPanels.get(0).isModified()) {
return true;
}
}
boolean schemeListModified = myModel.isSchemeListModified();
if (schemeListModified) {
myApplyCompleted = false;
myRevertCompleted = false;
}
return schemeListModified;
}
return false;
}
@Override
@NotNull
public String getId() {
return "preferences.sourceCode";
}
@Override
public Set<String> processListOptions() {
HashSet<String> result = new HashSet<String>();
for (CodeStyleConfigurableWrapper panel : myPanels) {
result.addAll(panel.processListOptions());
}
return result;
}
private class CodeStyleConfigurableWrapper implements SearchableConfigurable, NoScroll, OptionsContainingConfigurable {
private boolean myInitialResetInvoked;
private CodeStyleMainPanel myPanel;
private final CodeStyleSettingsProvider myProvider;
private final CodeStyleSettingsPanelFactory myFactory;
public CodeStyleConfigurableWrapper(@NotNull CodeStyleSettingsProvider provider, @NotNull CodeStyleSettingsPanelFactory factory) {
myProvider = provider;
myFactory = factory;
myInitialResetInvoked = false;
}
@Override
@Nls
public String getDisplayName() {
String displayName = myProvider.getConfigurableDisplayName();
if (displayName != null) return displayName;
return myPanel != null ? myPanel.getDisplayName() : null; // fallback for 8.0 API compatibility
}
@Override
public String getHelpTopic() {
return myPanel != null ? myPanel.getHelpTopic() : null;
}
@Override
public JComponent createComponent() {
myPanel = new CodeStyleMainPanel(ensureModel(), myLangSelector, myFactory);
return myPanel;
}
@Override
public boolean isModified() {
if (myPanel != null) {
boolean someSchemeModified = myPanel.isModified();
if (someSchemeModified) {
myApplyCompleted = false;
myRevertCompleted = false;
}
return someSchemeModified;
}
return false;
}
@Override
public void apply() throws ConfigurationException {
CodeStyleSchemesConfigurable.this.apply();
}
public void resetPanel() {
if (myPanel != null) {
myPanel.reset();
}
}
@Override
public String toString() {
return myProvider.getClass().getName();
}
@Override
public void reset() {
if (!myInitialResetInvoked) {
try {
resetFromChild();
}
finally {
myInitialResetInvoked = true;
}
}
else {
revert();
}
}
@Override
@NotNull
public String getId() {
return "preferences.sourceCode." + getDisplayName();
}
@Override
public Runnable enableSearch(final String option) {
return null;
}
@Override
public void disposeUIResources() {
if (myPanel != null) {
myPanel.disposeUIResources();
}
}
public boolean isPanelModified(CodeStyleScheme scheme) {
return myPanel != null && myPanel.isModified(scheme);
}
public boolean isPanelModified() {
return myPanel != null && myPanel.isModified();
}
public void applyPanel() throws ConfigurationException {
if (myPanel != null) {
myPanel.apply();
}
}
@Override
public Set<String> processListOptions() {
if (myPanel == null) {
myPanel = new CodeStyleMainPanel(ensureModel(), myLangSelector, myFactory);
}
return myPanel.processListOptions();
}
}
}