Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ plugins.withId("org.jetbrains.kotlin.jvm") {
kotlin {
license()
trimTrailingWhitespace()
ktlint("0.40.0")
ktlint("0.40.0") {
filter {
// TODO: remove exclusion when update ktlint
exclude("**/org/apache/jorphan/locale/PlainValue.kt")
}
}
endWithNewline()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.util.EnumUtils;
import org.apache.jorphan.locale.ResourceKeyed;
import org.apache.jorphan.util.JMeterStopThreadException;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.jorphan.util.StringUtilities;
Expand Down Expand Up @@ -70,20 +70,20 @@
public class CSVDataSet extends ConfigTestElement
implements TestBean, LoopIterationListener, NoConfigMerge {

public enum ShareMode {
public enum ShareMode implements ResourceKeyed {
ALL("shareMode.all"),
GROUP("shareMode.group"),
THREAD("shareMode.thread");

private final String value;
private final String propertyName;

ShareMode(String value) {
this.value = value;
ShareMode(String propertyName) {
this.propertyName = propertyName;
}

@Override
public String toString() {
return value;
public String getResourceKey() {
return propertyName;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class CSVDataSetBeanInfo extends BeanInfoSupport {
for (CSVDataSet.ShareMode value : CSVDataSet.ShareMode.values()) {
@SuppressWarnings("EnumOrdinal")
int index = value.ordinal();
SHARE_TAGS[index] = value.toString();
SHARE_TAGS[index] = value.getResourceKey();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.IdentityKey;
import org.apache.jorphan.locale.ResourceKeyed;
import org.apache.jorphan.util.EnumUtils;
import org.apiguardian.api.API;

Expand Down Expand Up @@ -71,7 +72,7 @@ private static class ThroughputInfo{
/**
* This enum defines the calculation modes used by the ConstantThroughputTimer.
*/
public enum Mode {
public enum Mode implements ResourceKeyed {
ThisThreadOnly("calcMode.1"), // NOSONAR Keep naming for compatibility
AllActiveThreads("calcMode.2"), // NOSONAR Keep naming for compatibility
AllActiveThreadsInCurrentThreadGroup("calcMode.3"), // NOSONAR Keep naming for compatibility
Expand All @@ -89,6 +90,11 @@ public enum Mode {
public String toString() {
return propertyName;
}

@Override
public String getResourceKey() {
return propertyName;
}
}

/**
Expand Down Expand Up @@ -161,15 +167,13 @@ public Mode getMode() {
}

@Deprecated
@SuppressWarnings("EnumOrdinal")
public void setCalcMode(int mode) {
setMode(EnumUtils.values(Mode.class).get(mode));
setMode(EnumUtils.getEnumValues(Mode.class).get(mode));
}

@SuppressWarnings("EnumOrdinal")
@API(status = API.Status.MAINTAINED, since = "6.0.0")
public void setMode(Mode newMode) {
getSchema().getCalcMode().set(this, newMode.toString());
getSchema().getCalcMode().set(this, newMode.getResourceKey());
}

/**
Expand Down Expand Up @@ -296,7 +300,6 @@ public String toString() {
* so the conversion only needs to happen once.
*/
@Override
@SuppressWarnings("EnumOrdinal")
public void setProperty(JMeterProperty property) {
String propertyName = property.getName();
if (propertyName.equals("calcMode")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
*/
public class ConstantThroughputTimerBeanInfo extends BeanInfoSupport {

@SuppressWarnings("EnumOrdinal")
public ConstantThroughputTimerBeanInfo() {
super(ConstantThroughputTimer.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,20 @@ public class TestPlanGui extends AbstractJMeterGuiComponent {
private final JBooleanPropertyEditor functionalMode =
new JBooleanPropertyEditor(
TestPlanSchema.INSTANCE.getFunctionalMode(),
JMeterUtils.getResString("functional_mode"));
"functional_mode",
JMeterUtils::getResString);

private final JBooleanPropertyEditor serializedMode =
new JBooleanPropertyEditor(
TestPlanSchema.INSTANCE.getSerializeThreadgroups(),
JMeterUtils.getResString("testplan.serialized"));
"testplan.serialized",
JMeterUtils::getResString);

private final JBooleanPropertyEditor tearDownOnShutdown =
new JBooleanPropertyEditor(
TestPlanSchema.INSTANCE.getTearDownOnShutdown(),
JMeterUtils.getResString("teardown_on_shutdown"));
"teardown_on_shutdown",
JMeterUtils::getResString);

/** A panel allowing the user to define variables. */
private final ArgumentsPanel argsPanel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ public class TransactionControllerGui extends AbstractControllerGui {
private final JBooleanPropertyEditor generateParentSample =
new JBooleanPropertyEditor(
TransactionControllerSchema.INSTANCE.getGenearteParentSample(),
JMeterUtils.getResString("transaction_controller_parent"));
"transaction_controller_parent",
JMeterUtils::getResString);

/** if selected, add duration of timers to total runtime */
private final JBooleanPropertyEditor includeTimers =
new JBooleanPropertyEditor(
TransactionControllerSchema.INSTANCE.getIncludeTimers(),
JMeterUtils.getResString("transaction_controller_include_timers"));
"transaction_controller_parent",
JMeterUtils::getResString);

/**
* Create a new TransactionControllerGui instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@
import org.apache.jmeter.testelement.TestElementSchema;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.Printable;
import org.apache.jorphan.gui.JEditableTextArea;
import org.apache.jorphan.gui.JFactory;
import org.apache.jorphan.gui.ResetMode;
import org.apache.jorphan.locale.LocalizedString;
import org.apiguardian.api.API;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -81,7 +84,32 @@ public abstract class AbstractJMeterGuiComponent extends JPanel implements JMete
@SuppressWarnings("DeprecatedIsStillUsed")
protected NamePanel namePanel;

private final JTextArea commentField = JFactory.tabMovesFocus(new JTextArea());
private final JEditableTextArea commentEditor = createCommentEditor();
// The legacy commentField reference still points at the inner JTextArea
// so existing setText / getText callers keep working unchanged.
private final JTextArea commentField = JFactory.tabMovesFocus(commentEditor.getInnerTextArea());

private static JEditableTextArea createCommentEditor() {
// Reset for a comment means "clear it" — the default comment is empty.
// Overriding resetToDefault is required: the base implementation is a
// no-op, so without this the popup "Reset" item and the backspace
// gesture would do nothing.
JEditableTextArea editor = new JEditableTextArea(
new JEditableTextArea.Configuration(
new ResetMode.Allow(new LocalizedString("reset", JMeterUtils::getResString)))) {
@Override
protected void resetToDefault() {
setValue(""); // $NON-NLS-1$
}
};
// Comment-field semantics: the gutter lights up while the comment
// is non-empty. There is no concept of "explicit empty" for a
// comment, so we recompute the modified flag from the live text on
// every value change (programmatic loads as well as typing).
editor.addPropertyChangeListener(JEditableTextArea.VALUE_PROPERTY,
evt -> editor.setModified(!editor.getValue().isEmpty()));
return editor;
}

/**
* Stores a collection of property editors, so GuiCompoenent can have default implementations that
Expand Down Expand Up @@ -209,6 +237,9 @@ protected Component createTitleLabel() {
*/
@Override
public void configure(TestElement element) {
// Drive the name field's modified gutter against the static label,
// so a custom name lights the gutter while the default name does not.
namePanel.setDefaultName(getStaticLabel());
setName(element.getName());
enabled = element.isEnabled();
commentField.setText(element.getComment());
Expand All @@ -228,6 +259,7 @@ public void clearGui() {
}

private void initGui() {
namePanel.setDefaultName(getStaticLabel());
setName(getStaticLabel());
commentField.setText("");
}
Expand Down Expand Up @@ -300,12 +332,14 @@ protected Container makeTitlePanel() {

JTextField nameField = namePanel.getNameField();
titlePanel.add(labelFor(nameField, "name"));
titlePanel.add(nameField);
// Add the gutter-aware editor (not the raw nameField) so the
// modified indicator next to the name is shown.
titlePanel.add(namePanel.getNameComponent());

titlePanel.add(labelFor(nameField, "testplan_comments"));
commentField.setWrapStyleWord(true);
commentField.setLineWrap(true);
titlePanel.add(commentField);
titlePanel.add(commentEditor);

// Note: VerticalPanel has a workaround for Box layout which aligns elements, so we can't
// use trivial JPanel.
Expand Down
64 changes: 62 additions & 2 deletions src/core/src/main/java/org/apache/jmeter/gui/NamePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.awt.BorderLayout;
import java.util.Collection;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
Expand All @@ -30,21 +31,50 @@
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.JEditableTextField;
import org.apache.jorphan.gui.ResetMode;
import org.apache.jorphan.locale.LocalizedString;
import org.apiguardian.api.API;

public class NamePanel extends JPanel implements JMeterGUIComponent {
private static final long serialVersionUID = 240L;

private static final String LABEL_RESOURCE = "root"; // $NON-NLS-1$

/**
* The default name to compare against for the "modified" indicator —
* typically the owning component's {@code getStaticLabel()}. When the
* name equals this default, the modified gutter stays dark.
*/
private String defaultName = ""; // $NON-NLS-1$

/** Gutter-aware editor wrapping the name text field. */
private final JEditableTextField nameEditor = new JEditableTextField(
new JEditableTextField.Configuration(
new ResetMode.Allow(new LocalizedString("reset", JMeterUtils::getResString)))) {
@Override
protected void resetToDefault() {
// Qualify with NamePanel.this: an unqualified setName(...) would
// resolve to Component.setName (the Swing component name), not the
// name-field setter we want.
NamePanel.this.setName(defaultName);
}
};

/** A text field containing the name. */
private final JTextField nameField = new JTextField(15);
private final JTextField nameField = nameEditor.getInnerTextField();


/**
* Create a new NamePanel with the default name.
*/
public NamePanel() {
nameField.setColumns(15);
// The gutter lights up whenever the name differs from the default
// (the owning component's static label). This is recomputed on every
// edit and whenever the default changes.
nameEditor.addPropertyChangeListener(
JEditableTextField.VALUE_PROPERTY, evt -> updateModified());
_setName(JMeterUtils.getResString(LABEL_RESOURCE));
init();
}
Expand All @@ -60,14 +90,44 @@ private void init() { // WARNING: called from ctor so must not be overridden (i.
nameLabel.setLabelFor(nameField);

add(nameLabel, BorderLayout.WEST);
add(nameField, BorderLayout.CENTER);
add(nameEditor, BorderLayout.CENTER);
}

@API(status = INTERNAL, since = "5.2.0")
public JTextField getNameField() {
return nameField;
}

/**
* Returns the gutter-aware editor that wraps the name field. Callers that
* lay out the name control themselves (e.g.
* {@code AbstractJMeterGuiComponent.makeTitlePanel}) must add this
* component — not {@link #getNameField()} — so that the modified gutter
* is shown.
*
* @return the editor component to place in a layout
*/
@API(status = INTERNAL, since = "6.0.0")
public JComponent getNameComponent() {
return nameEditor;
}

/**
* Sets the default name used to drive the modified-gutter indicator.
* When the displayed name equals this value the gutter stays dark.
*
* @param defaultName the default name, usually the owning component's static label
*/
@API(status = INTERNAL, since = "6.0.0")
public void setDefaultName(String defaultName) {
this.defaultName = defaultName != null ? defaultName : ""; // $NON-NLS-1$
updateModified();
}

private void updateModified() {
nameEditor.setModified(!getName().equals(defaultName));
}

@Override
public void clearGui() {
setName(getStaticLabel());
Expand Down
Loading
Loading