list, table: Add scroll_to_item to List, scroll_to_row to Table. (#535)
This commit is contained in:
parent
8aac2f75e4
commit
bf82e3db13
4 changed files with 142 additions and 73 deletions
|
|
@ -3,17 +3,18 @@ use std::time::Duration;
|
||||||
|
|
||||||
use fake::Fake;
|
use fake::Fake;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, px, relative, AnyElement, AppContext, ElementId, FocusHandle, FocusableView,
|
actions, div, px, AppContext, ElementId, FocusHandle, FocusableView, InteractiveElement,
|
||||||
InteractiveElement, IntoElement, ParentElement, Render, RenderOnce, Styled, Task, Timer, View,
|
IntoElement, ParentElement, Render, RenderOnce, Styled, Task, Timer, View, ViewContext,
|
||||||
ViewContext, VisualContext, WindowContext,
|
VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ui::{
|
use ui::{
|
||||||
|
button::Button,
|
||||||
h_flex,
|
h_flex,
|
||||||
label::Label,
|
label::Label,
|
||||||
list::{List, ListDelegate, ListItem},
|
list::{List, ListDelegate, ListItem},
|
||||||
theme::{hsl, ActiveTheme},
|
theme::{hsl, ActiveTheme},
|
||||||
v_flex,
|
v_flex, Sizable,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(list_story, [SelectedCompany]);
|
actions!(list_story, [SelectedCompany]);
|
||||||
|
|
@ -171,39 +172,6 @@ impl ListDelegate for CompanyListDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_initial(&self, cx: &mut ViewContext<List<Self>>) -> Option<AnyElement> {
|
|
||||||
let histories = ["BABA", "BIDU", "GOOGL", "LB", "LP", "LBW"];
|
|
||||||
|
|
||||||
let input_history = histories
|
|
||||||
.into_iter()
|
|
||||||
.map(|name| {
|
|
||||||
div()
|
|
||||||
.rounded_xl()
|
|
||||||
.min_w(px(30.))
|
|
||||||
.border_1()
|
|
||||||
.rounded_md()
|
|
||||||
.border_color(cx.theme().muted_foreground.opacity(0.3))
|
|
||||||
.line_height(relative(1.))
|
|
||||||
.p_1()
|
|
||||||
.child(div().whitespace_nowrap().child(name).text_xs())
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let element = v_flex()
|
|
||||||
.p_4()
|
|
||||||
.child(
|
|
||||||
v_flex().gap_y_2().child("History").child(
|
|
||||||
h_flex()
|
|
||||||
.gap_x_4()
|
|
||||||
.gap_y_2()
|
|
||||||
.flex_wrap()
|
|
||||||
.children(input_history),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into_any_element();
|
|
||||||
Some(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_selected_index(&mut self, ix: Option<usize>, cx: &mut ViewContext<List<Self>>) {
|
fn set_selected_index(&mut self, ix: Option<usize>, cx: &mut ViewContext<List<Self>>) {
|
||||||
if let Some(ix) = ix {
|
if let Some(ix) = ix {
|
||||||
self.selected_index = ix;
|
self.selected_index = ix;
|
||||||
|
|
@ -357,14 +325,43 @@ impl FocusableView for ListStory {
|
||||||
|
|
||||||
impl Render for ListStory {
|
impl Render for ListStory {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
div()
|
v_flex()
|
||||||
.track_focus(&self.focus_handle)
|
.track_focus(&self.focus_handle)
|
||||||
.on_action(cx.listener(Self::selected_company))
|
.on_action(cx.listener(Self::selected_company))
|
||||||
.size_full()
|
.size_full()
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.border_1()
|
.child(
|
||||||
.border_color(cx.theme().border)
|
h_flex()
|
||||||
.rounded_md()
|
.gap_2()
|
||||||
.child(self.company_list.clone())
|
.child(
|
||||||
|
Button::new("scroll-top")
|
||||||
|
.child("Scroll to Top")
|
||||||
|
.small()
|
||||||
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.company_list.update(cx, |list, cx| {
|
||||||
|
list.scroll_to_item(0, cx);
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("scroll-bottom")
|
||||||
|
.child("Scroll to Bottom")
|
||||||
|
.small()
|
||||||
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.company_list.update(cx, |list, cx| {
|
||||||
|
list.scroll_to_item(list.delegate().items_count(cx) - 1, cx);
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.flex_1()
|
||||||
|
.w_full()
|
||||||
|
.border_1()
|
||||||
|
.border_color(cx.theme().border)
|
||||||
|
.rounded_md()
|
||||||
|
.child(self.company_list.clone()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use ui::{
|
use ui::{
|
||||||
button::{Button, ButtonVariants},
|
button::Button,
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
h_flex,
|
h_flex,
|
||||||
indicator::Indicator,
|
indicator::Indicator,
|
||||||
|
|
@ -18,7 +18,7 @@ use ui::{
|
||||||
prelude::FluentBuilder as _,
|
prelude::FluentBuilder as _,
|
||||||
table::{ColFixed, ColSort, Table, TableDelegate, TableEvent},
|
table::{ColFixed, ColSort, Table, TableDelegate, TableEvent},
|
||||||
theme::ActiveTheme as _,
|
theme::ActiveTheme as _,
|
||||||
v_flex, Selectable, Size, StyleSized as _,
|
v_flex, Selectable, Sizable as _, Size, StyleSized as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
|
@ -707,34 +707,6 @@ impl Render for TableStory {
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_3()
|
.gap_3()
|
||||||
.flex_wrap()
|
.flex_wrap()
|
||||||
.child(
|
|
||||||
Button::new("size")
|
|
||||||
.compact()
|
|
||||||
.outline()
|
|
||||||
.label(format!("size: {:?}", self.size))
|
|
||||||
.popup_menu(move |menu, _| {
|
|
||||||
menu.menu_with_check(
|
|
||||||
"Large",
|
|
||||||
size == Size::Large,
|
|
||||||
Box::new(ChangeSize(Size::Large)),
|
|
||||||
)
|
|
||||||
.menu_with_check(
|
|
||||||
"Medium",
|
|
||||||
size == Size::Medium,
|
|
||||||
Box::new(ChangeSize(Size::Medium)),
|
|
||||||
)
|
|
||||||
.menu_with_check(
|
|
||||||
"Small",
|
|
||||||
size == Size::Small,
|
|
||||||
Box::new(ChangeSize(Size::Small)),
|
|
||||||
)
|
|
||||||
.menu_with_check(
|
|
||||||
"XSmall",
|
|
||||||
size == Size::XSmall,
|
|
||||||
Box::new(ChangeSize(Size::XSmall)),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Checkbox::new("loop-selection")
|
Checkbox::new("loop-selection")
|
||||||
.label("Loop Selection")
|
.label("Loop Selection")
|
||||||
|
|
@ -784,6 +756,76 @@ impl Render for TableStory {
|
||||||
.on_click(cx.listener(Self::toggle_refresh_data)),
|
.on_click(cx.listener(Self::toggle_refresh_data)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(
|
||||||
|
Button::new("size")
|
||||||
|
.small()
|
||||||
|
.label(format!("size: {:?}", self.size))
|
||||||
|
.popup_menu(move |menu, _| {
|
||||||
|
menu.menu_with_check(
|
||||||
|
"Large",
|
||||||
|
size == Size::Large,
|
||||||
|
Box::new(ChangeSize(Size::Large)),
|
||||||
|
)
|
||||||
|
.menu_with_check(
|
||||||
|
"Medium",
|
||||||
|
size == Size::Medium,
|
||||||
|
Box::new(ChangeSize(Size::Medium)),
|
||||||
|
)
|
||||||
|
.menu_with_check(
|
||||||
|
"Small",
|
||||||
|
size == Size::Small,
|
||||||
|
Box::new(ChangeSize(Size::Small)),
|
||||||
|
)
|
||||||
|
.menu_with_check(
|
||||||
|
"XSmall",
|
||||||
|
size == Size::XSmall,
|
||||||
|
Box::new(ChangeSize(Size::XSmall)),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("scroll-top")
|
||||||
|
.child("Scroll to Top")
|
||||||
|
.small()
|
||||||
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.table.update(cx, |table, cx| {
|
||||||
|
table.scroll_to_row(0, cx);
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("scroll-bottom")
|
||||||
|
.child("Scroll to Bottom")
|
||||||
|
.small()
|
||||||
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.table.update(cx, |table, cx| {
|
||||||
|
table.scroll_to_row(table.delegate().rows_count(cx) - 1, cx);
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
), // .child(
|
||||||
|
// Button::new("scroll-first-col")
|
||||||
|
// .child("Scroll to First Column")
|
||||||
|
// .small()
|
||||||
|
// .on_click(cx.listener(|this, _, cx| {
|
||||||
|
// this.table.update(cx, |table, cx| {
|
||||||
|
// table.scroll_to_col(0, cx);
|
||||||
|
// })
|
||||||
|
// })),
|
||||||
|
// )
|
||||||
|
// .child(
|
||||||
|
// Button::new("scroll-last-col")
|
||||||
|
// .child("Scroll to Last Column")
|
||||||
|
// .small()
|
||||||
|
// .on_click(cx.listener(|this, _, cx| {
|
||||||
|
// this.table.update(cx, |table, cx| {
|
||||||
|
// table.scroll_to_col(table.delegate().cols_count(cx), cx);
|
||||||
|
// })
|
||||||
|
// })),
|
||||||
|
// ),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex().items_center().gap_2().child(
|
h_flex().items_center().gap_2().child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,18 @@ where
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scroll to the item at the given index.
|
||||||
|
pub fn scroll_to_item(&mut self, ix: usize, cx: &mut ViewContext<Self>) {
|
||||||
|
self.vertical_scroll_handle
|
||||||
|
.scroll_to_item(ix, ScrollStrategy::Top);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get scroll handle
|
||||||
|
pub fn scroll_handle(&self) -> &UniformListScrollHandle {
|
||||||
|
&self.vertical_scroll_handle
|
||||||
|
}
|
||||||
|
|
||||||
fn scroll_to_selected_item(&mut self, _cx: &mut ViewContext<Self>) {
|
fn scroll_to_selected_item(&mut self, _cx: &mut ViewContext<Self>) {
|
||||||
if let Some(ix) = self.selected_index {
|
if let Some(ix) = self.selected_index {
|
||||||
self.vertical_scroll_handle
|
self.vertical_scroll_handle
|
||||||
|
|
|
||||||
|
|
@ -367,12 +367,30 @@ where
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to_row(&mut self, row_ix: usize, cx: &mut ViewContext<Self>) {
|
/// Scroll to the row at the given index.
|
||||||
|
pub fn scroll_to_row(&mut self, row_ix: usize, cx: &mut ViewContext<Self>) {
|
||||||
self.vertical_scroll_handle
|
self.vertical_scroll_handle
|
||||||
.scroll_to_item(row_ix, ScrollStrategy::Top);
|
.scroll_to_item(row_ix, ScrollStrategy::Top);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll to the column at the given index.
|
||||||
|
// TODO: Fix scroll to selected col, this was not working after fixed col.
|
||||||
|
// pub fn scroll_to_col(&mut self, col_ix: usize, cx: &mut ViewContext<Self>) {
|
||||||
|
// self.horizontal_scroll_handle.scroll_to_item(col_ix);
|
||||||
|
// cx.notify();
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Get scroll handle
|
||||||
|
pub fn scroll_handle(&self) -> &UniformListScrollHandle {
|
||||||
|
&self.vertical_scroll_handle
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get horizontal scroll handle
|
||||||
|
pub fn horizontal_scroll_handle(&self) -> &ScrollHandle {
|
||||||
|
&self.horizontal_scroll_handle
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the selected row index.
|
/// Returns the selected row index.
|
||||||
pub fn selected_row(&self) -> Option<usize> {
|
pub fn selected_row(&self) -> Option<usize> {
|
||||||
self.selected_row
|
self.selected_row
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue