You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by se...@apache.org on 2012/12/06 02:42:22 UTC
svn commit: r1417726 - in /jmeter/trunk:
src/core/org/apache/jmeter/gui/util/TristateCheckBox.java
src/core/org/apache/jmeter/gui/util/TristateState.java
test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java
xdocs/changes.xml
Author: sebb
Date: Thu Dec 6 01:42:20 2012
New Revision: 1417726
URL: http://svn.apache.org/viewvc?rev=1417726&view=rev
Log:
Add tristate checkbox implementation
Bugzilla Id: 54251
Added:
jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java (with props)
jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java (with props)
jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java (with props)
Modified:
jmeter/trunk/xdocs/changes.xml
Added: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java?rev=1417726&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java Thu Dec 6 01:42:20 2012
@@ -0,0 +1,322 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.gui.util;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.Serializable;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.ButtonModel;
+import javax.swing.Icon;
+import javax.swing.JCheckBox;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.ActionMapUIResource;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+import sun.swing.plaf.synth.SynthUI;
+
+// derived from: http://www.javaspecialists.eu/archive/Issue145.html
+
+public final class TristateCheckBox extends JCheckBox {
+ private static final long serialVersionUID = 1L;
+ // Listener on model changes to maintain correct focusability
+ private final ChangeListener enableListener = new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ TristateCheckBox.this.setFocusable(
+ getModel().isEnabled());
+ }
+ };
+
+ public TristateCheckBox(String text) {
+ this(text, null, TristateState.DESELECTED);
+ }
+
+ public TristateCheckBox(String text, Icon icon,
+ TristateState initial) {
+ super(text, icon);
+
+ //Set default single model
+ setModel(new TristateButtonModel(initial, this));
+
+ // override action behaviour
+ super.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ TristateCheckBox.this.iterateState();
+ }
+ });
+ ActionMap actions = new ActionMapUIResource();
+ actions.put("pressed", new AbstractAction() {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ TristateCheckBox.this.iterateState();
+ }
+ });
+ actions.put("released", null);
+ SwingUtilities.replaceUIActionMap(this, actions);
+ }
+
+ // Next two methods implement new API by delegation to model
+ public void setIndeterminate() {
+ getTristateModel().setIndeterminate();
+ }
+
+ public boolean isIndeterminate() {
+ return getTristateModel().isIndeterminate();
+ }
+
+ public TristateState getState() {
+ return getTristateModel().getState();
+ }
+
+ //Overrides superclass method
+ @Override
+ public void setModel(ButtonModel newModel) {
+ super.setModel(newModel);
+ //Listen for enable changes
+ if (model instanceof TristateButtonModel)
+ model.addChangeListener(enableListener);
+ }
+
+ //Empty override of superclass method
+ @Override
+ public synchronized void addMouseListener(MouseListener l) {
+ }
+
+ // Mostly delegates to model
+ private void iterateState() {
+ //Maybe do nothing at all?
+ if (!getModel().isEnabled()) return;
+
+ grabFocus();
+
+ // Iterate state
+ getTristateModel().iterateState();
+
+ // Fire ActionEvent
+ int modifiers = 0;
+ AWTEvent currentEvent = EventQueue.getCurrentEvent();
+ if (currentEvent instanceof InputEvent) {
+ modifiers = ((InputEvent) currentEvent).getModifiers();
+ } else if (currentEvent instanceof ActionEvent) {
+ modifiers = ((ActionEvent) currentEvent).getModifiers();
+ }
+ fireActionPerformed(new ActionEvent(this,
+ ActionEvent.ACTION_PERFORMED, getText(),
+ System.currentTimeMillis(), modifiers));
+ }
+
+ //Convenience cast
+ public TristateButtonModel getTristateModel() {
+ return (TristateButtonModel) super.getModel();
+ }
+
+ private static class TristateButtonModel extends ToggleButtonModel {
+
+ private static final long serialVersionUID = 1L;
+ private TristateState state = TristateState.DESELECTED;
+ private final TristateCheckBox tristateCheckBox;
+ private final Icon icon;
+
+ public TristateButtonModel(TristateState initial,
+ TristateCheckBox tristateCheckBox) {
+ setState(TristateState.DESELECTED);
+ this.tristateCheckBox = tristateCheckBox;
+ icon = new TristateCheckBoxIcon(tristateCheckBox);
+ }
+
+ public void setIndeterminate() {
+ setState(TristateState.INDETERMINATE);
+ }
+
+ public boolean isIndeterminate() {
+ return state == TristateState.INDETERMINATE;
+ }
+
+ // Overrides of superclass methods
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ // Restore state display
+ displayState();
+ }
+
+ @Override
+ public void setSelected(boolean selected) {
+ setState(selected ?
+ TristateState.SELECTED : TristateState.DESELECTED);
+ }
+
+ // Empty overrides of superclass methods
+ @Override
+ public void setArmed(boolean b) {
+ }
+
+ @Override
+ public void setPressed(boolean b) {
+ }
+
+ void iterateState() {
+ setState(state.next());
+ }
+
+ private void setState(TristateState state) {
+ //Set internal state
+ this.state = state;
+ displayState();
+ if (state == TristateState.INDETERMINATE && isEnabled()) {
+ // force the events to fire
+
+ // Send ChangeEvent
+ fireStateChanged();
+
+ // Send ItemEvent
+ int indeterminate = 3;
+ fireItemStateChanged(new ItemEvent(
+ this, ItemEvent.ITEM_STATE_CHANGED, this,
+ indeterminate));
+ }
+ }
+
+ private void displayState() {
+ super.setSelected(state != TristateState.DESELECTED);
+ // original used:
+// super.setArmed(state == TristateState.INDETERMINATE);
+ if (state == TristateState.INDETERMINATE) {
+ tristateCheckBox.setIcon(icon); // Needed for all but Nimbus
+ tristateCheckBox.setSelectedIcon(icon); // Nimbus works - after a fashion - with this
+ } else { // reset
+ if (tristateCheckBox!= null){
+ tristateCheckBox.setIcon(null);
+ tristateCheckBox.setSelectedIcon(null);
+ }
+ }
+ super.setPressed(state == TristateState.INDETERMINATE);
+
+ }
+
+ public TristateState getState() {
+ return state;
+ }
+ }
+
+ // derived from: http://www.coderanch.com/t/342563/GUI/java/TriState-CheckBox
+
+ private static class TristateCheckBoxIcon implements Icon, UIResource, Serializable {
+
+ private static final long serialVersionUID = 290L;
+
+ private final TristateCheckBox tristateCheckBox;
+
+ public TristateCheckBoxIcon(TristateCheckBox tristateCheckBox) {
+ this.tristateCheckBox = tristateCheckBox;
+ System.out.println(tristateCheckBox.getUI());
+ }
+
+ @Override
+ public void paintIcon(Component c, Graphics g, int x, int y) {
+ JCheckBox cb = (JCheckBox) c;
+ ButtonModel model = cb.getModel();
+ int controlSize = getControlSize();
+
+ // TODO fix up for Nimbus LAF
+ if (model.isEnabled()) {
+ if (model.isPressed() && model.isArmed()) {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(x, y, controlSize - 1, controlSize - 1);
+ drawPressed3DBorder(g, x, y, controlSize, controlSize);
+ } else {
+ drawFlush3DBorder(g, x, y, controlSize, controlSize);
+ }
+ g.setColor(MetalLookAndFeel.getControlInfo());
+ } else {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(x, y, controlSize - 1, controlSize - 1);
+ }
+
+ drawCross(c, g, x, y);
+
+ }// paintIcon
+
+ private void drawCross(Component c, Graphics g, int x, int y) {
+ int controlSize = getControlSize();
+ g.drawLine(x + (controlSize - 4), y + 2, x + 3, y
+ + (controlSize - 5));
+ g.drawLine(x + (controlSize - 4), y + 3, x + 3, y
+ + (controlSize - 4));
+ g.drawLine(x + 3, y + 2, x + (controlSize - 4), y
+ + (controlSize - 5));
+ g.drawLine(x + 3, y + 3, x + (controlSize - 4), y
+ + (controlSize - 4));
+ }
+
+ private void drawFlush3DBorder(Graphics g, int x, int y, int w, int h) {
+ g.translate(x, y);
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawRect(0, 0, w - 2, h - 2);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawRect(1, 1, w - 2, h - 2);
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(0, h - 1, 1, h - 2);
+ g.drawLine(w - 1, 0, w - 2, 1);
+ g.translate(-x, -y);
+ }
+
+ private void drawPressed3DBorder(Graphics g, int x, int y, int w, int h) {
+ g.translate(x, y);
+ drawFlush3DBorder(g, 0, 0, w, h);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(1, 1, 1, h - 2);
+ g.drawLine(1, 1, w - 2, 1);
+ g.translate(-x, -y);
+ }
+
+ @Override
+ public int getIconWidth() {
+ return getControlSize();
+ }
+
+ @Override
+ public int getIconHeight() {
+ return getControlSize();
+ }
+
+ private int getControlSize() {
+ if (tristateCheckBox.getUI() instanceof SynthUI) {
+ return 18; // see http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html
+ }
+ return 13;
+ }
+ }
+}
\ No newline at end of file
Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateCheckBox.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java?rev=1417726&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java Thu Dec 6 01:42:20 2012
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.gui.util;
+
+//derived from: http://www.javaspecialists.eu/archive/Issue145.html
+
+public enum TristateState {
+ SELECTED {
+ @Override
+ public TristateState next() {
+ return INDETERMINATE;
+ }
+ },
+ INDETERMINATE {
+ @Override
+ public TristateState next() {
+ return DESELECTED;
+ }
+ },
+ DESELECTED {
+ @Override
+ public TristateState next() {
+ return SELECTED;
+ }
+ };
+
+ public abstract TristateState next();
+}
\ No newline at end of file
Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/util/TristateState.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java?rev=1417726&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java (added)
+++ jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java Thu Dec 6 01:42:20 2012
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.gui.util;
+
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+
+//derived from: http://www.javaspecialists.eu/archive/Issue145.html
+
+public class TristateCheckBoxTest {
+ public static void main(String args[]) throws Exception {
+// UIManager.get
+ JFrame frame = new JFrame("TristateCheckBoxTest");
+ frame.setLayout(new GridLayout(0, 1, 15, 15));
+ UIManager.LookAndFeelInfo[] lfs =
+ UIManager.getInstalledLookAndFeels();
+ for (UIManager.LookAndFeelInfo lf : lfs) {
+ System.out.println("Look&Feel " + lf.getName());
+ UIManager.setLookAndFeel(lf.getClassName());
+ frame.add(makePanel(lf.getName()));
+ }
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ private static JPanel makePanel(String name) {
+ final TristateCheckBox tristateBox = new TristateCheckBox("Tristate checkbox");
+ tristateBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ System.out.println(e);
+ switch(tristateBox.getState()) {
+ case SELECTED:
+ System.out.println("Selected"); break;
+ case DESELECTED:
+ System.out.println("Not Selected"); break;
+ case INDETERMINATE:
+ System.out.println("Tristate Selected"); break;
+ }
+ }
+ });
+ tristateBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e);
+ switch(tristateBox.getState()) {
+ case SELECTED:
+ System.out.println("Selected"); break;
+ case DESELECTED:
+ System.out.println("Not Selected"); break;
+ case INDETERMINATE:
+ System.out.println("Tristate Selected"); break;
+ }
+ }
+ });
+ final JCheckBox normalBox = new JCheckBox("Normal checkbox");
+ normalBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e);
+ }
+ });
+
+ final JCheckBox enabledBox = new JCheckBox("Enable", true);
+ enabledBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ tristateBox.setEnabled(enabledBox.isSelected());
+ normalBox.setEnabled(enabledBox.isSelected());
+ }
+ });
+
+ JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
+ panel.add(new JLabel(name));
+ panel.add(tristateBox);
+ panel.add(normalBox);
+ panel.add(enabledBox);
+ return panel;
+ }
+}
\ No newline at end of file
Propchange: jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/test/src/org/apache/jmeter/gui/util/TristateCheckBoxTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1417726&r1=1417725&r2=1417726&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Thu Dec 6 01:42:20 2012
@@ -213,6 +213,7 @@ to the elements View Results Tree, Asser
<li><bugzilla>54204</bugzilla> - Result Status Action Handler : Add start next thread loop option</li>
<li><bugzilla>54232</bugzilla> - Search Feature : Add a button to search and expand results</li>
<li><bugzilla>54155</bugzilla> - ModuleController : Add a shortcut button to unfold the tree up to referenced controller and highlight it</li>
+<li><bugzilla>54251</bugzilla> - Add tristate checkbox implementation</li>
</ul>
<h2>Non-functional changes</h2>