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-IDE
Re-organizing arrangement UI - tree -> list
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.application.options;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementSettingsPanel;
|
||||
import com.intellij.application.options.codeStyle.arrangement.newui.ArrangementSettingsPanel2;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/12 8:57 AM
|
||||
*/
|
||||
public class JavaArrangementPanel extends ArrangementSettingsPanel {
|
||||
public class JavaArrangementPanel extends ArrangementSettingsPanel2 {
|
||||
|
||||
public JavaArrangementPanel(@NotNull CodeStyleSettings settings) {
|
||||
super(settings, JavaLanguage.INSTANCE);
|
||||
|
||||
@@ -154,7 +154,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
|
||||
return;
|
||||
}
|
||||
|
||||
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition();
|
||||
for (Object condition : conditions) {
|
||||
composite.addOperand(new ArrangementAtomMatchCondition(ArrangementUtil.parseType(condition), condition));
|
||||
}
|
||||
|
||||
-98
@@ -1,98 +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.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.JavaRearranger;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
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 ArrangementTreeNode myRoot;
|
||||
@NotNull protected TIntObjectHashMap<ArrangementRuleEditingModelImpl> myRowMappings;
|
||||
@NotNull protected List<Set<ArrangementMatchCondition>> myGroupingRules;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
myBuilder = new ArrangementRuleEditingModelBuilder();
|
||||
myRoot = new ArrangementTreeNode(null);
|
||||
myTree = new Tree(myRoot);
|
||||
myTree.expandPath(new TreePath(myRoot));
|
||||
myRowMappings = new TIntObjectHashMap<ArrangementRuleEditingModelImpl>();
|
||||
myGroupingRules = ContainerUtilRt.newArrayList();
|
||||
myGroupingRules.add(ContainerUtilRt.<ArrangementMatchCondition>newHashSet(
|
||||
atom(ArrangementEntryType.FIELD), atom(ArrangementEntryType.METHOD)
|
||||
));
|
||||
}
|
||||
|
||||
protected void configure(@NotNull ArrangementMatchCondition matchCondition) {
|
||||
Pair<ArrangementRuleEditingModelImpl, TIntIntHashMap> pair = myBuilder.build(
|
||||
new StdArrangementMatchRule(new StdArrangementEntryMatcher(matchCondition)), myTree, myRoot, null, myGroupingRules
|
||||
);
|
||||
assertNotNull(pair);
|
||||
myRowMappings.put(pair.first.getRow(), pair.first);
|
||||
}
|
||||
|
||||
protected static ArrangementAtomMatchCondition 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 ArrangementAtomMatchCondition(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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
-507
@@ -1,507 +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.psi.codeStyle.arrangement.model.ArrangementSettingType
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition
|
||||
import gnu.trove.TIntIntHashMap
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.junit.Test
|
||||
|
||||
import javax.swing.tree.DefaultTreeModel
|
||||
|
||||
import static org.junit.Assert.assertEquals
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/17/12 1:12 PM
|
||||
*/
|
||||
@SuppressWarnings(["GroovyAssignabilityCheck", "GroovyVariableNotAssigned"])
|
||||
class ArrangementConfigUtilTest {
|
||||
|
||||
@Test
|
||||
void replace() {
|
||||
// Init.
|
||||
def one;
|
||||
def four;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
one = '1' {
|
||||
'2' {
|
||||
'3'()
|
||||
four = '4'()
|
||||
'5'()}
|
||||
'6'()}
|
||||
}
|
||||
|
||||
// Modify.
|
||||
def replacement = new TreeNodeBuilder().
|
||||
'1' {
|
||||
'4'()
|
||||
}
|
||||
def rowMappings = doReplace(one, four, replacement)
|
||||
|
||||
// Check
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2' {
|
||||
'3'()}
|
||||
'4'()
|
||||
'2' {
|
||||
'5'()}
|
||||
'6'()}
|
||||
}
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([5 : 6, 6 : 7], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceWithMergeToNodeAbove() {
|
||||
// Init.
|
||||
def from;
|
||||
def to;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'() {
|
||||
'2'()
|
||||
'3'()}
|
||||
from = '4' {
|
||||
to = '5'()
|
||||
'6'()}
|
||||
}
|
||||
|
||||
// Modify.
|
||||
def replacement = new TreeNodeBuilder().
|
||||
'1' {
|
||||
'5'()
|
||||
}
|
||||
def rowMappings = doReplace(from, to, replacement)
|
||||
|
||||
// Check.
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()
|
||||
'3'()
|
||||
'5'()}
|
||||
'4' {
|
||||
'6'()}
|
||||
}
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([:], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceWithTwoLevelMergeToNodeAbove() {
|
||||
// Init.
|
||||
def node;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'() {
|
||||
'2'()
|
||||
'3'()}
|
||||
node = '4'()
|
||||
'5'() {
|
||||
'6'()}
|
||||
}
|
||||
|
||||
// Modify.
|
||||
def replacement = new TreeNodeBuilder().
|
||||
'1' {
|
||||
'4'()
|
||||
}
|
||||
def rowMappings = doReplace(node, node, replacement)
|
||||
|
||||
// Check.
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()
|
||||
'3'()
|
||||
'4'()}
|
||||
'5' {
|
||||
'6'()}
|
||||
}
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([:], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceWithTwoLevelMergeToNodeBelow() {
|
||||
// Init.
|
||||
def from;
|
||||
def to;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
from = '1'() {
|
||||
'2'()
|
||||
to = '3'()}
|
||||
'4'() {
|
||||
'5'() }
|
||||
}
|
||||
|
||||
// Modify.
|
||||
def replacement = new TreeNodeBuilder().
|
||||
'4' {
|
||||
'3'()
|
||||
}
|
||||
def rowMappings = doReplace(from, to, replacement)
|
||||
|
||||
// Check.
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()}
|
||||
'4' {
|
||||
'3'()
|
||||
'5'()}
|
||||
}
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([:], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceFirstChildWithMergeBelow() {
|
||||
// Init.
|
||||
def from;
|
||||
def to;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
from = '1'() {
|
||||
to = '2'()}
|
||||
'3'() {
|
||||
'4'() }
|
||||
'1' {
|
||||
'5'()
|
||||
'6'()}
|
||||
}
|
||||
|
||||
// Modify.
|
||||
def replacement = new TreeNodeBuilder().
|
||||
'3' {
|
||||
'2'()
|
||||
}
|
||||
def rowMappings = doReplace(from, to, replacement)
|
||||
|
||||
// Check.
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'3' {
|
||||
'2'()
|
||||
'4'()}
|
||||
'1' {
|
||||
'5'()
|
||||
'6'()}
|
||||
}
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([ 4 : 3, 5 : 4, 6 : 5, 7 : 6 ], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void addWithoutMergeAbove() {
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
def toAdd = new TreeNodeBuilder().
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
doInsert(initial, 0, toAdd)
|
||||
assertNodesEqual(expected, initial)
|
||||
}
|
||||
|
||||
@Test
|
||||
void addWithMergeAbove() {
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
def toAdd = new TreeNodeBuilder().
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
doInsert(initial, 1, toAdd)
|
||||
assertNodesEqual(expected, initial)
|
||||
}
|
||||
|
||||
@Test
|
||||
void addWithMergeBelow() {
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
def toAdd = new TreeNodeBuilder().
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
doInsert(initial, 2, toAdd)
|
||||
assertNodesEqual(expected, initial)
|
||||
}
|
||||
|
||||
@Test
|
||||
void addWithoutMergeBelow() {
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
}
|
||||
|
||||
def toAdd = new TreeNodeBuilder().
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1'()
|
||||
'2' {
|
||||
'3' {
|
||||
'4'()
|
||||
}
|
||||
}
|
||||
'5'()
|
||||
'2' {
|
||||
'3' {
|
||||
'6'()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doInsert(initial, 3, toAdd)
|
||||
assertNodesEqual(expected, initial)
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFirst() {
|
||||
def from;
|
||||
def to;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
from = '1' {
|
||||
to = '2'()
|
||||
'3'()}
|
||||
'4'()
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'3'()}
|
||||
'4'()
|
||||
}
|
||||
|
||||
def rowMappings = doRemove(from, to)
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([ 3 : 2, 4 : 3 ], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeWithMerge() {
|
||||
def from;
|
||||
def to;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()}
|
||||
from = '3'() {
|
||||
to = '4'()}
|
||||
'1' {
|
||||
'5'()}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()
|
||||
'5'()}
|
||||
}
|
||||
|
||||
def rowMappings = doRemove(from, to)
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([ 6 : 3 ], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeSingleNodeWithMerge() {
|
||||
def node;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()}
|
||||
node = '3'()
|
||||
'1' {
|
||||
'4'()}
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()
|
||||
'4'()}
|
||||
}
|
||||
|
||||
def rowMappings = doRemove(node, node)
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([ 5 : 3 ], rowMappings)
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeWithSingleNodeBelowMerge() {
|
||||
def node;
|
||||
def initial = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()}
|
||||
node = '3'()
|
||||
'1'()
|
||||
}
|
||||
|
||||
def expected = new TreeNodeBuilder().
|
||||
'0' {
|
||||
'1' {
|
||||
'2'()}
|
||||
'1'()
|
||||
}
|
||||
|
||||
def rowMappings = doRemove(node, node)
|
||||
assertNodesEqual(expected, initial)
|
||||
checkRowMappings([ 4 : 3 ], rowMappings)
|
||||
}
|
||||
|
||||
private static def doReplace(from, to, replacement) {
|
||||
ArrangementConfigUtil.replace(from, to, replacement, new DefaultTreeModel(ArrangementConfigUtil.getRoot(from)), true)
|
||||
}
|
||||
|
||||
private static def doInsert(parent, i, child) {
|
||||
ArrangementConfigUtil.insert(parent, i, child, new DefaultTreeModel(ArrangementConfigUtil.getRoot(parent)))
|
||||
}
|
||||
|
||||
private static def doRemove(from, to) {
|
||||
ArrangementConfigUtil.remove(from, to, new DefaultTreeModel(ArrangementConfigUtil.getRoot(from)), true)
|
||||
}
|
||||
|
||||
private static void assertNodesEqual(@NotNull ArrangementTreeNode expected, @NotNull ArrangementTreeNode actual) {
|
||||
assertEquals(expected.userObject, actual.userObject)
|
||||
assertEquals(expected.childCount, actual.childCount)
|
||||
for (i in 0..<expected.childCount) {
|
||||
assertNodesEqual(expected.getChildAt(i), actual.getChildAt(i))
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkRowMappings(@NotNull Map<Integer, Integer> expected, @NotNull TIntIntHashMap actual) {
|
||||
assertEquals(expected.size(), actual.size())
|
||||
expected.each {key, value -> assertEquals(value, actual.get(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
public class TreeNodeBuilder extends BuilderSupport {
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name) {
|
||||
def result = new ArrangementTreeNode(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, name))
|
||||
currentNode?.add(result)
|
||||
result
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ArrangementTreeNode getCurrentNode() {
|
||||
getCurrent() as ArrangementTreeNode
|
||||
}
|
||||
|
||||
@Override protected void setParent(Object parent, Object child) { }
|
||||
@Override protected Object createNode(Object name, Object value) { throw new UnsupportedOperationException() }
|
||||
@Override protected Object createNode(Object name, Map attributes) { throw new UnsupportedOperationException() }
|
||||
@Override protected Object createNode(Object name, Map attributes, Object value) { throw new UnsupportedOperationException() }
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
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.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 08/15/2012
|
||||
*/
|
||||
public class ArrangementRuleEditingModelBuilderTest extends AbstractArrangementRuleEditingModelTest {
|
||||
|
||||
@Test
|
||||
public void mapToTheSameLayer() {
|
||||
configure(and(atom(PUBLIC), atom(STATIC)));
|
||||
checkRows(1);
|
||||
ArrangementRuleEditingModel model = myRowMappings.get(1);
|
||||
assertTrue(model.hasCondition(PUBLIC));
|
||||
assertTrue(model.hasCondition(STATIC));
|
||||
assertFalse(model.hasCondition(PRIVATE));
|
||||
assertEquals(1, myRoot.getChildCount());
|
||||
assertEquals(and(atom(PUBLIC), atom(STATIC)), myRoot.getFirstChild().getBackingCondition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitIntoTwoLayers() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC), atom(STATIC)));
|
||||
|
||||
checkRows(2);
|
||||
|
||||
ArrangementTreeNode fieldUiNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldUiNode);
|
||||
assertEquals(atom(FIELD), fieldUiNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode modifiersUiNode = fieldUiNode.getFirstChild();
|
||||
assertNotNull(modifiersUiNode);
|
||||
assertEquals(and(atom(PUBLIC), atom(STATIC)), modifiersUiNode.getBackingCondition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addToExistingLayer() {
|
||||
configure(and(atom(PUBLIC), atom(STATIC), atom(FIELD)));
|
||||
configure(and(atom(PRIVATE), atom(FIELD)));
|
||||
|
||||
checkRows(2, 3);
|
||||
|
||||
ArrangementTreeNode fieldUiNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldUiNode);
|
||||
assertEquals(atom(FIELD), fieldUiNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode publicStaticUiNode = fieldUiNode.getFirstChild();
|
||||
assertNotNull(publicStaticUiNode);
|
||||
assertEquals(and(atom(PUBLIC), atom(STATIC)), publicStaticUiNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode privateUiNode = fieldUiNode.getLastChild();
|
||||
assertNotNull(privateUiNode);
|
||||
assertEquals(atom(PRIVATE), privateUiNode.getBackingCondition());
|
||||
}
|
||||
}
|
||||
-197
@@ -1,197 +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.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* @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));
|
||||
|
||||
ArrangementTreeNode child = myRoot.getFirstChild();
|
||||
assertNotNull(child);
|
||||
ArrangementMatchCondition expectedMatchCondition = and(atom(PUBLIC), atom(STATIC));
|
||||
assertEquals(expectedMatchCondition, child.getBackingCondition());
|
||||
assertEquals(expectedMatchCondition, model.getCondition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildNewSingleLevel() {
|
||||
configure(atom(PUBLIC));
|
||||
ArrangementRuleEditingModelImpl model = myRowMappings.get(1);
|
||||
assertNotNull(model);
|
||||
assertEquals(1, myRowMappings.size());
|
||||
|
||||
model.addAndCondition(atom(FIELD));
|
||||
|
||||
assertEquals(2, model.getRow());
|
||||
assertEquals(and(atom(FIELD), atom(PUBLIC)), model.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode publicNode = fieldNode.getFirstChild();
|
||||
assertNotNull(publicNode);
|
||||
assertEquals(atom(PUBLIC), publicNode.getBackingCondition());
|
||||
}
|
||||
|
||||
@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.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode modifiersNode = fieldNode.getFirstChild();
|
||||
assertNotNull(modifiersNode);
|
||||
assertEquals(and(atom(PUBLIC), atom(STATIC)), modifiersNode.getBackingCondition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAndKeepAllLevels() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC), atom(STATIC)));
|
||||
ArrangementRuleEditingModelImpl model = myRowMappings.get(2);
|
||||
assertNotNull(model);
|
||||
assertEquals(1, myRowMappings.size());
|
||||
|
||||
model.removeAndCondition(atom(PUBLIC));
|
||||
|
||||
assertEquals(1, myRowMappings.size());
|
||||
assertSame(model, myRowMappings.get(2));
|
||||
assertEquals(and(atom(FIELD), atom(STATIC)), model.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode modifiersNode = fieldNode.getFirstChild();
|
||||
assertNotNull(modifiersNode);
|
||||
assertEquals(atom(STATIC), modifiersNode.getBackingCondition());
|
||||
|
||||
checkModelTreeNodesConsistency(model);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeLastRowCondition() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC)));
|
||||
ArrangementRuleEditingModelImpl model = myRowMappings.get(2);
|
||||
assertNotNull(model);
|
||||
assertEquals(1, myRowMappings.size());
|
||||
|
||||
model.removeAndCondition(atom(PUBLIC));
|
||||
|
||||
assertEquals(1, model.getRow());
|
||||
assertEquals(atom(FIELD), model.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
assertEquals(0, fieldNode.getChildCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeFirstRowConditionFromMultiChildrenParent() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC)));
|
||||
configure(and(atom(FIELD), atom(STATIC)));
|
||||
|
||||
ArrangementRuleEditingModelImpl modelToChange = myRowMappings.get(2);
|
||||
assertNotNull(modelToChange);
|
||||
|
||||
ArrangementRuleEditingModelImpl siblingModel = myRowMappings.get(3);
|
||||
assertNotNull(siblingModel);
|
||||
assertEquals(2, myRowMappings.size());
|
||||
|
||||
modelToChange.removeAndCondition(atom(PUBLIC));
|
||||
|
||||
assertSame(3, siblingModel.getRow());
|
||||
assertEquals(and(atom(FIELD), atom(STATIC)), siblingModel.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode staticNode = fieldNode.getFirstChild();
|
||||
assertNotNull(staticNode);
|
||||
assertEquals(atom(STATIC), staticNode.getBackingCondition());
|
||||
|
||||
assertNull(staticNode.getNextNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeLastRowConditionFromMultiChildrenParent() {
|
||||
configure(and(atom(FIELD), atom(PUBLIC)));
|
||||
configure(and(atom(FIELD), atom(STATIC)));
|
||||
|
||||
assertEquals(2, myRowMappings.size());
|
||||
ArrangementRuleEditingModel siblingModel = myRowMappings.get(2);
|
||||
assertNotNull(siblingModel);
|
||||
|
||||
ArrangementRuleEditingModel modelToChange = myRowMappings.get(3);
|
||||
assertNotNull(modelToChange);
|
||||
|
||||
modelToChange.removeAndCondition(atom(STATIC));
|
||||
|
||||
assertEquals(2, myRowMappings.size());
|
||||
assertSame(siblingModel, myRowMappings.get(2));
|
||||
assertEquals(and(atom(FIELD), atom(PUBLIC)), siblingModel.getCondition());
|
||||
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode publicNode = fieldNode.getFirstChild();
|
||||
assertNotNull(publicNode);
|
||||
assertEquals(atom(PUBLIC), publicNode.getBackingCondition());
|
||||
|
||||
assertNull(publicNode.getNextNode());
|
||||
}
|
||||
|
||||
private void checkModelTreeNodesConsistency(@NotNull ArrangementRuleEditingModelImpl model) {
|
||||
model.refreshTreeNodes();
|
||||
ArrangementTreeNode root = ArrangementConfigUtil.getRoot(model.getBottomMost());
|
||||
assertSame(myRoot, root);
|
||||
assertSame(root, ArrangementConfigUtil.getRoot(model.getTopMost()));
|
||||
}
|
||||
}
|
||||
+71
@@ -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.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/31/12 12:30 PM
|
||||
*/
|
||||
public class ArrangementConditionInfo {
|
||||
|
||||
@NotNull private final Set<ArrangementAtomMatchCondition> myAtomConditions = ContainerUtilRt.newHashSet();
|
||||
@NotNull private final Set<Object> myConditions = ContainerUtilRt.newHashSet();
|
||||
|
||||
public void addAtomCondition(@NotNull ArrangementAtomMatchCondition condition) {
|
||||
myAtomConditions.add(condition);
|
||||
myConditions.add(condition.getValue());
|
||||
}
|
||||
|
||||
public boolean hasCondition(@NotNull Object condition) {
|
||||
return myConditions.contains(condition);
|
||||
}
|
||||
|
||||
public void removeCondition(@NotNull Object condition) {
|
||||
if (!myConditions.remove(condition)) {
|
||||
return;
|
||||
}
|
||||
for (Iterator<ArrangementAtomMatchCondition> iterator = myAtomConditions.iterator(); iterator.hasNext(); ) {
|
||||
ArrangementAtomMatchCondition c = iterator.next();
|
||||
if (c.getValue().equals(condition)) {
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArrangementMatchCondition buildCondition() {
|
||||
if (myAtomConditions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (myAtomConditions.size() == 1) {
|
||||
return myAtomConditions.iterator().next();
|
||||
}
|
||||
else {
|
||||
return new ArrangementCompositeMatchCondition(myAtomConditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,6 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -63,8 +61,8 @@ public class ArrangementUtil {
|
||||
//endregion
|
||||
|
||||
@NotNull
|
||||
public static ArrangementMatchCondition and(@NotNull ArrangementMatchCondition... nodes) {
|
||||
final ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
public static ArrangementMatchCondition combine(@NotNull ArrangementMatchCondition... nodes) {
|
||||
final ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition();
|
||||
final ArrangementMatchConditionVisitor visitor = new ArrangementMatchConditionVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementAtomMatchCondition node) {
|
||||
@@ -73,13 +71,8 @@ public class ArrangementUtil {
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition node) {
|
||||
if (node.getOperator() == ArrangementOperator.AND) {
|
||||
for (ArrangementMatchCondition operand : node.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.addOperand(node);
|
||||
for (ArrangementMatchCondition operand : node.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -157,81 +150,6 @@ public class ArrangementUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("AssignmentToForLoopParameter")
|
||||
@NotNull
|
||||
public static HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition condition,
|
||||
@NotNull List<Set<ArrangementMatchCondition>> groupingRules)
|
||||
{
|
||||
if (groupingRules.isEmpty()) {
|
||||
// No grouping rules have been provided, use a flat structure.
|
||||
return new HierarchicalArrangementConditionNode(condition);
|
||||
}
|
||||
|
||||
final List<ArrangementMatchCondition> conditions = new ArrayList<ArrangementMatchCondition>();
|
||||
condition.invite(new ArrangementMatchConditionVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
|
||||
conditions.add(condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
|
||||
if (condition.getOperator() == ArrangementOperator.AND && conditions.isEmpty() /* Don't process nested composite conditions*/) {
|
||||
for (ArrangementMatchCondition operand : condition.getOperands()) {
|
||||
conditions.add(operand);
|
||||
}
|
||||
}
|
||||
else {
|
||||
conditions.add(condition);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (conditions.isEmpty()) {
|
||||
return new HierarchicalArrangementConditionNode(condition);
|
||||
}
|
||||
|
||||
HierarchicalArrangementConditionNode result = null;
|
||||
for (Set<ArrangementMatchCondition> rules : groupingRules) {
|
||||
for (ArrangementMatchCondition rule : rules) {
|
||||
for (int i = 0; i < conditions.size(); i++) {
|
||||
ArrangementMatchCondition c = conditions.get(i);
|
||||
if (rule.equals(c)) {
|
||||
conditions.remove(i--);
|
||||
HierarchicalArrangementConditionNode node = new HierarchicalArrangementConditionNode(c);
|
||||
if (result == null) {
|
||||
result = node;
|
||||
}
|
||||
else {
|
||||
result.setChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!conditions.isEmpty()) {
|
||||
HierarchicalArrangementConditionNode node;
|
||||
if (conditions.size() == 1) {
|
||||
node = new HierarchicalArrangementConditionNode(conditions.get(0));
|
||||
}
|
||||
else {
|
||||
ArrangementCompositeMatchCondition c = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
for (ArrangementMatchCondition operand : conditions) {
|
||||
c.addOperand(operand);
|
||||
}
|
||||
node = new HierarchicalArrangementConditionNode(c);
|
||||
}
|
||||
if (result == null) {
|
||||
result = node;
|
||||
}
|
||||
else {
|
||||
result.setChild(node);
|
||||
}
|
||||
}
|
||||
assert result != null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> Set<T> flatten(@NotNull Iterable<? extends Iterable<T>> data) {
|
||||
Set<T> result = ContainerUtilRt.newHashSet();
|
||||
for (Iterable<T> i : data) {
|
||||
@@ -241,4 +159,23 @@ public class ArrangementUtil {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ArrangementConditionInfo extractConditions(@NotNull ArrangementMatchCondition condition) {
|
||||
final ArrangementConditionInfo result = new ArrangementConditionInfo();
|
||||
condition.invite(new ArrangementMatchConditionVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
|
||||
result.addAtomCondition(condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
|
||||
for (ArrangementMatchCondition operand : condition.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-28
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi.codeStyle.arrangement.match;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
@@ -28,35 +27,19 @@ import java.util.*;
|
||||
public class CompositeArrangementEntryMatcher implements ArrangementEntryMatcher {
|
||||
|
||||
@NotNull private final Set<ArrangementEntryMatcher> myMatchers = new HashSet<ArrangementEntryMatcher>();
|
||||
@NotNull private final ArrangementOperator myOperator;
|
||||
|
||||
public CompositeArrangementEntryMatcher(@NotNull ArrangementOperator operator, @NotNull ArrangementEntryMatcher... matchers) {
|
||||
myOperator = operator;
|
||||
public CompositeArrangementEntryMatcher(@NotNull ArrangementEntryMatcher... matchers) {
|
||||
myMatchers.addAll(Arrays.asList(matchers));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatched(@NotNull ArrangementEntry entry) {
|
||||
for (ArrangementEntryMatcher matcher : myMatchers) {
|
||||
boolean matched = matcher.isMatched(entry);
|
||||
if (matched && myOperator == ArrangementOperator.OR) {
|
||||
return true;
|
||||
}
|
||||
else if (!matched && myOperator == ArrangementOperator.AND) {
|
||||
if (!matcher.isMatched(entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return myOperator == ArrangementOperator.AND;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementOperator getOperator() {
|
||||
return myOperator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<ArrangementEntryMatcher> getMatchers() {
|
||||
return myMatchers;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addMatcher(@NotNull ArrangementEntryMatcher rule) {
|
||||
@@ -65,9 +48,7 @@ public class CompositeArrangementEntryMatcher implements ArrangementEntryMatcher
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myMatchers.hashCode();
|
||||
result = 31 * result + myOperator.hashCode();
|
||||
return result;
|
||||
return myMatchers.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,14 +58,11 @@ public class CompositeArrangementEntryMatcher implements ArrangementEntryMatcher
|
||||
|
||||
CompositeArrangementEntryMatcher matcher = (CompositeArrangementEntryMatcher)o;
|
||||
|
||||
if (!myMatchers.equals(matcher.myMatchers)) return false;
|
||||
if (myOperator != matcher.myOperator) return false;
|
||||
|
||||
return true;
|
||||
return myMatchers.equals(matcher.myMatchers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s of those: %s", myOperator == ArrangementOperator.AND ? "all" : "any", myMatchers);
|
||||
return String.format("all of those: %s", myMatchers);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-10
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi.codeStyle.arrangement.match;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
@@ -72,14 +71,13 @@ public class DefaultArrangementEntryMatcherSerializer {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName());
|
||||
private static final Set<String> COMPOSITE_OPERATORS = new HashSet<String>();
|
||||
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName());
|
||||
|
||||
@NotNull private static final String COMPOSITE_CONDITION_NAME = "AND";
|
||||
|
||||
private static final Set<String> ATOM_SETTINGS_TYPES = new HashSet<String>();
|
||||
|
||||
static {
|
||||
for (ArrangementOperator operator : ArrangementOperator.values()) {
|
||||
COMPOSITE_OPERATORS.add(operator.toString());
|
||||
}
|
||||
for (ArrangementSettingType type : ArrangementSettingType.values()) {
|
||||
ATOM_SETTINGS_TYPES.add(type.toString());
|
||||
}
|
||||
@@ -115,7 +113,7 @@ public class DefaultArrangementEntryMatcherSerializer {
|
||||
@Nullable
|
||||
private static ArrangementMatchCondition deserializeCondition(@NotNull Element matcherElement) {
|
||||
String name = matcherElement.getName();
|
||||
if (!COMPOSITE_OPERATORS.contains(name)) {
|
||||
if (!COMPOSITE_CONDITION_NAME.equals(name)) {
|
||||
if (ATOM_SETTINGS_TYPES.contains(name)) {
|
||||
return deserializeAtomCondition(matcherElement);
|
||||
}
|
||||
@@ -123,13 +121,13 @@ public class DefaultArrangementEntryMatcherSerializer {
|
||||
LOG.warn(String.format(
|
||||
"Can't deserialize an arrangement entry matcher from matchElement with name '%s'. Reason: only the following elements"
|
||||
+ "are supported: %s and %s",
|
||||
name, COMPOSITE_OPERATORS, ATOM_SETTINGS_TYPES
|
||||
name, COMPOSITE_CONDITION_NAME, ATOM_SETTINGS_TYPES
|
||||
));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition(ArrangementOperator.valueOf(name));
|
||||
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition();
|
||||
for (Object child : matcherElement.getChildren()) {
|
||||
ArrangementMatchCondition deserialised = deserializeCondition((Element)child);
|
||||
if (deserialised != null) {
|
||||
@@ -175,7 +173,7 @@ public class DefaultArrangementEntryMatcherSerializer {
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
|
||||
Element composite = new Element(condition.getOperator().toString());
|
||||
Element composite = new Element(COMPOSITE_CONDITION_NAME);
|
||||
if (result == null) {
|
||||
result = composite;
|
||||
}
|
||||
|
||||
+2
-5
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi.codeStyle.arrangement.match;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
@@ -93,7 +92,6 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
|
||||
@NotNull private final Set<ArrangementEntryType> myTypes = EnumSet.noneOf(ArrangementEntryType.class);
|
||||
@NotNull private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
|
||||
|
||||
private ArrangementOperator myOperator;
|
||||
private boolean nestedComposite;
|
||||
|
||||
@Override
|
||||
@@ -110,7 +108,6 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
|
||||
if (!nestedComposite) {
|
||||
myOperator = condition.getOperator();
|
||||
nestedComposite = true;
|
||||
for (ArrangementMatchCondition c : condition.getOperands()) {
|
||||
c.invite(this);
|
||||
@@ -126,7 +123,7 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
|
||||
public ArrangementEntryMatcher getMatcher() {
|
||||
ByTypeArrangementEntryMatcher byType = myTypes.isEmpty() ? null : new ByTypeArrangementEntryMatcher(myTypes);
|
||||
ByModifierArrangementEntryMatcher byModifiers = myModifiers.isEmpty() ? null : new ByModifierArrangementEntryMatcher(myModifiers);
|
||||
if (byType == null && byModifiers == null && (myOperator == null || myMatchers.isEmpty())) {
|
||||
if (byType == null && byModifiers == null && myMatchers.isEmpty()) {
|
||||
return ArrangementEntryMatcher.EMPTY;
|
||||
}
|
||||
if (myMatchers.isEmpty() && (byType == null ^ byModifiers == null)) {
|
||||
@@ -136,7 +133,7 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
|
||||
return myMatchers.get(0);
|
||||
}
|
||||
else {
|
||||
CompositeArrangementEntryMatcher result = new CompositeArrangementEntryMatcher(myOperator);
|
||||
CompositeArrangementEntryMatcher result = new CompositeArrangementEntryMatcher();
|
||||
for (ArrangementEntryMatcher matcher : myMatchers) {
|
||||
result.addMatcher(matcher);
|
||||
}
|
||||
|
||||
+11
-23
@@ -16,10 +16,10 @@
|
||||
package com.intellij.psi.codeStyle.arrangement.model;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -33,10 +33,12 @@ import java.util.Set;
|
||||
public class ArrangementCompositeMatchCondition implements ArrangementMatchCondition {
|
||||
|
||||
@NotNull private final Set<ArrangementMatchCondition> myOperands = new HashSet<ArrangementMatchCondition>();
|
||||
@NotNull private final ArrangementOperator myOperator;
|
||||
|
||||
public ArrangementCompositeMatchCondition(@NotNull ArrangementOperator operator) {
|
||||
myOperator = operator;
|
||||
|
||||
public ArrangementCompositeMatchCondition() {
|
||||
}
|
||||
|
||||
public ArrangementCompositeMatchCondition(@NotNull Collection<? extends ArrangementMatchCondition> conditions) {
|
||||
myOperands.addAll(conditions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -54,11 +56,6 @@ public class ArrangementCompositeMatchCondition implements ArrangementMatchCondi
|
||||
myOperands.remove(condition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementOperator getOperator() {
|
||||
return myOperator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invite(@NotNull ArrangementMatchConditionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
@@ -67,7 +64,7 @@ public class ArrangementCompositeMatchCondition implements ArrangementMatchCondi
|
||||
@NotNull
|
||||
@Override
|
||||
public ArrangementCompositeMatchCondition clone() {
|
||||
ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(myOperator);
|
||||
ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition();
|
||||
for (ArrangementMatchCondition operand : myOperands) {
|
||||
result.addOperand(operand.clone());
|
||||
}
|
||||
@@ -76,9 +73,7 @@ public class ArrangementCompositeMatchCondition implements ArrangementMatchCondi
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myOperands.hashCode();
|
||||
result = 31 * result + myOperator.hashCode();
|
||||
return result;
|
||||
return myOperands.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,18 +87,11 @@ public class ArrangementCompositeMatchCondition implements ArrangementMatchCondi
|
||||
|
||||
ArrangementCompositeMatchCondition setting = (ArrangementCompositeMatchCondition)o;
|
||||
|
||||
if (!myOperands.equals(setting.myOperands)) {
|
||||
return false;
|
||||
}
|
||||
if (myOperator != setting.myOperator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return myOperands.equals(setting.myOperands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(%s)", StringUtil.join(myOperands, myOperator == ArrangementOperator.AND ? " and " : " or "));
|
||||
return String.format("(%s)", StringUtil.join(myOperands, " and "));
|
||||
}
|
||||
}
|
||||
|
||||
-57
@@ -1,57 +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.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* {@link #getCurrent() Wraps} {@link ArrangementMatchCondition} 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 HierarchicalArrangementConditionNode {
|
||||
|
||||
@NotNull private final ArrangementMatchCondition myCurrent;
|
||||
@Nullable private HierarchicalArrangementConditionNode myChild;
|
||||
|
||||
public HierarchicalArrangementConditionNode(@NotNull ArrangementMatchCondition current) {
|
||||
myCurrent = current;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementMatchCondition getCurrent() {
|
||||
return myCurrent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HierarchicalArrangementConditionNode getChild() {
|
||||
return myChild;
|
||||
}
|
||||
|
||||
public void setChild(@Nullable HierarchicalArrangementConditionNode child) {
|
||||
myChild = child;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myCurrent.toString();
|
||||
}
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/12/12 8:10 PM
|
||||
*/
|
||||
public class ArrangementUtilTest {
|
||||
|
||||
@Test
|
||||
public void oneLevelGroupingAndMultipleNonGroupedNodes() {
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
ArrangementMatchCondition abstractCondition =
|
||||
new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.ABSTRACT);
|
||||
ArrangementMatchCondition methodCondition
|
||||
= new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD);
|
||||
ArrangementMatchCondition publicCondition =
|
||||
new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC);
|
||||
condition.addOperand(abstractCondition);
|
||||
condition.addOperand(methodCondition);
|
||||
condition.addOperand(publicCondition);
|
||||
|
||||
HierarchicalArrangementConditionNode grouped =
|
||||
ArrangementUtil.group(condition, Collections.singletonList(Collections.singleton(methodCondition)));
|
||||
assertEquals(methodCondition, grouped.getCurrent());
|
||||
|
||||
HierarchicalArrangementConditionNode child = grouped.getChild();
|
||||
assertNotNull(child);
|
||||
ArrangementCompositeMatchCondition expectedChildCondition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
expectedChildCondition.addOperand(abstractCondition);
|
||||
expectedChildCondition.addOperand(publicCondition);
|
||||
assertEquals(expectedChildCondition, child.getCurrent());
|
||||
|
||||
assertNull(child.getChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneLevelGroupingAndSingleNonGroupedNode() {
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
ArrangementMatchCondition abstractCondition =
|
||||
new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.ABSTRACT);
|
||||
ArrangementMatchCondition methodCondition
|
||||
= new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD);
|
||||
condition.addOperand(abstractCondition);
|
||||
condition.addOperand(methodCondition);
|
||||
|
||||
HierarchicalArrangementConditionNode grouped =
|
||||
ArrangementUtil.group(condition, Collections.singletonList(Collections.singleton(methodCondition)));
|
||||
assertEquals(methodCondition, grouped.getCurrent());
|
||||
|
||||
HierarchicalArrangementConditionNode child = grouped.getChild();
|
||||
assertNotNull(child);
|
||||
assertEquals(abstractCondition, child.getCurrent());
|
||||
|
||||
assertNull(child.getChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void groupSingleNode() {
|
||||
ArrangementMatchCondition condition = new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.ABSTRACT);
|
||||
HierarchicalArrangementConditionNode grouped =
|
||||
ArrangementUtil.group(condition, Collections.singletonList(Collections.singleton(condition)));
|
||||
assertEquals(condition, grouped.getCurrent());
|
||||
assertNull(grouped.getChild());
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -27,7 +27,6 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.psi.codeStyle.arrangement.ArrangementOperator.AND;
|
||||
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.CLASS;
|
||||
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.FIELD;
|
||||
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.METHOD;
|
||||
@@ -52,12 +51,12 @@ public class DefaultArrangementEntryMatcherSerializerTest {
|
||||
|
||||
@Test
|
||||
public void compositeMatchers() {
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(AND);
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, METHOD));
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, SYNCHRONIZED));
|
||||
doTest(condition);
|
||||
|
||||
condition = new ArrangementCompositeMatchCondition(AND);
|
||||
condition = new ArrangementCompositeMatchCondition();
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, FIELD));
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, PUBLIC));
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(MODIFIER, STATIC));
|
||||
@@ -67,7 +66,7 @@ public class DefaultArrangementEntryMatcherSerializerTest {
|
||||
@Test
|
||||
public void conditionsOrder() {
|
||||
// Inspired by IDEA-91826.
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(AND);
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
|
||||
ArrangementEntryType typeToPreserve = FIELD;
|
||||
Set<ArrangementModifier> modifiersToPreserve = EnumSet.of(PUBLIC, STATIC, FINAL);
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(TYPE, typeToPreserve));
|
||||
|
||||
+1
-2
@@ -18,7 +18,6 @@ package com.intellij.psi.codeStyle.arrangement.match;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import com.intellij.psi.codeStyle.arrangement.ModifierAwareArrangementEntry;
|
||||
import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
@@ -80,7 +79,7 @@ public class StandardArrangementEntryMatcherTest {
|
||||
|
||||
@Test
|
||||
public void compositeAndCondition() {
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
|
||||
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition();
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD));
|
||||
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
|
||||
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/31/12 1:06 PM
|
||||
*/
|
||||
public interface ArrangementChangeConditionCallback {
|
||||
|
||||
@Nullable
|
||||
StdArrangementMatchRule onChange(@NotNull StdArrangementMatchRule rule, @Nullable ArrangementMatchCondition newCondition);
|
||||
}
|
||||
-471
@@ -15,22 +15,15 @@
|
||||
*/
|
||||
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.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -119,468 +112,4 @@ public class ArrangementConfigUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getDepth(@NotNull HierarchicalArrangementConditionNode node) {
|
||||
HierarchicalArrangementConditionNode child = node.getChild();
|
||||
return child == null ? 1 : 1 + getDepth(child);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HierarchicalArrangementConditionNode getLast(@NotNull HierarchicalArrangementConditionNode node) {
|
||||
HierarchicalArrangementConditionNode result = node;
|
||||
for (HierarchicalArrangementConditionNode child = node.getChild(); child != null; child = child.getChild()) {
|
||||
result = child;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
public static ArrangementTreeNode getLastBefore(@NotNull ArrangementTreeNode start, @NotNull ArrangementTreeNode stop)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
ArrangementTreeNode result = start;
|
||||
for (ArrangementTreeNode 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;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ArrangementTreeNode getLast(@NotNull final ArrangementTreeNode node) {
|
||||
ArrangementTreeNode result = node;
|
||||
int childCount = result.getChildCount();
|
||||
while (childCount > 0) {
|
||||
result = result.getChildAt(childCount - 1);
|
||||
}
|
||||
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;
|
||||
* <code>null</code> as an indication that we want to create a standalone nodes hierarchy
|
||||
* @param conditionNode settings node which should be represented at the UI tree denoted by the given UI tree node
|
||||
* @param model tree model to use for the tree modification
|
||||
* @return pair {@code (bottom-most leaf node created; number of rows created)}
|
||||
*/
|
||||
@NotNull
|
||||
public static Pair<ArrangementTreeNode, Integer> map(@Nullable ArrangementTreeNode uiParentNode,
|
||||
@NotNull HierarchicalArrangementConditionNode conditionNode,
|
||||
@Nullable DefaultTreeModel model)
|
||||
{
|
||||
ArrangementTreeNode uiNode = null;
|
||||
int rowsCreated = 0;
|
||||
if (uiParentNode != null && uiParentNode.getChildCount() > 0) {
|
||||
ArrangementTreeNode child = uiParentNode.getChildAt(uiParentNode.getChildCount() - 1);
|
||||
if (conditionNode.getCurrent().equals(child.getBackingCondition())) {
|
||||
uiNode = child;
|
||||
}
|
||||
}
|
||||
if (uiNode == null) {
|
||||
uiNode = new ArrangementTreeNode(conditionNode.getCurrent());
|
||||
if (uiParentNode != null) {
|
||||
if (model == null) {
|
||||
uiParentNode.add(uiNode);
|
||||
}
|
||||
else {
|
||||
model.insertNodeInto(uiNode, uiParentNode, uiParentNode.getChildCount());
|
||||
}
|
||||
}
|
||||
rowsCreated++;
|
||||
}
|
||||
ArrangementTreeNode leaf = uiNode;
|
||||
HierarchicalArrangementConditionNode childConditionNode = conditionNode.getChild();
|
||||
if (childConditionNode != null) {
|
||||
Pair<ArrangementTreeNode, Integer> pair = map(uiNode, childConditionNode, model);
|
||||
leaf = pair.first;
|
||||
rowsCreated += pair.second;
|
||||
}
|
||||
return Pair.create(leaf, rowsCreated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method which helps to replace node sub-hierarchy identified by the given start and end nodes (inclusive) by
|
||||
* a sub-hierarchy which is denoted by the given root.
|
||||
*
|
||||
* @param from indicates start of the node sub-hierarchy (top-most node) to be replaced (inclusive)
|
||||
* @param to indicates end of the node sub-hierarchy (bottom-most node) to be replaced (inclusive)
|
||||
* @param replacement root of the node sub-hierarchy which should replace the one identified by the given 'start' and 'end' nodes
|
||||
* @param treeModel model which should hold ui nodes
|
||||
* @param rootVisible determines if the root should be count during rows calculations
|
||||
* @return collection of row changes at the form {@code 'old row -> new row'} (all rows are zero-based)
|
||||
*/
|
||||
public static TIntIntHashMap replace(@NotNull ArrangementTreeNode from,
|
||||
@NotNull ArrangementTreeNode to,
|
||||
@NotNull ArrangementTreeNode replacement,
|
||||
@NotNull DefaultTreeModel treeModel,
|
||||
boolean rootVisible)
|
||||
{
|
||||
return doReplace(from, to, replacement, treeModel, rootVisible);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("AssignmentToForLoopParameter")
|
||||
@NotNull
|
||||
private static TIntIntHashMap doReplace(@NotNull ArrangementTreeNode from,
|
||||
@NotNull ArrangementTreeNode to,
|
||||
@Nullable ArrangementTreeNode replacement,
|
||||
@NotNull DefaultTreeModel treeModel,
|
||||
boolean rootVisible)
|
||||
{
|
||||
// The algorithm looks as follows:
|
||||
// 1. Cut sub-hierarchy which belongs to the given 'from' root and is located below the 'to -> from' path;
|
||||
// 2. Remove 'to -> from' sub-hierarchy' by going bottom-up and stopping as soon as a current node has a child over than one
|
||||
// from the sub-hierarchy to remove;
|
||||
// 3. Add 'replacement' sub-hierarchy starting after the 'from' index at its parent;
|
||||
// 4. Add sub-hierarchy cut at the 1) starting after the 'replacement' sub-hierarchy index;
|
||||
// Example:
|
||||
// Initial:
|
||||
// 0
|
||||
// |_1
|
||||
// |_2
|
||||
// | |_3
|
||||
// | |_4
|
||||
// | |_5
|
||||
// |
|
||||
// |_6
|
||||
// Let's say we want to replace the sub-hierarchy '1 -> 2 -> 4' by the sub-hierarchy '1 -> 4'. The algorithm in action:
|
||||
// 1. Cut bottom sub-hierarchy:
|
||||
// Current: Cut:
|
||||
// 0 1
|
||||
// |_1 |_2
|
||||
// |_2 | |_5
|
||||
// |_3 |
|
||||
// |_4 |_6
|
||||
//
|
||||
// 2. Remove target sub-hierarchy:
|
||||
// Current:
|
||||
// 0
|
||||
// |_1
|
||||
// |_2 <-- stop at this node because it has a child node '3' which doesn't belong to the '1 -> 2 -> 4'
|
||||
// |_3
|
||||
// 3. Add 'replacement' sub-hierarchy:
|
||||
// Current:
|
||||
// 0
|
||||
// |_1 <-- re-use this node for '1 -> 4' addition
|
||||
// |_2
|
||||
// | |_3
|
||||
// |
|
||||
// |_4
|
||||
// 4. Add 'bottom' sub-hierarchy:
|
||||
// Current:
|
||||
// 0
|
||||
// |_1 <-- re-use this node either for '1 -> 2 -> 5' or '1 -> 6' addition
|
||||
// |_2
|
||||
// | |_3
|
||||
// |
|
||||
// |_4
|
||||
// |
|
||||
// |_2
|
||||
// | |_5
|
||||
// |
|
||||
// |_6
|
||||
//
|
||||
// Note: we need to have a notion of 'equal nodes' for node re-usage. It's provided by comparing node user objects.
|
||||
|
||||
markRows(from, rootVisible);
|
||||
final ArrangementTreeNode root = from.getParent();
|
||||
assert root != null;
|
||||
|
||||
@Nullable ArrangementTreeNode cutHierarchy = cutSubHierarchy(root, treeModel, to);
|
||||
|
||||
int childCountBefore = root.getChildCount();
|
||||
|
||||
for (ArrangementTreeNode current = to; current != root;) {
|
||||
ArrangementTreeNode parent = current.getParent();
|
||||
treeModel.removeNodeFromParent(current);
|
||||
current = parent;
|
||||
if (parent == null || parent.getChildCount() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int insertionIndex = root.getChildCount() < childCountBefore ? childCountBefore - 1 : childCountBefore;
|
||||
if (replacement != null) {
|
||||
insert(root, insertionIndex, replacement, treeModel);
|
||||
}
|
||||
if (cutHierarchy != null) {
|
||||
insert(root, root.getChildCount(), cutHierarchy, treeModel);
|
||||
}
|
||||
|
||||
return collectRowChangesAndUnmark(root, rootVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all nodes which lay below the path identified by the given 'top' and 'bottom' nodes from the tree structure and returns them.
|
||||
*
|
||||
* @param topMost top most node marker, i.e. all cut nodes descend from this node
|
||||
* @param treeModel tree model which manages the nodes
|
||||
* @param bottomMost bottom most node after which all other nodes should be cut
|
||||
* @return removed nodes below the target path if any; <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public static ArrangementTreeNode cutSubHierarchy(@NotNull ArrangementTreeNode topMost,
|
||||
@NotNull DefaultTreeModel treeModel,
|
||||
@NotNull ArrangementTreeNode bottomMost)
|
||||
{
|
||||
ArrangementTreeNode cutHierarchy = null;
|
||||
for (ArrangementTreeNode current = bottomMost; current != null && current != topMost; current = current.getParent()) {
|
||||
ArrangementTreeNode parent = current.getParent();
|
||||
assert parent != null;
|
||||
int i = parent.getIndex(current);
|
||||
int childCount = parent.getChildCount();
|
||||
if (i >= childCount - 1) {
|
||||
continue;
|
||||
}
|
||||
ArrangementTreeNode parentCopy = parent.copy();
|
||||
if (parent.getChildCount() > 0) {
|
||||
parentCopy.resetRow();
|
||||
}
|
||||
if (cutHierarchy != null) {
|
||||
parentCopy.add(cutHierarchy);
|
||||
}
|
||||
for (int j = i + 1; j < childCount; j++) {
|
||||
ArrangementTreeNode child = parent.getChildAt(i + 1);
|
||||
treeModel.removeNodeFromParent(child);
|
||||
parentCopy.add(child);
|
||||
}
|
||||
cutHierarchy = parentCopy;
|
||||
}
|
||||
return cutHierarchy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enriches every node at the hierarchy denoted by the given node by information about it's row.
|
||||
*
|
||||
* @param node reference to the target hierarchy
|
||||
* @param rootVisible determines if the root should be count during rows calculations
|
||||
*/
|
||||
public static void markRows(@NotNull ArrangementTreeNode node, boolean rootVisible) {
|
||||
ArrangementTreeNode root = getRoot(node);
|
||||
int row = rootVisible ? 0 : -1;
|
||||
Stack<ArrangementTreeNode> nodes = new Stack<ArrangementTreeNode>();
|
||||
nodes.push(root);
|
||||
while (!nodes.isEmpty()) {
|
||||
ArrangementTreeNode n = nodes.pop();
|
||||
n.markRow(row++);
|
||||
for (int i = n.getChildCount() - 1; i >= 0; i--) {
|
||||
nodes.push(n.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ArrangementTreeNode getRoot(@NotNull ArrangementTreeNode node) {
|
||||
ArrangementTreeNode root = node;
|
||||
for (ArrangementTreeNode n = root; n != null; n = n.getParent()) {
|
||||
root = n;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes hierarchy denoted by the given node assuming that every node there contains information about its initial row
|
||||
* (see {@link #markRows(ArrangementTreeNode, boolean)}).
|
||||
* <p/>
|
||||
* Collects all row changes and returns them. All row information is dropped from the nodes during the current method processing.
|
||||
*
|
||||
* @param node reference to the target nodes hierarchy
|
||||
* @return collection of row changes at the form {@code 'old row -> new row'} (all rows are zero-based)
|
||||
*/
|
||||
@NotNull
|
||||
public static TIntIntHashMap collectRowChangesAndUnmark(@NotNull ArrangementTreeNode node, boolean rootVisible) {
|
||||
@NotNull TIntIntHashMap changes = new TIntIntHashMap();
|
||||
ArrangementTreeNode root = getRoot(node);
|
||||
int row = rootVisible ? 0 : -1;
|
||||
Stack<ArrangementTreeNode> nodes = new Stack<ArrangementTreeNode>();
|
||||
nodes.push(root);
|
||||
while (!nodes.isEmpty()) {
|
||||
ArrangementTreeNode n = nodes.pop();
|
||||
if (n.isRowSet() && n.getRow() != row) {
|
||||
changes.put(n.getRow(), row);
|
||||
}
|
||||
n.resetRow();
|
||||
row++;
|
||||
for (int i = n.getChildCount() - 1; i >= 0; i--) {
|
||||
nodes.push(n.getChildAt(i));
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to map given node to its row at the hierarchy.
|
||||
*
|
||||
* @param node target node
|
||||
* @param rootVisible determines if the root should be count on rows calculation
|
||||
* @return given node's row at the nodes hierarchy (0-based)
|
||||
*/
|
||||
public static int getRow(@NotNull ArrangementTreeNode node, boolean rootVisible) {
|
||||
ArrangementTreeNode root = getRoot(node);
|
||||
int row = rootVisible ? 0 : -1;
|
||||
Stack<ArrangementTreeNode> nodes = new Stack<ArrangementTreeNode>();
|
||||
nodes.push(root);
|
||||
while (!nodes.isEmpty()) {
|
||||
ArrangementTreeNode n = nodes.pop();
|
||||
if (n == node) {
|
||||
return row;
|
||||
}
|
||||
row++;
|
||||
for (int i = n.getChildCount() - 1; i >= 0; i--) {
|
||||
nodes.push(n.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String separator = "->";
|
||||
for (TreeNode n = node; n != null; n = n.getParent()) {
|
||||
buffer.append(n).append(separator);
|
||||
}
|
||||
buffer.setLength(buffer.length() - separator.length());
|
||||
throw new RuntimeException("Invalid ArrangementTreeNode detected: " + buffer.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts given child to the given parent re-using existing nodes under the parent sub-hierarchy if possible.
|
||||
* <p/>
|
||||
* Example:
|
||||
* <pre>
|
||||
* parent: 0 to-insert: 2
|
||||
* |_1 |_3
|
||||
* |_2 |_6
|
||||
* | |_3
|
||||
* | |_4
|
||||
* |_5
|
||||
* -------------------------------------------------------------------------------------------------
|
||||
* | index: | 0 | 1 | 2 | 3 |
|
||||
* |-------------------------------------------------------------------------------------------------
|
||||
* | result: | 0 | 0 | 0 | 0 |
|
||||
* | | |_2 | |_1 | |_1 | |_1 |
|
||||
* | | | |_3 | |_2 | |_2 | |_2 |
|
||||
* | | | |_6 | | |_3 | | |_3 | | |_3 |
|
||||
* | | |_1 | | |_6 | | |_4 | | |_4 |
|
||||
* | | |_2 | | |_4 | | |_6 | |_5 |
|
||||
* | | | |_3 | |_5 | |_5 | |_2 |
|
||||
* | | | |_4 | | | |_3 |
|
||||
* | | |_5 | | | |_6 |
|
||||
* </pre>
|
||||
* <p/>
|
||||
*
|
||||
* @param parent parent node to insert into
|
||||
* @param index insertion index to use for the given parent node
|
||||
* @param child node to insert to the given parent node at the given insertion index
|
||||
* @param treeModel model which should hold UI nodes
|
||||
* @return <code>true</code> if given child node has been merged to the existing node; <code>false</code> otherwise
|
||||
*/
|
||||
public static void insert(@NotNull final ArrangementTreeNode parent,
|
||||
final int index,
|
||||
@NotNull final ArrangementTreeNode child,
|
||||
@NotNull DefaultTreeModel treeModel)
|
||||
{
|
||||
ArrangementTreeNode root = getRoot(parent);
|
||||
List<ArrangementTreeNode> toInsert = new ArrayList<ArrangementTreeNode>();
|
||||
if (hasEqualSetting(root, child)) {
|
||||
for (int i = 0; i < child.getChildCount(); i++) {
|
||||
toInsert.add(child.getChildAt(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
toInsert.add(child);
|
||||
}
|
||||
int i = index;
|
||||
for (ArrangementTreeNode node : toInsert) {
|
||||
doInsert(parent, i++, node, treeModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean doInsert(@NotNull final ArrangementTreeNode parent,
|
||||
final int index,
|
||||
@NotNull final ArrangementTreeNode child,
|
||||
@NotNull DefaultTreeModel treeModel)
|
||||
{
|
||||
if (parent.getChildCount() < index) {
|
||||
treeModel.insertNodeInto(child, parent, parent.getChildCount());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (child.getChildCount() <= 0) {
|
||||
// Don't merge the last child.
|
||||
treeModel.insertNodeInto(child, parent, index);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean anchorAbove = false;
|
||||
ArrangementTreeNode mergeCandidate = null;
|
||||
if (index > 0) {
|
||||
mergeCandidate = parent.getChildAt(index - 1);
|
||||
if (mergeCandidate.getChildCount() <= 0 /* don't merge into leaf node*/ || !hasEqualSetting(mergeCandidate, child)) {
|
||||
mergeCandidate = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < parent.getChildCount()) {
|
||||
ArrangementTreeNode n = parent.getChildAt(index);
|
||||
if (hasEqualSetting(n, child)) {
|
||||
mergeCandidate = n;
|
||||
anchorAbove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mergeCandidate == null) {
|
||||
treeModel.insertNodeInto(child, parent, index);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0, limit = child.getChildCount(); i < limit; i++) {
|
||||
insert(mergeCandidate, anchorAbove ? 0 : mergeCandidate.getChildCount(), child.getChildAt(0), treeModel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean hasEqualSetting(@NotNull ArrangementTreeNode node1, @NotNull ArrangementTreeNode node2) {
|
||||
ArrangementMatchCondition matchCondition1 = node1.getBackingCondition();
|
||||
ArrangementMatchCondition matchCondition2 = node2.getBackingCondition();
|
||||
if (matchCondition1 == null) {
|
||||
return matchCondition2 == null;
|
||||
}
|
||||
else {
|
||||
return matchCondition1.equals(matchCondition2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes target sub-hierarchy from the tree.
|
||||
*
|
||||
* @param from indicates start of the node sub-hierarchy (top-most node) to be replaced (inclusive)
|
||||
* @param to indicates end of the node sub-hierarchy (bottom-most node) to be replaced (inclusive)
|
||||
* @param treeModel model which should hold ui nodes
|
||||
* @param rootVisible determines if the root should be count during rows calculations
|
||||
* @return collection of row changes at the form {@code 'old row -> new row'} (all rows are zero-based)
|
||||
*/
|
||||
@NotNull
|
||||
public static TIntIntHashMap remove(@NotNull final ArrangementTreeNode from,
|
||||
@NotNull final ArrangementTreeNode to,
|
||||
@NotNull DefaultTreeModel treeModel,
|
||||
boolean rootVisible)
|
||||
{
|
||||
return doReplace(from, to, null, treeModel, rootVisible);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,7 +17,6 @@ package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
@@ -33,8 +32,9 @@ public class ArrangementConstants {
|
||||
@NonNls public static final String RULE_EDITOR_PLACE = "Arrangement.RuleEditor.Place";
|
||||
@NonNls public static final String RULE_EDITOR_TOOL_WINDOW_PLACE = "Arrangement.RuleEditor.ToolWindow.Place";
|
||||
@NonNls public static final String RULE_TREE_PLACE = "Arrangement.RuleTree.Place";
|
||||
|
||||
|
||||
public static final int HORIZONTAL_PADDING = 8;
|
||||
public static final int HORIZONTAL_GAP = 8;
|
||||
|
||||
public static final boolean LOG_RULE_MODIFICATION = Boolean.parseBoolean(System.getProperty("log.arrangement.rule.modification"));
|
||||
|
||||
|
||||
+4
-4
@@ -28,7 +28,7 @@ import java.awt.*;
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/30/12 12:10 PM
|
||||
*/
|
||||
public class ArrangementEditorTreeNode extends ArrangementTreeNode implements ArrangementRepresentationAwareNode {
|
||||
public class ArrangementEditorTreeNode /*extends ArrangementTreeNode implements ArrangementRepresentationAwareNode*/ {
|
||||
|
||||
private static final int STEPS_NUMBER = 10;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ArrangementEditorTreeNode extends ArrangementTreeNode implements Ar
|
||||
private int myStep = 1;
|
||||
|
||||
public ArrangementEditorTreeNode(@NotNull ArrangementRuleEditor editor, @NotNull DefaultTreeModel treeModel, int availableWidth) {
|
||||
super(null);
|
||||
//super(null);
|
||||
myTreeModel = treeModel;
|
||||
myAvailableWidth = availableWidth;
|
||||
editor.applyAvailableWidth(availableWidth - ArrangementConstants.HORIZONTAL_PADDING);
|
||||
@@ -99,11 +99,11 @@ public class ArrangementEditorTreeNode extends ArrangementTreeNode implements Ar
|
||||
|
||||
public void changeState() {
|
||||
myStep++;
|
||||
myTreeModel.nodeChanged(this);
|
||||
//myTreeModel.nodeChanged(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
//@Override
|
||||
public JComponent getRenderer() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementCheckBoxNode;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementComboBoxNode;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementSectionNode;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is responsible for representing {@link ArrangementGroupingRule grouping rules} at tree structure.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 2:36 PM
|
||||
*/
|
||||
public class ArrangementGroupingRulesManager {
|
||||
|
||||
@NotNull public static final ArrangementGroupingRulesManager INSTANCE = new ArrangementGroupingRulesManager();
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
@Nullable
|
||||
public MutableTreeNode buildAvailableRules(@NotNull ArrangementStandardSettingsAware settingsFilter,
|
||||
@NotNull ArrangementNodeDisplayManager displayManager)
|
||||
{
|
||||
ArrangementSectionNode result = new ArrangementSectionNode(ApplicationBundle.message("arrangement.settings.section.groups"));
|
||||
String orderLabel = ApplicationBundle.message("arrangement.settings.label.order") + ":";
|
||||
for (ArrangementGroupingType groupingType : ArrangementGroupingType.values()) {
|
||||
if (!settingsFilter.isEnabled(groupingType, null)) {
|
||||
continue;
|
||||
}
|
||||
final ArrangementCheckBoxNode<ArrangementGroupingType> groupingNode
|
||||
= new ArrangementCheckBoxNode<ArrangementGroupingType>(displayManager, groupingType);
|
||||
result.add(groupingNode);
|
||||
List<ArrangementEntryOrderType> supportedOrderTypes = new ArrayList<ArrangementEntryOrderType>();
|
||||
for (ArrangementEntryOrderType orderType : ArrangementEntryOrderType.values()) {
|
||||
if (settingsFilter.isEnabled(groupingType, orderType)) {
|
||||
supportedOrderTypes.add(orderType);
|
||||
}
|
||||
}
|
||||
if (supportedOrderTypes.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final ArrangementComboBoxNode<ArrangementEntryOrderType> orderTypeNode
|
||||
= new ArrangementComboBoxNode<ArrangementEntryOrderType>(displayManager, orderLabel, supportedOrderTypes);
|
||||
groupingNode.add(orderTypeNode);
|
||||
groupingNode.setChangeCallback(new Consumer<ArrangementCheckBoxNode<ArrangementGroupingType>>() {
|
||||
@Override
|
||||
public void consume(ArrangementCheckBoxNode<ArrangementGroupingType> node) {
|
||||
orderTypeNode.setEnabled(groupingNode.isSelected());
|
||||
}
|
||||
});
|
||||
groupingNode.setSelected(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"MethodMayBeStatic", "unchecked"})
|
||||
public void applyRules(@NotNull List<ArrangementGroupingRule> rules,
|
||||
@NotNull MutableTreeNode groupsRoot,
|
||||
@NotNull DefaultTreeModel model)
|
||||
{
|
||||
for (int i = 0; i < groupsRoot.getChildCount(); i++) {
|
||||
ArrangementCheckBoxNode<?> child = (ArrangementCheckBoxNode<?>)groupsRoot.getChildAt(i);
|
||||
child.setSelected(false);
|
||||
}
|
||||
for (int i = 0; i < rules.size(); i++) {
|
||||
ArrangementGroupingRule rule = rules.get(i);
|
||||
int index = getIndex(groupsRoot, rule.getRule());
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrangementCheckBoxNode<?> child = (ArrangementCheckBoxNode<?>)groupsRoot.getChildAt(index);
|
||||
child.setSelected(true);
|
||||
|
||||
if (i != index) {
|
||||
model.removeNodeFromParent(child);
|
||||
int insertionIndex = i < index ? i : i - 1;
|
||||
model.insertNodeInto(child, groupsRoot, insertionIndex);
|
||||
}
|
||||
|
||||
if (child.getChildCount() > 0) {
|
||||
ArrangementComboBoxNode<ArrangementEntryOrderType> orderTypeNode =
|
||||
(ArrangementComboBoxNode<ArrangementEntryOrderType>)child.getChildAt(0);
|
||||
orderTypeNode.setSelectedValue(rule.getOrderType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getIndex(@NotNull TreeNode root, @NotNull Object data) {
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
TreeNode child = root.getChildAt(i);
|
||||
if (child instanceof ArrangementCheckBoxNode<?> && data.equals(((ArrangementCheckBoxNode)child).getValue())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "MethodMayBeStatic"})
|
||||
@NotNull
|
||||
public List<ArrangementGroupingRule> buildRules(@NotNull TreeNode groupsRoot) {
|
||||
List<ArrangementGroupingRule> result = new ArrayList<ArrangementGroupingRule>();
|
||||
for (int i = 0; i < groupsRoot.getChildCount(); i++) {
|
||||
ArrangementCheckBoxNode<ArrangementGroupingType> groupNode =
|
||||
(ArrangementCheckBoxNode<ArrangementGroupingType>)groupsRoot.getChildAt(i);
|
||||
if (!groupNode.isSelected()) {
|
||||
continue;
|
||||
}
|
||||
ArrangementGroupingType groupingType = groupNode.getValue();
|
||||
if (groupNode.getChildCount() < 1) {
|
||||
result.add(new ArrangementGroupingRule(groupingType));
|
||||
continue;
|
||||
}
|
||||
|
||||
ArrangementComboBoxNode<ArrangementEntryOrderType> orderNode =
|
||||
(ArrangementComboBoxNode<ArrangementEntryOrderType>)groupNode.getChildAt(0);
|
||||
ArrangementEntryOrderType orderType = orderNode.getSelectedValue();
|
||||
result.add(new ArrangementGroupingRule(groupingType, orderType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-84
@@ -1,84 +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.psi.codeStyle.arrangement.ArrangementOperator;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Combines and encapsulates information about arrangement matcher rules representation (tree nodes) and
|
||||
* underlying {@link ArrangementMatchCondition 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
|
||||
StdArrangementMatchRule EMPTY_RULE = new StdArrangementMatchRule(new StdArrangementEntryMatcher(
|
||||
new ArrangementCompositeMatchCondition(ArrangementOperator.AND)
|
||||
));
|
||||
|
||||
@NotNull
|
||||
ArrangementMatchCondition getCondition();
|
||||
|
||||
@NotNull
|
||||
StdArrangementMatchRule getRule();
|
||||
|
||||
/**
|
||||
* Asks current model to destroy itself.
|
||||
* <p/>
|
||||
* The key concern here is to perform necessary tree modification.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* 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 ArrangementAtomMatchCondition condition);
|
||||
|
||||
void removeAndCondition(@NotNull ArrangementMatchCondition condition);
|
||||
|
||||
/**
|
||||
* We need to be able to replace one condition by another. Most of the time it can be simulated by
|
||||
* {@link #removeAndCondition(ArrangementMatchCondition) 'remove old'} and
|
||||
* {@link #addAndCondition(ArrangementAtomMatchCondition) 'add new'} actions sequence but that doesn't work when
|
||||
* {@link #getRule() underlying condition} has the only atom condition. Removing it eliminates the condition at all.
|
||||
*
|
||||
* @param from condition which should be replaced
|
||||
* @param to replacement condition
|
||||
* @throws IllegalArgumentException when given 'from' condition is not a part of the
|
||||
* {@link #getRule() underlying match condition}
|
||||
*/
|
||||
void replaceCondition(@NotNull ArrangementAtomMatchCondition from, @NotNull ArrangementAtomMatchCondition to)
|
||||
throws IllegalArgumentException;
|
||||
}
|
||||
-123
@@ -1,123 +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.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Holds glue logic between arrangement settings and their representation -
|
||||
* '{@link ArrangementMatchCondition} -> {@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 HierarchicalArrangementConditionNode Groups} given {@link ArrangementMatchCondition settings} using
|
||||
* the given grouping rules;
|
||||
* </li>
|
||||
* <li>
|
||||
* Build {@link DefaultMutableTreeNode tree nodes} for the {@link HierarchicalArrangementConditionNode 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 rule target rule to process
|
||||
* @param tree UI tree which shows arrangement matcher rules
|
||||
* @param root UI tree settings root to use (may be not the same as the tree root)
|
||||
* @param anchor node after which should be previous sibling for the root node of the inserted condition;
|
||||
* <code>null</code> as an indication that new condition nodes should be inserted as the last 'root' child
|
||||
* @param groupingRules conditions grouping rules
|
||||
* {@link ArrangementStandardSettingsRepresentationAware#getDisplayValue(ArrangementModifier) group} setting
|
||||
* nodes for UI representation
|
||||
* @return created model and collection of row changes at the form {@code 'old row -> new row'} (all rows are zero-based);
|
||||
* <code>null</code> if no model has been created
|
||||
*/
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
@Nullable
|
||||
public Pair<ArrangementRuleEditingModelImpl, TIntIntHashMap> build(
|
||||
@NotNull StdArrangementMatchRule rule,
|
||||
@NotNull JTree tree,
|
||||
@NotNull ArrangementTreeNode root,
|
||||
@Nullable ArrangementTreeNode anchor,
|
||||
@NotNull List<Set<ArrangementMatchCondition>> groupingRules)
|
||||
{
|
||||
HierarchicalArrangementConditionNode grouped = ArrangementUtil.group(rule.getMatcher().getCondition(), groupingRules);
|
||||
DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
|
||||
|
||||
if (grouped.getChild() == null) {
|
||||
ArrangementTreeNode lastChild = null;
|
||||
if (root.getChildCount() > 0) {
|
||||
lastChild = root.getLastChild();
|
||||
}
|
||||
if (lastChild != null && grouped.getCurrent().equals(lastChild.getBackingCondition())) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Pair<ArrangementTreeNode, Integer> pair = ArrangementConfigUtil.map(null, grouped, null);
|
||||
ArrangementTreeNode topMostNode = ArrangementConfigUtil.getRoot(pair.first);
|
||||
ArrangementConfigUtil.markRows(root, true);
|
||||
ArrangementTreeNode bottomHierarchy = null;
|
||||
if (anchor != null) {
|
||||
bottomHierarchy = ArrangementConfigUtil.cutSubHierarchy(root, treeModel, anchor);
|
||||
}
|
||||
ArrangementConfigUtil.insert(root, root.getChildCount(), topMostNode, treeModel);
|
||||
if (bottomHierarchy != null) {
|
||||
ArrangementConfigUtil.insert(root, root.getChildCount(), bottomHierarchy, treeModel);
|
||||
}
|
||||
|
||||
TIntIntHashMap rowChanges = ArrangementConfigUtil.collectRowChangesAndUnmark(root, true);
|
||||
topMostNode = ArrangementConfigUtil.getLastBefore(pair.first, root);
|
||||
int row = ArrangementConfigUtil.getRow(pair.first, tree.isRootVisible());
|
||||
ArrangementRuleEditingModelImpl model = new ArrangementRuleEditingModelImpl(
|
||||
treeModel,
|
||||
rule,
|
||||
topMostNode,
|
||||
pair.first,
|
||||
groupingRules,
|
||||
row,
|
||||
tree.isRootVisible()
|
||||
);
|
||||
return Pair.create(model, rowChanges);
|
||||
}
|
||||
}
|
||||
-284
@@ -1,284 +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.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/15/12 2:40 PM
|
||||
*/
|
||||
public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingModel {
|
||||
|
||||
@NotNull private static final MyConditionsBuilder CONDITIONS_BUILDER = new MyConditionsBuilder();
|
||||
|
||||
@NotNull private static final Logger LOG = Logger.getInstance("#" + ArrangementRuleEditingModelImpl.class.getName());
|
||||
|
||||
@NotNull private final Set<Listener> myListeners = new HashSet<Listener>();
|
||||
@NotNull private final Set<Object> myConditions = new HashSet<Object>();
|
||||
|
||||
@NotNull private final DefaultTreeModel myTreeModel;
|
||||
@NotNull private final List<Set<ArrangementMatchCondition>> myGroupingRules;
|
||||
private final boolean myRootVisible;
|
||||
|
||||
@NotNull private ArrangementTreeNode myTopMost;
|
||||
@NotNull private ArrangementTreeNode myBottomMost;
|
||||
@NotNull private StdArrangementMatchRule myRule;
|
||||
private int myRow;
|
||||
|
||||
/**
|
||||
* Creates new <code>ArrangementRuleEditingModelImpl</code> object.
|
||||
*
|
||||
* @param model tree model which holds target ui nodes. Basically, we need to perform ui nodes modification via it in order
|
||||
* to generate corresponding events automatically
|
||||
* @param rule backing arrangement rule
|
||||
* @param topMost there is a possible case that a single settings node is shown in more than one visual line
|
||||
* ({@link HierarchicalArrangementConditionNode}). 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 groupingRules grouping rules
|
||||
* @param row row number for which current model is registered at the given model mappings
|
||||
* @param rootVisible determines if the root should be count during rows calculations
|
||||
*/
|
||||
public ArrangementRuleEditingModelImpl(@NotNull DefaultTreeModel model,
|
||||
@NotNull StdArrangementMatchRule rule,
|
||||
@NotNull ArrangementTreeNode topMost,
|
||||
@NotNull ArrangementTreeNode bottomMost,
|
||||
@NotNull List<Set<ArrangementMatchCondition>> groupingRules,
|
||||
int row,
|
||||
boolean rootVisible)
|
||||
{
|
||||
myTreeModel = model;
|
||||
myRule = rule;
|
||||
myTopMost = topMost;
|
||||
myBottomMost = bottomMost;
|
||||
myGroupingRules = groupingRules;
|
||||
myRow = row;
|
||||
myRootVisible = rootVisible;
|
||||
refreshConditions();
|
||||
}
|
||||
|
||||
private void refreshConditions() {
|
||||
myConditions.clear();
|
||||
CONDITIONS_BUILDER.conditions = myConditions;
|
||||
try {
|
||||
getCondition().invite(CONDITIONS_BUILDER);
|
||||
}
|
||||
finally {
|
||||
CONDITIONS_BUILDER.conditions = null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ArrangementMatchCondition getCondition() {
|
||||
return myRule.getMatcher().getCondition();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StdArrangementMatchRule getRule() {
|
||||
return myRule;
|
||||
}
|
||||
|
||||
public int getRow() {
|
||||
return myRow;
|
||||
}
|
||||
|
||||
public void setRow(int row) {
|
||||
myRow = row;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementTreeNode getTopMost() {
|
||||
return myTopMost;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementTreeNode getBottomMost() {
|
||||
return myBottomMost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCondition(@NotNull Object key) {
|
||||
return myConditions.contains(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* There is a possible case that tree nodes referenced by the current model become out of date due to a tree modification.
|
||||
* <p/>
|
||||
* This method asks the model to refresh its tree nodes if necessary.
|
||||
*/
|
||||
public void refreshTreeNodes() {
|
||||
for (ArrangementTreeNode node = myBottomMost; node != null; node = node.getParent()) {
|
||||
if (node == myTopMost) {
|
||||
// No refresh is necessary.
|
||||
return;
|
||||
}
|
||||
ArrangementMatchCondition matchCondition = myTopMost.getBackingCondition();
|
||||
if (matchCondition != null && matchCondition.equals(node.getBackingCondition())) {
|
||||
myTopMost = node;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAndCondition(@NotNull ArrangementAtomMatchCondition condition) {
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info(String.format(
|
||||
"Arrangement rule modification - adding a condition '%s'. Model: '%s', row: %d", condition, myRule, myRow
|
||||
));
|
||||
}
|
||||
ArrangementMatchCondition newCondition = ArrangementUtil.and(getCondition().clone(), condition);
|
||||
applyNewCondition(newCondition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAndCondition(@NotNull ArrangementMatchCondition condition) {
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info(String.format(
|
||||
"Arrangement rule modification - removing a condition '%s'. Model: '%s', row: %d", condition, myRule, myRow
|
||||
));
|
||||
}
|
||||
|
||||
if (condition.equals(myBottomMost.getBackingCondition())) {
|
||||
if (myTopMost != myBottomMost && myTopMost.getChildCount() > 1) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ArrangementMatchCondition matchCondition = getCondition();
|
||||
assert matchCondition instanceof ArrangementCompositeMatchCondition;
|
||||
ArrangementMatchCondition newCondition = matchCondition.clone();
|
||||
ArrangementCompositeMatchCondition composite = (ArrangementCompositeMatchCondition)newCondition;
|
||||
composite.getOperands().remove(condition);
|
||||
if (composite.getOperands().size() == 1) {
|
||||
newCondition = composite.getOperands().iterator().next();
|
||||
}
|
||||
applyNewCondition(newCondition);
|
||||
}
|
||||
|
||||
private void applyNewCondition(@NotNull ArrangementMatchCondition newCondition) {
|
||||
myRule = new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition));
|
||||
HierarchicalArrangementConditionNode grouped = ArrangementUtil.group(newCondition, myGroupingRules);
|
||||
Pair<ArrangementTreeNode, Integer> replacement = ArrangementConfigUtil.map(null, grouped, null);
|
||||
ArrangementTreeNode newBottom = replacement.first;
|
||||
ArrangementTreeNode newTop = ArrangementConfigUtil.getRoot(newBottom);
|
||||
final TIntIntHashMap rowChanges = ArrangementConfigUtil.replace(myTopMost, myBottomMost, newTop, myTreeModel, myRootVisible);
|
||||
myBottomMost = newBottom;
|
||||
myTopMost = newTop;
|
||||
refreshTreeNodes();
|
||||
int newRow = ArrangementConfigUtil.getRow(myBottomMost, myRootVisible);
|
||||
if (myRow != newRow) {
|
||||
rowChanges.put(myRow, newRow);
|
||||
myRow = newRow;
|
||||
}
|
||||
refreshConditions();
|
||||
for (Listener listener : myListeners) {
|
||||
listener.onChanged(this, rowChanges);
|
||||
}
|
||||
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info(String.format("Arrangement rule is modified: '%s', row: %d", myRule, myRow));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceCondition(@NotNull ArrangementAtomMatchCondition from, @NotNull ArrangementAtomMatchCondition to) {
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info(String.format(
|
||||
"Arrangement rule modification - replacing condition '%s' by '%s'. Model: '%s', row: %d", from, to, myRule, myRow
|
||||
));
|
||||
}
|
||||
ArrangementMatchCondition newCondition;
|
||||
ArrangementMatchCondition matchCondition = getCondition();
|
||||
if (matchCondition.equals(from)) {
|
||||
newCondition = to;
|
||||
}
|
||||
else {
|
||||
assert matchCondition instanceof ArrangementCompositeMatchCondition;
|
||||
ArrangementCompositeMatchCondition composite = (ArrangementCompositeMatchCondition)matchCondition;
|
||||
ArrangementCompositeMatchCondition newComposite = composite.clone();
|
||||
newComposite.getOperands().remove(from);
|
||||
newComposite.getOperands().add(to);
|
||||
newCondition = newComposite;
|
||||
}
|
||||
applyNewCondition(newCondition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info(String.format("Arrangement rule modification - destroy. Model: '%s', row: %d", myRule, myRow));
|
||||
}
|
||||
for (Listener listener : myListeners) {
|
||||
listener.beforeModelDestroy(this);
|
||||
}
|
||||
TIntIntHashMap rowChanges = ArrangementConfigUtil.remove(myTopMost, myBottomMost, myTreeModel, myRootVisible);
|
||||
for (Listener listener : myListeners) {
|
||||
listener.afterModelDestroy(rowChanges);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(@NotNull Listener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "model for " + myRule;
|
||||
}
|
||||
|
||||
private static class MyConditionsBuilder implements ArrangementMatchConditionVisitor {
|
||||
|
||||
@NotNull Set<Object> conditions;
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
|
||||
conditions.add(setting.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
|
||||
for (ArrangementMatchCondition operand : setting.getOperands()) {
|
||||
operand.invite(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onChanged(@NotNull ArrangementRuleEditingModelImpl model, @NotNull TIntIntHashMap rowChanges);
|
||||
void beforeModelDestroy(@NotNull ArrangementRuleEditingModelImpl model);
|
||||
void afterModelDestroy(@NotNull TIntIntHashMap rowChanges);
|
||||
}
|
||||
}
|
||||
+63
-40
@@ -15,11 +15,15 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementAtomMatchNodeComponent;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponent;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementAtomMatchConditionComponent;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchConditionComponent;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementConditionInfo;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
@@ -47,19 +51,24 @@ public class ArrangementRuleEditor extends JPanel {
|
||||
|
||||
@NotNull private final List<MultiRowFlowPanel> myRows = new ArrayList<MultiRowFlowPanel>();
|
||||
|
||||
@NotNull private final Map<Object, ArrangementAtomMatchNodeComponent> myComponents =
|
||||
new HashMap<Object, ArrangementAtomMatchNodeComponent>();
|
||||
@NotNull private final Map<Object, ArrangementAtomMatchConditionComponent> myComponents =
|
||||
new HashMap<Object, ArrangementAtomMatchConditionComponent>();
|
||||
|
||||
@NotNull private final ArrangementStandardSettingsAware myFilter;
|
||||
@NotNull private final ArrangementColorsProvider myColorsProvider;
|
||||
@Nullable private ArrangementRuleEditingModel myModel;
|
||||
@NotNull private final ArrangementStandardSettingsAware myFilter;
|
||||
@NotNull private final ArrangementColorsProvider myColorsProvider;
|
||||
@NotNull private final ArrangementChangeConditionCallback myChangeCallback;
|
||||
|
||||
@Nullable private StdArrangementMatchRule myRule;
|
||||
@Nullable private ArrangementConditionInfo myConditionInfo;
|
||||
|
||||
public ArrangementRuleEditor(@NotNull ArrangementStandardSettingsAware filter,
|
||||
@NotNull ArrangementColorsProvider provider,
|
||||
@NotNull ArrangementNodeDisplayManager displayManager)
|
||||
@NotNull ArrangementNodeDisplayManager displayManager,
|
||||
@NotNull ArrangementChangeConditionCallback callback)
|
||||
{
|
||||
myFilter = filter;
|
||||
myColorsProvider = provider;
|
||||
myChangeCallback = callback;
|
||||
init(displayManager);
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
@@ -89,13 +98,13 @@ public class ArrangementRuleEditor extends JPanel {
|
||||
|
||||
MultiRowFlowPanel valuesPanel = new MultiRowFlowPanel(FlowLayout.LEFT, 8, 5);
|
||||
for (Object value : manager.sort(values)) {
|
||||
ArrangementAtomMatchNodeComponent component =
|
||||
new ArrangementAtomMatchNodeComponent(manager, myColorsProvider, new ArrangementAtomMatchCondition(key, value), null);
|
||||
ArrangementAtomMatchConditionComponent component =
|
||||
new ArrangementAtomMatchConditionComponent(manager, myColorsProvider, new ArrangementAtomMatchCondition(key, value), null);
|
||||
myComponents.put(value, component);
|
||||
valuesPanel.add(component.getUiComponent());
|
||||
}
|
||||
|
||||
int top = ArrangementAtomMatchNodeComponent.VERTICAL_PADDING;
|
||||
int top = ArrangementAtomMatchConditionComponent.VERTICAL_PADDING;
|
||||
add(new JLabel(manager.getDisplayLabel(key) + ":"), new GridBag().anchor(GridBagConstraints.NORTHWEST).insets(top, 0, 0, 0));
|
||||
add(valuesPanel, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine());
|
||||
myRows.add(valuesPanel);
|
||||
@@ -105,36 +114,46 @@ public class ArrangementRuleEditor 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 model current rule settings model if defined; null as an indication that no settings should be active
|
||||
* @param rule rule which match condition should be edited (if defined);
|
||||
* <code>null</code> as an indication that no settings should be active
|
||||
*/
|
||||
public void updateState(@Nullable ArrangementRuleEditingModel model) {
|
||||
myModel = model;
|
||||
public void updateState(@Nullable StdArrangementMatchRule rule) {
|
||||
myRule = rule;
|
||||
myConditionInfo = null;
|
||||
|
||||
// Reset state.
|
||||
for (ArrangementAtomMatchNodeComponent component : myComponents.values()) {
|
||||
for (ArrangementAtomMatchConditionComponent component : myComponents.values()) {
|
||||
component.setEnabled(false);
|
||||
component.setSelected(false);
|
||||
}
|
||||
|
||||
if (model == null) {
|
||||
if (rule == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableConditions(
|
||||
myFilter, model.getRule().getMatcher().getCondition()
|
||||
);
|
||||
ArrangementMatchCondition condition = rule.getMatcher().getCondition();
|
||||
myConditionInfo = ArrangementUtil.extractConditions(condition);
|
||||
|
||||
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
|
||||
for (Collection<?> ids : available.values()) {
|
||||
for (Object id : ids) {
|
||||
ArrangementAtomMatchNodeComponent component = myComponents.get(id);
|
||||
ArrangementAtomMatchConditionComponent component = myComponents.get(id);
|
||||
if (component != null) {
|
||||
component.setEnabled(true);
|
||||
component.setSelected(model.hasCondition(id));
|
||||
component.setSelected(myConditionInfo.hasCondition(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
private void updateState() {
|
||||
assert myConditionInfo != null;
|
||||
ArrangementMatchCondition newCondition = myConditionInfo.buildCondition();
|
||||
myChangeCallback.onChange(myRule, newCondition);
|
||||
updateState(myRule);
|
||||
}
|
||||
|
||||
public void applyAvailableWidth(int width) {
|
||||
for (MultiRowFlowPanel row : myRows) {
|
||||
row.setForcedWidth(width);
|
||||
@@ -150,19 +169,20 @@ public class ArrangementRuleEditor extends JPanel {
|
||||
}
|
||||
|
||||
private void onMouseClicked(@NotNull MouseEvent e) {
|
||||
if (myModel == null) {
|
||||
if (myRule == null || myConditionInfo == null) {
|
||||
return;
|
||||
}
|
||||
ArrangementAtomMatchNodeComponent clickedComponent = getNodeComponentAt(e.getLocationOnScreen());
|
||||
ArrangementAtomMatchConditionComponent clickedComponent = getNodeComponentAt(e.getLocationOnScreen());
|
||||
if (clickedComponent == null || !clickedComponent.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
ArrangementAtomMatchCondition chosenCondition = clickedComponent.getMatchCondition();
|
||||
boolean remove = myModel.hasCondition(chosenCondition.getValue());
|
||||
boolean remove = myConditionInfo.hasCondition(chosenCondition.getValue());
|
||||
clickedComponent.setSelected(!remove);
|
||||
repaintComponent(clickedComponent);
|
||||
if (remove) {
|
||||
myModel.removeAndCondition(chosenCondition);
|
||||
myConditionInfo.removeCondition(chosenCondition);
|
||||
updateState();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,30 +192,33 @@ public class ArrangementRuleEditor extends JPanel {
|
||||
continue;
|
||||
}
|
||||
for (Object key : mutex) {
|
||||
if (myModel.hasCondition(key)) {
|
||||
ArrangementAtomMatchNodeComponent componentToDeselect = myComponents.get(key);
|
||||
myModel.replaceCondition(componentToDeselect.getMatchCondition(), chosenCondition);
|
||||
for (ArrangementAtomMatchNodeComponent componentToCheck : myComponents.values()) {
|
||||
if (myConditionInfo.hasCondition(key)) {
|
||||
ArrangementAtomMatchConditionComponent componentToDeselect = myComponents.get(key);
|
||||
myConditionInfo.removeCondition(componentToDeselect.getMatchCondition().getValue());
|
||||
myConditionInfo.addAtomCondition(chosenCondition);
|
||||
ArrangementMatchCondition newCondition = myConditionInfo.buildCondition();
|
||||
for (ArrangementAtomMatchConditionComponent componentToCheck : myComponents.values()) {
|
||||
Object value = componentToCheck.getMatchCondition().getValue();
|
||||
if (myModel.hasCondition(value) && !ArrangementConfigUtil.isEnabled(value, myFilter, myModel.getCondition())) {
|
||||
myModel.removeAndCondition(componentToCheck.getMatchCondition());
|
||||
if (myConditionInfo.hasCondition(value) && !ArrangementConfigUtil.isEnabled(value, myFilter, newCondition)) {
|
||||
myConditionInfo.removeCondition(componentToCheck.getMatchCondition().getValue());
|
||||
newCondition = myConditionInfo.buildCondition();
|
||||
}
|
||||
}
|
||||
|
||||
// There is a possible case that some conditions become unavailable, e.g. changing type from 'field' to 'method'
|
||||
// makes 'volatile' condition inappropriate.
|
||||
updateState(myModel);
|
||||
updateState();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
myModel.addAndCondition(chosenCondition);
|
||||
updateState(myModel);
|
||||
myConditionInfo.addAtomCondition(chosenCondition);
|
||||
updateState();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private ArrangementAtomMatchNodeComponent getNodeComponentAt(@NotNull Point screenPoint) {
|
||||
for (ArrangementAtomMatchNodeComponent component : myComponents.values()) {
|
||||
private ArrangementAtomMatchConditionComponent getNodeComponentAt(@NotNull Point screenPoint) {
|
||||
for (ArrangementAtomMatchConditionComponent component : myComponents.values()) {
|
||||
Rectangle screenBounds = component.getScreenBounds();
|
||||
if (screenBounds != null && screenBounds.contains(screenPoint)) {
|
||||
return component;
|
||||
@@ -204,7 +227,7 @@ public class ArrangementRuleEditor extends JPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void repaintComponent(@NotNull ArrangementMatchNodeComponent component) {
|
||||
private void repaintComponent(@NotNull ArrangementMatchConditionComponent component) {
|
||||
Rectangle bounds = component.getScreenBounds();
|
||||
if (bounds != null) {
|
||||
Point location = bounds.getLocation();
|
||||
|
||||
+905
-941
File diff suppressed because it is too large
Load Diff
+29
-28
@@ -26,7 +26,6 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.Rearranger;
|
||||
@@ -68,7 +67,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
|
||||
@NotNull private final Language myLanguage;
|
||||
@NotNull private final ArrangementStandardSettingsAware mySettingsAware;
|
||||
@NotNull private final ArrangementRuleTree myRuleTree;
|
||||
@NotNull private final ArrangementRuleTree myRuleTree = null;
|
||||
|
||||
public ArrangementSettingsPanel(@NotNull CodeStyleSettings settings, @NotNull Language language) {
|
||||
super(settings);
|
||||
@@ -106,8 +105,9 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
toolbarControl.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.TOP | SideBorder.RIGHT));
|
||||
myContent.add(toolbarControl, new GridBag().weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
myRuleTree = new ArrangementRuleTree(getSettings(settings), groupingRules, displayManager, colorsProvider, mySettingsAware);
|
||||
final Tree treeComponent = myRuleTree.getTreeComponent();
|
||||
//myRuleTree = new ArrangementRuleTree(getSettings(settings), groupingRules, displayManager, colorsProvider, mySettingsAware);
|
||||
//final Tree treeComponent = myRuleTree.getTreeComponent();
|
||||
final Tree treeComponent = null;
|
||||
actionToolbar.setTargetComponent(treeComponent);
|
||||
JBScrollPane scrollPane = new JBScrollPane(treeComponent);
|
||||
myContent.add(scrollPane, new GridBag().weightx(1).weighty(1).fillCell().coverLine());
|
||||
@@ -138,7 +138,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
}
|
||||
if (myWidth != visibleRect.width) {
|
||||
myWidth = visibleRect.width;
|
||||
myRuleTree.updateCanvasWidth(myWidth);
|
||||
//myRuleTree.updateCanvasWidth(myWidth);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -178,20 +178,20 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
}
|
||||
else {
|
||||
myYToRestore = -1;
|
||||
List<ArrangementRuleEditingModelImpl> models = myRuleTree.getActiveModels();
|
||||
if (models.size() == 1) {
|
||||
Rectangle bounds = treeComponent.getPathBounds(new TreePath(models.get(0).getBottomMost().getPath()));
|
||||
if (bounds != null) {
|
||||
myYToRestore = bounds.y;
|
||||
Rectangle viewRect = viewport.getViewRect();
|
||||
if (bounds.y < viewRect.y) {
|
||||
scroll(bounds.y);
|
||||
}
|
||||
else if (bounds.y + bounds.height >= viewRect.y + viewRect.height) {
|
||||
scroll(bounds.y + bounds.height - viewRect.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
//List<ArrangementRuleEditingModelImpl> models = myRuleTree.getActiveModels();
|
||||
//if (models.size() == 1) {
|
||||
// Rectangle bounds = treeComponent.getPathBounds(new TreePath(models.get(0).getBottomMost().getPath()));
|
||||
// if (bounds != null) {
|
||||
// myYToRestore = bounds.y;
|
||||
// Rectangle viewRect = viewport.getViewRect();
|
||||
// if (bounds.y < viewRect.y) {
|
||||
// scroll(bounds.y);
|
||||
// }
|
||||
// else if (bounds.y + bounds.height >= viewRect.y + viewRect.height) {
|
||||
// scroll(bounds.y + bounds.height - viewRect.height);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
@Override
|
||||
public void run() {
|
||||
treeComponent.requestFocus();
|
||||
ArrangementRuleEditingModel model = myRuleTree.newModel();
|
||||
//ArrangementRuleEditingModel model = myRuleTree.newModel();
|
||||
//ruleEditor.updateState(model, scrollPane.getVisibleRect().width);
|
||||
resetEditor.set(Boolean.FALSE);
|
||||
try {
|
||||
@@ -232,10 +232,10 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
@Override
|
||||
public void run() {
|
||||
treeComponent.requestFocus();
|
||||
List<ArrangementRuleEditingModelImpl> models = myRuleTree.getActiveModels();
|
||||
for (ArrangementRuleEditingModelImpl model : models) {
|
||||
model.destroy();
|
||||
}
|
||||
//List<ArrangementRuleEditingModelImpl> models = myRuleTree.getActiveModels();
|
||||
//for (ArrangementRuleEditingModelImpl model : models) {
|
||||
// model.destroy();
|
||||
//}
|
||||
}
|
||||
};
|
||||
final NotNullFunction<Boolean, Boolean> updateMoveFunction = new NotNullFunction<Boolean, Boolean>() {
|
||||
@@ -320,17 +320,18 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
|
||||
@Override
|
||||
public boolean isModified(@NotNull CodeStyleSettings settings) {
|
||||
return !Comparing.equal(getSettings(settings), myRuleTree.getSettings());
|
||||
//return !Comparing.equal(getSettings(settings), myRuleTree.getSettings());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(@NotNull CodeStyleSettings settings) {
|
||||
settings.getCommonSettings(myLanguage).setArrangementSettings(myRuleTree.getSettings());
|
||||
//settings.getCommonSettings(myLanguage).setArrangementSettings(myRuleTree.getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl(@NotNull CodeStyleSettings settings) {
|
||||
myRuleTree.setSettings(getSettings(settings));
|
||||
//myRuleTree.setSettings(getSettings(settings));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,6 +347,6 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
myRuleTree.disposeUI();
|
||||
//myRuleTree.disposeUI();
|
||||
}
|
||||
}
|
||||
|
||||
-121
@@ -1,121 +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.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
/**
|
||||
* JTree node for arrangement rule tree.
|
||||
* <p/>
|
||||
* The general idea is to provide two additional properties - {@link #getBackingCondition() backing condition} and {@link #getRow() row}
|
||||
* and encapsulate class casts.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/20/12 10:53 PM
|
||||
*/
|
||||
public class ArrangementTreeNode extends DefaultMutableTreeNode {
|
||||
|
||||
private static final int NO_ROW = -1;
|
||||
|
||||
@Nullable private final ArrangementMatchCondition myCondition;
|
||||
private int myRow;
|
||||
|
||||
public ArrangementTreeNode(@Nullable ArrangementMatchCondition condition) {
|
||||
this(condition, NO_ROW);
|
||||
}
|
||||
|
||||
public ArrangementTreeNode(@Nullable ArrangementMatchCondition condition, int row) {
|
||||
myCondition = condition;
|
||||
myRow = row;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArrangementMatchCondition getBackingCondition() {
|
||||
return myCondition;
|
||||
}
|
||||
|
||||
public boolean isRowSet() {
|
||||
return myRow >= 0;
|
||||
}
|
||||
|
||||
public int getRow() {
|
||||
return myRow;
|
||||
}
|
||||
|
||||
public void markRow(int row) {
|
||||
myRow = row;
|
||||
}
|
||||
|
||||
public void resetRow() {
|
||||
myRow = NO_ROW;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrangementTreeNode copy() {
|
||||
// Settings are copied by-ref intentionally here.
|
||||
return new ArrangementTreeNode(myCondition, myRow);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ArrangementTreeNode getParent() {
|
||||
return (ArrangementTreeNode)super.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getChildAt(int index) {
|
||||
return (ArrangementTreeNode)super.getChildAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getFirstChild() {
|
||||
return (ArrangementTreeNode)super.getFirstChild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getLastChild() {
|
||||
return (ArrangementTreeNode)super.getLastChild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getNextSibling() {
|
||||
return (ArrangementTreeNode)super.getNextSibling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getNextNode() {
|
||||
return (ArrangementTreeNode)super.getNextNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getPreviousNode() {
|
||||
return (ArrangementTreeNode)super.getPreviousNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementTreeNode getLastLeaf() {
|
||||
return (ArrangementTreeNode)super.getLastLeaf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myCondition == null ? "" : myCondition.toString() + (myRow >= 0 ? ": row=" + myRow : "");
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.newui;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsProvider;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchConditionComponent;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponentFactory;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/31/12 1:23 PM
|
||||
*/
|
||||
public class ArrangementMatchingRulesList extends JBList {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + ArrangementMatchingRulesList.class.getName());
|
||||
|
||||
@NotNull private final TIntObjectHashMap<ArrangementMatchConditionComponent> myComponents
|
||||
= new TIntObjectHashMap<ArrangementMatchConditionComponent>();
|
||||
|
||||
@NotNull private final DefaultListModel myModel = new DefaultListModel();
|
||||
|
||||
@NotNull private final ArrangementMatchNodeComponentFactory myFactory;
|
||||
|
||||
public ArrangementMatchingRulesList(@NotNull ArrangementNodeDisplayManager displayManager,
|
||||
@NotNull ArrangementColorsProvider colorsProvider,
|
||||
@NotNull ArrangementStandardSettingsAware settingsFilter)
|
||||
{
|
||||
myFactory = new ArrangementMatchNodeComponentFactory(displayManager, colorsProvider, myModel);
|
||||
setModel(myModel);
|
||||
setCellRenderer(new MyListCellRenderer());
|
||||
}
|
||||
|
||||
public void setRules(@Nullable List<StdArrangementMatchRule> rules) {
|
||||
myComponents.clear();
|
||||
myModel.clear();
|
||||
|
||||
if (rules == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (StdArrangementMatchRule rule : rules) {
|
||||
myModel.addElement(rule);
|
||||
}
|
||||
|
||||
if (ArrangementConstants.LOG_RULE_MODIFICATION) {
|
||||
LOG.info("Arrangement matching rules list is refreshed. Given rules:");
|
||||
for (StdArrangementMatchRule rule : rules) {
|
||||
LOG.info(" " + rule.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<StdArrangementMatchRule> getRules() {
|
||||
// TODO den implement
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// TODO den remove
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
private class MyListCellRenderer implements ListCellRenderer {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
ArrangementMatchConditionComponent component = myComponents.get(index);
|
||||
if (component == null) {
|
||||
StdArrangementMatchRule rule = (StdArrangementMatchRule)value;
|
||||
myComponents.put(index, component = myFactory.getComponent(rule.getMatcher().getCondition(), rule, true));
|
||||
}
|
||||
return component.getUiComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.newui;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsProvider;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/30/12 5:28 PM
|
||||
*/
|
||||
public class ArrangementMatchingRulesPanel extends JPanel {
|
||||
|
||||
@NotNull private final ArrangementMatchingRulesList myList;
|
||||
|
||||
public ArrangementMatchingRulesPanel(@NotNull ArrangementNodeDisplayManager displayManager,
|
||||
@NotNull ArrangementColorsProvider colorsProvider,
|
||||
@NotNull ArrangementStandardSettingsAware settingsFilter)
|
||||
{
|
||||
myList = new ArrangementMatchingRulesList(displayManager, colorsProvider, settingsFilter);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("arrangement.settings.section.match")));
|
||||
setLayout(new GridBagLayout());
|
||||
JBScrollPane scrollPane = new JBScrollPane(myList);
|
||||
add(scrollPane, new GridBag().fillCell().weightx(1).weighty(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<StdArrangementMatchRule> getRules() {
|
||||
return myList.getRules();
|
||||
}
|
||||
|
||||
public void setRules(@Nullable List<StdArrangementMatchRule> rules) {
|
||||
myList.setRules(rules);
|
||||
}
|
||||
}
|
||||
+10
-4
@@ -13,12 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
package com.intellij.application.options.codeStyle.arrangement.newui;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/27/12 10:30 AM
|
||||
* @since 10/30/12 6:57 PM
|
||||
*/
|
||||
public enum ArrangementOperator {
|
||||
AND, OR
|
||||
public interface ArrangementRepresentationAware {
|
||||
|
||||
@NotNull
|
||||
JComponent getRenderer();
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.newui;
|
||||
|
||||
import com.intellij.application.options.CodeStyleAbstractPanel;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsProvider;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsProviderImpl;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.Rearranger;
|
||||
import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementColorsAware;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.DefaultArrangementSettingsRepresentationManager;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/30/12 5:17 PM
|
||||
*/
|
||||
public abstract class ArrangementSettingsPanel2 extends CodeStyleAbstractPanel {
|
||||
|
||||
@NotNull private final JPanel myContent = new JPanel(new GridBagLayout());
|
||||
|
||||
@NotNull private final Language myLanguage;
|
||||
@NotNull private final ArrangementStandardSettingsAware mySettingsAware;
|
||||
@NotNull private final ArrangementMatchingRulesPanel myMatchingRulesPanel;
|
||||
|
||||
public ArrangementSettingsPanel2(@NotNull CodeStyleSettings settings, @NotNull Language language) {
|
||||
super(settings);
|
||||
myLanguage = language;
|
||||
Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(language);
|
||||
|
||||
assert rearranger instanceof ArrangementStandardSettingsAware;
|
||||
mySettingsAware = (ArrangementStandardSettingsAware)rearranger;
|
||||
|
||||
final ArrangementColorsProvider colorsProvider;
|
||||
if (rearranger instanceof ArrangementColorsAware) {
|
||||
colorsProvider = new ArrangementColorsProviderImpl((ArrangementColorsAware)rearranger);
|
||||
}
|
||||
else {
|
||||
colorsProvider = new ArrangementColorsProviderImpl(null);
|
||||
}
|
||||
|
||||
ArrangementStandardSettingsRepresentationAware representationManager = DefaultArrangementSettingsRepresentationManager.INSTANCE;
|
||||
if (mySettingsAware instanceof ArrangementStandardSettingsRepresentationAware) {
|
||||
representationManager = (ArrangementStandardSettingsRepresentationAware)mySettingsAware;
|
||||
}
|
||||
|
||||
final ArrangementNodeDisplayManager displayManager = new ArrangementNodeDisplayManager(
|
||||
mySettingsAware, colorsProvider, representationManager
|
||||
);
|
||||
|
||||
myMatchingRulesPanel = new ArrangementMatchingRulesPanel(displayManager, colorsProvider, mySettingsAware);
|
||||
myContent.add(myMatchingRulesPanel, new GridBag().fillCell().weightx(1).weighty(1));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPanel() {
|
||||
return myContent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) {
|
||||
// TODO den implement
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private StdArrangementSettings getSettings(@NotNull CodeStyleSettings settings) {
|
||||
StdArrangementSettings result = (StdArrangementSettings)settings.getCommonSettings(myLanguage).getArrangementSettings();
|
||||
if (result == null) {
|
||||
result = mySettingsAware.getDefaultSettings();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(CodeStyleSettings settings) {
|
||||
// TODO den implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified(CodeStyleSettings settings) {
|
||||
StdArrangementSettings s = new StdArrangementSettings(myMatchingRulesPanel.getRules());
|
||||
// TODO den add grouping rules support
|
||||
return !Comparing.equal(getSettings(settings), s);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl(CodeStyleSettings settings) {
|
||||
StdArrangementSettings s = getSettings(settings);
|
||||
if (s == null) {
|
||||
myMatchingRulesPanel.setRules(null);
|
||||
}
|
||||
else {
|
||||
myMatchingRulesPanel.setRules(s.getRules());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTabTitle() {
|
||||
return ApplicationBundle.message("arrangement.title.settings.tab");
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -16,7 +16,6 @@
|
||||
package com.intellij.application.options.codeStyle.arrangement.node;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementTreeNode;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
@@ -33,8 +32,8 @@ import java.awt.event.ItemListener;
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 3:10 PM
|
||||
*/
|
||||
public class ArrangementCheckBoxNode<T> extends ArrangementTreeNode
|
||||
implements ArrangementRepresentationAwareNode, ArrangementEditableNode
|
||||
public class ArrangementCheckBoxNode<T>/* extends ArrangementTreeNode
|
||||
implements ArrangementRepresentationAwareNode, ArrangementEditableNode*/
|
||||
{
|
||||
@NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout());
|
||||
@NotNull private final JBCheckBox myCheckBox = new JBCheckBox();
|
||||
@@ -44,7 +43,7 @@ public class ArrangementCheckBoxNode<T> extends ArrangementTreeNode
|
||||
@Nullable private Consumer<ArrangementCheckBoxNode<T>> myListener;
|
||||
|
||||
public ArrangementCheckBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull T data) {
|
||||
super(null);
|
||||
//super(null);
|
||||
myCheckBox.setText(displayManager.getDisplayValue(data));
|
||||
myData = data;
|
||||
myCheckBox.setBackground(UIUtil.getTreeBackground());
|
||||
@@ -60,13 +59,13 @@ public class ArrangementCheckBoxNode<T> extends ArrangementTreeNode
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
//@Override
|
||||
public JComponent getRenderer() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
//@Override
|
||||
public JComponent getEditor() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
+4
-5
@@ -16,7 +16,6 @@
|
||||
package com.intellij.application.options.codeStyle.arrangement.node;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementTreeNode;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -29,7 +28,7 @@ import java.util.List;
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 5:01 PM
|
||||
*/
|
||||
public class ArrangementComboBoxNode<T> extends ArrangementTreeNode implements ArrangementRepresentationAwareNode, ArrangementEditableNode {
|
||||
public class ArrangementComboBoxNode<T> /*extends ArrangementTreeNode implements ArrangementRepresentationAwareNode, ArrangementEditableNode*/ {
|
||||
|
||||
@NotNull private final JPanel myControl = new JPanel(new GridBagLayout());
|
||||
@NotNull private final JLabel myLabel = new JLabel();
|
||||
@@ -37,7 +36,7 @@ public class ArrangementComboBoxNode<T> extends ArrangementTreeNode implements A
|
||||
@NotNull private final List<T> myData = new ArrayList<T>();
|
||||
|
||||
public ArrangementComboBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull String text, @NotNull Iterable<T> data) {
|
||||
super(null);
|
||||
//super(null);
|
||||
for (T t : data) {
|
||||
myData.add(t);
|
||||
myComboBox.addItem(displayManager.getDisplayValue(t));
|
||||
@@ -48,13 +47,13 @@ public class ArrangementComboBoxNode<T> extends ArrangementTreeNode implements A
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
//@Override
|
||||
public JComponent getEditor() {
|
||||
return myControl;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
//@Override
|
||||
public JComponent getRenderer() {
|
||||
return myControl;
|
||||
}
|
||||
|
||||
+2
-3
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement.node;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -24,13 +23,13 @@ import javax.swing.*;
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 2:24 PM
|
||||
*/
|
||||
public class ArrangementSectionNode extends ArrangementTreeNode implements ArrangementRepresentationAwareNode {
|
||||
public class ArrangementSectionNode /*extends ArrangementTreeNode implements ArrangementRepresentationAwareNode*/ {
|
||||
|
||||
@NotNull private final JPanel myRenderer = new JPanel();
|
||||
@NotNull private final JLabel myTextLabel = new JLabel();
|
||||
|
||||
public ArrangementSectionNode(@NotNull String text) {
|
||||
super(null);
|
||||
//super(null);
|
||||
myTextLabel.setText(text);
|
||||
myRenderer.add(myTextLabel);
|
||||
}
|
||||
|
||||
+15
-61
@@ -16,14 +16,14 @@
|
||||
package com.intellij.application.options.codeStyle.arrangement.node.match;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementConfigUtil;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementRuleEditingModel;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -36,26 +36,24 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link ArrangementMatchNodeComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}.
|
||||
* {@link ArrangementMatchConditionComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/12 10:51 AM
|
||||
*/
|
||||
public class ArrangementAndMatchNodeComponent extends JPanel implements ArrangementMatchNodeComponent {
|
||||
public class ArrangementAndMatchConditionComponent extends JPanel implements ArrangementMatchConditionComponent {
|
||||
|
||||
private static final int BUBBLE_CONNECTOR_LENGTH = 5;
|
||||
|
||||
@NotNull private final List<ArrangementMatchNodeComponent> myComponents = new ArrayList<ArrangementMatchNodeComponent>();
|
||||
@NotNull private final List<ArrangementMatchConditionComponent> myComponents = new ArrayList<ArrangementMatchConditionComponent>();
|
||||
|
||||
@NotNull private final ArrangementCompositeMatchCondition mySetting;
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
|
||||
public ArrangementAndMatchNodeComponent(@NotNull ArrangementCompositeMatchCondition setting,
|
||||
@NotNull ArrangementMatchNodeComponentFactory factory,
|
||||
@NotNull ArrangementNodeDisplayManager manager,
|
||||
@Nullable ArrangementRuleEditingModel model)
|
||||
public ArrangementAndMatchConditionComponent(@NotNull StdArrangementMatchRule rule,
|
||||
@NotNull ArrangementCompositeMatchCondition setting,
|
||||
@NotNull ArrangementMatchNodeComponentFactory factory,
|
||||
@NotNull ArrangementNodeDisplayManager manager)
|
||||
{
|
||||
mySetting = setting;
|
||||
setOpaque(false);
|
||||
@@ -81,13 +79,13 @@ public class ArrangementAndMatchNodeComponent extends JPanel implements Arrangem
|
||||
for (Object key : ordered) {
|
||||
ArrangementMatchCondition operand = operands.get(key);
|
||||
assert operand != null;
|
||||
ArrangementMatchNodeComponent component = factory.getComponent(operand, model, false);
|
||||
ArrangementMatchConditionComponent component = factory.getComponent(operand, rule, true);
|
||||
myComponents.add(component);
|
||||
JComponent uiComponent = component.getUiComponent();
|
||||
Dimension size = uiComponent.getPreferredSize();
|
||||
add(uiComponent);
|
||||
uiComponent.setBounds(x, 0, size.width, size.height);
|
||||
x += size.width + BUBBLE_CONNECTOR_LENGTH;
|
||||
x += size.width + ArrangementConstants.HORIZONTAL_GAP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,30 +119,11 @@ public class ArrangementAndMatchNodeComponent extends JPanel implements Arrangem
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
for (ArrangementMatchNodeComponent component : myComponents) {
|
||||
for (ArrangementMatchConditionComponent component : myComponents) {
|
||||
component.setSelected(selected);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
if (myScreenBounds == null) {
|
||||
return null;
|
||||
}
|
||||
Point screenPoint = point.getScreenPoint();
|
||||
if (!myScreenBounds.contains(screenPoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ArrangementMatchNodeComponent component : myComponents) {
|
||||
Rectangle screenBounds = component.getScreenBounds();
|
||||
if (screenBounds != null && screenBounds.contains(screenPoint)) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
@@ -166,7 +145,7 @@ public class ArrangementAndMatchNodeComponent extends JPanel implements Arrangem
|
||||
myHeight = Math.max(size.height, myHeight);
|
||||
}
|
||||
if (components.length > 1) {
|
||||
myWidth += (components.length - 1) * BUBBLE_CONNECTOR_LENGTH;
|
||||
myWidth += (components.length - 1) * ArrangementConstants.HORIZONTAL_GAP;
|
||||
}
|
||||
return new Dimension(myWidth, myHeight);
|
||||
}
|
||||
@@ -179,37 +158,12 @@ public class ArrangementAndMatchNodeComponent extends JPanel implements Arrangem
|
||||
myScreenBounds = new Rectangle(point.x, point.y, bounds.width, bounds.height);
|
||||
}
|
||||
super.paint(g);
|
||||
|
||||
Component[] components = getComponents();
|
||||
if (components.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw node connectors.
|
||||
int x = 0;
|
||||
g.setColor(UIManager.getColor("Tree.hash"));
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
Component component = components[i];
|
||||
Rectangle bounds = component.getBounds();
|
||||
if (myScreenBounds != null && i < myComponents.size()) {
|
||||
myComponents.get(i).setScreenBounds(new Rectangle(
|
||||
myScreenBounds.x + bounds.x, myScreenBounds.y + bounds.y, bounds.width, bounds.height
|
||||
));
|
||||
}
|
||||
int y = bounds.y + bounds.height / 2;
|
||||
x += bounds.width;
|
||||
if (i < components.length - 1) {
|
||||
// TODO den check
|
||||
//g.drawLine(x, y, x + BUBBLE_CONNECTOR_LENGTH, y);
|
||||
}
|
||||
x += BUBBLE_CONNECTOR_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
|
||||
Point location = event.getLocationOnScreen();
|
||||
for (ArrangementMatchNodeComponent component : myComponents) {
|
||||
for (ArrangementMatchConditionComponent component : myComponents) {
|
||||
Rectangle bounds = component.getScreenBounds();
|
||||
if (bounds != null && bounds.contains(location)) {
|
||||
return component.handleMouseMove(event);
|
||||
@@ -221,7 +175,7 @@ public class ArrangementAndMatchNodeComponent extends JPanel implements Arrangem
|
||||
@Override
|
||||
public void handleMouseClick(@NotNull MouseEvent event) {
|
||||
Point location = event.getLocationOnScreen();
|
||||
for (ArrangementMatchNodeComponent component : myComponents) {
|
||||
for (ArrangementMatchConditionComponent component : myComponents) {
|
||||
Rectangle bounds = component.getScreenBounds();
|
||||
if (bounds != null && bounds.contains(location)) {
|
||||
component.handleMouseClick(event);
|
||||
+17
-34
@@ -23,7 +23,7 @@ import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.RoundedLineBorder;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,16 +33,16 @@ import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* {@link ArrangementMatchNodeComponent} for {@link ArrangementAtomMatchCondition} representation.
|
||||
* {@link ArrangementMatchConditionComponent} for {@link ArrangementAtomMatchCondition} representation.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/12 10:06 AM
|
||||
*/
|
||||
public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeComponent {
|
||||
public class ArrangementAtomMatchConditionComponent implements ArrangementMatchConditionComponent {
|
||||
|
||||
public static final int VERTICAL_PADDING = 4;
|
||||
public static final int VERTICAL_PADDING = 4;
|
||||
|
||||
@NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout()) {
|
||||
@Override
|
||||
@@ -76,14 +76,14 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
return myTextControlSize == null ? super.getPreferredSize() : myTextControlSize;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull private final String myText;
|
||||
|
||||
@NotNull private final String myText;
|
||||
@NotNull private final ArrangementColorsProvider myColorsProvider;
|
||||
@NotNull private final RoundedLineBorder myBorder;
|
||||
@NotNull private final ArrangementAtomMatchCondition myCondition;
|
||||
|
||||
@Nullable private final ActionButton myCloseButton;
|
||||
@Nullable private final Runnable myCloseCallback;
|
||||
@Nullable private final ActionButton myCloseButton;
|
||||
@Nullable private final Consumer<ArrangementAtomMatchCondition> myCloseCallback;
|
||||
|
||||
@NotNull private Color myBackgroundColor;
|
||||
|
||||
@@ -91,13 +91,12 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
|
||||
private boolean myEnabled = true;
|
||||
private boolean myInverted;
|
||||
private boolean myCloseButtonHovered;
|
||||
|
||||
public ArrangementAtomMatchNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementColorsProvider colorsProvider,
|
||||
@NotNull ArrangementAtomMatchCondition condition,
|
||||
@Nullable Runnable closeCallback)
|
||||
public ArrangementAtomMatchConditionComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementColorsProvider colorsProvider,
|
||||
@NotNull ArrangementAtomMatchCondition condition,
|
||||
@Nullable Consumer<ArrangementAtomMatchCondition> closeCallback)
|
||||
{
|
||||
myColorsProvider = colorsProvider;
|
||||
myCondition = condition;
|
||||
@@ -117,7 +116,7 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
}
|
||||
};
|
||||
|
||||
GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.CENTER).insets(0, 0, 0, 0);
|
||||
GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.WEST).weightx(1).insets(0, 0, 0, 0);
|
||||
|
||||
JPanel insetsPanel = new JPanel(new GridBagLayout());
|
||||
insetsPanel.add(myTextControl, constraints);
|
||||
@@ -140,8 +139,8 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
super.paint(g);
|
||||
}
|
||||
};
|
||||
roundBorderPanel.add(insetsPanel, new GridBag().fillCellHorizontally());
|
||||
roundBorderPanel.add(myCloseButton, new GridBag().anchor(GridBagConstraints.CENTER).insets(VERTICAL_PADDING, 0, 0, 0));
|
||||
roundBorderPanel.add(insetsPanel, new GridBag().fillCellHorizontally().anchor(GridBagConstraints.WEST));
|
||||
roundBorderPanel.add(myCloseButton, new GridBag().anchor(GridBagConstraints.CENTER).weightx(1).insets(VERTICAL_PADDING, 0, 0, 0));
|
||||
myBorder = IdeBorderFactory.createRoundedBorder(arcSize);
|
||||
roundBorderPanel.setBorder(myBorder);
|
||||
roundBorderPanel.setOpaque(false);
|
||||
@@ -180,11 +179,6 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'selected' state.
|
||||
*
|
||||
@@ -212,17 +206,6 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
myEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'inverted' state.
|
||||
* <p/>
|
||||
* For example, target rule might look like 'public' and inverting it produces 'not public'.
|
||||
*
|
||||
* @param inverted flag that indicates if current component should be drawn as 'inverted'
|
||||
*/
|
||||
public void setInverted(boolean inverted) {
|
||||
myInverted = inverted;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
|
||||
@@ -237,8 +220,8 @@ public class ArrangementAtomMatchNodeComponent implements ArrangementMatchNodeCo
|
||||
@Override
|
||||
public void handleMouseClick(@NotNull MouseEvent event) {
|
||||
Rectangle buttonBounds = getCloseButtonScreenLocation();
|
||||
if (buttonBounds != null && buttonBounds.contains(event.getLocationOnScreen()) && myCloseCallback != null) {
|
||||
myCloseCallback.run();
|
||||
if (buttonBounds != null && myCloseCallback != null && buttonBounds.contains(event.getLocationOnScreen())) {
|
||||
myCloseCallback.consume(getMatchCondition());
|
||||
}
|
||||
}
|
||||
|
||||
+6
-13
@@ -22,7 +22,6 @@ import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionButton;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -36,14 +35,14 @@ import java.awt.event.MouseEvent;
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/29/12 11:53 AM
|
||||
*/
|
||||
public class ArrangementEditIconMatchNodeComponent extends JPanel implements ArrangementMatchNodeComponent {
|
||||
public class ArrangementEditIconMatchConditionComponent extends JPanel implements ArrangementMatchConditionComponent {
|
||||
|
||||
@NotNull private final ArrangementMatchNodeComponent myDelegate;
|
||||
@NotNull private final Icon myActiveEditIcon;
|
||||
@NotNull private final Icon myInactiveEditIcon;
|
||||
@NotNull private final ActionButton myEditButton;
|
||||
@NotNull private final ArrangementMatchConditionComponent myDelegate;
|
||||
@NotNull private final Icon myActiveEditIcon;
|
||||
@NotNull private final Icon myInactiveEditIcon;
|
||||
@NotNull private final ActionButton myEditButton;
|
||||
|
||||
public ArrangementEditIconMatchNodeComponent(@NotNull ArrangementMatchNodeComponent delegate) {
|
||||
public ArrangementEditIconMatchConditionComponent(@NotNull ArrangementMatchConditionComponent delegate) {
|
||||
myDelegate = delegate;
|
||||
|
||||
setLayout(null);
|
||||
@@ -93,12 +92,6 @@ public class ArrangementEditIconMatchNodeComponent extends JPanel implements Arr
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
return myDelegate.getNodeComponentAt(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Rectangle getScreenBounds() {
|
||||
+3
-10
@@ -20,7 +20,6 @@ import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDis
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -34,7 +33,7 @@ import java.awt.event.MouseEvent;
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/12/12 5:39 PM
|
||||
*/
|
||||
public class ArrangementGroupingMatchNodeComponent extends JPanel implements ArrangementMatchNodeComponent {
|
||||
public class ArrangementGroupingMatchConditionComponent extends JPanel implements ArrangementMatchConditionComponent {
|
||||
|
||||
private static final int TOP_INSET = 3;
|
||||
|
||||
@@ -43,8 +42,8 @@ public class ArrangementGroupingMatchNodeComponent extends JPanel implements Arr
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
@NotNull private Dimension myPreferredSize;
|
||||
|
||||
public ArrangementGroupingMatchNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementAtomMatchCondition condition)
|
||||
public ArrangementGroupingMatchConditionComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementAtomMatchCondition condition)
|
||||
{
|
||||
myCondition = condition;
|
||||
String text = StringUtil.capitalize(StringUtil.pluralize(manager.getDisplayValue(myCondition.getValue())));
|
||||
@@ -66,12 +65,6 @@ public class ArrangementGroupingMatchNodeComponent extends JPanel implements Arr
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Rectangle getScreenBounds() {
|
||||
+10
-11
@@ -16,7 +16,6 @@
|
||||
package com.intellij.application.options.codeStyle.arrangement.node.match;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -25,25 +24,25 @@ import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* Component which manages {@link ArrangementMatchCondition match condition} UI representation.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/10/12 11:22 AM
|
||||
*/
|
||||
public interface ArrangementMatchNodeComponent {
|
||||
public interface ArrangementMatchConditionComponent {
|
||||
|
||||
@NotNull
|
||||
ArrangementMatchCondition getMatchCondition();
|
||||
|
||||
// TODO den add doc
|
||||
|
||||
/**
|
||||
* @return UI component for the {@link #getMatchCondition() target match condition}
|
||||
*/
|
||||
@NotNull
|
||||
JComponent getUiComponent();
|
||||
|
||||
// TODO den add doc
|
||||
@Nullable
|
||||
ArrangementMatchNodeComponent getNodeComponentAt(@NotNull RelativePoint point);
|
||||
|
||||
// TODO den add doc
|
||||
/**
|
||||
* @return screen bounds for the {@link #getUiComponent() target UI component} (if known)
|
||||
*/
|
||||
@Nullable
|
||||
Rectangle getScreenBounds();
|
||||
|
||||
@@ -52,7 +51,7 @@ public interface ArrangementMatchNodeComponent {
|
||||
/**
|
||||
* Notifies current component that canvas (container where current component is painted) width has been changed.
|
||||
* <p/>
|
||||
* The intended usage is to allow component to draw something up to/at the right screen size.
|
||||
* The intended usage is to allow component to draw something up to/at the right edge.
|
||||
*
|
||||
* @param width new canvas width
|
||||
* @return <code>true</code> if current component's representation has been changed;
|
||||
+64
-52
@@ -17,17 +17,17 @@ package com.intellij.application.options.codeStyle.arrangement.node.match;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementColorsProvider;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementRuleEditingModel;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -36,78 +36,90 @@ import java.util.Set;
|
||||
*/
|
||||
public class ArrangementMatchNodeComponentFactory {
|
||||
|
||||
@NotNull private final Set<ArrangementMatchCondition> myGroupingConditions = ContainerUtilRt.newHashSet();
|
||||
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
|
||||
@NotNull private final ArrangementColorsProvider myColorsProvider;
|
||||
@Nullable private final Runnable myRemoveConditionCallback;
|
||||
@NotNull private final DefaultListModel myListModel;
|
||||
|
||||
public ArrangementMatchNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull ArrangementColorsProvider provider,
|
||||
@Nullable Runnable removeConditionCallback,
|
||||
@NotNull List<Set<ArrangementMatchCondition>> groupingRules)
|
||||
@NotNull final DefaultListModel model)
|
||||
{
|
||||
myDisplayManager = manager;
|
||||
myColorsProvider = provider;
|
||||
myRemoveConditionCallback = removeConditionCallback;
|
||||
for (Set<ArrangementMatchCondition> rules : groupingRules) {
|
||||
myGroupingConditions.addAll(rules);
|
||||
myListModel = model;
|
||||
}
|
||||
|
||||
private static void removeCondition(@NotNull DefaultListModel model,
|
||||
@NotNull StdArrangementMatchRule rule,
|
||||
@NotNull ArrangementAtomMatchCondition condition)
|
||||
{
|
||||
int i = model.indexOf(rule);
|
||||
if (i < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrangementMatchCondition existingCondition = rule.getMatcher().getCondition();
|
||||
if (existingCondition.equals(condition)) {
|
||||
model.remove(i);
|
||||
return;
|
||||
}
|
||||
|
||||
assert existingCondition instanceof ArrangementCompositeMatchCondition;
|
||||
Set<ArrangementMatchCondition> operands = ((ArrangementCompositeMatchCondition)existingCondition).getOperands();
|
||||
operands.remove(condition);
|
||||
|
||||
if (operands.isEmpty()) {
|
||||
model.remove(i);
|
||||
}
|
||||
else if (operands.size() == 1) {
|
||||
model.set(i, new StdArrangementMatchRule(new StdArrangementEntryMatcher(operands.iterator().next()), rule.getOrderType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to build UI component for the given model.
|
||||
*
|
||||
* @param rendererTarget target model element for which UI component should be built
|
||||
* @param rule rule which contains given 'renderer target' condition and serves as
|
||||
* a data entry for the target list model
|
||||
* @param allowModification flag which indicates whether given model can be changed at future
|
||||
* @return renderer for the given model
|
||||
*/
|
||||
@NotNull
|
||||
public ArrangementMatchNodeComponent getComponent(@NotNull final ArrangementMatchCondition node,
|
||||
@Nullable final ArrangementRuleEditingModel model,
|
||||
boolean showEditIcon)
|
||||
public ArrangementMatchConditionComponent getComponent(@NotNull final ArrangementMatchCondition rendererTarget,
|
||||
@NotNull final StdArrangementMatchRule rule,
|
||||
final boolean allowModification)
|
||||
{
|
||||
final Ref<ArrangementMatchNodeComponent> ref = new Ref<ArrangementMatchNodeComponent>();
|
||||
node.invite(new ArrangementMatchConditionVisitor() {
|
||||
final Ref<ArrangementMatchConditionComponent> ref = new Ref<ArrangementMatchConditionComponent>();
|
||||
rendererTarget.invite(new ArrangementMatchConditionVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
|
||||
ArrangementMatchNodeComponent component;
|
||||
if (myGroupingConditions.contains(condition)) {
|
||||
component = new ArrangementGroupingMatchNodeComponent(myDisplayManager, condition);
|
||||
}
|
||||
else {
|
||||
component = new ArrangementAtomMatchNodeComponent(
|
||||
myDisplayManager, myColorsProvider, condition, prepareRemoveCallback(condition, model)
|
||||
);
|
||||
}
|
||||
RemoveAtomConditionCallback callback = allowModification ? new RemoveAtomConditionCallback(rule) : null;
|
||||
ArrangementMatchConditionComponent component = new ArrangementAtomMatchConditionComponent(
|
||||
myDisplayManager, myColorsProvider, condition, callback
|
||||
);
|
||||
ref.set(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
|
||||
switch (condition.getOperator()) {
|
||||
case AND:
|
||||
ref.set(new ArrangementAndMatchNodeComponent(condition, ArrangementMatchNodeComponentFactory.this, myDisplayManager, model));
|
||||
break;
|
||||
case OR: // TODO den implement
|
||||
}
|
||||
ref.set(new ArrangementAndMatchConditionComponent(rule, condition, ArrangementMatchNodeComponentFactory.this, myDisplayManager));
|
||||
}
|
||||
});
|
||||
if (showEditIcon) {
|
||||
return new ArrangementEditIconMatchNodeComponent(ref.get());
|
||||
}
|
||||
else {
|
||||
return ref.get();
|
||||
}
|
||||
return ref.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Runnable prepareRemoveCallback(@NotNull final ArrangementMatchCondition condition,
|
||||
@Nullable final ArrangementRuleEditingModel model)
|
||||
{
|
||||
if (model == null) {
|
||||
return null;
|
||||
private class RemoveAtomConditionCallback implements Consumer<ArrangementAtomMatchCondition> {
|
||||
|
||||
@NotNull private final StdArrangementMatchRule myRule;
|
||||
|
||||
RemoveAtomConditionCallback(@NotNull StdArrangementMatchRule rule) {
|
||||
myRule = rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(ArrangementAtomMatchCondition condition) {
|
||||
removeCondition(myListModel, myRule, condition);
|
||||
}
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
model.removeAndCondition(condition);
|
||||
if (myRemoveConditionCallback != null) {
|
||||
myRemoveConditionCallback.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFixtureTes
|
||||
condition = atom(conditions[0])
|
||||
}
|
||||
else {
|
||||
condition = ArrangementUtil.and(conditions.collect { atom(it) } as ArrangementMatchCondition[])
|
||||
condition = ArrangementUtil.combine(conditions.collect { atom(it) } as ArrangementMatchCondition[])
|
||||
}
|
||||
|
||||
new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition))
|
||||
|
||||
Reference in New Issue
Block a user