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

1. Add ability to remove atom condition via single click;
2. Refactoring;
This commit is contained in:
Denis.Zhdanov
2012-08-23 13:47:00 +04:00
parent c38865bbaa
commit c0b46963e5
12 changed files with 86 additions and 58 deletions
@@ -127,12 +127,12 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementMatchCondition node) {
final Ref<HierarchicalArrangementSettingsNode> result = new Ref<HierarchicalArrangementSettingsNode>();
public HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node) {
final Ref<HierarchicalArrangementConditionNode> result = new Ref<HierarchicalArrangementConditionNode>();
node.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
result.set(new HierarchicalArrangementSettingsNode(setting));
result.set(new HierarchicalArrangementConditionNode(setting));
}
@Override
@@ -145,10 +145,10 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
}
if (typeNode == null) {
result.set(new HierarchicalArrangementSettingsNode(setting));
result.set(new HierarchicalArrangementConditionNode(setting));
}
else {
HierarchicalArrangementSettingsNode parent = new HierarchicalArrangementSettingsNode(typeNode);
HierarchicalArrangementConditionNode parent = new HierarchicalArrangementConditionNode(typeNode);
ArrangementCompositeMatchCondition compositeWithoutType = new ArrangementCompositeMatchCondition(setting.getOperator());
for (ArrangementMatchCondition n : setting.getOperands()) {
if (n != typeNode) {
@@ -156,10 +156,10 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
}
if (compositeWithoutType.getOperands().size() == 1) {
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType.getOperands().iterator().next()));
parent.setChild(new HierarchicalArrangementConditionNode(compositeWithoutType.getOperands().iterator().next()));
}
else {
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType));
parent.setChild(new HierarchicalArrangementConditionNode(compositeWithoutType));
}
result.set(parent);
}
@@ -27,12 +27,12 @@ import org.jetbrains.annotations.Nullable;
* @author Denis Zhdanov
* @since 8/8/12 1:23 PM
*/
public class HierarchicalArrangementSettingsNode {
public class HierarchicalArrangementConditionNode {
@NotNull private final ArrangementMatchCondition myCurrent;
@Nullable private HierarchicalArrangementSettingsNode myChild;
@NotNull private final ArrangementMatchCondition myCurrent;
@Nullable private HierarchicalArrangementConditionNode myChild;
public HierarchicalArrangementSettingsNode(@NotNull ArrangementMatchCondition current) {
public HierarchicalArrangementConditionNode(@NotNull ArrangementMatchCondition current) {
myCurrent = current;
}
@@ -42,11 +42,11 @@ public class HierarchicalArrangementSettingsNode {
}
@Nullable
public HierarchicalArrangementSettingsNode getChild() {
public HierarchicalArrangementConditionNode getChild() {
return myChild;
}
public void setChild(@Nullable HierarchicalArrangementSettingsNode child) {
public void setChild(@Nullable HierarchicalArrangementConditionNode child) {
myChild = child;
}
@@ -16,7 +16,7 @@
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import org.jetbrains.annotations.NotNull;
/**
@@ -39,12 +39,12 @@ public interface ArrangementSettingsGrouper {
* |
* ---public---static---final
* </pre>
* That means that we'll return a {@link HierarchicalArrangementSettingsNode} with condition <code>'type: field'</code> and
* That means that we'll return a {@link HierarchicalArrangementConditionNode} with condition <code>'type: field'</code> and
* a single child node with composite <code>'AND'</code> condition <code>'modifier: public; modifier: static; modifier: final'</code>.
*
* @param node settings node which conditions should be grouped
* @return grouping-aware node
*/
@NotNull
HierarchicalArrangementSettingsNode group(@NotNull ArrangementMatchCondition node);
HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node);
}
@@ -16,7 +16,7 @@
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import org.jetbrains.annotations.NotNull;
/**
@@ -29,8 +29,8 @@ public class DefaultArrangementSettingsGrouper implements ArrangementSettingsGro
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementMatchCondition node) {
public HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node) {
// Don't group.
return new HierarchicalArrangementSettingsNode(node);
return new HierarchicalArrangementConditionNode(node);
}
}
@@ -207,6 +207,18 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
return null;
}
@Override
public void handleMouseClick(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementNodeComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null && bounds.contains(location)) {
component.handleMouseClick(event);
return;
}
}
}
@Override
public String toString() {
return String.format("(%s)", StringUtil.join(myComponents, " and "));
@@ -73,8 +73,9 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
}
};
@NotNull private final ArrangementAtomMatchCondition mySetting;
@Nullable private final ActionButton myCloseButton;
@NotNull private final ArrangementAtomMatchCondition myCondition;
@Nullable private final ActionButton myCloseButton;
@Nullable private final Consumer<ArrangementAtomMatchCondition> myCloseCallback;
@Nullable private Dimension mySize;
@Nullable private Rectangle myScreenBounds;
@@ -85,14 +86,15 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
private boolean myCloseButtonHovered;
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
@NotNull ArrangementAtomMatchCondition setting,
@NotNull ArrangementAtomMatchCondition condition,
@Nullable Consumer<ArrangementAtomMatchCondition> closeCallback)
{
mySetting = setting;
myCondition = condition;
myCloseCallback = closeCallback;
myLabel.setHorizontalAlignment(SwingConstants.CENTER);
myLabel.setText(manager.getDisplayValue(setting));
myLabel.setText(manager.getDisplayValue(condition));
int width = manager.getMaxWidth(setting.getType());
int width = manager.getMaxWidth(condition.getType());
int height = myLabel.getPreferredSize().height;
final ArrangementRemoveConditionAction action;
if (closeCallback == null) {
@@ -162,7 +164,7 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
@NotNull
@Override
public ArrangementAtomMatchCondition getMatchCondition() {
return mySetting;
return myCondition;
}
@NotNull
@@ -227,6 +229,14 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
return (mouseOverButton ^ myCloseButtonHovered) ? buttonBounds : null;
}
@Override
public void handleMouseClick(@NotNull MouseEvent event) {
Rectangle buttonBounds = getCloseButtonScreenLocation();
if (buttonBounds != null && buttonBounds.contains(event.getLocationOnScreen()) && myCloseCallback != null) {
myCloseCallback.consume(myCondition);
}
}
@Nullable
private Rectangle getCloseButtonScreenLocation() {
if (myCloseButton == null || myScreenBounds == null) {
@@ -20,7 +20,7 @@ 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.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.containers.Stack;
@@ -121,15 +121,15 @@ public class ArrangementConfigUtil {
return null;
}
public static int getDepth(@NotNull HierarchicalArrangementSettingsNode node) {
HierarchicalArrangementSettingsNode child = node.getChild();
public static int getDepth(@NotNull HierarchicalArrangementConditionNode node) {
HierarchicalArrangementConditionNode child = node.getChild();
return child == null ? 1 : 1 + getDepth(child);
}
@NotNull
public static HierarchicalArrangementSettingsNode getLast(@NotNull HierarchicalArrangementSettingsNode node) {
HierarchicalArrangementSettingsNode result = node;
for (HierarchicalArrangementSettingsNode child = node.getChild(); child != null; child = child.getChild()) {
public static HierarchicalArrangementConditionNode getLast(@NotNull HierarchicalArrangementConditionNode node) {
HierarchicalArrangementConditionNode result = node;
for (HierarchicalArrangementConditionNode child = node.getChild(); child != null; child = child.getChild()) {
result = child;
}
return result;
@@ -175,25 +175,25 @@ public class ArrangementConfigUtil {
/**
* @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 settingsNode settings node which should be represented at the UI tree denoted by the given UI tree node
* @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 HierarchicalArrangementSettingsNode settingsNode,
@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 (settingsNode.getCurrent().equals(child.getBackingSetting())) {
if (conditionNode.getCurrent().equals(child.getBackingSetting())) {
uiNode = child;
}
}
if (uiNode == null) {
uiNode = new ArrangementTreeNode(settingsNode.getCurrent());
uiNode = new ArrangementTreeNode(conditionNode.getCurrent());
if (uiParentNode != null) {
if (model == null) {
uiParentNode.add(uiNode);
@@ -205,9 +205,9 @@ public class ArrangementConfigUtil {
rowsCreated++;
}
ArrangementTreeNode leaf = uiNode;
HierarchicalArrangementSettingsNode childSettingsNode = settingsNode.getChild();
if (childSettingsNode != null) {
Pair<ArrangementTreeNode, Integer> pair = map(uiNode, childSettingsNode, model);
HierarchicalArrangementConditionNode childConditionNode = conditionNode.getChild();
if (childConditionNode != null) {
Pair<ArrangementTreeNode, Integer> pair = map(uiNode, childConditionNode, model);
leaf = pair.first;
rowsCreated += pair.second;
}
@@ -68,4 +68,6 @@ public interface ArrangementNodeComponent {
*/
@Nullable
Rectangle handleMouseMove(@NotNull MouseEvent event);
void handleMouseClick(@NotNull MouseEvent event);
}
@@ -45,7 +45,7 @@ public interface ArrangementRuleEditingModel {
*/
boolean hasCondition(@NotNull Object key);
void addAndCondition(@NotNull ArrangementAtomMatchCondition setting);
void addAndCondition(@NotNull ArrangementAtomMatchCondition condition);
void removeAndCondition(@NotNull ArrangementMatchCondition node);
void removeAndCondition(@NotNull ArrangementMatchCondition condition);
}
@@ -18,7 +18,7 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import gnu.trove.TIntObjectHashMap;
@@ -45,11 +45,11 @@ public class ArrangementRuleEditingModelBuilder {
* <pre>
* <ol>
* <li>
* {@link HierarchicalArrangementSettingsNode Groups} given {@link ArrangementMatchCondition settings} using
* {@link HierarchicalArrangementConditionNode Groups} given {@link ArrangementMatchCondition settings} using
* the given {@link ArrangementSettingsGrouper#group(ArrangementMatchCondition) strategy};
* </li>
* <li>
* Build {@link DefaultMutableTreeNode tree nodes} for the {@link HierarchicalArrangementSettingsNode groiping-aware nodes}
* 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>
@@ -92,7 +92,7 @@ public class ArrangementRuleEditingModelBuilder {
initialInsertRow--;
}
HierarchicalArrangementSettingsNode grouped = grouper.group(matchCondition);
HierarchicalArrangementConditionNode grouped = grouper.group(matchCondition);
DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
Pair<ArrangementTreeNode, Integer> pair = ArrangementConfigUtil.map(root, grouped, treeModel);
ArrangementTreeNode topMostNode = ArrangementConfigUtil.getLastBefore(pair.first, root);
@@ -57,7 +57,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
* to generate corresponding events automatically
* @param node backing settings node
* @param topMost there is a possible case that a single settings node is shown in more than one visual line
* ({@link HierarchicalArrangementSettingsNode}). This argument is the top-most UI node used for the
* ({@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 grouper strategy that encapsulates information on how settings node should be displayed
@@ -139,21 +139,21 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
}
@Override
public void addAndCondition(@NotNull ArrangementAtomMatchCondition setting) {
TIntIntHashMap rowChanges = doAddAndCondition(setting);
public void addAndCondition(@NotNull ArrangementAtomMatchCondition condition) {
TIntIntHashMap rowChanges = doAddAndCondition(condition);
refreshConditions();
notifyListeners(rowChanges);
}
@NotNull
private TIntIntHashMap doAddAndCondition(@NotNull ArrangementAtomMatchCondition setting) {
ArrangementMatchCondition newNode = ArrangementUtil.and(myMatchCondition.clone(), setting);
return applyNewSetting(newNode);
private TIntIntHashMap doAddAndCondition(@NotNull ArrangementAtomMatchCondition condition) {
ArrangementMatchCondition newNode = ArrangementUtil.and(myMatchCondition.clone(), condition);
return applyNewCondition(newNode);
}
@Override
public void removeAndCondition(@NotNull ArrangementMatchCondition node) {
TIntIntHashMap rowChanges = doRemoveAndCondition(node);
public void removeAndCondition(@NotNull ArrangementMatchCondition condition) {
TIntIntHashMap rowChanges = doRemoveAndCondition(condition);
refreshConditions();
notifyListeners(rowChanges);
}
@@ -171,13 +171,13 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
newNode = composite.getOperands().iterator().next();
}
return applyNewSetting(newNode);
return applyNewCondition(newNode);
}
@NotNull
private TIntIntHashMap applyNewSetting(@NotNull ArrangementMatchCondition newNode) {
private TIntIntHashMap applyNewCondition(@NotNull ArrangementMatchCondition newNode) {
myMatchCondition = newNode;
HierarchicalArrangementSettingsNode grouped = myGrouper.group(newNode);
HierarchicalArrangementConditionNode grouped = myGrouper.group(newNode);
int newDepth = ArrangementConfigUtil.getDepth(grouped);
int oldDepth = ArrangementConfigUtil.distance(myTopMost, myBottomMost);
if (oldDepth == newDepth) {
@@ -350,8 +350,11 @@ public class ArrangementRuleTree {
}
private void removeConditionFromActiveModel(@NotNull ArrangementAtomMatchCondition condition) {
// TODO den implement
System.out.println("Remove condition " + condition);
ArrangementRuleEditingModel model = getActiveModel();
if (model != null) {
model.removeAndCondition(condition);
notifySelectionListeners(model);
}
}
private void onMouseMoved(@NotNull MouseEvent e) {
@@ -368,6 +371,7 @@ public class ArrangementRuleTree {
private void onMouseClicked(@NotNull MouseEvent e) {
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
if (component != null) {
component.handleMouseClick(e);
return;
}
// Clear selection