/*
* 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.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.match.tokens.ArrangementRuleAliasDialog;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.intellij.application.options.codeStyle.arrangement.match.ArrangementSectionRuleManager.ArrangementSectionRuleData;
/**
* @author Denis Zhdanov
* @since 10/31/12 1:23 PM
*/
public class ArrangementSectionRulesControl extends ArrangementMatchingRulesControl {
@NotNull public static final DataKey<ArrangementSectionRulesControl> KEY = DataKey.create("Arrangement.Rule.Match.Control");
@NotNull private static final Logger LOG = Logger.getInstance("#" + ArrangementSectionRulesControl.class.getName());
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final ArrangementStandardSettingsManager mySettingsManager;
@Nullable private final ArrangementSectionRuleManager mySectionRuleManager;
@Nullable private ArrangementStandardSettingsManager myExtendedSettingsManager;
public ArrangementSectionRulesControl(@NotNull Language language,
@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull RepresentationCallback callback) {
super(settingsManager, colorsProvider, callback);
mySectionRuleManager = ArrangementSectionRuleManager.getInstance(language, settingsManager, colorsProvider, this);
mySettingsManager = settingsManager;
myColorsProvider = colorsProvider;
}
private static void appendBufferedSectionRules(@NotNull List<ArrangementSectionRule> result,
@NotNull List<StdArrangementMatchRule> buffer,
@Nullable String currentSectionStart) {
if (currentSectionStart == null) {
return;
}
if (buffer.isEmpty()) {
result.add(ArrangementSectionRule.create(currentSectionStart, null));
}
else {
result.add(ArrangementSectionRule.create(currentSectionStart, null, buffer.get(0)));
for (int j = 1; j < buffer.size(); j++) {
result.add(ArrangementSectionRule.create(buffer.get(j)));
}
buffer.clear();
}
}
@Override
protected MatchingRulesRendererBase createRender() {
return new MatchingRulesRenderer();
}
@NotNull
@Override
protected ArrangementMatchingRulesValidator createValidator() {
return new ArrangementSectionRulesValidator(getModel(), mySectionRuleManager);
}
@Nullable
public ArrangementSectionRuleManager getSectionRuleManager() {
return mySectionRuleManager;
}
public List<ArrangementSectionRule> getSections() {
if (getModel().getSize() <= 0) {
return Collections.emptyList();
}
final List<ArrangementSectionRule> result = ContainerUtil.newArrayList();
final List<StdArrangementMatchRule> buffer = ContainerUtil.newArrayList();
String currentSectionStart = null;
for (int i = 0; i < getModel().getSize(); i++) {
final Object element = getModel().getElementAt(i);
if (element instanceof StdArrangementMatchRule) {
final ArrangementSectionRuleData sectionRule =
mySectionRuleManager == null ? null : mySectionRuleManager.getSectionRuleData((StdArrangementMatchRule)element);
if (sectionRule != null) {
if (sectionRule.isSectionStart()) {
appendBufferedSectionRules(result, buffer, currentSectionStart);
currentSectionStart = sectionRule.getText();
}
else {
result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), buffer));
buffer.clear();
currentSectionStart = null;
}
}
else {
if (currentSectionStart == null) {
result.add(ArrangementSectionRule.create((StdArrangementMatchRule)element));
}
else {
buffer.add((StdArrangementMatchRule)element);
}
}
}
}
appendBufferedSectionRules(result, buffer, currentSectionStart);
return result;
}
public void setSections(@Nullable List<ArrangementSectionRule> sections) {
final List<StdArrangementMatchRule> rules = sections == null ? null : ArrangementUtil.collectMatchRules(sections);
myComponents.clear();
getModel().clear();
if (rules == null) {
return;
}
for (StdArrangementMatchRule rule : rules) {
getModel().add(rule);
}
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
LOG.info("Arrangement matching rules list is refreshed. Given rules:");
for (StdArrangementMatchRule rule : rules) {
LOG.info(" " + rule.toString());
}
}
}
@Nullable
public Collection<StdArrangementRuleAliasToken> getRulesAliases() {
return myExtendedSettingsManager == null ? null : myExtendedSettingsManager.getRuleAliases();
}
public void setRulesAliases(@Nullable Collection<StdArrangementRuleAliasToken> aliases) {
if (aliases != null) {
myExtendedSettingsManager = new ArrangementStandardSettingsManager(mySettingsManager.getDelegate(), myColorsProvider, aliases);
myEditor = new ArrangementMatchingRuleEditor(myExtendedSettingsManager, myColorsProvider, this);
}
}
public void showEditor(int rowToEdit) {
if (mySectionRuleManager != null && mySectionRuleManager.isSectionRule(getModel().getElementAt(rowToEdit))) {
mySectionRuleManager.showEditor(rowToEdit);
}
else {
super.showEditor(rowToEdit);
}
}
@NotNull
public ArrangementRuleAliasDialog createRuleAliasEditDialog() {
final Set<String> tokenIds = new THashSet<String>();
final List<ArrangementSectionRule> sections = getSections();
for (ArrangementSectionRule section : sections) {
for (StdArrangementMatchRule rule : section.getMatchRules()) {
rule.getMatcher().getCondition().invite(new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
if (ArrangementUtil.isAliasedCondition(condition)) {
tokenIds.add(condition.getType().getId());
}
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
for (ArrangementMatchCondition operand : condition.getOperands()) {
operand.invite(this);
}
}
});
}
}
final Collection<StdArrangementRuleAliasToken> aliases = getRulesAliases();
assert aliases != null;
return new ArrangementRuleAliasDialog(null, mySettingsManager, myColorsProvider, aliases, tokenIds);
}
private class MatchingRulesRenderer extends MatchingRulesRendererBase {
@Override
public boolean allowModifications(StdArrangementMatchRule rule) {
return !(mySectionRuleManager != null && mySectionRuleManager.isSectionRule(rule));
}
}
}