IDEA-182834 Incorrect checkboxes in the trees

This commit is contained in:
Kirill Kirichenko
2017-11-30 17:40:17 +03:00
parent 8898f03be3
commit d4b0fa55c0
3 changed files with 37 additions and 32 deletions
@@ -26,6 +26,8 @@ import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import java.awt.*;
import static com.intellij.util.ui.ThreeStateCheckBox.State;
public class CheckboxTreeBase extends Tree {
private final CheckboxTreeHelper myHelper;
private final EventDispatcher<CheckboxTreeListener> myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
@@ -122,9 +124,9 @@ public class CheckboxTreeBase extends Tree {
protected void nodeStateWillChange(CheckedTreeNode node) {
}
@SuppressWarnings("unused")
@Deprecated
protected void adjustParents(final CheckedTreeNode node, final boolean checked) {
}
protected void adjustParents(final CheckedTreeNode node, final boolean checked) {}
public static class CheckboxTreeCellRendererBase extends JPanel implements TreeCellRenderer {
private final ColoredTreeCellRenderer myTextRenderer;
@@ -159,10 +161,11 @@ public class CheckboxTreeBase extends Tree {
if (value instanceof CheckedTreeNode) {
CheckedTreeNode node = (CheckedTreeNode)value;
NodeState state = getNodeStatus(node);
State state = getNodeStatus(node);
myCheckbox.setVisible(true);
myCheckbox.setSelected(state != NodeState.CLEAR);
myCheckbox.setEnabled(node.isEnabled() && state != NodeState.PARTIAL);
myCheckbox.setEnabled(node.isEnabled());
myCheckbox.setSelected(state != State.NOT_SELECTED);
myCheckbox.setState(state);
myCheckbox.setOpaque(false);
myCheckbox.setBackground(null);
setBackground(null);
@@ -190,27 +193,27 @@ public class CheckboxTreeBase extends Tree {
return this;
}
private NodeState getNodeStatus(final CheckedTreeNode node) {
if (myIgnoreInheritance) return node.isChecked() ? NodeState.FULL : NodeState.CLEAR;
private State getNodeStatus(final CheckedTreeNode node) {
if (myIgnoreInheritance) return node.isChecked() ? State.SELECTED : State.NOT_SELECTED;
final boolean checked = node.isChecked();
if (node.getChildCount() == 0 || !myUsePartialStatusForParentNodes) return checked ? NodeState.FULL : NodeState.CLEAR;
if (node.getChildCount() == 0 || !myUsePartialStatusForParentNodes) return checked ? State.SELECTED : State.NOT_SELECTED;
NodeState result = null;
State result = null;
for (int i = 0; i < node.getChildCount(); i++) {
TreeNode child = node.getChildAt(i);
NodeState childStatus = child instanceof CheckedTreeNode? getNodeStatus((CheckedTreeNode)child) :
checked? NodeState.FULL : NodeState.CLEAR;
if (childStatus == NodeState.PARTIAL) return NodeState.PARTIAL;
State childStatus = child instanceof CheckedTreeNode? getNodeStatus((CheckedTreeNode)child) :
checked? State.SELECTED : State.NOT_SELECTED;
if (childStatus == State.DONT_CARE) return State.DONT_CARE;
if (result == null) {
result = childStatus;
}
else if (result != childStatus) {
return NodeState.PARTIAL;
return State.DONT_CARE;
}
}
return result == null ? NodeState.CLEAR : result;
return result == null ? State.NOT_SELECTED : result;
}
/**
@@ -254,7 +257,12 @@ public class CheckboxTreeBase extends Tree {
}
}
/**
* Don't use this enum. Left for API compatibility.
* @see ThreeStateCheckBox.State
* @deprecated
*/
@Deprecated
public enum NodeState {
FULL, CLEAR, PARTIAL
}
@@ -19,10 +19,7 @@ import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.Gray;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.*;
import sun.swing.SwingUtilities2;
import javax.swing.*;
@@ -268,6 +265,7 @@ public class DarculaCheckBoxUI extends MetalCheckBoxUI {
}
protected boolean isIndeterminate(AbstractButton checkBox) {
return "indeterminate".equals(checkBox.getClientProperty("JButton.selectedState"));
return "indeterminate".equals(checkBox.getClientProperty("JButton.selectedState")) ||
checkBox instanceof ThreeStateCheckBox && ((ThreeStateCheckBox)checkBox).getState() == ThreeStateCheckBox.State.DONT_CARE;
}
}
@@ -47,12 +47,12 @@ import java.util.*;
import java.util.List;
import static com.intellij.openapi.keymap.KeymapUtil.getActiveKeymapShortcuts;
import static com.intellij.util.ui.ThreeStateCheckBox.State;
public abstract class ChangesTree extends Tree implements DataProvider {
@NotNull protected final Project myProject;
private final boolean myShowCheckboxes;
private final int myCheckboxWidth;
private final boolean myHighlightProblems;
private boolean myShowFlatten;
private boolean myIsModelFlat;
@@ -72,7 +72,6 @@ public abstract class ChangesTree extends Tree implements DataProvider {
super(ChangesBrowserNode.createRoot(project));
myProject = project;
myShowCheckboxes = showCheckboxes;
myHighlightProblems = highlightProblems;
myCheckboxWidth = new JCheckBox().getPreferredSize().width;
setHorizontalAutoScrollingEnabled(false);
@@ -81,7 +80,7 @@ public abstract class ChangesTree extends Tree implements DataProvider {
setOpaque(false);
new TreeSpeedSearch(this, ChangesBrowserNode.TO_TEXT_CONVERTER);
final ChangesBrowserNodeRenderer nodeRenderer = new ChangesBrowserNodeRenderer(myProject, () -> myShowFlatten, myHighlightProblems);
final ChangesBrowserNodeRenderer nodeRenderer = new ChangesBrowserNodeRenderer(myProject, () -> myShowFlatten, highlightProblems);
setCellRenderer(new MyTreeCellRenderer(nodeRenderer));
new MyToggleSelectionAction().registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), this);
@@ -265,7 +264,7 @@ public abstract class ChangesTree extends Tree implements DataProvider {
while (enumeration.hasMoreElements()) {
ChangesBrowserNode node = (ChangesBrowserNode)enumeration.nextElement();
if (node != root && getNodeStatus(node) == CheckboxTree.NodeState.CLEAR) {
if (node != root && getNodeStatus(node) == State.NOT_SELECTED) {
collapsePath(new TreePath(node.getPath()));
}
}
@@ -273,7 +272,7 @@ public abstract class ChangesTree extends Tree implements DataProvider {
enumeration = root.depthFirstEnumeration();
while (enumeration.hasMoreElements()) {
ChangesBrowserNode node = (ChangesBrowserNode)enumeration.nextElement();
if (node.isLeaf() && getNodeStatus(node) == CheckboxTree.NodeState.FULL) {
if (node.isLeaf() && getNodeStatus(node) == State.SELECTED) {
selectedTreeRow = getRowForPath(new TreePath(node.getPath()));
break;
}
@@ -487,8 +486,8 @@ public abstract class ChangesTree extends Tree implements DataProvider {
myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (myShowCheckboxes) {
@SuppressWarnings("unchecked")
CheckboxTree.NodeState state = getNodeStatus((ChangesBrowserNode)value);
myCheckBox.setSelected(state != CheckboxTree.NodeState.CLEAR);
State state = getNodeStatus((ChangesBrowserNode)value);
myCheckBox.setSelected(state != State.NOT_SELECTED);
myCheckBox.setEnabled(tree.isEnabled() && isNodeEnabled((ChangesBrowserNode)value));
revalidate();
@@ -507,7 +506,7 @@ public abstract class ChangesTree extends Tree implements DataProvider {
}
private CheckboxTree.NodeState getNodeStatus(ChangesBrowserNode<?> node) {
private State getNodeStatus(ChangesBrowserNode<?> node) {
boolean hasIncluded = false;
boolean hasExcluded = false;
@@ -520,13 +519,13 @@ public abstract class ChangesTree extends Tree implements DataProvider {
}
}
if (hasIncluded && hasExcluded) return CheckboxTree.NodeState.PARTIAL;
if (hasIncluded) return CheckboxTree.NodeState.FULL;
return CheckboxTree.NodeState.CLEAR;
if (hasIncluded && hasExcluded) return State.DONT_CARE;
if (hasIncluded) return State.SELECTED;
return State.NOT_SELECTED;
}
protected boolean isNodeEnabled(ChangesBrowserNode<?> node) {
return getNodeStatus(node) != CheckboxTree.NodeState.PARTIAL;
return getNodeStatus(node) != State.DONT_CARE;
}
private class MyToggleSelectionAction extends AnAction implements DumbAware {