IDEA-19061 Integrate the Rearranger-plugin into core-IDEA

1. Adding ability to modify arrangement rules;
2. Refactoring;
This commit is contained in:
Denis.Zhdanov
2012-08-15 16:56:18 +04:00
parent 818d47044c
commit 339d8e021b
22 changed files with 708 additions and 360 deletions
@@ -16,11 +16,13 @@
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType;
import org.jetbrains.annotations.NotNull;
@@ -32,7 +34,9 @@ import java.util.*;
* @author Denis Zhdanov
* @since 7/20/12 2:31 PM
*/
public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware {
public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware,
ArrangementSettingsGrouper
{
// Type
@NotNull private static final Set<ArrangementEntryType> SUPPORTED_TYPES = EnumSet.of(
@@ -80,35 +84,87 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
@Override
public boolean isNameFilterEnabled(@Nullable ArrangementMatcherSettings settings) {
public boolean isNameFilterEnabled(@Nullable ArrangementSettingsNode current) {
// TODO den implement
return true;
}
@Override
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatcherSettings settings) {
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementSettingsNode current) {
return SUPPORTED_TYPES.contains(type);
}
@Override
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatcherSettings settings) {
if (settings == null) {
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementSettingsNode current) {
if (current == null) {
return SUPPORTED_MODIFIERS.contains(modifier);
}
Object key = NO_TYPE;
for (ArrangementEntryType type : ArrangementEntryType.values()) {
if (settings.hasCondition(type)) {
key = type;
break;
final Ref<Object> typeRef = new Ref<Object>();
current.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
if (node.getType() == ArrangementSettingType.TYPE) {
typeRef.set(node.getValue());
}
}
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
for (ArrangementSettingsNode n : node.getOperands()) {
if (typeRef.get() != null) {
return;
}
n.invite(this);
}
}
});
Object key = typeRef.get() == null ? NO_TYPE : typeRef.get();
Set<ArrangementModifier> modifiers = MODIFIERS_BY_TYPE.get(key);
return modifiers != null && modifiers.contains(modifier);
}
@Override
public boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementMatcherSettings settings) {
public boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementSettingsNode current) {
// TODO den implement
return true;
}
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node) {
final Ref<HierarchicalArrangementSettingsNode> result = new Ref<HierarchicalArrangementSettingsNode>();
node.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
result.set(new HierarchicalArrangementSettingsNode(node));
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
ArrangementSettingsNode typeNode = null;
for (ArrangementSettingsNode n : node.getOperands()) {
if (n instanceof ArrangementSettingsAtomNode && ((ArrangementSettingsAtomNode)n).getType() == ArrangementSettingType.TYPE) {
typeNode = n;
break;
}
}
if (typeNode == null) {
result.set(new HierarchicalArrangementSettingsNode(node));
}
else {
HierarchicalArrangementSettingsNode parent = new HierarchicalArrangementSettingsNode(typeNode);
ArrangementSettingsCompositeNode compositeWithoutType = new ArrangementSettingsCompositeNode(node.getOperator());
for (ArrangementSettingsNode n : node.getOperands()) {
if (n != typeNode) {
compositeWithoutType.addOperand(n);
}
}
parent.addChild(new HierarchicalArrangementSettingsNode(compositeWithoutType));
result.set(parent);
}
}
});
return result.get();
}
}
@@ -0,0 +1,79 @@
/*
* 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.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.JavaRearranger;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
import javax.swing.tree.DefaultMutableTreeNode;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.PUBLIC;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.STATIC;
import static org.junit.Assert.assertEquals;
/**
* @author Denis Zhdanov
* @since 08/15/2012
*/
public class ArrangementRuleEditingModelBuilderTest {
@NotNull private ArrangementRuleEditingModelBuilder myBuilder;
@NotNull private DefaultMutableTreeNode myRoot;
@NotNull private TIntObjectHashMap<ArrangementRuleEditingModel> myRowMappings;
@NotNull private JavaRearranger myGrouper;
@Before
public void setUp() {
myBuilder = new ArrangementRuleEditingModelBuilder();
myRoot = new DefaultMutableTreeNode();
myRowMappings = new TIntObjectHashMap<ArrangementRuleEditingModel>();
myGrouper = new JavaRearranger();
}
@Test
public void mapToTheSameLayer() {
build(ArrangementUtil.and(atom(PUBLIC), atom(STATIC)));
// TODO den uncomment
//assertEquals(1, myRowMappings.size());
}
private void build(@NotNull ArrangementSettingsNode node) {
myBuilder.build(node, myRoot, myGrouper, myRowMappings);
}
private static ArrangementSettingsAtomNode atom(@NotNull Object condition) {
final ArrangementSettingType type;
if (condition instanceof ArrangementEntryType) {
type = ArrangementSettingType.TYPE;
}
else if (condition instanceof ArrangementModifier) {
type = ArrangementSettingType.MODIFIER;
}
else {
throw new IllegalArgumentException(String.format("Unexpected condition of class %s: %s", condition.getClass(), condition));
}
return new ArrangementSettingsAtomNode(type, condition);
}
}
@@ -16,10 +16,15 @@
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.lang.Language;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNodeVisitor;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -108,17 +113,48 @@ public class ArrangementUtil {
}
//endregion
//region Matchers composition
//region Rule composition
@NotNull
public static ArrangementSettingsNode and(@NotNull ArrangementSettingsNode... nodes) {
final ArrangementSettingsCompositeNode result = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
final ArrangementSettingsNodeVisitor visitor = new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
result.addOperand(node);
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
if (node.getOperator() == ArrangementSettingsCompositeNode.Operator.AND) {
for (ArrangementSettingsNode operand : node.getOperands()) {
operand.invite(this);
}
}
else {
result.addOperand(node);
}
}
};
for (ArrangementSettingsNode node : nodes) {
node.invite(visitor);
}
return result;
}
// TODO den remove
@NotNull
public static ArrangementEntryMatcher or(@NotNull ArrangementEntryMatcher... matchers) {
return combine(CompositeArrangementEntryMatcher.Operator.OR, matchers);
}
// TODO den remove
@NotNull
public static ArrangementEntryMatcher and(@NotNull ArrangementEntryMatcher... matchers) {
return combine(CompositeArrangementEntryMatcher.Operator.AND, matchers);
}
// TODO den remove
@NotNull
private static ArrangementEntryMatcher combine(@NotNull CompositeArrangementEntryMatcher.Operator operator,
@NotNull ArrangementEntryMatcher... matchers)
@@ -90,6 +90,7 @@ public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
return true;
}
@NotNull
@Override
public ArrangementSettingsAtomNode clone() {
ArrangementSettingsAtomNode result = new ArrangementSettingsAtomNode(myType, myValue);
@@ -16,11 +16,10 @@
package com.intellij.psi.codeStyle.arrangement.model;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* // TODO den add doc
@@ -30,7 +29,7 @@ import java.util.List;
*/
public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode {
@NotNull private final List<ArrangementSettingsNode> myOperands = new ArrayList<ArrangementSettingsNode>();
@NotNull private final Set<ArrangementSettingsNode> myOperands = new HashSet<ArrangementSettingsNode>();
@NotNull private final Operator myOperator;
public ArrangementSettingsCompositeNode(@NotNull Operator operator) {
@@ -38,7 +37,7 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
}
@NotNull
public List<ArrangementSettingsNode> getOperands() {
public Set<ArrangementSettingsNode> getOperands() {
return myOperands;
}
@@ -57,6 +56,7 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
visitor.visit(this);
}
@NotNull
@Override
public ArrangementSettingsCompositeNode clone() {
ArrangementSettingsCompositeNode result = new ArrangementSettingsCompositeNode(myOperator);
@@ -70,7 +70,7 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
public String toString() {
return StringUtil.join(myOperands, myOperator == Operator.AND ? " and " : " or ");
}
public enum Operator {
AND, OR
}
@@ -27,5 +27,6 @@ public interface ArrangementSettingsNode extends Cloneable {
void invite(@NotNull ArrangementSettingsNodeVisitor visitor);
@NotNull
ArrangementSettingsNode clone();
}
@@ -0,0 +1,50 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import org.jetbrains.annotations.NotNull;
/**
* Strategy which hints on how arrangement settings should be grouped at the UI.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
* @author Denis Zhdanov
* @since 8/15/12 4:21 PM
*/
public interface ArrangementSettingsGrouper {
/**
* Allows to answer if and how should be grouped given settings.
* <p/>
* Example: given settings node is a composite <code>'AND'</code> node with the following conditions:
* <code>'type: field; modifier: public; modifier: static; modifier: final'</code>. We might want to show it like below:
* <pre>
* field
* |
* ---public---static---final
* </pre>
* That means that we'll return a {@link HierarchicalArrangementSettingsNode} with condition <code>'type: field'</code> and
* a single child node with composite <code>'AND'</code> condition <code>'modifier: public; modifier: static; modifier: final'</code>.
*
* @param node settings node which conditions should be grouped
* @return grouping-aware node
*/
@NotNull
HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node);
}
@@ -17,6 +17,7 @@ package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,14 +34,14 @@ import java.util.List;
public interface ArrangementStandardSettingsAware {
// TODO den add doc
boolean isNameFilterEnabled(@Nullable ArrangementMatcherSettings current);
boolean isNameFilterEnabled(@Nullable ArrangementSettingsNode current);
// TODO den add doc
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatcherSettings current);
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementSettingsNode current);
// TODO den add doc
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatcherSettings current);
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementSettingsNode current);
// TODO den add doc
boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementMatcherSettings current);
boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementSettingsNode current);
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import org.jetbrains.annotations.NotNull;
/**
* @author Denis Zhdanov
* @since 8/15/12 4:23 PM
*/
public class DefaultArrangementSettingsGrouper implements ArrangementSettingsGrouper {
@NotNull public static final DefaultArrangementSettingsGrouper INSTANCE = new DefaultArrangementSettingsGrouper();
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node) {
// Don't group.
return new HierarchicalArrangementSettingsNode(node);
}
}
@@ -1,25 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.settings.group;
/**
* // TODO den add doc
*
* @author Denis Zhdanov
* @since 8/8/12 12:29 PM
*/
public interface ArrangementSettingsNodeGrouper {
}
@@ -135,7 +135,7 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
@Override
public void paint(Graphics g) {
Point point = ArrangementSettingsUtil.getLocationOnScreen(this);
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
@@ -16,7 +16,6 @@
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.GridBag;
@@ -40,7 +39,7 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
@NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout()) {
@Override
public void paint(Graphics g) {
Point point = ArrangementSettingsUtil.getLocationOnScreen(this);
Point point = ArrangementConfigUtil.getLocationOnScreen(this);
if (point != null) {
Rectangle bounds = myRenderer.getBounds();
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
@@ -114,7 +113,7 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
@NotNull
@Override
public ArrangementSettingsNode getSettingsNode() {
public ArrangementSettingsAtomNode getSettingsNode() {
return mySettingsNode;
}
@@ -0,0 +1,116 @@
/*
* 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.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* Contains various utility methods to be used during showing arrangement settings.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 9:14 AM
*/
public class ArrangementConfigUtil {
private ArrangementConfigUtil() {
}
/**
* Allows to answer what new settings are available for a particular {@link ArrangementMatcherSettings arrangement matcher rules}.
*
* @param filter filter to use
* @param settings object that encapsulates information about current arrangement matcher settings
* @return map which contains information on what new new settings are available at the current situation
*/
@NotNull
public static Map<ArrangementSettingType, Collection<?>> buildAvailableOptions(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings)
{
Map<ArrangementSettingType, Collection<?>> result = new EnumMap<ArrangementSettingType, Collection<?>>(ArrangementSettingType.class);
processData(filter, settings, result, ArrangementSettingType.TYPE, ArrangementEntryType.values());
processData(filter, settings, result, ArrangementSettingType.MODIFIER, ArrangementModifier.values());
return result;
}
private static <T> void processData(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings,
@NotNull Map<ArrangementSettingType, Collection<?>> result,
@NotNull ArrangementSettingType type,
@NotNull T[] values)
{
List<T> data = null;
for (T v : values) {
if (!isEnabled(v, filter, settings)) {
continue;
}
if (data == null) {
data = new ArrayList<T>();
}
data.add(v);
}
if (data != null) {
result.put(type, data);
}
}
public static boolean isEnabled(@NotNull Object conditionId,
@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings)
{
if (conditionId instanceof ArrangementEntryType) {
return filter.isEnabled((ArrangementEntryType)conditionId, settings);
}
else if (conditionId instanceof ArrangementModifier) {
return filter.isEnabled((ArrangementModifier)conditionId, settings);
}
else {
return false;
}
}
@Nullable
public static Point getLocationOnScreen(@NotNull JComponent component) {
int dx = 0;
int dy = 0;
for (Container c = component; c != null; c = c.getParent()) {
if (c.isShowing()) {
Point locationOnScreen = c.getLocationOnScreen();
locationOnScreen.translate(dx, dy);
return locationOnScreen;
}
else {
Point location = c.getLocation();
dx += location.x;
dy += location.y;
}
}
return null;
}
}
@@ -16,11 +16,8 @@
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.MultiRowFlowPanel;
@@ -29,6 +26,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
@@ -47,18 +46,25 @@ public class ArrangementMatcherRuleEditor extends JPanel {
new HashMap<Object, ArrangementAtomNodeComponent>();
@NotNull private final ArrangementStandardSettingsAware myFilter;
@Nullable private ArrangementRuleEditingModel myModel;
public ArrangementMatcherRuleEditor(@NotNull ArrangementStandardSettingsAware filter,
@NotNull ArrangementNodeDisplayManager displayManager)
{
myFilter = filter;
init(displayManager);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
onMouseClicked(e);
}
});
}
private void init(@NotNull ArrangementNodeDisplayManager displayManager) {
setLayout(new GridBagLayout());
Map<ArrangementSettingType, Collection<?>> supportedSettings = ArrangementSettingsUtil.buildAvailableOptions(myFilter, null);
Map<ArrangementSettingType, Collection<?>> supportedSettings = ArrangementConfigUtil.buildAvailableOptions(myFilter, null);
addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager);
addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager);
}
@@ -78,7 +84,7 @@ public class ArrangementMatcherRuleEditor extends JPanel {
myComponents.put(value, component);
valuesPanel.add(component.getUiComponent());
}
int top = ArrangementAtomNodeComponent.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());
@@ -89,52 +95,68 @@ public class ArrangementMatcherRuleEditor extends JPanel {
* Asks current editor to refresh its state in accordance with the given arguments (e.g. when new rule is selected and
* we want to show only available conditions).
*
* @param settings current rule settings if defined; null as an indication that no settings should be active
* @param model current rule settings model if defined; null as an indication that no settings should be active
*/
public void updateState(@Nullable ArrangementMatcherSettings settings) {
for (ArrangementEntryType type : ArrangementEntryType.values()) {
ArrangementAtomNodeComponent component = myComponents.get(type);
if (component == null) {
continue;
}
boolean enabled;
boolean selected;
if (settings == null) {
enabled = false;
selected = false;
}
else {
enabled = myFilter.isEnabled(type, settings);
selected = settings.hasCondition(type);
}
component.setEnabled(enabled);
component.setSelected(selected);
public void updateState(@Nullable ArrangementRuleEditingModel model) {
myModel = model;
// Reset state.
for (ArrangementAtomNodeComponent component : myComponents.values()) {
component.setEnabled(false);
component.setSelected(false);
}
for (ArrangementModifier modifier : ArrangementModifier.values()) {
ArrangementAtomNodeComponent component = myComponents.get(modifier);
if (component == null) {
continue;
if (model == null) {
return;
}
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableOptions(myFilter, model.getSettingsNode());
for (Collection<?> ids : available.values()) {
for (Object id : ids) {
ArrangementAtomNodeComponent component = myComponents.get(id);
if (component != null) {
component.setEnabled(true);
component.setSelected(model.hasCondition(id));
}
}
boolean enabled;
boolean selected;
if (settings == null) {
enabled = false;
selected = false;
}
else {
enabled = myFilter.isEnabled(modifier, settings);
selected = settings.hasCondition(modifier);
}
component.setEnabled(enabled);
component.setSelected(selected);
}
repaint();
}
public void applyBackground(@NotNull Color color) {
setBackground(color);
for (JComponent component : myColoredComponents) {
component.setBackground(color);
}
}
private void onMouseClicked(@NotNull MouseEvent e) {
if (myModel == null) {
return;
}
ArrangementAtomNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
if (component == null) {
return;
}
ArrangementSettingsAtomNode settingsNode = component.getSettingsNode();
boolean remove = myModel.hasCondition(settingsNode.getValue());
component.setSelected(!remove);
if (remove) {
myModel.removeAndCondition(settingsNode);
}
else {
myModel.addAndCondition(settingsNode);
}
}
@Nullable
private ArrangementAtomNodeComponent getNodeComponentAt(@NotNull Point screenPoint) {
for (ArrangementAtomNodeComponent component : myComponents.values()) {
Rectangle screenBounds = component.getScreenBounds();
if (screenBounds != null && screenBounds.contains(screenPoint)) {
return component;
}
}
return null;
}
}
@@ -49,7 +49,7 @@ public class ArrangementNodeDisplayManager {
@NotNull ArrangementStandardSettingsRepresentationAware representationManager)
{
myRepresentationManager = representationManager;
Map<ArrangementSettingType, Collection<?>> map = ArrangementSettingsUtil.buildAvailableOptions(filter, null);
Map<ArrangementSettingType, Collection<?>> map = ArrangementConfigUtil.buildAvailableOptions(filter, null);
for (Map.Entry<ArrangementSettingType, Collection<?>> entry : map.entrySet()) {
myMaxWidths.put(entry.getKey(), maxWidth(entry.getValue()));
}
@@ -15,16 +15,15 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import org.jetbrains.annotations.NotNull;
/**
* @author Denis Zhdanov
* @since 8/15/12 9:14 AM
*/
public interface ArrangementMatcherEditingListener {
public interface ArrangementRuleEditingListener {
void startEditing(@NotNull ArrangementMatcherSettings settings);
void startEditing(@NotNull ArrangementRuleEditingModel settings);
void stopEditing();
}
@@ -0,0 +1,51 @@
/*
* 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.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import org.jetbrains.annotations.NotNull;
/**
* Combines and encapsulates information about arrangement matcher rules representation (tree nodes) and
* underlying {@link ArrangementSettingsNode data model}.
* <p/>
* Implementations of this interface are not obliged to be thread-safe.
*
* @author Denis Zhdanov
* @since 8/15/12 1:04 PM
*/
public interface ArrangementRuleEditingModel {
@NotNull
ArrangementSettingsNode getSettingsNode();
/**
* Allows to answer if current model has a registered condition for the given key. A key is expected to be one of the standard
* keys, e.g. {@link ArrangementEntryType type}, {@link ArrangementModifier modifier} etc.
*
* @param key target key
* @return <code>true</code> if current model has a registered mapping for the given key;
* <code>false</code> otherwise
*/
boolean hasCondition(@NotNull Object key);
void addAndCondition(@NotNull ArrangementSettingsAtomNode node);
void removeAndCondition(@NotNull ArrangementSettingsNode node);
}
@@ -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.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* Holds glue logic between arrangement settings and their representation -
* '{@link ArrangementSettingsNode} -&gt; {@link ArrangementRuleEditingModel}'
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 8/15/12 2:50 PM
*/
public class ArrangementRuleEditingModelBuilder {
/**
* Does the following:
* <pre>
* <ol>
* <li>
* {@link HierarchicalArrangementSettingsNode Groups} given {@link ArrangementSettingsNode settings} using
* the given {@link ArrangementStandardSettingsRepresentationAware#group(ArrangementSettingsNode) strategy};
* </li>
* <li>
* Build {@link DefaultMutableTreeNode tree nodes} for the {@link HierarchicalArrangementSettingsNode groiping-aware nodes}
* and register them within the target tree structure (denoted by the given settings root element);
* </li>
* <li>
* Build necessary {@link ArrangementRuleEditingModel editing models} and store them at the given container (a key is a node row);
* </li>
* </ol>
* </pre>
*
* @param setting target settings to process
* @param root UI tree settings root to use
* @param grouper strategy that knows how to
* {@link ArrangementStandardSettingsRepresentationAware#getDisplayValue(ArrangementModifier) group} setting
* nodes for UI representation
* @param rowMappings container to hold built {@link ArrangementRuleEditingModel editing models} (UI tree row numbers are used as keys)
*/
public void build(@NotNull ArrangementSettingsNode setting,
@NotNull DefaultMutableTreeNode root,
@NotNull ArrangementSettingsGrouper grouper,
@NotNull TIntObjectHashMap<ArrangementRuleEditingModel> rowMappings)
{
HierarchicalArrangementSettingsNode grouped = grouper.group(setting);
}
}
@@ -0,0 +1,56 @@
/*
* 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.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import org.jetbrains.annotations.NotNull;
/**
* @author Denis Zhdanov
* @since 8/15/12 2:40 PM
*/
public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingModel {
@NotNull private ArrangementSettingsNode mySettingsNode;
public ArrangementRuleEditingModelImpl(@NotNull ArrangementSettingsNode node) {
mySettingsNode = node;
}
@NotNull
@Override
public ArrangementSettingsNode getSettingsNode() {
return mySettingsNode;
}
@Override
public boolean hasCondition(@NotNull Object key) {
// TODO den implement
return false;
}
@Override
public void addAndCondition(@NotNull ArrangementSettingsAtomNode node) {
// TODO den implement
}
@Override
public void removeAndCondition(@NotNull ArrangementSettingsNode node) {
// TODO den implement
}
}
@@ -17,8 +17,11 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.treeStructure.Tree;
import gnu.trove.TIntObjectHashMap;
@@ -43,18 +46,20 @@ import java.util.List;
*/
public class ArrangementRuleTree {
@NotNull private final List<ArrangementMatcherEditingListener> myListeners = new ArrayList<ArrangementMatcherEditingListener>();
@NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel();
@NotNull private final TIntObjectHashMap<ArrangementNodeComponent> myRenderers = new TIntObjectHashMap<ArrangementNodeComponent>();
@NotNull private final TIntObjectHashMap<ArrangementMatcherSettings> mySettings =
new TIntObjectHashMap<ArrangementMatcherSettings>();
@NotNull private final List<ArrangementRuleEditingListener> myListeners = new ArrayList<ArrangementRuleEditingListener>();
@NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel();
@NotNull private final Tree myTree;
@NotNull private final ArrangementNodeComponentFactory myFactory;
@NotNull private final TIntObjectHashMap<ArrangementNodeComponent> myRenderers =
new TIntObjectHashMap<ArrangementNodeComponent>();
@NotNull private final TIntObjectHashMap<ArrangementRuleEditingModel> myModels =
new TIntObjectHashMap<ArrangementRuleEditingModel>();
@NotNull private final Tree myTree;
@NotNull private final ArrangementNodeComponentFactory myFactory;
private boolean mySkipSelectionChange;
public ArrangementRuleTree(@NotNull ArrangementNodeDisplayManager displayManager) {
public ArrangementRuleTree(@NotNull ArrangementSettingsGrouper grouper, @NotNull ArrangementNodeDisplayManager displayManager) {
myFactory = new ArrangementNodeComponentFactory(displayManager);
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
DefaultTreeModel treeModel = new DefaultTreeModel(root);
@@ -102,32 +107,23 @@ public class ArrangementRuleTree {
onMouseClicked(e);
}
});
ArrangementSettingsCompositeNode constants = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC));
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL));
ArrangementSettingsCompositeNode privateFields = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
privateFields.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE));
HierarchicalArrangementSettingsNode fields = new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
ArrangementSettingType.TYPE, ArrangementEntryType.FIELD
));
fields.addChild(new HierarchicalArrangementSettingsNode(constants));
fields.addChild(new HierarchicalArrangementSettingsNode(privateFields));
int row = map(root, fields, null, 0);
HierarchicalArrangementSettingsNode methods = new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
ArrangementSettingType.TYPE, ArrangementEntryType.METHOD
));
methods.addChild(new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC
)));
methods.addChild(new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE
)));
map(root, methods, null, row);
List<ArrangementSettingsNode> rules = new ArrayList<ArrangementSettingsNode>();
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
map(root, rules, grouper);
expandAll(myTree, new TreePath(root));
myTree.setRootVisible(false);
@@ -168,58 +164,37 @@ public class ArrangementRuleTree {
tree.expandPath(parent);
}
private int map(@NotNull DefaultMutableTreeNode parentTreeNode,
@NotNull HierarchicalArrangementSettingsNode settingsNode,
@Nullable ArrangementSettingsCompositeNode template,
int row)
private void map(@NotNull DefaultMutableTreeNode root,
@NotNull List<ArrangementSettingsNode> settings,
@NotNull ArrangementSettingsGrouper grouper)
{
DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(settingsNode.getCurrent());
parentTreeNode.add(childTreeNode);
List<HierarchicalArrangementSettingsNode> children = settingsNode.getChildren();
if (children.isEmpty()) {
ArrangementMatcherSettings settings = new ArrangementMatcherSettings();
ArrangementSettingsNode condition;
if (template == null) {
condition = settingsNode.getCurrent();
}
else {
condition = template.clone().addOperand(settingsNode.getCurrent());
}
settings.addCondition(condition);
mySettings.put(row, settings);
return row + 1;
}
else {
row++;
ArrangementSettingsCompositeNode newTemplate =
template == null ? new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
: template.clone();
newTemplate.addOperand(settingsNode.getCurrent());
for (HierarchicalArrangementSettingsNode node : children) {
row = map(childTreeNode, node, newTemplate, row);
}
return row;
ArrangementRuleEditingModelBuilder builder = new ArrangementRuleEditingModelBuilder();
for (ArrangementSettingsNode setting : settings) {
builder.build(setting, root, grouper, myModels);
}
}
public void addEditingListener(@NotNull ArrangementMatcherEditingListener listener) {
public void addEditingListener(@NotNull ArrangementRuleEditingListener listener) {
myListeners.add(listener);
}
/**
* @return matcher settings for the selected tree row(s) if any; null otherwise
* @return matcher model for the selected tree row(s) if any; null otherwise
*/
@Nullable
public ArrangementMatcherSettings getActiveSettings() {
public ArrangementRuleEditingModel getActiveModel() {
TreePath[] paths = mySelectionModel.getSelectionPaths();
if (paths == null) {
return null;
}
// There is a possible case that particular settings node is represented on multiple rows and that non-leaf nodes are served
// for more than one rule. No model is registered for them then and we want just to skip them.
for (int i = paths.length - 1; i >= 0; i--) {
int row = myTree.getRowForPath(paths[i]);
ArrangementMatcherSettings settings = mySettings.get(row);
if (settings != null) {
return settings;
ArrangementRuleEditingModel model = myModels.get(row);
if (model != null) {
return model;
}
}
return null;
@@ -296,13 +271,13 @@ public class ArrangementRuleTree {
}
}
private void notifyEditingListeners(@Nullable ArrangementMatcherSettings settings) {
for (ArrangementMatcherEditingListener listener : myListeners) {
if (settings == null) {
private void notifyEditingListeners(@Nullable ArrangementRuleEditingModel model) {
for (ArrangementRuleEditingListener listener : myListeners) {
if (model == null) {
listener.stopEditing();
}
else {
listener.startEditing(settings);
listener.startEditing(model);
}
}
}
@@ -328,7 +303,7 @@ public class ArrangementRuleTree {
public void setSelectionPath(TreePath path) {
if (!mySkipSelectionChange) {
super.setSelectionPath(path);
notifyEditingListeners(getActiveSettings());
notifyEditingListeners(getActiveModel());
}
}
}
@@ -22,10 +22,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import com.intellij.psi.codeStyle.arrangement.settings.DefaultArrangementSettingsRepresentationManager;
import com.intellij.psi.codeStyle.arrangement.settings.*;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.GridBag;
@@ -54,8 +51,12 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
representationManager = (ArrangementStandardSettingsRepresentationAware)filter;
}
ArrangementNodeDisplayManager displayManager = new ArrangementNodeDisplayManager(filter, representationManager);
ArrangementSettingsGrouper grouper = DefaultArrangementSettingsGrouper.INSTANCE;
if (filter instanceof ArrangementSettingsGrouper) {
grouper = (ArrangementSettingsGrouper)filter;
}
final ArrangementRuleTree ruleTree = new ArrangementRuleTree(displayManager);
final ArrangementRuleTree ruleTree = new ArrangementRuleTree(grouper, displayManager);
Tree component = ruleTree.getTreeComponent();
myContent.add(new JBScrollPane(component), new GridBag().weightx(1).weighty(1).fillCell().coverLine());
CustomizationUtil.installPopupHandler(
@@ -78,10 +79,10 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
}
}
});
ruleTree.addEditingListener(new ArrangementMatcherEditingListener() {
ruleTree.addEditingListener(new ArrangementRuleEditingListener() {
@Override
public void startEditing(@NotNull ArrangementMatcherSettings settings) {
ruleEditor.updateState(settings);
public void startEditing(@NotNull ArrangementRuleEditingModel model) {
ruleEditor.updateState(model);
resetEditor.set(Boolean.FALSE);
try {
editorPane.setCollapsed(false);
@@ -1,177 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* // TODO den add doc
*
* @author Denis Zhdanov
* @since 8/8/12 9:14 AM
*/
public class ArrangementSettingsUtil {
public static final DataKey<ArrangementNodeComponent> NODE_COMPONENT = DataKey.create("Arrangement.Rule.Editor.Node.Component");
public static final DataKey<ArrangementStandardSettingsAware> FILTER = DataKey.create("Arrangement.Rule.Editor.Settings.Filter");
public static final DataKey<ArrangementNodeDisplayManager> DISPLAY_MANAGER = DataKey.create("Arrangement.Rule.Editor.Display.Manager");
public static final DataKey<ArrangementMatcherSettings> SETTINGS = DataKey.create("Arrangement.Rule.Editor.Matcher.Settings");
public static final DataKey<JComponent> TREE = DataKey.create("Arrangement.Rule.Editor.Tree");
private static final EntryTypeHelper ENTRY_TYPE_HELPER = new EntryTypeHelper();
private static final ModifierHelper MODIFIER_HELPER = new ModifierHelper();
private ArrangementSettingsUtil() {
}
@Nullable
public static ArrangementSettingsNode getSettingsNode(@NotNull DataContext context) {
ArrangementNodeComponent nodeComponent = NODE_COMPONENT.getData(context);
return nodeComponent == null ? null : nodeComponent.getSettingsNode();
}
@Nullable
public static HierarchicalArrangementSettingsNode buildTreeStructure(@NotNull ArrangementSettingsNode modelNode) {
// TODO den implement
return new HierarchicalArrangementSettingsNode(modelNode);
}
/**
* Serves for the same purposes as {@link #buildAvailableOptions(ArrangementStandardSettingsAware, ArrangementMatcherSettings)} but
* retrieves necessary information from the given context.
*
* @param context target information holder
* @return map which contains information on what new new settings are available at the current situation
*/
@NotNull
public static Map<ArrangementSettingType, Collection<?>> buildAvailableOptions(@NotNull DataContext context) {
ArrangementStandardSettingsAware filter = FILTER.getData(context);
if (filter == null) {
return Collections.emptyMap();
}
return buildAvailableOptions(filter, SETTINGS.getData(context));
}
/**
* Allows to answer what new settings are available for a particular {@link ArrangementMatcherSettings arrangement matcher rules}.
*
* @param filter filter to use
* @param settings object that encapsulates information about current arrangement matcher settings
* @return map which contains information on what new new settings are available at the current situation
*/
@NotNull
public static Map<ArrangementSettingType, Collection<?>> buildAvailableOptions(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatcherSettings settings)
{
Map<ArrangementSettingType, Collection<?>> result = new EnumMap<ArrangementSettingType, Collection<?>>(ArrangementSettingType.class);
processData(filter, settings, result, ArrangementEntryType.values(), ENTRY_TYPE_HELPER);
processData(filter, settings, result, ArrangementModifier.values(), MODIFIER_HELPER);
return result;
}
private static <T> void processData(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatcherSettings settings,
Map<ArrangementSettingType, Collection<?>> result,
@NotNull T[] values,
@NotNull Helper<T> helper)
{
List<T> data = null;
for (T v : values) {
if (!helper.isEnabled(v, filter, settings)) {
continue;
}
if (data == null) {
data = new ArrayList<T>();
}
data.add(v);
}
if (data != null) {
result.put(helper.getType(), data);
}
}
@Nullable
public static Point getLocationOnScreen(@NotNull JComponent component) {
int dx = 0;
int dy = 0;
for (Container c = component; c != null; c = c.getParent()) {
if (c.isShowing()) {
Point locationOnScreen = c.getLocationOnScreen();
locationOnScreen.translate(dx, dy);
return locationOnScreen;
}
else {
Point location = c.getLocation();
dx += location.x;
dy += location.y;
}
}
return null;
}
private interface Helper<T> {
@NotNull ArrangementSettingType getType();
boolean isEnabled(@NotNull T data, @NotNull ArrangementStandardSettingsAware filter, @Nullable ArrangementMatcherSettings settings);
}
private static class EntryTypeHelper implements Helper<ArrangementEntryType> {
@NotNull
@Override
public ArrangementSettingType getType() {
return ArrangementSettingType.TYPE;
}
@Override
public boolean isEnabled(@NotNull ArrangementEntryType data,
@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatcherSettings settings)
{
return filter.isEnabled(data, settings);
}
}
private static class ModifierHelper implements Helper<ArrangementModifier> {
@NotNull
@Override
public ArrangementSettingType getType() {
return ArrangementSettingType.MODIFIER;
}
@Override
public boolean isEnabled(@NotNull ArrangementModifier data,
@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatcherSettings settings)
{
return filter.isEnabled(data, settings);
}
}
}