list: Refactor ListDelegate to easy access delegate. (#1713)
Continue #1712 ## Break Changes - The argument type of `render_item`, `render_section_header`, `render_section_footer`, `render_empty`, `render_initial`, `render_loading` in `ListDelegate` has been changed to has `&mut self` and `&mut Context<ListState<Self>>`. ```diff - fn render_item(&self, ix: IndexPath, window: &mut Window, cx: &mut App) -> Option<Self::Item> + fn render_item(&mut self, ix: IndexPath, window: &mut Window, cx: &mut Context<ListState<Self>>) -> Option<Self::Item> ```
This commit is contained in:
parent
001b1795f1
commit
c0f801dd8c
8 changed files with 89 additions and 52 deletions
|
|
@ -225,10 +225,10 @@ impl ListDelegate for CompanyListDelegate {
|
|||
}
|
||||
|
||||
fn render_section_header(
|
||||
&self,
|
||||
&mut self,
|
||||
section: usize,
|
||||
_: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let Some(industry) = self.industries.get(section) else {
|
||||
return None;
|
||||
|
|
@ -247,10 +247,10 @@ impl ListDelegate for CompanyListDelegate {
|
|||
}
|
||||
|
||||
fn render_section_footer(
|
||||
&self,
|
||||
&mut self,
|
||||
section: usize,
|
||||
_: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let Some(_) = self.industries.get(section) else {
|
||||
return None;
|
||||
|
|
@ -270,7 +270,7 @@ impl ListDelegate for CompanyListDelegate {
|
|||
)
|
||||
}
|
||||
|
||||
fn render_item(&self, ix: IndexPath, _: &mut Window, _: &mut App) -> Option<Self::Item> {
|
||||
fn render_item(&mut self, ix: IndexPath, _: &mut Window, _: &mut Context<ListState<Self>>) -> Option<Self::Item> {
|
||||
let selected = Some(ix) == self.selected_index || Some(ix) == self.confirmed_index;
|
||||
if let Some(company) = self.matched_companies[ix.section].get(ix.row) {
|
||||
return Some(CompanyListItem::new(ix, company.clone(), selected));
|
||||
|
|
|
|||
|
|
@ -75,10 +75,10 @@ impl ListDelegate for DropdownListDelegate {
|
|||
}
|
||||
|
||||
fn render_item(
|
||||
&self,
|
||||
&mut self,
|
||||
ix: gpui_component::IndexPath,
|
||||
_: &mut Window,
|
||||
_: &mut App,
|
||||
_: &mut Context<ListState<Self>>,
|
||||
) -> Option<Self::Item> {
|
||||
Some(ListItem::new(ix).child(format!("Item {}", ix.row)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ impl ListDelegate for ListItemDeletegate {
|
|||
})
|
||||
}
|
||||
|
||||
fn render_item(&self, ix: IndexPath, _: &mut Window, _: &mut App) -> Option<Self::Item> {
|
||||
fn render_item(&mut self, ix: IndexPath, _: &mut Window, _: &mut Context<ListState<Self>>) -> Option<Self::Item> {
|
||||
let confirmed = Some(ix.row) == self.confirmed_index;
|
||||
|
||||
if let Some(item) = self.matches.get(ix.row) {
|
||||
|
|
@ -97,7 +97,11 @@ impl ListDelegate for ListItemDeletegate {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_empty(&self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
fn render_empty(
|
||||
&mut self,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> impl IntoElement {
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use gpui::{
|
||||
canvas, deferred, div, prelude::FluentBuilder, px, relative, Action, AnyElement, App,
|
||||
AppContext, Bounds, Context, DismissEvent, Empty, Entity, EventEmitter,
|
||||
InteractiveElement as _, IntoElement, ParentElement, Pixels, Point, Render, RenderOnce,
|
||||
SharedString, Styled, StyledText, Subscription, Window,
|
||||
Action, AnyElement, App, AppContext, Bounds, Context, DismissEvent, Empty, Entity,
|
||||
EventEmitter, InteractiveElement as _, IntoElement, ParentElement, Pixels, Point, Render,
|
||||
RenderOnce, SharedString, Styled, StyledText, Subscription, Window, canvas, deferred, div,
|
||||
prelude::FluentBuilder, px, relative,
|
||||
};
|
||||
use lsp_types::CodeAction;
|
||||
|
||||
|
|
@ -12,10 +12,9 @@ const MAX_MENU_WIDTH: Pixels = px(320.);
|
|||
const MAX_MENU_HEIGHT: Pixels = px(480.);
|
||||
|
||||
use crate::{
|
||||
actions, h_flex,
|
||||
input::{self, popovers::editor_popover, InputState},
|
||||
ActiveTheme, IndexPath, Selectable, actions, h_flex,
|
||||
input::{self, InputState, popovers::editor_popover},
|
||||
list::{List, ListDelegate, ListEvent, ListState},
|
||||
ActiveTheme, IndexPath, Selectable,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -110,7 +109,12 @@ impl ListDelegate for MenuDelegate {
|
|||
self.items.len()
|
||||
}
|
||||
|
||||
fn render_item(&self, ix: crate::IndexPath, _: &mut Window, _: &mut App) -> Option<Self::Item> {
|
||||
fn render_item(
|
||||
&mut self,
|
||||
ix: crate::IndexPath,
|
||||
_: &mut Window,
|
||||
_: &mut Context<ListState<Self>>,
|
||||
) -> Option<Self::Item> {
|
||||
let item = self.items.get(ix.row)?;
|
||||
Some(MenuItem::new(ix.row, item.clone()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use gpui::{
|
||||
canvas, deferred, div, prelude::FluentBuilder, px, relative, Action, AnyElement, App,
|
||||
AppContext, Bounds, Context, DismissEvent, Empty, Entity, EventEmitter, HighlightStyle,
|
||||
InteractiveElement as _, IntoElement, ParentElement, Pixels, Point, Render, RenderOnce,
|
||||
SharedString, Styled, StyledText, Subscription, Window,
|
||||
Action, AnyElement, App, AppContext, Bounds, Context, DismissEvent, Empty, Entity,
|
||||
EventEmitter, HighlightStyle, InteractiveElement as _, IntoElement, ParentElement, Pixels,
|
||||
Point, Render, RenderOnce, SharedString, Styled, StyledText, Subscription, Window, canvas,
|
||||
deferred, div, prelude::FluentBuilder, px, relative,
|
||||
};
|
||||
use lsp_types::{CompletionItem, CompletionTextEdit};
|
||||
|
||||
|
|
@ -13,15 +13,13 @@ const MAX_MENU_HEIGHT: Pixels = px(240.);
|
|||
const POPOVER_GAP: Pixels = px(4.);
|
||||
|
||||
use crate::{
|
||||
actions, h_flex,
|
||||
ActiveTheme, IndexPath, Selectable, actions, h_flex,
|
||||
input::{
|
||||
self,
|
||||
self, InputState, RopeExt,
|
||||
popovers::{editor_popover, render_markdown},
|
||||
InputState, RopeExt,
|
||||
},
|
||||
label::Label,
|
||||
list::{List, ListDelegate, ListEvent, ListState},
|
||||
ActiveTheme, IndexPath, Selectable,
|
||||
};
|
||||
|
||||
struct ContextMenuDelegate {
|
||||
|
|
@ -137,7 +135,12 @@ impl ListDelegate for ContextMenuDelegate {
|
|||
self.items.len()
|
||||
}
|
||||
|
||||
fn render_item(&self, ix: crate::IndexPath, _: &mut Window, _: &mut App) -> Option<Self::Item> {
|
||||
fn render_item(
|
||||
&mut self,
|
||||
ix: crate::IndexPath,
|
||||
_: &mut Window,
|
||||
_: &mut Context<ListState<Self>>,
|
||||
) -> Option<Self::Item> {
|
||||
let item = self.items.get(ix.row)?;
|
||||
Some(CompletionMenuItem::new(ix.row, item.clone()).highlight_prefix(self.query.clone()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use gpui::{AnyElement, App, Context, IntoElement, ParentElement as _, Styled as _, Task, Window};
|
||||
|
||||
use crate::{
|
||||
h_flex,
|
||||
list::{loading::Loading, ListState},
|
||||
ActiveTheme as _, Icon, IconName, IndexPath, Selectable,
|
||||
ActiveTheme as _, Icon, IconName, IndexPath, Selectable, h_flex,
|
||||
list::{ListState, loading::Loading},
|
||||
};
|
||||
|
||||
/// A delegate for the List.
|
||||
|
|
@ -35,16 +34,21 @@ pub trait ListDelegate: Sized + 'static {
|
|||
/// Return None will skip the item.
|
||||
///
|
||||
/// NOTE: Every item should have same height.
|
||||
fn render_item(&self, ix: IndexPath, window: &mut Window, cx: &mut App) -> Option<Self::Item>;
|
||||
fn render_item(
|
||||
&mut self,
|
||||
ix: IndexPath,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<Self::Item>;
|
||||
|
||||
/// Render the section header at the given index, default is None.
|
||||
///
|
||||
/// NOTE: Every header should have same height.
|
||||
fn render_section_header(
|
||||
&self,
|
||||
&mut self,
|
||||
section: usize,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<impl IntoElement> {
|
||||
None::<AnyElement>
|
||||
}
|
||||
|
|
@ -53,16 +57,20 @@ pub trait ListDelegate: Sized + 'static {
|
|||
///
|
||||
/// NOTE: Every footer should have same height.
|
||||
fn render_section_footer(
|
||||
&self,
|
||||
&mut self,
|
||||
section: usize,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<impl IntoElement> {
|
||||
None::<AnyElement>
|
||||
}
|
||||
|
||||
/// Return a Element to show when list is empty.
|
||||
fn render_empty(&self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
fn render_empty(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> impl IntoElement {
|
||||
h_flex()
|
||||
.size_full()
|
||||
.justify_center()
|
||||
|
|
@ -79,7 +87,11 @@ pub trait ListDelegate: Sized + 'static {
|
|||
/// For example: The last search results, or the last selected item.
|
||||
///
|
||||
/// Default is None, that means no initial state.
|
||||
fn render_initial(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||
fn render_initial(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<AnyElement> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +102,11 @@ pub trait ListDelegate: Sized + 'static {
|
|||
|
||||
/// Returns a Element to show when loading, default is built-in Skeleton
|
||||
/// loading view.
|
||||
fn render_loading(&self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
fn render_loading(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> impl IntoElement {
|
||||
Loading
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ where
|
|||
}
|
||||
|
||||
fn render_list_item(
|
||||
&self,
|
||||
&mut self,
|
||||
ix: IndexPath,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
|
|
@ -474,7 +474,7 @@ where
|
|||
}
|
||||
|
||||
fn render_items(
|
||||
&self,
|
||||
&mut self,
|
||||
items_count: usize,
|
||||
entities_count: usize,
|
||||
window: &mut Window,
|
||||
|
|
@ -526,11 +526,11 @@ where
|
|||
.into_any_element(),
|
||||
),
|
||||
RowEntry::SectionHeader(section_ix) => list
|
||||
.delegate()
|
||||
.delegate_mut()
|
||||
.render_section_header(section_ix, window, cx)
|
||||
.map(|r| r.into_any_element()),
|
||||
RowEntry::SectionFooter(section_ix) => list
|
||||
.delegate()
|
||||
.delegate_mut()
|
||||
.render_section_footer(section_ix, window, cx)
|
||||
.map(|r| r.into_any_element()),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
use gpui::{
|
||||
anchored, canvas, deferred, div, prelude::FluentBuilder, px, rems, AnyElement, App, AppContext,
|
||||
Bounds, ClickEvent, Context, DismissEvent, Edges, ElementId, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, InteractiveElement, IntoElement, KeyBinding, Length, ParentElement, Pixels, Render,
|
||||
RenderOnce, SharedString, StatefulInteractiveElement, StyleRefinement, Styled, Subscription,
|
||||
Task, WeakEntity, Window,
|
||||
AnyElement, App, AppContext, Bounds, ClickEvent, Context, DismissEvent, Edges, ElementId,
|
||||
Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, KeyBinding,
|
||||
Length, ParentElement, Pixels, Render, RenderOnce, SharedString, StatefulInteractiveElement,
|
||||
StyleRefinement, Styled, Subscription, Task, WeakEntity, Window, anchored, canvas, deferred,
|
||||
div, prelude::FluentBuilder, px, rems,
|
||||
};
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::{
|
||||
ActiveTheme, Disableable, Icon, IconName, IndexPath, Selectable, Sizable, Size, StyleSized,
|
||||
StyledExt,
|
||||
actions::{Cancel, Confirm, SelectDown, SelectUp},
|
||||
h_flex,
|
||||
input::clear_button,
|
||||
list::{List, ListDelegate, ListState},
|
||||
v_flex, ActiveTheme, Disableable, Icon, IconName, IndexPath, Selectable, Sizable, Size,
|
||||
StyleSized, StyledExt,
|
||||
v_flex,
|
||||
};
|
||||
|
||||
const CONTEXT: &str = "Select";
|
||||
|
|
@ -167,10 +168,10 @@ where
|
|||
}
|
||||
|
||||
fn render_section_header(
|
||||
&self,
|
||||
&mut self,
|
||||
section: usize,
|
||||
_: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let state = self.state.upgrade()?.read(cx);
|
||||
let Some(item) = self.delegate.section(section) else {
|
||||
|
|
@ -188,7 +189,12 @@ where
|
|||
);
|
||||
}
|
||||
|
||||
fn render_item(&self, ix: IndexPath, window: &mut Window, cx: &mut App) -> Option<Self::Item> {
|
||||
fn render_item(
|
||||
&mut self,
|
||||
ix: IndexPath,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> Option<Self::Item> {
|
||||
let selected = self
|
||||
.selected_index
|
||||
.map_or(false, |selected_index| selected_index == ix);
|
||||
|
|
@ -273,7 +279,11 @@ where
|
|||
self.selected_index = ix;
|
||||
}
|
||||
|
||||
fn render_empty(&self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
fn render_empty(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ListState<Self>>,
|
||||
) -> impl IntoElement {
|
||||
if let Some(empty) = self
|
||||
.state
|
||||
.upgrade()
|
||||
|
|
|
|||
Loading…
Reference in a new issue