IDEA-102405 Arrangement: Refactor the API in accordance with design problems discovered during non-java arrangement implementations

1. Old settings enum (ArrangementEntryType, ArrangementModifier etc) are replaced by ArrangementSettingsToken;
2. All existing arrangement codebase is switched to the new api;
This commit is contained in:
Denis.Zhdanov
2013-03-14 11:57:11 +04:00
parent 7b96f5945e
commit 9dd8224f79
97 changed files with 2981 additions and 2907 deletions
@@ -18,12 +18,12 @@ package com.intellij.psi.codeStyle.arrangement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,37 +33,41 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*;
public class JavaArrangementVisitor extends JavaElementVisitor {
private static final String NULL_CONTENT = "no content";
private static final Map<String, ArrangementModifier> MODIFIERS = new HashMap<String, ArrangementModifier>();
private static final Map<String, ArrangementSettingsToken> MODIFIERS = ContainerUtilRt.newHashMap();
static {
MODIFIERS.put(PsiModifier.PUBLIC, ArrangementModifier.PUBLIC);
MODIFIERS.put(PsiModifier.PROTECTED, ArrangementModifier.PROTECTED);
MODIFIERS.put(PsiModifier.PRIVATE, ArrangementModifier.PRIVATE);
MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, ArrangementModifier.PACKAGE_PRIVATE);
MODIFIERS.put(PsiModifier.STATIC, ArrangementModifier.STATIC);
MODIFIERS.put(PsiModifier.FINAL, ArrangementModifier.FINAL);
MODIFIERS.put(PsiModifier.TRANSIENT, ArrangementModifier.TRANSIENT);
MODIFIERS.put(PsiModifier.VOLATILE, ArrangementModifier.VOLATILE);
MODIFIERS.put(PsiModifier.SYNCHRONIZED, ArrangementModifier.SYNCHRONIZED);
MODIFIERS.put(PsiModifier.ABSTRACT, ArrangementModifier.ABSTRACT);
MODIFIERS.put(PsiModifier.PUBLIC, PUBLIC);
MODIFIERS.put(PsiModifier.PROTECTED, PROTECTED);
MODIFIERS.put(PsiModifier.PRIVATE, PRIVATE);
MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, PACKAGE_PRIVATE);
MODIFIERS.put(PsiModifier.STATIC, STATIC);
MODIFIERS.put(PsiModifier.FINAL, FINAL);
MODIFIERS.put(PsiModifier.TRANSIENT, TRANSIENT);
MODIFIERS.put(PsiModifier.VOLATILE, VOLATILE);
MODIFIERS.put(PsiModifier.SYNCHRONIZED, SYNCHRONIZED);
MODIFIERS.put(PsiModifier.ABSTRACT, ABSTRACT);
}
@NotNull private final Stack<JavaElementArrangementEntry> myStack = new Stack<JavaElementArrangementEntry>();
@NotNull private final Map<PsiElement, JavaElementArrangementEntry> myEntries = new HashMap<PsiElement, JavaElementArrangementEntry>();
@NotNull private final JavaArrangementParseInfo myInfo;
@NotNull private final Collection<TextRange> myRanges;
@NotNull private final Set<ArrangementGroupingType> myGroupingRules;
@NotNull private final MethodBodyProcessor myMethodBodyProcessor;
@Nullable private final Document myDocument;
@NotNull private final JavaArrangementParseInfo myInfo;
@NotNull private final Collection<TextRange> myRanges;
@NotNull private final Set<ArrangementSettingsToken> myGroupingRules;
@NotNull private final MethodBodyProcessor myMethodBodyProcessor;
@Nullable private final Document myDocument;
public JavaArrangementVisitor(@NotNull JavaArrangementParseInfo infoHolder,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull Set<ArrangementGroupingType> groupingRules)
@NotNull Set<ArrangementSettingsToken> groupingRules)
{
myInfo = infoHolder;
myDocument = document;
@@ -74,12 +78,12 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
@Override
public void visitClass(PsiClass aClass) {
ArrangementEntryType type = ArrangementEntryType.CLASS;
ArrangementSettingsToken type = CLASS;
if (aClass.isEnum()) {
type = ArrangementEntryType.ENUM;
type = ENUM;
}
else if (aClass.isInterface()) {
type = ArrangementEntryType.INTERFACE;
type = INTERFACE;
}
JavaElementArrangementEntry entry = createNewEntry(aClass, aClass.getTextRange(), type, aClass.getName(), true);
processEntry(entry, aClass, aClass);
@@ -88,7 +92,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
@Override
public void visitAnonymousClass(PsiAnonymousClass aClass) {
JavaElementArrangementEntry entry = createNewEntry(
aClass, aClass.getTextRange(), ArrangementEntryType.ANONYMOUS_CLASS, aClass.getName(), false
aClass, aClass.getTextRange(), ANONYMOUS_CLASS, aClass.getName(), false
);
processEntry(entry, null, aClass);
}
@@ -107,8 +111,8 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
PsiElement fieldPrev = getPreviousNonWsComment(field.getPrevSibling(), 0);
if (fieldPrev instanceof PsiJavaToken && ((PsiJavaToken)fieldPrev).getTokenType() == JavaTokenType.COMMA) {
return;
}
}
// There is a possible case that fields which share the same type declaration are located on different document lines, e.g.:
// int i1,
// i2;
@@ -158,7 +162,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
break;
}
}
JavaElementArrangementEntry entry = createNewEntry(field, range, ArrangementEntryType.FIELD, field.getName(), true);
JavaElementArrangementEntry entry = createNewEntry(field, range, FIELD, field.getName(), true);
processEntry(entry, field, field.getInitializer());
}
@@ -182,7 +186,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
@Override
public void visitClassInitializer(PsiClassInitializer initializer) {
JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), ArrangementEntryType.FIELD, null, true);
JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), FIELD, null, true);
if (entry == null) {
return;
}
@@ -211,7 +215,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
@Override
public void visitMethod(PsiMethod method) {
ArrangementEntryType type = method.isConstructor() ? ArrangementEntryType.CONSTRUCTOR : ArrangementEntryType.METHOD;
ArrangementSettingsToken type = method.isConstructor() ? CONSTRUCTOR : METHOD;
JavaElementArrangementEntry entry = createNewEntry(method, method.getTextRange(), type, method.getName(), true);
if (entry == null) {
return;
@@ -236,7 +240,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
}
private void parseProperties(PsiMethod method, JavaElementArrangementEntry entry) {
if (!myGroupingRules.contains(ArrangementGroupingType.GETTERS_AND_SETTERS)) {
if (!myGroupingRules.contains(StdArrangementTokens.Grouping.GETTERS_AND_SETTERS)) {
return;
}
@@ -283,7 +287,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
return;
}
JavaElementArrangementEntry entry =
createNewEntry(anonymousClass, anonymousClass.getTextRange(), ArrangementEntryType.CLASS, anonymousClass.getName(), false);
createNewEntry(anonymousClass, anonymousClass.getTextRange(), CLASS, anonymousClass.getName(), false);
processEntry(entry, null, anonymousClass);
}
@@ -326,7 +330,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
@Nullable
private JavaElementArrangementEntry createNewEntry(@NotNull PsiElement element,
@NotNull TextRange range,
@NotNull ArrangementEntryType type,
@NotNull ArrangementSettingsToken type,
@Nullable String name,
boolean canArrange)
{
@@ -375,14 +379,14 @@ public class JavaArrangementVisitor extends JavaElementVisitor {
}
for (String modifier : PsiModifier.MODIFIERS) {
if (modifierList.hasModifierProperty(modifier)) {
ArrangementModifier arrangementModifier = MODIFIERS.get(modifier);
ArrangementSettingsToken arrangementModifier = MODIFIERS.get(modifier);
if (arrangementModifier != null) {
entry.addModifier(arrangementModifier);
}
}
}
if (modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
entry.addModifier(ArrangementModifier.PACKAGE_PRIVATE);
entry.addModifier(PACKAGE_PRIVATE);
}
}
@@ -17,12 +17,11 @@ package com.intellij.psi.codeStyle.arrangement;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.Set;
/**
@@ -35,15 +34,15 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry
implements TypeAwareArrangementEntry, NameAwareArrangementEntry,ModifierAwareArrangementEntry
{
private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
@NotNull private final Set<ArrangementSettingsToken> myModifiers = ContainerUtilRt.newHashSet();
@NotNull private final Set<ArrangementSettingsToken> myTypes = ContainerUtilRt.newHashSet();
@NotNull private final Set<ArrangementEntryType> myTypes;
@NotNull private final ArrangementEntryType myType;
@Nullable private final String myName;
@NotNull private final ArrangementSettingsToken myType;
@Nullable private final String myName;
public JavaElementArrangementEntry(@Nullable ArrangementEntry parent,
@NotNull TextRange range,
@NotNull ArrangementEntryType type,
@NotNull ArrangementSettingsToken type,
@Nullable String name,
boolean canBeMatched)
{
@@ -53,26 +52,23 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry
public JavaElementArrangementEntry(@Nullable ArrangementEntry parent,
int startOffset,
int endOffset,
@NotNull ArrangementEntryType type,
@NotNull ArrangementSettingsToken type,
@Nullable String name,
boolean canBeArranged)
{
super(parent, startOffset, endOffset, canBeArranged);
myType = type;
myTypes = EnumSet.of(type);
if (myType == ArrangementEntryType.CONSTRUCTOR) {
myTypes.add(ArrangementEntryType.METHOD);
}
myTypes.add(type);
myName = name;
}
@NotNull
@Override
public Set<ArrangementModifier> getModifiers() {
public Set<ArrangementSettingsToken> getModifiers() {
return myModifiers;
}
public void addModifier(@NotNull ArrangementModifier modifier) {
public void addModifier(@NotNull ArrangementSettingsToken modifier) {
myModifiers.add(modifier);
}
@@ -84,12 +80,12 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry
@NotNull
@Override
public Set<ArrangementEntryType> getTypes() {
public Set<ArrangementSettingsToken> getTypes() {
return myTypes;
}
@NotNull
public ArrangementEntryType getType() {
public ArrangementSettingsToken getType() {
return myType;
}
@@ -18,31 +18,25 @@ package com.intellij.psi.codeStyle.arrangement;
import com.intellij.ide.highlighter.JavaHighlightingColors;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementConditionsGrouper;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
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.std.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,36 +45,38 @@ import java.awt.*;
import java.util.*;
import java.util.List;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.*;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*;
/**
* @author Denis Zhdanov
* @since 7/20/12 2:31 PM
*/
public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware,
ArrangementConditionsGrouper, ArrangementColorsAware
{
public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware, ArrangementColorsAware {
// Type
@NotNull private static final Set<ArrangementEntryType> SUPPORTED_TYPES = EnumSet.of(INTERFACE, CLASS, ENUM, FIELD, METHOD, CONSTRUCTOR);
// Modifier
@NotNull private static final Set<ArrangementModifier> SUPPORTED_MODIFIERS = EnumSet.of(
PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE, STATIC, FINAL, VOLATILE, TRANSIENT, SYNCHRONIZED, ABSTRACT
@NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES = ContainerUtilRt.newLinkedHashSet(
FIELD, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM
);
@NotNull private static final Object NO_TYPE = new Object();
@NotNull private static final Map<Object, Set<ArrangementModifier>> MODIFIERS_BY_TYPE = new HashMap<Object, Set<ArrangementModifier>>();
@NotNull private static final Collection<Set<?>> MUTEXES = new ArrayList<Set<?>>();
// Modifier
@NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_MODIFIERS = ContainerUtilRt.newLinkedHashSet(
PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE, STATIC, FINAL, ABSTRACT, SYNCHRONIZED, TRANSIENT, VOLATILE
);
@NotNull private static final List<ArrangementSettingsToken> SUPPORTED_ORDERS = ContainerUtilRt.newArrayList(KEEP, BY_NAME);
@NotNull private static final ArrangementSettingsToken NO_TYPE = new ArrangementSettingsToken("NO_TYPE", "NO_TYPE");
@NotNull
private static final Map<ArrangementSettingsToken, Set<ArrangementSettingsToken>> MODIFIERS_BY_TYPE = ContainerUtilRt.newHashMap();
@NotNull private static final Collection<Set<ArrangementSettingsToken>> MUTEXES = ContainerUtilRt.newArrayList();
static {
EnumSet<ArrangementModifier> visibilityModifiers = EnumSet.of(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE);
Set<ArrangementSettingsToken> visibilityModifiers = ContainerUtilRt.newHashSet(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE);
MUTEXES.add(visibilityModifiers);
MUTEXES.add(SUPPORTED_TYPES);
Set<ArrangementModifier> commonModifiers = concat(visibilityModifiers, STATIC, FINAL);
Set<ArrangementSettingsToken> commonModifiers = concat(visibilityModifiers, STATIC, FINAL);
MODIFIERS_BY_TYPE.put(NO_TYPE, commonModifiers);
MODIFIERS_BY_TYPE.put(ENUM, visibilityModifiers);
MODIFIERS_BY_TYPE.put(INTERFACE, visibilityModifiers);
@@ -89,135 +85,20 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
MODIFIERS_BY_TYPE.put(CONSTRUCTOR, concat(commonModifiers, SYNCHRONIZED));
MODIFIERS_BY_TYPE.put(FIELD, concat(commonModifiers, TRANSIENT, VOLATILE));
}
@NotNull private static final List<Set<ArrangementMatchCondition>> UI_GROUPING_RULES = ContainerUtilRt.newArrayList();
private static final Map<ArrangementSettingsToken, List<ArrangementSettingsToken>> GROUPING_RULES = ContainerUtilRt.newLinkedHashMap();
static {
UI_GROUPING_RULES.add(new HashSet<ArrangementMatchCondition>(
ContainerUtil.map(
SUPPORTED_TYPES,
new Function<ArrangementEntryType, ArrangementMatchCondition>() {
@Override
public ArrangementMatchCondition fun(ArrangementEntryType type) {
return new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, type);
}
}
)
));
}
private static final Map<ArrangementGroupingType, Set<ArrangementEntryOrderType>> GROUPING_RULES = ContainerUtilRt.newHashMap();
static {
GROUPING_RULES.put(ArrangementGroupingType.GETTERS_AND_SETTERS, EnumSet.noneOf(ArrangementEntryOrderType.class));
GROUPING_RULES.put(ArrangementGroupingType.OVERRIDDEN_METHODS,
EnumSet.of(ArrangementEntryOrderType.BY_NAME, ArrangementEntryOrderType.KEEP));
GROUPING_RULES.put(ArrangementGroupingType.DEPENDENT_METHODS,
EnumSet.of(ArrangementEntryOrderType.BREADTH_FIRST, ArrangementEntryOrderType.DEPTH_FIRST));
}
private static final List<ArrangementGroupingRule> DEFAULT_GROUPING_RULES = new ArrayList<ArrangementGroupingRule>();
static {
DEFAULT_GROUPING_RULES.add(new ArrangementGroupingRule(ArrangementGroupingType.GETTERS_AND_SETTERS));
}
private static final List<StdArrangementMatchRule> DEFAULT_MATCH_RULES = new ArrayList<StdArrangementMatchRule>();
static {
ArrangementModifier[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE};
for (ArrangementModifier modifier : visibility) {
and(FIELD, STATIC, FINAL, modifier);
}
for (ArrangementModifier modifier : visibility) {
and(FIELD, STATIC, modifier);
}
for (ArrangementModifier modifier : visibility) {
and(FIELD, FINAL, modifier);
}
for (ArrangementModifier modifier : visibility) {
and(FIELD, modifier);
}
and(FIELD);
and(CONSTRUCTOR);
and(METHOD, STATIC);
and(METHOD);
and(ENUM);
and(INTERFACE);
and(CLASS, STATIC);
and(CLASS);
}
private static final StdArrangementSettings DEFAULT_SETTINGS = new StdArrangementSettings(DEFAULT_GROUPING_RULES, DEFAULT_MATCH_RULES);
private static void and(@NotNull Object... conditions) {
if (conditions.length == 1) {
DEFAULT_MATCH_RULES.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(new ArrangementAtomMatchCondition(
ArrangementUtil.parseType(conditions[0]), conditions[0]
))));
return;
}
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition();
for (Object condition : conditions) {
composite.addOperand(new ArrangementAtomMatchCondition(ArrangementUtil.parseType(condition), condition));
}
DEFAULT_MATCH_RULES.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(composite)));
GROUPING_RULES.put(GETTERS_AND_SETTERS, Collections.<ArrangementSettingsToken>emptyList());
GROUPING_RULES.put(OVERRIDDEN_METHODS, ContainerUtilRt.newArrayList(BY_NAME, KEEP));
GROUPING_RULES.put(DEPENDENT_METHODS, ContainerUtilRt.newArrayList(BREADTH_FIRST, DEPTH_FIRST));
}
@NotNull
private static Set<ArrangementModifier> concat(@NotNull Set<ArrangementModifier> base, ArrangementModifier... modifiers) {
EnumSet<ArrangementModifier> result = EnumSet.copyOf(base);
private static Set<ArrangementSettingsToken> concat(@NotNull Set<ArrangementSettingsToken> base, ArrangementSettingsToken... modifiers) {
Set<ArrangementSettingsToken> result = ContainerUtilRt.newHashSet(base);
Collections.addAll(result, modifiers);
return result;
}
@Nullable
@Override
public Pair<JavaElementArrangementEntry, List<JavaElementArrangementEntry>> parseWithNew(
@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull PsiElement element,
@Nullable ArrangementSettings settings)
{
Set<ArrangementGroupingType> groupingRules = getGroupingRules(settings);
JavaArrangementParseInfo existingEntriesInfo = new JavaArrangementParseInfo();
root.accept(new JavaArrangementVisitor(existingEntriesInfo, document, ranges, groupingRules));
JavaArrangementParseInfo newEntryInfo = new JavaArrangementParseInfo();
element.accept(new JavaArrangementVisitor(newEntryInfo, document, Collections.singleton(element.getTextRange()), groupingRules));
if (newEntryInfo.getEntries().size() != 1) {
return null;
}
return Pair.create(newEntryInfo.getEntries().get(0), existingEntriesInfo.getEntries());
}
@NotNull
@Override
public List<JavaElementArrangementEntry> parse(@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@Nullable ArrangementSettings settings)
{
// Following entries are subject to arrangement: class, interface, field, method.
JavaArrangementParseInfo parseInfo = new JavaArrangementParseInfo();
root.accept(new JavaArrangementVisitor(parseInfo, document, ranges, getGroupingRules(settings)));
if (settings != null) {
for (ArrangementGroupingRule rule : settings.getGroupings()) {
switch (rule.getGroupingType()) {
case GETTERS_AND_SETTERS:
setupGettersAndSetters(parseInfo);
break;
case DEPENDENT_METHODS:
setupUtilityMethods(parseInfo, rule.getOrderType());
break;
case OVERRIDDEN_METHODS:
setupOverriddenMethods(parseInfo);
default: // Do nothing
}
}
}
return parseInfo.getEntries();
}
private static void setupGettersAndSetters(@NotNull JavaArrangementParseInfo info) {
Collection<JavaArrangementPropertyInfo> properties = info.getProperties();
for (JavaArrangementPropertyInfo propertyInfo : properties) {
@@ -229,18 +110,19 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
}
private static void setupUtilityMethods(@NotNull JavaArrangementParseInfo info, @NotNull ArrangementEntryOrderType orderType) {
switch (orderType) {
case DEPTH_FIRST:
for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) {
setupDepthFirstDependency(rootInfo);
}
break;
case BREADTH_FIRST:
for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) {
setupBreadthFirstDependency(rootInfo);
}
default: // Unexpected type, do nothing
private static void setupUtilityMethods(@NotNull JavaArrangementParseInfo info, @NotNull ArrangementSettingsToken orderType) {
if (DEPTH_FIRST.equals(orderType)) {
for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) {
setupDepthFirstDependency(rootInfo);
}
}
else if (BREADTH_FIRST.equals(orderType)) {
for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) {
setupBreadthFirstDependency(rootInfo);
}
}
else {
assert false : orderType;
}
}
@@ -280,16 +162,52 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
}
}
@Nullable
@Override
public Pair<JavaElementArrangementEntry, List<JavaElementArrangementEntry>> parseWithNew(
@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull PsiElement element,
@Nullable ArrangementSettings settings)
{
Set<ArrangementSettingsToken> groupingRules = getGroupingRules(settings);
JavaArrangementParseInfo existingEntriesInfo = new JavaArrangementParseInfo();
root.accept(new JavaArrangementVisitor(existingEntriesInfo, document, ranges, groupingRules));
JavaArrangementParseInfo newEntryInfo = new JavaArrangementParseInfo();
element.accept(new JavaArrangementVisitor(newEntryInfo, document, Collections.singleton(element.getTextRange()), groupingRules));
if (newEntryInfo.getEntries().size() != 1) {
return null;
}
return Pair.create(newEntryInfo.getEntries().get(0), existingEntriesInfo.getEntries());
}
@NotNull
private static Set<ArrangementGroupingType> getGroupingRules(@Nullable ArrangementSettings settings) {
Set<ArrangementGroupingType> groupingRules = EnumSet.noneOf(ArrangementGroupingType.class);
@Override
public List<JavaElementArrangementEntry> parse(@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@Nullable ArrangementSettings settings)
{
// Following entries are subject to arrangement: class, interface, field, method.
JavaArrangementParseInfo parseInfo = new JavaArrangementParseInfo();
root.accept(new JavaArrangementVisitor(parseInfo, document, ranges, getGroupingRules(settings)));
if (settings != null) {
for (ArrangementGroupingRule rule : settings.getGroupings()) {
groupingRules.add(rule.getGroupingType());
if (GETTERS_AND_SETTERS.equals(rule.getGroupingType())) {
setupGettersAndSetters(parseInfo);
}
else if (DEPENDENT_METHODS.equals(rule.getGroupingType())) {
setupUtilityMethods(parseInfo, rule.getOrderType());
}
else if (OVERRIDDEN_METHODS.equals(rule.getGroupingType())) {
setupOverriddenMethods(parseInfo);
}
}
}
return groupingRules;
return parseInfo.getEntries();
}
@Override
@@ -303,112 +221,153 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
switch (target.getType()) {
case FIELD:
if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE;
}
else {
return commonSettings.BLANK_LINES_AROUND_FIELD;
}
case METHOD:
if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE;
}
else {
return commonSettings.BLANK_LINES_AROUND_METHOD;
}
case CLASS: return commonSettings.BLANK_LINES_AROUND_CLASS;
default: return -1;
if (FIELD.equals(target.getType())) {
if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE;
}
else {
return commonSettings.BLANK_LINES_AROUND_FIELD;
}
}
else if (METHOD.equals(target.getType())) {
if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE;
}
else {
return commonSettings.BLANK_LINES_AROUND_METHOD;
}
}
else if (CLASS.equals(target.getType())) {
return commonSettings.BLANK_LINES_AROUND_CLASS;
}
else {
return -1;
}
}
@Override
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current) {
return SUPPORTED_TYPES.contains(type);
}
@Override
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current) {
if (current == null) {
return SUPPORTED_MODIFIERS.contains(modifier);
@NotNull
private static Set<ArrangementSettingsToken> getGroupingRules(@Nullable ArrangementSettings settings) {
Set<ArrangementSettingsToken> groupingRules = ContainerUtilRt.newHashSet();
if (settings != null) {
for (ArrangementGroupingRule rule : settings.getGroupings()) {
groupingRules.add(rule.getGroupingType());
}
}
final Ref<Object> typeRef = new Ref<Object>();
current.invite(new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
if (setting.getType() == ArrangementSettingType.TYPE) {
typeRef.set(setting.getValue());
}
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
for (ArrangementMatchCondition n : setting.getOperands()) {
if (typeRef.get() != null) {
return;
}
n.invite(this);
}
}
});
Object key = typeRef.get() == null ? NO_TYPE : typeRef.get();
Set<ArrangementModifier> modifiers = MODIFIERS_BY_TYPE.get(key);
return modifiers != null && modifiers.contains(modifier);
return groupingRules;
}
@NotNull
@Override
public Collection<Set<?>> getMutexes() {
public StdArrangementSettings getDefaultSettings() {
List<ArrangementGroupingRule> groupingRules = ContainerUtilRt.newArrayList(new ArrangementGroupingRule(GETTERS_AND_SETTERS));
List<StdArrangementMatchRule> matchRules = ContainerUtilRt.newArrayList();
ArrangementSettingsToken[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE};
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, STATIC, FINAL, modifier);
}
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, STATIC, modifier);
}
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, FINAL, modifier);
}
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, modifier);
}
and(matchRules, FIELD);
and(matchRules, CONSTRUCTOR);
and(matchRules, METHOD, STATIC);
and(matchRules, METHOD);
and(matchRules, ENUM);
and(matchRules, INTERFACE);
and(matchRules, CLASS, STATIC);
and(matchRules, CLASS);
return new StdArrangementSettings(groupingRules, matchRules);
}
@Nullable
@Override
public List<CompositeArrangementSettingsToken> getSupportedGroupingTokens() {
return ContainerUtilRt.newArrayList(
new CompositeArrangementSettingsToken(GETTERS_AND_SETTERS),
new CompositeArrangementSettingsToken(OVERRIDDEN_METHODS, BY_NAME, KEEP),
new CompositeArrangementSettingsToken(DEPENDENT_METHODS, BREADTH_FIRST, DEPTH_FIRST)
);
}
@Nullable
@Override
public List<CompositeArrangementSettingsToken> getSupportedMatchingTokens() {
return ContainerUtilRt.newArrayList(
new CompositeArrangementSettingsToken(TYPE, SUPPORTED_TYPES),
new CompositeArrangementSettingsToken(MODIFIER, SUPPORTED_MODIFIERS),
new CompositeArrangementSettingsToken(NAME),
new CompositeArrangementSettingsToken(ORDER, KEEP, BY_NAME)
);
}
@Override
public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) {
if (SUPPORTED_TYPES.contains(token) || SUPPORTED_ORDERS.contains(token) || NAME.equals(token)) {
return true;
}
ArrangementSettingsToken type = null;
if (current != null) {
type = ArrangementUtil.parseType(current);
}
if (type == null) {
type = NO_TYPE;
}
Set<ArrangementSettingsToken> modifiers = MODIFIERS_BY_TYPE.get(type);
return modifiers != null && modifiers.contains(token);
}
@NotNull
@Override
public ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
throw new IllegalArgumentException("Can't build a matcher for condition " + condition);
}
@NotNull
@Override
public Collection<Set<ArrangementSettingsToken>> getMutexes() {
return MUTEXES;
}
@NotNull
@Override
public List<Set<ArrangementMatchCondition>> getGroupingConditions() {
return Collections.emptyList();
//return UI_GROUPING_RULES;
}
@Nullable
@Override
public StdArrangementSettings getDefaultSettings() {
return DEFAULT_SETTINGS;
}
private static void and(@NotNull List<StdArrangementMatchRule> matchRules, @NotNull ArrangementSettingsToken... conditions) {
if (conditions.length == 1) {
matchRules.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(new ArrangementAtomMatchCondition(
conditions[0], conditions[0]
))));
return;
}
@Override
public boolean isNameFilterSupported() {
return true;
}
@Override
public boolean isEnabled(@NotNull ArrangementGroupingType groupingType, @Nullable ArrangementEntryOrderType orderType) {
Set<ArrangementEntryOrderType> orderTypes = GROUPING_RULES.get(groupingType);
if (orderTypes == null) {
return false;
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition();
for (ArrangementSettingsToken condition : conditions) {
composite.addOperand(new ArrangementAtomMatchCondition(condition, condition));
}
matchRules.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(composite)));
}
return orderType == null || orderTypes.contains(orderType);
}
@Nullable
@Override
public TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingType type, boolean selected) {
public TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingsToken token, boolean selected) {
if (selected) {
TextAttributes attributes = new TextAttributes();
attributes.setForegroundColor(scheme.getColor(EditorColors.SELECTION_FOREGROUND_COLOR));
attributes.setBackgroundColor(scheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR));
return attributes;
}
if (type == ArrangementSettingType.MODIFIER) {
else if (SUPPORTED_TYPES.contains(token)) {
return getAttributes(scheme, JavaHighlightingColors.KEYWORD);
}
else if (type == ArrangementSettingType.TYPE) {
return getAttributes(scheme, CodeInsightColors.CLASS_NAME_ATTRIBUTES, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES);
else if (SUPPORTED_MODIFIERS.contains(token)) {
getAttributes(scheme, JavaHighlightingColors.KEYWORD);
}
return null;
}
@Nullable
private static TextAttributes getAttributes(@NotNull EditorColorsScheme scheme, @NotNull TextAttributesKey ... keys) {
TextAttributes result = null;
@@ -15,8 +15,9 @@
*/
package com.intellij.psi.codeStyle.arrangement
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.*
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*
/**
* @author Denis Zhdanov
* @since 8/30/12 12:14 PM
@@ -15,13 +15,11 @@
*/
package com.intellij.psi.codeStyle.arrangement
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType
import org.junit.Before
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PROTECTED
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PUBLIC
import static com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType.BY_NAME
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PROTECTED
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PUBLIC
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME
/**
* @author Denis Zhdanov
@@ -50,7 +48,7 @@ class Test {
public void setI() {}
public void test() {}
}''',
rules: [rule("get.*")]
rules: [nameRule("get.*")]
)
}
@@ -68,7 +66,7 @@ class Test {
protected void test() {}
private void getInner() {}
}''',
rules: [rule("get.*", PUBLIC), rule(PROTECTED)]
rules: [nameRule("get.*", PUBLIC), rule(PROTECTED)]
)
}
@@ -88,7 +86,7 @@ class Test {
private void getC() {}
public void test() {}
}''',
rules: [rule(BY_NAME, "get.*")]
rules: [ruleWithOrder(BY_NAME, nameRule("get.*"))]
)
}
}
@@ -15,15 +15,16 @@
*/
package com.intellij.psi.codeStyle.arrangement
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.*
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*
/**
* @author Denis Zhdanov
* @since 8/28/12 6:42 PM
*/
class JavaRearrangerByTypeAndModifierTest extends AbstractJavaRearrangerTest {
void testComplex() {
void "test complex sample"() {
commonSettings.BLANK_LINES_AROUND_METHOD = 0
commonSettings.BLANK_LINES_AROUND_CLASS = 0
@@ -34,7 +35,7 @@ class Test {
protected static class ProtectedStaticInner {}
public class PublicInner {}
private interface PrivateInterface {}
public abstract abstractMethod();
public abstract void abstractMethod();
private void privateMethod() {}
public void publicMethod() {}
private int privateField;
@@ -48,7 +49,7 @@ class Test {
public int publicField;
private volatile int privateVolatileField;
private int privateField;
public abstract abstractMethod();
public abstract void abstractMethod();
public void publicMethod() {}
private void privateMethod() {}
private interface PrivateInterface {}
@@ -70,7 +71,7 @@ class Test {
)
}
void testInstanceInitializationBlockBoundToField() {
void "test instance initialization block bound to a field"() {
doTest(
initial: '''\
class Test {
@@ -89,7 +90,7 @@ class Test {
rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)])
}
void testInstanceInitializationBlockAsFirstChild() {
void "test instance initialization block as the first child"() {
doTest(
initial: '''\
class Test {
@@ -15,13 +15,12 @@
*/
package com.intellij.psi.codeStyle.arrangement
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType
import org.junit.Before
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.*
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PRIVATE
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PROTECTED
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PUBLIC
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.*
/**
* @author Denis Zhdanov
* @since 7/20/12 2:45 PM
@@ -35,7 +34,7 @@ class JavaRearrangerByTypeTest extends AbstractJavaRearrangerTest {
commonSettings.BLANK_LINES_AROUND_CLASS = 0
}
void testFieldsBeforeMethods() {
void "test fields before methods"() {
doTest(
initial: '''\
class Test {
@@ -48,6 +47,7 @@ public void test() {
private int i;
private int j;
}''',
rules: [rule(FIELD)],
expected: '''\
class Test {
private int i;
@@ -58,12 +58,11 @@ class Test2 {
private int j;
public void test() {
}
}''',
rules: [rule(FIELD)]
}'''
)
}
void testAnonymousClassAtFieldInitializer() {
void "test anonymous class at field initializer"() {
doTest(
initial: '''\
class Test {
@@ -107,7 +106,7 @@ class Test {
)
}
void testAnonymousClassAtMethod() {
void "test anonymous class at method"() {
doTest(
initial: '''\
class Test {
@@ -145,7 +144,7 @@ class Test {
)
}
void testInnerClassInterfaceAndEnum() {
void "test inner class interface and enum"() {
doTest(
initial: '''\
class Test {
@@ -165,7 +164,7 @@ class Test {
)
}
void testRanges() {
void "test ranges"() {
doTest(
initial: '''\
class Test {
@@ -203,7 +202,7 @@ class Test {
)
}
void testMethodsAndConstructors() {
void "test methods and constructors"() {
doTest(
initial: '''\
class Test {
@@ -220,24 +219,7 @@ class Test {
rules: [rule(CONSTRUCTOR), rule(METHOD)])
}
void testConstructorAsMethod() {
doTest(
initial: '''\
class Test {
private int i;
Test() {}
public int j;
}''',
expected: '''\
class Test {
public int j;
Test() {}
private int i;
}''',
rules: [rule(FIELD, PUBLIC), rule(METHOD), rule(FIELD)])
}
void testMultipleFieldsInOneRow() {
void "test multiple fields in one row"() {
doTest(
initial: '''\
class Test {
@@ -326,7 +308,7 @@ class Test {
int c; // comment
int a;
}''',
rules: [rule(ArrangementEntryOrderType.BY_NAME, FIELD)],
rules: [ruleWithOrder(BY_NAME, rule(FIELD))],
expected: '''\
class Test {
int a;
@@ -17,12 +17,10 @@ package com.intellij.psi.codeStyle.arrangement
import org.junit.Test
import static com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType.GETTERS_AND_SETTERS
import static com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType.OVERRIDDEN_METHODS
import static com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType.DEPENDENT_METHODS
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PUBLIC
import static com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType.BREADTH_FIRST
import static com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType.DEPTH_FIRST
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.*
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PUBLIC
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BREADTH_FIRST
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.DEPTH_FIRST
/**
* @author Denis Zhdanov
@@ -35,7 +33,7 @@ class JavaRearrangerGrouperTest extends AbstractJavaRearrangerTest {
commonSettings.BLANK_LINES_AROUND_METHOD = 0
}
void testGettersAndSetters() {
void "test getters and setters"() {
commonSettings.BLANK_LINES_AROUND_METHOD = 1
doTest(
@@ -59,7 +57,7 @@ class Test {
}
@Test
void testUtilityMethodsDepthFirst() {
void "test utility methods depth-first"() {
doTest(
initial: '''\
class Test {
@@ -81,7 +79,7 @@ class Test {
}
@Test
void testUtilityMethodsBreadthFirst() {
void "test utility methods breadth-first"() {
doTest(
initial: '''\
class Test {
@@ -100,7 +98,7 @@ class Test {
}''')
}
void testOverriddenMethods() {
void "test overridden methods"() {
doTest(
initial: '''\
class Base {
@@ -128,7 +126,7 @@ class Sub extends Base {
void test2() {}
}''')
}
void testOverriddenAndUtilityMethods() {
void "test overriden and utility methods"() {
doTest(
initial: '''\
class Base {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -15,9 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.application.options.codeStyle.arrangement.group.ArrangementGroupingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.openapi.actionSystem.DataKey;
import org.jetbrains.annotations.NonNls;
/**
@@ -26,11 +23,6 @@ import org.jetbrains.annotations.NonNls;
*/
public class ArrangementConstants {
public static final DataKey<ArrangementGroupingRulesControl> GROUPING_RULES_CONTROL_KEY =
DataKey.create("Arrangement.Rule.Group.Control");
public static final DataKey<ArrangementMatchingRulesControl> MATCHING_RULES_CONTROL_KEY =
DataKey.create("Arrangement.Rule.Match.Control");
@NonNls public static final String ACTION_GROUP_GROUPING_RULES_CONTROL_TOOLBAR = "Arrangement.Rule.Group.Control.ToolBar";
@NonNls public static final String GROUPING_RULES_CONTROL_TOOLBAR_PLACE = "Arrangement.Rule.Group.Control.ToolBar.Place";
@@ -39,19 +31,19 @@ public class ArrangementConstants {
@NonNls public static final String MATCHING_RULES_CONTROL_TOOLBAR_PLACE = "Arrangement.Rule.Match.Control.ToolBar.Place";
@NonNls public static final String MATCHING_RULES_CONTROL_PLACE = "Arrangement.Rule.Match.Control.Place";
public static final int HORIZONTAL_PADDING = 8;
public static final int VERTICAL_PADDING = 4;
public static final int HORIZONTAL_GAP = 5;
public static final int VERTICAL_GAP = 3;
public static final int HORIZONTAL_PADDING = 8;
public static final int VERTICAL_PADDING = 4;
public static final int HORIZONTAL_GAP = 5;
public static final int VERTICAL_GAP = 3;
public static final int CALLOUT_BORDER_HEIGHT = 10;
public static final int BORDER_ARC_SIZE = 12;
public static final int ANIMATION_ITERATION_PIXEL_STEP = 5;
public static final int ANIMATION_STEPS_TIME_GAP_MILLIS = 40;
public static final int NAME_CONDITION_UPDATE_DELAY_MILLIS = 1000;
public static final int ANIMATION_ITERATION_PIXEL_STEP = 5;
public static final int ANIMATION_STEPS_TIME_GAP_MILLIS = 40;
public static final int TEXT_UPDATE_DELAY_MILLIS = 1000;
public static final boolean LOG_RULE_MODIFICATION = Boolean.parseBoolean(System.getProperty("log.arrangement.rule.modification"));
private ArrangementConstants() {
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -16,7 +16,7 @@
package com.intellij.application.options.codeStyle.arrangement.color;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
@@ -31,5 +31,5 @@ public interface ArrangementColorsProvider {
Color getBorderColor(boolean selected);
@NotNull
TextAttributes getTextAttributes(@NotNull ArrangementSettingType type, boolean selected);
TextAttributes getTextAttributes(@NotNull ArrangementSettingsToken token, boolean selected);
}
@@ -1,133 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
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.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 10/31/12 12:30 PM
*/
public class ArrangementRuleInfo {
@NotNull private final Set<ArrangementAtomMatchCondition> myAtomConditions = ContainerUtilRt.newHashSet();
@NotNull private final Set<Object> myConditions = ContainerUtilRt.newHashSet();
@NotNull private ArrangementEntryOrderType myOrderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
@Nullable private String myNamePattern;
@Nullable
public String getNamePattern() {
return myNamePattern;
}
public void setNamePattern(@Nullable String namePattern) {
myNamePattern = namePattern;
}
@NotNull
public ArrangementEntryOrderType getOrderType() {
return myOrderType;
}
public void setOrderType(@NotNull ArrangementEntryOrderType orderType) {
myOrderType = orderType;
}
public void addAtomCondition(@NotNull ArrangementAtomMatchCondition condition) {
switch (condition.getType()) {
case NAME: myNamePattern = condition.getValue().toString(); break;
default:
myAtomConditions.add(condition);
myConditions.add(condition.getValue());
}
}
public boolean hasCondition(@NotNull Object condition) {
return myConditions.contains(condition);
}
public void removeCondition(@NotNull Object condition) {
if (!myConditions.remove(condition)) {
return;
}
for (Iterator<ArrangementAtomMatchCondition> iterator = myAtomConditions.iterator(); iterator.hasNext(); ) {
ArrangementAtomMatchCondition c = iterator.next();
if (c.getValue().equals(condition)) {
iterator.remove();
break;
}
}
}
public void copyConditionsFrom(@NotNull ArrangementRuleInfo info) {
clearConditions();
myConditions.addAll(info.myConditions);
myAtomConditions.addAll(info.myAtomConditions);
myNamePattern = info.myNamePattern;
}
public void clear() {
clearConditions();
myOrderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
myNamePattern = null;
}
public void clearConditions() {
myConditions.clear();
myAtomConditions.clear();
}
@Nullable
public StdArrangementMatchRule buildRule() {
ArrangementMatchCondition condition = buildCondition();
if (condition == null) {
return null;
}
return new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), myOrderType);
}
@Nullable
public ArrangementMatchCondition buildCondition() {
if (myAtomConditions.isEmpty()) {
return myNamePattern == null ? null : new ArrangementAtomMatchCondition(ArrangementSettingType.NAME, myNamePattern);
}
else if (myAtomConditions.size() == 1 && myNamePattern == null) {
return myAtomConditions.iterator().next();
}
else {
ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(myAtomConditions);
if (myNamePattern != null) {
result.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.NAME, myNamePattern));
}
return result;
}
}
}
@@ -51,5 +51,5 @@ public interface ArrangementSettingsSerializer {
* @param settings settings to serialize
* @param holder element to hold serialized settings
*/
void serialize(ArrangementSettings settings, @NotNull Element holder);
void serialize(@NotNull ArrangementSettings settings, @NotNull Element holder);
}
@@ -15,18 +15,27 @@
*/
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.match.*;
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.ContainerUtilRt;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
/**
* @author Denis Zhdanov
@@ -135,22 +144,29 @@ public class ArrangementUtil {
}
//endregion
@NotNull
public static ArrangementSettingType parseType(@NotNull Object condition) throws IllegalArgumentException {
if (condition instanceof ArrangementEntryType) {
return ArrangementSettingType.TYPE;
}
else if (condition instanceof ArrangementModifier) {
return ArrangementSettingType.MODIFIER;
}
else if (condition instanceof String) {
return ArrangementSettingType.NAME;
}
else {
throw new IllegalArgumentException(String.format(
"Can't parse type for the given condition of class '%s': %s", condition.getClass(), condition
));
}
@Nullable
public static ArrangementSettingsToken parseType(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
final Ref<ArrangementSettingsToken> result = new Ref<ArrangementSettingsToken>();
condition.invite(new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
if (StdArrangementTokens.EntryType.is(condition.getType())) {
result.set(condition.getType());
}
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
for (ArrangementMatchCondition c : condition.getOperands()) {
c.invite(this);
if (result.get() != null) {
return;
}
}
}
});
return result.get();
}
public static <T> Set<T> flatten(@NotNull Iterable<? extends Iterable<T>> data) {
@@ -164,12 +180,12 @@ public class ArrangementUtil {
}
@NotNull
public static ArrangementRuleInfo extractConditions(@NotNull ArrangementMatchCondition condition) {
final ArrangementRuleInfo result = new ArrangementRuleInfo();
public static Set<ArrangementSettingsToken> extractTokens(@NotNull ArrangementMatchCondition condition) {
final Set<ArrangementSettingsToken> result = ContainerUtilRt.newHashSet();
condition.invite(new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
result.addAtomCondition(condition);
result.add(condition.getType());
}
@Override
@@ -181,4 +197,88 @@ public class ArrangementUtil {
});
return result;
}
@Nullable
public static ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) {
final Ref<ArrangementEntryMatcher> result = new Ref<ArrangementEntryMatcher>();
final Stack<CompositeArrangementEntryMatcher> composites = new Stack<CompositeArrangementEntryMatcher>();
ArrangementMatchConditionVisitor visitor = new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
ArrangementEntryMatcher matcher = buildMatcher(condition);
if (matcher == null) {
return;
}
if (composites.isEmpty()) {
result.set(matcher);
}
else {
composites.peek().addMatcher(matcher);
}
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
composites.push(new CompositeArrangementEntryMatcher());
try {
for (ArrangementMatchCondition operand : condition.getOperands()) {
operand.invite(this);
}
}
finally {
CompositeArrangementEntryMatcher matcher = composites.pop();
if (composites.isEmpty()) {
result.set(matcher);
}
}
}
};
condition.invite(visitor);
return result.get();
}
@Nullable
public static ArrangementEntryMatcher buildMatcher(@NotNull ArrangementAtomMatchCondition condition) {
if (StdArrangementTokens.EntryType.is(condition.getType())) {
return new ByTypeArrangementEntryMatcher(condition.getType());
}
else if (StdArrangementTokens.Modifier.is(condition.getType())) {
return new ByModifierArrangementEntryMatcher(condition.getType());
}
else if (StdArrangementTokens.General.NAME.equals(condition.getType())) {
return new ByNameArrangementEntryMatcher(condition.getValue().toString());
}
else {
return null;
}
}
// TODO den add doc
@NotNull
public static ArrangementUiComponent buildUiComponent(@NotNull StdArrangementTokenUiRole role,
@NotNull List<ArrangementSettingsToken> tokens,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsManager settingsManager)
throws IllegalArgumentException
{
for (ArrangementUiComponent.Factory factory : Extensions.getExtensions(ArrangementUiComponent.Factory.EP_NAME)) {
ArrangementUiComponent result = factory.build(role, tokens, colorsProvider, settingsManager);
if (result != null) {
return result;
}
}
throw new IllegalArgumentException("Unsupported UI token role " + role);
}
@NotNull
public static List<CompositeArrangementSettingsToken> flatten(@NotNull CompositeArrangementSettingsToken base) {
List<CompositeArrangementSettingsToken> result = ContainerUtilRt.newArrayList();
Queue<CompositeArrangementSettingsToken> toProcess = ContainerUtilRt.newLinkedList(base);
while (!toProcess.isEmpty()) {
CompositeArrangementSettingsToken token = toProcess.remove();
result.add(token);
toProcess.addAll(token.getChildren());
}
return result;
}
}
@@ -17,12 +17,13 @@ package com.intellij.psi.codeStyle.arrangement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.DefaultArrangementEntryMatcherSerializer;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -31,14 +32,17 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* {@link ArrangementSettingsSerializer} which knows how to handle {@link StdArrangementSettings built-in arrangement tokens}
* and {@link Mixin can be used as a base for custom serializer implementation}.
*
* @author Denis Zhdanov
* @since 7/18/12 10:37 AM
*/
public class DefaultArrangementSettingsSerializer implements ArrangementSettingsSerializer {
public static final ArrangementSettingsSerializer INSTANCE = new DefaultArrangementSettingsSerializer();
private static final Logger LOG =
Logger.getInstance("#" + DefaultArrangementSettingsSerializer.class.getName());
public static final ArrangementSettingsSerializer INSTANCE = new DefaultArrangementSettingsSerializer(Mixin.NULL);
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementSettingsSerializer.class.getName());
@NotNull @NonNls private static final String GROUPS_ELEMENT_NAME = "groups";
@NotNull @NonNls private static final String GROUP_ELEMENT_NAME = "group";
@@ -48,10 +52,16 @@ public class DefaultArrangementSettingsSerializer implements ArrangementSettings
@NotNull @NonNls private static final String MATCHER_ELEMENT_NAME = "match";
@NotNull @NonNls private static final String ORDER_TYPE_ELEMENT_NAME = "order";
@NotNull private final DefaultArrangementEntryMatcherSerializer myMatcherSerializer = new DefaultArrangementEntryMatcherSerializer();
@NotNull private final DefaultArrangementEntryMatcherSerializer myMatcherSerializer;
@NotNull private final Mixin myMixin;
public DefaultArrangementSettingsSerializer(@NotNull Mixin mixin) {
myMixin = mixin;
myMatcherSerializer = new DefaultArrangementEntryMatcherSerializer(mixin);
}
@Override
public void serialize(ArrangementSettings s, @NotNull Element holder) {
public void serialize(@NotNull ArrangementSettings s, @NotNull Element holder) {
if (!(s instanceof StdArrangementSettings)) {
return;
}
@@ -65,8 +75,8 @@ public class DefaultArrangementSettingsSerializer implements ArrangementSettings
for (ArrangementGroupingRule group : groupings) {
Element groupElement = new Element(GROUP_ELEMENT_NAME);
groupingsElement.addContent(groupElement);
groupElement.addContent(new Element(TYPE_ELEMENT_NAME).setText(group.getGroupingType().toString()));
groupElement.addContent(new Element(ORDER_TYPE_ELEMENT_NAME).setText(group.getOrderType().toString()));
groupElement.addContent(new Element(TYPE_ELEMENT_NAME).setText(group.getGroupingType().getId()));
groupElement.addContent(new Element(ORDER_TYPE_ELEMENT_NAME).setText(group.getOrderType().getId()));
}
}
@@ -88,15 +98,29 @@ public class DefaultArrangementSettingsSerializer implements ArrangementSettings
if (groups != null) {
for (Object group : groups.getChildren(GROUP_ELEMENT_NAME)) {
Element groupElement = (Element)group;
try {
ArrangementGroupingType type = ArrangementGroupingType.valueOf(groupElement.getChildText(TYPE_ELEMENT_NAME));
ArrangementEntryOrderType orderType = ArrangementEntryOrderType.valueOf(groupElement.getChildText(ORDER_TYPE_ELEMENT_NAME));
ArrangementGroupingRule groupingRule = new ArrangementGroupingRule(type, orderType);
result.addGrouping(groupingRule);
// Grouping type.
String groupingTypeId = groupElement.getChildText(TYPE_ELEMENT_NAME);
ArrangementSettingsToken groupingType = StdArrangementTokens.byId(groupingTypeId);
if (groupingType == null) {
groupingType = myMixin.deserializeToken(groupingTypeId);
}
catch (Exception e) {
LOG.warn(String.format("Can't deserialize grouping rule '%s'", groupElement.getText()), e);
if (groupingType == null) {
LOG.warn(String.format("Can't deserialize grouping type token by id '%s'", groupingTypeId));
continue;
}
// Order type.
String orderTypeId = groupElement.getChildText(ORDER_TYPE_ELEMENT_NAME);
ArrangementSettingsToken orderType = StdArrangementTokens.byId(orderTypeId);
if (orderType == null) {
orderType = myMixin.deserializeToken(orderTypeId);
}
if (orderType == null) {
LOG.warn(String.format("Can't deserialize grouping order type token by id '%s'", orderTypeId));
continue;
}
result.addGrouping(new ArrangementGroupingRule(groupingType, orderType));
}
}
@@ -122,15 +146,21 @@ public class DefaultArrangementSettingsSerializer implements ArrangementSettings
}
Element orderTypeElement = ruleElement.getChild(ORDER_TYPE_ELEMENT_NAME);
ArrangementEntryOrderType orderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
ArrangementSettingsToken orderType = null;
if (orderTypeElement != null) {
try {
orderType = ArrangementEntryOrderType.valueOf(orderTypeElement.getText());
String orderTypeId = orderTypeElement.getText();
orderType = StdArrangementTokens.byId(orderTypeId);
if (orderType == null) {
orderType = myMixin.deserializeToken(orderTypeId);
}
catch (Exception e) {
LOG.warn(String.format("Can't deserialize matching rule order type for '%s'", ruleElement.getText()), e);
if (orderType == null) {
LOG.warn(String.format("Can't deserialize matching rule order type for id '%s'. Falling back to default (%s)",
orderTypeId, ArrangementMatchRule.DEFAULT_ORDER_TYPE.getId()));
}
}
if (orderType == null) {
orderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
}
result.addRule(new StdArrangementMatchRule(matcher, orderType));
}
}
@@ -148,8 +178,20 @@ public class DefaultArrangementSettingsSerializer implements ArrangementSettings
Element result = new Element(RULE_ELEMENT_NAME);
result.addContent(new Element(MATCHER_ELEMENT_NAME).addContent(matcherElement));
if (rule.getOrderType() != ArrangementMatchRule.DEFAULT_ORDER_TYPE) {
result.addContent(new Element(ORDER_TYPE_ELEMENT_NAME).setText(rule.getOrderType().toString()));
result.addContent(new Element(ORDER_TYPE_ELEMENT_NAME).setText(rule.getOrderType().getId()));
}
return result;
}
public interface Mixin {
Mixin NULL = new Mixin() {
@Nullable
@Override
public ArrangementSettingsToken deserializeToken(@NotNull String id) { return null; }
};
@Nullable
ArrangementSettingsToken deserializeToken(@NotNull String id);
}
}
@@ -15,8 +15,7 @@
*/
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
@@ -28,5 +27,5 @@ import java.util.Set;
public interface ModifierAwareArrangementEntry extends ArrangementEntry {
@NotNull
Set<ArrangementModifier> getModifiers();
Set<ArrangementSettingsToken> getModifiers();
}
@@ -21,7 +21,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +49,7 @@ public interface Rearranger<E extends ArrangementEntry> {
*
* @param element element to wrap into format eligible for further processing by arrangement engine
* @param settings arrangement settings to use. The primary idea is to make the rearranger aware about
* {@link ArrangementGroupingType grouping rules} (if any). E.g. it's not worth to process java method bodies
* {@link StdArrangementTokens.Grouping grouping rules} (if any). E.g. it's not worth to process java method bodies
* in order to build method dependency graph if no such grouping rule is defined
* @return arrangement entry for the given element if it's possible to perform the mapping and list of arrangement entries
* available at the given context plus newly created entry for the given element;
@@ -69,7 +69,7 @@ public interface Rearranger<E extends ArrangementEntry> {
* @param document document which corresponds to the target PSI tree
* @param ranges target offsets ranges to use for filtering given root's children
* @param settings arrangement settings to use. The primary idea is to make the rearranger aware about
* {@link ArrangementGroupingType grouping rules} (if any). E.g. it's not worth to process java method bodies
* {@link StdArrangementTokens.Grouping grouping rules} (if any). E.g. it's not worth to process java method bodies
* in order to build method dependency graph if no such grouping rule is defined
* @return given root's children which are subject for further rearrangement
*/
@@ -15,9 +15,8 @@
*/
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@@ -32,5 +31,5 @@ import java.util.Set;
public interface TypeAwareArrangementEntry extends ArrangementEntry {
@NotNull
Set<ArrangementEntryType> getTypes();
Set<ArrangementSettingsToken> getTypes();
}
@@ -15,7 +15,8 @@
*/
package com.intellij.psi.codeStyle.arrangement.group;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import org.jetbrains.annotations.NotNull;
/**
@@ -28,25 +29,25 @@ import org.jetbrains.annotations.NotNull;
*/
public class ArrangementGroupingRule {
@NotNull private final ArrangementGroupingType myGroupingType;
@NotNull private final ArrangementEntryOrderType myOrderType;
@NotNull private final ArrangementSettingsToken myGroupingType;
@NotNull private final ArrangementSettingsToken myOrderType;
public ArrangementGroupingRule(@NotNull ArrangementGroupingType groupingType) {
this(groupingType, ArrangementEntryOrderType.KEEP);
public ArrangementGroupingRule(@NotNull ArrangementSettingsToken groupingType) {
this(groupingType, StdArrangementTokens.Order.KEEP);
}
public ArrangementGroupingRule(@NotNull ArrangementGroupingType groupingType, @NotNull ArrangementEntryOrderType orderType) {
public ArrangementGroupingRule(@NotNull ArrangementSettingsToken groupingType, @NotNull ArrangementSettingsToken orderType) {
myGroupingType = groupingType;
myOrderType = orderType;
}
@NotNull
public ArrangementGroupingType getGroupingType() {
public ArrangementSettingsToken getGroupingType() {
return myGroupingType;
}
@NotNull
public ArrangementEntryOrderType getOrderType() {
public ArrangementSettingsToken getOrderType() {
return myOrderType;
}
@@ -1,33 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.group;
/**
* Enumerates available grouping types.
*
* @author Denis Zhdanov
* @since 9/17/12 11:47 AM
*/
public enum ArrangementGroupingType {
GETTERS_AND_SETTERS,
OVERRIDDEN_METHODS,
DEPENDENT_METHODS,
GROUP_PROPERTY_FIELD_WITH_GETTER_SETTER
}
@@ -1,37 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
/**
* Enumerates all possible {@link ArrangementEntry entry} types.
* <p/>
* This enum is expected to be populated every time new entry type is introduced.
*
* @author Denis Zhdanov
* @since 7/17/12 11:14 AM
*/
public enum ArrangementEntryType {
CLASS, ANONYMOUS_CLASS, FIELD, CONSTRUCTOR, METHOD, ENUM, INTERFACE,
CONST, VAR, PROPERTY, EVENT_HANDLER, STATIC_INIT,
NAMESPACE, TRAIT,
XML_TAG, XML_ATTRIBUTE
}
@@ -15,7 +15,8 @@
*/
package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import org.jetbrains.annotations.NotNull;
/**
@@ -30,18 +31,18 @@ import org.jetbrains.annotations.NotNull;
*/
public class ArrangementMatchRule {
@NotNull public static final ArrangementEntryOrderType DEFAULT_ORDER_TYPE = ArrangementEntryOrderType.KEEP;
@NotNull public static final ArrangementSettingsToken DEFAULT_ORDER_TYPE = StdArrangementTokens.Order.KEEP;
@NotNull private final ArrangementEntryMatcher myMatcher;
@NotNull private final ArrangementEntryOrderType myOrderType;
@NotNull private final ArrangementEntryMatcher myMatcher;
@NotNull private final ArrangementSettingsToken myOrderType;
public ArrangementMatchRule(@NotNull ArrangementEntryMatcher matcher) {
this(matcher, DEFAULT_ORDER_TYPE);
}
public ArrangementMatchRule(@NotNull ArrangementEntryMatcher matcher, @NotNull ArrangementEntryOrderType type) {
public ArrangementMatchRule(@NotNull ArrangementEntryMatcher matcher, @NotNull ArrangementSettingsToken orderType) {
myMatcher = matcher;
myOrderType = type;
myOrderType = orderType;
}
@NotNull
@@ -50,7 +51,7 @@ public class ArrangementMatchRule {
}
@NotNull
public ArrangementEntryOrderType getOrderType() {
public ArrangementSettingsToken getOrderType() {
return myOrderType;
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.match;
/**
* @author Denis Zhdanov
* @since 7/17/12 8:54 PM
*/
public enum ArrangementModifier {
//region Visibility
PUBLIC, PROTECTED, PRIVATE, PACKAGE_PRIVATE,
//endregion
STATIC, FINAL, TRANSIENT, VOLATILE, SYNCHRONIZED, ABSTRACT,
OVERRIDE // e.g. ActionScript keyword
}
@@ -17,10 +17,11 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.ModifierAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;
/**
@@ -29,12 +30,16 @@ import java.util.Set;
*/
public class ByModifierArrangementEntryMatcher implements ArrangementEntryMatcher {
@NotNull private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
@NotNull private final Set<ArrangementSettingsToken> myModifiers = ContainerUtilRt.newHashSet();
public ByModifierArrangementEntryMatcher(@NotNull Collection<ArrangementModifier> interestedModifiers) {
myModifiers.addAll(interestedModifiers);
public ByModifierArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedModifier) {
myModifiers.add(interestedModifier);
}
public ByModifierArrangementEntryMatcher(@NotNull Collection<ArrangementSettingsToken> interestedModifiers) {
myModifiers.addAll(interestedModifiers);
}
@Override
public boolean isMatched(@NotNull ArrangementEntry entry) {
if (entry instanceof ModifierAwareArrangementEntry) {
@@ -17,15 +17,15 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;
/**
* Filters {@link ArrangementEntry entries} by {@link TypeAwareArrangementEntry#getType() their types}.
* Filters {@link ArrangementEntry entries} by {@link TypeAwareArrangementEntry#getTypes() their types}.
* <p/>
* <b>Note:</b> type-unaware entry will not be matched by the current rule.
* <p/>
@@ -36,13 +36,13 @@ import java.util.Set;
*/
public class ByTypeArrangementEntryMatcher implements ArrangementEntryMatcher {
@NotNull private final Set<ArrangementEntryType> myTypes = EnumSet.noneOf(ArrangementEntryType.class);
@NotNull private final Set<ArrangementSettingsToken> myTypes = ContainerUtilRt.newHashSet();
public ByTypeArrangementEntryMatcher(@NotNull ArrangementEntryType... interestedTypes) {
this(Arrays.asList(interestedTypes));
public ByTypeArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedType) {
myTypes.add(interestedType);
}
public ByTypeArrangementEntryMatcher(@NotNull Collection<ArrangementEntryType> interestedTypes) {
public ByTypeArrangementEntryMatcher(@NotNull Collection<ArrangementSettingsToken> interestedTypes) {
myTypes.addAll(interestedTypes);
}
@@ -55,7 +55,7 @@ public class ByTypeArrangementEntryMatcher implements ArrangementEntryMatcher {
}
@NotNull
public Set<ArrangementEntryType> getTypes() {
public Set<ArrangementSettingsToken> getTypes() {
return myTypes;
}
@@ -17,18 +17,21 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.DefaultArrangementSettingsSerializer;
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.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import gnu.trove.TObjectIntHashMap;
import com.intellij.util.containers.ContainerUtilRt;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* @author Denis Zhdanov
@@ -38,18 +41,6 @@ public class DefaultArrangementEntryMatcherSerializer {
private static final Comparator<ArrangementMatchCondition> CONDITION_COMPARATOR = new Comparator<ArrangementMatchCondition>() {
private final TObjectIntHashMap<Object> WEIGHTS = new TObjectIntHashMap<Object>();
{
int weight = 0;
for (ArrangementEntryType entryType : ArrangementEntryType.values()) {
WEIGHTS.put(entryType, weight++);
}
for (ArrangementModifier modifier : ArrangementModifier.values()) {
WEIGHTS.put(modifier, weight++);
}
}
@Override
public int compare(ArrangementMatchCondition c1, ArrangementMatchCondition c2) {
boolean isAtom1 = c1 instanceof ArrangementAtomMatchCondition;
@@ -57,30 +48,28 @@ public class DefaultArrangementEntryMatcherSerializer {
if (isAtom1 ^ isAtom2) {
return isAtom1 ? 1 : -1; // Composite conditions before atom conditions.
}
else if (!isAtom1 && !isAtom2) {
else if (!isAtom1) {
return 0;
}
ArrangementAtomMatchCondition atom1 = (ArrangementAtomMatchCondition)c1;
ArrangementAtomMatchCondition atom2 = (ArrangementAtomMatchCondition)c2;
if (WEIGHTS.containsKey(atom1.getValue()) && WEIGHTS.containsKey(atom2.getValue())) {
return WEIGHTS.get(atom1.getValue()) - WEIGHTS.get(atom2.getValue());
}
else {
return 0;
int cmp = atom1.getType().compareTo(atom2.getType());
if (cmp == 0) {
cmp = atom1.getValue().toString().compareTo(atom2.getValue().toString());
}
return cmp;
}
};
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName());
@NotNull private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName());
@NotNull private static final String COMPOSITE_CONDITION_NAME = "AND";
private static final Set<String> ATOM_SETTINGS_TYPES = new HashSet<String>();
static {
for (ArrangementSettingType type : ArrangementSettingType.values()) {
ATOM_SETTINGS_TYPES.add(type.toString());
}
private final DefaultArrangementSettingsSerializer.Mixin myMixin;
public DefaultArrangementEntryMatcherSerializer(DefaultArrangementSettingsSerializer.Mixin mixin) {
myMixin = mixin;
}
@SuppressWarnings("MethodMayBeStatic")
@@ -111,22 +100,9 @@ public class DefaultArrangementEntryMatcherSerializer {
}
@Nullable
private static ArrangementMatchCondition deserializeCondition(@NotNull Element matcherElement) {
private ArrangementMatchCondition deserializeCondition(@NotNull Element matcherElement) {
String name = matcherElement.getName();
if (!COMPOSITE_CONDITION_NAME.equals(name)) {
if (ATOM_SETTINGS_TYPES.contains(name)) {
return deserializeAtomCondition(matcherElement);
}
else {
LOG.warn(String.format(
"Can't deserialize an arrangement entry matcher from matchElement with name '%s'. Reason: only the following elements"
+ "are supported: %s and %s",
name, COMPOSITE_CONDITION_NAME, ATOM_SETTINGS_TYPES
));
return null;
}
}
else {
if (COMPOSITE_CONDITION_NAME.equals(name)) {
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition();
for (Object child : matcherElement.getChildren()) {
ArrangementMatchCondition deserialised = deserializeCondition((Element)child);
@@ -136,24 +112,47 @@ public class DefaultArrangementEntryMatcherSerializer {
}
return composite;
}
else {
return deserializeAtomCondition(matcherElement);
}
}
@Nullable
private static ArrangementMatchCondition deserializeAtomCondition(@NotNull Element matcherElement) {
ArrangementSettingType settingType = ArrangementSettingType.valueOf(matcherElement.getName());
Object value;
switch (settingType) {
case TYPE: value = ArrangementEntryType.valueOf(matcherElement.getText()); break;
case MODIFIER: value = ArrangementModifier.valueOf(matcherElement.getText()); break;
case NAME: value = StringUtil.unescapeStringCharacters(matcherElement.getText()); break;
default:
LOG.warn(String.format(
"Can't deserialize an arrangement entry matcher from element of type '%s' with text '%s'",
settingType, matcherElement.getText()
));
private ArrangementMatchCondition deserializeAtomCondition(@NotNull Element matcherElement) {
String id = matcherElement.getName();
ArrangementSettingsToken token = StdArrangementTokens.byId(id);
boolean processInnerText = true;
if (token != null
&& (StdArrangementTokens.General.TYPE.equals(token) || StdArrangementTokens.General.MODIFIER.equals(token)))
{
// Backward compatibility with old arrangement settings format.
id = matcherElement.getText();
if (StringUtil.isEmpty(id)) {
LOG.warn("Can't deserialize match condition at legacy format");
return null;
}
token = StdArrangementTokens.byId(id);
processInnerText = false;
}
return new ArrangementAtomMatchCondition(settingType, value);
if (token == null) {
token = myMixin.deserializeToken(id);
}
if (token == null) {
LOG.warn(String.format("Can't deserialize match condition with id '%s'", id));
return null;
}
Object value = token;
String text = matcherElement.getText();
if (text != null && processInnerText) {
text = StringUtil.unescapeStringCharacters(matcherElement.getText());
if (!StringUtil.isEmpty(text)) {
value = text;
}
}
return new ArrangementAtomMatchCondition(token, value);
}
private static class MySerializationVisitor implements ArrangementMatchConditionVisitor {
@@ -163,11 +162,10 @@ public class DefaultArrangementEntryMatcherSerializer {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
String content = condition.getValue().toString();
if (condition.getType() == ArrangementSettingType.NAME) {
content = StringUtil.escapeStringCharacters(content);
final Element element = new Element(condition.getType().getId());
if (StdArrangementTokens.General.NAME.equals(condition.getType())) {
element.setText(StringUtil.escapeStringCharacters(condition.getValue().toString()));
}
Element element = new Element(condition.getType().toString()).setText(content);
register(element);
}
@@ -176,7 +174,7 @@ public class DefaultArrangementEntryMatcherSerializer {
Element composite = new Element(COMPOSITE_CONDITION_NAME);
register(composite);
parent = composite;
List<ArrangementMatchCondition> operands = new ArrayList<ArrangementMatchCondition>(condition.getOperands());
List<ArrangementMatchCondition> operands = ContainerUtilRt.newArrayList(condition.getOperands());
ContainerUtil.sort(operands, CONDITION_COMPARATOR);
for (ArrangementMatchCondition c : operands) {
c.invite(this);
@@ -17,17 +17,17 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
/**
* {@link ArrangementEntryMatcher} which is based on standard match conditions like {@link ArrangementEntryType entry type}
* or {@link ArrangementModifier modifier}.
* {@link ArrangementEntryMatcher} which is based on standard match conditions in form of {@link ArrangementSettingsToken}.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
@@ -76,7 +76,7 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
public String toString() {
return myCondition.toString();
}
@NotNull
private static ArrangementEntryMatcher doBuildMatcher(@NotNull ArrangementMatchCondition condition) {
MyVisitor visitor = new MyVisitor();
@@ -87,8 +87,8 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
private static class MyVisitor implements ArrangementMatchConditionVisitor {
@NotNull private final List<ArrangementEntryMatcher> myMatchers = ContainerUtilRt.newArrayList();
@NotNull private final Set<ArrangementEntryType> myTypes = EnumSet.noneOf(ArrangementEntryType.class);
@NotNull private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
@NotNull private final Set<ArrangementSettingsToken> myTypes = ContainerUtilRt.newHashSet();
@NotNull private final Set<ArrangementSettingsToken> myModifiers = ContainerUtilRt.newHashSet();
@Nullable private String myNamePattern;
@@ -96,15 +96,19 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
switch (condition.getType()) {
case TYPE:
myTypes.add((ArrangementEntryType)condition.getValue());
break;
case MODIFIER:
myModifiers.add((ArrangementModifier)condition.getValue());
break;
case NAME:
myNamePattern = condition.getValue().toString();
if (StdArrangementTokens.General.NAME.equals(condition.getType())) {
myNamePattern = condition.getValue().toString();
return;
}
Object v = condition.getValue();
if (v instanceof ArrangementSettingsToken) {
ArrangementSettingsToken token = (ArrangementSettingsToken)v;
if (StdArrangementTokens.EntryType.is(token)) {
myTypes.add(token);
}
else if (StdArrangementTokens.Modifier.is(token)) {
myModifiers.add(token);
}
}
}
@@ -15,7 +15,7 @@
*/
package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
/**
@@ -32,8 +32,8 @@ public class StdArrangementMatchRule extends ArrangementMatchRule implements Clo
super(matcher);
}
public StdArrangementMatchRule(@NotNull StdArrangementEntryMatcher matcher, @NotNull ArrangementEntryOrderType type) {
super(matcher, type);
public StdArrangementMatchRule(@NotNull StdArrangementEntryMatcher matcher, @NotNull ArrangementSettingsToken orderType) {
super(matcher, orderType);
}
@NotNull
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.codeStyle.arrangement.model;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
/**
@@ -27,18 +28,22 @@ import org.jetbrains.annotations.NotNull;
*/
public class ArrangementAtomMatchCondition implements ArrangementMatchCondition {
@NotNull private final ArrangementSettingType myType;
@NotNull private final Object myValue;
@NotNull private final ArrangementSettingsToken myType;
@NotNull private final Object myValue;
private boolean myInverted;
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingType type, @NotNull Object value) {
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingsToken type) {
this(type, type);
}
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingsToken type, @NotNull Object value) {
myType = type;
myValue = value;
}
@NotNull
public ArrangementSettingType getType() {
public ArrangementSettingsToken getType() {
return myType;
}
@@ -78,7 +83,7 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
if (myInverted != setting.myInverted) {
return false;
}
if (myType != setting.myType) {
if (!myType.equals(setting.myType)) {
return false;
}
if (!myValue.equals(setting.myValue)) {
@@ -98,6 +103,11 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
@Override
public String toString() {
return String.format("%s: %s%s", myType.toString().toLowerCase(), myInverted ? "not " : "", myValue.toString().toLowerCase());
if (myType.equals(myValue)) {
return String.format("%s%s", myInverted ? "not " : "", myType.getRepresentationValue());
}
else {
return String.format("%s: %s%s", myType.getRepresentationValue(), myInverted ? "not " : "", myValue.toString().toLowerCase());
}
}
}
@@ -1,25 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.order;
/**
* @author Denis Zhdanov
* @since 7/19/12 6:24 PM
*/
public enum ArrangementEntryOrderType {
KEEP, BY_NAME, DEPTH_FIRST, BREADTH_FIRST
}
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.order;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Defines a contract for a strategy that knows how to order {@link ArrangementEntry arrangement entries}
* {@link ArrangementEntryMatcher#isMatched(ArrangementEntry) matched} against the same rule using particular
* {@link ArrangementEntryOrderType order type}.
* <p/>
* Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
* @author Denis Zhdanov
* @since 7/18/12 12:41 PM
*/
public interface ArrangementEntryOrderer {
/**
* Asks to sort given entries matched against the current rule. Given list defines a default order to be used.
*
* @param entries entries matched against the current rule
*/
void order(@NotNull List<? extends ArrangementEntry> entries);
}
@@ -1,63 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.order;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author Denis Zhdanov
* @since 7/19/12 6:17 PM
*/
public class ByNameArrangementEntryOrderer implements ArrangementEntryOrderer {
@Override
public void order(@NotNull List<? extends ArrangementEntry> entries) {
TObjectIntHashMap<ArrangementEntry> weights = new TObjectIntHashMap<ArrangementEntry>();
for (int i = 0; i < entries.size(); i++) {
weights.put(entries.get(i), i);
}
Collections.sort(entries, new MyComparator(weights));
}
private static class MyComparator implements Comparator<ArrangementEntry> {
@NotNull
private final TObjectIntHashMap<ArrangementEntry> myFallbackWeights;
MyComparator(@NotNull TObjectIntHashMap<ArrangementEntry> weights) {
myFallbackWeights = weights;
}
@Override
public int compare(ArrangementEntry o1, ArrangementEntry o2) {
if (o1 instanceof NameAwareArrangementEntry && o2 instanceof NameAwareArrangementEntry) {
String name1 = ((NameAwareArrangementEntry)o1).getName();
String name2 = ((NameAwareArrangementEntry)o1).getName();
if (name1 != null && name2 != null) {
return name1.compareTo(name2);
}
}
return myFallbackWeights.get(o1) - myFallbackWeights.get(o2);
}
}
}
@@ -1,64 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
/**
* Strategy which hints on how arrangement match conditions should be grouped at the UI.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
* @author Denis Zhdanov
* @since 8/15/12 4:21 PM
*/
public interface ArrangementConditionsGrouper {
/**
* Allows to answer if and how should be grouped given match conditions.
* <p/>
* Example: we have the following composite <code>'AND'</code> conditions below:
* <pre>
* <ul>
* <li><code>'type: field; modifier: public; modifier: static; modifier: final'</code>;</li>
* <li><code>'type: field; modifier: private; modifier: static; modifier: final'</code>;</li>
* <li><code>'type: method; modifier: public; modifier: static;'</code>;</li>
* <li><code>'type: method; modifier: private; modifier: static;'</code>;</li>
* </ul>
* </pre>
* We might want to show it like below:
* <pre>
* field
* |
* |---public---static---final
* |---private---static---final
* method
* |
* |---public---static
* |---private---static
* </pre>
* That means that we'll return a list with the single set which contains <code>'type: field'</code> and <code>'type: method'</code>
* conditions.
*
* @return grouping rules to use
*/
@NotNull
List<Set<ArrangementMatchCondition>> getGroupingConditions();
}
@@ -1,93 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Set;
/**
* Strategy that defines what subset of standard arrangement settings can be used during defining arrangement settings
* and how they are organised (e.g. single settings can't have more than one visibility modifier for java language).
*
* @author Denis Zhdanov
* @since 8/6/12 2:26 PM
*/
public interface ArrangementStandardSettingsAware {
/**
* @return settings to use by default, i.e. when a user hasn't been explicitly modified arrangement settings;
* <code>null</code> as an indication that no default settings are available
*/
@Nullable
StdArrangementSettings getDefaultSettings();
/**
* @return <code>true</code> if name-based rules are supported by the current rearranger (it knows
* about {@link NameAwareArrangementEntry});
* <code>false</code> otherwise
*/
boolean isNameFilterSupported();
/**
* Allows to answer if given entry type can be applied for the rule specified by the given settings node.
*
* @param type target entry type to check
* @param current holds information about current rule
* (<code>null</code> to indicate a query if given entry type is supported in general)
* @return <code>true</code> if given entry type is supported; <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current);
/**
* Allows to answer if given modifier can be applied for the rule specified by the given settings node.
*
* @param modifier target modifier to check
* @param current holds information about current rule
* (<code>null</code> to indicate a query if given modifier is supported in general)
* @return <code>true</code> if given modifier is supported; <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current);
/**
* Allows to answer if given grouping type (optionally with the given order type) can be used.
*
* @param groupingType target grouping type to check
* @param orderType target order type to check whether it can be used with the given grouping type;
* <code>null</code> to indicate that we want to know if given grouping type can be used in general
* for the languages-specific realisation of this interface
* @return <code>true</code> if given arguments are eligible for the languages-specific realisation of this interface;
* <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementGroupingType groupingType, @Nullable ArrangementEntryOrderType orderType);
/**
* @return collections of mutual exclusion settings. E.g. not more than one visibility modifier can be used for a single
* java language rule
*/
@NotNull
Collection<Set<?>> getMutexes();
}
@@ -1,77 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
/**
* Allows to inject custom logic for representation {@link ArrangementStandardSettingsAware standard settings-aware}
* {@link Rearranger language-specific rearranger}.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
* @author Denis Zhdanov
* @since 8/15/12 10:15 AM
*/
public interface ArrangementStandardSettingsRepresentationAware {
/**
* @param type target entry type
* @return text to show end-user for the given type
*/
@NotNull
String getDisplayValue(@NotNull ArrangementEntryType type);
/**
* @param modifier target modifier
* @return text to show end-user for the given modifier
*/
@NotNull
String getDisplayValue(@NotNull ArrangementModifier modifier);
/**
* @param groupingType target grouping type
* @return text to show end-user for the given grouping type
*/
@NotNull
String getDisplayValue(@NotNull ArrangementGroupingType groupingType);
/**
* @param orderType target order type
* @return text to show end-user for the given order type
*/
@NotNull
String getDisplayValue(@NotNull ArrangementEntryOrderType orderType);
/**
* Allows to sort given arrangement condition ids ('field', 'class', 'method', 'public', 'static', 'final' etc) before showing
* them to an end-user.
*
* @param ids target ids to use
* @param <T> id type
* @return sorted ids to use
*/
@NotNull
<T> List<T> sort(@NotNull Collection<T> ids);
}
@@ -1,151 +0,0 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement.settings;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author Denis Zhdanov
* @since 8/15/12 10:24 AM
*/
public class DefaultArrangementSettingsRepresentationManager implements ArrangementStandardSettingsRepresentationAware {
@NotNull public static final DefaultArrangementSettingsRepresentationManager INSTANCE =
new DefaultArrangementSettingsRepresentationManager();
@NotNull private static final TObjectIntHashMap<Object> WEIGHTS = new TObjectIntHashMap<Object>();
static {
Object[] ids = {
// Types.
ArrangementEntryType.FIELD, ArrangementEntryType.CONSTRUCTOR, ArrangementEntryType.METHOD, ArrangementEntryType.CLASS,
ArrangementEntryType.INTERFACE, ArrangementEntryType.ENUM,
ArrangementEntryType.STATIC_INIT, ArrangementEntryType.CONST, ArrangementEntryType.VAR,
ArrangementEntryType.PROPERTY, ArrangementEntryType.EVENT_HANDLER,
ArrangementEntryType.NAMESPACE, ArrangementEntryType.TRAIT,
// Visibility.
ArrangementModifier.PUBLIC, ArrangementModifier.PROTECTED, ArrangementModifier.PACKAGE_PRIVATE, ArrangementModifier.PRIVATE,
// Other common modifiers.
ArrangementModifier.STATIC, ArrangementModifier.FINAL,
ArrangementModifier.OVERRIDE,
// Semi-common modifiers.
ArrangementModifier.ABSTRACT,
// Method-specific modifiers.
ArrangementModifier.SYNCHRONIZED,
// Field-specific modifiers.
ArrangementModifier.TRANSIENT, ArrangementModifier.VOLATILE
};
for (int i = 0; i < ids.length; i++) {
WEIGHTS.put(ids[i], i);
}
}
@NotNull
private static final Comparator<Object> COMPARATOR = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
if (WEIGHTS.containsKey(o1) && WEIGHTS.containsKey(o2)) {
return WEIGHTS.get(o1) - WEIGHTS.get(o2);
}
else if (WEIGHTS.containsKey(o1) && !WEIGHTS.containsKey(o2)) {
return -1;
}
else if (!WEIGHTS.containsKey(o1) && WEIGHTS.containsKey(o2)) {
return 1;
}
else {
return o1.hashCode() - o2.hashCode();
}
}
};
private static final Map<ArrangementGroupingType, String> GROUPING_TYPES = ContainerUtil.newHashMap();
static {
GROUPING_TYPES.put(ArrangementGroupingType.GETTERS_AND_SETTERS,
ApplicationBundle.message("arrangement.settings.groups.getters.and.setters.together"));
GROUPING_TYPES.put(ArrangementGroupingType.OVERRIDDEN_METHODS,
ApplicationBundle.message("arrangement.settings.groups.overridden.methods"));
GROUPING_TYPES.put(ArrangementGroupingType.DEPENDENT_METHODS,
ApplicationBundle.message("arrangement.settings.groups.dependent.methods"));
GROUPING_TYPES.put(ArrangementGroupingType.GROUP_PROPERTY_FIELD_WITH_GETTER_SETTER,
ApplicationBundle.message("arrangement.settings.groups.property.field"));
assert GROUPING_TYPES.size() == ArrangementGroupingType.values().length;
}
private static final Map<ArrangementEntryOrderType, String> ORDER_TYPES = ContainerUtil.newHashMap();
static {
ORDER_TYPES.put(ArrangementEntryOrderType.KEEP, ApplicationBundle.message("arrangement.settings.order.type.keep"));
ORDER_TYPES.put(ArrangementEntryOrderType.BY_NAME, ApplicationBundle.message("arrangement.settings.order.type.by.name"));
ORDER_TYPES.put(ArrangementEntryOrderType.DEPTH_FIRST, ApplicationBundle.message("arrangement.settings.order.type.depth.first"));
ORDER_TYPES.put(ArrangementEntryOrderType.BREADTH_FIRST, ApplicationBundle.message("arrangement.settings.order.type.breadth.first"));
assert ORDER_TYPES.size() == ArrangementEntryOrderType.values().length;
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementEntryType type) {
return getDisplayValue(type.toString());
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementModifier modifier) {
return getDisplayValue(modifier.toString());
}
@NotNull
private static String getDisplayValue(@NotNull String s) {
return s.toLowerCase().replace("_", " ");
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementGroupingType groupingType) {
return GROUPING_TYPES.get(groupingType);
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementEntryOrderType orderType) {
return ORDER_TYPES.get(orderType);
}
@NotNull
@Override
public <T> List<T> sort(@NotNull Collection<T> ids) {
List<T> result = new ArrayList<T>(ids);
Collections.sort(result, COMPARATOR);
return result;
}
}
@@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.settings;
package com.intellij.psi.codeStyle.arrangement.std;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,7 +33,7 @@ import java.awt.*;
public interface ArrangementColorsAware {
@Nullable
TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingType type, boolean selected);
TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingsToken token, boolean selected);
@Nullable
Color getBorderColor(@NotNull EditorColorsScheme scheme, boolean selected);
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2013 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.psi.codeStyle.arrangement.std;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Stands for an atomic settings element. The general idea is to allow third-party plugin developers to use platform
* codebase for managing arrangement settings, that's why we need a general purpose class that represent a setting.
* I.e. third-party developers can create their own instances of this class and implement {@link ArrangementStandardSettingsAware}.
*
* @author Denis Zhdanov
* @since 3/6/13 12:38 PM
*/
public class ArrangementSettingsToken implements Comparable<ArrangementSettingsToken> {
@NotNull private final String myId;
@NotNull private final String myRepresentationName;
public ArrangementSettingsToken(@NotNull String id, @NotNull String name) {
myId = id;
myRepresentationName = name;
}
@NotNull
public String getId() {
return myId;
}
@NotNull
public String getRepresentationValue() {
return myRepresentationName;
}
@Override
public int compareTo(ArrangementSettingsToken that) {
return myId.compareTo(that.myId);
}
@Override
public int hashCode() {
return myId.hashCode();
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArrangementSettingsToken that = (ArrangementSettingsToken)o;
return myId.equals(that.myId);
}
@Override
public String toString() {
return myRepresentationName;
}
}
@@ -0,0 +1,89 @@
/*
* Copyright 2000-2013 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.psi.codeStyle.arrangement.std;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Defines a contract for {@link Rearranger} implementation which wants to use standard platform UI for configuring
* and managing arrangement settings.
*
* @author Denis Zhdanov
* @since 8/6/12 2:26 PM
*/
public interface ArrangementStandardSettingsAware {
/**
* @return settings to use by default, i.e. when a user hasn't been explicitly modified arrangement settings;
* <code>null</code> as an indication that no default settings are available
*/
@Nullable
StdArrangementSettings getDefaultSettings();
/**
* @return ordered collection of grouping tokens eligible to use with the current rearranger.
* <b>Note:</b> platform code which uses this method caches returned results
*/
@Nullable
List<CompositeArrangementSettingsToken> getSupportedGroupingTokens();
/**
* @return ordered collection of matching tokens eligible to use with the current rearranger
* <b>Note:</b> platform code which uses this method caches returned results
*/
@Nullable
List<CompositeArrangementSettingsToken> getSupportedMatchingTokens();
/**
* Allows to answer if given token is enabled in combination with other conditions specified by the given condition object.
* <p/>
* Example: say, current rearranger is for java and given condition is like 'public class'. This method is expected to
* return <code>false</code> for token 'volatile' (because it can be applied only to fields) but <code>true</code>
* for token 'abstract' (a java class can be abstract).
*
* @param token target token to check
* @param current an object which represents currently chosen tokens; <code>null</code> if no other token is selected
* @return <code>true</code> if given token is enabled with the given condition; <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current);
/**
* This method is assumed to be used only by third-party developers. All built-in IJ conditions are supposed
* to be implemented in terms of {@link StdArrangementTokens}.
*
* @param condition target condition
* @return a matcher for the given condition
* @throws IllegalArgumentException if current rearranger doesn't know how to build a matcher from the given condition
*/
@NotNull
ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException;
/**
* @return collections of mutual exclusion settings. It's is used by standard arrangement settings UI to automatically
* deselect elements on selection change. Example: 'private' modifier was selected. When any other modifier is selected
* 'public' modifier is deselected if returned collection contains set of all supported visibility modifiers
*/
@NotNull
Collection<Set<ArrangementSettingsToken>> getMutexes();
}
@@ -0,0 +1,182 @@
/*
* Copyright 2000-2013 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.psi.codeStyle.arrangement.std;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.CompositeArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.containers.ContainerUtilRt;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Wraps {@link ArrangementStandardSettingsAware} for the common arrangement UI managing code.
*
* @author Denis Zhdanov
* @since 3/7/13 3:11 PM
*/
public class ArrangementStandardSettingsManager {
@NotNull private final TObjectIntHashMap<ArrangementSettingsToken> myWidths = new TObjectIntHashMap<ArrangementSettingsToken>();
@NotNull private final TObjectIntHashMap<ArrangementSettingsToken> myWeights = new TObjectIntHashMap<ArrangementSettingsToken>();
@NotNull private final Comparator<ArrangementSettingsToken> myComparator = new Comparator<ArrangementSettingsToken>() {
@Override
public int compare(ArrangementSettingsToken t1, ArrangementSettingsToken t2) {
if (myWeights.containsKey(t1)) {
if (myWeights.containsKey(t2)) {
return myWeights.get(t1) - myWeights.get(t2);
}
else {
return -1;
}
}
else if (myWeights.containsKey(t2)) {
return 1;
}
else {
return t1.compareTo(t2);
}
}
};
@NotNull private final ArrangementStandardSettingsAware myDelegate;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final Collection<Set<ArrangementSettingsToken>> myMutexes;
@Nullable private final StdArrangementSettings myDefaultSettings;
@Nullable private final List<CompositeArrangementSettingsToken> myGroupingTokens;
@Nullable private final List<CompositeArrangementSettingsToken> myMatchingTokens;
public ArrangementStandardSettingsManager(@NotNull ArrangementStandardSettingsAware delegate,
@NotNull ArrangementColorsProvider colorsProvider)
{
myDelegate = delegate;
myColorsProvider = colorsProvider;
myMutexes = delegate.getMutexes();
myDefaultSettings = delegate.getDefaultSettings();
SimpleColoredComponent renderer = new SimpleColoredComponent();
myGroupingTokens = delegate.getSupportedGroupingTokens();
if (myGroupingTokens != null) {
parseWidths(myGroupingTokens, renderer);
buildWeights(myGroupingTokens);
}
myMatchingTokens = delegate.getSupportedMatchingTokens();
if (myMatchingTokens != null) {
parseWidths(myMatchingTokens, renderer);
buildWeights(myMatchingTokens);
}
}
private void parseWidths(@NotNull Collection<CompositeArrangementSettingsToken> compositeTokens,
@NotNull SimpleColoredComponent renderer)
{
int width = 0;
for (CompositeArrangementSettingsToken compositeToken : compositeTokens) {
width = Math.max(width, parseWidth(compositeToken.getToken(), renderer));
}
for (CompositeArrangementSettingsToken compositeToken : compositeTokens) {
myWidths.put(compositeToken.getToken(), width);
parseWidths(compositeToken.getChildren(), renderer);
}
}
private void buildWeights(@NotNull Collection<CompositeArrangementSettingsToken> compositeTokens) {
for (CompositeArrangementSettingsToken token : compositeTokens) {
myWeights.put(token.getToken(), myWeights.size());
buildWeights(token.getChildren());
}
}
/**
* @see ArrangementStandardSettingsAware#getDefaultSettings()
*/
@Nullable
public StdArrangementSettings getDefaultSettings() {
return myDefaultSettings;
}
/**
* @see ArrangementStandardSettingsAware#getSupportedGroupingTokens()
*/
@Nullable
public List<CompositeArrangementSettingsToken> getSupportedGroupingTokens() {
return myGroupingTokens;
}
/**
* @see ArrangementStandardSettingsAware#getSupportedMatchingTokens()
*/
@Nullable
public List<CompositeArrangementSettingsToken> getSupportedMatchingTokens() {
return myMatchingTokens;
}
public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) {
return myDelegate.isEnabled(token, current);
}
@NotNull
public ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
ArrangementEntryMatcher matcher = ArrangementUtil.buildMatcher(condition);
if (matcher == null) {
matcher = myDelegate.buildMatcher(condition);
}
return matcher;
}
@NotNull
public Collection<Set<ArrangementSettingsToken>> getMutexes() {
return myMutexes;
}
public int getWidth(@NotNull ArrangementSettingsToken token) {
if (myWidths.containsKey(token)) {
return myWidths.get(token);
}
return parseWidth(token, new SimpleColoredComponent());
}
private int parseWidth(@NotNull ArrangementSettingsToken token, @NotNull SimpleColoredComponent renderer) {
renderer.clear();
renderer.append(token.getRepresentationValue(),
SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, true)));
int result = renderer.getPreferredSize().width;
renderer.clear();
renderer.append(token.getRepresentationValue(),
SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, false)));
return Math.max(result, renderer.getPreferredSize().width);
}
public List<ArrangementSettingsToken> sort(@NotNull Collection<ArrangementSettingsToken> tokens) {
List<ArrangementSettingsToken> result = ContainerUtilRt.newArrayList(tokens);
Collections.sort(result, myComparator);
return result;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.match;
package com.intellij.psi.codeStyle.arrangement.std;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,44 +24,61 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.List;
/**
* Component which manages {@link ArrangementMatchCondition match condition} UI representation.
* Defines a contract for UI component used at standard arrangement settings managing code.
* <p/>
* It's assumed that there is a dedicated implementation of this interface for every {@link StdArrangementTokenUiRole}.
*
* @author Denis Zhdanov
* @since 8/10/12 11:22 AM
* @since 3/11/13 10:22 AM
*/
public interface ArrangementMatchConditionComponent {
public interface ArrangementUiComponent {
@Nullable ArrangementSettingsToken getToken();
void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException, UnsupportedOperationException;
@NotNull
ArrangementMatchCondition getMatchCondition();
@NotNull JComponent getUiComponent();
/**
* @return UI component for the {@link #getMatchCondition() target match condition}
* We use 'enabled by user' property name here in order to avoid clash
* with {@link Component#isEnabled() standard awt 'enabled' property}.
*
* @return <code>true</code> if current ui token is enabled; <code>false</code> otherwise
*/
@NotNull
JComponent getUiComponent();
boolean isEnabled();
void setEnabled(boolean enabled);
/**
* @return screen bounds for the {@link #getUiComponent() target UI component} (if known)
*/
@Nullable
Rectangle getScreenBounds();
boolean isSelected();
/**
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'selected' state.
*
* @param selected flag that indicates if current component should be drawn as 'selected'
*/
void setSelected(boolean selected);
void reset();
/**
* Notifies current component about mose move event.
* <p/>
* Primary intention is to allow to react on event like 'on mouse hover' etc. We can't do that by subscribing to the
* mouse events at the {@link #getUiComponent() corresponding UI control} because it's used only as a renderer and is not put
* to the containers hierarchy, hence, doesn't receive mouse events.
*
*
* @param event target mouse move event
* @return bounds to be repainted (in screen coordinates) if any; <code>null</code> otherwise
*/
@@ -73,4 +92,27 @@ public interface ArrangementMatchConditionComponent {
@Nullable
Rectangle onMouseEntered(@NotNull MouseEvent e);
/**
* @param width the width to get baseline for
* @param height the height to get baseline for
* @return baseline's y coordinate if applicable; negative value otherwise
*/
int getBaselineToUse(int width, int height);
void setListener(@NotNull Listener listener);
interface Factory {
ExtensionPointName<Factory> EP_NAME = ExtensionPointName.create("com.intellij.rearranger.ui");
@Nullable
ArrangementUiComponent build(@NotNull StdArrangementTokenUiRole role,
@NotNull List<ArrangementSettingsToken> tokens,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsManager settingsManager);
}
interface Listener {
void stateChanged();
}
}
@@ -0,0 +1,118 @@
/*
* Copyright 2000-2013 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.psi.codeStyle.arrangement.std;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Used to group ordered collections of {@link StdArrangementTokens} along with their {@link StdArrangementTokenUiRole roles}.
*
* @author Denis Zhdanov
* @since 3/6/13 8:01 PM
*/
public class CompositeArrangementSettingsToken {
private static final Function<ArrangementSettingsToken, CompositeArrangementSettingsToken> WRAPPER =
new Function<ArrangementSettingsToken, CompositeArrangementSettingsToken>() {
@Override
public CompositeArrangementSettingsToken fun(ArrangementSettingsToken token) {
return new CompositeArrangementSettingsToken(token, deduceRole(token), Collections.<CompositeArrangementSettingsToken>emptyList());
}
};
@NotNull private final List<CompositeArrangementSettingsToken> myChildren = ContainerUtilRt.newArrayList();
@NotNull private final ArrangementSettingsToken myToken;
@NotNull private final StdArrangementTokenUiRole myRole;
/**
* Creates new <code>CompositeArrangementSettingsToken</code> object with no nested tokens.
* <p/>
* <b>Note:</b> given token is expected to be one of {@link StdArrangementTokens standard tokens} because
* {@link StdArrangementTokenUiRole its role} is deduced.
*
* @param token token to wrap
*/
public CompositeArrangementSettingsToken(@NotNull ArrangementSettingsToken token) {
this(token, deduceRole(token), Collections.<CompositeArrangementSettingsToken>emptyList());
}
/**
* Creates new <code>CompositeArrangementSettingsToken</code> object with the given token and all given children
* assuming that every child {@link CompositeArrangementSettingsToken} will have no children.
* <p/>
* <b>Note:</b> given tokens are expected to be from {@link StdArrangementTokens standard tokens} because
* {@link StdArrangementTokenUiRole their roles} are deduced.
*
* @param token token to wrap
* @param children children to wrap
*/
public CompositeArrangementSettingsToken(@NotNull ArrangementSettingsToken token,
@NotNull ArrangementSettingsToken... children)
{
this(token, deduceRole(token), ContainerUtilRt.map2List(children, WRAPPER));
}
public CompositeArrangementSettingsToken(@NotNull ArrangementSettingsToken token,
@NotNull Collection<ArrangementSettingsToken> children)
{
this(token, deduceRole(token), ContainerUtilRt.map2List(children, WRAPPER));
}
public CompositeArrangementSettingsToken(@NotNull ArrangementSettingsToken token,
@NotNull StdArrangementTokenUiRole role,
@NotNull List<CompositeArrangementSettingsToken> children)
{
myToken = token;
myRole = role;
myChildren.addAll(children);
}
@NotNull
private static StdArrangementTokenUiRole deduceRole(@NotNull ArrangementSettingsToken token) {
StdArrangementTokenUiRole role = StdArrangementTokens.role(token);
if (role == null) {
throw new IllegalArgumentException("Can't deduce UI role for token " + token);
}
return role;
}
@NotNull
public List<CompositeArrangementSettingsToken> getChildren() {
return myChildren;
}
@NotNull
public ArrangementSettingsToken getToken() {
return myToken;
}
@NotNull
public StdArrangementTokenUiRole getRole() {
return myRole;
}
@Override
public String toString() {
return myToken.toString() + "-" + myRole;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement;
package com.intellij.psi.codeStyle.arrangement.std;
import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import org.jetbrains.annotations.NotNull;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.model;
package com.intellij.psi.codeStyle.arrangement.std;
/**
* @author Denis Zhdanov
* @since 8/6/12 5:02 PM
* @since 3/11/13 9:45 AM
*/
public enum ArrangementSettingType {
TYPE, MODIFIER, NAME, ORDER
public enum StdArrangementTokenUiRole {
LABEL,
CHECKBOX,
COMBO_BOX,
TEXT_FIELD,
BULB,
}
@@ -0,0 +1,237 @@
/*
* Copyright 2000-2013 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.psi.codeStyle.arrangement.std;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokenUiRole.*;
/**
* // TODO den add doc
*
* @author Denis Zhdanov
* @since 3/6/13 3:16 PM
*/
public class StdArrangementTokens {
private static final Map<String, ArrangementSettingsToken> TOKENS_BY_ID = ContainerUtilRt.newHashMap();
private static final Map<ArrangementSettingsToken, StdArrangementTokenUiRole> ROLES_BY_TOKEN = ContainerUtilRt.newHashMap();
/**
* Forces nested classes initialization - otherwise it's possible that, say, {@link #byId(String)} returns null for valid
* id just because corresponding nested class hasn't been initialized yet.
*/
private static final NotNullLazyValue<Integer> NESTED_CLASSES_INITIALIZER = new NotNullLazyValue<Integer>() {
@NotNull
@Override
protected Integer compute() {
int dummy = 0;
for (Class<?> clazz : StdArrangementTokens.class.getClasses()) {
try {
dummy += clazz.getDeclaredFields()[0].get(null).hashCode();
}
catch (IllegalAccessException e) {
assert false;
}
}
return dummy;
}
};
private StdArrangementTokens() {
}
@Nullable
public static ArrangementSettingsToken byId(@NotNull String id) {
NESTED_CLASSES_INITIALIZER.getValue();
return TOKENS_BY_ID.get(id);
}
@Nullable
public static StdArrangementTokenUiRole role(@NotNull ArrangementSettingsToken token) {
NESTED_CLASSES_INITIALIZER.getValue();
return ROLES_BY_TOKEN.get(token);
}
@NotNull
private static ArrangementSettingsToken token(@NotNull String id, @NotNull StdArrangementTokenUiRole role) {
ArrangementSettingsToken result = new ArrangementSettingsToken(id, id.toLowerCase().replace("_", " "));
TOKENS_BY_ID.put(id, result);
ROLES_BY_TOKEN.put(result, role);
return result;
}
@NotNull
private static ArrangementSettingsToken token(@NotNull String id,
@NotNull @PropertyKey(resourceBundle = ApplicationBundle.BUNDLE) String key,
@NotNull StdArrangementTokenUiRole role)
{
ArrangementSettingsToken result = new ArrangementSettingsToken(id, ApplicationBundle.message(key));
TOKENS_BY_ID.put(id, result);
ROLES_BY_TOKEN.put(result, role);
return result;
}
private static NotNullLazyValue<Set<ArrangementSettingsToken>> collectFields(@NotNull final Class<?> clazz) {
return new NotNullLazyValue<Set<ArrangementSettingsToken>>() {
@NotNull
@Override
protected Set<ArrangementSettingsToken> compute() {
Set<ArrangementSettingsToken> result = ContainerUtilRt.newHashSet();
for (Field field : clazz.getFields()) {
if (ArrangementSettingsToken.class.isAssignableFrom(field.getType())) {
try {
result.add((ArrangementSettingsToken)field.get(null));
}
catch (IllegalAccessException e) {
assert false : e;
}
}
}
return result;
}
};
}
public static class General {
@NotNull public static final ArrangementSettingsToken TYPE = token("TYPE", "arrangement.settings.text.general.type", LABEL);
@NotNull public static final ArrangementSettingsToken MODIFIER = token("MODIFIER", "arrangement.settings.text.general.modifier", LABEL);
@NotNull public static final ArrangementSettingsToken NAME = token("NAME", "arrangement.settings.text.general.name", TEXT_FIELD);
@NotNull public static final ArrangementSettingsToken ORDER = token("ORDER", "arrangement.settings.text.general.order", LABEL);
private static final NotNullLazyValue<Set<ArrangementSettingsToken>> TOKENS = collectFields(General.class);
private General() {
}
public static boolean is(@NotNull ArrangementSettingsToken token) {
return TOKENS.getValue().contains(token);
}
}
public static class EntryType {
@NotNull public static final ArrangementSettingsToken CLASS = token("CLASS", BULB);
@NotNull public static final ArrangementSettingsToken ANONYMOUS_CLASS = token("ANONYMOUS_CLASS", BULB);
@NotNull public static final ArrangementSettingsToken FIELD = token("FIELD", BULB);
@NotNull public static final ArrangementSettingsToken CONSTRUCTOR = token("CONSTRUCTOR", BULB);
@NotNull public static final ArrangementSettingsToken METHOD = token("METHOD", BULB);
@NotNull public static final ArrangementSettingsToken ENUM = token("ENUM", BULB);
@NotNull public static final ArrangementSettingsToken INTERFACE = token("INTERFACE", BULB);
@NotNull public static final ArrangementSettingsToken CONST = token("CONST", BULB);
@NotNull public static final ArrangementSettingsToken VAR = token("VAR", BULB);
@NotNull public static final ArrangementSettingsToken PROPERTY = token("PROPERTY", BULB);
@NotNull public static final ArrangementSettingsToken EVENT_HANDLER = token("EVENT_HANDLER", BULB);
@NotNull public static final ArrangementSettingsToken STATIC_INIT = token("STATIC_INIT", BULB);
@NotNull public static final ArrangementSettingsToken NAMESPACE = token("NAMESPACE", BULB);
@NotNull public static final ArrangementSettingsToken TRAIT = token("TRAIT", BULB);
@NotNull public static final ArrangementSettingsToken XML_TAG =
token("XML_TAG", "arrangement.settings.text.entry.type.xml.tag", BULB);
@NotNull public static final ArrangementSettingsToken XML_ATTRIBUTE =
token("XML_ATTRIBUTE", "arrangement.settings.text.entry.type.xml.attribute", BULB);
private static final NotNullLazyValue<Set<ArrangementSettingsToken>> TOKENS = collectFields(EntryType.class);
private EntryType() {
}
@NotNull
public static Set<ArrangementSettingsToken> values() {
return TOKENS.getValue();
}
public static boolean is(@NotNull ArrangementSettingsToken token) {
return TOKENS.getValue().contains(token);
}
}
public static class Modifier {
@NotNull public static final ArrangementSettingsToken PUBLIC = token("PUBLIC", BULB);
@NotNull public static final ArrangementSettingsToken PROTECTED = token("PROTECTED", BULB);
@NotNull public static final ArrangementSettingsToken PRIVATE = token("PRIVATE", BULB);
@NotNull public static final ArrangementSettingsToken PACKAGE_PRIVATE = token("PACKAGE_PRIVATE", BULB);
@NotNull public static final ArrangementSettingsToken STATIC = token("STATIC", BULB);
@NotNull public static final ArrangementSettingsToken FINAL = token("FINAL", BULB);
@NotNull public static final ArrangementSettingsToken TRANSIENT = token("TRANSIENT", BULB);
@NotNull public static final ArrangementSettingsToken VOLATILE = token("VOLATILE", BULB);
@NotNull public static final ArrangementSettingsToken SYNCHRONIZED = token("SYNCHRONIZED", BULB);
@NotNull public static final ArrangementSettingsToken ABSTRACT = token("ABSTRACT", BULB);
@NotNull public static final ArrangementSettingsToken OVERRIDE = token("OVERRIDE", BULB);
private static final NotNullLazyValue<Set<ArrangementSettingsToken>> TOKENS = collectFields(Modifier.class);
private Modifier() {
}
@NotNull
public static Set<ArrangementSettingsToken> values() {
return TOKENS.getValue();
}
public static boolean is(@NotNull ArrangementSettingsToken token) {
return TOKENS.getValue().contains(token);
}
}
public static class Grouping {
@NotNull public static final ArrangementSettingsToken GETTERS_AND_SETTERS =
token("GETTERS_AND_SETTERS", "arrangement.settings.groups.getters.and.setters.together", CHECKBOX);
@NotNull public static final ArrangementSettingsToken OVERRIDDEN_METHODS =
token("OVERRIDDEN_METHODS", "arrangement.settings.groups.overridden.methods", CHECKBOX);
@NotNull public static final ArrangementSettingsToken DEPENDENT_METHODS =
token("DEPENDENT_METHODS", "arrangement.settings.groups.dependent.methods", CHECKBOX);
@NotNull public static final ArrangementSettingsToken GROUP_PROPERTY_FIELD_WITH_GETTER_SETTER =
token("GROUP_PROPERTY_FIELD_WITH_GETTER_SETTER", "arrangement.settings.groups.property.field", CHECKBOX);
private Grouping() {
}
}
public static class Order {
@NotNull public static final ArrangementSettingsToken KEEP = token("KEEP", "arrangement.settings.order.type.keep",
COMBO_BOX);
@NotNull public static final ArrangementSettingsToken BY_NAME = token("BY_NAME", "arrangement.settings.order.type.by.name",
COMBO_BOX);
@NotNull public static final ArrangementSettingsToken DEPTH_FIRST = token("DEPTH_FIRST",
"arrangement.settings.order.type.depth.first",
COMBO_BOX);
@NotNull public static final ArrangementSettingsToken BREADTH_FIRST = token("BREADTH_FIRST",
"arrangement.settings.order.type.breadth.first",
COMBO_BOX);
private static final NotNullLazyValue<Set<ArrangementSettingsToken>> TOKENS = collectFields(Order.class);
private Order() {
}
public static boolean is(@NotNull ArrangementSettingsToken token) {
return TOKENS.getValue().contains(token);
}
}
}
@@ -16,16 +16,16 @@
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import org.jdom.Element;
import org.junit.Test;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.FIELD;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.OVERRIDDEN_METHODS;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME;
import static org.junit.Assert.assertEquals;
/**
@@ -37,9 +37,9 @@ public class ArrangementSettingsSerializationTest {
@Test
public void all() {
StdArrangementSettings settings = new StdArrangementSettings();
settings.addGrouping(new ArrangementGroupingRule(ArrangementGroupingType.OVERRIDDEN_METHODS, ArrangementEntryOrderType.BY_NAME));
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD);
settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), ArrangementEntryOrderType.BY_NAME));
settings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME));
Element holder = new Element("holder");
ArrangementSettingsSerializer instance = DefaultArrangementSettingsSerializer.INSTANCE;
@@ -16,24 +16,23 @@
package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.codeStyle.arrangement.DefaultArrangementSettingsSerializer;
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.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.util.containers.ContainerUtilRt;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.CLASS;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.FIELD;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.METHOD;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*;
import static com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType.MODIFIER;
import static com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType.NAME;
import static com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType.TYPE;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*;
import static org.junit.Assert.*;
/**
@@ -42,62 +41,63 @@ import static org.junit.Assert.*;
*/
public class DefaultArrangementEntryMatcherSerializerTest {
private final DefaultArrangementEntryMatcherSerializer mySerializer = new DefaultArrangementEntryMatcherSerializer();
private final DefaultArrangementEntryMatcherSerializer mySerializer =
new DefaultArrangementEntryMatcherSerializer(DefaultArrangementSettingsSerializer.Mixin.NULL);
@Test
public void simpleMatchers() {
doTest(new ArrangementAtomMatchCondition(TYPE, CLASS));
doTest(new ArrangementAtomMatchCondition(MODIFIER, PRIVATE));
doTest(new ArrangementAtomMatchCondition(CLASS));
doTest(new ArrangementAtomMatchCondition(PRIVATE));
}
@Test
public void compositeMatchers() {
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, METHOD));
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, SYNCHRONIZED));
condition.addOperand(new ArrangementAtomMatchCondition(METHOD));
condition.addOperand(new ArrangementAtomMatchCondition(SYNCHRONIZED));
doTest(condition);
condition = new ArrangementCompositeMatchCondition();
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, PUBLIC));
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, STATIC));
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, FINAL));
condition.addOperand(new ArrangementAtomMatchCondition(FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(PUBLIC));
condition.addOperand(new ArrangementAtomMatchCondition(STATIC));
condition.addOperand(new ArrangementAtomMatchCondition(FINAL));
}
@Test
public void conditionsOrder() {
// Inspired by IDEA-91826.
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
ArrangementEntryType typeToPreserve = FIELD;
Set<ArrangementModifier> modifiersToPreserve = EnumSet.of(PUBLIC, STATIC, FINAL);
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, typeToPreserve));
for (ArrangementModifier modifier : modifiersToPreserve) {
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, modifier));
ArrangementSettingsToken typeToPreserve = FIELD;
Set<ArrangementSettingsToken> modifiersToPreserve = ContainerUtilRt.newHashSet(PUBLIC, STATIC, FINAL);
condition.addOperand(new ArrangementAtomMatchCondition(typeToPreserve, typeToPreserve));
for (ArrangementSettingsToken modifier : modifiersToPreserve) {
condition.addOperand(new ArrangementAtomMatchCondition(modifier, modifier));
}
Element element = mySerializer.serialize(new StdArrangementEntryMatcher(condition));
assertNotNull(element);
// Change hash-container data distribution at the composite condition.
for (ArrangementEntryType type : ArrangementEntryType.values()) {
for (ArrangementSettingsToken type : StdArrangementTokens.EntryType.values()) {
if (type != typeToPreserve) {
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, type));
condition.addOperand(new ArrangementAtomMatchCondition(type, type));
}
}
for (ArrangementModifier modifier : values()) {
for (ArrangementSettingsToken modifier : StdArrangementTokens.Modifier.values()) {
if (!modifiersToPreserve.contains(modifier)) {
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, modifier));
condition.addOperand(new ArrangementAtomMatchCondition(modifier, modifier));
}
}
// Revert state to the initial one.
for (ArrangementEntryType type : ArrangementEntryType.values()) {
for (ArrangementSettingsToken type : StdArrangementTokens.EntryType.values()) {
if (type != typeToPreserve) {
condition.removeOperand(new ArrangementAtomMatchCondition(TYPE, type));
condition.removeOperand(new ArrangementAtomMatchCondition(type, type));
}
}
for (ArrangementModifier modifier : values()) {
for (ArrangementSettingsToken modifier : StdArrangementTokens.Modifier.values()) {
if (!modifiersToPreserve.contains(modifier)) {
condition.removeOperand(new ArrangementAtomMatchCondition(MODIFIER, modifier));
condition.removeOperand(new ArrangementAtomMatchCondition(modifier, modifier));
}
}
@@ -116,8 +116,8 @@ public class DefaultArrangementEntryMatcherSerializerTest {
@Test
public void compositeConditionWithName() {
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, METHOD));
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, SYNCHRONIZED));
condition.addOperand(new ArrangementAtomMatchCondition(METHOD));
condition.addOperand(new ArrangementAtomMatchCondition(SYNCHRONIZED));
condition.addOperand(new ArrangementAtomMatchCondition(NAME, ("get*")));
doTest(condition);
}
@@ -148,7 +148,6 @@ public class DefaultArrangementEntryMatcherSerializerTest {
assertNotNull(String.format("Can't serialize match condition '%s'", condition), element);
ArrangementEntryMatcher matcher = mySerializer.deserialize(element);
assertNotNull(matcher);
assertTrue(matcher instanceof StdArrangementEntryMatcher);
assertEquals(condition, ((StdArrangementEntryMatcher)matcher).getCondition());
}
}
@@ -15,25 +15,24 @@
*/
package com.intellij.psi.codeStyle.arrangement.match;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import com.intellij.psi.codeStyle.arrangement.ModifierAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.util.containers.ContainerUtilRt;
import org.jmock.Expectations;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.runner.RunWith;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.EnumSet;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*;
import static org.junit.Assert.*;
/**
* @author Denis Zhdanov
@@ -58,7 +57,7 @@ public class StandardArrangementEntryMatcherTest {
@Test
public void atomCondition() {
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD);
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
StdArrangementEntryMatcher matcher = new StdArrangementEntryMatcher(condition);
assertEquals(condition, matcher.getCondition());
@@ -67,9 +66,9 @@ public class StandardArrangementEntryMatcherTest {
final TypeAwareArrangementEntry classEntry = myMockery.mock(TypeAwareArrangementEntry.class, "class");
final ModifierAwareArrangementEntry publicEntry = myMockery.mock(ModifierAwareArrangementEntry.class, "public");
myMockery.checking(new Expectations() {{
allowing(fieldEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.FIELD)));
allowing(classEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.CLASS)));
allowing(publicEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PUBLIC)));
allowing(fieldEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(FIELD)));
allowing(classEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(CLASS)));
allowing(publicEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PUBLIC)));
}});
assertTrue(matcher.isMatched(fieldEntry));
@@ -80,8 +79,8 @@ public class StandardArrangementEntryMatcherTest {
@Test
public void compositeAndCondition() {
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
condition.addOperand(new ArrangementAtomMatchCondition(FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(PUBLIC));
StdArrangementEntryMatcher matcher = new StdArrangementEntryMatcher(condition);
assertEquals(condition, matcher.getCondition());
@@ -93,21 +92,21 @@ public class StandardArrangementEntryMatcherTest {
final TypeAndModifierAware publicFieldEntry = myMockery.mock(TypeAndModifierAware.class, "public field");
final TypeAndModifierAware publicStaticFieldEntry = myMockery.mock(TypeAndModifierAware.class, "public static field");
myMockery.checking(new Expectations() {{
allowing(fieldEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.FIELD)));
allowing(fieldEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(FIELD)));
allowing(publicEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PUBLIC)));
allowing(publicEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PUBLIC)));
allowing(privateFieldEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.FIELD)));
allowing(privateFieldEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PRIVATE)));
allowing(privateFieldEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(FIELD)));
allowing(privateFieldEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PRIVATE)));
allowing(publicMethodEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.METHOD)));
allowing(publicMethodEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PUBLIC)));
allowing(publicMethodEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(METHOD)));
allowing(publicMethodEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PUBLIC)));
allowing(publicFieldEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.FIELD)));
allowing(publicFieldEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PUBLIC)));
allowing(publicFieldEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(FIELD)));
allowing(publicFieldEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PUBLIC)));
allowing(publicStaticFieldEntry).getTypes(); will(returnValue(EnumSet.of(ArrangementEntryType.FIELD)));
allowing(publicStaticFieldEntry).getModifiers(); will(returnValue(EnumSet.of(ArrangementModifier.PUBLIC, ArrangementModifier.STATIC)));
allowing(publicStaticFieldEntry).getTypes(); will(returnValue(ContainerUtilRt.newHashSet(FIELD)));
allowing(publicStaticFieldEntry).getModifiers(); will(returnValue(ContainerUtilRt.newHashSet(PUBLIC, STATIC)));
}});
assertFalse(matcher.isMatched(fieldEntry));
@@ -1,167 +0,0 @@
/*
* Copyright 2000-2012 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;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Encapsulates various functionality related to showing arrangement nodes to end-users.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 8/9/12 3:02 PM
*/
@SuppressWarnings("MethodMayBeStatic")
public class ArrangementNodeDisplayManager {
@NotNull private final TObjectIntHashMap<ArrangementSettingType> myMaxWidths = new TObjectIntHashMap<ArrangementSettingType>();
@NotNull private final ArrangementStandardSettingsAware myFilter;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private ArrangementStandardSettingsRepresentationAware myRepresentationManager;
public ArrangementNodeDisplayManager(@NotNull ArrangementStandardSettingsAware filter,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsRepresentationAware representationManager)
{
myFilter = filter;
myColorsProvider = colorsProvider;
myRepresentationManager = representationManager;
refreshMaxWidths();
}
private void refreshMaxWidths() {
Map<ArrangementSettingType, Set<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
for (Map.Entry<ArrangementSettingType, Set<?>> entry : map.entrySet()) {
myMaxWidths.put(entry.getKey(), maxWidth(entry.getKey(), entry.getValue()));
}
}
private int maxWidth(@NotNull ArrangementSettingType type, @NotNull Collection<?> values) {
SimpleColoredComponent renderer = new SimpleColoredComponent();
int result = 0;
for (Object value : values) {
renderer.clear();
renderer.append(getDisplayValue(value), SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(type, true)));
result = Math.max(result, renderer.getPreferredSize().width);
renderer.clear();
renderer.append(getDisplayValue(value), SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(type, false)));
result = Math.max(result, renderer.getPreferredSize().width);
}
return result;
}
@NotNull
public String getDisplayValue(@NotNull ArrangementAtomMatchCondition setting) {
return getDisplayValue(setting.getValue());
}
@NotNull
public String getDisplayLabel(@NotNull ArrangementSettingType type) {
switch (type) {
case TYPE:
return ApplicationBundle.message("arrangement.text.type");
case MODIFIER:
return ApplicationBundle.message("arrangement.text.modifier");
case NAME:
return ApplicationBundle.message("arrangement.text.name");
}
return type.toString().toLowerCase();
}
@NotNull
public String getDisplayValue(@NotNull Object value) {
if (value instanceof ArrangementEntryType) {
return myRepresentationManager.getDisplayValue((ArrangementEntryType)value);
}
else if (value instanceof ArrangementModifier) {
return myRepresentationManager.getDisplayValue((ArrangementModifier)value);
}
else if (value instanceof ArrangementGroupingType) {
return myRepresentationManager.getDisplayValue((ArrangementGroupingType)value);
}
else if (value instanceof ArrangementEntryOrderType) {
return myRepresentationManager.getDisplayValue((ArrangementEntryOrderType)value);
}
else {
return value.toString();
}
}
/**
* @param type target condition type
* @return max width in pixels for the condition value of the given type if any;
* <code>'-1'</code> as an indication that no max width limit exists for the condition value of the given type
*/
public int getMaxWidth(@NotNull ArrangementSettingType type) {
if (type == ArrangementSettingType.NAME) {
return -1;
}
return myMaxWidths.get(type);
}
public int getMaxWidth(@NotNull ArrangementEntryOrderType... orderTypes) {
SimpleColoredComponent renderer = new SimpleColoredComponent();
int result = 0;
for (ArrangementEntryOrderType type : orderTypes) {
renderer.clear();
TextAttributes attributes = myColorsProvider.getTextAttributes(ArrangementSettingType.ORDER, true);
renderer.append(getDisplayValue(type), SimpleTextAttributes.fromTextAttributes(attributes));
result = Math.max(result, renderer.getPreferredSize().width);
renderer.clear();
attributes = myColorsProvider.getTextAttributes(ArrangementSettingType.ORDER, false);
renderer.append(getDisplayValue(type), SimpleTextAttributes.fromTextAttributes(attributes));
result = Math.max(result, renderer.getPreferredSize().width);
}
return result;
}
/**
* Asks current manager to sort in-place given arrangement condition ids ('field', 'class', 'method', 'public', 'static', 'final' etc).
*
* @param ids target ids to use
* @param <T> id type
* @return sorted ids to use (the given list)
*/
@NotNull
public <T> List<T> sort(@NotNull Collection<T> ids) {
return myRepresentationManager.sort(ids);
}
}
@@ -32,13 +32,12 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import com.intellij.psi.codeStyle.arrangement.settings.DefaultArrangementSettingsRepresentationManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;
@@ -78,17 +77,10 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
colorsProvider = new ArrangementColorsProviderImpl(null);
}
ArrangementStandardSettingsRepresentationAware representationManager = DefaultArrangementSettingsRepresentationManager.INSTANCE;
if (mySettingsAware instanceof ArrangementStandardSettingsRepresentationAware) {
representationManager = (ArrangementStandardSettingsRepresentationAware)mySettingsAware;
}
ArrangementStandardSettingsManager settingsManager = new ArrangementStandardSettingsManager(mySettingsAware, colorsProvider);
final ArrangementNodeDisplayManager displayManager = new ArrangementNodeDisplayManager(
mySettingsAware, colorsProvider, representationManager
);
myGroupingRulesPanel = new ArrangementGroupingRulesPanel(displayManager, mySettingsAware);
myMatchingRulesPanel = new ArrangementMatchingRulesPanel(displayManager, colorsProvider, mySettingsAware);
myGroupingRulesPanel = new ArrangementGroupingRulesPanel(settingsManager, colorsProvider);
myMatchingRulesPanel = new ArrangementMatchingRulesPanel(settingsManager, colorsProvider);
myContent.add(myGroupingRulesPanel, new GridBag().coverLine().fillCellHorizontally().weightx(1));
myContent.add(myMatchingRulesPanel, new GridBag().fillCell().weightx(1).weighty(1));
@@ -99,11 +91,6 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
myMatchingRulesPanel.putClientProperty(AnAction.ourClientProperty, ContainerUtilRt.newArrayList(removeRuleAction));
}
@NotNull
protected JPanel getGroupingRulesPanel() {
return myGroupingRulesPanel;
}
@Nullable
@Override
public JComponent getPanel() {
@@ -146,7 +133,11 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
myMatchingRulesPanel.setRules(null);
}
else {
myGroupingRulesPanel.setRules(new ArrayList<ArrangementGroupingRule>(s.getGroupings()));
List<ArrangementGroupingRule> groupings = s.getGroupings();
myGroupingRulesPanel.setVisible(!groupings.isEmpty());
if (!groupings.isEmpty()) {
myGroupingRulesPanel.setRules(ContainerUtilRt.newArrayList(groupings));
}
myMatchingRulesPanel.setRules(copy(s.getRules()));
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesModel;
import com.intellij.openapi.actionSystem.AnAction;
@@ -35,7 +34,7 @@ public abstract class AbstractMoveArrangementRuleAction extends AnAction impleme
@Override
public void update(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
e.getPresentation().setEnabled(false);
return;
@@ -54,7 +53,7 @@ public abstract class AbstractMoveArrangementRuleAction extends AnAction impleme
@Override
public void actionPerformed(AnActionEvent e) {
final ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
final ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesModel;
import com.intellij.application.options.codeStyle.arrangement.match.EmptyArrangementRuleComponent;
@@ -45,7 +44,7 @@ public class AddArrangementRuleAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -37,13 +36,13 @@ public class EditArrangementRuleAction extends AnAction implements DumbAware, To
@Override
public void update(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
e.getPresentation().setEnabled(control != null && control.getSelectedModelRows().size() == 1);
}
@Override
public void actionPerformed(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.group.ArrangementGroupingRulesControl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -37,7 +36,7 @@ public class MoveArrangementGroupingRuleDownAction extends AnAction implements D
@Override
public void update(AnActionEvent e) {
ArrangementGroupingRulesControl control = ArrangementConstants.GROUPING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementGroupingRulesControl control = ArrangementGroupingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
e.getPresentation().setEnabled(false);
return;
@@ -49,7 +48,7 @@ public class MoveArrangementGroupingRuleDownAction extends AnAction implements D
@Override
public void actionPerformed(AnActionEvent e) {
ArrangementGroupingRulesControl control = ArrangementConstants.GROUPING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementGroupingRulesControl control = ArrangementGroupingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.group.ArrangementGroupingRulesControl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -37,7 +36,7 @@ public class MoveArrangementGroupingRuleUpAction extends AnAction implements Dum
@Override
public void update(AnActionEvent e) {
ArrangementGroupingRulesControl control = ArrangementConstants.GROUPING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementGroupingRulesControl control = ArrangementGroupingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
e.getPresentation().setEnabled(false);
return;
@@ -49,7 +48,7 @@ public class MoveArrangementGroupingRuleUpAction extends AnAction implements Dum
@Override
public void actionPerformed(AnActionEvent e) {
ArrangementGroupingRulesControl control = ArrangementConstants.GROUPING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementGroupingRulesControl control = ArrangementGroupingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -15,7 +15,6 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesModel;
import com.intellij.icons.AllIcons;
@@ -38,14 +37,14 @@ public class RemoveArrangementRuleAction extends AnAction {
@Override
public void update(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
e.getPresentation().setEnabled(control != null && !control.getSelectedModelRows().isEmpty());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
e.getPresentation().setEnabled(control != null && !control.isEditing() && !control.getSelectedModelRows().isEmpty());
e.getPresentation().setIcon(SystemInfoRt.isMac ? AllIcons.ToolbarDecorator.Mac.Remove : AllIcons.ToolbarDecorator.Remove);
}
@Override
public void actionPerformed(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
ArrangementMatchingRulesControl control = ArrangementMatchingRulesControl.KEY.getData(e.getDataContext());
if (control == null) {
return;
}
@@ -16,17 +16,16 @@
package com.intellij.application.options.codeStyle.arrangement.color;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementColorsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.ui.GroupedElementsRenderer;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.EnumMap;
import java.util.Map;
/**
@@ -35,34 +34,94 @@ import java.util.Map;
*/
public class ArrangementColorsProviderImpl implements ArrangementColorsProvider {
@NotNull private final Map<ArrangementSettingsToken, TextAttributes> myNormalAttributesCache = ContainerUtilRt.newHashMap();
@NotNull private final Map<ArrangementSettingsToken, TextAttributes> mySelectedAttributesCache = ContainerUtilRt.newHashMap();
@NotNull private final TextAttributes myDefaultNormalAttributes = new TextAttributes();
@NotNull private final TextAttributes myDefaultSelectedAttributes = new TextAttributes();
@NotNull private final Color myDefaultNormalBorderColor;
@NotNull private final Color myDefaultSelectedBorderColor;
@Nullable private final ArrangementColorsAware myColorsAware;
@NotNull private final Map<ArrangementSettingType, TextAttributes> myTextAttributes
= new EnumMap<ArrangementSettingType, TextAttributes>(ArrangementSettingType.class);
@NotNull private final Map<ArrangementSettingType, TextAttributes> mySelectedTextAttributes
= new EnumMap<ArrangementSettingType, TextAttributes>(ArrangementSettingType.class);
@NotNull private Color myBorderColor;
@NotNull private Color mySelectedBorderColor;
@Nullable private Color myCachedNormalBorderColor;
@Nullable private Color myCachedSelectedBorderColor;
public ArrangementColorsProviderImpl(@Nullable ArrangementColorsAware colorsAware) {
myColorsAware = colorsAware;
applyDefaultColors();
if (colorsAware != null) {
applyCustomColors(colorsAware);
// Default settings.
myDefaultNormalAttributes.setForegroundColor(UIUtil.getTreeTextForeground());
myDefaultNormalAttributes.setBackgroundColor(UIUtil.getPanelBackground());
myDefaultSelectedAttributes.setForegroundColor(UIUtil.getTreeSelectionForeground());
myDefaultSelectedAttributes.setBackgroundColor(UIUtil.getTreeSelectionBackground());
myDefaultNormalBorderColor = UIUtil.getBorderColor();
Color selectionBorderColor = UIUtil.getTreeSelectionBorderColor();
if (selectionBorderColor == null) {
selectionBorderColor = GroupedElementsRenderer.SELECTED_FRAME_FOREGROUND;
}
myDefaultSelectedBorderColor = selectionBorderColor;
}
@NotNull
@Override
public Color getBorderColor(boolean selected) {
return selected ? mySelectedBorderColor : myBorderColor;
final Color cached;
if (selected) {
cached = myCachedSelectedBorderColor;
}
else {
cached = myCachedNormalBorderColor;
}
if (cached != null) {
return cached;
}
Color result = null;
if (myColorsAware != null) {
result = myColorsAware.getBorderColor(EditorColorsManager.getInstance().getGlobalScheme(), selected);
}
if (result == null) {
result = selected ? myDefaultSelectedBorderColor : myDefaultNormalBorderColor;
}
if (selected) {
myCachedSelectedBorderColor = result;
}
else {
myCachedNormalBorderColor = result;
}
return result;
}
@NotNull
@Override
public TextAttributes getTextAttributes(@NotNull ArrangementSettingType type, boolean selected) {
return selected ? mySelectedTextAttributes.get(type) : myTextAttributes.get(type);
public TextAttributes getTextAttributes(@NotNull ArrangementSettingsToken token, boolean selected) {
final TextAttributes cached;
if (selected) {
cached = mySelectedAttributesCache.get(token);
}
else {
cached = myNormalAttributesCache.get(token);
}
if (cached != null) {
return cached;
}
TextAttributes result = null;
if (myColorsAware != null) {
result = myColorsAware.getTextAttributes(EditorColorsManager.getInstance().getGlobalScheme(), token, selected);
}
if (result == null) {
result = selected ? myDefaultSelectedAttributes : myDefaultNormalAttributes;
}
if (selected) {
mySelectedAttributesCache.put(token, result);
}
else {
myNormalAttributesCache.put(token, result);
}
return result;
}
/**
@@ -72,61 +131,9 @@ public class ArrangementColorsProviderImpl implements ArrangementColorsProvider
* accordingly.
*/
public void refresh() {
if (myColorsAware == null) {
return;
}
myTextAttributes.clear();
mySelectedTextAttributes.clear();
applyDefaultColors();
applyCustomColors(myColorsAware);
}
private void applyDefaultColors() {
TextAttributes normalTextAttributes = new TextAttributes();
normalTextAttributes.setForegroundColor(UIUtil.getTreeTextForeground());
normalTextAttributes.setBackgroundColor(UIUtil.getPanelBackground());
TextAttributes selectedTextAttributes = new TextAttributes();
selectedTextAttributes.setForegroundColor(UIUtil.getTreeSelectionForeground());
selectedTextAttributes.setBackgroundColor(UIUtil.getTreeSelectionBackground());
for (ArrangementSettingType type : ArrangementSettingType.values()) {
myTextAttributes.put(type, normalTextAttributes);
mySelectedTextAttributes.put(type, selectedTextAttributes);
}
myBorderColor = UIUtil.getBorderColor();
Color selectionBorderColor = UIUtil.getTreeSelectionBorderColor();
if (selectionBorderColor == null) {
selectionBorderColor = GroupedElementsRenderer.SELECTED_FRAME_FOREGROUND;
}
mySelectedBorderColor = selectionBorderColor;
}
private void applyCustomColors(@NotNull ArrangementColorsAware colorsAware) {
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
for (ArrangementSettingType type : ArrangementSettingType.values()) {
TextAttributes textAttributes = colorsAware.getTextAttributes(scheme, type, false);
if (textAttributes != null) {
myTextAttributes.put(type, textAttributes);
}
TextAttributes selectedTextAttributes = colorsAware.getTextAttributes(scheme, type, true);
if (selectedTextAttributes != null) {
mySelectedTextAttributes.put(type, selectedTextAttributes);
}
}
Color borderColor = colorsAware.getBorderColor(scheme, false);
if (borderColor != null) {
myBorderColor = borderColor;
}
Color selectedBorderColor = colorsAware.getBorderColor(scheme, true);
if (selectedBorderColor != null) {
mySelectedBorderColor = selectedBorderColor;
if (myColorsAware != null) {
myNormalAttributesCache.clear();
mySelectedAttributesCache.clear();
}
}
}
@@ -0,0 +1,151 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @author Denis Zhdanov
* @since 3/11/13 10:41 AM
*/
public abstract class AbstractArrangementUiComponent implements ArrangementUiComponent {
@NotNull private final NotNullLazyValue<JComponent> myComponent = new NotNullLazyValue<JComponent>() {
@NotNull
@Override
protected JComponent compute() {
JPanel result = new JPanel(new GridBagLayout()) {
@Override
protected void paintComponent(Graphics g) {
Point point = UIUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
}
if (!myEnabled && g instanceof Graphics2D) {
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
}
super.paintComponent(g);
}
@Override
public boolean isFocusOwner() {
Component[] components = getComponents();
if (components != null) {
for (Component component : components) {
if (component.isFocusOwner()) {
return true;
}
}
}
return false;
}
@Override
public boolean requestFocusInWindow() {
if (getComponentCount() > 0) {
return getComponent(0).requestFocusInWindow();
}
else {
return super.requestFocusInWindow();
}
}
};
result.setOpaque(false);
result.add(doGetUiComponent(), new GridBag().fillCell());
return result;
}
};
@Nullable private Listener myListener;
@Nullable private Rectangle myScreenBounds;
private boolean myEnabled = true;
@NotNull
@Override
public final JComponent getUiComponent() {
return myComponent.getValue();
}
protected abstract JComponent doGetUiComponent();
public void setListener(@Nullable Listener listener) {
myListener = listener;
}
@Nullable
@Override
public Rectangle getScreenBounds() {
return myScreenBounds;
}
@Override
public boolean isEnabled() {
return myEnabled;
}
@Override
public void setEnabled(boolean enabled) {
myEnabled = enabled;
}
@Nullable
@Override
public Rectangle onMouseMove(@NotNull MouseEvent event) {
return null;
}
@Override
public void onMouseRelease(@NotNull MouseEvent event) {
}
@Nullable
@Override
public Rectangle onMouseExited() {
return null;
}
@Nullable
@Override
public Rectangle onMouseEntered(@NotNull MouseEvent e) {
return null;
}
protected void fireStateChanged() {
if (myListener != null) {
myListener.stateChanged();
}
}
@Override
public final void reset() {
setEnabled(false);
setSelected(false);
doReset();
}
protected abstract void doReset();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,65 +13,77 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.match;
package com.intellij.application.options.codeStyle.arrangement.component;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchNodeComponentFactory;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.*;
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.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* {@link ArrangementMatchConditionComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}.
* {@link ArrangementUiComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}.
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 10:51 AM
*/
public class ArrangementAndMatchConditionComponent extends JPanel implements ArrangementMatchConditionComponent {
public class ArrangementAndMatchConditionComponent extends JPanel implements ArrangementUiComponent {
@NotNull private final List<ArrangementMatchConditionComponent> myComponents = new ArrayList<ArrangementMatchConditionComponent>();
@NotNull private final List<ArrangementUiComponent> myComponents = ContainerUtilRt.newArrayList();
@NotNull private final ArrangementCompositeMatchCondition mySetting;
@Nullable private Rectangle myScreenBounds;
@Nullable private ArrangementMatchConditionComponent myComponentUnderMouse;
@Nullable private ArrangementUiComponent myComponentUnderMouse;
public ArrangementAndMatchConditionComponent(@NotNull StdArrangementMatchRule rule,
@NotNull ArrangementCompositeMatchCondition setting,
@NotNull ArrangementMatchNodeComponentFactory factory,
@NotNull ArrangementNodeDisplayManager manager)
@NotNull ArrangementStandardSettingsManager manager)
{
mySetting = setting;
setOpaque(false);
setLayout(new GridBagLayout());
final Map<Object, ArrangementMatchCondition> operands = new HashMap<Object, ArrangementMatchCondition>();
final Map<ArrangementSettingsToken, ArrangementMatchCondition> operands = ContainerUtilRt.newHashMap();
ArrangementMatchConditionVisitor visitor = new ArrangementMatchConditionVisitor() {
@Override public void visit(@NotNull ArrangementAtomMatchCondition condition) { operands.put(condition.getValue(), condition); }
@Override public void visit(@NotNull ArrangementCompositeMatchCondition condition) { operands.put(condition, condition); }
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
operands.put(condition.getType(), condition);
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
assert false;
}
};
for (ArrangementMatchCondition operand : setting.getOperands()) {
operand.invite(visitor);
}
List<Object> ordered = manager.sort(operands.keySet());
List<ArrangementSettingsToken> ordered = manager.sort(operands.keySet());
GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.EAST).insets(0, 0, 0, ArrangementConstants.HORIZONTAL_GAP);
for (Object key : ordered) {
for (ArrangementSettingsToken key : ordered) {
ArrangementMatchCondition operand = operands.get(key);
assert operand != null;
ArrangementMatchConditionComponent component = factory.getComponent(operand, rule, true);
ArrangementUiComponent component = factory.getComponent(operand, rule, true);
myComponents.add(component);
JComponent uiComponent = component.getUiComponent();
add(uiComponent, constraints);
@@ -98,7 +110,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
@Override
public void setSelected(boolean selected) {
for (ArrangementMatchConditionComponent component : myComponents) {
for (ArrangementUiComponent component : myComponents) {
component.setSelected(selected);
}
}
@@ -115,7 +127,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
@Override
public void paint(Graphics g) {
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
Point point = UIUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
@@ -126,7 +138,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
@Override
public Rectangle onMouseMove(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementMatchConditionComponent component : myComponents) {
for (ArrangementUiComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds == null || !bounds.contains(location)) {
continue;
@@ -170,7 +182,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
@Override
public void onMouseRelease(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementMatchConditionComponent component : myComponents) {
for (ArrangementUiComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null && bounds.contains(location)) {
component.onMouseRelease(event);
@@ -182,7 +194,7 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
@Override
public Rectangle onMouseEntered(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementMatchConditionComponent component : myComponents) {
for (ArrangementUiComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null && bounds.contains(location)) {
myComponentUnderMouse = component;
@@ -203,6 +215,41 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
return null;
}
@Nullable
@Override
public ArrangementSettingsToken getToken() {
return myComponentUnderMouse == null ? null : myComponentUnderMouse.getToken();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public boolean isSelected() {
return myComponentUnderMouse != null && myComponentUnderMouse.isSelected();
}
@Override
public void reset() {
for (ArrangementUiComponent component : myComponents) {
component.reset();
}
}
@Override
public int getBaselineToUse(int width, int height) {
return -1;
}
@Override
public void setListener(@NotNull Listener listener) {
for (ArrangementUiComponent component : myComponents) {
component.setListener(listener);
}
}
@Override
public String toString() {
return String.format("(%s)", StringUtil.join(myComponents, " and "));
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,52 +13,46 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.match;
package com.intellij.application.options.codeStyle.arrangement.component;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.action.ArrangementRemoveConditionAction;
import com.intellij.application.options.codeStyle.arrangement.animation.ArrangementAnimationPanel;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.application.options.codeStyle.arrangement.util.InsetsPanel;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.RoundedLineBorder;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.Map;
/**
* {@link ArrangementMatchConditionComponent} for {@link ArrangementAtomMatchCondition} representation.
* {@link ArrangementUiComponent} for {@link ArrangementAtomMatchCondition} representation.
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 10:06 AM
*/
public class ArrangementAtomMatchConditionComponent implements ArrangementMatchConditionComponent {
public class ArrangementAtomMatchConditionComponent implements ArrangementUiComponent {
@NotNull private static final Map<ArrangementSettingType, BorderStrategy> BORDER_STRATEGIES = ContainerUtilRt.newHashMap();
static {
BORDER_STRATEGIES.put(ArrangementSettingType.NAME, new NameBorderStrategy());
PredefinedConditionBorderStrategy strategy = new PredefinedConditionBorderStrategy();
BORDER_STRATEGIES.put(ArrangementSettingType.TYPE, strategy);
BORDER_STRATEGIES.put(ArrangementSettingType.MODIFIER, strategy);
}
@NotNull private static final BorderStrategy NAME_BORDER_STRATEGY = new NameBorderStrategy();
@NotNull private static final BorderStrategy PREDEFINED_BORDER_STRATEGY = new PredefinedConditionBorderStrategy();
@NotNull
private final SimpleColoredComponent myTextControl = new SimpleColoredComponent() {
@@ -98,11 +92,13 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
@Nullable private Dimension myTextControlSize;
@Nullable private Rectangle myScreenBounds;
@Nullable private Listener myListener;
private boolean myEnabled = true;
private boolean mySelected;
private boolean myCloseButtonHovered;
public ArrangementAtomMatchConditionComponent(@NotNull ArrangementNodeDisplayManager manager,
public ArrangementAtomMatchConditionComponent(@NotNull ArrangementStandardSettingsManager manager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementAtomMatchCondition condition,
@Nullable Consumer<ArrangementAtomMatchConditionComponent> closeCallback)
@@ -110,12 +106,17 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
myColorsProvider = colorsProvider;
myCondition = condition;
myCloseCallback = closeCallback;
myBorderStrategy = BORDER_STRATEGIES.get(condition.getType());
myText = manager.getDisplayValue(condition);
myBorderStrategy = StdArrangementTokens.General.NAME.equals(condition.getType()) ? NAME_BORDER_STRATEGY : PREDEFINED_BORDER_STRATEGY;
if (condition.getType().equals(condition.getValue())) {
myText = condition.getType().getRepresentationValue();
}
else {
myText = condition.getValue().toString();
}
myTextControl.setTextAlign(SwingConstants.CENTER);
myTextControl.append(myText, SimpleTextAttributes.fromTextAttributes(colorsProvider.getTextAttributes(condition.getType(), false)));
myTextControl.setOpaque(false);
int maxWidth = manager.getMaxWidth(condition.getType());
int maxWidth = manager.getWidth(condition.getType());
if (maxWidth > 0) {
myTextControlSize = new Dimension(maxWidth, myTextControl.getPreferredSize().height);
}
@@ -195,7 +196,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
myAnimationPanel = new ArrangementAnimationPanel(roundBorderPanel, false, true) {
@Override
public void paint(Graphics g) {
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
Point point = UIUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = myAnimationPanel.getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
@@ -237,11 +238,16 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
* @param selected flag that indicates if current component should be drawn as 'selected'
*/
public void setSelected(boolean selected) {
boolean notifyListener = selected != mySelected;
mySelected = selected;
myTextControl.clear();
TextAttributes attributes = myColorsProvider.getTextAttributes(myCondition.getType(), selected);
myTextControl.append(myText, SimpleTextAttributes.fromTextAttributes(attributes));
myBorder.setColor(myColorsProvider.getBorderColor(selected));
myBackgroundColor = attributes.getBackgroundColor();
if (notifyListener && myListener != null) {
myListener.stateChanged();
}
}
public boolean isEnabled() {
@@ -255,7 +261,9 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
*/
public void setEnabled(boolean enabled) {
myEnabled = enabled;
setSelected(false);
if (!enabled) {
setSelected(false);
}
}
@Nullable
@@ -322,7 +330,39 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC
public String toString() {
return myText;
}
@NotNull
@Override
public ArrangementSettingsToken getToken() {
return myCondition.getType();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public boolean isSelected() {
return mySelected;
}
@Override
public void reset() {
setSelected(false);
}
@Override
public int getBaselineToUse(int width, int height) {
return -1;
}
@SuppressWarnings("NullableProblems")
@Override
public void setListener(@NotNull Listener listener) {
myListener = listener;
}
private interface BorderStrategy {
RoundedLineBorder create();
void setup(@NotNull Graphics2D g);
@@ -0,0 +1,124 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author Denis Zhdanov
* @since 3/11/13 10:25 AM
*/
public class ArrangementCheckBoxUiComponent extends AbstractArrangementUiComponent {
@NotNull private final JPanel myComponent = new JPanel(new GridBagLayout());
@NotNull private final ArrangementAtomMatchCondition myCondition;
@NotNull private final JBCheckBox myCheckBox;
@NotNull private final JLabel myTextLabel;
public ArrangementCheckBoxUiComponent(@NotNull ArrangementSettingsToken token) {
myComponent.setOpaque(false);
myCondition = new ArrangementAtomMatchCondition(token);
myCheckBox = new JBCheckBox();
myCheckBox.setOpaque(false);
myTextLabel = new JLabel(token.getRepresentationValue());
myCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
myTextLabel.setEnabled(myCheckBox.isEnabled());
fireStateChanged();
}
});
myTextLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
myCheckBox.setSelected(!myCheckBox.isSelected());
}
});
myComponent.add(myCheckBox, new GridBag().anchor(GridBagConstraints.WEST).insets(0, 0, 0, 2));
myComponent.add(myTextLabel, new GridBag().anchor(GridBagConstraints.WEST).insets(0, 0, 0, ArrangementConstants.HORIZONTAL_GAP));
}
@NotNull
@Override
public ArrangementSettingsToken getToken() {
return myCondition.getType();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws UnsupportedOperationException {
if (!getToken().equals(data)) {
throw new UnsupportedOperationException(String.format(
"Can't choose '%s' data at the check box token with data '%s'", data, getToken()
));
}
}
@NotNull
@Override
public ArrangementMatchCondition getMatchCondition() {
return myCondition;
}
@Override
protected JComponent doGetUiComponent() {
return myComponent;
}
@Override
protected void doReset() {
}
@Override
public boolean isEnabled() {
return myCheckBox.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
myCheckBox.setEnabled(enabled);
}
@Override
public boolean isSelected() {
return myCheckBox.isSelected();
}
@Override
public void setSelected(boolean selected) {
myCheckBox.setSelected(selected);
}
@Override
public int getBaselineToUse(int width, int height) {
return myTextLabel.getBaseline(width, height);
}
}
@@ -0,0 +1,125 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @author Denis Zhdanov
* @since 3/11/13 11:56 AM
*/
public class ArrangementComboBoxUiComponent extends AbstractArrangementUiComponent {
@NotNull private final JComboBox myComboBox;
@SuppressWarnings("unchecked")
public ArrangementComboBoxUiComponent(@NotNull List<ArrangementSettingsToken> tokens) {
ArrangementSettingsToken[] tokensArray = tokens.toArray(new ArrangementSettingsToken[tokens.size()]);
Arrays.sort(tokensArray, new Comparator<ArrangementSettingsToken>() {
@Override
public int compare(ArrangementSettingsToken t1, ArrangementSettingsToken t2) {
return t1.getRepresentationValue().compareTo(t2.getRepresentationValue());
}
});
myComboBox = new JComboBox(tokensArray);
myComboBox.setRenderer(new ListCellRendererWrapper() {
@Override
public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
setText(((ArrangementSettingsToken)value).getRepresentationValue());
}
});
myComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
fireStateChanged();
}
}
});
int minWidth = 0;
ListCellRenderer renderer = myComboBox.getRenderer();
JBList dummyList = new JBList();
for (int i = 0, max = myComboBox.getItemCount(); i < max; i++) {
Component rendererComponent = renderer.getListCellRendererComponent(dummyList, myComboBox.getItemAt(i), i, false, true);
minWidth = Math.max(minWidth, rendererComponent.getPreferredSize().width);
}
myComboBox.setPreferredSize(new Dimension(minWidth * 5 / 3, myComboBox.getPreferredSize().height));
}
@NotNull
@Override
public ArrangementSettingsToken getToken() {
return (ArrangementSettingsToken)myComboBox.getSelectedItem();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException {
myComboBox.setSelectedItem(data);
}
@NotNull
@Override
public ArrangementMatchCondition getMatchCondition() {
ArrangementSettingsToken token = getToken();
return new ArrangementAtomMatchCondition(token, token);
}
@Override
protected JComponent doGetUiComponent() {
return myComboBox;
}
@Override
public boolean isSelected() {
return true;
}
@Override
public void setSelected(boolean selected) {
}
@Override
public boolean isEnabled() {
return myComboBox.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
myComboBox.setEnabled(enabled);
}
@Override
protected void doReset() {
}
@Override
public int getBaselineToUse(int width, int height) {
return -1;
}
}
@@ -0,0 +1,87 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Denis Zhdanov
* @since 3/12/13 11:09 AM
*/
public class ArrangementLabelUiComponent extends AbstractArrangementUiComponent {
@NotNull private final ArrangementAtomMatchCondition myCondition;
@NotNull private final JLabel myLabel;
public ArrangementLabelUiComponent(@NotNull ArrangementSettingsToken token) {
myCondition = new ArrangementAtomMatchCondition(token);
myLabel = new JLabel(token.getRepresentationValue());
}
@NotNull
@Override
public ArrangementSettingsToken getToken() {
return myCondition.getType();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public ArrangementMatchCondition getMatchCondition() {
return myCondition;
}
@Override
protected JComponent doGetUiComponent() {
return myLabel;
}
@Override
public boolean isSelected() {
return true;
}
@Override
public void setSelected(boolean selected) {
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public void setEnabled(boolean enabled) {
}
@Override
protected void doReset() {
}
@Override
public int getBaselineToUse(int width, int height) {
return myLabel.getBaseline(width, height);
}
}
@@ -0,0 +1,123 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* @author Denis Zhdanov
* @since 3/12/13 11:18 AM
*/
public class ArrangementTextFieldUiComponent extends AbstractArrangementUiComponent {
@NotNull private final JBTextField myTextField = new JBTextField(20);
@NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@NotNull private final ArrangementSettingsToken myToken;
public ArrangementTextFieldUiComponent(@NotNull ArrangementSettingsToken token) {
myToken = token;
myTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
scheduleUpdate();
}
@Override
public void removeUpdate(DocumentEvent e) {
scheduleUpdate();
}
@Override
public void changedUpdate(DocumentEvent e) {
scheduleUpdate();
}
});
}
private void scheduleUpdate() {
myAlarm.cancelAllRequests();
myAlarm.addRequest(new Runnable() {
@Override
public void run() {
fireStateChanged();
}
}, ArrangementConstants.TEXT_UPDATE_DELAY_MILLIS);
}
@NotNull
@Override
public ArrangementSettingsToken getToken() {
return myToken;
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public ArrangementMatchCondition getMatchCondition() {
String text = myTextField.getText();
return new ArrangementAtomMatchCondition(myToken, StringUtil.isEmpty(text) ? "" : text.trim());
}
@Override
protected JComponent doGetUiComponent() {
return myTextField;
}
@Override
public boolean isSelected() {
return !StringUtil.isEmpty(myTextField.getText());
}
@Override
public void setSelected(boolean selected) {
}
@Override
public boolean isEnabled() {
return myTextField.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
myTextField.setEnabled(enabled);
}
@Override
public void doReset() {
myTextField.setText("");
}
@Override
public int getBaselineToUse(int width, int height) {
return myTextField.getBaseline(width, height);
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2000-2013 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.component;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokenUiRole;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Denis Zhdanov
* @since 3/12/13 2:23 PM
*/
public class DefaultArrangementUiComponentFactory implements ArrangementUiComponent.Factory {
@Nullable
@Override
public ArrangementUiComponent build(@NotNull StdArrangementTokenUiRole role,
@NotNull List<ArrangementSettingsToken> tokens,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsManager settingsManager)
{
switch (role) {
case CHECKBOX:
if (tokens.size() != 1) {
throw new IllegalArgumentException("Can't build a checkbox token for elements " + tokens);
}
else {
return new ArrangementCheckBoxUiComponent(tokens.get(0));
}
case COMBO_BOX:
if (tokens.isEmpty()) {
throw new IllegalArgumentException("Can't build a combo box token with empty content");
}
return new ArrangementComboBoxUiComponent(tokens);
case LABEL:
if (tokens.size() != 1) {
throw new IllegalArgumentException("Can't build a label token for elements " + tokens);
}
return new ArrangementLabelUiComponent(tokens.get(0));
case TEXT_FIELD:
if (tokens.size() != 1) {
throw new IllegalArgumentException("Can't build a text field token for elements " + tokens);
}
return new ArrangementTextFieldUiComponent(tokens.get(0));
case BULB:
if (tokens.size() != 1) {
throw new IllegalArgumentException("Can't build a bulb token for elements " + tokens);
}
return new ArrangementAtomMatchConditionComponent(
settingsManager, colorsProvider, new ArrangementAtomMatchCondition(tokens.get(0)), null
);
}
return null;
}
}
@@ -16,15 +16,14 @@
package com.intellij.application.options.codeStyle.arrangement.group;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementRuleIndexControl;
import com.intellij.application.options.codeStyle.arrangement.util.InsetsPanel;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -32,11 +31,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author Denis Zhdanov
@@ -44,18 +40,44 @@ import java.util.Collection;
*/
public class ArrangementGroupingComponent extends JPanel implements ArrangementRepresentationAware, ArrangementEditorAware {
@NotNull private final ArrangementGroupingType myGroupingType;
@NotNull private final ArrangementUiComponent myGroupingTypeToken;
@NotNull private final ArrangementRuleIndexControl myRowIndexControl;
@NotNull private final JBCheckBox myCheckedBox;
@NotNull private final JLabel myGroupingTypeLabel;
@Nullable private final JComboBox myOrderTypeBox;
@Nullable private final ArrangementUiComponent myOrderTypeToken;
public ArrangementGroupingComponent(@NotNull final ArrangementNodeDisplayManager displayManager,
@NotNull ArrangementGroupingType groupingType,
@NotNull Collection<ArrangementEntryOrderType> availableOrderTypes)
/**
* Assumes that given token {@link CompositeArrangementSettingsToken#getChildren() has no children} or all its children have
* the {@link CompositeArrangementSettingsToken#getRole() same UI role}.
* <p/>
* Lays out given token (and its children if any) in a single row.
*
* @param token base token which serves as a grouping rule model
* @param colorsProvider colors provider
*
* @throws IllegalArgumentException if invariant described above is not satisfied
*/
public ArrangementGroupingComponent(@NotNull CompositeArrangementSettingsToken token,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsManager settingsManager)
throws IllegalArgumentException
{
myGroupingType = groupingType;
List<ArrangementSettingsToken> children = ContainerUtilRt.newArrayList();
StdArrangementTokenUiRole childRole = null;
for (CompositeArrangementSettingsToken child : token.getChildren()) {
if (childRole == null) {
childRole = child.getRole();
children.add(child.getToken());
}
else if (!childRole.equals(child.getRole())) {
throw new IllegalArgumentException(String.format(
"Can't build a grouping component for token '%s'. Reason: its children has different UI roles (%s and %s)",
token, childRole, child.getRole()
));
}
else {
children.add(child.getToken());
}
}
FontMetrics metrics = getFontMetrics(getFont());
int maxWidth = 0;
@@ -66,32 +88,20 @@ public class ArrangementGroupingComponent extends JPanel implements ArrangementR
int diameter = Math.max(maxWidth, height) * 5 / 3;
myRowIndexControl = new ArrangementRuleIndexControl(diameter, height);
myCheckedBox = new JBCheckBox();
myCheckedBox.setOpaque(false);
myCheckedBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
refreshControl();
}
});
myGroupingTypeLabel = new JLabel(displayManager.getDisplayValue(groupingType));
myGroupingTypeLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
myCheckedBox.setSelected(!myCheckedBox.isSelected());
}
});
myGroupingTypeToken = ArrangementUtil.buildUiComponent(
token.getRole(), Collections.singletonList(token.getToken()), colorsProvider, settingsManager
);
if (availableOrderTypes.isEmpty()) {
myOrderTypeBox = null;
if (children.size() <= 0) {
myOrderTypeToken = null;
}
else {
myOrderTypeBox = new JComboBox(availableOrderTypes.toArray());
myOrderTypeBox.setRenderer(new ListCellRenderer() {
assert childRole != null;
myOrderTypeToken = ArrangementUtil.buildUiComponent(childRole, children, colorsProvider, settingsManager);
myGroupingTypeToken.setListener(new ArrangementUiComponent.Listener() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
return new JLabel(displayManager.getDisplayValue(value));
public void stateChanged() {
myOrderTypeToken.setEnabled(myGroupingTypeToken.isEnabled());
}
});
}
@@ -105,17 +115,9 @@ public class ArrangementGroupingComponent extends JPanel implements ArrangementR
new GridBag().anchor(GridBagConstraints.CENTER)
.insets(0, ArrangementConstants.HORIZONTAL_PADDING, 0, ArrangementConstants.HORIZONTAL_GAP * 2)
);
add(myCheckedBox, new GridBag().anchor(GridBagConstraints.WEST).insets(0, 0, 0, 2));
add(myGroupingTypeLabel, new GridBag().anchor(GridBagConstraints.WEST).insets(0, 0, 0, ArrangementConstants.HORIZONTAL_GAP));
if (myOrderTypeBox != null) {
int minWidth = 0;
ListCellRenderer renderer = myOrderTypeBox.getRenderer();
for (int i = 0, max = myOrderTypeBox.getItemCount(); i < max; i++) {
Component rendererComponent = renderer.getListCellRendererComponent(null, myOrderTypeBox.getItemAt(i), i, false, true);
minWidth = Math.max(minWidth, rendererComponent.getPreferredSize().width);
}
myOrderTypeBox.setPreferredSize(new Dimension(minWidth * 5 / 3, myOrderTypeBox.getPreferredSize().height));
add(myOrderTypeBox, new GridBag().anchor(GridBagConstraints.WEST));
add(myGroupingTypeToken.getUiComponent(), new GridBag().anchor(GridBagConstraints.WEST).insets(0, 0, 0, 2));
if (myOrderTypeToken != null) {
add(myOrderTypeToken.getUiComponent(), new GridBag().anchor(GridBagConstraints.WEST));
}
add(new JLabel(" "), new GridBag().weightx(1).fillCellHorizontally());
@@ -127,9 +129,11 @@ public class ArrangementGroupingComponent extends JPanel implements ArrangementR
protected void paintComponent(Graphics g) {
Dimension size = getSize();
if (size != null) {
int baseline = myGroupingTypeLabel.getBaseline(size.width, size.height);
baseline -= myRowIndexControl.getBounds().y;
myRowIndexControl.setBaseLine(baseline);
int baseline = myGroupingTypeToken.getBaselineToUse(size.width, size.height);
if (baseline > 0) {
baseline -= myRowIndexControl.getBounds().y;
myRowIndexControl.setBaseLine(baseline);
}
}
super.paintComponent(g);
}
@@ -140,31 +144,32 @@ public class ArrangementGroupingComponent extends JPanel implements ArrangementR
return this;
}
public boolean isChecked() {
return myCheckedBox.isSelected();
public boolean isSelected() {
return myGroupingTypeToken.isSelected();
}
public void setChecked(boolean checked) {
myCheckedBox.setSelected(checked);
public void setSelected(boolean selected) {
myGroupingTypeToken.setSelected(selected);
refreshControl();
}
private void refreshControl() {
boolean checked = isChecked();
myGroupingTypeLabel.setEnabled(checked);
if (myOrderTypeBox != null) {
myOrderTypeBox.setEnabled(checked);
boolean checked = isSelected();
if (myOrderTypeToken != null) {
myOrderTypeToken.setEnabled(checked);
}
}
@NotNull
public ArrangementGroupingType getGroupingType() {
return myGroupingType;
public ArrangementSettingsToken getGroupingType() {
ArrangementSettingsToken token = myGroupingTypeToken.getToken();
assert token != null;
return token;
}
public void setOrderType(@NotNull ArrangementEntryOrderType type) {
if (myOrderTypeBox != null) {
myOrderTypeBox.setSelectedItem(type);
public void setOrderType(@NotNull ArrangementSettingsToken type) {
if (myOrderTypeToken != null) {
myOrderTypeToken.chooseToken(type);
}
}
@@ -177,12 +182,12 @@ public class ArrangementGroupingComponent extends JPanel implements ArrangementR
}
@Nullable
public ArrangementEntryOrderType getOrderType() {
return myOrderTypeBox == null ? null : (ArrangementEntryOrderType)myOrderTypeBox.getSelectedItem();
public ArrangementSettingsToken getOrderType() {
return myOrderTypeToken == null ? null : myOrderTypeToken.getToken();
}
@Override
public String toString() {
return myGroupingType.toString();
return myGroupingTypeToken.toString();
}
}
@@ -15,18 +15,18 @@
*/
package com.intellij.application.options.codeStyle.arrangement.group;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementRepresentationAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.CompositeArrangementSettingsToken;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.table.JBTable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.AbstractTableCellEditor;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,8 +35,9 @@ import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Denis Zhdanov
@@ -44,15 +45,19 @@ import java.util.List;
*/
public class ArrangementGroupingRulesControl extends JBTable {
@NotNull private final Map<ArrangementGroupingType, ArrangementGroupingComponent> myComponents
= new EnumMap<ArrangementGroupingType, ArrangementGroupingComponent>(ArrangementGroupingType.class);
@NotNull public static final DataKey<ArrangementGroupingRulesControl> KEY = DataKey.create("Arrangement.Rule.Group.Control");
@NotNull private final Map<ArrangementSettingsToken, ArrangementGroupingComponent> myComponents = ContainerUtilRt.newHashMap();
@NotNull private final ArrangementStandardSettingsManager mySettingsManager;
private int myRowUnderMouse = -1;
public ArrangementGroupingRulesControl(@NotNull ArrangementNodeDisplayManager displayManager,
@NotNull ArrangementStandardSettingsAware settingsFilter)
public ArrangementGroupingRulesControl(@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider)
{
super(new DefaultTableModel(0, 1));
mySettingsManager = settingsManager;
setDefaultRenderer(Object.class, new MyRenderer());
getColumnModel().getColumn(0).setCellEditor(new MyEditor());
setShowColumns(false);
@@ -61,19 +66,13 @@ public class ArrangementGroupingRulesControl extends JBTable {
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
for (ArrangementGroupingType groupingType : ArrangementGroupingType.values()) {
if (!settingsFilter.isEnabled(groupingType, null)) {
continue;
List<CompositeArrangementSettingsToken> groupingTokens = settingsManager.getSupportedGroupingTokens();
if (groupingTokens != null) {
for (CompositeArrangementSettingsToken token : groupingTokens) {
ArrangementGroupingComponent component = new ArrangementGroupingComponent(token, colorsProvider, settingsManager);
myComponents.put(token.getToken(), component);
getModel().addRow(new Object[]{component});
}
List<ArrangementEntryOrderType> orderTypes = new ArrayList<ArrangementEntryOrderType>();
for (ArrangementEntryOrderType orderType : ArrangementEntryOrderType.values()) {
if (settingsFilter.isEnabled(groupingType, orderType)) {
orderTypes.add(orderType);
}
}
ArrangementGroupingComponent component = new ArrangementGroupingComponent(displayManager, groupingType, orderTypes);
myComponents.put(groupingType, component);
getModel().addRow(new Object[]{component});
}
}
@@ -84,9 +83,9 @@ public class ArrangementGroupingRulesControl extends JBTable {
public void setRules(@Nullable List<ArrangementGroupingRule> rules) {
for (ArrangementGroupingComponent component : myComponents.values()) {
component.setChecked(false);
component.setSelected(false);
}
if (rules == null) {
return;
}
@@ -96,15 +95,15 @@ public class ArrangementGroupingRulesControl extends JBTable {
model.removeRow(model.getRowCount() - 1);
}
List<ArrangementGroupingType> types = new ArrayList<ArrangementGroupingType>(myComponents.keySet());
ContainerUtil.sort(types, new MyComparator(rules));
for (ArrangementGroupingType type : types) {
model.addRow(new Object[] { myComponents.get(type) });
List<ArrangementSettingsToken> types = ContainerUtilRt.newArrayList(myComponents.keySet());
types = mySettingsManager.sort(types);
for (ArrangementSettingsToken type : types) {
model.addRow(new Object[]{myComponents.get(type)});
}
for (ArrangementGroupingRule rule : rules) {
ArrangementGroupingComponent component = myComponents.get(rule.getGroupingType());
component.setChecked(true);
ArrangementEntryOrderType orderType = rule.getOrderType();
component.setSelected(true);
ArrangementSettingsToken orderType = rule.getOrderType();
component.setOrderType(orderType);
}
}
@@ -115,10 +114,10 @@ public class ArrangementGroupingRulesControl extends JBTable {
DefaultTableModel model = getModel();
for (int i = 0, max = model.getRowCount(); i < max; i++) {
ArrangementGroupingComponent component = (ArrangementGroupingComponent)model.getValueAt(i, 0);
if (!component.isChecked()) {
if (!component.isSelected()) {
continue;
}
ArrangementEntryOrderType orderType = component.getOrderType();
ArrangementSettingsToken orderType = component.getOrderType();
if (orderType == null) {
result.add(new ArrangementGroupingRule(component.getGroupingType()));
}
@@ -154,6 +153,7 @@ public class ArrangementGroupingRulesControl extends JBTable {
super.processMouseEvent(e);
}
@SuppressWarnings("ConstantConditions")
private class MyRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@@ -170,6 +170,7 @@ public class ArrangementGroupingRulesControl extends JBTable {
}
}
@SuppressWarnings("ConstantConditions")
private static class MyEditor extends AbstractTableCellEditor {
@Nullable Object myValue;
@@ -195,30 +196,4 @@ public class ArrangementGroupingRulesControl extends JBTable {
return true;
}
}
private static class MyComparator implements Comparator<ArrangementGroupingType> {
@NotNull private final TObjectIntHashMap<ArrangementGroupingType> myWeights = new TObjectIntHashMap<ArrangementGroupingType>();
MyComparator(@NotNull List<ArrangementGroupingRule> list) {
int weight = 0;
for (ArrangementGroupingRule rule : list) {
myWeights.put(rule.getGroupingType(), weight++);
}
}
@Override
public int compare(ArrangementGroupingType t1, ArrangementGroupingType t2) {
if (myWeights.containsKey(t1) && myWeights.containsKey(t2)) {
return myWeights.get(t1) - myWeights.get(t2);
}
else if (myWeights.containsKey(t1)) {
return -1;
}
else if (myWeights.containsKey(t2)) {
return 1;
}
return 0;
}
}
}
@@ -16,12 +16,12 @@
package com.intellij.application.options.codeStyle.arrangement.group;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.TitleWithToolbar;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -39,12 +39,12 @@ public class ArrangementGroupingRulesPanel extends JPanel implements DataProvide
@NotNull private final ArrangementGroupingRulesControl myControl;
public ArrangementGroupingRulesPanel(@NotNull ArrangementNodeDisplayManager displayManager,
@NotNull ArrangementStandardSettingsAware settingsFilter)
public ArrangementGroupingRulesPanel(@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider)
{
super(new GridBagLayout());
myControl = new ArrangementGroupingRulesControl(displayManager, settingsFilter);
myControl = new ArrangementGroupingRulesControl(settingsManager, colorsProvider);
TitleWithToolbar top = new TitleWithToolbar(
ApplicationBundle.message("arrangement.settings.section.groups"),
@@ -69,7 +69,7 @@ public class ArrangementGroupingRulesPanel extends JPanel implements DataProvide
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (ArrangementConstants.GROUPING_RULES_CONTROL_KEY.is(dataId)) {
if (ArrangementGroupingRulesControl.KEY.is(dataId)) {
return myControl;
}
return null;
@@ -16,11 +16,8 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.animation.ArrangementAnimationManager;
import com.intellij.application.options.codeStyle.arrangement.animation.ArrangementAnimationPanel;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRuleEditor;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.util.CalloutBorder;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -1,120 +0,0 @@
/*
* Copyright 2000-2012 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.util.ArrangementConfigUtil;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @author Denis Zhdanov
* @since 9/12/12 5:39 PM
*/
public class ArrangementGroupingMatchConditionComponent extends JPanel implements ArrangementMatchConditionComponent {
private static final int TOP_INSET = 3;
@NotNull private final ArrangementAtomMatchCondition myCondition;
@Nullable private Rectangle myScreenBounds;
@NotNull private Dimension myPreferredSize;
public ArrangementGroupingMatchConditionComponent(@NotNull ArrangementNodeDisplayManager manager,
@NotNull ArrangementAtomMatchCondition condition)
{
myCondition = condition;
String text = StringUtil.capitalize(StringUtil.pluralize(manager.getDisplayValue(myCondition.getValue())));
setLayout(new GridBagLayout());
GridBag constraints = new GridBag().anchor(GridBagConstraints.WEST).weightx(1).insets(TOP_INSET * 2, 20, 0, 0);
add(new JLabel(String.format("<html><i>%s", text)), constraints);
myPreferredSize = super.getPreferredSize();
}
@NotNull
@Override
public ArrangementMatchCondition getMatchCondition() {
return myCondition;
}
@NotNull
@Override
public JComponent getUiComponent() {
return this;
}
@Nullable
@Override
public Rectangle getScreenBounds() {
return myScreenBounds;
}
@NotNull
@Override
public Dimension getPreferredSize() {
return myPreferredSize;
}
@Override
public void setSelected(boolean selected) {
}
@Nullable
@Override
public Rectangle onMouseMove(@NotNull MouseEvent event) {
return null;
}
@Override
public void onMouseRelease(@NotNull MouseEvent event) {
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle bounds = getBounds();
g.setColor(UIManager.getColor("Tree.hash"));
int cornerX = UIUtil.getTreeLeftChildIndent();
int y = TOP_INSET;
g.drawLine(cornerX, y, bounds.width, y);
g.drawLine(cornerX, y, cornerX, y + bounds.height);
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
if (point != null) {
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
}
}
@Override
public Rectangle onMouseEntered(@NotNull MouseEvent e) {
return null;
}
@Nullable
@Override
public Rectangle onMouseExited() {
return null;
}
}
@@ -16,15 +16,21 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.animation.ArrangementAnimationManager;
import com.intellij.application.options.codeStyle.arrangement.animation.ArrangementAnimationPanel;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementAndMatchConditionComponent;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementAtomMatchConditionComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.*;
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.ArrangementUiComponent;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
@@ -38,15 +44,15 @@ public class ArrangementMatchNodeComponentFactory {
private static final Logger LOG = Logger.getInstance("#" + ArrangementMatchNodeComponentFactory.class.getName());
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final ArrangementMatchingRulesControl myList;
@NotNull private final ArrangementStandardSettingsManager mySettingsManager;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final ArrangementMatchingRulesControl myList;
public ArrangementMatchNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager,
public ArrangementMatchNodeComponentFactory(@NotNull ArrangementStandardSettingsManager manager,
@NotNull ArrangementColorsProvider provider,
@NotNull ArrangementMatchingRulesControl list)
{
myDisplayManager = manager;
mySettingsManager = manager;
myColorsProvider = provider;
myList = list;
}
@@ -61,24 +67,24 @@ public class ArrangementMatchNodeComponentFactory {
* @return renderer for the given model
*/
@NotNull
public ArrangementMatchConditionComponent getComponent(@NotNull final ArrangementMatchCondition rendererTarget,
@NotNull final StdArrangementMatchRule rule,
final boolean allowModification)
public ArrangementUiComponent getComponent(@NotNull final ArrangementMatchCondition rendererTarget,
@NotNull final StdArrangementMatchRule rule,
final boolean allowModification)
{
final Ref<ArrangementMatchConditionComponent> ref = new Ref<ArrangementMatchConditionComponent>();
final Ref<ArrangementUiComponent> ref = new Ref<ArrangementUiComponent>();
rendererTarget.invite(new ArrangementMatchConditionVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
RemoveAtomConditionCallback callback = allowModification ? new RemoveAtomConditionCallback(rule) : null;
ArrangementMatchConditionComponent component = new ArrangementAtomMatchConditionComponent(
myDisplayManager, myColorsProvider, condition, callback
ArrangementUiComponent component = new ArrangementAtomMatchConditionComponent(
mySettingsManager, myColorsProvider, condition, callback
);
ref.set(component);
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
ref.set(new ArrangementAndMatchConditionComponent(rule, condition, ArrangementMatchNodeComponentFactory.this, myDisplayManager));
ref.set(new ArrangementAndMatchConditionComponent(rule, condition, ArrangementMatchNodeComponentFactory.this, mySettingsManager));
}
});
return ref.get();
@@ -16,34 +16,25 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.ArrangementRuleInfo;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.Alarm;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.MultiRowFlowPanel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@@ -58,148 +49,184 @@ import java.util.List;
* @author Denis Zhdanov
* @since 8/14/12 9:54 AM
*/
public class ArrangementMatchingRuleEditor extends JPanel {
public class ArrangementMatchingRuleEditor extends JPanel implements ArrangementUiComponent.Listener {
@NotNull private final Map<Object, ArrangementAtomMatchConditionComponent> myConditionComponents = ContainerUtilRt.newHashMap();
@NotNull private final List<MultiRowFlowPanel> myRows = ContainerUtilRt.newArrayList();
@NotNull private final Map<ArrangementSettingsToken, ArrangementUiComponent> myComponents = ContainerUtilRt.newHashMap();
@NotNull private final List<MultiRowFlowPanel> myRows = ContainerUtilRt.newArrayList();
@NotNull private final Map<ArrangementEntryOrderType, ArrangementOrderTypeComponent> myOrderTypeComponents
= new EnumMap<ArrangementEntryOrderType, ArrangementOrderTypeComponent>(ArrangementEntryOrderType.class);
@NotNull private final ArrangementRuleInfo myRuleInfo = new ArrangementRuleInfo();
@NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@NotNull private final JBTextField myNameField = new JBTextField(20);
@NotNull private final ArrangementMatchingRulesControl myControl;
@NotNull private final ArrangementStandardSettingsAware myFilter;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final ArrangementMatchingRulesControl myControl;
@NotNull private final ArrangementStandardSettingsManager mySettingsManager;
@NotNull private final ArrangementColorsProvider myColorsProvider;
private int myRow = -1;
private int myLabelWidth;
private boolean myRequestFocus;
private int myLabelWidth;
@Nullable private JComponent myDefaultFocusRequestor;
@Nullable private JComponent myFocusRequestor;
private boolean mySkipStateChange;
public ArrangementMatchingRuleEditor(@NotNull ArrangementStandardSettingsAware filter,
@NotNull ArrangementColorsProvider provider,
@NotNull ArrangementNodeDisplayManager displayManager,
public ArrangementMatchingRuleEditor(@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementMatchingRulesControl control)
{
myFilter = filter;
myColorsProvider = provider;
mySettingsManager = settingsManager;
myColorsProvider = colorsProvider;
myControl = control;
init(displayManager);
init(settingsManager);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
onMouseClicked(e);
}
});
myNameField.getDocument().addDocumentListener(new DocumentListener() {
@Override public void insertUpdate(DocumentEvent e) { scheduleNameUpdate(); }
@Override public void removeUpdate(DocumentEvent e) { scheduleNameUpdate(); }
@Override public void changedUpdate(DocumentEvent e) { scheduleNameUpdate(); }
});
}
private void init(@NotNull ArrangementNodeDisplayManager displayManager) {
private void init(@NotNull ArrangementStandardSettingsManager settingsManager) {
setLayout(new GridBagLayout());
setBorder(IdeBorderFactory.createEmptyBorder(5));
Map<ArrangementSettingType, Set<?>> supportedSettings = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager);
addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager);
addNameFilterIfPossible();
addOrderRowIfPossible(displayManager);
List<CompositeArrangementSettingsToken> tokens = settingsManager.getSupportedMatchingTokens();
if (tokens != null) {
for (CompositeArrangementSettingsToken token : tokens) {
addToken(token);
}
}
applyBackground(UIUtil.getListBackground());
}
private void addRowIfPossible(@NotNull ArrangementSettingType key,
@NotNull Map<ArrangementSettingType, Set<?>> supportedSettings,
@NotNull ArrangementNodeDisplayManager manager)
{
Set<?> values = supportedSettings.get(key);
if (values == null || values.isEmpty()) {
return;
}
MultiRowFlowPanel valuesPanel = newRow(manager.getDisplayLabel(key));
for (Object value : manager.sort(values)) {
ArrangementAtomMatchConditionComponent component =
new ArrangementAtomMatchConditionComponent(manager, myColorsProvider, new ArrangementAtomMatchCondition(key, value), null);
myConditionComponents.put(value, component);
valuesPanel.add(component.getUiComponent());
}
}
private void addNameFilterIfPossible() {
if (!myFilter.isNameFilterSupported()) {
return;
}
MultiRowFlowPanel panel = newRow(ApplicationBundle.message("arrangement.text.name"));
panel.add(myNameField);
}
private void addOrderRowIfPossible(@NotNull ArrangementNodeDisplayManager displayManager) {
if (!myFilter.isNameFilterSupported()) {
return;
}
MultiRowFlowPanel panel = newRow(ApplicationBundle.message("arrangement.order.name"));
ArrangementEntryOrderType[] orderTypes = { ArrangementEntryOrderType.KEEP, ArrangementEntryOrderType.BY_NAME };
int maxWidth = displayManager.getMaxWidth(orderTypes);
for (ArrangementEntryOrderType type : orderTypes) {
ArrangementOrderTypeComponent component = new ArrangementOrderTypeComponent(type, displayManager, myColorsProvider, maxWidth);
panel.add(component);
myOrderTypeComponents.put(type, component);
}
}
private MultiRowFlowPanel newRow(@NotNull String rowLabel) {
MultiRowFlowPanel result = new MultiRowFlowPanel(
private void addToken(@NotNull CompositeArrangementSettingsToken rowToken) {
List<CompositeArrangementSettingsToken> tokens = ArrangementUtil.flatten(rowToken);
GridBag labelConstraints = new GridBag().anchor(GridBagConstraints.NORTHWEST).insets(ArrangementConstants.VERTICAL_PADDING, 0, 0, 0);
MultiRowFlowPanel panel = new MultiRowFlowPanel(
FlowLayout.LEFT, ArrangementConstants.HORIZONTAL_GAP, ArrangementConstants.VERTICAL_GAP
);
JLabel label = new JLabel(rowLabel + ":");
add(label, new GridBag().anchor(GridBagConstraints.NORTHWEST).insets(ArrangementConstants.VERTICAL_PADDING, 0, 0, 0));
myLabelWidth = Math.max(myLabelWidth, label.getPreferredSize().width);
add(result, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine());
myRows.add(result);
return result;
}
private void scheduleNameUpdate() {
myAlarm.cancelAllRequests();
myAlarm.addRequest(new Runnable() {
@Override
public void run() {
updateName();
List<ArrangementSettingsToken> prevTokens = ContainerUtilRt.newArrayList();
StdArrangementTokenUiRole prevRole = null;
ArrangementUiComponent component;
JComponent uiComponent;
for (CompositeArrangementSettingsToken token : tokens) {
StdArrangementTokenUiRole role = token.getRole();
if (role != prevRole && !prevTokens.isEmpty()) {
component = ArrangementUtil.buildUiComponent(
role, prevTokens, myColorsProvider, mySettingsManager
);
component.setListener(this);
for (ArrangementSettingsToken prevToken : prevTokens) {
myComponents.put(prevToken, component);
}
panel.add(component.getUiComponent());
panel = addRowIfNecessary(panel);
prevRole = null;
prevTokens.clear();
}
}, ArrangementConstants.NAME_CONDITION_UPDATE_DELAY_MILLIS);
component = ArrangementUtil.buildUiComponent(
role, Collections.singletonList(token.getToken()), myColorsProvider, mySettingsManager
);
component.setListener(this);
uiComponent = component.getUiComponent();
switch (role) {
case LABEL:
panel = addRowIfNecessary(panel);
add(uiComponent, labelConstraints);
myLabelWidth = Math.max(myLabelWidth, uiComponent.getPreferredSize().width);
prevRole = null;
break;
case TEXT_FIELD:
panel = addRowIfNecessary(panel);
ArrangementUiComponent textLabel = ArrangementUtil.buildUiComponent(
StdArrangementTokenUiRole.LABEL, Collections.singletonList(token.getToken()), myColorsProvider, mySettingsManager
);
JComponent textLabelComponent = textLabel.getUiComponent();
add(textLabelComponent, labelConstraints);
myLabelWidth = Math.max(myLabelWidth, textLabelComponent.getPreferredSize().width);
panel.add(uiComponent);
panel = addRowIfNecessary(panel);
prevRole = null;
myComponents.put(token.getToken(), component);
if (myDefaultFocusRequestor == null) {
myDefaultFocusRequestor = uiComponent;
}
break;
default:
if (role == StdArrangementTokenUiRole.COMBO_BOX) {
prevTokens.add(token.getToken());
prevRole = role;
break;
}
panel.add(uiComponent);
myComponents.put(token.getToken(), component);
}
}
if (prevRole != null && !prevTokens.isEmpty()) {
component = ArrangementUtil.buildUiComponent(prevRole, prevTokens, myColorsProvider, mySettingsManager);
panel.add(component.getUiComponent());
component.setListener(this);
for (ArrangementSettingsToken prevToken : prevTokens) {
myComponents.put(prevToken, component);
}
}
addRowIfNecessary(panel);
}
private void updateName() {
myAlarm.cancelAllRequests();
if (myRow < 0) {
return;
@NotNull
private MultiRowFlowPanel addRowIfNecessary(@NotNull MultiRowFlowPanel panel) {
if (panel.getComponentCount() <= 0) {
return panel;
}
String namePattern = myNameField.getText();
if (StringUtil.isEmpty(namePattern)) {
namePattern = null;
}
if (Comparing.equal(namePattern, myRuleInfo.getNamePattern())) {
return;
}
myRuleInfo.setNamePattern(namePattern);
apply();
add(panel, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine());
myRows.add(panel);
return new MultiRowFlowPanel(
FlowLayout.LEFT, ArrangementConstants.HORIZONTAL_GAP, ArrangementConstants.VERTICAL_GAP
);
}
@Override
protected void paintComponent(Graphics g) {
if (myRequestFocus) {
if (myNameField.isFocusOwner()) {
myRequestFocus = false;
public void stateChanged() {
if (!mySkipStateChange) {
apply();
}
}
@Nullable
private Pair<ArrangementMatchCondition, ArrangementSettingsToken> buildCondition() {
List<ArrangementMatchCondition> conditions = ContainerUtilRt.newArrayList();
ArrangementSettingsToken orderType = null;
for (ArrangementUiComponent component : myComponents.values()) {
if (!component.isEnabled() || !component.isSelected()) {
continue;
}
ArrangementSettingsToken token = component.getToken();
if (token != null && StdArrangementTokens.Order.is(token)) {
orderType = token;
}
else {
myNameField.requestFocusInWindow();
conditions.add(component.getMatchCondition());
}
}
if (orderType != null && !conditions.isEmpty()) {
return Pair.create(ArrangementUtil.combine(conditions.toArray(new ArrangementMatchCondition[conditions.size()])), orderType);
}
else {
return null;
}
}
@Override
protected void paintComponent(Graphics g) {
if (myFocusRequestor != null) {
if (myFocusRequestor.isFocusOwner()) {
myFocusRequestor = null;
}
else {
myFocusRequestor.requestFocusInWindow();
}
}
super.paintComponent(g);
@@ -213,17 +240,16 @@ public class ArrangementMatchingRuleEditor extends JPanel {
*/
public void reset(int row) {
// Reset state.
myNameField.setText("");
myAlarm.cancelAllRequests();
myRow = row;
myRuleInfo.clear();
myRequestFocus = true;
for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) {
component.setEnabled(false);
component.setSelected(false);
myFocusRequestor = myDefaultFocusRequestor;
mySkipStateChange = true;
try {
for (ArrangementUiComponent component : myComponents.values()) {
component.reset();
}
}
for (ArrangementOrderTypeComponent component : myOrderTypeComponents.values()) {
component.setSelected(false);
finally {
mySkipStateChange = false;
}
ArrangementMatchingRulesModel model = myControl.getModel();
@@ -233,69 +259,69 @@ public class ArrangementMatchingRuleEditor extends JPanel {
}
Object element = model.getElementAt(row);
if (element instanceof EmptyArrangementRuleComponent) {
// Disable conditions which are not applicable for empty rules (e.g. we don't want to enable 'volatile' condition
// for java rearranger if no 'field' condition is selected.
for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) {
ArrangementAtomMatchCondition condition = component.getMatchCondition();
Map<ArrangementSettingType, Set<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
component.setEnabled(map.get(condition.getType()).contains(condition.getValue()));
}
return;
}
if (!(element instanceof StdArrangementMatchRule)) {
return;
}
StdArrangementMatchRule rule = (StdArrangementMatchRule)element;
myRuleInfo.setOrderType(rule.getOrderType());
ArrangementOrderTypeComponent orderTypeComponent = myOrderTypeComponents.get(rule.getOrderType());
if (orderTypeComponent != null) {
orderTypeComponent.setSelected(true);
}
ArrangementMatchCondition condition = rule.getMatcher().getCondition();
ArrangementRuleInfo infoWithConditions = ArrangementUtil.extractConditions(condition);
myRuleInfo.copyConditionsFrom(infoWithConditions);
myNameField.setText(myRuleInfo.getNamePattern());
for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) {
if (myRuleInfo.hasCondition(component.getMatchCondition().getValue())) {
component.setEnabled(true);
component.setSelected(true);
}
}
ArrangementSettingsToken orderType = element instanceof ArrangementMatchRule ? ((ArrangementMatchRule)element).getOrderType() : null;
final ArrangementMatchCondition condition;
final Set<ArrangementSettingsToken> conditionTokens;
refreshConditions();
if (element instanceof EmptyArrangementRuleComponent) {
// We need to disable conditions which are not applicable for empty rules (e.g. we don't want to enable 'volatile' condition
// for java rearranger if no 'field' condition is selected.
condition = null;
conditionTokens = ContainerUtilRt.newHashSet();
}
else if (!(element instanceof StdArrangementMatchRule)) {
return;
}
else {
condition = ((StdArrangementMatchRule)element).getMatcher().getCondition();
conditionTokens = ArrangementUtil.extractTokens(condition);
}
mySkipStateChange = true;
try {
for (ArrangementUiComponent component : myComponents.values()) {
ArrangementSettingsToken token = component.getToken();
if (token != null && (token.equals(orderType) || mySettingsManager.isEnabled(token, condition))) {
component.setEnabled(true);
component.setSelected(conditionTokens.contains(token));
}
}
refreshConditions();
}
finally {
mySkipStateChange = false;
}
}
/**
* Disable conditions not applicable at the current context (e.g. disable 'synchronized' if no 'method' is selected).
*/
private void refreshConditions() {
Map<ArrangementSettingType, Set<?>> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, myRuleInfo.buildCondition());
for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) {
ArrangementAtomMatchCondition c = component.getMatchCondition();
Set<?> s = available.get(c.getType());
if (s == null || !s.contains(c.getValue())) {
if (myRuleInfo.hasCondition(c.getValue())) {
removeCondition(component);
}
else {
component.setEnabled(false);
}
Pair<ArrangementMatchCondition, ArrangementSettingsToken> pair = buildCondition();
ArrangementMatchCondition condition = pair == null ? null : pair.first;
for (ArrangementUiComponent component : myComponents.values()) {
ArrangementSettingsToken token = component.getToken();
if (token == null) {
continue;
}
else if (s.contains(c.getValue()) && !component.isEnabled()) {
component.setEnabled(true);
boolean enabled = mySettingsManager.isEnabled(token, condition);
component.setEnabled(enabled);
if (!enabled) {
component.setSelected(false);
}
}
}
private void apply() {
Object modelValue = myRuleInfo.buildRule();
if (modelValue == null) {
final Pair<ArrangementMatchCondition, ArrangementSettingsToken> pair = buildCondition();
final Object modelValue;
if (pair == null) {
modelValue = new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow));
}
else {
modelValue = new StdArrangementMatchRule(new StdArrangementEntryMatcher(pair.first), pair.second);
}
myControl.getModel().set(myRow, modelValue);
myControl.repaintRows(myRow, myRow, true);
}
@@ -320,13 +346,13 @@ public class ArrangementMatchingRuleEditor extends JPanel {
}
Point locationOnScreen = e.getLocationOnScreen();
for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) {
for (ArrangementUiComponent component : myComponents.values()) {
Rectangle screenBounds = component.getScreenBounds();
if (screenBounds == null || !screenBounds.contains(locationOnScreen)) {
continue;
}
if (component.isEnabled()) {
if (myRuleInfo.hasCondition(component.getMatchCondition().getValue())) {
if (component.isSelected()) {
removeCondition(component);
}
else {
@@ -336,50 +362,37 @@ public class ArrangementMatchingRuleEditor extends JPanel {
apply();
return;
}
for (ArrangementOrderTypeComponent component : myOrderTypeComponents.values()) {
Rectangle bounds = component.getScreenBounds();
if (bounds == null || !bounds.contains(locationOnScreen)) {
continue;
}
if (component.getOrderType() != myRuleInfo.getOrderType()) {
ArrangementOrderTypeComponent orderTypeComponent = myOrderTypeComponents.get(myRuleInfo.getOrderType());
if (orderTypeComponent != null) {
orderTypeComponent.setSelected(false);
}
private void addCondition(@NotNull ArrangementUiComponent component) {
mySkipStateChange = true;
try {
component.setSelected(true);
Collection<Set<ArrangementSettingsToken>> mutexes = mySettingsManager.getMutexes();
// Update 'mutex conditions', i.e. conditions which can't be active at the same time (e.g. type 'field' and type 'method').
for (Set<ArrangementSettingsToken> mutex : mutexes) {
if (!mutex.contains(component.getToken())) {
continue;
}
orderTypeComponent = myOrderTypeComponents.get(component.getOrderType());
if (orderTypeComponent != null) {
orderTypeComponent.setSelected(true);
for (ArrangementSettingsToken key : mutex) {
if (key.equals(component.getToken())) {
continue;
}
ArrangementUiComponent c = myComponents.get(key);
if (c != null && c.isEnabled()) {
removeCondition(c);
}
}
myRuleInfo.setOrderType(component.getOrderType());
apply();
}
return;
refreshConditions();
}
finally {
mySkipStateChange = false;
}
}
private void addCondition(@NotNull ArrangementAtomMatchConditionComponent component) {
ArrangementAtomMatchCondition chosenCondition = component.getMatchCondition();
myRuleInfo.addAtomCondition(chosenCondition);
component.setSelected(true);
Collection<Set<?>> mutexes = myFilter.getMutexes();
// Update 'mutex conditions', i.e. conditions which can't be active at the same time (e.g. type 'field' and type 'method').
for (Set<?> mutex : mutexes) {
if (!mutex.contains(chosenCondition.getValue())) {
continue;
}
for (Object key : mutex) {
if (!chosenCondition.getValue().equals(key) && myRuleInfo.hasCondition(key)) {
removeCondition(myConditionComponents.get(key));
myRuleInfo.addAtomCondition(chosenCondition);
}
}
}
refreshConditions();
}
private void removeCondition(@NotNull ArrangementAtomMatchConditionComponent component) {
myRuleInfo.removeCondition(component.getMatchCondition().getValue());
private void removeCondition(@NotNull ArrangementUiComponent component) {
component.setSelected(false);
refreshConditions();
}
@@ -16,20 +16,20 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.component.*;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementListRowDecorator;
import com.intellij.application.options.codeStyle.arrangement.util.IntObjectMap;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.AbstractTableCellEditor;
import gnu.trove.TIntArrayList;
@@ -56,6 +56,8 @@ import java.util.List;
*/
public class ArrangementMatchingRulesControl extends JBTable {
@NotNull public static final DataKey<ArrangementMatchingRulesControl> KEY = DataKey.create("Arrangement.Rule.Match.Control");
@NotNull private static final Logger LOG = Logger.getInstance("#" + ArrangementMatchingRulesControl.class.getName());
@NotNull private static final JLabel EMPTY_RENDERER = new JLabel(ApplicationBundle.message("arrangement.text.empty.rule"));
@@ -72,14 +74,13 @@ public class ArrangementMatchingRulesControl extends JBTable {
private int myEditorRow = -1;
private boolean mySkipSelectionChange;
public ArrangementMatchingRulesControl(@NotNull ArrangementNodeDisplayManager displayManager,
public ArrangementMatchingRulesControl(@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsAware settingsFilter,
@NotNull RepresentationCallback callback)
{
super(new ArrangementMatchingRulesModel());
myRepresentationCallback = callback;
myFactory = new ArrangementMatchNodeComponentFactory(displayManager, colorsProvider, this);
myFactory = new ArrangementMatchNodeComponentFactory(settingsManager, colorsProvider, this);
myRenderer = new MyRenderer();
setDefaultRenderer(Object.class, myRenderer);
getColumnModel().getColumn(0).setCellEditor(new MyEditor());
@@ -89,12 +90,12 @@ public class ArrangementMatchingRulesControl extends JBTable {
setSurrendersFocusOnKeystroke(true);
putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.CLASS);
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(StdArrangementTokens.EntryType.CLASS);
StdArrangementMatchRule rule = new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition));
ArrangementMatchConditionComponent component = myFactory.getComponent(condition, rule, true);
ArrangementUiComponent component = myFactory.getComponent(condition, rule, true);
myMinRowHeight = new ArrangementListRowDecorator(component, this).getPreferredSize().height;
myEditor = new ArrangementMatchingRuleEditor(settingsFilter, colorsProvider, displayManager, this);
myEditor = new ArrangementMatchingRuleEditor(settingsManager, colorsProvider, this);
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
@@ -108,7 +109,8 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
});
getModel().addTableModelListener(new TableModelListener() {
@Override public void tableChanged(TableModelEvent e) { onTableChange(e); }
@Override
public void tableChanged(TableModelEvent e) { onTableChange(e); }
});
}
@@ -467,7 +469,7 @@ public class ArrangementMatchingRulesControl extends JBTable {
return EMPTY_RENDERER;
}
StdArrangementMatchRule rule = (StdArrangementMatchRule)value;
ArrangementMatchConditionComponent ruleComponent = myFactory.getComponent(rule.getMatcher().getCondition(), rule, true);
ArrangementUiComponent ruleComponent = myFactory.getComponent(rule.getMatcher().getCondition(), rule, true);
component = new ArrangementListRowDecorator(ruleComponent, ArrangementMatchingRulesControl.this);
myComponents.set(row, component);
}
@@ -477,12 +479,13 @@ public class ArrangementMatchingRulesControl extends JBTable {
component.setSelected(getSelectionModel().isSelectedIndex(row) || (myEditorRow >= 0 && row == myEditorRow - 1));
component.setBeingEdited(myEditorRow >= 0 && myEditorRow == row + 1);
boolean showSortIcon = value instanceof StdArrangementMatchRule
&& ((StdArrangementMatchRule)value).getOrderType() == ArrangementEntryOrderType.BY_NAME;
&& StdArrangementTokens.Order.BY_NAME.equals(((StdArrangementMatchRule)value).getOrderType());
component.setShowSortIcon(showSortIcon);
return component.getUiComponent();
}
}
@SuppressWarnings("ConstantConditions")
private class MyEditor extends AbstractTableCellEditor {
private int myRow;
@@ -16,7 +16,7 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementEditorAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
@@ -16,14 +16,13 @@
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.TitleWithToolbar;
import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NonNls;
@@ -42,9 +41,8 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide
@NotNull private final ArrangementMatchingRulesControl myControl;
public ArrangementMatchingRulesPanel(@NotNull ArrangementNodeDisplayManager displayManager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementStandardSettingsAware settingsFilter)
public ArrangementMatchingRulesPanel(@NotNull ArrangementStandardSettingsManager settingsManager,
@NotNull ArrangementColorsProvider colorsProvider)
{
super(new GridBagLayout());
@@ -69,7 +67,7 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide
}
}
};
myControl = new ArrangementMatchingRulesControl(displayManager, colorsProvider, settingsFilter, callback);
myControl = new ArrangementMatchingRulesControl(settingsManager, colorsProvider, callback);
scrollPane.setViewportView(myControl);
CustomizationUtil.installPopupHandler(
myControl, ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU, ArrangementConstants.MATCHING_RULES_CONTROL_PLACE
@@ -97,7 +95,7 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (ArrangementConstants.MATCHING_RULES_CONTROL_KEY.is(dataId)) {
if (ArrangementMatchingRulesControl.KEY.is(dataId)) {
return myControl;
}
return null;
@@ -1,104 +0,0 @@
/*
* Copyright 2000-2012 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.ArrangementNodeDisplayManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
/**
* @author Denis Zhdanov
* @since 11/15/12 1:01 PM
*/
public class ArrangementOrderTypeComponent extends JPanel {
@NotNull
private final SimpleColoredComponent myTextControl = new SimpleColoredComponent() {
@Override public Dimension getMinimumSize() { return getPreferredSize(); }
@Override public Dimension getMaximumSize() { return getPreferredSize(); }
@Override public Dimension getPreferredSize() { return myTextControlSize == null ? super.getPreferredSize() : myTextControlSize; }
@Override public String toString() { return "text component for " + this; }
};
@NotNull private final ArrangementEntryOrderType myOrderType;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@NotNull private final String myText;
@NotNull private final SideBorder myBorder;
@Nullable private final Dimension myTextControlSize;
@Nullable private Rectangle myScreenBounds;
public ArrangementOrderTypeComponent(@NotNull ArrangementEntryOrderType orderType,
@NotNull ArrangementNodeDisplayManager displayManager,
@NotNull ArrangementColorsProvider colorsProvider,
int width)
{
super(new GridBagLayout());
myOrderType = orderType;
myColorsProvider = colorsProvider;
myTextControl.setTextAlign(SwingConstants.CENTER);
myText = displayManager.getDisplayValue(orderType);
TextAttributes attributes = colorsProvider.getTextAttributes(ArrangementSettingType.ORDER, false);
myTextControl.append(myText, SimpleTextAttributes.fromTextAttributes(attributes));
myTextControlSize = new Dimension(width, myTextControl.getPreferredSize().height);
add(myTextControl, new GridBag().anchor(GridBagConstraints.WEST));
setBorder(myBorder = (SideBorder)IdeBorderFactory.createBorder());
}
public void setSelected(boolean selected) {
myTextControl.clear();
TextAttributes attributes = myColorsProvider.getTextAttributes(ArrangementSettingType.ORDER, selected);
myTextControl.append(myText, SimpleTextAttributes.fromTextAttributes(attributes));
myBorder.setLineColor(myColorsProvider.getBorderColor(selected));
Color myBackgroundColor = attributes.getBackgroundColor();
myTextControl.setBackground(myBackgroundColor);
}
@Override
protected void paintComponent(Graphics g) {
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
}
super.paintComponent(g);
}
@NotNull
public ArrangementEntryOrderType getOrderType() {
return myOrderType;
}
@Nullable
public Rectangle getScreenBounds() {
return myScreenBounds;
}
}
@@ -15,8 +15,7 @@
*/
package com.intellij.application.options.codeStyle.arrangement.match;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementRepresentationAware;
import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
@@ -1,94 +0,0 @@
/*
* Copyright 2000-2012 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.node;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.Consumer;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* @author Denis Zhdanov
* @since 9/27/12 3:10 PM
*/
public class ArrangementCheckBoxNode<T>/* extends ArrangementTreeNode
implements ArrangementRepresentationAwareNode, ArrangementEditableNode*/
{
@NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout());
@NotNull private final JBCheckBox myCheckBox = new JBCheckBox();
@NotNull private final T myData;
@Nullable private Consumer<ArrangementCheckBoxNode<T>> myListener;
public ArrangementCheckBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull T data) {
//super(null);
myCheckBox.setText(displayManager.getDisplayValue(data));
myData = data;
myCheckBox.setBackground(UIUtil.getTreeBackground());
myRenderer.add(myCheckBox, new GridBag().anchor(GridBagConstraints.WEST));
myCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (myListener != null) {
myListener.consume(ArrangementCheckBoxNode.this);
}
}
});
}
@NotNull
//@Override
public JComponent getRenderer() {
return myRenderer;
}
@NotNull
//@Override
public JComponent getEditor() {
return myRenderer;
}
public boolean isSelected() {
return myCheckBox.isSelected();
}
public void setSelected(boolean selected) {
myCheckBox.setSelected(selected);
}
@NotNull
public T getValue() {
return myData;
}
public void setChangeCallback(@Nullable Consumer<ArrangementCheckBoxNode<T>> listener) {
myListener = listener;
}
@Override
public String toString() {
return myData.toString();
}
}
@@ -1,86 +0,0 @@
/*
* Copyright 2000-2012 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.node;
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Denis Zhdanov
* @since 9/27/12 5:01 PM
*/
public class ArrangementComboBoxNode<T> /*extends ArrangementTreeNode implements ArrangementRepresentationAwareNode, ArrangementEditableNode*/ {
@NotNull private final JPanel myControl = new JPanel(new GridBagLayout());
@NotNull private final JLabel myLabel = new JLabel();
@NotNull private final JComboBox myComboBox = new JComboBox();
@NotNull private final List<T> myData = new ArrayList<T>();
public ArrangementComboBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull String text, @NotNull Iterable<T> data) {
//super(null);
for (T t : data) {
myData.add(t);
myComboBox.addItem(displayManager.getDisplayValue(t));
}
myLabel.setText(text);
myControl.add(myLabel, new GridBag().setColumn(0).insets(0, 3, 0, 0));
myControl.add(myComboBox, new GridBag().setColumn(1));
}
@NotNull
//@Override
public JComponent getEditor() {
return myControl;
}
@NotNull
//@Override
public JComponent getRenderer() {
return myControl;
}
public void setEnabled(boolean enabled) {
myLabel.setEnabled(enabled);
myComboBox.setEnabled(enabled);
}
@NotNull
public T getSelectedValue() {
int index = myComboBox.getSelectedIndex();
if (index < 0 || index >= myData.size()) {
return myData.get(0);
}
return myData.get(index);
}
public void setSelectedValue(@NotNull T value) {
int i = myData.indexOf(value);
if (i >= 0) {
myComboBox.setSelectedIndex(i);
}
}
@Override
public String toString() {
return myData.toString();
}
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2012 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.node;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.TreeNode;
/**
* @author Denis Zhdanov
* @since 9/27/12 4:44 PM
*/
public interface ArrangementEditableNode extends TreeNode {
@NotNull
JComponent getEditor();
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2012 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.node;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.TreeNode;
/**
* @author Denis Zhdanov
* @since 9/27/12 2:48 PM
*/
public interface ArrangementRepresentationAwareNode extends TreeNode {
@NotNull
JComponent getRenderer();
}
@@ -1,46 +0,0 @@
/*
* Copyright 2000-2012 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.node;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Denis Zhdanov
* @since 9/27/12 2:24 PM
*/
public class ArrangementSectionNode /*extends ArrangementTreeNode implements ArrangementRepresentationAwareNode*/ {
@NotNull private final JPanel myRenderer = new JPanel();
@NotNull private final JLabel myTextLabel = new JLabel();
public ArrangementSectionNode(@NotNull String text) {
//super(null);
myTextLabel.setText(text);
myRenderer.add(myTextLabel);
}
@NotNull
public JComponent getRenderer() {
return myRenderer;
}
@Override
public String toString() {
return String.format("section '%s'", myTextLabel.getText());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.component;
package com.intellij.application.options.codeStyle.arrangement.ui;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.component;
package com.intellij.application.options.codeStyle.arrangement.ui;
import org.jetbrains.annotations.NotNull;
@@ -1,117 +0,0 @@
/*
* Copyright 2000-2012 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.util;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Contains various utility methods to be used during showing arrangement settings.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 9:14 AM
*/
public class ArrangementConfigUtil {
private ArrangementConfigUtil() {
}
/**
* Allows to answer what settings are available for a particular match condition.
*
* @param filter filter to use
* @param condition object that encapsulates information about current arrangement matcher settings
* @return map which contains information on what settings are available at the current situation
*/
@NotNull
public static Map<ArrangementSettingType, Set<?>> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatchCondition condition)
{
Map<ArrangementSettingType, Set<?>> result = new EnumMap<ArrangementSettingType, Set<?>>(ArrangementSettingType.class);
processData(filter, condition, result, ArrangementSettingType.TYPE, ArrangementEntryType.values());
processData(filter, condition, result, ArrangementSettingType.MODIFIER, ArrangementModifier.values());
return result;
}
private static <T> void processData(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatchCondition settings,
@NotNull Map<ArrangementSettingType, Set<?>> result,
@NotNull ArrangementSettingType type,
@NotNull T[] values)
{
Set<T> data = null;
for (T v : values) {
if (!isEnabled(v, filter, settings)) {
continue;
}
if (data == null) {
data = new HashSet<T>();
}
data.add(v);
}
if (data != null) {
result.put(type, data);
}
}
public static boolean isEnabled(@NotNull Object conditionId,
@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatchCondition condition)
{
if (conditionId instanceof ArrangementEntryType) {
return filter.isEnabled((ArrangementEntryType)conditionId, condition);
}
else if (conditionId instanceof ArrangementModifier) {
return filter.isEnabled((ArrangementModifier)conditionId, condition);
}
else {
return false;
}
}
@Nullable
public static Point getLocationOnScreen(@NotNull JComponent component) {
int dx = 0;
int dy = 0;
for (Container c = component; c != null; c = c.getParent()) {
if (c.isShowing()) {
Point locationOnScreen = c.getLocationOnScreen();
locationOnScreen.translate(dx, dy);
return locationOnScreen;
}
else {
Point location = c.getLocation();
dx += location.x;
dy += location.y;
}
}
return null;
}
}
@@ -16,7 +16,6 @@
package com.intellij.application.options.codeStyle.arrangement.util;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchConditionComponent;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -25,6 +24,8 @@ import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.Toggleable;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.util.ui.GridBag;
@@ -40,28 +41,28 @@ import java.awt.event.MouseEvent;
* @author Denis Zhdanov
* @since 10/31/12 5:00 PM
*/
public class ArrangementListRowDecorator extends JPanel implements ArrangementMatchConditionComponent {
public class ArrangementListRowDecorator extends JPanel implements ArrangementUiComponent {
@NotNull private final JLabel mySortLabel = new JLabel(AllIcons.Icons.Inspector.SortByName);
@NotNull private final ArrangementRuleIndexControl myRowIndexControl;
@NotNull private final ArrangementMatchConditionComponent myDelegate;
@NotNull private final ArrangementMatchingRulesControl myControl;
@NotNull private final MyActionButton myEditButton;
@NotNull private final ArrangementRuleIndexControl myRowIndexControl;
@NotNull private final ArrangementUiComponent myDelegate;
@NotNull private final ArrangementMatchingRulesControl myControl;
@NotNull private final MyActionButton myEditButton;
@Nullable private Rectangle myScreenBounds;
private boolean myBeingEdited;
private boolean myUnderMouse;
public ArrangementListRowDecorator(@NotNull ArrangementMatchConditionComponent delegate,
public ArrangementListRowDecorator(@NotNull ArrangementUiComponent delegate,
@NotNull ArrangementMatchingRulesControl control)
{
myDelegate = delegate;
myControl = control;
mySortLabel.setVisible(false);
AnAction action = ActionManager.getInstance().getAction("Arrangement.Rule.Edit");
Presentation presentation = action.getTemplatePresentation().clone();
Icon editIcon = presentation.getIcon();
@@ -95,7 +96,7 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa
@Override
protected void paintComponent(Graphics g) {
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
Point point = UIUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
@@ -228,7 +229,38 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa
Rectangle bounds = myEditButton.getBounds();
return new Rectangle(bounds.x + myScreenBounds.x, bounds.y + myScreenBounds.y, bounds.width, bounds.height);
}
@Nullable
@Override
public ArrangementSettingsToken getToken() {
return myDelegate.getToken();
}
@Override
public void chooseToken(@NotNull ArrangementSettingsToken data) throws IllegalArgumentException, UnsupportedOperationException {
myDelegate.chooseToken(data);
}
@Override
public boolean isSelected() {
return myDelegate.isSelected();
}
@Override
public void reset() {
myDelegate.reset();
}
@Override
public int getBaselineToUse(int width, int height) {
return myDelegate.getBaselineToUse(width, height);
}
@Override
public void setListener(@NotNull Listener listener) {
myDelegate.setListener(listener);
}
@Override
public String toString() {
return "list row decorator for " + myDelegate.toString();
@@ -20,7 +20,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,8 +32,8 @@ import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.HashSet;
@@ -226,9 +226,9 @@ public class ArrangementEngine {
public static <E extends ArrangementEntry> List<E> arrange(@NotNull Collection<E> entries,
@NotNull List<? extends ArrangementMatchRule> rules)
{
List<E> arranged = new ArrayList<E>();
Set<E> unprocessed = new LinkedHashSet<E>();
List<Pair<Set<ArrangementEntry>, E>> dependent = new ArrayList<Pair<Set<ArrangementEntry>, E>>();
List<E> arranged = ContainerUtilRt.newArrayList();
Set<E> unprocessed = ContainerUtilRt.newLinkedHashSet();
List<Pair<Set<ArrangementEntry>, E>> dependent = ContainerUtilRt.newArrayList();
for (E entry : entries) {
List<? extends ArrangementEntry> dependencies = entry.getDependencies();
if (dependencies == null) {
@@ -261,7 +261,7 @@ public class ArrangementEngine {
unprocessed.removeAll(matched);
// Sort by name if necessary.
if (rule.getOrderType() == ArrangementEntryOrderType.BY_NAME) {
if (StdArrangementTokens.Order.BY_NAME.equals(rule.getOrderType())) {
sortByName(arranged, startIndex);
}
}
@@ -29,7 +29,7 @@ import java.util.ResourceBundle;
public class ApplicationBundle {
private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.ApplicationBundle";
@NonNls public static final String BUNDLE = "messages.ApplicationBundle";
private ApplicationBundle() {
}
@@ -589,6 +589,12 @@ arrangement.settings.order.type.keep=keep order
arrangement.settings.order.type.by.name=order by name
arrangement.settings.order.type.depth.first=depth-first order
arrangement.settings.order.type.breadth.first=breadth-first order
arrangement.settings.text.general.type=Type:
arrangement.settings.text.general.modifier=Modifier:
arrangement.settings.text.general.name=Name:
arrangement.settings.text.general.order=Order:
arrangement.settings.text.entry.type.xml.tag=tag
arrangement.settings.text.entry.type.xml.attribute=attribute
checkbox.spaces.around.lambda.arrow=Lambda arrow
checkbox.spaces.around.method.ref.dbl.colon.arrow=Method reference double colon
@@ -186,6 +186,7 @@
<extensionPoint name="lang.rearranger" beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.psi.codeStyle.arrangement.Rearranger"/>
</extensionPoint>
<extensionPoint name="rearranger.ui" interface="com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent$Factory"/>
<extensionPoint name="lang.surroundDescriptor" beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.lang.surroundWith.SurroundDescriptor"/>
@@ -189,6 +189,7 @@
<applicationService serviceImplementation="com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine"/>
<applicationService serviceImplementation="com.intellij.psi.codeStyle.arrangement.MemberOrderService"/>
<rearranger.ui implementation="com.intellij.application.options.codeStyle.arrangement.component.DefaultArrangementUiComponentFactory"/>
<projectService serviceInterface="com.intellij.ui.EditorTextFieldProvider"
serviceImplementation="com.intellij.ui.EditorTextFieldProviderImpl"/>
@@ -24,16 +24,18 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
import org.jetbrains.annotations.NotNull
import org.junit.Assert
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.KEEP
/**
* @author Denis Zhdanov
* @since 7/20/12 2:54 PM
@@ -63,36 +65,62 @@ abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFixtureTes
}
@NotNull
protected static ArrangementGroupingRule group(@NotNull ArrangementGroupingType type) {
group(type, ArrangementEntryOrderType.KEEP)
protected static ArrangementGroupingRule group(@NotNull ArrangementSettingsToken type) {
group(type, KEEP)
}
@NotNull
protected static ArrangementGroupingRule group(@NotNull ArrangementGroupingType type, @NotNull ArrangementEntryOrderType order) {
protected static ArrangementGroupingRule group(@NotNull ArrangementSettingsToken type, @NotNull ArrangementSettingsToken order) {
new ArrangementGroupingRule(type, order)
}
@NotNull
protected static StdArrangementMatchRule rule(@NotNull Object ... conditions) {
rule(ArrangementEntryOrderType.KEEP, conditions)
protected static StdArrangementMatchRule rule(@NotNull ArrangementSettingsToken token) {
new StdArrangementMatchRule(new StdArrangementEntryMatcher(atom(token)))
}
@NotNull
protected static StdArrangementMatchRule rule(@NotNull ArrangementEntryOrderType orderType, @NotNull Object ... conditions) {
def condition
if (conditions.length == 1) {
condition = atom(conditions[0])
protected static StdArrangementMatchRule nameRule(@NotNull String nameFilter, @NotNull ArrangementSettingsToken ... tokens) {
if (tokens.length == 0) {
new StdArrangementMatchRule(new StdArrangementEntryMatcher(atom(nameFilter)))
}
else {
condition = ArrangementUtil.combine(conditions.collect { atom(it) } as ArrangementMatchCondition[])
def compositeCondition = ArrangementUtil.combine([atom(nameFilter)] + tokens.collect { atom(it) } as ArrangementAtomMatchCondition[])
new StdArrangementMatchRule(new StdArrangementEntryMatcher(compositeCondition))
}
new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), orderType)
}
@NotNull
protected static ArrangementAtomMatchCondition atom(@NotNull Object condition) {
new ArrangementAtomMatchCondition(ArrangementUtil.parseType(condition), condition)
protected static StdArrangementMatchRule rule(@NotNull ArrangementSettingsToken ... conditions) {
rule(conditions.collect { atom(it) })
}
@NotNull
protected static StdArrangementMatchRule rule(@NotNull ArrangementAtomMatchCondition ... conditions) {
def compositeCondition = ArrangementUtil.combine(conditions)
new StdArrangementMatchRule(new StdArrangementEntryMatcher(compositeCondition))
}
@NotNull
protected static StdArrangementMatchRule rule(@NotNull List<ArrangementAtomMatchCondition> conditions) {
rule(conditions as ArrangementAtomMatchCondition[])
}
@NotNull
protected static StdArrangementMatchRule ruleWithOrder(@NotNull ArrangementSettingsToken orderType,
@NotNull StdArrangementMatchRule rule)
{
new StdArrangementMatchRule(rule.matcher, orderType)
}
@NotNull
protected static ArrangementAtomMatchCondition atom(@NotNull ArrangementSettingsToken token) {
new ArrangementAtomMatchCondition(token)
}
@NotNull
protected static ArrangementAtomMatchCondition atom(@NotNull String nameFilter) {
new ArrangementAtomMatchCondition(StdArrangementTokens.General.NAME, nameFilter)
}
protected void doTest(@NotNull args) {
@@ -2604,4 +2604,24 @@ public class UIUtil {
public static Paint getGradientPaint(float x1, float y1, @NotNull Color c1, float x2, float y2, @NotNull Color c2) {
return (Registry.is("ui.no.bangs.and.whistles", false)) ? ColorUtil.mix(c1, c2, .5) : new GradientPaint(x1, y1, c1, x2, y2, c2);
}
@Nullable
public static Point getLocationOnScreen(@NotNull JComponent component) {
int dx = 0;
int dy = 0;
for (Container c = component; c != null; c = c.getParent()) {
if (c.isShowing()) {
Point locationOnScreen = c.getLocationOnScreen();
locationOnScreen.translate(dx, dy);
return locationOnScreen;
}
else {
Point location = c.getLocation();
dx += location.x;
dy += location.y;
}
}
return null;
}
}
@@ -4,7 +4,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.codeStyle.arrangement.DefaultArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
@@ -14,6 +14,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_ATTRIBUTE;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_TAG;
/**
* @author Eugene.Kudelevsky
*/
@@ -41,7 +44,7 @@ public class XmlArrangementVisitor extends XmlElementVisitor {
@Override
public void visitXmlTag(XmlTag tag) {
final XmlElementArrangementEntry entry = createNewEntry(
tag.getTextRange(), ArrangementEntryType.XML_TAG, null, true);
tag.getTextRange(), XML_TAG, null, true);
processEntry(entry, tag);
}
@@ -49,7 +52,7 @@ public class XmlArrangementVisitor extends XmlElementVisitor {
public void visitXmlAttribute(XmlAttribute attribute) {
final String name = attribute.isNamespaceDeclaration() ? "" : attribute.getName();
final XmlElementArrangementEntry entry = createNewEntry(
attribute.getTextRange(), ArrangementEntryType.XML_ATTRIBUTE, name, true);
attribute.getTextRange(), XML_ATTRIBUTE, name, true);
processEntry(entry, null);
}
@@ -68,7 +71,7 @@ public class XmlArrangementVisitor extends XmlElementVisitor {
@Nullable
private XmlElementArrangementEntry createNewEntry(@NotNull TextRange range,
@NotNull ArrangementEntryType type,
@NotNull ArrangementSettingsToken type,
@Nullable String name,
boolean canBeMatched) {
if (!isWithinBounds(range)) {
@@ -100,4 +103,6 @@ public class XmlArrangementVisitor extends XmlElementVisitor {
}
return false;
}
}
@@ -5,7 +5,7 @@ import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.DefaultArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -18,14 +18,15 @@ import java.util.Set;
public class XmlElementArrangementEntry extends DefaultArrangementEntry
implements TypeAwareArrangementEntry, NameAwareArrangementEntry {
private final ArrangementEntryType myType;
private final String myName;
private final ArrangementSettingsToken myType;
private final String myName;
public XmlElementArrangementEntry(@Nullable ArrangementEntry parent,
@NotNull TextRange range,
@NotNull ArrangementEntryType type,
@NotNull ArrangementSettingsToken type,
@Nullable String name,
boolean canBeMatched) {
boolean canBeMatched)
{
super(parent, range.getStartOffset(), range.getEndOffset(), canBeMatched);
myName = name;
myType = type;
@@ -39,12 +40,7 @@ public class XmlElementArrangementEntry extends DefaultArrangementEntry
@NotNull
@Override
public Set<ArrangementEntryType> getTypes() {
public Set<ArrangementSettingsToken> getTypes() {
return Collections.singleton(myType);
}
@NotNull
public ArrangementEntryType getType() {
return myType;
}
}
@@ -7,69 +7,41 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import com.intellij.psi.codeStyle.arrangement.settings.DefaultArrangementSettingsRepresentationManager;
import gnu.trove.TObjectIntHashMap;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.CompositeArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_ATTRIBUTE;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_TAG;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.NAME;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.ORDER;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.TYPE;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.KEEP;
/**
* @author Eugene.Kudelevsky
*/
public class XmlRearranger
implements Rearranger<XmlElementArrangementEntry>,
ArrangementStandardSettingsAware,
ArrangementStandardSettingsRepresentationAware {
private static final Set<ArrangementEntryType> SUPPORTED_TYPES = EnumSet.of(
ArrangementEntryType.XML_ATTRIBUTE, ArrangementEntryType.XML_TAG);
ArrangementStandardSettingsAware {
private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES = ContainerUtilRt.newLinkedHashSet(XML_TAG, XML_ATTRIBUTE);
private static final List<StdArrangementMatchRule> DEFAULT_MATCH_RULES = new ArrayList<StdArrangementMatchRule>();
private static final StdArrangementSettings DEFAULT_SETTINGS = new StdArrangementSettings(
Collections.<ArrangementGroupingRule>emptyList(), DEFAULT_MATCH_RULES);
@NotNull private static final TObjectIntHashMap<Object> WEIGHTS = new TObjectIntHashMap<Object>();
@NotNull
private static final Comparator<Object> COMPARATOR = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
if (WEIGHTS.containsKey(o1) && WEIGHTS.containsKey(o2)) {
return WEIGHTS.get(o1) - WEIGHTS.get(o2);
}
else if (WEIGHTS.containsKey(o1) && !WEIGHTS.containsKey(o2)) {
return -1;
}
else if (!WEIGHTS.containsKey(o1) && WEIGHTS.containsKey(o2)) {
return 1;
}
else {
return o1.hashCode() - o2.hashCode();
}
}
};
static {
final Object[] ids = {
ArrangementEntryType.XML_TAG, ArrangementEntryType.XML_ATTRIBUTE
};
for (int i = 0; i < ids.length; i++) {
WEIGHTS.put(ids[i], i);
}
}
@Nullable
@Override
public StdArrangementSettings getDefaultSettings() {
@@ -77,29 +49,14 @@ public class XmlRearranger
}
@Override
public boolean isNameFilterSupported() {
return true;
}
@Override
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current) {
return SUPPORTED_TYPES.contains(type);
}
@Override
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current) {
return false;
}
@Override
public boolean isEnabled(@NotNull ArrangementGroupingType groupingType, @Nullable ArrangementEntryOrderType orderType) {
return false;
public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) {
return NAME.equals(token) || KEEP.equals(token) || BY_NAME.equals(token) || SUPPORTED_TYPES.contains(token);
}
@NotNull
@Override
public Collection<Set<?>> getMutexes() {
return Collections.<Set<?>>singleton(SUPPORTED_TYPES);
public Collection<Set<ArrangementSettingsToken>> getMutexes() {
return Collections.singleton(SUPPORTED_TYPES);
}
@Nullable
@@ -108,7 +65,8 @@ public class XmlRearranger
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull PsiElement element,
@Nullable ArrangementSettings settings) {
@Nullable ArrangementSettings settings)
{
final XmlArrangementParseInfo newEntryInfo = new XmlArrangementParseInfo();
element.accept(new XmlArrangementVisitor(newEntryInfo, Collections.singleton(element.getTextRange())));
@@ -140,43 +98,25 @@ public class XmlRearranger
return -1;
}
@NotNull
@Nullable
@Override
public String getDisplayValue(@NotNull ArrangementEntryType type) {
switch (type) {
case XML_TAG:
return "tag";
case XML_ATTRIBUTE:
return "attribute";
default:
return DefaultArrangementSettingsRepresentationManager.
INSTANCE.getDisplayValue(type);
}
public List<CompositeArrangementSettingsToken> getSupportedGroupingTokens() {
return null;
}
@Nullable
@Override
public List<CompositeArrangementSettingsToken> getSupportedMatchingTokens() {
return ContainerUtilRt.newArrayList(
new CompositeArrangementSettingsToken(TYPE, SUPPORTED_TYPES),
new CompositeArrangementSettingsToken(NAME),
new CompositeArrangementSettingsToken(ORDER, KEEP, BY_NAME)
);
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementModifier modifier) {
return DefaultArrangementSettingsRepresentationManager.INSTANCE.getDisplayValue(modifier);
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementGroupingType groupingType) {
return DefaultArrangementSettingsRepresentationManager.INSTANCE.getDisplayValue(groupingType);
}
@NotNull
@Override
public String getDisplayValue(@NotNull ArrangementEntryOrderType orderType) {
return DefaultArrangementSettingsRepresentationManager.INSTANCE.getDisplayValue(orderType);
}
@NotNull
@Override
public <T> List<T> sort(@NotNull Collection<T> ids) {
final List<T> result = new ArrayList<T>(ids);
Collections.sort(result, COMPARATOR);
return result;
public ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
throw new IllegalArgumentException("Can't build a matcher for condition " + condition);
}
}
@@ -3,7 +3,8 @@ import com.intellij.ide.highlighter.XmlFileType
import com.intellij.lang.xml.XMLLanguage
import com.intellij.psi.codeStyle.arrangement.AbstractRearrangerTest
import static com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType.BY_NAME
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME
/**
* @author Eugene.Kudelevsky
*/
@@ -17,7 +18,7 @@ class XmlRearrangerTest extends AbstractRearrangerTest {
doTest(
initial: '''<root xmlns:ns="http://ns.com" attr2="value2" attr1="value1" attr3="value3"/>''',
expected: '''<root xmlns:ns="http://ns.com" attr1="value1" attr2="value2" attr3="value3"/>''',
rules: [rule(BY_NAME, ".*")]
rules: [ruleWithOrder(BY_NAME, nameRule(".*"))]
)
}
@@ -25,7 +26,7 @@ class XmlRearrangerTest extends AbstractRearrangerTest {
doTest(
initial: '''<root attr3="value3" attr2="value2" attr1="value1" xmlns:ns="http://ns.com"/>''',
expected: '''<root xmlns:ns="http://ns.com" attr1="value1" attr2="value2" attr3="value3"/>''',
rules: [rule(BY_NAME, ".*")]
rules: [ruleWithOrder(BY_NAME, nameRule(".*"))]
)
}
@@ -47,7 +48,7 @@ class XmlRearrangerTest extends AbstractRearrangerTest {
</tag1>
</root>
''',
rules: [rule(BY_NAME, ".*")]
rules: [ruleWithOrder(BY_NAME, nameRule(".*"))]
)
}
}