From f3fdfae00238b460c5a49d4f36378a89ab6ccf8f Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 6 Aug 2024 11:31:35 +0800 Subject: [PATCH] Fix list next to select first item, cancel to deselect item. (#110) - Add confirmed to ListItem to show check style. --- Cargo.lock | 20 ++++++++++---------- crates/story/src/picker_story.rs | 20 +++++++++++++------- crates/ui/src/list/list.rs | 10 +++++++--- crates/ui/src/list/list_item.rs | 18 +++++++++++++++--- crates/ui/src/svg_img.rs | 8 ++++---- 5 files changed, 49 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fea0a9c..b0ebddb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -925,7 +925,7 @@ dependencies = [ [[package]] name = "collections" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "rustc-hash", ] @@ -1238,7 +1238,7 @@ dependencies = [ [[package]] name = "derive_refineable" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "proc-macro2", "quote", @@ -2178,7 +2178,7 @@ dependencies = [ [[package]] name = "gpui" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "anyhow", "as-raw-xcb-connection", @@ -2278,7 +2278,7 @@ dependencies = [ [[package]] name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "proc-macro2", "quote", @@ -2482,7 +2482,7 @@ dependencies = [ [[package]] name = "http_client" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "anyhow", "derive_more", @@ -2997,7 +2997,7 @@ dependencies = [ [[package]] name = "media" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "anyhow", "bindgen", @@ -4107,7 +4107,7 @@ dependencies = [ [[package]] name = "refineable" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "derive_refineable", ] @@ -4382,7 +4382,7 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "semantic_version" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "anyhow", "serde", @@ -4791,7 +4791,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sum_tree" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "arrayvec", "log", @@ -5427,7 +5427,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "util" version = "0.1.0" -source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#d18b49a95309fdc8b46b64cb57dae96d4be0e49b" +source = "git+https://github.com/huacnlee/zed.git?branch=export-platform-window#371a680215f5a1e91fdfd6a00afbbf362f71eade" dependencies = [ "anyhow", "async-fs 1.6.0", diff --git a/crates/story/src/picker_story.rs b/crates/story/src/picker_story.rs index 43759afa..b22196f7 100644 --- a/crates/story/src/picker_story.rs +++ b/crates/story/src/picker_story.rs @@ -17,7 +17,8 @@ use ui::{ pub struct ListItemDeletegate { story: WeakView, - selected_index: usize, + confirmed_index: Option, + selected_index: Option, items: Vec>, matches: Vec>, } @@ -30,7 +31,7 @@ impl ListDelegate for ListItemDeletegate { } fn confirmed_index(&self) -> Option { - Some(self.selected_index) + self.confirmed_index } fn perform_search(&mut self, query: &str, cx: &mut ViewContext>) -> Task<()> { @@ -55,10 +56,13 @@ impl ListDelegate for ListItemDeletegate { } fn render_item(&self, ix: usize, _: &mut ViewContext>) -> Option { - let selected = ix == self.selected_index; + let confirmed = Some(ix) == self.confirmed_index; + let selected = Some(ix) == self.selected_index; + if let Some(item) = self.matches.get(ix) { let list_item = ListItem::new(("item", ix)) .check_icon(ui::IconName::Check) + .confirmed(confirmed) .selected(selected) .py_1() .px_3() @@ -115,7 +119,7 @@ impl ListDelegate for ListItemDeletegate { if let Some(story) = self.story.upgrade() { cx.update_view(&story, |story, cx| { if let Some(ix) = ix { - self.selected_index = ix; + self.confirmed_index = Some(ix); if let Some(item) = self.matches.get(ix) { story.selected_value = Some(item.clone()); } @@ -127,8 +131,9 @@ impl ListDelegate for ListItemDeletegate { } fn set_selected_index(&mut self, ix: Option, cx: &mut ViewContext>) { - if let Some(ix) = ix { - self.selected_index = ix; + self.selected_index = ix; + + if let Some(_) = ix { cx.notify(); } } @@ -204,7 +209,8 @@ impl PickerStory { let story = cx.view().downgrade(); let delegate = ListItemDeletegate { story, - selected_index: 0, + selected_index: None, + confirmed_index: None, items: items.clone(), matches: items.clone(), }; diff --git a/crates/ui/src/list/list.rs b/crates/ui/src/list/list.rs index bf2b7793..1e1141e3 100644 --- a/crates/ui/src/list/list.rs +++ b/crates/ui/src/list/list.rs @@ -225,6 +225,7 @@ where } fn action_cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { + self.set_selected_index(None, cx); self.delegate.cancel(cx); cx.notify(); } @@ -259,9 +260,12 @@ where return; } - let selected_index = self.selected_index.unwrap_or(0); - if selected_index < self.delegate.items_count() - 1 { - self.selected_index = Some(selected_index + 1); + if let Some(selected_index) = self.selected_index { + if selected_index < self.delegate.items_count() - 1 { + self.selected_index = Some(selected_index + 1); + } else { + self.selected_index = Some(0); + } } else { self.selected_index = Some(0); } diff --git a/crates/ui/src/list/list_item.rs b/crates/ui/src/list/list_item.rs index f10955df..21c92150 100644 --- a/crates/ui/src/list/list_item.rs +++ b/crates/ui/src/list/list_item.rs @@ -12,6 +12,7 @@ pub struct ListItem { base: Stateful
, disabled: bool, selected: bool, + confirmed: bool, check_icon: Option, on_click: Option>, on_secondary_mouse_down: Option>, @@ -25,6 +26,7 @@ impl ListItem { base: h_flex().id(id.into()).gap_x_1().py_1().px_2().text_base(), disabled: false, selected: false, + confirmed: false, on_click: None, on_secondary_mouse_down: None, check_icon: None, @@ -33,16 +35,24 @@ impl ListItem { } } + /// Set to show check icon, default is None. pub fn check_icon(mut self, icon: IconName) -> Self { self.check_icon = Some(Icon::new(icon)); self } + /// Set ListItem as the selected item style. pub fn selected(mut self, selected: bool) -> Self { self.selected = selected; self } + /// Set ListItem as the confirmed item style, it will show a check icon. + pub fn confirmed(mut self, confirmed: bool) -> Self { + self.confirmed = confirmed; + self + } + pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self @@ -100,6 +110,8 @@ impl ParentElement for ListItem { impl RenderOnce for ListItem { fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let is_active = self.selected || self.confirmed; + self.base .text_color(cx.theme().foreground) .relative() @@ -112,8 +124,8 @@ impl RenderOnce for ListItem { this } }) - .when(self.selected, |this| this.bg(cx.theme().list_active)) - .when(!self.selected && !self.disabled, |this| { + .when(is_active, |this| this.bg(cx.theme().list_active)) + .when(!is_active && !self.disabled, |this| { this.hover(|this| this.bg(cx.theme().list_hover)) }) // Right click @@ -133,7 +145,7 @@ impl RenderOnce for ListItem { .child(div().w_full().overflow_hidden().children(self.children)) .when_some(self.check_icon, |this, icon| { this.child(div().w_5().items_center().justify_center().when( - self.selected, + self.confirmed, |this| { this.child( icon.size(Size::Small) diff --git a/crates/ui/src/svg_img.rs b/crates/ui/src/svg_img.rs index 64a1837b..4e774954 100644 --- a/crates/ui/src/svg_img.rs +++ b/crates/ui/src/svg_img.rs @@ -84,8 +84,8 @@ impl Asset for Image { return Err(usvg::Error::InvalidSize.into()); } let size = Size { - width: size.width * scale, - height: size.height * scale, + width: (size.width * scale).ceil(), + height: (size.height * scale).ceil(), }; let bytes = match source.source { @@ -258,8 +258,8 @@ impl Element for SvgImg { }; let img_bounds = Bounds { - size: new_size, - origin: new_origin, + origin: new_origin.map(|origin| origin.floor()), + size: new_size.map(|size| size.ceil()), }; match cx.paint_image(img_bounds, px(0.).into(), data, 0, false) {