mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-03 09:11:10 +00:00
docking: one model; profile differences are style data
Remove `Profile`. What it switched is now a `DockStyle` setting with the dock-and-canvas behaviour as the default: `side_edge_zones`, `new_dock_zones`, `maximize_item`, `close_others_item`, `command_press_floats`, `float_hint`, and plain bools for `wheel_selects_tabs` and `middle_click_closes_tabs`. The undock and Close Panel Group labels go; an app sets `float_label`, `float_group_label` and `close_group_label` instead. Remove the size machinery that made frames stick: `DockContent::bare`, `FixedSlot` and the split that took a parent's or sibling's half beside a fixed-size frame, and the gap snapping to the nearest frame. A tab group takes the largest maximum of its panels, so a panel without one lifts the cap of the group it joins. A dragged divider stores a ratio whatever mode it was saved with. Sizes follow the reference rules: a divider resizes only the groups that touch it and stops at their minimums; a four-way handle where a divider ends on another moves both (`Divider::Intersection`); a split or outer-edge drop that would leave a group without `min_pane` is not offered, and a group too small to halve takes the drop as a tab. Tests: one per rule, the stuck cases from the FilmCraft map, and a property test over random drops checking minimums and divider travel.
This commit is contained in:
1 parent
958c5ada58
commit
d30c207c8d
20 files changed
+974
-511
No files matched your search
+39
-28
@@ -7,16 +7,17 @@ gestures. The app owns panel contents, commands, document state and where layout
|
||||
Office apps that draw their own document with a few task panes beside it use
|
||||
[`craft_ui::panes`](ui-panes.md) instead.
|
||||
|
||||
## Profiles
|
||||
## Arrangements
|
||||
|
||||
`DockStyle::profile` picks one of two arrangements. Both use the same model and actions.
|
||||
An app builds its style with `DockStyle::from_ui`, `from_visuals` or `default` and then sets
|
||||
fields; new fields can be added, so the struct has no literal form outside the crate.
|
||||
One model serves every app. What differs between apps is the default layout and a few
|
||||
`DockStyle` settings. An app builds its style with `DockStyle::from_ui`, `from_visuals` or
|
||||
`default` and then sets fields; new fields can be added, so the struct has no literal form
|
||||
outside the crate.
|
||||
|
||||
| Profile | Arrangement | Apps |
|
||||
|---|---|---|
|
||||
| `Profile::Dock` (default) | Docks on the window's start and end edges. A dock has columns; a column has stacked groups and can collapse to icons. Frames (tab groups and splits) fill the space between the docks. | Creative apps with a canvas and panel docks |
|
||||
| `Profile::Frame` | A split tree of tab frames. Frame menus offer Maximize Frame, Undock and Close Other Panels. Ctrl/Cmd + drag undocks, and a hint under the pointer says so. Drops on all four outer edges split at the root. | Apps whose whole window is frames |
|
||||
| Arrangement | Layout | Style settings | Apps |
|
||||
|---|---|---|---|
|
||||
| Docks beside a canvas (the defaults) | `Node::Dock`s on the window's start and end edges. A dock has columns; a column has stacked groups and can collapse to icons. Frames (tab groups and splits) fill the space between the docks. | `new_dock_zones` on | Creative apps with a canvas and panel docks |
|
||||
| A split tree of tab groups | `Split`s and `Tabs` only. | `side_edge_zones`, `maximize_item`, `close_others_item`, `command_press_floats`, `float_hint`, `wheel_selects_tabs`, `middle_click_closes_tabs` on, `new_dock_zones` off; menu labels such as "Undock Panel" set on `float_label`, `float_group_label` and `close_group_label` | Apps whose whole window is frames |
|
||||
|
||||
Sides are logical: `Side::Start` is the left edge, or the right edge when
|
||||
`DockStyle::right_to_left` is set. egui has no app-wide direction, so the app sets it from its
|
||||
@@ -32,7 +33,7 @@ their sides.
|
||||
| Node | Holds |
|
||||
|---|---|
|
||||
| `Tabs` | A tab group: panels and the active index. |
|
||||
| `Split` | Two children, horizontal or vertical, with a ratio or a fixed first or second size. |
|
||||
| `Split` | Two children, horizontal or vertical, with a ratio. A fixed first or second size from a saved layout is drawn at that size until the divider moves; a moved divider stores a ratio. |
|
||||
| `Stack` | Accordion entries, each open or closed, with an optional height. |
|
||||
| `Dock` | A side and its columns. A `Column` has `Group`s, a width, and `iconic`. |
|
||||
|
||||
@@ -68,11 +69,9 @@ layout.apply(Action::Move {
|
||||
`Placement::for_zone(layout, anchor, zone, right_to_left)` maps a left, right, top, bottom or
|
||||
center zone onto what the anchor's container takes: a split in the frame tree, a new column on
|
||||
that side or a new group above or below in a dock, a group above or below in a floating window.
|
||||
- A side split zone puts what moves in a new half-size split of the anchor's frame. A frame
|
||||
that holds the fixed size of its parent split along the same axis, such as a tool strip, keeps
|
||||
that size: on its outer side the new split wraps the parent, on its inner side it halves the
|
||||
parent's other child. The new split has its own divider, and the drop preview shows the half
|
||||
the new frame takes.
|
||||
- A side split zone puts what moves in a new half-size split of the anchor's frame, and no
|
||||
other frame changes size. The new split has its own divider, and the drop preview shows the
|
||||
half the new frame takes.
|
||||
- Other actions select, minimize, collapse to icons, resize splits, columns and groups, and move
|
||||
a floating window to its own OS window (`SetNative`, feature `native-windows`).
|
||||
|
||||
@@ -112,19 +111,19 @@ its own command path, so pointer, keyboard and control commands share one path.
|
||||
`DockContent<P>` is the app's adapter. It draws each panel body and gives its label, icon,
|
||||
permissions, size limits, preferred floating size, panel menu and group header. The group header
|
||||
sits at the end of the tab strip; `group_header_width` gets the strip width, so a header that
|
||||
draws its own tabs can size them to the room left. `bare` hides the tab strip of a lone panel. An icon is an image (`icon`), or drawn in code by `paint_icon`, which
|
||||
draws its own tabs can size them to the room left. An icon is an image (`icon`), or drawn in code by `paint_icon`, which
|
||||
gets a painter, the icon rect and the tint color and returns true when it painted. Panel bodies keep a stable egui id when they move, so widget memory
|
||||
survives.
|
||||
|
||||
`DockOutput` also has:
|
||||
|
||||
- `focused`: the panel the user focused this frame: a clicked tab, a drop, or a press of any
|
||||
pointer button in a panel body (bare and protected panels included) or in the group header,
|
||||
pointer button in a panel body (protected panels included) or in the group header,
|
||||
which focuses the group's shown panel. Commands, `raise_panel` and
|
||||
workspace resets never set it; a host that tracks the last focused panel clears it when a reset
|
||||
or command hides, closes or moves that panel.
|
||||
- `events`: requests outside the layout, such as `DockEvent::ToggleMaximize` (Frame) and
|
||||
`DockEvent::ToggleAutoCollapse` (Dock), and `DockEvent::FlyoutChanged { panel }` (Dock): the
|
||||
- `events`: requests outside the layout, such as `DockEvent::ToggleMaximize` (`maximize_item`) and
|
||||
`DockEvent::ToggleAutoCollapse` and `DockEvent::FlyoutChanged { panel }` (docks): the
|
||||
flyout opened, switched or closed (`None`). It comes once per change, whatever made it: an
|
||||
icon, Escape, a press outside, a raised panel, `open_flyout` or `close_flyout`.
|
||||
- `error`: a rejected gesture.
|
||||
@@ -191,21 +190,33 @@ A flyout fits its content the same way, without the title bar.
|
||||
4 pt band above the title bar (`chrome::RESIZE_BAND`), so they take no moves and no clicks on
|
||||
the title bar's buttons. A resize keeps the opposite edges in place and stays within the size
|
||||
limits and the screen. A focused resize handle moves its edge 8 pt per arrow key.
|
||||
- Over a frame, the tab strip and the middle join its tabs, and the nearest side splits it. A
|
||||
side zone is a quarter of the frame deep, at least 32 pt and at most half the frame, so a narrow
|
||||
tool strip keeps both side targets. A drop in the gap between two frames splits beside the
|
||||
nearer one.
|
||||
- Over a frame, the tab strip and the middle join its tabs, and the nearest side splits it. The
|
||||
side zones are trapezoids along the four edges, like a picture frame: a quarter of the frame
|
||||
deep, at least 32 pt and at most half the frame. A split that would leave either half without
|
||||
`DockStyle::min_pane` joins the frame's tabs instead. The gap between two frames is no target.
|
||||
- The outer edge band (`DockStyle::edge_band`) takes a drop as a new frame across the whole
|
||||
window side: top and bottom, and left and right with `side_edge_zones`. It takes a quarter of
|
||||
the window and is offered only when every frame keeps its minimum. Past the band, a frame's own
|
||||
side zones apply.
|
||||
- A divider resizes only the frames that touch it; every other frame keeps its size. It stops
|
||||
when a frame touching it reaches its minimum. Where a divider ends on another divider, a
|
||||
four-way handle (`Divider::Intersection`) moves both.
|
||||
- Every frame has the same minimum, `DockStyle::min_pane` (plus its tab strip), unless its panels
|
||||
ask for more through `PanelLimits::min`. Frames have no maximum unless every panel in them asks
|
||||
for one through `PanelLimits::max`: a panel without a maximum lifts the maximum of the panels it
|
||||
joins.
|
||||
- Drop previews show the destination: an outline for tabs, a line for a new group, column or dock,
|
||||
a filled half for a split. Escape or losing window focus cancels a drag.
|
||||
- In the Frame profile, Ctrl (⌘ on macOS) held while dragging a tab, a drag bar or a grip that
|
||||
calls `begin_drag` floats the drop wherever it lands. While a drag offers a docking target, a
|
||||
hint under the pointer names the modifier: `float_hint_label`, where `{key}` becomes ⌘ or Ctrl.
|
||||
- Ctrl (⌘ on macOS) held at the drop floats it wherever it lands. With `command_press_floats`,
|
||||
the key held when a tab drag of a frame starts is enough. With `float_hint`, a hint under the
|
||||
pointer names the modifier while a drag offers a docking target: `float_hint_label`, where
|
||||
`{key}` becomes ⌘ or Ctrl.
|
||||
- Double-click a tab or drag bar to minimize a group to its strip.
|
||||
- Right-click a tab for its menu, or a drag bar for the group menu; Enter or Space on a focused
|
||||
drag bar opens it too. A left click on the drag bar only focuses it.
|
||||
- In the Frame profile, the mouse wheel over a tab strip selects the next or previous tab, and a
|
||||
middle click on a closable panel's tab closes it. `DockStyle::wheel_selects_tabs` and
|
||||
`middle_click_closes_tabs` turn either on or off in any profile.
|
||||
- With `DockStyle::wheel_selects_tabs`, the mouse wheel over a tab strip selects the next or
|
||||
previous tab. With `middle_click_closes_tabs`, a middle click on a closable panel's tab closes
|
||||
it.
|
||||
- A column's »/« button collapses it to icons, one icon per panel with a separator between groups.
|
||||
Widen an iconic column to show panel names. Click an icon to open its group as a flyout on the
|
||||
canvas side. Drag an icon to move its panel, or an icon group's top edge (the separator line above it) to move the group.
|
||||
|
||||
Reference in new issue
Block a user