Skip to content

feat: split DockPane on edge drag-and-drop#3759

Merged
kasemir merged 1 commit intoControlSystemStudio:masterfrom
emilioheredia-source:feat_dock_split_on_drag
Mar 31, 2026
Merged

feat: split DockPane on edge drag-and-drop#3759
kasemir merged 1 commit intoControlSystemStudio:masterfrom
emilioheredia-source:feat_dock_split_on_drag

Conversation

@emilioheredia-source
Copy link
Copy Markdown

@emilioheredia-source emilioheredia-source commented Mar 31, 2026

Dragging a tab to an edge zone (outer 25% of width/height) now splits the pane in that direction instead of floating the tab. Dropping in the centre zone, or on the tab header strip, merges the tab into the target pane as before.
To float a tabs, drop it outside the Main Window, or use right click "Detach" on the tab context menu.
Colored outlines indicate the type of drop action (green rectangle = merge, blue edge = split).

What changed (DockPane.java only)

  • Add DropZone enum (CENTER/LEFT/RIGHT/TOP/BOTTOM)
  • DRAG_OVER registers as a capture-phase filter so drops onto content-heavy panes (e.g. file browser) are accepted even when child nodes consume the event; previously those drops would float the tab
  • Tab header strip always maps to CENTER (merge, not split): boundary measured via getBoundsInParent() and cached in handleTabChanges() to avoid a repeated CSS scene-graph walk on every pointer-move event
  • Directional blue border feedback via inline CSS: only the edge where the new pane will appear is highlighted (LEFT/RIGHT/TOP/BOTTOM); inline style is used because it sits at the highest cascade priority and is not overridden by the application stylesheet
  • mergeTabIntoPaneDeferred / splitAndPlaceTabAsync defer the remove+add to the same UI pulse so the source pane is never transiently empty, preventing spurious mergeEmptyAnonymousSplit calls that caused the application close button to require two clicks
  • mergeEmptyAnonymousSplit guards against running when the pane is no longer empty by the time the deferred call executes
  • split() restores setActiveDockPane(this) after constructing the new empty pane, preventing a null active-item notification to listeners during a live drag
  • Window.requestFocus() after drop re-asserts window focus so the first mouse action after a drag is not swallowed as a focus-click

The new behavior was tested manually by trigin to cover most or all use cases.

Dragging a tab to an edge zone (outer 25% of width/height) now splits
the pane in that direction instead of floating the tab.  Dropping in
the centre zone, or on the tab header strip, merges the tab into the
target pane as before.

## What changed (DockPane.java only)

- Add DropZone enum (CENTER/LEFT/RIGHT/TOP/BOTTOM)
- DRAG_OVER registers as a capture-phase filter so drops onto
  content-heavy panes (e.g. file browser) are accepted even when child
  nodes consume the event; previously those drops would float the tab
- Tab header strip always maps to CENTER (merge, not split): boundary
  measured via getBoundsInParent() and cached in handleTabChanges() to
  avoid a repeated CSS scene-graph walk on every pointer-move event
- Directional blue border feedback via inline CSS: only the edge where
  the new pane will appear is highlighted (LEFT/RIGHT/TOP/BOTTOM);
  inline style is used because it sits at the highest cascade priority
  and is not overridden by the application stylesheet
- mergeTabIntoPaneDeferred / splitAndPlaceTabAsync defer the remove+add
  to the same UI pulse so the source pane is never transiently empty,
  preventing spurious mergeEmptyAnonymousSplit calls that caused the
  application close button to require two clicks
- mergeEmptyAnonymousSplit guards against running when the pane is no
  longer empty by the time the deferred call executes
- split() restores setActiveDockPane(this) after constructing the new
  empty pane, preventing a null active-item notification to listeners
  during a live drag
- Window.requestFocus() after drop re-asserts window focus so the first
  mouse action after a drag is not swallowed as a focus-click
@sonarqubecloud
Copy link
Copy Markdown

@emilioheredia-source
Copy link
Copy Markdown
Author

emilioheredia-source commented Mar 31, 2026

Ok, this is the first real change. I know it's an invasive one, but I assume given most of the old behavior is still there, and this PR just adds new options, most users won't mind. And I really miss rearranging tabs by drag and drop, like the original CS Studio does.
If it helps with his adoption, I could make the new "drag and drop close to edges to split" feature, into a option so it can be turned on/off.
Thanks for considering this.

@kasemir
Copy link
Copy Markdown
Collaborator

kasemir commented Mar 31, 2026

This is good, thanks!
I think this is generally useful and there's no need to make it optional.
It this creates new bugs, they might be fixable, or worst case, we revert this single-file change until it can be fixed.

@kasemir kasemir merged commit b924dc3 into ControlSystemStudio:master Mar 31, 2026
4 checks passed
@emilioheredia-source emilioheredia-source deleted the feat_dock_split_on_drag branch March 31, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants