A tab strip that scrolls to the selected tab and while a tab is dragged against its edge, and hooks for every mouse button and for the modifiers, for an application that hands the mouse on
A strip with more tabs than fit left the selected one wherever it was, so a tab opened at the end or chosen with the keyboard could stay out of sight, and a tab could only be dragged as far as the visible part reached. A terminal that passes the mouse to the program in it, as xterm does, also needs every click with its modifiers, which ltk kept to itself apart from the middle button, and the modifiers held while the wheel turns, which the wheel does not carry. Scrolling to the selected tab. `TabRow` now knows the key of the selected tab, and in the layout it asks the `TabMotion` where the scroll of the tabs should go before drawing it; the answer is written into the scroll's own offset, which is keyed by the same index. When the selection changes the strip scrolls just enough to show that tab, through the scroll's `offset_into_view`, and keeps following it while it grows from nothing, so a new tab at the end is shown whole once it has opened. After that the strip is left where the user scrolls it. Dragging against the edge. While a tab is dragged and its lifted copy touches either edge of the visible part, the strip scrolls 8 widget pixels further that way on each frame (`EDGE_SCROLL`), and every layout places the dragged tab under the pointer again, so it travels with the strip although the pointer holds still and drops among the tabs that come into view. Pointer coordinates. A scroll and a viewport draw their child on a canvas of their own, so the tabs were laid out in coordinates that no longer matched the pointer once the strip scrolled. `DrawCtx.origin` now holds where the canvas being drawn on sits on the surface, set around the child of every `Scroll` and `Viewport`, and `TabCells` and `TabCards` hand it to the `TabMotion`, which takes it off the pointer in `drag_move`. The mouse. `App::on_mouse_button( &MouseButtonEvent )` reports every press and release of the left, middle and right buttons, with the position in physical pixels and Ctrl, Shift and Alt, before ltk handles it; `MouseButton` and `MouseButtonEvent` are exported. `App::on_modifiers( ctrl, shift, alt )` is called whenever the modifiers held change. Both do nothing by default. Tests cover a selected tab scrolled into view once and back, and a tab dragged against the edge scrolling the strip. The documentation of `tab_strip` describes the scrolling.
This commit is contained in:
+15
-1
@@ -96,11 +96,18 @@ pub( crate ) fn layout_and_draw<Msg: Clone>(
|
||||
}
|
||||
Element::TabRow( r ) =>
|
||||
{
|
||||
let inner = r.arrange( rect, canvas );
|
||||
// The child is the scroll of the tabs, whose offset is keyed by this same index.
|
||||
let inner = r.arrange( rect, canvas );
|
||||
let offset = ctx.scroll_offsets.get( &flat_idx ).copied().unwrap_or( ( 0.0, 0.0 ) );
|
||||
if let Some( x ) = r.scroll_to( offset.0, inner.width, canvas )
|
||||
{
|
||||
ctx.scroll_offsets.insert( flat_idx, ( x, offset.1 ) );
|
||||
}
|
||||
layout_and_draw::<Msg>( r.child.as_ref(), canvas, inner, ctx, flat_idx )
|
||||
}
|
||||
Element::TabCells( cells ) =>
|
||||
{
|
||||
cells.motion.set_origin( ctx.origin );
|
||||
let child_rects = cells.layout( rect, canvas );
|
||||
let mut idx = flat_idx;
|
||||
for ( child_rect, child_i ) in child_rects
|
||||
@@ -111,6 +118,7 @@ pub( crate ) fn layout_and_draw<Msg: Clone>(
|
||||
}
|
||||
Element::TabCards( cards ) =>
|
||||
{
|
||||
cards.motion.set_origin( ctx.origin );
|
||||
let child_rects = cards.layout( rect, canvas );
|
||||
let mut idx = flat_idx;
|
||||
for ( child_rect, child_i ) in child_rects
|
||||
@@ -300,7 +308,10 @@ pub( crate ) fn layout_and_draw<Msg: Clone>(
|
||||
|
||||
let rects_before = ctx.widget_rects.len();
|
||||
let scroll_rects_before = ctx.scroll_rects.len();
|
||||
let origin = ctx.origin;
|
||||
ctx.origin = ( origin.0 + rect.x, origin.1 + rect.y );
|
||||
let next_idx = layout_and_draw::<Msg>( s.child.as_ref(), &mut sub, child_rect, ctx, my_idx + 1 );
|
||||
ctx.origin = origin;
|
||||
|
||||
// Translate widget_rects from sub-canvas space to global space; drop
|
||||
// clipped ones. Also clamp `paint_rect` to the scroll viewport so a
|
||||
@@ -452,7 +463,10 @@ pub( crate ) fn layout_and_draw<Msg: Clone>(
|
||||
let child_rect = Rect { x: 0.0, y: 0.0, width: rect.width, height: effective_h };
|
||||
let rects_before = ctx.widget_rects.len();
|
||||
let scroll_rects_before = ctx.scroll_rects.len();
|
||||
let origin = ctx.origin;
|
||||
ctx.origin = ( origin.0 + rect.x, origin.1 + rect.y );
|
||||
let next_idx = layout_and_draw::<Msg>( v.child.as_ref(), &mut sub, child_rect, ctx, flat_idx );
|
||||
ctx.origin = origin;
|
||||
|
||||
let new_rects: Vec<LaidOutWidget<Msg>> = ctx.widget_rects.drain( rects_before.. ).collect();
|
||||
for mut w in new_rects
|
||||
|
||||
Reference in New Issue
Block a user