Project · focus that follows: segments, the tracker's action, tests
A segmented control too narrow for its segments now scrolls sideways in a strip of its own, and a segment that takes focus comes into view: its focus is a tab_stop handle, and layout::reveal_when_focused, now shared with the board's cards, measures it from a box that holds its ring. The DatabaseView's own strip goes. The time tracker's Start and Stop are one Button that keeps one handle through the new Button::focus_handle. A start moves focus to it, a stop hands focus back to the field, and the field starts on Enter's release, so the release no longer clicks the Stop that took focus. ProgressRing's percent refuses content inside, as content refuses a percent. Tests: Enter starts, Enter stops after 90 seconds, and the field takes the keys again; Skip moves on at once; a focused Timeline segment at 280px comes into view; the ring's refusal.
This commit is contained in:
1 parent
f70726476a
commit
384872cbf0
13 files changed
+294
-132
No files matched your search
+1
-1
@@ -22,8 +22,8 @@ pub use grid::{Masonry, SimpleGrid};
|
||||
pub(crate) use grid::{columns_for, fit};
|
||||
pub use page::{AppShell, MasterDetail, Page};
|
||||
pub use panes::{PaneGroup, PaneId, PaneLayout};
|
||||
pub(crate) use scroll::bring_into_view;
|
||||
pub use scroll::{ScrollArea, Scrollbar, on_axis};
|
||||
pub(crate) use scroll::{bring_into_view, reveal_when_focused};
|
||||
pub use scroll_aids::{ScrollShadow, ScrollToTop, StickyHeader};
|
||||
pub use sheet::{Drawer, Sheet};
|
||||
pub use sidebar::Sidebar;
|
||||
|
||||
+36
-3
@@ -5,9 +5,10 @@ use std::{
|
||||
};
|
||||
|
||||
use gpui::{
|
||||
AnyElement, App, Axis, Bounds, Div, ElementId, EmptyView, Entity, EntityId, InteractiveElement,
|
||||
IntoElement, ParentElement, Pixels, Point, RenderOnce, ScrollHandle,
|
||||
StatefulInteractiveElement, StyleRefinement, Styled, Window, div, point, prelude::*,
|
||||
AnyElement, App, Axis, Bounds, Canvas, Div, ElementId, EmptyView, Entity, EntityId,
|
||||
FocusHandle, InteractiveElement, IntoElement, ParentElement, Pixels, Point, RenderOnce,
|
||||
ScrollHandle, StatefulInteractiveElement, StyleRefinement, Styled, Window, canvas, div, point,
|
||||
prelude::*,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
@@ -39,6 +40,38 @@ pub(crate) fn bring_into_view(scroll: &ScrollHandle, item: Bounds<Pixels>, axis:
|
||||
shift != Pixels::ZERO
|
||||
}
|
||||
|
||||
/// A canvas over a Tab stop in a scroll box: when the stop takes focus, it brings its painted box into view along `axis`, once per focus. A new `id` reveals again.
|
||||
pub(crate) fn reveal_when_focused(
|
||||
id: impl Into<ElementId>,
|
||||
scroll: &ScrollHandle,
|
||||
focus: &FocusHandle,
|
||||
axis: Axis,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Canvas<()> {
|
||||
let shown = window.use_keyed_state(id, cx, |_, _| false);
|
||||
let (scroll, focus) = (scroll.clone(), focus.clone());
|
||||
canvas(
|
||||
move |bounds, window, cx| {
|
||||
let (focused, held) = (focus.is_focused(window), *shown.read(cx));
|
||||
if focused && !held {
|
||||
shown.update(cx, |shown, _| *shown = true);
|
||||
if bring_into_view(&scroll, bounds, axis) {
|
||||
log::info!("scroll: a focused stop came into view");
|
||||
window.request_animation_frame();
|
||||
}
|
||||
} else if !focused && held {
|
||||
shown.update(cx, |shown, _| *shown = false);
|
||||
}
|
||||
},
|
||||
|_, _, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.top_0()
|
||||
.left_0()
|
||||
.size_full()
|
||||
}
|
||||
|
||||
/// Keeps a scroll box's wheel to its own axes; gpui turns a wheel along the other axis onto a box that scrolls one way, while the page scrolls too.
|
||||
pub fn on_axis<E: Styled>(mut element: E) -> E {
|
||||
element.style().restrict_scroll_to_axis = Some(true);
|
||||
|
||||
Reference in new issue
Block a user