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
Grouping rules UI
This commit is contained in:
+87
-6
@@ -16,17 +16,20 @@
|
||||
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.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -48,24 +51,102 @@ public class ArrangementGroupingRulesManager {
|
||||
@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;
|
||||
}
|
||||
ArrangementCheckBoxNode groupingCheckNode = new ArrangementCheckBoxNode(displayManager.getDisplayValue(groupingType));
|
||||
result.add(groupingCheckNode);
|
||||
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;
|
||||
}
|
||||
|
||||
public void applyRules(@NotNull List<ArrangementGroupingRule> rules, @NotNull TreeNode groupsRoot) {
|
||||
// TODO den implement
|
||||
@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>();
|
||||
// TODO den implement
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+48
-12
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementEditableNode;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementRepresentationAwareNode;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.ArrangementSectionNode;
|
||||
import com.intellij.application.options.codeStyle.arrangement.node.match.ArrangementMatchNodeComponent;
|
||||
@@ -205,16 +206,22 @@ public class ArrangementRuleTree {
|
||||
setSettings(settings);
|
||||
|
||||
myTree.setShowsRootHandles(false);
|
||||
myTree.setCellRenderer(new MyCellRenderer());
|
||||
TreeUI ui = myTree.getUI();
|
||||
if (!(ui instanceof WideSelectionTreeUI)) {
|
||||
// IJ wide selection tree ui is not applied for some LAFs (e.g. GTK) and default wide selection tree ui doesn't allow
|
||||
// to customize selection background appliance algorithm (don't draw background for rule components; do draw for
|
||||
// 'new rule' node).
|
||||
// That's why we forcibly apply UI with custom selection strategy here.
|
||||
// P.S. 'wide selection tree ui' appliance decision is taken at the com.intellij.ui.treeStructure.Tree.setUI().
|
||||
myTree.setUI(new WideSelectionTreeUI(true, wideSelectionCondition));
|
||||
}
|
||||
MyCellRenderer renderer = new MyCellRenderer();
|
||||
myTree.setCellRenderer(renderer);
|
||||
myTree.setEditable(true);
|
||||
myTree.setCellEditor(new MyCellEditor(myTree, renderer));
|
||||
|
||||
// IJ wide selection tree ui is not applied for some LAFs (e.g. GTK) and default wide selection tree ui doesn't allow
|
||||
// to customize selection background appliance algorithm (don't draw background for rule components; do draw for
|
||||
// 'new rule' node).
|
||||
// That's why we forcibly apply UI with custom selection strategy here.
|
||||
// P.S. 'wide selection tree ui' appliance decision is taken at the com.intellij.ui.treeStructure.Tree.setUI().
|
||||
myTree.setUI(new WideSelectionTreeUI(true, wideSelectionCondition) {
|
||||
@Override
|
||||
protected boolean shouldPaintExpandControl(TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateCanvasWidth(final int width) {
|
||||
@@ -464,7 +471,7 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
|
||||
if (myGroupingsRoot != null) {
|
||||
myGroupingRulesManager.applyRules(settings.getGroupings(), myGroupingsRoot);
|
||||
myGroupingRulesManager.applyRules(settings.getGroupings(), myGroupingsRoot, myTreeModel);
|
||||
}
|
||||
|
||||
List<StdArrangementMatchRule> rules = settings.getRules();
|
||||
@@ -670,7 +677,7 @@ public class ArrangementRuleTree {
|
||||
if (parent != null) parent.remove(EMPTY_RENDERER);
|
||||
}
|
||||
|
||||
private class MyCellRenderer implements TreeCellRenderer {
|
||||
private class MyCellRenderer extends DefaultTreeCellRenderer {
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree,
|
||||
Object value,
|
||||
@@ -702,6 +709,35 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyCellEditor extends DefaultTreeCellEditor {
|
||||
MyCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
|
||||
super(tree, renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
|
||||
if (value instanceof ArrangementEditableNode) {
|
||||
return ((ArrangementEditableNode)value).getEditor();
|
||||
}
|
||||
else {
|
||||
return super.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(EventObject event) {
|
||||
if (event instanceof MouseEvent) {
|
||||
MouseEvent mouseEvent = (MouseEvent)event;
|
||||
TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
return path.getLastPathComponent() instanceof ArrangementEditableNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class MySelectionModel extends DefaultTreeSelectionModel {
|
||||
|
||||
MySelectionModel() {
|
||||
|
||||
+54
-8
@@ -15,30 +15,48 @@
|
||||
*/
|
||||
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.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 3:10 PM
|
||||
*/
|
||||
public class ArrangementCheckBoxNode extends ArrangementTreeNode implements ArrangementRepresentationAwareNode {
|
||||
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();
|
||||
|
||||
@NotNull private final JPanel myRenderer = new JPanel(new GridBagLayout());
|
||||
@NotNull private final T myData;
|
||||
|
||||
public ArrangementCheckBoxNode(@NotNull String text) {
|
||||
@Nullable private Consumer<ArrangementCheckBoxNode<T>> myListener;
|
||||
|
||||
public ArrangementCheckBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull T data) {
|
||||
super(null);
|
||||
JBCheckBox checkBox = new JBCheckBox(text);
|
||||
checkBox.setBackground(UIUtil.getTreeBackground());
|
||||
myRenderer.add(checkBox, new GridBag().anchor(GridBagConstraints.WEST));
|
||||
myCheckBox.setText(displayManager.getDisplayValue(data));
|
||||
myData = data;
|
||||
myCheckBox.setBackground(UIUtil.getTreeBackground());
|
||||
myRenderer.add(myCheckBox, new GridBag().anchor(GridBagConstraints.WEST));
|
||||
myCheckBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (myListener != null) {
|
||||
myListener.consume(ArrangementCheckBoxNode.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -46,4 +64,32 @@ public class ArrangementCheckBoxNode extends ArrangementTreeNode implements Arr
|
||||
public JComponent getRenderer() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getEditor() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return myCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
myCheckBox.setSelected(selected);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public T getValue() {
|
||||
return myData;
|
||||
}
|
||||
|
||||
public void setChangeCallback(@Nullable Consumer<ArrangementCheckBoxNode<T>> listener) {
|
||||
myListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myData.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 5:01 PM
|
||||
*/
|
||||
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();
|
||||
@NotNull private final JComboBox myComboBox = new JComboBox();
|
||||
@NotNull private final List<T> myData = new ArrayList<T>();
|
||||
|
||||
public ArrangementComboBoxNode(@NotNull ArrangementNodeDisplayManager displayManager, @NotNull String text, @NotNull Iterable<T> data) {
|
||||
super(null);
|
||||
for (T t : data) {
|
||||
myData.add(t);
|
||||
myComboBox.addItem(displayManager.getDisplayValue(t));
|
||||
}
|
||||
myLabel.setText(text);
|
||||
myControl.add(myLabel, new GridBag().setColumn(0).insets(0, 3, 0, 0));
|
||||
myControl.add(myComboBox, new GridBag().setColumn(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getEditor() {
|
||||
return myControl;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getRenderer() {
|
||||
return myControl;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
myLabel.setEnabled(enabled);
|
||||
myComboBox.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public T getSelectedValue() {
|
||||
int index = myComboBox.getSelectedIndex();
|
||||
if (index < 0 || index >= myData.size()) {
|
||||
return myData.get(0);
|
||||
}
|
||||
return myData.get(index);
|
||||
}
|
||||
|
||||
public void setSelectedValue(@NotNull T value) {
|
||||
int i = myData.indexOf(value);
|
||||
if (i >= 0) {
|
||||
myComboBox.setSelectedIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myData.toString();
|
||||
}
|
||||
}
|
||||
+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.node;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/27/12 4:44 PM
|
||||
*/
|
||||
public interface ArrangementEditableNode extends TreeNode {
|
||||
|
||||
@NotNull
|
||||
JComponent getEditor();
|
||||
}
|
||||
@@ -565,10 +565,11 @@ arrangement.settings.section.match=Matching rules
|
||||
arrangement.settings.groups.dependent.methods=Keep dependent methods together
|
||||
arrangement.settings.groups.overridden.methods=Keep overridden methods together
|
||||
arrangement.settings.groups.getters.and.setters.together=Keep getters and setters together
|
||||
arrangement.settings.order.type.keep=Keep
|
||||
arrangement.settings.order.type.by.name=By name
|
||||
arrangement.settings.order.type.depth.first=Depth-first
|
||||
arrangement.settings.order.type.breadth.first=Breadth-first
|
||||
arrangement.settings.order.type.keep=keep
|
||||
arrangement.settings.order.type.by.name=by name
|
||||
arrangement.settings.order.type.depth.first=depth-first
|
||||
arrangement.settings.order.type.breadth.first=breadth-first
|
||||
arrangement.settings.label.order=order
|
||||
|
||||
checkbox.spaces.around.lambda.arrow=Lambda arrow
|
||||
checkbox.spaces.around.method.ref.dbl.colon.arrow=Method reference double colon
|
||||
Reference in New Issue
Block a user