| /* |
| * 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.codeStyle; |
| |
| import com.intellij.openapi.options.SchemesManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.codeStyle.CodeStyleScheme; |
| import com.intellij.psi.codeStyle.CodeStyleSchemes; |
| import com.intellij.psi.codeStyle.CodeStyleSettings; |
| import com.intellij.psi.codeStyle.CodeStyleSettingsManager; |
| import com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeImpl; |
| import com.intellij.psi.impl.source.codeStyle.CodeStyleSchemesImpl; |
| import com.intellij.util.EventDispatcher; |
| import com.intellij.util.containers.ContainerUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| |
| public class CodeStyleSchemesModel { |
| |
| private final List<CodeStyleScheme> mySchemes = new ArrayList<CodeStyleScheme>(); |
| private CodeStyleScheme myGlobalSelected; |
| private final CodeStyleSchemeImpl myProjectScheme; |
| private final CodeStyleScheme myDefault; |
| private final Map<CodeStyleScheme, CodeStyleSettings> mySettingsToClone = new HashMap<CodeStyleScheme, CodeStyleSettings>(); |
| |
| private final EventDispatcher<CodeStyleSettingsListener> myDispatcher = EventDispatcher.create(CodeStyleSettingsListener.class); |
| private final Project myProject; |
| private boolean myUsePerProjectSettings; |
| |
| public static final String PROJECT_SCHEME_NAME = "Project"; |
| |
| public CodeStyleSchemesModel(Project project) { |
| myProject = project; |
| myProjectScheme = new CodeStyleSchemeImpl(PROJECT_SCHEME_NAME, false, CodeStyleSchemes.getInstance().getDefaultScheme()); |
| reset(); |
| myDefault = CodeStyleSchemes.getInstance().getDefaultScheme(); |
| } |
| |
| public void selectScheme(final CodeStyleScheme selected, @Nullable Object source) { |
| if (myGlobalSelected != selected && selected != myProjectScheme) { |
| myGlobalSelected = selected; |
| myDispatcher.getMulticaster().currentSchemeChanged(source); |
| } |
| } |
| |
| public void addScheme(final CodeStyleScheme newScheme, boolean changeSelection) { |
| mySchemes.add(newScheme); |
| myDispatcher.getMulticaster().schemeListChanged(); |
| if (changeSelection) { |
| selectScheme(newScheme, this); |
| } |
| } |
| |
| public void removeScheme(final CodeStyleScheme scheme) { |
| mySchemes.remove(scheme); |
| myDispatcher.getMulticaster().schemeListChanged(); |
| if (myGlobalSelected == scheme) { |
| selectScheme(myDefault, this); |
| } |
| } |
| |
| public CodeStyleSettings getCloneSettings(final CodeStyleScheme scheme) { |
| if (!mySettingsToClone.containsKey(scheme)) { |
| mySettingsToClone.put(scheme, scheme.getCodeStyleSettings().clone()); |
| } |
| return mySettingsToClone.get(scheme); |
| } |
| |
| public CodeStyleScheme getSelectedScheme(){ |
| if (myUsePerProjectSettings) { |
| return myProjectScheme; |
| } |
| return myGlobalSelected; |
| } |
| |
| public void addListener(CodeStyleSettingsListener listener) { |
| myDispatcher.addListener(listener); |
| } |
| |
| public List<CodeStyleScheme> getSchemes() { |
| return Collections.unmodifiableList(mySchemes); |
| } |
| |
| public void reset() { |
| myUsePerProjectSettings = getProjectSettings().USE_PER_PROJECT_SETTINGS; |
| |
| CodeStyleScheme[] allSchemes = CodeStyleSchemes.getInstance().getSchemes(); |
| mySettingsToClone.clear(); |
| mySchemes.clear(); |
| ContainerUtil.addAll(mySchemes, allSchemes); |
| myGlobalSelected = CodeStyleSchemes.getInstance().findPreferredScheme(getProjectSettings().PREFERRED_PROJECT_CODE_STYLE); |
| |
| CodeStyleSettings perProjectSettings = getProjectSettings().PER_PROJECT_SETTINGS; |
| if (perProjectSettings != null) { |
| myProjectScheme.setCodeStyleSettings(perProjectSettings); |
| } |
| |
| |
| myDispatcher.getMulticaster().schemeListChanged(); |
| myDispatcher.getMulticaster().currentSchemeChanged(this); |
| |
| } |
| |
| public boolean isUsePerProjectSettings() { |
| return myUsePerProjectSettings; |
| } |
| |
| public void setUsePerProjectSettings(final boolean usePerProjectSettings) { |
| setUsePerProjectSettings(usePerProjectSettings, false); |
| } |
| |
| /** |
| * Updates 'use per-project settings' value within the current model and optionally at the project settings. |
| * |
| * @param usePerProjectSettings defines whether 'use per-project settings' are in use |
| * @param commit flag that defines if current project settings should be applied as well |
| */ |
| public void setUsePerProjectSettings(final boolean usePerProjectSettings, final boolean commit) { |
| if (commit) { |
| final CodeStyleSettingsManager projectSettings = getProjectSettings(); |
| projectSettings.USE_PER_PROJECT_SETTINGS = usePerProjectSettings; |
| projectSettings.PER_PROJECT_SETTINGS = myProjectScheme.getCodeStyleSettings(); |
| } |
| |
| if (myUsePerProjectSettings != usePerProjectSettings) { |
| myUsePerProjectSettings = usePerProjectSettings; |
| myDispatcher.getMulticaster().usePerProjectSettingsOptionChanged(); |
| myDispatcher.getMulticaster().currentSchemeChanged(this); |
| } |
| } |
| |
| private CodeStyleSettingsManager getProjectSettings() { |
| return CodeStyleSettingsManager.getInstance(myProject); |
| } |
| |
| public boolean isSchemeListModified() { |
| CodeStyleSchemes schemes = CodeStyleSchemes.getInstance(); |
| if (getProjectSettings().USE_PER_PROJECT_SETTINGS != myUsePerProjectSettings) return true; |
| if (!myUsePerProjectSettings && |
| getSelectedScheme() != schemes.findPreferredScheme(getProjectSettings().PREFERRED_PROJECT_CODE_STYLE)) { |
| return true; |
| } |
| Set<CodeStyleScheme> configuredSchemesSet = new HashSet<CodeStyleScheme>(getSchemes()); |
| Set<CodeStyleScheme> savedSchemesSet = new HashSet<CodeStyleScheme>(Arrays.asList(schemes.getSchemes())); |
| return !configuredSchemesSet.equals(savedSchemesSet); |
| } |
| |
| public void apply() { |
| CodeStyleSettingsManager projectSettingsManager = getProjectSettings(); |
| projectSettingsManager.USE_PER_PROJECT_SETTINGS = myUsePerProjectSettings; |
| projectSettingsManager.PREFERRED_PROJECT_CODE_STYLE = |
| myUsePerProjectSettings || myGlobalSelected == null ? null : myGlobalSelected.getName(); |
| projectSettingsManager.PER_PROJECT_SETTINGS = myProjectScheme.getCodeStyleSettings(); |
| |
| final CodeStyleScheme[] savedSchemes = CodeStyleSchemes.getInstance().getSchemes(); |
| final Set<CodeStyleScheme> savedSchemesSet = new HashSet<CodeStyleScheme>(Arrays.asList(savedSchemes)); |
| List<CodeStyleScheme> configuredSchemes = getSchemes(); |
| |
| for (CodeStyleScheme savedScheme : savedSchemes) { |
| if (!configuredSchemes.contains(savedScheme)) { |
| CodeStyleSchemes.getInstance().deleteScheme(savedScheme); |
| } |
| } |
| |
| for (CodeStyleScheme configuredScheme : configuredSchemes) { |
| if (!savedSchemesSet.contains(configuredScheme)) { |
| CodeStyleSchemes.getInstance().addScheme(configuredScheme); |
| } |
| } |
| |
| CodeStyleSchemes.getInstance().setCurrentScheme(myGlobalSelected); |
| |
| // We want to avoid the situation when 'real code style' differs from the copy stored here (e.g. when 'real code style' changes |
| // are 'committed' by pressing 'Apply' button). So, we reset the copies here assuming that this method is called on 'Apply' |
| // button processing |
| mySettingsToClone.clear(); |
| } |
| |
| static SchemesManager<CodeStyleScheme, CodeStyleSchemeImpl> getSchemesManager() { |
| return ((CodeStyleSchemesImpl) CodeStyleSchemes.getInstance()).getSchemesManager(); |
| } |
| |
| public static boolean cannotBeModified(final CodeStyleScheme currentScheme) { |
| return currentScheme.isDefault() || getSchemesManager().isShared(currentScheme); |
| } |
| |
| public static boolean cannotBeDeleted(final CodeStyleScheme currentScheme) { |
| return currentScheme.isDefault(); |
| } |
| |
| public void fireCurrentSettingsChanged() { |
| myDispatcher.getMulticaster().currentSettingsChanged(); |
| } |
| |
| public void fireSchemeChanged(CodeStyleScheme scheme) { |
| myDispatcher.getMulticaster().schemeChanged(scheme); |
| } |
| |
| public CodeStyleScheme getSelectedGlobalScheme() { |
| return myGlobalSelected; |
| } |
| |
| public void copyToProject(final CodeStyleScheme selectedScheme) { |
| myProjectScheme.getCodeStyleSettings().copyFrom(selectedScheme.getCodeStyleSettings()); |
| myDispatcher.getMulticaster().schemeChanged(myProjectScheme); |
| } |
| |
| public CodeStyleScheme exportProjectScheme(@NotNull String name) { |
| CodeStyleScheme newScheme = createNewScheme(name, myProjectScheme); |
| ((CodeStyleSchemeImpl)newScheme).setCodeStyleSettings(getCloneSettings(myProjectScheme)); |
| addScheme(newScheme, false); |
| |
| return newScheme; |
| } |
| |
| public CodeStyleScheme createNewScheme(final String preferredName, final CodeStyleScheme parentScheme) { |
| String name; |
| if (preferredName == null) { |
| if (parentScheme == null) throw new IllegalArgumentException("parentScheme must not be null"); |
| // Generate using parent name |
| name = null; |
| for (int i = 1; name == null; i++) { |
| String currName = parentScheme.getName() + " (" + i + ")"; |
| if (findSchemeByName(currName) == null) { |
| name = currName; |
| } |
| } |
| } |
| else { |
| name = null; |
| for (int i = 0; name == null; i++) { |
| String currName = i == 0 ? preferredName : preferredName + " (" + i + ")"; |
| if (findSchemeByName(currName) == null) { |
| name = currName; |
| } |
| } |
| } |
| |
| return new CodeStyleSchemeImpl(name, false, parentScheme); |
| } |
| |
| @Nullable |
| private CodeStyleScheme findSchemeByName(final String name) { |
| for (CodeStyleScheme scheme : mySchemes) { |
| if (name.equals(scheme.getName())) return scheme; |
| } |
| return null; |
| } |
| |
| public CodeStyleScheme getProjectScheme() { |
| return myProjectScheme; |
| } |
| |
| public boolean isProjectScheme(CodeStyleScheme scheme) { |
| return myProjectScheme == scheme; |
| } |
| |
| public List<CodeStyleScheme> getAllSortedSchemes() { |
| List<CodeStyleScheme> schemes = new ArrayList<CodeStyleScheme>(); |
| schemes.addAll(getSchemes()); |
| schemes.add(myProjectScheme); |
| Collections.sort(schemes, new Comparator<CodeStyleScheme>() { |
| @Override |
| public int compare(CodeStyleScheme s1, CodeStyleScheme s2) { |
| if (isProjectScheme(s1)) return -1; |
| if (isProjectScheme(s2)) return 1; |
| if (s1.isDefault()) return -1; |
| if (s2.isDefault()) return 1; |
| return s1.getName().compareToIgnoreCase(s2.getName()); |
| } |
| }); |
| return schemes; |
| } |
| } |