diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementConditionInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleInfo.java similarity index 69% rename from platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementConditionInfo.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleInfo.java index 94b688681af3..d551093e8233 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementConditionInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleInfo.java @@ -15,10 +15,14 @@ */ 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; @@ -30,11 +34,13 @@ import java.util.Set; * @author Denis Zhdanov * @since 10/31/12 12:30 PM */ -public class ArrangementConditionInfo { +public class ArrangementRuleInfo { @NotNull private final Set myAtomConditions = ContainerUtilRt.newHashSet(); @NotNull private final Set myConditions = ContainerUtilRt.newHashSet(); + @NotNull private ArrangementEntryOrderType myOrderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE; + @Nullable private String myNamePattern; @Nullable @@ -46,6 +52,15 @@ public class ArrangementConditionInfo { 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; @@ -72,6 +87,32 @@ public class ArrangementConditionInfo { } } + public void copyConditionsFrom(@NotNull ArrangementRuleInfo info) { + clearConditions(); + myConditions.addAll(info.myConditions); + myAtomConditions.addAll(info.myAtomConditions); + } + + 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()) { diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java index f7b5bb67cf50..508587e4612f 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java @@ -164,8 +164,8 @@ public class ArrangementUtil { } @NotNull - public static ArrangementConditionInfo extractConditions(@NotNull ArrangementMatchCondition condition) { - final ArrangementConditionInfo result = new ArrangementConditionInfo(); + public static ArrangementRuleInfo extractConditions(@NotNull ArrangementMatchCondition condition) { + final ArrangementRuleInfo result = new ArrangementRuleInfo(); condition.invite(new ArrangementMatchConditionVisitor() { @Override public void visit(@NotNull ArrangementAtomMatchCondition condition) { diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementSettingType.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementSettingType.java index d95368afe0a5..9a9440c0fe1f 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementSettingType.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementSettingType.java @@ -20,5 +20,5 @@ package com.intellij.psi.codeStyle.arrangement.model; * @since 8/6/12 5:02 PM */ public enum ArrangementSettingType { - TYPE, MODIFIER, NAME + TYPE, MODIFIER, NAME, ORDER } 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 7c6e5d2a78b6..fc738ccadc64 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 @@ -18,6 +18,7 @@ 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; @@ -98,6 +99,8 @@ public class ArrangementNodeDisplayManager { 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(); } @@ -133,6 +136,23 @@ public class ArrangementNodeDisplayManager { 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). * diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementAtomMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementAtomMatchConditionComponent.java index 86c35f51ac2e..4120426c05d4 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementAtomMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementAtomMatchConditionComponent.java @@ -58,7 +58,6 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementMatchC PredefinedConditionBorderStrategy strategy = new PredefinedConditionBorderStrategy(); BORDER_STRATEGIES.put(ArrangementSettingType.TYPE, strategy); BORDER_STRATEGIES.put(ArrangementSettingType.MODIFIER, strategy); - assert BORDER_STRATEGIES.size() == ArrangementSettingType.values().length; } @NotNull diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java index b24dfdadf7ab..e640d85dd3fb 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java @@ -22,15 +22,15 @@ import com.intellij.application.options.codeStyle.arrangement.util.ArrangementCo 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.ArrangementConditionInfo; +import com.intellij.psi.codeStyle.arrangement.ArrangementRuleInfo; 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.ui.IdeBorderFactory; import com.intellij.ui.components.JBTextField; @@ -40,20 +40,15 @@ 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.FocusEvent; -import java.awt.event.FocusListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.Collection; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Set; /** * Control for managing {@link ArrangementEntryMatcher matching rule conditions} for a single {@link ArrangementMatchRule}. @@ -65,19 +60,22 @@ import java.util.Set; */ public class ArrangementMatchingRuleEditor extends JPanel { - @NotNull private final Map myComponents = ContainerUtilRt.newHashMap(); - @NotNull private final List myRows = ContainerUtilRt.newArrayList(); + @NotNull private final Map myConditionComponents = ContainerUtilRt.newHashMap(); + @NotNull private final List myRows = ContainerUtilRt.newArrayList(); - @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - @NotNull private final JBTextField myNameField = new JBTextField(20); + @NotNull private final Map myOrderTypeComponents + = new EnumMap(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; - @Nullable private ArrangementConditionInfo myConditionInfo; private int myRow = -1; - private int myLabelWidth; + private int myLabelWidth; private boolean myRequestFocus; public ArrangementMatchingRuleEditor(@NotNull ArrangementStandardSettingsAware filter, @@ -110,9 +108,63 @@ public class ArrangementMatchingRuleEditor extends JPanel { addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager); addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager); addNameFilterIfPossible(); + addOrderRowIfPossible(displayManager); applyBackground(UIUtil.getListBackground()); } + private void addRowIfPossible(@NotNull ArrangementSettingType key, + @NotNull Map> 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( + 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() { @@ -125,7 +177,7 @@ public class ArrangementMatchingRuleEditor extends JPanel { private void updateName() { myAlarm.cancelAllRequests(); - if (myRow < 0 || myConditionInfo == null) { + if (myRow < 0) { return; } @@ -133,55 +185,11 @@ public class ArrangementMatchingRuleEditor extends JPanel { if (StringUtil.isEmpty(namePattern)) { namePattern = null; } - if (Comparing.equal(namePattern, myConditionInfo.getNamePattern())) { + if (Comparing.equal(namePattern, myRuleInfo.getNamePattern())) { return; } - myConditionInfo.setNamePattern(namePattern); - ArrangementMatchCondition newCondition = myConditionInfo.buildCondition(); - Object modelValue = newCondition == null - ? new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow)) - : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition)); - myControl.getModel().set(myRow, modelValue); - myControl.repaintRows(myRow, myRow, true); - } - - private void addRowIfPossible(@NotNull ArrangementSettingType key, - @NotNull Map> 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); - myComponents.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 MultiRowFlowPanel newRow(@NotNull String rowLabel) { - MultiRowFlowPanel result = 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; + myRuleInfo.setNamePattern(namePattern); + updateModelValue(); } @Override @@ -211,14 +219,14 @@ public class ArrangementMatchingRuleEditor extends JPanel { myAlarm.cancelAllRequests(); if (newModel) { myRow = row; - myConditionInfo = null; + myRuleInfo.clear(); myNameField.setText(""); myAlarm.cancelAllRequests(); myRequestFocus = true; } // Reset state. - for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { + for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) { component.setEnabled(false); component.setSelected(false); } @@ -231,44 +239,61 @@ public class ArrangementMatchingRuleEditor extends JPanel { Object element = model.getElementAt(row); if (element instanceof EmptyArrangementRuleComponent) { - for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { + for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) { ArrangementAtomMatchCondition condition = component.getMatchCondition(); Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); component.setEnabled(map.get(condition.getType()).contains(condition.getValue())); } - myConditionInfo = new ArrangementConditionInfo(); + myRuleInfo.clearConditions(); + ArrangementOrderTypeComponent orderTypeComponent = myOrderTypeComponents.get(myRuleInfo.getOrderType()); + if (orderTypeComponent != null) { + orderTypeComponent.setSelected(true); + } return; } if (!(element instanceof StdArrangementMatchRule)) { return; } - ArrangementMatchCondition condition = ((StdArrangementMatchRule)element).getMatcher().getCondition(); - myConditionInfo = ArrangementUtil.extractConditions(condition); - myNameField.setText(myConditionInfo.getNamePattern() == null ? "" : myConditionInfo.getNamePattern()); + StdArrangementMatchRule rule = (StdArrangementMatchRule)element; + ArrangementMatchCondition condition = rule.getMatcher().getCondition(); + ArrangementRuleInfo infoWithConditions = ArrangementUtil.extractConditions(condition); + myRuleInfo.copyConditionsFrom(infoWithConditions); + myNameField.setText(myRuleInfo.getNamePattern() == null ? "" : myRuleInfo.getNamePattern()); Map> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); for (Collection ids : available.values()) { for (Object id : ids) { - ArrangementAtomMatchConditionComponent component = myComponents.get(id); + ArrangementAtomMatchConditionComponent component = myConditionComponents.get(id); if (component != null) { component.setEnabled(true); - component.setSelected(myConditionInfo.hasCondition(id)); + component.setSelected(myRuleInfo.hasCondition(id)); } } } + for (ArrangementOrderTypeComponent component : myOrderTypeComponents.values()) { + component.setSelected(false); + } + ArrangementOrderTypeComponent orderTypeComponent = myOrderTypeComponents.get(rule.getOrderType()); + if (orderTypeComponent != null) { + orderTypeComponent.setSelected(true); + } + repaint(); } private void updateState() { - assert myConditionInfo != null; - ArrangementMatchCondition newCondition = myConditionInfo.buildCondition(); - Object modelValue = newCondition == null - ? new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow)) - : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition)); + updateModelValue(); + updateState(myRow, false); + } + + private void updateModelValue() { + Object modelValue = myRuleInfo.buildRule(); + if (modelValue == null) { + modelValue = new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow)); + } myControl.getModel().set(myRow, modelValue); myControl.repaintRows(myRow, myRow, true); - updateState(myRow, false); } public void applyAvailableWidth(int width) { @@ -286,22 +311,41 @@ public class ArrangementMatchingRuleEditor extends JPanel { } private void onMouseClicked(@NotNull MouseEvent e) { - if (myRow < 0 || myConditionInfo == null) { + if (myRow < 0) { return; } - ArrangementAtomMatchConditionComponent clickedComponent = getNodeComponentAt(e.getLocationOnScreen()); - if (clickedComponent != null && clickedComponent.isEnabled()) { - onComponentSelected(clickedComponent); + + Point locationOnScreen = e.getLocationOnScreen(); + for (ArrangementAtomMatchConditionComponent component : myConditionComponents.values()) { + Rectangle screenBounds = component.getScreenBounds(); + if (screenBounds == null || !screenBounds.contains(locationOnScreen)) { + continue; + } + if (component.isEnabled()) { + onComponentSelected(component); + } + return; + } + for (ArrangementOrderTypeComponent component : myOrderTypeComponents.values()) { + Rectangle bounds = component.getScreenBounds(); + if (bounds == null || !bounds.contains(locationOnScreen)) { + continue; + } + if (component.getOrderType() != myRuleInfo.getOrderType()) { + myRuleInfo.setOrderType(component.getOrderType()); + updateState(); + } + return; } } private void onComponentSelected(@NotNull ArrangementAtomMatchConditionComponent component) { ArrangementAtomMatchCondition chosenCondition = component.getMatchCondition(); - boolean remove = myConditionInfo.hasCondition(chosenCondition.getValue()); + boolean remove = myRuleInfo.hasCondition(chosenCondition.getValue()); component.setSelected(!remove); repaintComponent(component); if (remove) { - myConditionInfo.removeCondition(chosenCondition.getValue()); + myRuleInfo.removeCondition(chosenCondition.getValue()); ensureConsistency(); updateState(); return; @@ -313,16 +357,16 @@ public class ArrangementMatchingRuleEditor extends JPanel { continue; } for (Object key : mutex) { - if (myConditionInfo.hasCondition(key)) { - ArrangementAtomMatchConditionComponent componentToDeselect = myComponents.get(key); - myConditionInfo.removeCondition(componentToDeselect.getMatchCondition().getValue()); - myConditionInfo.addAtomCondition(chosenCondition); - ArrangementMatchCondition newCondition = myConditionInfo.buildCondition(); - for (ArrangementAtomMatchConditionComponent componentToCheck : myComponents.values()) { + if (myRuleInfo.hasCondition(key)) { + ArrangementAtomMatchConditionComponent componentToDeselect = myConditionComponents.get(key); + myRuleInfo.removeCondition(componentToDeselect.getMatchCondition().getValue()); + myRuleInfo.addAtomCondition(chosenCondition); + ArrangementMatchCondition newCondition = myRuleInfo.buildCondition(); + for (ArrangementAtomMatchConditionComponent componentToCheck : myConditionComponents.values()) { Object value = componentToCheck.getMatchCondition().getValue(); - if (myConditionInfo.hasCondition(value) && !ArrangementConfigUtil.isEnabled(value, myFilter, newCondition)) { - myConditionInfo.removeCondition(componentToCheck.getMatchCondition().getValue()); - newCondition = myConditionInfo.buildCondition(); + if (myRuleInfo.hasCondition(value) && !ArrangementConfigUtil.isEnabled(value, myFilter, newCondition)) { + myRuleInfo.removeCondition(componentToCheck.getMatchCondition().getValue()); + newCondition = myRuleInfo.buildCondition(); } } @@ -333,19 +377,16 @@ public class ArrangementMatchingRuleEditor extends JPanel { } } } - myConditionInfo.addAtomCondition(chosenCondition); + myRuleInfo.addAtomCondition(chosenCondition); updateState(); } private void ensureConsistency() { - if (myConditionInfo == null) { - return; - } - ArrangementMatchCondition condition = myConditionInfo.buildCondition(); + ArrangementMatchCondition condition = myRuleInfo.buildCondition(); Map> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition); - for (ArrangementAtomMatchConditionComponent c : myComponents.values()) { + for (ArrangementAtomMatchConditionComponent c : myConditionComponents.values()) { Object v = c.getMatchCondition().getValue(); - if (!myConditionInfo.hasCondition(v)) { + if (!myRuleInfo.hasCondition(v)) { continue; } boolean remain = false; @@ -356,24 +397,13 @@ public class ArrangementMatchingRuleEditor extends JPanel { } } if (!remain) { - myConditionInfo.removeCondition(v); + myRuleInfo.removeCondition(v); ensureConsistency(); return; } } } - @Nullable - private ArrangementAtomMatchConditionComponent getNodeComponentAt(@NotNull Point screenPoint) { - for (ArrangementAtomMatchConditionComponent component : myComponents.values()) { - Rectangle screenBounds = component.getScreenBounds(); - if (screenBounds != null && screenBounds.contains(screenPoint)) { - return component; - } - } - return null; - } - private void repaintComponent(@NotNull ArrangementMatchConditionComponent component) { Rectangle bounds = component.getScreenBounds(); if (bounds != null) { diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java index 644cab1f8a95..166d67d9ab2d 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java @@ -24,6 +24,7 @@ import com.intellij.application.options.codeStyle.arrangement.util.IntObjectMap; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; +import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType; import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware; import com.intellij.ui.table.JBTable; import com.intellij.util.ui.AbstractTableCellEditor; @@ -423,12 +424,14 @@ public class ArrangementMatchingRulesControl extends JBTable { if (value instanceof ArrangementRepresentationAware) { return ((ArrangementRepresentationAware)value).getComponent(); } + + if (!(value instanceof StdArrangementMatchRule)) { + return EMPTY_RENDERER; + } + + StdArrangementMatchRule rule = (StdArrangementMatchRule)value; ArrangementListRowDecorator component = myComponents.get(row); if (component == null) { - if (!(value instanceof StdArrangementMatchRule)) { - return EMPTY_RENDERER; - } - StdArrangementMatchRule rule = (StdArrangementMatchRule)value; ArrangementMatchConditionComponent ruleComponent = myFactory.getComponent(rule.getMatcher().getCondition(), rule, true); component = new ArrangementListRowDecorator(ruleComponent, ArrangementMatchingRulesControl.this); myComponents.set(row, component); @@ -438,6 +441,7 @@ public class ArrangementMatchingRulesControl extends JBTable { component.setRowIndex((myEditorRow >= 0 && row > myEditorRow) ? row : row + 1); component.setSelected(getSelectionModel().isSelectedIndex(row) || (myEditorRow >= 0 && row == myEditorRow - 1)); component.setBeingEdited(myEditorRow >= 0 && myEditorRow == row + 1); + component.setShowSortIcon(rule.getOrderType() == ArrangementEntryOrderType.BY_NAME); return component.getUiComponent(); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementOrderTypeComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementOrderTypeComponent.java new file mode 100644 index 000000000000..ad80cdad0b43 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementOrderTypeComponent.java @@ -0,0 +1,104 @@ +/* + * 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; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java index ee1e02de4d3b..427ac5b9cb8f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java @@ -18,6 +18,7 @@ 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; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.Presentation; @@ -41,6 +42,8 @@ import java.awt.event.MouseEvent; */ public class ArrangementListRowDecorator extends JPanel implements ArrangementMatchConditionComponent { + @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; @@ -56,7 +59,9 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa { myDelegate = delegate; myControl = control; - + + mySortLabel.setVisible(false); + AnAction action = ActionManager.getInstance().getAction("Arrangement.Rule.Edit"); Presentation presentation = action.getTemplatePresentation().clone(); Icon editIcon = presentation.getIcon(); @@ -82,6 +87,7 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa GridBag constraints = new GridBag().anchor(GridBagConstraints.CENTER) .insets(0, ArrangementConstants.HORIZONTAL_PADDING, 0, ArrangementConstants.HORIZONTAL_GAP * 2); add(myRowIndexControl, constraints); + add(new InsetsPanel(mySortLabel), new GridBag().anchor(GridBagConstraints.CENTER).insets(0, 0, 0, ArrangementConstants.HORIZONTAL_GAP)); add(myDelegate.getUiComponent(), new GridBag().weightx(1).anchor(GridBagConstraints.WEST)); add(myEditButton, new GridBag().anchor(GridBagConstraints.EAST)); setBorder(IdeBorderFactory.createEmptyBorder(ArrangementConstants.VERTICAL_GAP)); @@ -154,6 +160,10 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa myDelegate.setSelected(selected); } + public void setShowSortIcon(boolean show) { + mySortLabel.setVisible(show); + } + @Override public Rectangle onMouseEntered(@NotNull MouseEvent e) { setBackground(UIUtil.getDecoratedRowColor()); diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 3e1ebb4b8381..de5bbb68df0f 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -558,6 +558,7 @@ arrangement.text.empty.rule= arrangement.text.type=Type arrangement.text.modifier=Modifier arrangement.text.name=Name +arrangement.order.name=Order arrangement.action.rule.add.text=Add rule arrangement.action.rule.add.description=Add new arrangement rule arrangement.action.rule.remove.text=Remove rule(s)