Lists: a selectable list's cursor starts on the owner's pick; the waveform's fit is tested
SelectableList keeps the owner's last selection and the one it last sent. A selection the owner makes, on first paint or later, moves the cursor to its first row; the echo of the list's own pick leaves the cursor where the pick put it. The playlist's keys start from the song under way. The waveform's bar count and inset move into `fit`, tested beside `resample`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4b86283d69
commit
235f059c8e
6 files changed
+102
-5
No files matched your search
+13
-1
@@ -38,13 +38,15 @@ pub(crate) fn picked(
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// The row the keyboard is on and where a Shift range starts, by index and by key so they follow their rows when the owner reorders them, and the scroll that follows them.
|
||||
/// The row the keyboard is on and where a Shift range starts, by index and by key so they follow their rows when the owner reorders them, and the scroll that follows them; the owner's last selection, and the one the list last sent.
|
||||
#[derive(Default)]
|
||||
struct Cursor {
|
||||
at: usize,
|
||||
anchor: usize,
|
||||
keys: Option<(SharedString, SharedString)>,
|
||||
scroll: ScrollHandle,
|
||||
seen: Option<Vec<SharedString>>,
|
||||
sent: Option<Vec<SharedString>>,
|
||||
}
|
||||
|
||||
type OnSelect = Rc<dyn Fn(&[SharedString], &mut Window, &mut App)>;
|
||||
@@ -125,6 +127,15 @@ impl RenderOnce for SelectableList {
|
||||
let cursor =
|
||||
window.use_keyed_state((self.id.clone(), "cursor"), cx, |_, _| Cursor::default());
|
||||
let keys: Rc<[SharedString]> = self.rows.iter().map(|(key, _)| key.clone()).collect();
|
||||
if cursor.read(cx).seen.as_ref() != Some(&self.selected) {
|
||||
cursor.update(cx, |cursor, _| {
|
||||
let echo = cursor.sent.take().as_ref() == Some(&self.selected);
|
||||
if let Some(first) = self.selected.first().filter(|_| !echo) {
|
||||
cursor.keys = Some((first.clone(), first.clone()));
|
||||
}
|
||||
cursor.seen = Some(self.selected.clone());
|
||||
});
|
||||
}
|
||||
let (at, anchor, scroll) = {
|
||||
let cursor = cursor.read(cx);
|
||||
let place = |key: Option<&SharedString>, ix: usize| {
|
||||
@@ -183,6 +194,7 @@ impl RenderOnce for SelectableList {
|
||||
keys[cursor.anchor.min(keys.len() - 1)].clone(),
|
||||
));
|
||||
cursor.scroll.scroll_to_item(ix);
|
||||
cursor.sent = Some(next.clone());
|
||||
cx.notify();
|
||||
});
|
||||
log::info!("selectable list {id:?}: {next:?}");
|
||||
|
||||
@@ -117,6 +117,41 @@ fn presses_pick_one_toggle_with_cmd_and_range_with_shift(cx: &mut TestAppContext
|
||||
assert_eq!(picks(&view, cx), NAMES);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn the_cursor_starts_on_the_first_selected_row(cx: &mut TestAppContext) {
|
||||
setup(cx);
|
||||
let (view, cx) = cx.add_window_view(|_, _| Picks(vec!["c".into()], Vec::new(), None, false));
|
||||
settle(cx);
|
||||
cx.update(|window, _| window.focus_next());
|
||||
cx.simulate_keystrokes("down");
|
||||
settle(cx);
|
||||
assert_eq!(picks(&view, cx), ["d"]);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_selection_from_the_owner_moves_the_cursor_and_an_echo_does_not(cx: &mut TestAppContext) {
|
||||
setup(cx);
|
||||
let (view, cx) = cx.add_window_view(|_, _| Picks(vec!["a".into()], Vec::new(), None, false));
|
||||
settle(cx);
|
||||
view.update(cx, |picks, _| picks.0 = vec!["b".into()]);
|
||||
settle(cx);
|
||||
cx.update(|window, _| window.focus_next());
|
||||
cx.simulate_keystrokes("shift-down shift-down");
|
||||
settle(cx);
|
||||
assert_eq!(
|
||||
picks(&view, cx),
|
||||
["b", "c", "d"],
|
||||
"the range starts where the owner put it"
|
||||
);
|
||||
cx.simulate_keystrokes("up");
|
||||
settle(cx);
|
||||
assert_eq!(
|
||||
picks(&view, cx),
|
||||
["c"],
|
||||
"its own range left the cursor at its end"
|
||||
);
|
||||
}
|
||||
|
||||
/// A row with two actions, 144 across; it reports where the row sits and which action ran.
|
||||
struct Swiped {
|
||||
left: Rc<Cell<Pixels>>,
|
||||
|
||||
Reference in new issue
Block a user