From 2529cf996c7dfda9c4a49361cfdcf19298d9d06f Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 27 Sep 2012 16:33:34 +0400 Subject: [PATCH] IDEA-19061 Integrate the Rearranger-plugin into core-IDE Grouping rules UI --- .../codeStyle/arrangement/JavaRearranger.java | 37 +++++- .../JavaRearrangerGrouperTest.groovy | 8 +- .../group/ArrangementGroupingType.java | 4 +- .../ArrangementStandardSettingsAware.java | 15 +++ ...ntStandardSettingsRepresentationAware.java | 16 +++ ...angementSettingsRepresentationManager.java | 39 +++++- .../ArrangementGroupingRulesManager.java | 71 ++++++++++ .../ArrangementNodeDisplayManager.java | 8 ++ .../ArrangementRuleEditingModelBuilder.java | 4 +- .../arrangement/ArrangementRuleEditor.java | 29 +++-- .../arrangement/ArrangementRuleTree.java | 122 ++++++++++-------- .../arrangement/ArrangementSettingsPanel.java | 2 +- .../node/ArrangementCheckBoxNode.java | 49 +++++++ .../ArrangementRepresentationAwareNode.java | 31 +++++ .../node/ArrangementSectionNode.java | 47 +++++++ .../ArrangementAndMatchNodeComponent.java} | 35 ++--- .../ArrangementAtomMatchNodeComponent.java} | 17 +-- ...rrangementGroupingMatchNodeComponent.java} | 19 +-- .../match/ArrangementMatchNodeComponent.java} | 6 +- ...ArrangementMatchNodeComponentFactory.java} | 26 ++-- .../src/messages/ApplicationBundle.properties | 10 ++ 21 files changed, 468 insertions(+), 127 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingRulesManager.java create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementCheckBoxNode.java create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementRepresentationAwareNode.java create mode 100644 platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementSectionNode.java rename platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/{ArrangementAndNodeComponent.java => node/match/ArrangementAndMatchNodeComponent.java} (78%) rename platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/{ArrangementAtomNodeComponent.java => node/match/ArrangementAtomMatchNodeComponent.java} (92%) rename platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/{ArrangementGroupingNodeComponent.java => node/match/ArrangementGroupingMatchNodeComponent.java} (83%) rename platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/{ArrangementNodeComponent.java => node/match/ArrangementMatchNodeComponent.java} (92%) rename platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/{ArrangementNodeComponentFactory.java => node/match/ArrangementMatchNodeComponentFactory.java} (67%) diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java index 3d36872dbf70..a1dda59afe63 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java @@ -95,12 +95,22 @@ public class JavaRearranger implements Rearranger, )); } + private static final Map> 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 DEFAULT_GROUPING_RULES = new ArrayList(); static { DEFAULT_GROUPING_RULES.add(new ArrangementGroupingRule(ArrangementGroupingType.GETTERS_AND_SETTERS)); } private static final List DEFAULT_MATCH_RULES = new ArrayList(); + static { ArrangementModifier[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE}; for (ArrangementModifier modifier : visibility) { @@ -169,7 +179,7 @@ public class JavaRearranger implements Rearranger, } return Pair.create(newEntryInfo.getEntries().get(0), existingEntriesInfo.getEntries()); } - + @NotNull @Override public List parse(@NotNull PsiElement root, @@ -183,9 +193,14 @@ public class JavaRearranger implements Rearranger, if (settings != null) { for (ArrangementGroupingRule rule : settings.getGroupings()) { switch (rule.getRule()) { - case GETTERS_AND_SETTERS: setupGettersAndSetters(parseInfo); break; - case UTILITY_METHODS: setupUtilityMethods(parseInfo, rule.getOrderType()); break; - case OVERRIDDEN_METHODS: setupOverriddenMethods(parseInfo); + case GETTERS_AND_SETTERS: + setupGettersAndSetters(parseInfo); + break; + case DEPENDENT_METHODS: + setupUtilityMethods(parseInfo, rule.getOrderType()); + break; + case OVERRIDDEN_METHODS: + setupOverriddenMethods(parseInfo); } } } @@ -341,12 +356,22 @@ public class JavaRearranger implements Rearranger, @NotNull @Override public List> getGroupingConditions() { - return UI_GROUPING_RULES; + return Collections.emptyList(); + //return UI_GROUPING_RULES; } - + @Nullable @Override public StdArrangementSettings getDefaultSettings() { return DEFAULT_SETTINGS; } + + @Override + public boolean isEnabled(@NotNull ArrangementGroupingType groupingType, @Nullable ArrangementEntryOrderType orderType) { + Set orderTypes = GROUPING_RULES.get(groupingType); + if (orderTypes == null) { + return false; + } + return orderType == null || orderTypes.contains(orderType); + } } diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy index 8915039cef05..7e2c72e250b2 100644 --- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy @@ -19,7 +19,7 @@ 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.UTILITY_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 @@ -65,7 +65,7 @@ class Test { void util11() {} void service2() { util2(); } }''', - groups: [group(UTILITY_METHODS, DEPTH_FIRST)], + groups: [group(DEPENDENT_METHODS, DEPTH_FIRST)], expected: '''\ class Test { void service1() { util1(); } @@ -87,7 +87,7 @@ class Test { void service2() { util2(); util1(); } void util3() {} }''', - groups: [group(UTILITY_METHODS, BREADTH_FIRST)], + groups: [group(DEPENDENT_METHODS, BREADTH_FIRST)], expected: '''\ class Test { void service1() { util1(); util2(); } @@ -143,7 +143,7 @@ class Base { void test4() {} void test1() { test2(); } }''', - groups: [group(UTILITY_METHODS, DEPTH_FIRST), group(OVERRIDDEN_METHODS)], + groups: [group(DEPENDENT_METHODS, DEPTH_FIRST), group(OVERRIDDEN_METHODS)], expected: '''\ class Base { void base1() {} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingType.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingType.java index 4778695b754c..81c0f62d041b 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingType.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingType.java @@ -26,6 +26,6 @@ public enum ArrangementGroupingType { GETTERS_AND_SETTERS, OVERRIDDEN_METHODS, - - UTILITY_METHODS + + DEPENDENT_METHODS } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsAware.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsAware.java index 64df1e956241..a338fa566b37 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsAware.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsAware.java @@ -16,9 +16,11 @@ package com.intellij.psi.codeStyle.arrangement.settings; 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; @@ -61,6 +63,19 @@ public interface ArrangementStandardSettingsAware { */ 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; + * null 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 true if given arguments are eligible for the languages-specific realisation of this interface; + * false 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 diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsRepresentationAware.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsRepresentationAware.java index 945e0792ebda..42d90d6eda53 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsRepresentationAware.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/ArrangementStandardSettingsRepresentationAware.java @@ -16,8 +16,10 @@ 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; @@ -48,6 +50,20 @@ public interface ArrangementStandardSettingsRepresentationAware { @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. diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/DefaultArrangementSettingsRepresentationManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/DefaultArrangementSettingsRepresentationManager.java index 03ab9672d34b..a370db1f8ef1 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/DefaultArrangementSettingsRepresentationManager.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/settings/DefaultArrangementSettingsRepresentationManager.java @@ -15,8 +15,12 @@ */ 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; @@ -60,7 +64,8 @@ public class DefaultArrangementSettingsRepresentationManager implements Arrangem } } - @NotNull private static final Comparator COMPARATOR = new Comparator() { + @NotNull + private static final Comparator COMPARATOR = new Comparator() { @Override public int compare(Object o1, Object o2) { if (WEIGHTS.containsKey(o1) && WEIGHTS.containsKey(o2)) { @@ -78,6 +83,26 @@ public class DefaultArrangementSettingsRepresentationManager implements Arrangem } }; + private static final Map 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")); + assert GROUPING_TYPES.size() == ArrangementGroupingType.values().length; + } + + private static final Map 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) { @@ -95,6 +120,18 @@ public class DefaultArrangementSettingsRepresentationManager implements Arrangem 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 List sort(@NotNull Collection ids) { diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingRulesManager.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingRulesManager.java new file mode 100644 index 000000000000..96dc8071b962 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingRulesManager.java @@ -0,0 +1,71 @@ +/* + * 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.node.ArrangementCheckBoxNode; +import com.intellij.application.options.codeStyle.arrangement.node.ArrangementSectionNode; +import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule; +import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType; +import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeNode; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is responsible for representing {@link ArrangementGroupingRule grouping rules} at tree structure. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since 9/27/12 2:36 PM + */ +public class ArrangementGroupingRulesManager { + + @NotNull public static final ArrangementGroupingRulesManager INSTANCE = new ArrangementGroupingRulesManager(); + + @SuppressWarnings("MethodMayBeStatic") + @Nullable + public MutableTreeNode buildAvailableRules(@NotNull ArrangementStandardSettingsAware settingsFilter, + @NotNull ArrangementNodeDisplayManager displayManager) + { + ArrangementSectionNode result = new ArrangementSectionNode(ApplicationBundle.message("arrangement.settings.section.groups")); + for (ArrangementGroupingType groupingType : ArrangementGroupingType.values()) { + if (!settingsFilter.isEnabled(groupingType, null)) { + continue; + } + ArrangementCheckBoxNode groupingCheckNode = new ArrangementCheckBoxNode(displayManager.getDisplayValue(groupingType)); + result.add(groupingCheckNode); + } + return result; + } + + public void applyRules(@NotNull List rules, @NotNull TreeNode groupsRoot) { + // TODO den implement + } + + @NotNull + public List buildRules(@NotNull TreeNode groupsRoot) { + List result = new ArrayList(); + // TODO den implement + return result; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java index 01ee26587f1c..db7c47ddca9d 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java @@ -17,11 +17,13 @@ package com.intellij.application.options.codeStyle.arrangement; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; +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.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.settings.ArrangementStandardSettingsRepresentationAware; import gnu.trove.TObjectIntHashMap; @@ -94,6 +96,12 @@ public class ArrangementNodeDisplayManager { 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(); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditingModelBuilder.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditingModelBuilder.java index b6a122a0b61d..ffaede37e13c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditingModelBuilder.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditingModelBuilder.java @@ -96,7 +96,7 @@ public class ArrangementRuleEditingModelBuilder { Pair pair = ArrangementConfigUtil.map(null, grouped, null); ArrangementTreeNode topMostNode = ArrangementConfigUtil.getRoot(pair.first); - ArrangementConfigUtil.markRows(root, tree.isRootVisible()); + ArrangementConfigUtil.markRows(root, true); ArrangementTreeNode bottomHierarchy = null; if (anchor != null) { bottomHierarchy = ArrangementConfigUtil.cutSubHierarchy(root, treeModel, anchor); @@ -106,7 +106,7 @@ public class ArrangementRuleEditingModelBuilder { ArrangementConfigUtil.insert(root, root.getChildCount(), bottomHierarchy, treeModel); } - TIntIntHashMap rowChanges = ArrangementConfigUtil.collectRowChangesAndUnmark(root, tree.isRootVisible()); + TIntIntHashMap rowChanges = ArrangementConfigUtil.collectRowChangesAndUnmark(root, true); topMostNode = ArrangementConfigUtil.getLastBefore(pair.first, root); int row = ArrangementConfigUtil.getRow(pair.first, tree.isRootVisible()); ArrangementRuleEditingModelImpl model = new ArrangementRuleEditingModelImpl( diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditor.java index dee28adc91d9..3768fab1eeef 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditor.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleEditor.java @@ -15,6 +15,8 @@ */ package com.intellij.application.options.codeStyle.arrangement; +import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementAtomMatchNodeComponent; +import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponent; import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule; import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; @@ -42,9 +44,9 @@ import java.util.List; */ public class ArrangementRuleEditor extends JPanel { - @NotNull private final List myColoredComponents = new ArrayList(); - @NotNull private final Map myComponents = - new HashMap(); + @NotNull private final List myColoredComponents = new ArrayList(); + @NotNull private final Map myComponents = + new HashMap(); @NotNull private final ArrangementStandardSettingsAware myFilter; @Nullable private ArrangementRuleEditingModel myModel; @@ -79,12 +81,13 @@ public class ArrangementRuleEditor extends JPanel { JPanel valuesPanel = new MultiRowFlowPanel(FlowLayout.LEFT, 8, 5); for (Object value : manager.sort(values)) { - ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementAtomMatchCondition(key, value), null); + ArrangementAtomMatchNodeComponent component = + new ArrangementAtomMatchNodeComponent(manager, new ArrangementAtomMatchCondition(key, value), null); myComponents.put(value, component); valuesPanel.add(component.getUiComponent()); } - int top = ArrangementAtomNodeComponent.VERTICAL_PADDING; + int top = ArrangementAtomMatchNodeComponent.VERTICAL_PADDING; add(new JLabel(manager.getDisplayLabel(key) + ":"), new GridBag().anchor(GridBagConstraints.NORTHWEST).insets(top, 0, 0, 0)); add(valuesPanel, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine()); myColoredComponents.add(valuesPanel); @@ -100,7 +103,7 @@ public class ArrangementRuleEditor extends JPanel { myModel = model; // Reset state. - for (ArrangementAtomNodeComponent component : myComponents.values()) { + for (ArrangementAtomMatchNodeComponent component : myComponents.values()) { component.setEnabled(false); component.setSelected(false); } @@ -114,7 +117,7 @@ public class ArrangementRuleEditor extends JPanel { ); for (Collection ids : available.values()) { for (Object id : ids) { - ArrangementAtomNodeComponent component = myComponents.get(id); + ArrangementAtomMatchNodeComponent component = myComponents.get(id); if (component != null) { component.setEnabled(true); component.setSelected(model.hasCondition(id)); @@ -135,7 +138,7 @@ public class ArrangementRuleEditor extends JPanel { if (myModel == null) { return; } - ArrangementAtomNodeComponent clickedComponent = getNodeComponentAt(e.getLocationOnScreen()); + ArrangementAtomMatchNodeComponent clickedComponent = getNodeComponentAt(e.getLocationOnScreen()); if (clickedComponent == null || !clickedComponent.isEnabled()) { return; } @@ -155,9 +158,9 @@ public class ArrangementRuleEditor extends JPanel { } for (Object key : mutex) { if (myModel.hasCondition(key)) { - ArrangementAtomNodeComponent componentToDeselect = myComponents.get(key); + ArrangementAtomMatchNodeComponent componentToDeselect = myComponents.get(key); myModel.replaceCondition(componentToDeselect.getMatchCondition(), chosenCondition); - for (ArrangementAtomNodeComponent componentToCheck : myComponents.values()) { + for (ArrangementAtomMatchNodeComponent componentToCheck : myComponents.values()) { Object value = componentToCheck.getMatchCondition().getValue(); if (myModel.hasCondition(value) && !ArrangementConfigUtil.isEnabled(value, myFilter, myModel.getCondition())) { myModel.removeAndCondition(componentToCheck.getMatchCondition()); @@ -176,8 +179,8 @@ public class ArrangementRuleEditor extends JPanel { } @Nullable - private ArrangementAtomNodeComponent getNodeComponentAt(@NotNull Point screenPoint) { - for (ArrangementAtomNodeComponent component : myComponents.values()) { + private ArrangementAtomMatchNodeComponent getNodeComponentAt(@NotNull Point screenPoint) { + for (ArrangementAtomMatchNodeComponent component : myComponents.values()) { Rectangle screenBounds = component.getScreenBounds(); if (screenBounds != null && screenBounds.contains(screenPoint)) { return component; @@ -186,7 +189,7 @@ public class ArrangementRuleEditor extends JPanel { return null; } - private void repaintComponent(@NotNull ArrangementNodeComponent component) { + private void repaintComponent(@NotNull ArrangementMatchNodeComponent component) { Rectangle bounds = component.getScreenBounds(); if (bounds != null) { Point location = bounds.getLocation(); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleTree.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleTree.java index 00914cf85c1c..7d0639b433cc 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleTree.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementRuleTree.java @@ -15,15 +15,20 @@ */ package com.intellij.application.options.codeStyle.arrangement; +import com.intellij.application.options.codeStyle.arrangement.node.ArrangementRepresentationAwareNode; +import com.intellij.application.options.codeStyle.arrangement.node.ArrangementSectionNode; +import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponent; +import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponentFactory; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; -import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule; -import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher; +import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition; import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition; +import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Alarm; import com.intellij.util.containers.ContainerUtil; @@ -57,44 +62,53 @@ public class ArrangementRuleTree { private static final int EMPTY_RULE_REMOVE_DELAY_MILLIS = 300; - @NotNull private final List myListeners = new ArrayList(); - @NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel(); - @NotNull private final MyModelChangeListener myModelChangeListener = new MyModelChangeListener(); - @NotNull private final MyModelNodesRefresher myModelNodesRefresher = new MyModelNodesRefresher(); - @NotNull private final ArrangementRuleEditingModelBuilder myModelBuilder = new ArrangementRuleEditingModelBuilder(); - @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - @NotNull private final RemoveInactiveNewModelRequest myRequest = new RemoveInactiveNewModelRequest(); + @NotNull private final List myListeners = new ArrayList(); + @NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel(); + @NotNull private final MyModelChangeListener myModelChangeListener = new MyModelChangeListener(); + @NotNull private final MyModelNodesRefresher myModelNodesRefresher = new MyModelNodesRefresher(); + @NotNull private final ArrangementRuleEditingModelBuilder myModelBuilder = new ArrangementRuleEditingModelBuilder(); + @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + @NotNull private final RemoveInactiveNewModelRequest myRequest = new RemoveInactiveNewModelRequest(); + @NotNull private final ArrangementGroupingRulesManager myGroupingRulesManager = ArrangementGroupingRulesManager.INSTANCE; - @NotNull private final TIntObjectHashMap myRenderers = - new TIntObjectHashMap(); + @NotNull private final TIntObjectHashMap myRenderers = + new TIntObjectHashMap(); @NotNull private final TIntObjectHashMap myModels = new TIntObjectHashMap(); - @NotNull private final ArrangementTreeNode myRoot; + @NotNull private final ArrangementTreeNode myMatchRulesRoot; @NotNull private final DefaultTreeModel myTreeModel; @NotNull private final Tree myTree; - @NotNull private final ArrangementNodeComponentFactory myFactory; + @NotNull private final ArrangementMatchNodeComponentFactory myFactory; @NotNull private final List> myUiGroupingRules; - @Nullable private List myGroupings; - private int myCanvasWidth; - private boolean myExplicitSelectionChange; - private boolean mySkipSelectionChange; + @Nullable private final MutableTreeNode myGroupingsRoot; + + private int myCanvasWidth; + private boolean myExplicitSelectionChange; + private boolean mySkipSelectionChange; public ArrangementRuleTree(@Nullable StdArrangementSettings settings, @NotNull List> uiGroupingRules, - @NotNull ArrangementNodeDisplayManager displayManager) + @NotNull ArrangementNodeDisplayManager displayManager, + @NotNull ArrangementStandardSettingsAware settingsFilter) { myUiGroupingRules = uiGroupingRules; - myFactory = new ArrangementNodeComponentFactory(displayManager, new Runnable() { + myFactory = new ArrangementMatchNodeComponentFactory(displayManager, new Runnable() { @Override public void run() { notifySelectionListeners(); } }, uiGroupingRules); - myRoot = new ArrangementTreeNode(null); - myTreeModel = new DefaultTreeModel(myRoot); - + myGroupingsRoot = myGroupingRulesManager.buildAvailableRules(settingsFilter, displayManager); + ArrangementTreeNode root = new ArrangementTreeNode(null); + if (myGroupingsRoot != null) { + root.add(myGroupingsRoot); + } + myMatchRulesRoot = new ArrangementSectionNode(ApplicationBundle.message("arrangement.settings.section.match")); + root.add(myMatchRulesRoot); + myTreeModel = new DefaultTreeModel(root); + final Condition wideSelectionCondition = new Condition() { @Override public boolean value(Integer row) { @@ -218,7 +232,7 @@ public class ArrangementRuleTree { if (myCanvasWidth <= 0) { return; } - ArrangementNodeComponent component = myRenderers.get(row); + ArrangementMatchNodeComponent component = myRenderers.get(row); if (component == null) { return; } @@ -259,8 +273,8 @@ public class ArrangementRuleTree { private void selectNextRule() { ArrangementTreeNode currentSelectionBottom = getCurrentSelectionBottom(); if (currentSelectionBottom == null) { - if (myRoot.getChildCount() > 0) { - mySelectionModel.setSelectionPath(new TreePath(myRoot.getFirstChild().getPath())); + if (myMatchRulesRoot.getChildCount() > 0) { + mySelectionModel.setSelectionPath(new TreePath(myMatchRulesRoot.getFirstChild().getPath())); } return; } @@ -301,9 +315,9 @@ public class ArrangementRuleTree { private void doClearSelection() { mySelectionModel.clearSelection(); - myRenderers.forEachValue(new TObjectProcedure() { + myRenderers.forEachValue(new TObjectProcedure() { @Override - public boolean execute(ArrangementNodeComponent node) { + public boolean execute(ArrangementMatchNodeComponent node) { node.setSelected(false); return true; } @@ -312,7 +326,7 @@ public class ArrangementRuleTree { } /** - * Updates renderer {@link ArrangementNodeComponent#setSelected(boolean) 'selected'} state on tree node selection change. + * Updates renderer {@link ArrangementMatchNodeComponent#setSelected(boolean) 'selected'} state on tree node selection change. * * @param path changed selection path * @param selected true if given path is selected now; false if given path was selected anymore @@ -331,7 +345,7 @@ public class ArrangementRuleTree { if (row < 0) { return; } - ArrangementNodeComponent component = myRenderers.get(row); + ArrangementMatchNodeComponent component = myRenderers.get(row); if (component != null) { component.setSelected(selected); myTreeModel.nodeChanged(node); @@ -357,7 +371,8 @@ public class ArrangementRuleTree { private void map(@NotNull List rules) { for (StdArrangementMatchRule rule : rules) { - Pair pair = myModelBuilder.build(rule, myTree, myRoot, null, myUiGroupingRules); + Pair pair + = myModelBuilder.build(rule, myTree, myMatchRulesRoot, null, myUiGroupingRules); if (pair != null) { myModels.put(pair.first.getRow(), pair.first); pair.first.addListener(myModelChangeListener); @@ -421,7 +436,7 @@ public class ArrangementRuleTree { implicitGroupConditions.add(prevGroup); prevGroup = null; } - if (!myRoot.equals(topMost) && !topMost.equals(model.getBottomMost()) && !implicitGroupConditions.contains(currentGroup)) { + if (!myMatchRulesRoot.equals(topMost) && !topMost.equals(model.getBottomMost()) && !implicitGroupConditions.contains(currentGroup)) { prevGroup = currentGroup; } rules.add(model.getRule()); @@ -431,28 +446,30 @@ public class ArrangementRuleTree { rules.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(prevGroup))); } - if (myGroupings == null) { + if (myGroupingsRoot == null) { return new StdArrangementSettings(rules); } else { - return new StdArrangementSettings(myGroupings, rules); + return new StdArrangementSettings(myGroupingRulesManager.buildRules(myGroupingsRoot), rules); } } public void setSettings(@Nullable StdArrangementSettings settings) { myRenderers.clear(); myModels.clear(); - while (myRoot.getChildCount() > 0) - myTreeModel.removeNodeFromParent(myRoot.getFirstChild()); + while (myMatchRulesRoot.getChildCount() > 0) + myTreeModel.removeNodeFromParent(myMatchRulesRoot.getFirstChild()); if (settings == null) { return; } - myGroupings = settings.getGroupings(); + if (myGroupingsRoot != null) { + myGroupingRulesManager.applyRules(settings.getGroupings(), myGroupingsRoot); + } List rules = settings.getRules(); map(rules); - expandAll(myTree, new TreePath(myRoot)); + expandAll(myTree, new TreePath(myTreeModel.getRoot())); if (ArrangementConstants.LOG_RULE_MODIFICATION) { LOG.info("Arrangement tree is refreshed. Given rules:"); @@ -469,13 +486,13 @@ public class ArrangementRuleTree { }); } } - + @NotNull - private ArrangementNodeComponent getNodeComponentAt(int row, + private ArrangementMatchNodeComponent getNodeComponentAt(int row, @NotNull ArrangementMatchCondition condition, @Nullable ArrangementRuleEditingModelImpl model) { - ArrangementNodeComponent result = myRenderers.get(row); + ArrangementMatchNodeComponent result = myRenderers.get(row); if (result == null || !result.getMatchCondition().equals(condition)) { myRenderers.put(row, result = myFactory.getComponent(condition, model)); doUpdateCanvasWidth(row); @@ -484,7 +501,7 @@ public class ArrangementRuleTree { } private void onMouseMoved(@NotNull MouseEvent e) { - ArrangementNodeComponent component = getNodeComponentAt(e.getX(), e.getY()); + ArrangementMatchNodeComponent component = getNodeComponentAt(e.getX(), e.getY()); if (component == null) { return; } @@ -495,7 +512,7 @@ public class ArrangementRuleTree { } private void onMouseClicked(@NotNull MouseEvent e) { - ArrangementNodeComponent component = getNodeComponentAt(e.getX(), e.getY()); + ArrangementMatchNodeComponent component = getNodeComponentAt(e.getX(), e.getY()); if (component != null) { component.handleMouseClick(e); return; @@ -511,12 +528,12 @@ public class ArrangementRuleTree { } @Nullable - private ArrangementNodeComponent getNodeComponentAt(int x, int y) { + private ArrangementMatchNodeComponent getNodeComponentAt(int x, int y) { int row = myTree.getRowForLocation(x, y); return myRenderers.get(row); } - private void repaintComponent(@NotNull ArrangementNodeComponent component) { + private void repaintComponent(@NotNull ArrangementMatchNodeComponent component) { Rectangle bounds = component.getScreenBounds(); if (bounds != null) { repaintScreenBounds(bounds); @@ -632,7 +649,7 @@ public class ArrangementRuleTree { final ArrangementTreeNode anchor = activeModels.size() != 1 ? null : activeModels.get(0).getBottomMost(); doClearSelection(); Pair pair = myModelBuilder.build( - ArrangementRuleEditingModel.EMPTY_RULE, myTree, myRoot, anchor, myUiGroupingRules + ArrangementRuleEditingModel.EMPTY_RULE, myTree, myMatchRulesRoot, anchor, myUiGroupingRules ); assert pair != null; processRowChanges(pair.second); @@ -661,8 +678,11 @@ public class ArrangementRuleTree { boolean expanded, boolean leaf, int row, - boolean hasFocus) - { + boolean hasFocus) { + if (value instanceof ArrangementRepresentationAwareNode) { + return ((ArrangementRepresentationAwareNode)value).getRenderer(); + } + ArrangementMatchCondition node = ((ArrangementTreeNode)value).getBackingCondition(); if (node == null) { return EMPTY_RENDERER; @@ -670,13 +690,13 @@ public class ArrangementRuleTree { if (isEmptyCondition(node)) { return NEW_CONDITION_RENDERER; } - + if (row < 0) { - ArrangementNodeComponent component = myFactory.getComponent(node, null); + ArrangementMatchNodeComponent component = myFactory.getComponent(node, null); doUpdateCanvasWidth(row); return component.getUiComponent(); } - ArrangementNodeComponent component = getNodeComponentAt(row, node, myModels.get(row)); + ArrangementMatchNodeComponent component = getNodeComponentAt(row, node, myModels.get(row)); component.setSelected(selected); return component.getUiComponent(); } @@ -752,7 +772,7 @@ public class ArrangementRuleTree { } TreePath path = myTree.getPathForRow(mySelectedRowToRestore); if (path == null) { - ArrangementTreeNode lastLeaf = myRoot.getLastLeaf(); + ArrangementTreeNode lastLeaf = myMatchRulesRoot.getLastLeaf(); if (lastLeaf == null) { return; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java index f500173fde96..fcd2f4e68968 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java @@ -99,7 +99,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel { toolbarControl.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.TOP | SideBorder.RIGHT)); myContent.add(toolbarControl, new GridBag().weightx(1).fillCellHorizontally().coverLine()); - myRuleTree = new ArrangementRuleTree(getSettings(settings), groupingRules, displayManager); + myRuleTree = new ArrangementRuleTree(getSettings(settings), groupingRules, displayManager, mySettingsAware); final Tree treeComponent = myRuleTree.getTreeComponent(); actionToolbar.setTargetComponent(treeComponent); JBScrollPane scrollPane = new JBScrollPane(treeComponent); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementCheckBoxNode.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementCheckBoxNode.java new file mode 100644 index 000000000000..c9a4babf415f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementCheckBoxNode.java @@ -0,0 +1,49 @@ +/* + * 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.ArrangementTreeNode; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.util.ui.GridBag; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; + +/** + * @author Denis Zhdanov + * @since 9/27/12 3:10 PM + */ +public class ArrangementCheckBoxNode extends ArrangementTreeNode implements ArrangementRepresentationAwareNode { + + @NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout()); + + public ArrangementCheckBoxNode(@NotNull String text) { + super(null); + JBCheckBox checkBox = new JBCheckBox(text); + checkBox.setBackground(UIUtil.getTreeBackground()); + myRenderer.add(checkBox, new GridBag().anchor(GridBagConstraints.WEST)); + } + + @NotNull + @Override + public JComponent getRenderer() { + return myRenderer; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementRepresentationAwareNode.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementRepresentationAwareNode.java new file mode 100644 index 000000000000..b236871eea88 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementRepresentationAwareNode.java @@ -0,0 +1,31 @@ +/* + * 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(); +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementSectionNode.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementSectionNode.java new file mode 100644 index 000000000000..5f39b5f9eaf7 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/ArrangementSectionNode.java @@ -0,0 +1,47 @@ +/* + * 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.ArrangementTreeNode; +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()); + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAndNodeComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchNodeComponent.java similarity index 78% rename from platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAndNodeComponent.java rename to platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchNodeComponent.java index 1f278dbe7623..c5332bae2f92 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAndNodeComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAndMatchNodeComponent.java @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.application.options.codeStyle.arrangement; +package com.intellij.application.options.codeStyle.arrangement.node.match; +import com.intellij.application.options.codeStyle.arrangement.ArrangementConfigUtil; +import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager; +import com.intellij.application.options.codeStyle.arrangement.ArrangementRuleEditingModel; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition; @@ -33,26 +36,26 @@ import java.util.List; import java.util.Map; /** - * {@link ArrangementNodeComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}. + * {@link ArrangementMatchNodeComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}. *

* Not thread-safe. * * @author Denis Zhdanov * @since 8/8/12 10:51 AM */ -public class ArrangementAndNodeComponent extends JPanel implements ArrangementNodeComponent { +public class ArrangementAndMatchNodeComponent extends JPanel implements ArrangementMatchNodeComponent { private static final int BUBBLE_CONNECTOR_LENGTH = 10; - @NotNull private final List myComponents = new ArrayList(); + @NotNull private final List myComponents = new ArrayList(); - @NotNull private final ArrangementCompositeMatchCondition mySetting; - @Nullable private Rectangle myScreenBounds; + @NotNull private final ArrangementCompositeMatchCondition mySetting; + @Nullable private Rectangle myScreenBounds; - public ArrangementAndNodeComponent(@NotNull ArrangementCompositeMatchCondition setting, - @NotNull ArrangementNodeComponentFactory factory, - @NotNull ArrangementNodeDisplayManager manager, - @Nullable ArrangementRuleEditingModel model) + public ArrangementAndMatchNodeComponent(@NotNull ArrangementCompositeMatchCondition setting, + @NotNull ArrangementMatchNodeComponentFactory factory, + @NotNull ArrangementNodeDisplayManager manager, + @Nullable ArrangementRuleEditingModel model) { mySetting = setting; setLayout(null); @@ -77,7 +80,7 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo for (Object key : ordered) { ArrangementMatchCondition operand = operands.get(key); assert operand != null; - ArrangementNodeComponent component = factory.getComponent(operand, model); + ArrangementMatchNodeComponent component = factory.getComponent(operand, model); myComponents.add(component); JComponent uiComponent = component.getUiComponent(); Dimension size = uiComponent.getPreferredSize(); @@ -117,13 +120,13 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo @Override public void setSelected(boolean selected) { - for (ArrangementNodeComponent component : myComponents) { + for (ArrangementMatchNodeComponent component : myComponents) { component.setSelected(selected); } } @Override - public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { + public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { if (myScreenBounds == null) { return null; } @@ -132,7 +135,7 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo return null; } - for (ArrangementNodeComponent component : myComponents) { + for (ArrangementMatchNodeComponent component : myComponents) { Rectangle screenBounds = component.getScreenBounds(); if (screenBounds != null && screenBounds.contains(screenPoint)) { return component; @@ -204,7 +207,7 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo @Override public Rectangle handleMouseMove(@NotNull MouseEvent event) { Point location = event.getLocationOnScreen(); - for (ArrangementNodeComponent component : myComponents) { + for (ArrangementMatchNodeComponent component : myComponents) { Rectangle bounds = component.getScreenBounds(); if (bounds != null && bounds.contains(location)) { return component.handleMouseMove(event); @@ -216,7 +219,7 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo @Override public void handleMouseClick(@NotNull MouseEvent event) { Point location = event.getLocationOnScreen(); - for (ArrangementNodeComponent component : myComponents) { + for (ArrangementMatchNodeComponent component : myComponents) { Rectangle bounds = component.getScreenBounds(); if (bounds != null && bounds.contains(location)) { component.handleMouseClick(event); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAtomNodeComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchNodeComponent.java similarity index 92% rename from platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAtomNodeComponent.java rename to platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchNodeComponent.java index 1d61feb130d2..deb96ee2c09a 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementAtomNodeComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementAtomMatchNodeComponent.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.application.options.codeStyle.arrangement; +package com.intellij.application.options.codeStyle.arrangement.node.match; +import com.intellij.application.options.codeStyle.arrangement.*; import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.components.ServiceManager; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; @@ -30,14 +31,14 @@ import java.awt.*; import java.awt.event.MouseEvent; /** - * {@link ArrangementNodeComponent} for {@link ArrangementAtomMatchCondition} representation. + * {@link ArrangementMatchNodeComponent} for {@link ArrangementAtomMatchCondition} representation. *

* Not thread-safe. * * @author Denis Zhdanov * @since 8/8/12 10:06 AM */ -public class ArrangementAtomNodeComponent implements ArrangementNodeComponent { +public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeComponent { public static final int VERTICAL_PADDING = 2; public static final int HORIZONTAL_PADDING = 8; @@ -86,14 +87,14 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent { @Nullable private Dimension myLabelSize; @Nullable private Rectangle myScreenBounds; - + private boolean myEnabled = true; private boolean myInverted; private boolean myCloseButtonHovered; - public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager, - @NotNull ArrangementAtomMatchCondition condition, - @Nullable Runnable closeCallback) + public ArrangementAtomMatchNodeComponent(@NotNull ArrangementNodeDisplayManager manager, + @NotNull ArrangementAtomMatchCondition condition, + @Nullable Runnable closeCallback) { myCondition = condition; myCloseCallback = closeCallback; @@ -175,7 +176,7 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent { } @Override - public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { + public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingNodeComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchNodeComponent.java similarity index 83% rename from platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingNodeComponent.java rename to platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchNodeComponent.java index 27a39f1e3257..4d76c007e4b6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementGroupingNodeComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementGroupingMatchNodeComponent.java @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.application.options.codeStyle.arrangement; +package com.intellij.application.options.codeStyle.arrangement.node.match; +import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsService; +import com.intellij.application.options.codeStyle.arrangement.ArrangementConfigUtil; +import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; @@ -33,10 +36,10 @@ import java.awt.event.MouseEvent; * @author Denis Zhdanov * @since 9/12/12 5:39 PM */ -public class ArrangementGroupingNodeComponent extends JPanel implements ArrangementNodeComponent { - +public class ArrangementGroupingMatchNodeComponent extends JPanel implements ArrangementMatchNodeComponent { + private static final int TOP_INSET = 3; - + @NotNull private final ArrangementColorsService myColorsService = ServiceManager.getService(ArrangementColorsService.class); @NotNull private final ArrangementAtomMatchCondition myCondition; @@ -44,8 +47,8 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem @NotNull private Dimension myPreferredSize; private boolean mySelected; - public ArrangementGroupingNodeComponent(@NotNull ArrangementNodeDisplayManager manager, - @NotNull ArrangementAtomMatchCondition condition) + public ArrangementGroupingMatchNodeComponent(@NotNull ArrangementNodeDisplayManager manager, + @NotNull ArrangementAtomMatchCondition condition) { myCondition = condition; String text = StringUtil.capitalize(StringUtil.pluralize(manager.getDisplayValue(myCondition.getValue()))); @@ -69,7 +72,7 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem @Nullable @Override - public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { + public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) { return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null; } @@ -81,7 +84,7 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem @Override public void setScreenBounds(@Nullable Rectangle bounds) { - myScreenBounds = bounds; + myScreenBounds = bounds; } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponent.java similarity index 92% rename from platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponent.java rename to platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponent.java index fd4a9536084d..6f8794dc2f67 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponent.java @@ -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; +package com.intellij.application.options.codeStyle.arrangement.node.match; import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition; import com.intellij.ui.awt.RelativePoint; @@ -30,7 +30,7 @@ import java.awt.event.MouseEvent; * @author Denis Zhdanov * @since 8/10/12 11:22 AM */ -public interface ArrangementNodeComponent { +public interface ArrangementMatchNodeComponent { @NotNull ArrangementMatchCondition getMatchCondition(); @@ -41,7 +41,7 @@ public interface ArrangementNodeComponent { // TODO den add doc @Nullable - ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point); + ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point); // TODO den add doc @Nullable diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponentFactory.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponentFactory.java similarity index 67% rename from platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponentFactory.java rename to platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponentFactory.java index 02afffeb4e65..72542769a6c5 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeComponentFactory.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/node/match/ArrangementMatchNodeComponentFactory.java @@ -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; +package com.intellij.application.options.codeStyle.arrangement.node.match; +import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager; +import com.intellij.application.options.codeStyle.arrangement.ArrangementRuleEditingModel; import com.intellij.openapi.util.Ref; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition; @@ -31,15 +33,15 @@ import java.util.Set; * @author Denis Zhdanov * @since 8/10/12 2:53 PM */ -public class ArrangementNodeComponentFactory { +public class ArrangementMatchNodeComponentFactory { @NotNull private final Set myGroupingConditions = ContainerUtilRt.newHashSet(); @NotNull private final ArrangementNodeDisplayManager myDisplayManager; @NotNull private final Runnable myRemoveConditionCallback; - public ArrangementNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager, - @NotNull Runnable removeConditionCallback, - @NotNull List> groupingRules) + public ArrangementMatchNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager, + @NotNull Runnable removeConditionCallback, + @NotNull List> groupingRules) { myDisplayManager = manager; myRemoveConditionCallback = removeConditionCallback; @@ -49,19 +51,19 @@ public class ArrangementNodeComponentFactory { } @NotNull - public ArrangementNodeComponent getComponent(@NotNull final ArrangementMatchCondition node, - @Nullable final ArrangementRuleEditingModel model) + public ArrangementMatchNodeComponent getComponent(@NotNull final ArrangementMatchCondition node, + @Nullable final ArrangementRuleEditingModel model) { - final Ref ref = new Ref(); + final Ref ref = new Ref(); node.invite(new ArrangementMatchConditionVisitor() { @Override public void visit(@NotNull ArrangementAtomMatchCondition condition) { - ArrangementNodeComponent component; + ArrangementMatchNodeComponent component; if (myGroupingConditions.contains(condition)) { - component = new ArrangementGroupingNodeComponent(myDisplayManager, condition); + component = new ArrangementGroupingMatchNodeComponent(myDisplayManager, condition); } else { - component = new ArrangementAtomNodeComponent(myDisplayManager, condition, prepareRemoveCallback(condition, model)); + component = new ArrangementAtomMatchNodeComponent(myDisplayManager, condition, prepareRemoveCallback(condition, model)); } ref.set(component); } @@ -70,7 +72,7 @@ public class ArrangementNodeComponentFactory { public void visit(@NotNull ArrangementCompositeMatchCondition condition) { switch (condition.getOperator()) { case AND: - ref.set(new ArrangementAndNodeComponent(condition, ArrangementNodeComponentFactory.this, myDisplayManager, model)); + ref.set(new ArrangementAndMatchNodeComponent(condition, ArrangementMatchNodeComponentFactory.this, myDisplayManager, model)); break; case OR: // TODO den implement } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index c3948fa85027..38f26bd105d3 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -560,5 +560,15 @@ arrangement.action.rule.add.text=Add rule arrangement.action.rule.add.description=Add new arrangement rule arrangement.action.rule.remove.text=Remove rule arrangement.action.rule.remove.description=Remove selected arrangement rule +arrangement.settings.section.groups=Grouping rules +arrangement.settings.section.match=Matching rules +arrangement.settings.groups.dependent.methods=Keep dependent methods together +arrangement.settings.groups.overridden.methods=Keep overridden methods together +arrangement.settings.groups.getters.and.setters.together=Keep getters and setters together +arrangement.settings.order.type.keep=Keep +arrangement.settings.order.type.by.name=By name +arrangement.settings.order.type.depth.first=Depth-first +arrangement.settings.order.type.breadth.first=Breadth-first + checkbox.spaces.around.lambda.arrow=Lambda arrow checkbox.spaces.around.method.ref.dbl.colon.arrow=Method reference double colon \ No newline at end of file