Skip to content

Make tags that scroll out of view reachable in the tag field - #514

Open
tonygermano wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
tonygermano:feat/tag-field-edit-mode
Open

tonygermano wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
tonygermano:feat/tag-field-edit-mode

Conversation

@tonygermano

Copy link
Copy Markdown
Member

Summary

Follow-up to #437. When a tag field has more tags than fit, the first ones scroll past the left edge, and there was no way to get back to them (see @NicoPiel's review). In the channel editor, which has no clear button, the only way to remove the first tag was to backspace through every tag after it.

This PR makes every tag reachable from both the mouse and the keyboard, and removes a license notice #437 left behind. It applies to all three tag fields: the channel editor and the Dashboard and Channels filters.

Changes

Keyboard navigation with an edit mode. The text editor can now sit between chips, and new tags are inserted where it is. Typing enters an edit mode, shown by an outline around the text, and the keys behave differently in each mode:

Key Navigating Edit mode
Left / Right Move the editor past a chip Move the caret
Home / End Move the editor to the first or last slot Move the caret
Backspace / Delete Remove the chip before or after the editor Edit the text
Enter / comma Nothing Commit the text
Escape Passed on to the window Clear the text and leave edit mode without committing

Edit mode lasts until the text is committed, Escape is pressed, or the field loses focus with no text. Deleting the text doesn't end it, so holding Backspace to clear what you typed can't run on into the chips.

Mouse wheel scrolling. The wheel and sideways trackpad swipes scroll the chips. When all the chips fit, the wheel event is passed on, so an enclosing scroll pane still scrolls. Before, the field swallowed it.

Mouse deletion and placement.

  • Like a browser tab, a middle click anywhere on a chip deletes it.
  • The "×" deletes on release, and only if the pointer is still over it.
  • After a mouse delete, the row stays where it is, so the next chip slides under the pointer.
  • A left click in a gap between chips puts the editor there, so tags can be inserted with the mouse.

Third-party notice. #437 removed the last bundled copy of bootstrap-tokenfield, so its section of THIRD-PARTY-README.txt is removed. The jQuery and Bootstrap sections stay, since server/public_api_html still ships both.

Commits

Each commit builds on its own.

  1. Navigate tag chips from the keyboard with an edit mode. The editor sits between chips, edit mode works as described above, and the editor is sized to its text. The editor and its outline use TagChip's font and corner radius, so typed text looks like the chips.
  2. Drop the bootstrap-tokenfield third-party notice.
  3. Scroll the tag chips with the mouse wheel. This includes sideways scrolling on Linux. X11 reports it as mouse buttons 4 and 5 rather than as wheel events, so it needs its own listener.
  4. Delete tag chips with a middle click and place the editor by clicking.

Testing

  • I tested the channel editor and the Dashboard and Channels filters on Linux (X11) with a trackpad, a trackpoint, and a mouse with a tilt wheel. The mouse's back and forward buttons have no effect on the field.
  • On Windows, I tested scrolling with the tilt-wheel mouse.
  • I haven't tested on macOS. There, sideways scrolling arrives as wheel events with Shift, the same as on Windows.
  • ./gradlew clean build passes.
  • Claude checked the keyboard, mouse and scrolling behavior with a headless test harness, which isn't part of this PR. A separate Claude review with no prior context checked each commit on its own. The fixes from that review are included.

Drafted with Claude Code

The editor can now sit between chips, and commits insert at its
position. Typing enters an outlined edit mode, in which the keys act on
the text instead of the chips:

- Left / Right
  - Navigating: move the editor past a chip
  - Edit mode: move the caret
- Home / End
  - Navigating: move the editor to the first or last slot
  - Edit mode: move the caret
- Backspace / Delete
  - Navigating: remove the chip before or after the editor
  - Edit mode: edit the text
- Enter / comma
  - Navigating: nothing
  - Edit mode: commit the text
- Escape
  - Navigating: passed on to the window
  - Edit mode: clear the text and leave edit mode without committing

Edit mode lasts until the text is committed, Escape is pressed, or the
field loses focus with no text. Deleting the text doesn't end it, so
holding Backspace to clear the text can't run on into the chips.

A click on the row outside the chips moves the editor back to the end.
Deleting a chip from the keyboard scrolls the editor into view, but
deleting one with the mouse leaves the row where it is, so the next
chip slides under the pointer.

The editor is sized to its text and grows while typing; it fills the
rest of the row only while showing its prompt. TagChip's font and
corner arc are shared so the editor and its outline match the chips.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Tony Germano <tony@germano.name>
The Swing rewrite of the tag field removed the last bundled copy of
bootstrap-tokenfield, so its license notice no longer applies. The
jQuery and Bootstrap notices stay, since server/public_api_html still
ships both.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Tony Germano <tony@germano.name>
The chip row has no scrollbar, so the scroll pane's own wheel handling
did nothing, and tags scrolled off the left edge could not be reached
with the mouse. The wheel, or a sideways trackpad swipe, now scrolls
the row horizontally. While the chips fit, the event is passed on so
an enclosing scroll pane still scrolls; before, the field swallowed it.

On X11, horizontal scrolling arrives as presses of mouse buttons 4 and
5 rather than as wheel events, so a toolkit event listener scrolls the
row for those while the field is displayable. Buttons other than the
left one no longer focus the editor or move it to the end; otherwise
each sideways scroll step would pull the row back to the editor.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Tony Germano <tony@germano.name>
Like a browser tab, a middle click anywhere on a chip deletes it. The
"×" deletes on a left or middle click and ignores other buttons, which
on X11 include horizontal scrolling. Both act on release, and only if
the pointer is still over what was pressed; a click event is dropped if
the pointer moves while the button is down, which a trackpoint nearly
always does.

A left click in a gap between chips, or past the last one, puts the
editor in that gap, so tags can be inserted with the mouse. Clicks on a
chip itself don't move the editor, and neither does any click while
text is being edited or the field is disabled.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Tony Germano <tony@germano.name>
@tonygermano tonygermano added the enhancement New feature or request label Oct 26, 2026
@tonygermano
tonygermano requested a review from a team October 26, 2026 03:10
@tonygermano tonygermano added the licensing Eclipse Intellectual Property (IP) due diligence: licensing, provenance, Dash results, IP reviews label Oct 26, 2026
@github-actions

Copy link
Copy Markdown

Test Results

129 files  ±0  129 suites  ±0   4m 1s ⏱️ + 1m 4s
737 tests ±0  737 ✅ ±0  0 💤 ±0  0 ❌ ±0 
827 runs  ±0  821 ✅ ±0  6 💤 ±0  0 ❌ ±0 

Results for commit 91ed8fc. ± Comparison against base commit 6248cdd.

@mgaffigan mgaffigan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tags-control.mov

@NicoPiel

Copy link
Copy Markdown
Contributor

Bugs:

  1. Typed text carries over to the next channel. Text typed but not committed stays in the editor, still in edit mode, when you open another channel: editChannel → setChannelTags never clears it. Saving the second channel then adds that text as a tag via createTagOnFocusLost.
  2. Editor stuck between chips. If you type between two chips and click Save, the tag is added but the editor stays where it was, empty and unfocused, with no prompt.

Lower priority:

  • getPreferredSize reaches the editor through the outer editor field, which is still null while the text field is being built. It's a possible null pointer error if the size is ever asked for that early.
  • editorIndex is reset by hand before setTokens in three places, but update() and clear() don't do it. One reset inside setTokens would cover all of them.
  • moveEditor rebuilds every chip on each arrow-key press. setComponentZOrder would move the editor and keep focus.
  • On X11, each tag field installs its own app-wide mouse listener, so every mouse event in the client goes through up to three of them.
  • The edit outline's color comes from MetalLookAndFeel rather than UIManager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request licensing Eclipse Intellectual Property (IP) due diligence: licensing, provenance, Dash results, IP reviews

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants