dock: Refactor Panel trait to has &mut self and &mut Context<Self>. (#1716)
Continue #1712, #1713 ## Description Also change the `Panel` trait to has `&mut self` and `&mut Context<Self>`. ## Break Changes The methods `title`, `title_prefix`, `set_zoomed`, `set_active`, `dropdown_menu`, `toolbar_buttons`, `on_added_to`, `on_removed` has changed `&self` to `&mut self`, and `cx: &App` to `cx: &mut Context<Self>`. ```diff - fn title(&self, window: &Window, cx: &App) -> AnyElement + fn title(&mut self, window: &Window, cx: &mut Context<Self>) -> AnyElement ```
This commit is contained in:
parent
c0f801dd8c
commit
4ded78ed30
8 changed files with 106 additions and 113 deletions
|
|
@ -94,11 +94,11 @@ impl Panel for ContainerPanel {
|
||||||
"ContainerPanel"
|
"ContainerPanel"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, window: &Window, cx: &App) -> AnyElement {
|
fn title(&mut self, window: &Window, cx: &mut Context<Self>) -> AnyElement {
|
||||||
self.panel.title(window, cx)
|
self.panel.title(window, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title_suffix(&self, _: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
fn title_suffix(&mut self, _: &mut Window, cx: &mut Context<Self>) -> Option<AnyElement> {
|
||||||
Some(
|
Some(
|
||||||
div()
|
div()
|
||||||
.w_24()
|
.w_24()
|
||||||
|
|
|
||||||
|
|
@ -692,7 +692,7 @@ impl Panel for StoryContainer {
|
||||||
"StoryContainer"
|
"StoryContainer"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, _window: &Window, _cx: &App) -> AnyElement {
|
fn title(&mut self, _window: &Window, _cx: &mut Context<Self>) -> AnyElement {
|
||||||
self.name.clone().into_any_element()
|
self.name.clone().into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -722,11 +722,11 @@ impl Panel for StoryContainer {
|
||||||
.contains(&self.name)
|
.contains(&self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_zoomed(&mut self, zoomed: bool, _window: &mut Window, _cx: &mut App) {
|
fn set_zoomed(&mut self, zoomed: bool, _window: &mut Window, _cx: &mut Context<Self>) {
|
||||||
println!("panel: {} zoomed: {}", self.name, zoomed);
|
println!("panel: {} zoomed: {}", self.name, zoomed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_active(&mut self, active: bool, _window: &mut Window, cx: &mut App) {
|
fn set_active(&mut self, active: bool, _window: &mut Window, cx: &mut Context<Self>) {
|
||||||
println!("panel: {} active: {}", self.name, active);
|
println!("panel: {} active: {}", self.name, active);
|
||||||
if let Some(on_active) = self.on_active {
|
if let Some(on_active) = self.on_active {
|
||||||
if let Some(story) = self.story.clone() {
|
if let Some(story) = self.story.clone() {
|
||||||
|
|
@ -735,11 +735,20 @@ impl Panel for StoryContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dropdown_menu(&self, menu: PopupMenu, _window: &Window, _cx: &App) -> PopupMenu {
|
fn dropdown_menu(
|
||||||
|
&mut self,
|
||||||
|
menu: PopupMenu,
|
||||||
|
_window: &mut Window,
|
||||||
|
_cx: &mut Context<Self>,
|
||||||
|
) -> PopupMenu {
|
||||||
menu.menu("Info", Box::new(ShowPanelInfo))
|
menu.menu("Info", Box::new(ShowPanelInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toolbar_buttons(&self, _window: &mut Window, _cx: &mut App) -> Option<Vec<Button>> {
|
fn toolbar_buttons(
|
||||||
|
&mut self,
|
||||||
|
_window: &mut Window,
|
||||||
|
_cx: &mut Context<Self>,
|
||||||
|
) -> Option<Vec<Button>> {
|
||||||
Some(vec![
|
Some(vec![
|
||||||
Button::new("info")
|
Button::new("info")
|
||||||
.icon(IconName::Info)
|
.icon(IconName::Info)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
use std::{collections::HashMap, sync::Arc};
|
|
||||||
|
|
||||||
use crate::{button::Button, dock::TabPanel, menu::PopupMenu};
|
use crate::{button::Button, dock::TabPanel, menu::PopupMenu};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, AnyView, App, AppContext as _, Entity, EntityId, EventEmitter, FocusHandle,
|
AnyElement, AnyView, App, AppContext as _, Context, Entity, EntityId, EventEmitter,
|
||||||
Focusable, Global, Hsla, IntoElement, Render, SharedString, WeakEntity, Window,
|
FocusHandle, Focusable, Global, Hsla, IntoElement, Render, SharedString, WeakEntity, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use super::{DockArea, PanelInfo, PanelState, invalid_panel::InvalidPanel};
|
use super::{DockArea, PanelInfo, PanelState, invalid_panel::InvalidPanel};
|
||||||
|
|
||||||
|
|
@ -68,7 +66,7 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The title of the panel
|
/// The title of the panel
|
||||||
fn title(&self, window: &Window, cx: &App) -> AnyElement {
|
fn title(&mut self, window: &Window, cx: &mut Context<Self>) -> AnyElement {
|
||||||
SharedString::from(t!("Dock.Unnamed")).into_any_element()
|
SharedString::from(t!("Dock.Unnamed")).into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +78,7 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
|
||||||
/// The suffix of the panel title, default is `None`.
|
/// The suffix of the panel title, default is `None`.
|
||||||
///
|
///
|
||||||
/// This is used to add a suffix element to the panel title.
|
/// This is used to add a suffix element to the panel title.
|
||||||
fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
fn title_suffix(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<AnyElement> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,28 +108,43 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
|
||||||
/// This method will be called when the panel is active or inactive.
|
/// This method will be called when the panel is active or inactive.
|
||||||
///
|
///
|
||||||
/// The last_active_panel and current_active_panel will be touched when the panel is active.
|
/// The last_active_panel and current_active_panel will be touched when the panel is active.
|
||||||
fn set_active(&mut self, active: bool, window: &mut Window, cx: &mut App) {}
|
fn set_active(&mut self, active: bool, window: &mut Window, cx: &mut Context<Self>) {}
|
||||||
|
|
||||||
/// Set zoomed state of the panel.
|
/// Set zoomed state of the panel.
|
||||||
///
|
///
|
||||||
/// This method will be called when the panel is zoomed or unzoomed.
|
/// This method will be called when the panel is zoomed or unzoomed.
|
||||||
///
|
///
|
||||||
/// Only current Panel will touch this method.
|
/// Only current Panel will touch this method.
|
||||||
fn set_zoomed(&mut self, zoomed: bool, window: &mut Window, cx: &mut App) {}
|
fn set_zoomed(&mut self, zoomed: bool, window: &mut Window, cx: &mut Context<Self>) {}
|
||||||
|
|
||||||
/// When this Panel is added to a TabPanel, this will be called.
|
/// When this Panel is added to a TabPanel, this will be called.
|
||||||
fn on_added_to(&mut self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App) {}
|
fn on_added_to(
|
||||||
|
&mut self,
|
||||||
|
tab_panel: WeakEntity<TabPanel>,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/// When this Panel is removed from a TabPanel, this will be called.
|
/// When this Panel is removed from a TabPanel, this will be called.
|
||||||
fn on_removed(&mut self, window: &mut Window, cx: &mut App) {}
|
fn on_removed(&mut self, window: &mut Window, cx: &mut Context<Self>) {}
|
||||||
|
|
||||||
/// The addition dropdown menu of the panel, default is `None`.
|
/// The addition dropdown menu of the panel, default is `None`.
|
||||||
fn dropdown_menu(&self, this: PopupMenu, window: &Window, cx: &App) -> PopupMenu {
|
fn dropdown_menu(
|
||||||
|
&mut self,
|
||||||
|
this: PopupMenu,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> PopupMenu {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The addition toolbar buttons of the panel used to show in the right of the title bar, default is `None`.
|
/// The addition toolbar buttons of the panel used to show in the right of the title bar, default is `None`.
|
||||||
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>> {
|
fn toolbar_buttons(
|
||||||
|
&mut self,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Option<Vec<Button>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,7 +165,7 @@ pub trait PanelView: 'static + Send + Sync {
|
||||||
fn panel_name(&self, cx: &App) -> &'static str;
|
fn panel_name(&self, cx: &App) -> &'static str;
|
||||||
fn panel_id(&self, cx: &App) -> EntityId;
|
fn panel_id(&self, cx: &App) -> EntityId;
|
||||||
fn tab_name(&self, cx: &App) -> Option<SharedString>;
|
fn tab_name(&self, cx: &App) -> Option<SharedString>;
|
||||||
fn title(&self, window: &Window, cx: &App) -> AnyElement;
|
fn title(&self, window: &Window, cx: &mut App) -> AnyElement;
|
||||||
fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement>;
|
fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement>;
|
||||||
fn title_style(&self, cx: &App) -> Option<TitleStyle>;
|
fn title_style(&self, cx: &App) -> Option<TitleStyle>;
|
||||||
fn closable(&self, cx: &App) -> bool;
|
fn closable(&self, cx: &App) -> bool;
|
||||||
|
|
@ -162,7 +175,7 @@ pub trait PanelView: 'static + Send + Sync {
|
||||||
fn set_zoomed(&self, zoomed: bool, window: &mut Window, cx: &mut App);
|
fn set_zoomed(&self, zoomed: bool, window: &mut Window, cx: &mut App);
|
||||||
fn on_added_to(&self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App);
|
fn on_added_to(&self, tab_panel: WeakEntity<TabPanel>, window: &mut Window, cx: &mut App);
|
||||||
fn on_removed(&self, window: &mut Window, cx: &mut App);
|
fn on_removed(&self, window: &mut Window, cx: &mut App);
|
||||||
fn dropdown_menu(&self, menu: PopupMenu, window: &Window, cx: &App) -> PopupMenu;
|
fn dropdown_menu(&self, menu: PopupMenu, window: &mut Window, cx: &mut App) -> PopupMenu;
|
||||||
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>>;
|
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>>;
|
||||||
fn view(&self) -> AnyView;
|
fn view(&self) -> AnyView;
|
||||||
fn focus_handle(&self, cx: &App) -> FocusHandle;
|
fn focus_handle(&self, cx: &App) -> FocusHandle;
|
||||||
|
|
@ -183,8 +196,8 @@ impl<T: Panel> PanelView for Entity<T> {
|
||||||
self.read(cx).tab_name(cx)
|
self.read(cx).tab_name(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, window: &Window, cx: &App) -> AnyElement {
|
fn title(&self, window: &Window, cx: &mut App) -> AnyElement {
|
||||||
self.read(cx).title(window, cx)
|
self.update(cx, |this, cx| this.title(window, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||||
|
|
@ -227,8 +240,8 @@ impl<T: Panel> PanelView for Entity<T> {
|
||||||
self.update(cx, |this, cx| this.on_removed(window, cx));
|
self.update(cx, |this, cx| this.on_removed(window, cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dropdown_menu(&self, menu: PopupMenu, window: &Window, cx: &App) -> PopupMenu {
|
fn dropdown_menu(&self, menu: PopupMenu, window: &mut Window, cx: &mut App) -> PopupMenu {
|
||||||
self.read(cx).dropdown_menu(menu, window, cx)
|
self.update(cx, |this, cx| this.dropdown_menu(menu, window, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>> {
|
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>> {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ActiveTheme, AxisExt as _, Placement,
|
||||||
dock::PanelInfo,
|
dock::PanelInfo,
|
||||||
h_flex,
|
h_flex,
|
||||||
resizable::{
|
resizable::{
|
||||||
resizable_panel, ResizablePanelEvent, ResizablePanelGroup, ResizablePanelState,
|
PANEL_MIN_SIZE, ResizablePanelEvent, ResizablePanelGroup, ResizablePanelState,
|
||||||
ResizableState, PANEL_MIN_SIZE,
|
ResizableState, resizable_panel,
|
||||||
},
|
},
|
||||||
ActiveTheme, AxisExt as _, Placement,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{DockArea, Panel, PanelEvent, PanelState, PanelView, TabPanel};
|
use super::{DockArea, Panel, PanelEvent, PanelState, PanelView, TabPanel};
|
||||||
|
|
@ -32,10 +32,10 @@ impl Panel for StackPanel {
|
||||||
"StackPanel"
|
"StackPanel"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, _window: &gpui::Window, _cx: &gpui::App) -> gpui::AnyElement {
|
fn title(&mut self, _window: &gpui::Window, _cx: &mut Context<Self>) -> gpui::AnyElement {
|
||||||
"StackPanel".into_any_element()
|
"StackPanel".into_any_element()
|
||||||
}
|
}
|
||||||
fn set_active(&mut self, active: bool, window: &mut Window, cx: &mut App) {
|
fn set_active(&mut self, active: bool, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
for panel in &self.panels {
|
for panel in &self.panels {
|
||||||
panel.set_active(active, window, cx);
|
panel.set_active(active, window, cx);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ impl Panel for TabPanel {
|
||||||
"TabPanel"
|
"TabPanel"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, window: &Window, cx: &App) -> gpui::AnyElement {
|
fn title(&mut self, window: &Window, cx: &mut Context<Self>) -> gpui::AnyElement {
|
||||||
self.active_panel(cx)
|
self.active_panel(cx)
|
||||||
.map(|panel| panel.title(window, cx))
|
.map(|panel| panel.title(window, cx))
|
||||||
.unwrap_or("Empty Tab".into_any_element())
|
.unwrap_or("Empty Tab".into_any_element())
|
||||||
|
|
@ -121,7 +121,12 @@ impl Panel for TabPanel {
|
||||||
self.visible_panels(cx).next().is_some()
|
self.visible_panels(cx).next().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dropdown_menu(&self, menu: PopupMenu, window: &Window, cx: &App) -> PopupMenu {
|
fn dropdown_menu(
|
||||||
|
&mut self,
|
||||||
|
menu: PopupMenu,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> PopupMenu {
|
||||||
if let Some(panel) = self.active_panel(cx) {
|
if let Some(panel) = self.active_panel(cx) {
|
||||||
panel.dropdown_menu(menu, window, cx)
|
panel.dropdown_menu(menu, window, cx)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -129,7 +134,11 @@ impl Panel for TabPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toolbar_buttons(&self, window: &mut Window, cx: &mut App) -> Option<Vec<Button>> {
|
fn toolbar_buttons(
|
||||||
|
&mut self,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Option<Vec<Button>> {
|
||||||
self.active_panel(cx)
|
self.active_panel(cx)
|
||||||
.and_then(|panel| panel.toolbar_buttons(window, cx))
|
.and_then(|panel| panel.toolbar_buttons(window, cx))
|
||||||
}
|
}
|
||||||
|
|
@ -422,7 +431,7 @@ impl TabPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_toolbar(
|
fn render_toolbar(
|
||||||
&self,
|
&mut self,
|
||||||
state: &TabState,
|
state: &TabState,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
|
|
@ -481,23 +490,24 @@ impl TabPanel {
|
||||||
let zoomable = state.zoomable.map_or(false, |v| v.menu_visible());
|
let zoomable = state.zoomable.map_or(false, |v| v.menu_visible());
|
||||||
let closable = state.closable;
|
let closable = state.closable;
|
||||||
|
|
||||||
move |this, window, cx| {
|
move |menu, window, cx| {
|
||||||
view.read(cx)
|
view.update(cx, |this, cx| {
|
||||||
.dropdown_menu(this, window, cx)
|
this.dropdown_menu(menu, window, cx)
|
||||||
.separator()
|
.separator()
|
||||||
.menu_with_disabled(
|
.menu_with_disabled(
|
||||||
if zoomed {
|
if zoomed {
|
||||||
t!("Dock.Zoom Out")
|
t!("Dock.Zoom Out")
|
||||||
} else {
|
} else {
|
||||||
t!("Dock.Zoom In")
|
t!("Dock.Zoom In")
|
||||||
},
|
},
|
||||||
Box::new(ToggleZoom),
|
Box::new(ToggleZoom),
|
||||||
!zoomable,
|
!zoomable,
|
||||||
)
|
)
|
||||||
.when(closable, |this| {
|
.when(closable, |this| {
|
||||||
this.separator()
|
this.separator()
|
||||||
.menu(t!("Dock.Close"), Box::new(ClosePanel))
|
.menu(t!("Dock.Close"), Box::new(ClosePanel))
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.anchor(Corner::TopRight),
|
.anchor(Corner::TopRight),
|
||||||
|
|
@ -591,7 +601,7 @@ impl TabPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_title_bar(
|
fn render_title_bar(
|
||||||
&self,
|
&mut self,
|
||||||
state: &TabState,
|
state: &TabState,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ impl Panel for Tiles {
|
||||||
"Tiles"
|
"Tiles"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, _window: &Window, _cx: &App) -> AnyElement {
|
fn title(&mut self, _window: &Window, _cx: &mut Context<Self>) -> AnyElement {
|
||||||
"Tiles".into_any_element()
|
"Tiles".into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ impl ListDelegate for MyListDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_item(
|
fn render_item(
|
||||||
&self,
|
&mut self,
|
||||||
ix: IndexPath,
|
ix: IndexPath,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
_cx: &mut App,
|
_cx: &mut Context<TableState<Self>>,
|
||||||
) -> Option<Self::Item> {
|
) -> Option<Self::Item> {
|
||||||
self.items.get(ix.row).map(|item| {
|
self.items.get(ix.row).map(|item| {
|
||||||
ListItem::new(ix)
|
ListItem::new(ix)
|
||||||
|
|
@ -93,10 +93,10 @@ impl ListDelegate for MyListDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_section_header(
|
fn render_section_header(
|
||||||
&self,
|
&mut self,
|
||||||
section: usize,
|
section: usize,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut Context<TableState<Self>>,
|
||||||
) -> Option<impl IntoElement> {
|
) -> Option<impl IntoElement> {
|
||||||
let title = match section {
|
let title = match section {
|
||||||
0 => "Section 1",
|
0 => "Section 1",
|
||||||
|
|
@ -118,10 +118,10 @@ impl ListDelegate for MyListDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_section_footer(
|
fn render_section_footer(
|
||||||
&self,
|
&mut self,
|
||||||
section: usize,
|
section: usize,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut Context<TableState<Self>>,
|
||||||
) -> Option<impl IntoElement> {
|
) -> Option<impl IntoElement> {
|
||||||
Some(
|
Some(
|
||||||
div()
|
div()
|
||||||
|
|
@ -139,10 +139,10 @@ impl ListDelegate for MyListDelegate {
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn render_item(
|
fn render_item(
|
||||||
&self,
|
&mut self,
|
||||||
ix: IndexPath,
|
ix: IndexPath,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut Context<TableState<Self>>,
|
||||||
) -> Option<Self::Item> {
|
) -> Option<Self::Item> {
|
||||||
self.items.get(ix.row).map(|item| {
|
self.items.get(ix.row).map(|item| {
|
||||||
ListItem::new(ix)
|
ListItem::new(ix)
|
||||||
|
|
@ -205,9 +205,9 @@ impl ListDelegate for MyListDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_loading(
|
fn render_loading(
|
||||||
&self,
|
&mut self,
|
||||||
_window: &mut Window,
|
_window: &mut Window,
|
||||||
_cx: &mut App,
|
_cx: &mut Context<TableState<Self>>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
// Custom loading view
|
// Custom loading view
|
||||||
v_flex()
|
v_flex()
|
||||||
|
|
@ -305,7 +305,7 @@ ListSeparatorItem::new()
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl ListDelegate for MyListDelegate {
|
impl ListDelegate for MyListDelegate {
|
||||||
fn render_empty(&self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render_empty(&mut self, _window: &mut Window, cx: &mut Context<TableState<Self>>) -> impl IntoElement {
|
||||||
v_flex()
|
v_flex()
|
||||||
.size_full()
|
.size_full()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
|
|
@ -380,7 +380,7 @@ struct FileInfo {
|
||||||
impl ListDelegate for FileBrowserDelegate {
|
impl ListDelegate for FileBrowserDelegate {
|
||||||
type Item = ListItem;
|
type Item = ListItem;
|
||||||
|
|
||||||
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<TableState<Self>>) -> Option<Self::Item> {
|
||||||
self.files.get(ix.row).map(|file| {
|
self.files.get(ix.row).map(|file| {
|
||||||
let icon = if file.is_directory {
|
let icon = if file.is_directory {
|
||||||
IconName::Folder
|
IconName::Folder
|
||||||
|
|
@ -430,7 +430,7 @@ impl ListDelegate for ContactListDelegate {
|
||||||
self.contacts_by_letter.len()
|
self.contacts_by_letter.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_section_header(&self, section: usize, _window: &mut Window, cx: &mut App) -> Option<impl IntoElement> {
|
fn render_section_header(&mut self, section: usize, _window: &mut Window, cx: &mut Context<TableState<Self>>) -> Option<impl IntoElement> {
|
||||||
let letter = self.contacts_by_letter.keys().nth(section)?;
|
let letter = self.contacts_by_letter.keys().nth(section)?;
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -450,11 +450,3 @@ impl ListDelegate for ContactListDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
- **Virtualization**: Only renders visible items for large datasets
|
|
||||||
- **Efficient Updates**: Optimized re-rendering with proper change detection
|
|
||||||
- **Memory Management**: Automatic cleanup of off-screen items
|
|
||||||
- **Smooth Scrolling**: Hardware-accelerated scrolling with momentum
|
|
||||||
- **Lazy Loading**: Built-in support for infinite scrolling and pagination
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ impl TableDelegate for MyTableDelegate {
|
||||||
&self.columns[col_ix]
|
&self.columns[col_ix]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_td(&self, row_ix: usize, col_ix: usize, _: &mut Window, _: &mut App) -> impl IntoElement {
|
fn render_td(&mut self, row_ix: usize, col_ix: usize, _: &mut Window, _: &mut Context<TableState<Self>>) -> impl IntoElement {
|
||||||
let row = &self.data[row_ix];
|
let row = &self.data[row_ix];
|
||||||
let col = &self.columns[col_ix];
|
let col = &self.columns[col_ix];
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ impl TableDelegate for LargeDataDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only visible rows are rendered
|
// Only visible rows are rendered
|
||||||
fn render_td(&self, row_ix: usize, col_ix: usize, _: &mut Window, _: &mut Context<TableState<Self>>) -> impl IntoElement {
|
fn render_td(&mut self, row_ix: usize, col_ix: usize, _: &mut Window, _: &mut Context<TableState<Self>>) -> impl IntoElement {
|
||||||
// This is only called for visible rows
|
// This is only called for visible rows
|
||||||
// Efficiently render cell content
|
// Efficiently render cell content
|
||||||
let row = &self.data[row_ix];
|
let row = &self.data[row_ix];
|
||||||
|
|
@ -191,26 +191,12 @@ impl TableDelegate for MyTableDelegate {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Row Selection
|
### ContextMenu
|
||||||
|
|
||||||
Handle row selection and interaction:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl TableDelegate for MyTableDelegate {
|
impl TableDelegate for MyTableDelegate {
|
||||||
fn render_tr(&self, row_ix: usize, _: &mut Window, cx: &mut App) -> Stateful<Div> {
|
|
||||||
div()
|
|
||||||
.id(row_ix)
|
|
||||||
.on_click(move |ev, _, _| {
|
|
||||||
if ev.modifiers().secondary() {
|
|
||||||
println!("Right-clicked row {}", row_ix);
|
|
||||||
} else {
|
|
||||||
println!("Selected row {}", row_ix);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context menu for right-click
|
// Context menu for right-click
|
||||||
fn context_menu(&self, row_ix: usize, menu: PopupMenu, _: &mut Window, _: &mut App) -> PopupMenu {
|
fn context_menu(&mut self, row_ix: usize, menu: PopupMenu, _: &mut Window, _: &mut Context<TableState<Self>>) -> PopupMenu {
|
||||||
let row = &self.data[row_ix];
|
let row = &self.data[row_ix];
|
||||||
menu.menu(format!("Edit {}", row.name), Box::new(EditRowAction(row_ix)))
|
menu.menu(format!("Edit {}", row.name), Box::new(EditRowAction(row_ix)))
|
||||||
.menu("Delete", Box::new(DeleteRowAction(row_ix)))
|
.menu("Delete", Box::new(DeleteRowAction(row_ix)))
|
||||||
|
|
@ -218,32 +204,15 @@ impl TableDelegate for MyTableDelegate {
|
||||||
.menu("Duplicate", Box::new(DuplicateRowAction(row_ix)))
|
.menu("Duplicate", Box::new(DuplicateRowAction(row_ix)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle table events
|
|
||||||
cx.subscribe_in(&state, window, |view, table, event, _, cx| {
|
|
||||||
match event {
|
|
||||||
TableEvent::SelectRow(row_ix) => {
|
|
||||||
println!("Row {} selected", row_ix);
|
|
||||||
}
|
|
||||||
TableEvent::DoubleClickedRow(row_ix) => {
|
|
||||||
println!("Row {} double-clicked", row_ix);
|
|
||||||
// Open detail view or edit mode
|
|
||||||
}
|
|
||||||
TableEvent::SelectColumn(col_ix) => {
|
|
||||||
println!("Column {} selected", col_ix);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}).detach();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom Cell Rendering
|
### Cell Rendering
|
||||||
|
|
||||||
Create rich cell content with custom rendering:
|
Create rich cell content with custom rendering:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl TableDelegate for MyTableDelegate {
|
impl TableDelegate for MyTableDelegate {
|
||||||
fn render_td(&self, row_ix: usize, col_ix: usize, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render_td(&mut self, row_ix: usize, col_ix: usize, _: &mut Window, cx: &mut Context<TableState<Self>>) -> impl IntoElement {
|
||||||
let row = &self.data[row_ix];
|
let row = &self.data[row_ix];
|
||||||
let col = &self.columns[col_ix];
|
let col = &self.columns[col_ix];
|
||||||
|
|
||||||
|
|
@ -413,7 +382,7 @@ struct StockData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableDelegate for StockTableDelegate {
|
impl TableDelegate for StockTableDelegate {
|
||||||
fn render_td(&self, row_ix: usize, col_ix: usize, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render_td(&mut self, row_ix: usize, col_ix: usize, _: &mut Window, cx: &mut Context<TableState<Self>>) -> impl IntoElement {
|
||||||
let stock = &self.stocks[row_ix];
|
let stock = &self.stocks[row_ix];
|
||||||
let col = &self.columns[col_ix];
|
let col = &self.columns[col_ix];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue