You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by vl...@apache.org on 2019/10/05 10:33:04 UTC
[jmeter] branch master updated: Facelift ThreadGroup UI,
improve alignment of Name+Commments fields for all components
This is an automated email from the ASF dual-hosted git repository.
vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git
The following commit(s) were added to refs/heads/master by this push:
new b0448c8 Facelift ThreadGroup UI, improve alignment of Name+Commments fields for all components
b0448c8 is described below
commit b0448c8cb3b70e7c3c58f84af926d0071a091f78
Author: Vladimir Sitnikov <si...@gmail.com>
AuthorDate: Fri Oct 4 10:59:37 2019 +0300
Facelift ThreadGroup UI, improve alignment of Name+Commments fields for all components
---
checksum.xml | 1 +
gradle.properties | 2 +
src/bom/build.gradle.kts | 3 +
.../visualizers/RespTimeGraphVisualizer.java | 2 +-
.../jmeter/visualizers/StatGraphVisualizer.java | 2 +-
src/core/build.gradle.kts | 2 +
.../jmeter/control/gui/LoopControlPanel.java | 22 +++-
.../jmeter/gui/AbstractJMeterGuiComponent.java | 86 +++++++++-----
.../java/org/apache/jmeter/gui/CommentPanel.java | 6 +
.../main/java/org/apache/jmeter/gui/NamePanel.java | 8 ++
.../jmeter/threads/gui/AbstractThreadGroupGui.java | 4 +-
.../apache/jmeter/threads/gui/ThreadGroupGui.java | 131 ++++++---------------
.../java/org/apache/jmeter/util/JMeterUtils.java | 15 +++
.../apache/jmeter/resources/messages.properties | 6 +-
src/licenses/build.gradle.kts | 8 ++
src/licenses/licenses/miglayout/LICENSE | 27 +++++
xdocs/images/screenshots/setup_thread_group.png | Bin 21075 -> 29834 bytes
xdocs/images/screenshots/teardown_thread_group.png | Bin 21499 -> 110310 bytes
.../screenshots/thread_group_distributed.png | Bin 29000 -> 39480 bytes
xdocs/images/screenshots/threadgroup.png | Bin 22022 -> 31339 bytes
xdocs/usermanual/component_reference.xml | 10 +-
21 files changed, 198 insertions(+), 137 deletions(-)
diff --git a/checksum.xml b/checksum.xml
index 65ca9a2..671127f 100644
--- a/checksum.xml
+++ b/checksum.xml
@@ -27,6 +27,7 @@
<trusted-key id='e57428da9e879e7d' group='com.helger' />
<trusted-key id='3684155e9365c30e' group='com.jayway.jsonpath' />
<trusted-key id='a50569c7ca7fa1f0' group='com.jcraft' />
+ <trusted-key id='db45d3a62a183ce2' group='com.miglayout' />
<trusted-key id='aa49c633b4734832' group='com.pinterest' />
<trusted-key id='aa49c633b4734832' group='com.pinterest.ktlint' />
<trusted-key id='1063fe98bcecb758' group='com.puppycrawl.tools' />
diff --git a/gradle.properties b/gradle.properties
index 2107116..20681f7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -32,6 +32,7 @@ velocity.version=1.7
accessors-smart.version=1.2
activemq.version=5.15.8
apache-rat.version=0.13
+apiguardian-api.version=1.1.0
asm.version=7.1
bouncycastle.version=1.60
bsf.version=2.4.0
@@ -83,6 +84,7 @@ junit4.version=4.12
junit5.version=5.5.1
log4j.version=2.12.1
mail.version=1.5.0-b01
+miglayout.version=5.2
mina-core.version=2.0.19
mongo-java-driver.version=2.11.3
neo4j-java-driver.version=1.7.5
diff --git a/src/bom/build.gradle.kts b/src/bom/build.gradle.kts
index cdcec48..96a30cb 100644
--- a/src/bom/build.gradle.kts
+++ b/src/bom/build.gradle.kts
@@ -69,6 +69,8 @@ dependencies {
apiv("com.helger:ph-commons")
apiv("com.helger:ph-css")
apiv("com.jayway.jsonpath:json-path")
+ apiv("com.miglayout:miglayout-core", "miglayout")
+ apiv("com.miglayout:miglayout-swing", "miglayout")
apiv("com.sun.activation:javax.activation", "javax.activation")
apiv("com.thoughtworks.xstream:xstream")
apiv("commons-codec:commons-codec")
@@ -118,6 +120,7 @@ dependencies {
apiv("org.apache.tika:tika-core", "tika")
apiv("org.apache.velocity:velocity")
apiv("org.apache.xmlgraphics:xmlgraphics-commons")
+ apiv("org.apiguardian:apiguardian-api")
apiv("org.bouncycastle:bcmail-jdk15on", "bouncycastle")
apiv("org.bouncycastle:bcpkix-jdk15on", "bouncycastle")
apiv("org.bouncycastle:bcprov-jdk15on", "bouncycastle")
diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphVisualizer.java
index 8e88665..7e620b8 100644
--- a/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphVisualizer.java
+++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphVisualizer.java
@@ -522,7 +522,7 @@ public class RespTimeGraphVisualizer extends AbstractVisualizer implements Actio
log.error(e.getMessage());
}
} else if (eventSource == syncWithName) {
- graphTitle.setText(namePanel.getName());
+ graphTitle.setText(getName());
} else if (eventSource == dynamicGraphSize) {
enableDynamicGraph(dynamicGraphSize.isSelected());
} else if (eventSource == samplerSelection) {
diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/StatGraphVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/StatGraphVisualizer.java
index 2eb61b9..86d0174 100644
--- a/src/components/src/main/java/org/apache/jmeter/visualizers/StatGraphVisualizer.java
+++ b/src/components/src/main/java/org/apache/jmeter/visualizers/StatGraphVisualizer.java
@@ -748,7 +748,7 @@ public class StatGraphVisualizer extends AbstractVisualizer implements Clearable
colorForeGraph = color;
}
} else if (eventSource == syncWithName) {
- graphTitle.setText(namePanel.getName());
+ graphTitle.setText(getName());
} else if (eventSource == dynamicGraphSize) {
// if use dynamic graph size is checked, we disable the dimension fields
if (dynamicGraphSize.isSelected()) {
diff --git a/src/core/build.gradle.kts b/src/core/build.gradle.kts
index 7c4f855..9e578a8 100644
--- a/src/core/build.gradle.kts
+++ b/src/core/build.gradle.kts
@@ -45,6 +45,7 @@ dependencies {
api("org.apache.logging.log4j:log4j-slf4j-impl") {
because("Both log4j and slf4j are included, so it makes sense to just add log4j->slf4j bridge as well")
}
+ api("org.apiguardian:apiguardian-api")
api("oro:oro") {
because("Perl5Matcher org.apache.jmeter.util.JMeterUtils.getMatcher()")
}
@@ -70,6 +71,7 @@ dependencies {
implementation("com.fasterxml.jackson.core:jackson-annotations")
implementation("com.fasterxml.jackson.core:jackson-core")
implementation("com.fasterxml.jackson.core:jackson-databind")
+ implementation("com.miglayout:miglayout-swing")
implementation("org.freemarker:freemarker")
implementation("org.mozilla:rhino")
implementation("org.apache.xmlgraphics:xmlgraphics-commons")
diff --git a/src/core/src/main/java/org/apache/jmeter/control/gui/LoopControlPanel.java b/src/core/src/main/java/org/apache/jmeter/control/gui/LoopControlPanel.java
index 51a3271..082b41c 100644
--- a/src/core/src/main/java/org/apache/jmeter/control/gui/LoopControlPanel.java
+++ b/src/core/src/main/java/org/apache/jmeter/control/gui/LoopControlPanel.java
@@ -33,6 +33,7 @@ import org.apache.jmeter.gui.GUIMenuSortOrder;
import org.apache.jmeter.gui.util.FocusRequester;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
+import org.apiguardian.api.API;
/**
* The user interface for a controller which specifies that its subcomponents
@@ -42,7 +43,7 @@ import org.apache.jmeter.util.JMeterUtils;
*/
@GUIMenuSortOrder(3)
public class LoopControlPanel extends AbstractControllerGui implements ActionListener {
- private static final long serialVersionUID = 240L;
+ private static final long serialVersionUID = 241L;
/**
* A checkbox allowing the user to specify whether or not the controller
@@ -56,6 +57,8 @@ public class LoopControlPanel extends AbstractControllerGui implements ActionLis
*/
private JTextField loops;
+ private JLabel loopsLabel;
+
/**
* Boolean indicating whether or not this component should display its name.
* If true, this is a standalone component. If false, this component is
@@ -92,6 +95,21 @@ public class LoopControlPanel extends AbstractControllerGui implements ActionLis
setState(1);
}
+ @API(status = API.Status.EXPERIMENTAL)
+ public JLabel getLoopsLabel() {
+ return loopsLabel;
+ }
+
+ @API(status = API.Status.EXPERIMENTAL)
+ public JCheckBox getInfinite() {
+ return infinite;
+ }
+
+ @API(status = API.Status.EXPERIMENTAL)
+ public JTextField getLoops() {
+ return loops;
+ }
+
/**
* A newly created component can be initialized with the contents of a Test
* Element object by calling this method. The component is responsible for
@@ -202,7 +220,7 @@ public class LoopControlPanel extends AbstractControllerGui implements ActionLis
JPanel loopPanel = new JPanel(new BorderLayout(5, 0));
// LOOP LABEL
- JLabel loopsLabel = new JLabel(JMeterUtils.getResString("iterator_num")); // $NON-NLS-1$
+ loopsLabel = new JLabel(JMeterUtils.getResString("iterator_num")); // $NON-NLS-1$
loopPanel.add(loopsLabel, BorderLayout.WEST);
JPanel loopSubPanel = new JPanel(new BorderLayout(5, 0));
diff --git a/src/core/src/main/java/org/apache/jmeter/gui/AbstractJMeterGuiComponent.java b/src/core/src/main/java/org/apache/jmeter/gui/AbstractJMeterGuiComponent.java
index dcd4f56..22416cc 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/AbstractJMeterGuiComponent.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/AbstractJMeterGuiComponent.java
@@ -18,6 +18,11 @@
package org.apache.jmeter.gui;
+import static org.apache.jmeter.util.JMeterUtils.labelFor;
+import static org.apiguardian.api.API.Status.DEPRECATED;
+import static org.apiguardian.api.API.Status.EXPERIMENTAL;
+import static org.apiguardian.api.API.Status.INTERNAL;
+
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
@@ -28,6 +33,8 @@ import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
import javax.swing.border.Border;
import org.apache.jmeter.gui.util.VerticalPanel;
@@ -35,9 +42,12 @@ import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.Printable;
+import org.apiguardian.api.API;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import net.miginfocom.swing.MigLayout;
+
/**
* This abstract class takes care of the most basic functions necessary to
* create a viable JMeter GUI component. It extends JPanel and implements
@@ -63,11 +73,16 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
/** Flag indicating whether or not this component is enabled. */
private boolean enabled = true;
- /** A GUI panel containing the name of this component. */
+ /**
+ * A GUI panel containing the name of this component.
+ * @deprecated use {@link #getName()} or {@link AbstractJMeterGuiComponent#createTitleLabel()} for better alignment of the fields
+ **/
+ @API(status = INTERNAL, since = "5.2.0")
+ @Deprecated
+ @SuppressWarnings("DeprecatedIsStillUsed")
protected NamePanel namePanel;
- // used by AbstractReportGui
- private final CommentPanel commentPanel;
+ private final JTextArea commentField = new JTextArea();
/**
* When constructing a new component, this takes care of basic tasks like
@@ -76,8 +91,7 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
*/
public AbstractJMeterGuiComponent() {
namePanel = new NamePanel();
- commentPanel=new CommentPanel();
- initGui();
+ init();
}
/**
@@ -97,7 +111,7 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
* The comment for the property
*/
public void setComment(String comment) {
- commentPanel.setText(comment);
+ commentField.setText(comment);
}
/**
@@ -125,10 +139,7 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
*/
@Override
public String getName() {
- if (getNamePanel() != null) {
- return getNamePanel().getName();
- }
- return ""; // $NON-NLS-1$
+ return namePanel.getName(); // $NON-NLS-1$
}
/**
@@ -138,10 +149,7 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
* @return The comment for the property
*/
public String getComment() {
- if (getCommentPanel() != null) {
- return getCommentPanel().getText();
- }
- return ""; // $NON-NLS-1$
+ return commentField.getText();
}
/**
@@ -151,14 +159,14 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
* {@link #makeTitlePanel()} instead of directly calling this method.
*
* @return a NamePanel containing the name of this component
+ * @deprecated use {@link #getName()} or {@link AbstractJMeterGuiComponent#createTitleLabel()} for better alignment of the fields
*/
+ @API(status = DEPRECATED, since = "5.2.0")
+ @Deprecated
protected NamePanel getNamePanel() {
return namePanel;
}
- private CommentPanel getCommentPanel(){
- return commentPanel;
- }
/**
* Provides a label containing the title for the component. Subclasses
* typically place this label at the top of their GUI. The title is set to
@@ -194,7 +202,7 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
public void configure(TestElement element) {
setName(element.getName());
enabled = element.isEnabled();
- getCommentPanel().setText(element.getComment());
+ commentField.setText(element.getComment());
}
/**
@@ -209,10 +217,17 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
enabled = true;
}
- // helper method - also used by constructor
private void initGui() {
setName(getStaticLabel());
- commentPanel.clearGui();
+ commentField.setText("");
+ }
+
+ private void init() {
+ initGui();
+ // JTextArea does not have border by default (see https://bugs.openjdk.java.net/browse/JDK-4139076)
+ // However we want it to look like a text field. So we borrow a border from there
+ Border border = new JTextField().getBorder();
+ commentField.setBorder(border);
}
/**
@@ -248,14 +263,29 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
* @return a panel containing the component title and name panel
*/
protected Container makeTitlePanel() {
- VerticalPanel titlePanel = new VerticalPanel();
- titlePanel.add(createTitleLabel());
- VerticalPanel contentPanel = new VerticalPanel();
- contentPanel.setBorder(BorderFactory.createEmptyBorder());
- contentPanel.add(getNamePanel());
- contentPanel.add(getCommentPanel());
- titlePanel.add(contentPanel);
- return titlePanel;
+ JPanel titlePanel = new JPanel(new MigLayout("fillx, wrap 2, insets 0", "[][fill,grow]"));
+ titlePanel.add(createTitleLabel(), "span 2");
+
+ JTextField nameField = namePanel.getNameField();
+ titlePanel.add(labelFor(nameField, "name"));
+ titlePanel.add(nameField);
+
+ titlePanel.add(labelFor(nameField, "testplan_comments"));
+ titlePanel.add(commentField);
+
+ // Note: VerticalPanel has a workaround for Box layout which aligns elements, so we can't
+ // use trivial JPanel.
+ // Extra wrapper is often required to ensure that further additions to the panel would be vertical
+ // For instance AbstractVisualizer adds "browse file" panel
+ // If it calls just ..add(browseFilePanel), then it will go to
+ return wrapTitlePanel(titlePanel);
+ }
+
+ @API(status = EXPERIMENTAL, since = "5.2.0")
+ protected Container wrapTitlePanel(Container titlePanel) {
+ VerticalPanel vp = new VerticalPanel();
+ vp.add(titlePanel);
+ return vp;
}
/**
diff --git a/src/core/src/main/java/org/apache/jmeter/gui/CommentPanel.java b/src/core/src/main/java/org/apache/jmeter/gui/CommentPanel.java
index 160abd1..c69c682 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/CommentPanel.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/CommentPanel.java
@@ -18,6 +18,8 @@
package org.apache.jmeter.gui;
+import static org.apiguardian.api.API.Status.DEPRECATED;
+
import java.awt.BorderLayout;
import javax.swing.JLabel;
@@ -27,10 +29,14 @@ import javax.swing.JTextField;
import javax.swing.border.Border;
import org.apache.jmeter.util.JMeterUtils;
+import org.apiguardian.api.API;
/**
* Generic comment panel for Test Elements
+ * @deprecated {@link AbstractJMeterGuiComponent#createTitleLabel()} for better alignment of the fields
*/
+@API(status = DEPRECATED, since = "5.2.0")
+@Deprecated
public class CommentPanel extends JPanel {
private static final long serialVersionUID = 240L;
diff --git a/src/core/src/main/java/org/apache/jmeter/gui/NamePanel.java b/src/core/src/main/java/org/apache/jmeter/gui/NamePanel.java
index 5fb8ea2..5308d43 100644
--- a/src/core/src/main/java/org/apache/jmeter/gui/NamePanel.java
+++ b/src/core/src/main/java/org/apache/jmeter/gui/NamePanel.java
@@ -18,6 +18,8 @@
package org.apache.jmeter.gui;
+import static org.apiguardian.api.API.Status.INTERNAL;
+
import java.awt.BorderLayout;
import java.util.Collection;
@@ -30,6 +32,7 @@ import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.WorkBench;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
+import org.apiguardian.api.API;
public class NamePanel extends JPanel implements JMeterGUIComponent {
private static final long serialVersionUID = 240L;
@@ -62,6 +65,11 @@ public class NamePanel extends JPanel implements JMeterGUIComponent {
add(nameField, BorderLayout.CENTER);
}
+ @API(status = INTERNAL, since = "5.2.0")
+ public JTextField getNameField() {
+ return nameField;
+ }
+
@Override
public void clearGui() {
setName(getStaticLabel());
diff --git a/src/core/src/main/java/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java b/src/core/src/main/java/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java
index 2dc13b0..2a095c2 100644
--- a/src/core/src/main/java/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java
+++ b/src/core/src/main/java/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java
@@ -41,6 +41,8 @@ import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.threads.AbstractThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
+import net.miginfocom.swing.MigLayout;
+
public abstract class AbstractThreadGroupGui extends AbstractJMeterGuiComponent {
private static final long serialVersionUID = 240L;
@@ -136,7 +138,7 @@ public abstract class AbstractThreadGroupGui extends AbstractJMeterGuiComponent
}
private JPanel createOnErrorPanel() {
- JPanel panel = new JPanel();
+ JPanel panel = new JPanel(new MigLayout());
panel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("sampler_on_error_action"))); // $NON-NLS-1$
diff --git a/src/core/src/main/java/org/apache/jmeter/threads/gui/ThreadGroupGui.java b/src/core/src/main/java/org/apache/jmeter/threads/gui/ThreadGroupGui.java
index 9978565..2098e2c 100644
--- a/src/core/src/main/java/org/apache/jmeter/threads/gui/ThreadGroupGui.java
+++ b/src/core/src/main/java/org/apache/jmeter/threads/gui/ThreadGroupGui.java
@@ -18,30 +18,28 @@
package org.apache.jmeter.threads.gui;
+import static org.apache.jmeter.util.JMeterUtils.labelFor;
+
import java.awt.BorderLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.BorderFactory;
-import javax.swing.ButtonGroup;
-import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
-import javax.swing.JRadioButton;
import javax.swing.JTextField;
-import javax.swing.SwingConstants;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.gui.LoopControlPanel;
-import org.apache.jmeter.gui.util.HorizontalPanel;
-import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.threads.AbstractThreadGroup;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
+import net.miginfocom.swing.MigLayout;
+
public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListener {
private static final long serialVersionUID = 240L;
@@ -51,23 +49,24 @@ public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListen
private static final String RAMP_NAME = "Ramp Up Field";
- private JTextField threadInput;
+ private final JTextField threadInput = new JTextField();
- private JTextField rampInput;
+ private final JTextField rampInput = new JTextField();
private final boolean showDelayedStart;
private JCheckBox delayedStart;
- private JCheckBox scheduler;
-
- private JTextField duration;
+ private final JCheckBox scheduler = new JCheckBox(JMeterUtils.getResString("scheduler"));
- private JTextField delay; // Relative start-up time
+ private final JTextField duration = new JTextField();
+ private final JLabel durationLabel = labelFor(duration, "duration");
- private JRadioButton sameUserBox;
+ private final JTextField delay = new JTextField(); // Relative start-up time
+ private final JLabel delayLabel = labelFor(delay, "delay");
- private JRadioButton differentUserBox;
+ private final JCheckBox sameUserBox =
+ new JCheckBox(JMeterUtils.getResString("threadgroup_same_user"));
public ThreadGroupGui() {
this(true);
@@ -141,7 +140,9 @@ public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListen
*/
private void toggleSchedulerFields(boolean enable) {
duration.setEnabled(enable);
+ durationLabel.setEnabled(enable);
delay.setEnabled(enable);
+ delayLabel.setEnabled(enable);
}
private JPanel createControllerPanel() {
@@ -153,34 +154,6 @@ public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListen
}
- /**
- * Create a panel containing the Duration field and corresponding label.
- *
- * @return a GUI panel containing the Duration field
- */
- private JPanel createDurationPanel() {
- JPanel panel = new JPanel(new BorderLayout(5, 0));
- JLabel label = new JLabel(JMeterUtils.getResString("duration")); // $NON-NLS-1$
- panel.add(label, BorderLayout.WEST);
- duration = new JTextField();
- panel.add(duration, BorderLayout.CENTER);
- return panel;
- }
-
- /**
- * Create a panel containing the Duration field and corresponding label.
- *
- * @return a GUI panel containing the Duration field
- */
- private JPanel createDelayPanel() {
- JPanel panel = new JPanel(new BorderLayout(5, 0));
- JLabel label = new JLabel(JMeterUtils.getResString("delay")); // $NON-NLS-1$
- panel.add(label, BorderLayout.WEST);
- delay = new JTextField();
- panel.add(delay, BorderLayout.CENTER);
- return panel;
- }
-
@Override
public String getLabelResource() {
return "threadgroup"; // $NON-NLS-1$
@@ -204,77 +177,43 @@ public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListen
delay.setText(""); // $NON-NLS-1$
duration.setText(""); // $NON-NLS-1$
sameUserBox.setSelected(true);
- differentUserBox.setSelected(false);
}
- private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
+ private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
// THREAD PROPERTIES
- VerticalPanel threadPropsPanel = new VerticalPanel();
+ JPanel threadPropsPanel = new JPanel(new MigLayout("fillx, wrap 2", "[][fill,grow]"));
threadPropsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
JMeterUtils.getResString("thread_properties"))); // $NON-NLS-1$
// NUMBER OF THREADS
- JPanel threadPanel = new JPanel(new BorderLayout(5, 0));
-
- JLabel threadLabel = new JLabel(JMeterUtils.getResString("number_of_threads")); // $NON-NLS-1$
- threadPanel.add(threadLabel, BorderLayout.WEST);
-
- threadInput = new JTextField(5);
+ threadPropsPanel.add(labelFor(threadInput, "number_of_threads")); // $NON-NLS-1$
threadInput.setName(THREAD_NAME);
- threadLabel.setLabelFor(threadInput);
- threadPanel.add(threadInput, BorderLayout.CENTER);
-
- threadPropsPanel.add(threadPanel);
+ threadPropsPanel.add(threadInput);
// RAMP-UP
- JPanel rampPanel = new JPanel(new BorderLayout(5, 0));
- JLabel rampLabel = new JLabel(JMeterUtils.getResString("ramp_up")); // $NON-NLS-1$
- rampPanel.add(rampLabel, BorderLayout.WEST);
-
- rampInput = new JTextField(5);
+ threadPropsPanel.add(labelFor(rampInput, "ramp_up"));
rampInput.setName(RAMP_NAME);
- rampLabel.setLabelFor(rampInput);
- rampPanel.add(rampInput, BorderLayout.CENTER);
-
- threadPropsPanel.add(rampPanel);
+ threadPropsPanel.add(rampInput);
// LOOP COUNT
- threadPropsPanel.add(createControllerPanel());
- threadPropsPanel.add(createUserOptionsPanel());
+ LoopControlPanel loopController = (LoopControlPanel) createControllerPanel();
+ threadPropsPanel.add(loopController.getLoopsLabel(), "split 2");
+ threadPropsPanel.add(loopController.getInfinite(), "gapleft push");
+ threadPropsPanel.add(loopController.getLoops());
+ threadPropsPanel.add(sameUserBox, "span 2");
if (showDelayedStart) {
delayedStart = new JCheckBox(JMeterUtils.getResString("delayed_start")); // $NON-NLS-1$
- threadPropsPanel.add(delayedStart);
+ threadPropsPanel.add(delayedStart, "span 2");
}
- scheduler = new JCheckBox(JMeterUtils.getResString("scheduler")); // $NON-NLS-1$
scheduler.addItemListener(this);
- threadPropsPanel.add(scheduler);
- VerticalPanel mainPanel = new VerticalPanel();
- mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
- JMeterUtils.getResString("scheduler_configuration"))); // $NON-NLS-1$
-
- ImageIcon warningImg = JMeterUtils.getImage("warning.png");
- JLabel warningLabel = new JLabel(JMeterUtils.getResString("thread_group_scheduler_warning"),
- warningImg, SwingConstants.CENTER); // $NON-NLS-1$
- mainPanel.add(warningLabel);
- mainPanel.add(createDurationPanel());
- mainPanel.add(createDelayPanel());
- toggleSchedulerFields(false);
- VerticalPanel intgrationPanel = new VerticalPanel();
- intgrationPanel.add(threadPropsPanel);
- intgrationPanel.add(mainPanel);
- add(intgrationPanel, BorderLayout.CENTER);
+
+ threadPropsPanel.add(scheduler, "span 2");
+
+ threadPropsPanel.add(durationLabel);
+ threadPropsPanel.add(duration);
+ threadPropsPanel.add(delayLabel);
+ threadPropsPanel.add(delay);
+ add(threadPropsPanel, BorderLayout.CENTER);
}
- private JPanel createUserOptionsPanel(){
- ButtonGroup group = new ButtonGroup();
- sameUserBox = new JRadioButton(JMeterUtils.getResString("threadgroup_same_user")); //$NON-NLS-1$
- group.add(sameUserBox);
- sameUserBox.setSelected(true);
- differentUserBox = new JRadioButton(JMeterUtils.getResString("threadgroup_different_user")); //$NON-NLS-1$
- group.add(differentUserBox);
- JPanel optionsPanel = new HorizontalPanel();
- optionsPanel.add(sameUserBox);
- optionsPanel.add(differentUserBox);
- return optionsPanel;
- }
}
diff --git a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
index bdf26fe..d5a657b 100644
--- a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
+++ b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java
@@ -18,6 +18,7 @@
package org.apache.jmeter.util;
+import java.awt.Component;
import java.awt.Dialog;
import java.awt.Font;
import java.awt.Frame;
@@ -49,6 +50,7 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import javax.swing.ImageIcon;
+import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
@@ -915,6 +917,19 @@ public class JMeterUtils implements UnitTestManager {
}
/**
+ * Creates {@link JLabel} that is associated with a given {@link Component} instance.
+ * @param component component for the label
+ * @param resourceId resource ID to be used for retrieving label text
+ * @return JLabel instance
+ */
+ public static JLabel labelFor(Component component, String resourceId) {
+ JLabel label = new JLabel(getResString(resourceId));
+ label.setName(resourceId);
+ label.setLabelFor(component);
+ return label;
+ }
+
+ /**
* Takes an array of strings and a tokenizer character, and returns a string
* of all the strings concatenated with the tokenizer string in between each
* one.
diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
index 1bc0b75..628abbe 100644
--- a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
+++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties
@@ -484,7 +484,7 @@ include_controller=Include Controller
include_equals=Include Equals?
include_path=Include Test Plan
increment=Increment
-infinite=Forever
+infinite=Infinite
initial_context_factory=Initial Context Factory
insert_after=Insert After
insert_before=Insert Before
@@ -872,7 +872,7 @@ proxy_test_plan_creation=Test Plan Creation
proxy_test_plan_filtering=Requests Filtering
proxy_title=HTTP(S) Test Script Recorder
pt_br=Portuguese (Brazilian)
-ramp_up=Ramp-Up Period (in seconds)\:
+ramp_up=Ramp-up period (seconds)\:
random_control_title=Random Controller
random_order_control_title=Random Order Controller
random_multi_result_source_variable=Source Variable(s) (use | as separator)
@@ -1072,7 +1072,7 @@ save_timestamp=Save Time Stamp
save_url=Save URL
save_workbench=Save WorkBench
sbind=Single bind/unbind
-scheduler=Scheduler
+scheduler=Specify Thread lifetime
scheduler_configuration=Scheduler Configuration
schematic_view_errors=Error on generation of schematic view
schematic_view_generation_ok=Successful generation of schematic view in {0}
diff --git a/src/licenses/build.gradle.kts b/src/licenses/build.gradle.kts
index cf21f61..3367032 100644
--- a/src/licenses/build.gradle.kts
+++ b/src/licenses/build.gradle.kts
@@ -90,6 +90,14 @@ val gatherBinaryLicenses by tasks.registering(GatherLicenseTask::class) {
expectedLicense = SpdxLicense.BSD_2_Clause
}
+ for (mig in listOf("com.miglayout:miglayout-core", "com.miglayout:miglayout-swing")) {
+ overrideLicense(mig) {
+ expectedLicense = SimpleLicense("BSD", uri("http://www.debian.org/misc/bsd.license"))
+ effectiveLicense = SpdxLicense.BSD_3_Clause
+ licenseFiles = "miglayout"
+ }
+ }
+
overrideLicense("com.thoughtworks.xstream:xstream:1.4.11") {
expectedLicense = SimpleLicense("BSD style", uri("http://x-stream.github.io/license.html"))
// https://github.com/x-stream/xstream/issues/151
diff --git a/src/licenses/licenses/miglayout/LICENSE b/src/licenses/licenses/miglayout/LICENSE
new file mode 100644
index 0000000..5a0ea8a
--- /dev/null
+++ b/src/licenses/licenses/miglayout/LICENSE
@@ -0,0 +1,27 @@
+ License (BSD):
+ ==============
+
+ Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ Redistributions of source code must retain the above copyright notice, this list
+ of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ Neither the name of the MiG InfoCom AB nor the names of its contributors may be
+ used to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGE.
diff --git a/xdocs/images/screenshots/setup_thread_group.png b/xdocs/images/screenshots/setup_thread_group.png
index 7750c24..85f191a 100644
Binary files a/xdocs/images/screenshots/setup_thread_group.png and b/xdocs/images/screenshots/setup_thread_group.png differ
diff --git a/xdocs/images/screenshots/teardown_thread_group.png b/xdocs/images/screenshots/teardown_thread_group.png
index d75b326..29afa43 100644
Binary files a/xdocs/images/screenshots/teardown_thread_group.png and b/xdocs/images/screenshots/teardown_thread_group.png differ
diff --git a/xdocs/images/screenshots/thread_group_distributed.png b/xdocs/images/screenshots/thread_group_distributed.png
index 5e1ad12..eec161b 100644
Binary files a/xdocs/images/screenshots/thread_group_distributed.png and b/xdocs/images/screenshots/thread_group_distributed.png differ
diff --git a/xdocs/images/screenshots/threadgroup.png b/xdocs/images/screenshots/threadgroup.png
index f0d3d2d..e20f8a7 100644
Binary files a/xdocs/images/screenshots/threadgroup.png and b/xdocs/images/screenshots/threadgroup.png differ
diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml
index 5fa5c32..956b1f3 100644
--- a/xdocs/usermanual/component_reference.xml
+++ b/xdocs/usermanual/component_reference.xml
@@ -6445,16 +6445,16 @@ Behaviour can be modified with some properties by setting in user.properties:
</property>
<property name="Number of Threads" required="Yes">Number of users to simulate.</property>
<property name="Ramp-up Period" required="Yes">How long JMeter should take to get all the threads started. If there are 10 threads and a ramp-up time of 100 seconds, then each thread will begin 10 seconds after the previous thread started, for a total time of 100 seconds to get the test fully up to speed.</property>
- <property name="Loop Count" required="Yes, unless forever is selected">Number of times to perform the test case. Alternatively, "<code>forever</code>" can be selected causing the test to run until manually stopped.</property>
+ <property name="Loop Count" required="Yes, unless Infinite is selected">Number of times to perform the test case. Alternatively, "<code>infinite</code>" can be selected causing the test to run until manually stopped or end of the thread lifetime is reached.</property>
<property name="Delay Thread creation until needed" required="Yes">
If selected, threads are created only when the appropriate proportion of the ramp-up time has elapsed.
This is most appropriate for tests with a ramp-up time that is significantly longer than the time to execute a single thread.
- I.e. where earlier threads finish before later ones start.
+ I.e. where earlier threads finish before later ones start.
<br></br>
If not selected, all threads are created when the test starts (they then pause for the appropriate proportion of the ramp-up time).
This is the original default, and is appropriate for tests where threads are active throughout most of the test.
</property>
- <property name="Scheduler" required="Yes">If selected, enables the scheduler</property>
+ <property name="Specify Thread lifetime" required="Yes">If selected, confines Thread operation time to the given bounds</property>
<property name="Duration (seconds)" required="No">
If the scheduler checkbox is selected, one can choose a relative end time.
JMeter will use this to calculate the End Time.
@@ -7054,7 +7054,7 @@ This is done by default since JMeter 2.13.
</note>
</component>
-<component name="setUp Thread Group" index="§-num;.9.10" width="908" height="364" screenshot="setup_thread_group.png">
+<component name="setUp Thread Group" index="§-num;.9.10" width="1252" height="828" screenshot="setup_thread_group.png">
<description>
<p>
A special type of ThreadGroup that can be utilized to perform Pre-Test Actions. The behavior of these threads
@@ -7064,7 +7064,7 @@ This is done by default since JMeter 2.13.
</description>
</component>
-<component name="tearDown Thread Group" index="§-num;.9.11" width="909" height="366" screenshot="teardown_thread_group.png">
+<component name="tearDown Thread Group" index="§-num;.9.11" width="1248" height="824" screenshot="teardown_thread_group.png">
<description>
<p>
A special type of ThreadGroup that can be utilized to perform Post-Test Actions. The behavior of these threads