mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-19061 Integrate the Rearranger-plugin into core-IDEA
Added ability to add simple conditions
This commit is contained in:
@@ -161,10 +161,10 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
|
||||
}
|
||||
}
|
||||
if (compositeWithoutType.getOperands().size() == 1) {
|
||||
parent.addChild(new HierarchicalArrangementSettingsNode(compositeWithoutType.getOperands().iterator().next()));
|
||||
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType.getOperands().iterator().next()));
|
||||
}
|
||||
else {
|
||||
parent.addChild(new HierarchicalArrangementSettingsNode(compositeWithoutType));
|
||||
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType));
|
||||
}
|
||||
result.set(parent);
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.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 com.intellij.ui.treeStructure.Tree;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/16/12 11:04 AM
|
||||
*/
|
||||
public abstract class AbstractArrangementRuleEditingModelTest {
|
||||
|
||||
@NotNull protected ArrangementRuleEditingModelBuilder myBuilder;
|
||||
@NotNull protected JTree myTree;
|
||||
@NotNull protected DefaultMutableTreeNode myRoot;
|
||||
@NotNull protected TIntObjectHashMap<ArrangementRuleEditingModel> myRowMappings;
|
||||
@NotNull protected JavaRearranger myGrouper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
myBuilder = new ArrangementRuleEditingModelBuilder();
|
||||
myRoot = new DefaultMutableTreeNode();
|
||||
myTree = new Tree(myRoot);
|
||||
myTree.expandPath(new TreePath(myRoot));
|
||||
myRowMappings = new TIntObjectHashMap<ArrangementRuleEditingModel>();
|
||||
myGrouper = new JavaRearranger();
|
||||
}
|
||||
|
||||
protected void configure(@NotNull ArrangementSettingsNode settingsNode) {
|
||||
myBuilder.build(settingsNode, myTree, myRoot, myGrouper, myRowMappings);
|
||||
}
|
||||
|
||||
protected 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);
|
||||
}
|
||||
|
||||
protected void checkRows(int ... rows) {
|
||||
for (int row : rows) {
|
||||
assertTrue(
|
||||
String.format("Expected to find mappings for rows %s. Actual: %s", Arrays.toString(rows), Arrays.toString(myRowMappings.keys())),
|
||||
myRowMappings.containsKey(row)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-53
@@ -15,23 +15,10 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
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 com.intellij.ui.treeStructure.Tree;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.intellij.psi.codeStyle.arrangement.ArrangementUtil.and;
|
||||
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.FIELD;
|
||||
@@ -42,23 +29,7 @@ import static org.junit.Assert.*;
|
||||
* @author Denis Zhdanov
|
||||
* @since 08/15/2012
|
||||
*/
|
||||
public class ArrangementRuleEditingModelBuilderTest {
|
||||
|
||||
@NotNull private ArrangementRuleEditingModelBuilder myBuilder;
|
||||
@NotNull private JTree myTree;
|
||||
@NotNull private DefaultMutableTreeNode myRoot;
|
||||
@NotNull private TIntObjectHashMap<ArrangementRuleEditingModel> myRowMappings;
|
||||
@NotNull private JavaRearranger myGrouper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
myBuilder = new ArrangementRuleEditingModelBuilder();
|
||||
myRoot = new DefaultMutableTreeNode();
|
||||
myTree = new Tree(myRoot);
|
||||
myTree.expandPath(new TreePath(myRoot));
|
||||
myRowMappings = new TIntObjectHashMap<ArrangementRuleEditingModel>();
|
||||
myGrouper = new JavaRearranger();
|
||||
}
|
||||
public class ArrangementRuleEditingModelBuilderTest extends AbstractArrangementRuleEditingModelTest {
|
||||
|
||||
@Test
|
||||
public void mapToTheSameLayer() {
|
||||
@@ -108,27 +79,4 @@ public class ArrangementRuleEditingModelBuilderTest {
|
||||
assertNotNull(privateUiNode);
|
||||
assertEquals(atom(PRIVATE), privateUiNode.getUserObject());
|
||||
}
|
||||
|
||||
private void checkRows(int ... rows) {
|
||||
for (int row : rows) {
|
||||
assertTrue(
|
||||
String.format("Expected to find mappings for rows %s. Actual: %s", Arrays.toString(rows), Arrays.toString(myRowMappings.keys())),
|
||||
myRowMappings.containsKey(row)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.ArrangementSettingsNode;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
import static com.intellij.psi.codeStyle.arrangement.ArrangementUtil.and;
|
||||
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.FIELD;
|
||||
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;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/16/12 10:07 AM
|
||||
*/
|
||||
public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRuleEditingModelTest {
|
||||
|
||||
@Test
|
||||
public void addConditionToSameLevel() {
|
||||
configure(atom(PUBLIC));
|
||||
ArrangementRuleEditingModel model = myRowMappings.get(1);
|
||||
assertNotNull(model);
|
||||
model.addAndCondition(atom(STATIC));
|
||||
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode)myRoot.getFirstChild();
|
||||
assertNotNull(child);
|
||||
ArrangementSettingsNode expectedSettingsNode = and(atom(PUBLIC), atom(STATIC));
|
||||
assertEquals(expectedSettingsNode, child.getUserObject());
|
||||
assertEquals(expectedSettingsNode, model.getSettingsNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildNewSingleLevel() {
|
||||
configure(atom(PUBLIC));
|
||||
ArrangementRuleEditingModel model = myRowMappings.get(1);
|
||||
assertNotNull(model);
|
||||
assertEquals(1, myRowMappings.size());
|
||||
|
||||
model.addAndCondition(atom(FIELD));
|
||||
|
||||
assertEquals(1, myRowMappings.size());
|
||||
assertSame(model, myRowMappings.get(2));
|
||||
assertEquals(and(atom(FIELD), atom(PUBLIC)), model.getSettingsNode());
|
||||
|
||||
DefaultMutableTreeNode fieldNode = (DefaultMutableTreeNode)myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getUserObject());
|
||||
|
||||
DefaultMutableTreeNode publicNode = fieldNode.getFirstLeaf();
|
||||
assertNotNull(publicNode);
|
||||
assertEquals(atom(PUBLIC), publicNode.getUserObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addConditionToSameNestedLevel() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC)));
|
||||
ArrangementRuleEditingModel model = myRowMappings.get(2);
|
||||
assertNotNull(model);
|
||||
assertEquals(1, myRowMappings.size());
|
||||
|
||||
model.addAndCondition(atom(STATIC));
|
||||
|
||||
assertEquals(1, myRowMappings.size());
|
||||
assertSame(model, myRowMappings.get(2));
|
||||
assertEquals(and(atom(FIELD), atom(PUBLIC), atom(STATIC)), model.getSettingsNode());
|
||||
|
||||
DefaultMutableTreeNode fieldNode = (DefaultMutableTreeNode)myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getUserObject());
|
||||
|
||||
DefaultMutableTreeNode modifiersNode = fieldNode.getFirstLeaf();
|
||||
assertNotNull(modifiersNode);
|
||||
assertEquals(and(atom(PUBLIC), atom(STATIC)), modifiersNode.getUserObject());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -96,7 +96,7 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringUtil.join(myOperands, myOperator == Operator.AND ? " and " : " or ");
|
||||
return String.format("(%s)", StringUtil.join(myOperands, myOperator == Operator.AND ? " and " : " or "));
|
||||
}
|
||||
|
||||
public enum Operator {
|
||||
|
||||
+13
-13
@@ -16,21 +16,21 @@
|
||||
package com.intellij.psi.codeStyle.arrangement.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* {@link #getCurrent() Wraps} {@link ArrangementSettingsNode} in order to allow to build {@link #getChild() hierarchy}
|
||||
* from a plain sequence of them
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/12 1:23 PM
|
||||
*/
|
||||
public class HierarchicalArrangementSettingsNode {
|
||||
|
||||
@NotNull private final List<HierarchicalArrangementSettingsNode> myChildren = new ArrayList<HierarchicalArrangementSettingsNode>();
|
||||
|
||||
@NotNull private final ArrangementSettingsNode myCurrent;
|
||||
@NotNull private final ArrangementSettingsNode myCurrent;
|
||||
@Nullable private HierarchicalArrangementSettingsNode myChild;
|
||||
|
||||
public HierarchicalArrangementSettingsNode(@NotNull ArrangementSettingsNode current) {
|
||||
myCurrent = current;
|
||||
@@ -41,15 +41,15 @@ public class HierarchicalArrangementSettingsNode {
|
||||
return myCurrent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<HierarchicalArrangementSettingsNode> getChildren() {
|
||||
return myChildren;
|
||||
@Nullable
|
||||
public HierarchicalArrangementSettingsNode getChild() {
|
||||
return myChild;
|
||||
}
|
||||
|
||||
public void addChild(@NotNull HierarchicalArrangementSettingsNode child) {
|
||||
myChildren.add(child);
|
||||
public void setChild(@Nullable HierarchicalArrangementSettingsNode child) {
|
||||
myChild = child;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myCurrent.toString();
|
||||
|
||||
+34
-4
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
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 com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -24,10 +27,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* {@link ArrangementNodeComponent Component} for showing {@link ArrangementSettingsCompositeNode composite nodes}.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
@@ -43,11 +48,33 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
|
||||
@NotNull private final ArrangementSettingsCompositeNode mySettingsNode;
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
|
||||
public ArrangementAndNodeComponent(@NotNull ArrangementSettingsCompositeNode node, @NotNull ArrangementNodeComponentFactory factory) {
|
||||
public ArrangementAndNodeComponent(@NotNull ArrangementSettingsCompositeNode node,
|
||||
@NotNull ArrangementNodeComponentFactory factory,
|
||||
@NotNull ArrangementNodeDisplayManager manager)
|
||||
{
|
||||
mySettingsNode = node;
|
||||
setLayout(null);
|
||||
int x = 0;
|
||||
final Map<Object, ArrangementSettingsNode> operands = new HashMap<Object, ArrangementSettingsNode>();
|
||||
ArrangementSettingsNodeVisitor visitor = new ArrangementSettingsNodeVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
operands.put(node.getValue(), node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
operands.put(node, node);
|
||||
}
|
||||
};
|
||||
for (ArrangementSettingsNode operand : node.getOperands()) {
|
||||
operand.invite(visitor);
|
||||
}
|
||||
|
||||
List<Object> ordered = manager.sort(operands.keySet());
|
||||
for (Object key : ordered) {
|
||||
ArrangementSettingsNode operand = operands.get(key);
|
||||
assert operand != null;
|
||||
ArrangementNodeComponent component = factory.getComponent(operand);
|
||||
myComponents.add(component);
|
||||
JComponent uiComponent = component.getUiComponent();
|
||||
@@ -159,13 +186,16 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
|
||||
));
|
||||
}
|
||||
int y = bounds.y + bounds.height / 2;
|
||||
// TODO den shift y for the component
|
||||
x += bounds.width;
|
||||
// TODO den use right 'y'
|
||||
if (i < components.length - 1) {
|
||||
g.drawLine(x, y, x + BUBBLE_CONNECTOR_LENGTH, y);
|
||||
}
|
||||
x += BUBBLE_CONNECTOR_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%s)", StringUtil.join(myComponents, " and "));
|
||||
}
|
||||
}
|
||||
|
||||
+77
@@ -15,16 +15,21 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
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 javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -113,4 +118,76 @@ public class ArrangementConfigUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getDepth(@NotNull HierarchicalArrangementSettingsNode node) {
|
||||
HierarchicalArrangementSettingsNode child = node.getChild();
|
||||
return child == null ? 1 : 1 + getDepth(child);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HierarchicalArrangementSettingsNode getLast(@NotNull HierarchicalArrangementSettingsNode node) {
|
||||
HierarchicalArrangementSettingsNode result = node;
|
||||
for (HierarchicalArrangementSettingsNode child = node.getChild(); child != null; child = child.getChild()) {
|
||||
result = child;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TreeNode getLastBefore(@NotNull TreeNode start, @NotNull TreeNode stop) throws IllegalArgumentException {
|
||||
TreeNode result = start;
|
||||
for (TreeNode n = start.getParent(); n != stop; n = n.getParent()) {
|
||||
if (n == null) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Non-crossing paths detected - start: %s, stop: %s", new TreePath(start), new TreePath(stop)
|
||||
));
|
||||
}
|
||||
result = n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int distance(@NotNull TreeNode parent, @NotNull TreeNode child) {
|
||||
if (parent == child) {
|
||||
return 1;
|
||||
}
|
||||
int result = 1;
|
||||
for (TreeNode n = child; n != null && n != parent; n = n.getParent()) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uiParentNode UI tree node which should hold UI nodes created for representing given settings node
|
||||
* @param settingsNode settings node which should be represented at the UI tree denoted by the given UI tree node
|
||||
* @return pair {@code (bottom-most leaf node created; number of rows created)}
|
||||
*/
|
||||
@NotNull
|
||||
public static Pair<DefaultMutableTreeNode, Integer> map(@NotNull DefaultMutableTreeNode uiParentNode,
|
||||
@NotNull HierarchicalArrangementSettingsNode settingsNode)
|
||||
{
|
||||
DefaultMutableTreeNode uiNode = null;
|
||||
int rowsCreated = 0;
|
||||
for (int i = uiParentNode.getChildCount() - 1; i >= 0; i--) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode)uiParentNode.getChildAt(i);
|
||||
if (settingsNode.getCurrent().equals(child.getUserObject())) {
|
||||
uiNode = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uiNode == null) {
|
||||
uiNode = new DefaultMutableTreeNode(settingsNode.getCurrent());
|
||||
uiParentNode.add(uiNode);
|
||||
rowsCreated++;
|
||||
}
|
||||
DefaultMutableTreeNode leaf = uiNode;
|
||||
HierarchicalArrangementSettingsNode childSettingsNode = settingsNode.getChild();
|
||||
if (childSettingsNode != null) {
|
||||
Pair<DefaultMutableTreeNode, Integer> pair = map(uiNode, childSettingsNode);
|
||||
leaf = pair.first;
|
||||
rowsCreated += pair.second;
|
||||
}
|
||||
return Pair.create(leaf, rowsCreated);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public class ArrangementNodeComponentFactory {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
switch (node.getOperator()) {
|
||||
case AND: ref.set(new ArrangementAndNodeComponent(node, ArrangementNodeComponentFactory.this)); break;
|
||||
case AND: ref.set(new ArrangementAndNodeComponent(node, ArrangementNodeComponentFactory.this, myDisplayManager)); break;
|
||||
case OR: // TODO den implement
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -21,6 +21,8 @@ import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
/**
|
||||
* Combines and encapsulates information about arrangement matcher rules representation (tree nodes) and
|
||||
* underlying {@link ArrangementSettingsNode data model}.
|
||||
@@ -48,4 +50,10 @@ public interface ArrangementRuleEditingModel {
|
||||
void addAndCondition(@NotNull ArrangementSettingsAtomNode node);
|
||||
|
||||
void removeAndCondition(@NotNull ArrangementSettingsNode node);
|
||||
|
||||
void addListener(@NotNull Listener listener);
|
||||
|
||||
interface Listener {
|
||||
void onChanged(@NotNull TreeNode topMost, @NotNull TreeNode bottomMost);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-29
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
|
||||
@@ -91,9 +92,12 @@ public class ArrangementRuleEditingModelBuilder {
|
||||
}
|
||||
|
||||
HierarchicalArrangementSettingsNode grouped = grouper.group(setting);
|
||||
int rowsCreated = map(root, grouped);
|
||||
ArrangementRuleEditingModelImpl model = new ArrangementRuleEditingModelImpl(setting);
|
||||
rowMappings.put(initialInsertRow + rowsCreated - 1, model);
|
||||
Pair<DefaultMutableTreeNode, Integer> pair = ArrangementConfigUtil.map(root, grouped);
|
||||
DefaultMutableTreeNode topMostNode = (DefaultMutableTreeNode)ArrangementConfigUtil.getLastBefore(pair.first, root);
|
||||
int row = initialInsertRow + pair.second - 1;
|
||||
ArrangementRuleEditingModelImpl model
|
||||
= new ArrangementRuleEditingModelImpl(setting, topMostNode, pair.first, grouper, rowMappings, row);
|
||||
rowMappings.put(row, model);
|
||||
}
|
||||
|
||||
private static int calculateRowsCount(@NotNull TreeNode node) {
|
||||
@@ -103,30 +107,4 @@ public class ArrangementRuleEditingModelBuilder {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uiParentNode UI tree node which should hold UI nodes created for representing given settings node
|
||||
* @param settingsNode settings node which should be represented at the UI tree denoted by the given UI tree node
|
||||
* @return number of rows created
|
||||
*/
|
||||
private static int map(@NotNull DefaultMutableTreeNode uiParentNode, @NotNull HierarchicalArrangementSettingsNode settingsNode) {
|
||||
DefaultMutableTreeNode uiNode = null;
|
||||
int result = 0;
|
||||
for (int i = uiParentNode.getChildCount() - 1; i >= 0; i--) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode)uiParentNode.getChildAt(i);
|
||||
if (settingsNode.getCurrent().equals(child.getUserObject())) {
|
||||
uiNode = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uiNode == null) {
|
||||
uiNode = new DefaultMutableTreeNode(settingsNode.getCurrent());
|
||||
uiParentNode.add(uiNode);
|
||||
result++;
|
||||
}
|
||||
for (HierarchicalArrangementSettingsNode childSettingsNode : settingsNode.getChildren()) {
|
||||
result += map(uiNode, childSettingsNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+120
-21
@@ -15,40 +15,76 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
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 com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/15/12 2:40 PM
|
||||
*/
|
||||
public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingModel {
|
||||
|
||||
@NotNull private final Set<Object> myConditions = new HashSet<Object>();
|
||||
@NotNull private static final MyConditionsBuilder CONDITIONS_BUILDER = new MyConditionsBuilder();
|
||||
|
||||
@NotNull private final Set<Listener> myListeners = new HashSet<Listener>();
|
||||
@NotNull private final Set<Object> myConditions = new HashSet<Object>();
|
||||
|
||||
@NotNull private final TIntObjectHashMap<ArrangementRuleEditingModel> myRowMappings;
|
||||
@NotNull private final ArrangementSettingsGrouper myGrouper;
|
||||
|
||||
@NotNull private DefaultMutableTreeNode myTopMost;
|
||||
@NotNull private DefaultMutableTreeNode myBottomMost;
|
||||
@NotNull private ArrangementSettingsNode mySettingsNode;
|
||||
private int myRow;
|
||||
|
||||
public ArrangementRuleEditingModelImpl(@NotNull ArrangementSettingsNode node) {
|
||||
/**
|
||||
* Creates new <code>ArrangementRuleEditingModelImpl</code> object.
|
||||
*
|
||||
* @param node backing settings node
|
||||
* @param topMost there is a possible case that a single settings node is shown in more than one visual line
|
||||
* ({@link HierarchicalArrangementSettingsNode}). This argument is the top-most UI node used for the
|
||||
* settings node representation
|
||||
* @param bottomMost bottom-most UI node used for the given settings node representation
|
||||
* @param grouper strategy that encapsulates information on how settings node should be displayed
|
||||
* @param mappings {@code 'row -> model'} mappings
|
||||
* @param row row number for which current model is registered at the given model mappings
|
||||
*/
|
||||
public ArrangementRuleEditingModelImpl(@NotNull ArrangementSettingsNode node,
|
||||
@NotNull DefaultMutableTreeNode topMost,
|
||||
@NotNull DefaultMutableTreeNode bottomMost,
|
||||
@NotNull ArrangementSettingsGrouper grouper,
|
||||
@NotNull TIntObjectHashMap<ArrangementRuleEditingModel> mappings,
|
||||
int row)
|
||||
{
|
||||
mySettingsNode = node;
|
||||
node.invite(new ArrangementSettingsNodeVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
myConditions.add(node.getValue());
|
||||
}
|
||||
myTopMost = topMost;
|
||||
myBottomMost = bottomMost;
|
||||
myGrouper = grouper;
|
||||
myRowMappings = mappings;
|
||||
myRow = row;
|
||||
extractConditions(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
for (ArrangementSettingsNode operand : node.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
private void extractConditions(@NotNull ArrangementSettingsNode node) {
|
||||
myConditions.clear();
|
||||
CONDITIONS_BUILDER.conditions = myConditions;
|
||||
try {
|
||||
node.invite(CONDITIONS_BUILDER);
|
||||
}
|
||||
finally {
|
||||
CONDITIONS_BUILDER.conditions = null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -64,11 +100,74 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
|
||||
|
||||
@Override
|
||||
public void addAndCondition(@NotNull ArrangementSettingsAtomNode node) {
|
||||
// TODO den implement
|
||||
doAddAndCondition(node);
|
||||
extractConditions(mySettingsNode);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
private void doAddAndCondition(@NotNull ArrangementSettingsAtomNode node) {
|
||||
ArrangementSettingsNode newNode = ArrangementUtil.and(mySettingsNode.clone(), node);
|
||||
HierarchicalArrangementSettingsNode grouped = myGrouper.group(newNode);
|
||||
int newDepth = ArrangementConfigUtil.getDepth(grouped);
|
||||
int oldDepth = ArrangementConfigUtil.distance(myTopMost, myBottomMost);
|
||||
if (newDepth == oldDepth) {
|
||||
mySettingsNode = newNode;
|
||||
myBottomMost.setUserObject(ArrangementConfigUtil.getLast(grouped).getCurrent());
|
||||
return;
|
||||
}
|
||||
|
||||
mySettingsNode = newNode;
|
||||
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)myTopMost.getParent();
|
||||
parent.remove(myTopMost);
|
||||
Pair<DefaultMutableTreeNode,Integer> pair = ArrangementConfigUtil.map(parent, grouped);
|
||||
myTopMost = (DefaultMutableTreeNode)ArrangementConfigUtil.getLastBefore(pair.first, parent);
|
||||
myBottomMost = pair.first;
|
||||
int depthShift = newDepth - oldDepth;
|
||||
int[] rows = myRowMappings.keys();
|
||||
Arrays.sort(rows);
|
||||
for (int i = rows.length - 1; i >= 0; i--) {
|
||||
int row = rows[i];
|
||||
if (row >= myRow) {
|
||||
myRowMappings.put(row + depthShift, myRowMappings.get(row));
|
||||
myRowMappings.remove(row);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
myRow += depthShift;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAndCondition(@NotNull ArrangementSettingsNode node) {
|
||||
// TODO den implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(@NotNull Listener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (Listener listener : myListeners) {
|
||||
listener.onChanged(myTopMost, myBottomMost);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyConditionsBuilder implements ArrangementSettingsNodeVisitor {
|
||||
|
||||
@NotNull Set<Object> conditions;
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
conditions.add(node.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
for (ArrangementSettingsNode operand : node.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/15/12 9:14 AM
|
||||
*/
|
||||
public interface ArrangementRuleEditingListener {
|
||||
public interface ArrangementRuleSelectionListener {
|
||||
|
||||
void startEditing(@NotNull ArrangementRuleEditingModel settings);
|
||||
void onSelected(@NotNull ArrangementRuleEditingModel settings);
|
||||
|
||||
void stopEditing();
|
||||
void selectionRemoved();
|
||||
}
|
||||
+60
-13
@@ -46,14 +46,18 @@ import java.util.List;
|
||||
*/
|
||||
public class ArrangementRuleTree {
|
||||
|
||||
@NotNull private final List<ArrangementRuleEditingListener> myListeners = new ArrayList<ArrangementRuleEditingListener>();
|
||||
@NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel();
|
||||
@NotNull private static final JLabel EMPTY_RENDERER = new JLabel("");
|
||||
|
||||
@NotNull private final List<ArrangementRuleSelectionListener> myListeners = new ArrayList<ArrangementRuleSelectionListener>();
|
||||
@NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel();
|
||||
@NotNull private final MyModelChangeListener myModelChangeListener = new MyModelChangeListener();
|
||||
|
||||
@NotNull private final TIntObjectHashMap<ArrangementNodeComponent> myRenderers =
|
||||
new TIntObjectHashMap<ArrangementNodeComponent>();
|
||||
@NotNull private final TIntObjectHashMap<ArrangementRuleEditingModel> myModels =
|
||||
new TIntObjectHashMap<ArrangementRuleEditingModel>();
|
||||
|
||||
@NotNull private final DefaultTreeModel myTreeModel;
|
||||
@NotNull private final Tree myTree;
|
||||
@NotNull private final ArrangementNodeComponentFactory myFactory;
|
||||
|
||||
@@ -62,8 +66,8 @@ public class ArrangementRuleTree {
|
||||
public ArrangementRuleTree(@NotNull ArrangementSettingsGrouper grouper, @NotNull ArrangementNodeDisplayManager displayManager) {
|
||||
myFactory = new ArrangementNodeComponentFactory(displayManager);
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel(root);
|
||||
myTree = new Tree(treeModel) {
|
||||
myTreeModel = new DefaultTreeModel(root);
|
||||
myTree = new Tree(myTreeModel) {
|
||||
@Override
|
||||
protected void setExpandedState(TreePath path, boolean state) {
|
||||
// Don't allow node collapse
|
||||
@@ -85,7 +89,7 @@ public class ArrangementRuleTree {
|
||||
try {
|
||||
super.processMouseEvent(e);
|
||||
if (mySkipSelectionChange) {
|
||||
notifyEditingListeners(null);
|
||||
notifySelectionListeners(null);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -172,9 +176,16 @@ public class ArrangementRuleTree {
|
||||
for (ArrangementSettingsNode setting : settings) {
|
||||
builder.build(setting, myTree, root, grouper, myModels);
|
||||
}
|
||||
myModels.forEachValue(new TObjectProcedure<ArrangementRuleEditingModel>() {
|
||||
@Override
|
||||
public boolean execute(ArrangementRuleEditingModel model) {
|
||||
model.addListener(myModelChangeListener);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addEditingListener(@NotNull ArrangementRuleEditingListener listener) {
|
||||
public void addEditingListener(@NotNull ArrangementRuleSelectionListener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
@@ -271,17 +282,37 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyEditingListeners(@Nullable ArrangementRuleEditingModel model) {
|
||||
for (ArrangementRuleEditingListener listener : myListeners) {
|
||||
private void notifySelectionListeners(@Nullable ArrangementRuleEditingModel model) {
|
||||
for (ArrangementRuleSelectionListener listener : myListeners) {
|
||||
if (model == null) {
|
||||
listener.stopEditing();
|
||||
listener.selectionRemoved();
|
||||
}
|
||||
else {
|
||||
listener.startEditing(model);
|
||||
listener.onSelected(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onModelChange(@NotNull TreeNode topMost, @NotNull TreeNode bottomMost) {
|
||||
mySkipSelectionChange = true;
|
||||
try {
|
||||
for (DefaultMutableTreeNode node = (DefaultMutableTreeNode)bottomMost; node != null; node = (DefaultMutableTreeNode)node.getParent()) {
|
||||
TreePath path = new TreePath(node.getPath());
|
||||
int row = myTree.getRowForPath(path);
|
||||
myRenderers.remove(row);
|
||||
myTreeModel.nodeChanged(node);
|
||||
mySelectionModel.addSelectionPath(path);
|
||||
getNodeComponentAt(row, (ArrangementSettingsNode)node.getUserObject()).setSelected(true);
|
||||
if (node == topMost) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySkipSelectionChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCellRenderer implements TreeCellRenderer {
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree,
|
||||
@@ -290,8 +321,10 @@ public class ArrangementRuleTree {
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus)
|
||||
{
|
||||
boolean hasFocus) {
|
||||
if (row < 0) {
|
||||
return EMPTY_RENDERER;
|
||||
}
|
||||
ArrangementSettingsNode node = (ArrangementSettingsNode)((DefaultMutableTreeNode)value).getUserObject();
|
||||
return getNodeComponentAt(row, node).getUiComponent();
|
||||
}
|
||||
@@ -299,12 +332,26 @@ public class ArrangementRuleTree {
|
||||
|
||||
private class MySelectionModel extends DefaultTreeSelectionModel {
|
||||
|
||||
@Override
|
||||
public void addSelectionPath(TreePath path) {
|
||||
if (!mySkipSelectionChange) {
|
||||
super.addSelectionPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionPath(TreePath path) {
|
||||
if (!mySkipSelectionChange) {
|
||||
super.setSelectionPath(path);
|
||||
notifyEditingListeners(getActiveModel());
|
||||
notifySelectionListeners(getActiveModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyModelChangeListener implements ArrangementRuleEditingModel.Listener {
|
||||
@Override
|
||||
public void onChanged(@NotNull TreeNode topMost, @NotNull TreeNode bottomMost) {
|
||||
onModelChange(topMost, bottomMost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -79,9 +79,9 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
}
|
||||
}
|
||||
});
|
||||
ruleTree.addEditingListener(new ArrangementRuleEditingListener() {
|
||||
ruleTree.addEditingListener(new ArrangementRuleSelectionListener() {
|
||||
@Override
|
||||
public void startEditing(@NotNull ArrangementRuleEditingModel model) {
|
||||
public void onSelected(@NotNull ArrangementRuleEditingModel model) {
|
||||
ruleEditor.updateState(model);
|
||||
resetEditor.set(Boolean.FALSE);
|
||||
try {
|
||||
@@ -93,7 +93,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopEditing() {
|
||||
public void selectionRemoved() {
|
||||
editorPane.setCollapsed(true);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user