feat: ModifiedGutter pattern for property editors#6697
Draft
vlsi wants to merge 10 commits into
Draft
Conversation
Introduce the shared building blocks the editable property editors
depend on, ahead of the editors themselves:
* ModifiedGutter — a left-side accent strip that lights up when a
control holds an explicitly stored value, following the gutter
pattern used by IntelliJ IDEA and VS Code. The slot is reserved even
when the strip is transparent, so toggling the state never shifts the
layout, and the colour is muted when the wrapped control is disabled.
* ResetMode — a sealed type that wires a "Reset to default" entry into
an editor's popup menu, enabled only while the gutter is lit.
* ExpressionMode — a sealed type that controls whether an editor may
switch to a free-form ${expression} field.
ModifiedGutterTest covers the layout reservation, the property-change
semantics, and the accessibility description.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire JEditableCheckBox and its JBooleanPropertyEditor binding into the ModifiedGutter pattern and route their captions through a ResourceLocalizer. * The check-box label, the true/false captions, and the "Use Expression" action are localized from JMeter resource bundles. * "Use Expression" is offered as a popup-menu entry (right-click the control); there is no separate on-screen button. * The gutter lights up when the value is explicitly stored on the test element, and a "Reset to default" entry appears in the popup while it is lit. A suppress flag gives explicit-set semantics: any user-driven change marks the editor modified and it stays modified until reset, even when the explicit value equals the default. updateElement is gated on the modified flag, so the gutter, the element, and a save/reload round-trip agree. Tests cover the value getter/setter after the layout refactor, the full gutter state machine, and the updateElement -> updateUi cycle through a real AbstractTestElement, including round-trip preservation of an explicit value that equals the default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a pair of enum-typed editors built on the same gutter and explicit-set foundation as the check-box editor. * JEditableComboBox is the underlying control; JEnumPropertyEditor binds it to an enum-typed test element property and exposes a create(...) factory with sensible defaults plus a Configuration data class for full control. * UnsetMode (Forbid or Allow(unsetValue)) controls whether the user can clear the selection; the unset entry renders in italics and the editor reports null when it is selected. * The combo carries the ModifiedGutter, the "Reset to default" and "Use Expression" popup entries, and the same explicit-set semantics as the check-box editor. EnumEditor, ConstantThroughputTimer, and CSVDataSet move to the schema-based descriptors the new editor expects, and GenericTestBeanCustomizer is tightened to match. Tests drive the updateElement -> updateUi cycle through a real AbstractTestElement, including round-trip preservation of explicit values that equal the default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-as-reset
Adds a third gutter-aware property editor for plain string properties,
together with a backspace gesture that resets the field to its default
when invoked on an already-empty modified field.
Key changes:
* New JEditableTextField in jorphan.gui — a gutter-wrapped JTextField
with an optional Reset action in the popup menu. There is no
separate expression card: free-form text already accepts
${expressions}, so a card switch would just add chrome.
* "Quick reset" via Backspace / Delete: pressing the delete key on
an empty modified field is interpreted as "undo my custom value",
saving a popup trip. The first backspace clears the last character;
the next backspace on the now-empty field resets to default and
clears the gutter.
* New JStringPropertyEditor in core.gui — binds JEditableTextField to
a StringPropertyDescriptor with the same explicit-set semantics as
JBooleanPropertyEditor / JEnumPropertyEditor (suppress flag,
value-change listener, updateUi marks the editor modified iff the
property is stored on the element). Persistence is symmetric:
updateElement removes the property when not modified and stores the
value verbatim when modified, so explicit empty strings now survive
a save/reload round-trip.
* HttpTestSampleGui: embeddedAllowRE / embeddedExcludeRE are now
JStringPropertyEditor instances and provide the first smoke-test of
the gutter pattern on text inputs. The MigLayout column constraints
on the surrounding panel are tightened so that the two URL labels
share column 0 and their fields line up under the wider checkbox
row above (the original switch dragged the labels far from their
fields).
* JEditableTextFieldGutterSemanticsTest covers the full state machine,
the popup menu wiring, and the backspace / delete gestures.
* JStringPropertyEditorTest exercises updateElement → updateUi through
a real AbstractTestElement, including the round-trip case for an
explicit empty string.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a multi-line counterpart to JEditableTextField — same gutter, same Reset action, same backspace-as-reset gesture (triggered only when the entire text area is empty). * New JEditableTextArea in jorphan.gui. The text area is added directly to the gutter without a JScrollPane so that short comment-style fields render naturally; callers that need scrolling can wrap the editor or its inner JTextArea externally. * AbstractJMeterGuiComponent.commentField is now backed by a JEditableTextArea. The legacy `commentField` JTextArea reference is retained and points at the editor's inner text area so existing setText / getText callers keep working unchanged. The editor uses a simple "non-empty == modified" rule rather than the explicit-set semantics from JStringPropertyEditor — comments have no notion of "default vs absent", just "set vs cleared", so the listener recomputes the modified flag from the live text on every value change. * New JEditableTextAreaGutterSemanticsTest covers the same scenarios as the text-field test plus a check that multi-line content is read back verbatim and that backspace inside multi-line text falls through to the standard JTextArea behaviour (16 scenarios). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the name field into the modified-gutter pattern and, while in the same shared base class, fixes the comment field's Reset action. * NamePanel wraps its text field in a gutter-aware JEditableTextField. The gutter lights up when the name differs from the owning component's static label (its default name) and goes dark when it matches. AbstractJMeterGuiComponent feeds the static label through NamePanel.setDefaultName() on configure() / initGui(), and makeTitlePanel() now adds the gutter-aware editor (getNameComponent()) instead of the raw inner JTextField — adding the raw field bypassed the gutter entirely, so it never showed. * NamePanel.resetToDefault qualifies the call as NamePanel.this.setName; an unqualified setName resolved to Component.setName (the Swing component name), so Reset and the backspace gesture did nothing for the name field. * The comment editor now overrides resetToDefault to clear the text. Previously it inherited the no-op base implementation, so Reset and the backspace gesture did nothing for comments either. * NamePanelTest covers the gutter semantics (lit when name differs from default, dark when equal, recomputed on setDefaultName), the Reset menu item, the backspace gesture, and that makeTitlePanel adds the gutter wrapper rather than the raw field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds org.apache.jmeter.testkit.Screenshots, which renders a Swing component into a BufferedImage / PNG without showing a window, by briefly attaching it to a throwaway undecorated frame and painting it on the EDT. This lets tests (and documentation tooling) capture a component's appearance without a human driving the GUI — useful for eyeballing the modified gutter and for auto-generating screenshots for the manual. It needs a display and throws HeadlessException otherwise, so callers should skip when head-less (run under Xvfb on CI if needed). GutterScreenshotDemoTest is a worked example: it renders an unmodified and a modified NamePanel stacked on a white background and writes build/screenshots/name-gutter.png, skipping when head-less. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The lazy-decompression refactor dropped the `entity != null` check
before calling `entity.getContent()`. HttpClient4 returns a null
entity when the response has no body — HEAD requests and 304 Not
Modified — so those samples failed with a NullPointerException
("Non HTTP response code: java.lang.NullPointerException").
Restore the guard and set empty response data when there is no body.
This matches HTTPJavaImpl, whose stream is never null. Covered by
TestRedirects.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a "modified gutter": a thin coloured strip on the left edge of a property
editor that lights up when the field's value is explicitly stored on the test
element. It mirrors the IntelliJ IDEA / VS Code convention, so you can tell at a
glance which fields you have overridden and which still inherit a default.
The series introduces:
ModifiedGutterwidget plus theUnsetMode/ExpressionMode/ResetModesealed types that configure it.
jorphan:JEditableCheckBox,JEditableComboBox,JEditableTextField(single-line) andJEditableTextArea(multi-line).
JBooleanPropertyEditor,JEnumPropertyEditorand
JStringPropertyEditor.NamePanel) and the comment field are wiredinto the gutter; the comment field is backed by
JEditableTextArea.lit (shortcut: an extra Backspace on an empty modified text field). For the
check-box and combo editors, the same popup carries a "Use Expression" entry
that switches to a free-form
${expression}field.updateUi/updateElement, so a save / reload round-trip preservesan explicit value even when it equals the default.
Demo
Light theme; for each control the top row is the default (gutter dark) and the
bottom row is the modified state (gutter lit).
Element name field

Checkbox (
JBooleanPropertyEditor)Combo box (
JEnumPropertyEditor)Reset from the context menu — right-click a modified control and pick
"Reset to default"; the item is enabled only while the gutter is lit.
Out of scope
The final commit, "Store raw body in responseData and only decompress when
responseBody is accessed", is unrelated to the gutter. It is kept on this branch
only for local debugging and will be submitted as a separate PR — please ignore
it when reviewing.
Follow-up
Roll the gutter-aware editors out to the remaining element GUIs so every input
carries the indicator. Each is a separate change:
Test plan
:src:jorphan:testand:src:core:testare greenembedded resources", "URLs must match" and "URLs must not match"; check the
element name field and the Comment field on any element. Save / reload a
.jmxand confirm explicit values are preserved.🤖 Generated with Claude Code