summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStas Negara <snegara@google.com>2015-05-13 14:56:38 -0700
committerStas Negara <snegara@google.com>2015-05-13 15:46:49 -0700
commit905019fb9557e1728bd83016ca96665193a1c501 (patch)
tree6110c70fb2630e340e490dbd68ac38e4cceaefa7
parent0d67b0b2e2c4312b646c30531a1d7683cfedcf06 (diff)
downloadtesting-905019fb9557e1728bd83016ca96665193a1c501.tar.gz
Enforce single value choice for each cloud device dimension.
Also, make cloud device configuration dialog match better its purpose (vs. matrix configuration dialog). Change-Id: Iaae3167f7e71ba3d3d560bcb50d3095a8a03b78f
-rw-r--r--src/com/google/gct/testing/CloudConfigurationChooserDialog.java7
-rw-r--r--src/com/google/gct/testing/CloudConfigurationImpl.java11
-rw-r--r--src/com/google/gct/testing/TwoPanelTree.java295
3 files changed, 249 insertions, 64 deletions
diff --git a/src/com/google/gct/testing/CloudConfigurationChooserDialog.java b/src/com/google/gct/testing/CloudConfigurationChooserDialog.java
index f651097..830e02c 100644
--- a/src/com/google/gct/testing/CloudConfigurationChooserDialog.java
+++ b/src/com/google/gct/testing/CloudConfigurationChooserDialog.java
@@ -51,6 +51,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
+import static com.android.tools.idea.run.CloudConfiguration.Kind.SINGLE_DEVICE;
import static com.google.gct.testing.CloudTestingUtils.createConfigurationChooserGbc;
public class CloudConfigurationChooserDialog extends DialogWrapper implements ConfigurationChangeListener {
@@ -107,7 +108,11 @@ public class CloudConfigurationChooserDialog extends DialogWrapper implements Co
facet = AndroidFacet.getInstance(module);
- setTitle("Matrix Configurations");
+ if (configurationKind == SINGLE_DEVICE) {
+ setTitle("Single Device Configurations");
+ } else {
+ setTitle("Matrix Configurations");
+ }
getOKAction().setEnabled(true);
diff --git a/src/com/google/gct/testing/CloudConfigurationImpl.java b/src/com/google/gct/testing/CloudConfigurationImpl.java
index eaa89ea..b9a7acf 100644
--- a/src/com/google/gct/testing/CloudConfigurationImpl.java
+++ b/src/com/google/gct/testing/CloudConfigurationImpl.java
@@ -30,6 +30,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import static com.android.tools.idea.run.CloudConfiguration.Kind.SINGLE_DEVICE;
+
public class CloudConfigurationImpl extends CloudConfiguration {
public static final int ALL_CONFIGURATION_ID = Integer.MAX_VALUE;
@@ -139,7 +141,14 @@ public class CloudConfigurationImpl extends CloudConfiguration {
@Override
public String getDisplayName() {
- return name + " (" + getDeviceConfigurationCount() + ")";
+ int deviceConfigurationCount = getDeviceConfigurationCount();
+ if (kind != SINGLE_DEVICE) {
+ return name + " (" + deviceConfigurationCount + ")";
+ }
+ if (deviceConfigurationCount > 0) { // Should be exactly 1
+ return name;
+ }
+ return name + " (not configured)";
}
public void setName(String name) {
diff --git a/src/com/google/gct/testing/TwoPanelTree.java b/src/com/google/gct/testing/TwoPanelTree.java
index e6cae1f..b7f7e5f 100644
--- a/src/com/google/gct/testing/TwoPanelTree.java
+++ b/src/com/google/gct/testing/TwoPanelTree.java
@@ -21,11 +21,15 @@ import com.google.gct.testing.dimension.CloudTestingType;
import com.google.gct.testing.dimension.CloudTestingTypeGroup;
import com.intellij.openapi.ui.Splitter;
import com.intellij.ui.CheckboxTree;
+import com.intellij.ui.CheckboxTreeBase.CheckPolicy;
+import com.intellij.ui.CheckboxTreeBase.NodeState;
import com.intellij.ui.CheckedTreeNode;
+import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBList;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -33,6 +37,8 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@@ -43,6 +49,7 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
+import static com.android.tools.idea.run.CloudConfiguration.Kind.SINGLE_DEVICE;
import static javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION;
@@ -74,7 +81,7 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
// Listeners
List<TwoPanelTreeSelectionListener> listeners = new LinkedList<TwoPanelTreeSelectionListener>();
- private JLabel myConfigurationCountLabel;
+ private JLabel myConfigurationCountLabel = new JLabel();
public TwoPanelTree(CloudConfigurationImpl configuration) {
this.configuration = configuration;
@@ -100,10 +107,12 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
public void init() {
myPanel.add(topPanel, BorderLayout.NORTH);
- populateTopPanel();
- bottomPanel.setBackground(UIUtil.getListBackground());
- myPanel.add(bottomPanel, BorderLayout.SOUTH);
- populateBottomPanel();
+ if (configuration.getKind() != SINGLE_DEVICE) {
+ populateTopPanel();
+ bottomPanel.setBackground(UIUtil.getListBackground());
+ myPanel.add(bottomPanel, BorderLayout.SOUTH);
+ populateBottomPanel();
+ }
mySplitter.setFirstComponent(leftPanel);
JScrollPane scrollPane = new JScrollPane(rightPanel);
@@ -134,8 +143,6 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
private void populateBottomPanel() {
bottomPanel.setBorder(BorderFactory.createLineBorder(UIUtil.getBorderColor(), 1));
- // TODO: Update number of configurations when appropriate
- myConfigurationCountLabel = new JLabel();
updateConfigurationCountLabel();
bottomPanel.add(myConfigurationCountLabel);
}
@@ -196,11 +203,6 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
}
}
}));
- //topPanel.add(makeTextButton("Hide unselected", new MouseAdapter() {
- // public void mouseClicked(final MouseEvent e) {
- // System.out.println("Clicked " + "Hide unselected");
- // }
- //}));
}
private void updateCurrentCheckboxTree(Function<CheckedTreeNode, Void> updateFunction) {
@@ -225,8 +227,6 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
private void updateUI(CheckboxTree checkboxTree) {
checkboxTree.updateUI();
BasicTreeUI ui = (BasicTreeUI) checkboxTree.getUI();
- //ui.setRightChildIndent(0);
- //ui.setLeftChildIndent(0);
}
private JLabel makeTextButton(final String text, MouseAdapter mouseAdapter) {
@@ -241,12 +241,15 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
public void addDimension(CloudConfigurationDimension dimension) {
- // add this dimension as a list item
+ // Add this dimension as a list item.
listModel.addElement(dimension);
- // create a new tree with root node for this dimension
- CheckboxTree tree = new CheckboxTree();
CheckedTreeNode rootNode = new CheckedTreeNode(dimension); // Not really necessary since parent not visible
+ CheckPolicy radioButtonsCheckPolicy = new CheckPolicy(false, false, false, false);
+ // Create a new tree with root node for this dimension.
+ CheckboxTree tree = configuration.getKind() == SINGLE_DEVICE
+ ? new CheckboxTree(new CheckboxTree.CheckboxTreeCellRenderer(){}, rootNode, radioButtonsCheckPolicy)
+ : new CheckboxTree();
DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
tree.setModel(treeModel);
@@ -272,48 +275,10 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
}
}
- // record the tree
+ // Record the tree.
treeMap.put(dimension, tree);
- tree.setCellRenderer(new CheckboxTree.CheckboxTreeCellRenderer() {
- @Override
- public void customizeRenderer(final JTree tree,
- Object value,
- final boolean selected,
- final boolean expanded,
- final boolean leaf,
- final int row,
- final boolean hasFocus) {
-
- if (value instanceof DefaultMutableTreeNode) {
- Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
- if (userObject instanceof CloudTestingType) {
- CloudTestingType cloudTestingType = (CloudTestingType)userObject;
- getTextRenderer().append(cloudTestingType.getConfigurationDialogDisplayName());
- updateTreeState(tree, (CheckedTreeNode)value, cloudTestingType);
- } else if (userObject instanceof CloudTestingTypeGroup) {
- CloudTestingTypeGroup group = (CloudTestingTypeGroup)userObject;
- getTextRenderer().append(group.getName());
- CloudTestingType type = (CloudTestingType) ((CheckedTreeNode) ((DefaultMutableTreeNode)value).getChildAt(0)).getUserObject();
- updateTreeState(tree, (CheckedTreeNode)value, type);
- }
- }
- }
-
- private void updateTreeState(JTree tree, CheckedTreeNode node, CloudTestingType cloudTestingType) {
- if (node.isEnabled()) {
- //getTextRenderer().setForeground(Color.BLACK);
- } else {
- //getTextRenderer().setForeground(Color.LIGHT_GRAY);
- CloudConfigurationDimension cloudConfigurationDimension = (CloudConfigurationDimension)((CheckedTreeNode) tree.getModel().getRoot()).getUserObject();
- boolean isChecked = cloudConfigurationDimension.getEnabledTypes().contains(cloudTestingType);
- node.setChecked(isChecked);
- for (int childIndex = 0; childIndex < node.getChildCount(); childIndex++) {
- ((CheckedTreeNode) node.getChildAt(childIndex)).setChecked(isChecked);
- }
- }
- }
- });
+ tree.setCellRenderer(configuration.getKind() == SINGLE_DEVICE ? new RadioButtonRenderer() : new CheckBoxRenderer());
treeModel.reload();
@@ -374,13 +339,24 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
}
private void updateState() {
- CloudConfigurationDimension currentDimension = getSelectedDimension();
- CheckboxTree currentTree = treeMap.get(currentDimension);
+ CheckboxTree currentTree = treeMap.get(getSelectedDimension());
if (currentTree == null || currentTree.getSelectionPath() == null) {
return;
}
+ if (configuration.getKind() == SINGLE_DEVICE) {
+ updateRadioButtonTreeState(currentTree);
+ } else {
+ updateCheckBoxTreeState(currentTree);
+ }
+
+ updateConfigurationCountLabel();
+ list.updateUI();
+ }
+
+ private void updateCheckBoxTreeState(CheckboxTree currentTree) {
+ CloudConfigurationDimension currentDimension = getSelectedDimension();
CheckedTreeNode selectedNode = (CheckedTreeNode) currentTree.getSelectionPath().getLastPathComponent();
Object userObject = selectedNode.getUserObject();
if (userObject instanceof CloudTestingType) {
@@ -405,12 +381,207 @@ public class TwoPanelTree extends MouseAdapter implements ListSelectionListener,
listener.groupSelectionChanged(new TwoPanelTreeTypeGroupSelectionEvent(currentDimension, clickedGroup));
}
}
+ }
- updateConfigurationCountLabel();
- list.updateUI();
+ private void updateRadioButtonTreeState(CheckboxTree currentTree) {
+ CloudConfigurationDimension currentDimension = getSelectedDimension();
+ CheckedTreeNode selectedNode = (CheckedTreeNode) currentTree.getSelectionPath().getLastPathComponent();
+ Object userObject = selectedNode.getUserObject();
+ if (userObject instanceof CloudTestingType) {
+ CloudTestingType clickedType = (CloudTestingType)userObject;
+ if (selectedNode.isEnabled() && (selectedNode.isChecked() || !isAnythingChecked(currentTree))) {
+ uncheckAll(currentTree);
+ selectedNode.setChecked(true);
+ currentDimension.disableAll();
+ currentDimension.enable(clickedType);
+ currentDimension.dimensionChanged();
+ }
+ for (TwoPanelTreeSelectionListener listener : listeners) {
+ listener.typeSelectionChanged(new TwoPanelTreeTypeSelectionEvent(currentDimension, clickedType));
+ }
+ } else {
+ CloudTestingTypeGroup clickedGroup = (CloudTestingTypeGroup) userObject;
+ for (TwoPanelTreeSelectionListener listener : listeners) {
+ listener.groupSelectionChanged(new TwoPanelTreeTypeGroupSelectionEvent(currentDimension, clickedGroup));
+ }
+ }
+ }
+
+ private void uncheckAll(CheckboxTree currentTree) {
+ TreeNode root = (TreeNode)currentTree.getModel().getRoot();
+ for (int i = 0; i < root.getChildCount(); i++) {
+ CheckedTreeNode firstLevelChild = (CheckedTreeNode)root.getChildAt(i);
+ firstLevelChild.setChecked(false);
+ if (!firstLevelChild.isLeaf()) {
+ for (int j = 0; j < firstLevelChild.getChildCount(); j++) {
+ ((CheckedTreeNode)firstLevelChild.getChildAt(j)).setChecked(false);
+ }
+ }
+ }
+ }
+
+ private boolean isAnythingChecked(CheckboxTree currentTree) {
+ TreeNode root = (TreeNode)currentTree.getModel().getRoot();
+ for (int i = 0; i < root.getChildCount(); i++) {
+ CheckedTreeNode firstLevelChild = (CheckedTreeNode)root.getChildAt(i);
+ if (firstLevelChild.isChecked()) {
+ return true;
+ }
+ if (!firstLevelChild.isLeaf()) {
+ for (int j = 0; j < firstLevelChild.getChildCount(); j++) {
+ if (((CheckedTreeNode)firstLevelChild.getChildAt(j)).isChecked()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
- class EnhancedCellRenderer implements ListCellRenderer {
+ private static class CheckBoxRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
+ @Override
+ public void customizeRenderer(final JTree tree, Object value, final boolean selected, final boolean expanded, final boolean leaf,
+ final int row, final boolean hasFocus) {
+
+ if (value instanceof DefaultMutableTreeNode) {
+ Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
+ if (userObject instanceof CloudTestingType) {
+ CloudTestingType cloudTestingType = (CloudTestingType)userObject;
+ getTextRenderer().append(cloudTestingType.getConfigurationDialogDisplayName());
+ updateTreeState(tree, (CheckedTreeNode)value, cloudTestingType);
+ } else if (userObject instanceof CloudTestingTypeGroup) {
+ CloudTestingTypeGroup group = (CloudTestingTypeGroup)userObject;
+ getTextRenderer().append(group.getName());
+ CloudTestingType type = (CloudTestingType) ((CheckedTreeNode) ((DefaultMutableTreeNode)value).getChildAt(0)).getUserObject();
+ updateTreeState(tree, (CheckedTreeNode)value, type);
+ }
+ }
+ }
+
+ private void updateTreeState(JTree tree, CheckedTreeNode node, CloudTestingType cloudTestingType) {
+ if (node.isEnabled()) {
+ //getTextRenderer().setForeground(Color.BLACK);
+ } else {
+ //getTextRenderer().setForeground(Color.LIGHT_GRAY);
+ CloudConfigurationDimension dimension = (CloudConfigurationDimension)((CheckedTreeNode) tree.getModel().getRoot()).getUserObject();
+ boolean isChecked = dimension.getEnabledTypes().contains(cloudTestingType);
+ node.setChecked(isChecked);
+ for (int childIndex = 0; childIndex < node.getChildCount(); childIndex++) {
+ ((CheckedTreeNode) node.getChildAt(childIndex)).setChecked(isChecked);
+ }
+ }
+ }
+ }
+
+ private static class RadioButtonRenderer extends JPanel implements TreeCellRenderer {
+ private final ColoredTreeCellRenderer myTextRenderer;
+ public final JRadioButton myRadioButton;
+ private final boolean myUsePartialStatusForParentNodes;
+
+ public RadioButtonRenderer() {
+ this(true);
+ }
+
+ public RadioButtonRenderer(boolean opaque) {
+ this(opaque, true);
+ }
+
+ public RadioButtonRenderer(boolean opaque, final boolean usePartialStatusForParentNodes) {
+ super(new BorderLayout());
+ myUsePartialStatusForParentNodes = usePartialStatusForParentNodes;
+ myRadioButton = new JRadioButton();
+ myTextRenderer = new ColoredTreeCellRenderer() {
+ @Override
+ public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
+ boolean hasFocus) {}
+ };
+ myTextRenderer.setOpaque(opaque);
+ add(myRadioButton, BorderLayout.WEST);
+ add(myTextRenderer, BorderLayout.CENTER);
+ }
+
+ public void updateTreeState(JTree tree, CheckedTreeNode node, CloudTestingType cloudTestingType) {
+ if (node.isEnabled()) {
+ //getTextRenderer().setForeground(Color.BLACK);
+ } else {
+ //getTextRenderer().setForeground(Color.LIGHT_GRAY);
+ CloudConfigurationDimension dimension = (CloudConfigurationDimension)((CheckedTreeNode) tree.getModel().getRoot()).getUserObject();
+ boolean isChecked = dimension.getEnabledTypes().contains(cloudTestingType);
+ node.setChecked(isChecked);
+ }
+ }
+
+ @Override
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
+ boolean hasFocus) {
+
+ invalidate();
+ if (value instanceof CheckedTreeNode) {
+ CheckedTreeNode node = (CheckedTreeNode)value;
+
+ NodeState state = getNodeStatus(node);
+ myRadioButton.setVisible(leaf);
+
+ myRadioButton.setSelected(state != NodeState.CLEAR);
+ myRadioButton.setEnabled(node.isEnabled() && state != NodeState.PARTIAL);
+ myRadioButton.setOpaque(false);
+ myRadioButton.setBackground(null);
+ setBackground(null);
+ } else {
+ myRadioButton.setVisible(false);
+ }
+
+ myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
+
+ if (UIUtil.isUnderGTKLookAndFeel()) {
+ final Color background = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground();
+ UIUtil.changeBackGround(this, background);
+ }
+ else if (UIUtil.isUnderNimbusLookAndFeel()) {
+ UIUtil.changeBackGround(this, UIUtil.TRANSPARENT_COLOR);
+ }
+
+ revalidate();
+
+ if (value instanceof DefaultMutableTreeNode) {
+ Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
+ if (userObject instanceof CloudTestingType) {
+ CloudTestingType googleCloudTestingType = (CloudTestingType)userObject;
+ myTextRenderer.append(googleCloudTestingType.getConfigurationDialogDisplayName());
+ updateTreeState(tree, (CheckedTreeNode)value, googleCloudTestingType);
+ } else if (userObject instanceof CloudTestingTypeGroup) {
+ CloudTestingTypeGroup group = (CloudTestingTypeGroup)userObject;
+ myTextRenderer.append(group.getName());
+ CloudTestingType type = (CloudTestingType)((CheckedTreeNode)((DefaultMutableTreeNode)value).getChildAt(0)).getUserObject();
+ updateTreeState(tree, (CheckedTreeNode)value, type);
+ }
+ }
+ return this;
+ }
+
+ private NodeState getNodeStatus(final CheckedTreeNode node) {
+ final boolean checked = node.isChecked();
+ if (node.getChildCount() == 0 || !myUsePartialStatusForParentNodes) return checked ? NodeState.FULL : NodeState.CLEAR;
+
+ NodeState 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;
+ if (result == null) {
+ result = childStatus;
+ } else if (result != childStatus) {
+ return NodeState.PARTIAL;
+ }
+ }
+ return result == null ? NodeState.CLEAR : result;
+ }
+ }
+
+
+ private static class EnhancedCellRenderer implements ListCellRenderer {
protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
public Component getListCellRendererComponent(JList list, Object value, int index,