diff --git a/Cargo.lock b/Cargo.lock index 8d5309c717b75c17a17f9529021fc3083d807db7..2f022289a7cd92b36abd05fbdd7414b20778e854 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -841,17 +841,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "backtrace-on-stack-overflow" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd2d70527f3737a1ad17355e260706c1badebabd1fa06a7a053407380df841b" -dependencies = [ - "backtrace", - "libc", - "nix 0.23.2", -] - [[package]] name = "base64" version = "0.13.1" @@ -5570,19 +5559,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "nix" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.24.3" @@ -8854,45 +8830,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "storybook2" -version = "0.1.0" -dependencies = [ - "anyhow", - "backtrace-on-stack-overflow", - "chrono", - "clap 4.4.4", - "editor2", - "fuzzy2", - "gpui2", - "itertools 0.11.0", - "language2", - "log", - "menu2", - "picker2", - "rust-embed", - "serde", - "settings2", - "simplelog", - "smallvec", - "strum", - "theme", - "theme2", - "ui2", - "util", -] - -[[package]] -name = "storybook3" -version = "0.1.0" -dependencies = [ - "anyhow", - "gpui2", - "settings2", - "theme2", - "ui2", -] - [[package]] name = "stringprep" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index 7c51d32d05314e31a74e5452a938b2839bde4764..8bca4cd84efd60f799e98ea1a4fee46a41218483 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,8 +96,8 @@ members = [ "crates/sqlez", "crates/sqlez_macros", "crates/rich_text", - "crates/storybook2", - "crates/storybook3", + # "crates/storybook2", + # "crates/storybook3", "crates/sum_tree", "crates/terminal", "crates/terminal2", diff --git a/crates/auto_update2/src/update_notification.rs b/crates/auto_update2/src/update_notification.rs index 03a71bcabbba6111953a0754ef3455b317f771dd..e6a22b73248a8fce898c6871abb06d602a3a8e7a 100644 --- a/crates/auto_update2/src/update_notification.rs +++ b/crates/auto_update2/src/update_notification.rs @@ -8,8 +8,8 @@ pub struct UpdateNotification { impl EventEmitter for UpdateNotification {} -impl Render for UpdateNotification { - type Element = Div; +impl Render for UpdateNotification { + type Element = Div; fn render(&mut self, _cx: &mut gpui::ViewContext) -> Self::Element { div().child("Updated zed!") diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 901348d2e29b34454bac87b3dc7dff250b2ab835..6af188dfd200c82d21771a603b905a5e2377f182 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -3294,8 +3294,8 @@ impl CollabPanel { // .with_width(size.x()) // } -impl Render for CollabPanel { - type Element = Focusable>; +impl Render for CollabPanel { + type Element = Focusable
; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 42800269c74c31769f15f1008e15ef301a75808b..2c08840691c9a6120514c7160b3229da6882b968 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -81,8 +81,8 @@ pub struct CollabTitlebarItem { _subscriptions: Vec, } -impl Render for CollabTitlebarItem { - type Element = Stateful>; +impl Render for CollabTitlebarItem { + type Element = Stateful
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { h_stack() @@ -100,7 +100,7 @@ impl Render for CollabTitlebarItem { |s| s.pl(px(68.)), ) .bg(cx.theme().colors().title_bar_background) - .on_click(|_, event, cx| { + .on_click(|event, cx| { if event.up.click_count == 2 { cx.zoom_window(); } @@ -117,14 +117,14 @@ impl Render for CollabTitlebarItem { .variant(ButtonVariant::Ghost) .color(Some(TextColor::Player(0))), ) - .tooltip(move |_, cx| Tooltip::text("Toggle following", cx)), + .tooltip(move |cx| Tooltip::text("Toggle following", cx)), ) // TODO - Add project menu .child( div() .id("titlebar_project_menu_button") .child(Button::new("project_name").variant(ButtonVariant::Ghost)) - .tooltip(move |_, cx| Tooltip::text("Recent Projects", cx)), + .tooltip(move |cx| Tooltip::text("Recent Projects", cx)), ) // TODO - Add git menu .child( @@ -135,7 +135,7 @@ impl Render for CollabTitlebarItem { .variant(ButtonVariant::Ghost) .color(Some(TextColor::Muted)), ) - .tooltip(move |_, cx| { + .tooltip(move |cx| { cx.build_view(|_| { Tooltip::new("Recent Branches") .key_binding(KeyBinding::new(gpui::KeyBinding::new( diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 1296f35c55f05424f13045e2688a740b248b1704..3c6f2fff92150fd302576635e7589eb238e5d01b 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -76,8 +76,8 @@ impl FocusableView for CommandPalette { } } -impl Render for CommandPalette { - type Element = Div; +impl Render for CommandPalette { + type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { v_stack().w_96().child(self.picker.clone()) @@ -140,7 +140,7 @@ impl CommandPaletteDelegate { } impl PickerDelegate for CommandPaletteDelegate { - type ListItem = Div>; + type ListItem = Div; fn placeholder_text(&self) -> Arc { "Execute a command...".into() diff --git a/crates/diagnostics2/src/diagnostics.rs b/crates/diagnostics2/src/diagnostics.rs index 7203748470ce5b5093ca52fc1b13606fcc086600..d19c8f7b12bbed7a95ebce178c927ed9b5f42207 100644 --- a/crates/diagnostics2/src/diagnostics.rs +++ b/crates/diagnostics2/src/diagnostics.rs @@ -16,7 +16,7 @@ use gpui::{ actions, div, AnyElement, AnyView, AppContext, Context, Div, EventEmitter, FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView, InteractiveElement, Model, ParentElement, Render, RenderOnce, SharedString, Styled, Subscription, Task, View, ViewContext, - VisualContext, WeakView, + VisualContext, WeakView, WindowContext, }; use language::{ Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, @@ -90,8 +90,8 @@ struct DiagnosticGroupState { impl EventEmitter for ProjectDiagnosticsEditor {} -impl Render for ProjectDiagnosticsEditor { - type Element = Focusable>; +impl Render for ProjectDiagnosticsEditor { + type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let child = if self.path_states.is_empty() { @@ -109,8 +109,8 @@ impl Render for ProjectDiagnosticsEditor { div() .track_focus(&self.focus_handle) .size_full() - .on_focus_in(Self::focus_in) - .on_action(Self::toggle_warnings) + .on_focus_in(cx.listener(Self::focus_in)) + .on_action(cx.listener(Self::toggle_warnings)) .child(child) } } @@ -662,7 +662,7 @@ impl Item for ProjectDiagnosticsEditor { Some("Project Diagnostics".into()) } - fn tab_content(&self, _detail: Option, _: &AppContext) -> AnyElement { + fn tab_content(&self, _detail: Option, _: &WindowContext) -> AnyElement { render_summary(&self.summary) } @@ -796,11 +796,10 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { }) } -pub(crate) fn render_summary(summary: &DiagnosticSummary) -> AnyElement { +pub(crate) fn render_summary(summary: &DiagnosticSummary) -> AnyElement { if summary.error_count == 0 && summary.warning_count == 0 { let label = Label::new("No problems"); label.render_into_any() - //.render() } else { h_stack() .bg(gpui::red()) diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index 1d5183634f06bba5fd094c62cd8dfbfb753b9983..730927a79ea39d6047299a1577daa450867283c8 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -21,8 +21,8 @@ pub struct DiagnosticIndicator { _observe_active_editor: Option, } -impl Render for DiagnosticIndicator { - type Element = Stateful>; +impl Render for DiagnosticIndicator { + type Element = Stateful
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) { @@ -45,7 +45,7 @@ impl Render for DiagnosticIndicator { h_stack() .id(cx.entity_id()) - .on_action(Self::go_to_next_diagnostic) + .on_action(cx.listener(Self::go_to_next_diagnostic)) .rounded_md() .flex_none() .h(rems(1.375)) @@ -54,14 +54,14 @@ impl Render for DiagnosticIndicator { .bg(cx.theme().colors().ghost_element_background) .hover(|style| style.bg(cx.theme().colors().ghost_element_hover)) .active(|style| style.bg(cx.theme().colors().ghost_element_active)) - .tooltip(|_, cx| Tooltip::text("Project Diagnostics", cx)) - .on_click(|this, _, cx| { + .tooltip(|cx| Tooltip::text("Project Diagnostics", cx)) + .on_click(cx.listener(|this, _, cx| { if let Some(workspace) = this.workspace.upgrade() { workspace.update(cx, |workspace, cx| { ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx) }) } - }) + })) .child(diagnostic_indicator) } } diff --git a/crates/diagnostics2/src/toolbar_controls.rs b/crates/diagnostics2/src/toolbar_controls.rs index a22217f0a1cbdb4ff45faa1bcb340f111ff4ee36..f6c3ed996b6f238accb7afa9b9f83a997a4537c3 100644 --- a/crates/diagnostics2/src/toolbar_controls.rs +++ b/crates/diagnostics2/src/toolbar_controls.rs @@ -7,8 +7,8 @@ pub struct ToolbarControls { editor: Option>, } -impl Render for ToolbarControls { - type Element = Div; +impl Render for ToolbarControls { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let include_warnings = self @@ -26,14 +26,14 @@ impl Render for ToolbarControls { div().child( IconButton::new("toggle-warnings", Icon::ExclamationTriangle) - .tooltip(move |_, cx| Tooltip::text(tooltip, cx)) - .on_click(|this: &mut Self, cx| { + .tooltip(move |cx| Tooltip::text(tooltip, cx)) + .on_click(cx.listener(|this, _, cx| { if let Some(editor) = this.editor.as_ref().and_then(|editor| editor.upgrade()) { editor.update(cx, |editor, cx| { editor.toggle_warnings(&Default::default(), cx); }); } - }), + })), ) } } diff --git a/crates/editor2/src/display_map/block_map.rs b/crates/editor2/src/display_map/block_map.rs index 05106dd2a1f1416529689750f77b2e264f4d5e83..00778c2eddc8eec3cccf3a3a2a9fe89355d26ded 100644 --- a/crates/editor2/src/display_map/block_map.rs +++ b/crates/editor2/src/display_map/block_map.rs @@ -50,7 +50,7 @@ struct BlockRow(u32); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] struct WrapRow(u32); -pub type RenderBlock = Arc AnyElement>; +pub type RenderBlock = Arc AnyElement>; pub struct Block { id: BlockId, @@ -69,7 +69,7 @@ where pub position: P, pub height: u8, pub style: BlockStyle, - pub render: Arc AnyElement>, + pub render: Arc AnyElement>, pub disposition: BlockDisposition, } @@ -947,7 +947,7 @@ impl DerefMut for BlockContext<'_, '_> { } impl Block { - pub fn render(&self, cx: &mut BlockContext) -> AnyElement { + pub fn render(&self, cx: &mut BlockContext) -> AnyElement { self.render.lock()(cx) } diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 5e40f5368ede0af07626e8baf6ef68887be66019..d3bbbff522bd1c6c8697e676c03839ea7e6c0397 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -907,7 +907,7 @@ impl ContextMenu { style: &EditorStyle, workspace: Option>, cx: &mut ViewContext, - ) -> (DisplayPoint, AnyElement) { + ) -> (DisplayPoint, AnyElement) { match self { ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)), ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx), @@ -1223,7 +1223,7 @@ impl CompletionsMenu { style: &EditorStyle, workspace: Option>, cx: &mut ViewContext, - ) -> AnyElement { + ) -> AnyElement { todo!("old implementation below") } @@ -1541,13 +1541,15 @@ impl CodeActionsMenu { mut cursor_position: DisplayPoint, style: &EditorStyle, cx: &mut ViewContext, - ) -> (DisplayPoint, AnyElement) { + ) -> (DisplayPoint, AnyElement) { let actions = self.actions.clone(); let selected_item = self.selected_item; + let element = uniform_list( + cx.view().clone(), "code_actions_menu", self.actions.len(), - move |editor, range, cx| { + move |this, range, cx| { actions[range.clone()] .iter() .enumerate() @@ -1569,17 +1571,20 @@ impl CodeActionsMenu { .bg(colors.element_hover) .text_color(colors.text_accent) }) - .on_mouse_down(MouseButton::Left, move |editor: &mut Editor, _, cx| { - cx.stop_propagation(); - editor - .confirm_code_action( - &ConfirmCodeAction { - item_ix: Some(item_ix), - }, - cx, - ) - .map(|task| task.detach_and_log_err(cx)); - }) + .on_mouse_down( + MouseButton::Left, + cx.listener(move |editor, _, cx| { + cx.stop_propagation(); + editor + .confirm_code_action( + &ConfirmCodeAction { + item_ix: Some(item_ix), + }, + cx, + ) + .map(|task| task.detach_and_log_err(cx)); + }), + ) // TASK: It would be good to make lsp_action.title a SharedString to avoid allocating here. .child(SharedString::from(action.lsp_action.title.clone())) }) @@ -4354,11 +4359,11 @@ impl Editor { style: &EditorStyle, is_active: bool, cx: &mut ViewContext, - ) -> Option> { + ) -> Option { if self.available_code_actions.is_some() { Some( - IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click( - |editor: &mut Editor, cx| { + IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click(cx.listener( + |editor, e, cx| { editor.toggle_code_actions( &ToggleCodeActions { deployed_from_indicator: true, @@ -4366,7 +4371,7 @@ impl Editor { cx, ); }, - ), + )), ) } else { None @@ -4381,7 +4386,7 @@ impl Editor { line_height: Pixels, gutter_margin: Pixels, cx: &mut ViewContext, - ) -> Vec>> { + ) -> Vec> { fold_data .iter() .enumerate() @@ -4394,14 +4399,14 @@ impl Editor { FoldStatus::Foldable => ui::Icon::ChevronDown, }; IconButton::new(ix as usize, icon) - .on_click(move |editor: &mut Editor, cx| match fold_status { + .on_click(cx.listener(move |editor, e, cx| match fold_status { FoldStatus::Folded => { editor.unfold_at(&UnfoldAt { buffer_row }, cx); } FoldStatus::Foldable => { editor.fold_at(&FoldAt { buffer_row }, cx); } - }) + })) .color(ui::TextColor::Muted) }) }) @@ -4422,7 +4427,7 @@ impl Editor { cursor_position: DisplayPoint, style: &EditorStyle, cx: &mut ViewContext, - ) -> Option<(DisplayPoint, AnyElement)> { + ) -> Option<(DisplayPoint, AnyElement)> { self.context_menu.read().as_ref().map(|menu| { menu.render( cursor_position, @@ -7781,7 +7786,7 @@ impl Editor { } div() .pl(cx.anchor_x) - .child(rename_editor.render_with(EditorElement::new( + .child(EditorElement::new( &rename_editor, EditorStyle { background: cx.theme().system().transparent, @@ -7789,10 +7794,12 @@ impl Editor { text: text_style, scrollbar_width: cx.editor_style.scrollbar_width, syntax: cx.editor_style.syntax.clone(), - diagnostic_style: - cx.editor_style.diagnostic_style.clone(), + diagnostic_style: cx + .editor_style + .diagnostic_style + .clone(), }, - ))) + )) .render_into_any() } }), @@ -9382,7 +9389,7 @@ impl FocusableView for Editor { } } -impl Render for Editor { +impl Render for Editor { type Element = EditorElement; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { @@ -9996,10 +10003,10 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend .ml(cx.anchor_x) })) .cursor_pointer() - .on_click(move |_, _, cx| { + .on_click(cx.listener(move |_, _, cx| { cx.write_to_clipboard(ClipboardItem::new(message.clone())); - }) - .tooltip(|_, cx| Tooltip::text("Copy diagnostic message", cx)) + })) + .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)) .render_into_any() }) } diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 42cb47da4951c2f616a470bc589fbd333d922c8c..add9c9ad338541321999701d909a79d31e88f34a 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -23,7 +23,7 @@ use gpui::{ ElementId, ElementInputHandler, Entity, EntityId, Hsla, InteractiveElement, LineLayout, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, - TextRun, TextStyle, View, ViewContext, WindowContext, WrappedLine, + TextRun, TextStyle, View, ViewContext, WeakView, WindowContext, WrappedLine, }; use itertools::Itertools; use language::language_settings::ShowWhitespaceSetting; @@ -112,14 +112,14 @@ impl SelectionLayout { } pub struct EditorElement { - editor_id: EntityId, + editor: View, style: EditorStyle, } impl EditorElement { pub fn new(editor: &View, style: EditorStyle) -> Self { Self { - editor_id: editor.entity_id(), + editor: editor.clone(), style, } } @@ -349,7 +349,7 @@ impl EditorElement { gutter_bounds: Bounds, text_bounds: Bounds, layout: &LayoutState, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let bounds = gutter_bounds.union(&text_bounds); let scroll_top = @@ -460,7 +460,7 @@ impl EditorElement { bounds: Bounds, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let line_height = layout.position_map.line_height; @@ -495,7 +495,7 @@ impl EditorElement { AvailableSpace::MinContent, AvailableSpace::Definite(line_height * 0.55), ); - let fold_indicator_size = fold_indicator.measure(available_space, editor, cx); + let fold_indicator_size = fold_indicator.measure(available_space, cx); let position = point( bounds.size.width - layout.gutter_padding, @@ -506,7 +506,7 @@ impl EditorElement { (line_height - fold_indicator_size.height) / 2., ); let origin = bounds.origin + position + centering_offset; - fold_indicator.draw(origin, available_space, editor, cx); + fold_indicator.draw(origin, available_space, cx); } } @@ -516,7 +516,7 @@ impl EditorElement { AvailableSpace::MinContent, AvailableSpace::Definite(line_height), ); - let indicator_size = button.measure(available_space, editor, cx); + let indicator_size = button.measure(available_space, cx); let mut x = Pixels::ZERO; let mut y = indicator.row as f32 * line_height - scroll_top; @@ -524,15 +524,11 @@ impl EditorElement { x += ((layout.gutter_padding + layout.gutter_margin) - indicator_size.width) / 2.; y += (line_height - indicator_size.height) / 2.; - button.draw(bounds.origin + point(x, y), available_space, editor, cx); + button.draw(bounds.origin + point(x, y), available_space, cx); } } - fn paint_diff_hunks( - bounds: Bounds, - layout: &LayoutState, - cx: &mut ViewContext, - ) { + fn paint_diff_hunks(bounds: Bounds, layout: &LayoutState, cx: &mut WindowContext) { // todo!() // let diff_style = &theme::current(cx).editor.diff.clone(); // let line_height = layout.position_map.line_height; @@ -621,7 +617,7 @@ impl EditorElement { text_bounds: Bounds, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let scroll_position = layout.position_map.snapshot.scroll_position(); let start_row = layout.visible_display_row_range.start; @@ -676,20 +672,22 @@ impl EditorElement { div() .id(fold.id) .size_full() - .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation()) - .on_click(move |editor: &mut Editor, _, cx| { - editor.unfold_ranges( - [fold_range.start..fold_range.end], - true, - false, - cx, - ); - cx.stop_propagation(); - }) + .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation()) + .on_click(cx.listener_for( + &self.editor, + move |editor: &mut Editor, _, cx| { + editor.unfold_ranges( + [fold_range.start..fold_range.end], + true, + false, + cx, + ); + cx.stop_propagation(); + }, + )) .draw( fold_bounds.origin, fold_bounds.size, - editor, cx, |fold_element_state, cx| { if fold_element_state.is_active() { @@ -852,7 +850,7 @@ impl EditorElement { .min((text_bounds.size.height - line_height) / 2.), ), ); - let context_menu_size = context_menu.measure(available_space, editor, cx); + let context_menu_size = context_menu.measure(available_space, cx); let cursor_row_layout = &layout.position_map.line_layouts [(position.row() - start_row) as usize] @@ -876,7 +874,7 @@ impl EditorElement { list_origin.y -= layout.position_map.line_height - list_height; } - context_menu.draw(list_origin, available_space, editor, cx); + context_menu.draw(list_origin, available_space, cx); }) } @@ -1167,7 +1165,7 @@ impl EditorElement { layout: &LayoutState, content_origin: gpui::Point, bounds: Bounds, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let start_row = layout.visible_display_row_range.start; let end_row = layout.visible_display_row_range.end; @@ -1220,7 +1218,7 @@ impl EditorElement { bounds: Bounds, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_left = scroll_position.x * layout.position_map.em_width; @@ -1235,9 +1233,7 @@ impl EditorElement { if !matches!(block.style, BlockStyle::Sticky) { origin += point(-scroll_left, Pixels::ZERO); } - block - .element - .draw(origin, block.available_space, editor, cx); + block.element.draw(origin, block.available_space, cx); } } @@ -2030,12 +2026,10 @@ impl EditorElement { let jump_position = language::ToPoint::to_point(&jump_anchor, buffer); IconButton::new(block_id, ui::Icon::ArrowUpRight) - .on_click(move |editor: &mut Editor, cx| { + .on_click(cx.listener_for(&self.editor, move |editor, e, cx| { editor.jump(jump_path.clone(), jump_position, jump_anchor, cx); - }) - .tooltip(move |_, cx| { - Tooltip::for_action("Jump to Buffer", &OpenExcerpts, cx) - }) + })) + .tooltip(|cx| Tooltip::for_action("Jump to Buffer", &OpenExcerpts, cx)) }); let element = if *starts_new_buffer { @@ -2074,7 +2068,7 @@ impl EditorElement { } }; - let size = element.measure(available_space, editor, cx); + let size = element.measure(available_space, cx); (element, size) }; @@ -2133,47 +2127,61 @@ impl EditorElement { gutter_bounds: Bounds, text_bounds: Bounds, layout: &LayoutState, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); cx.on_mouse_event({ let position_map = layout.position_map.clone(); - move |editor, event: &ScrollWheelEvent, phase, cx| { + let editor = self.editor.clone(); + + move |event: &ScrollWheelEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } - if Self::scroll(editor, event, &position_map, bounds, cx) { + let should_cancel = editor.update(cx, |editor, cx| { + Self::scroll(editor, event, &position_map, bounds, cx) + }); + if should_cancel { cx.stop_propagation(); } } }); + cx.on_mouse_event({ let position_map = layout.position_map.clone(); - move |editor, event: &MouseDownEvent, phase, cx| { + let editor = self.editor.clone(); + + move |event: &MouseDownEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } - if Self::mouse_down(editor, event, &position_map, text_bounds, gutter_bounds, cx) { + let should_cancel = editor.update(cx, |editor, cx| { + Self::mouse_down(editor, event, &position_map, text_bounds, gutter_bounds, cx) + }); + + if should_cancel { cx.stop_propagation() } } }); + cx.on_mouse_event({ let position_map = layout.position_map.clone(); - move |editor, event: &MouseUpEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; - } + let editor = self.editor.clone(); + move |event: &MouseUpEvent, phase, cx| { + let should_cancel = editor.update(cx, |editor, cx| { + Self::mouse_up(editor, event, &position_map, text_bounds, cx) + }); - if Self::mouse_up(editor, event, &position_map, text_bounds, cx) { + if should_cancel { cx.stop_propagation() } } }); - // todo!() + //todo!() // on_down(MouseButton::Right, { // let position_map = layout.position_map.clone(); // move |event, editor, cx| { @@ -2190,12 +2198,17 @@ impl EditorElement { // }); cx.on_mouse_event({ let position_map = layout.position_map.clone(); - move |editor, event: &MouseMoveEvent, phase, cx| { + let editor = self.editor.clone(); + move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } - if Self::mouse_moved(editor, event, &position_map, text_bounds, gutter_bounds, cx) { + let stop_propogating = editor.update(cx, |editor, cx| { + Self::mouse_moved(editor, event, &position_map, text_bounds, gutter_bounds, cx) + }); + + if stop_propogating { cx.stop_propagation() } } @@ -2324,7 +2337,7 @@ impl LineWithInvisibles { content_origin: gpui::Point, whitespace_setting: ShowWhitespaceSetting, selection_ranges: &[Range], - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let line_height = layout.position_map.line_height; let line_y = line_height * row as f32 - layout.position_map.scroll_position.y; @@ -2356,7 +2369,7 @@ impl LineWithInvisibles { row: u32, line_height: Pixels, whitespace_setting: ShowWhitespaceSetting, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let allowed_invisibles_regions = match whitespace_setting { ShowWhitespaceSetting::None => return, @@ -2399,85 +2412,98 @@ enum Invisible { Whitespace { line_offset: usize }, } -impl Element for EditorElement { +impl Element for EditorElement { type State = (); fn layout( &mut self, - editor: &mut Editor, element_state: Option, - cx: &mut gpui::ViewContext, + cx: &mut gpui::WindowContext, ) -> (gpui::LayoutId, Self::State) { - editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. - - let rem_size = cx.rem_size(); - let mut style = Style::default(); - style.size.width = relative(1.).into(); - style.size.height = match editor.mode { - EditorMode::SingleLine => self.style.text.line_height_in_pixels(cx.rem_size()).into(), - EditorMode::AutoHeight { .. } => todo!(), - EditorMode::Full => relative(1.).into(), - }; - let layout_id = cx.request_layout(&style, None); - (layout_id, ()) + self.editor.update(cx, |editor, cx| { + editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. + + let rem_size = cx.rem_size(); + let mut style = Style::default(); + style.size.width = relative(1.).into(); + style.size.height = match editor.mode { + EditorMode::SingleLine => { + self.style.text.line_height_in_pixels(cx.rem_size()).into() + } + EditorMode::AutoHeight { .. } => todo!(), + EditorMode::Full => relative(1.).into(), + }; + let layout_id = cx.request_layout(&style, None); + + (layout_id, ()) + }) } fn paint( mut self, bounds: Bounds, - editor: &mut Editor, element_state: &mut Self::State, - cx: &mut gpui::ViewContext, + cx: &mut gpui::WindowContext, ) { - let mut layout = self.compute_layout(editor, cx, bounds); - let gutter_bounds = Bounds { - origin: bounds.origin, - size: layout.gutter_size, - }; - let text_bounds = Bounds { - origin: gutter_bounds.upper_right(), - size: layout.text_size, - }; - - let dispatch_context = editor.dispatch_context(cx); - cx.with_key_dispatch( - dispatch_context, - Some(editor.focus_handle.clone()), - |_, cx| { - register_actions(cx); + let editor = self.editor.clone(); + editor.update(cx, |editor, cx| { + let mut layout = self.compute_layout(editor, cx, bounds); + let gutter_bounds = Bounds { + origin: bounds.origin, + size: layout.gutter_size, + }; + let text_bounds = Bounds { + origin: gutter_bounds.upper_right(), + size: layout.text_size, + }; - // We call with_z_index to establish a new stacking context. - cx.with_z_index(0, |cx| { - cx.with_content_mask(Some(ContentMask { bounds }), |cx| { - // Paint mouse listeners first, so any elements we paint on top of the editor - // take precedence. - self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); - let input_handler = ElementInputHandler::new(bounds, cx); - cx.handle_input(&editor.focus_handle, input_handler); - - self.paint_background(gutter_bounds, text_bounds, &layout, cx); - if layout.gutter_size.width > Pixels::ZERO { - self.paint_gutter(gutter_bounds, &mut layout, editor, cx); - } - self.paint_text(text_bounds, &mut layout, editor, cx); + let dispatch_context = editor.dispatch_context(cx); + let editor_handle = cx.view().clone(); + cx.with_key_dispatch( + dispatch_context, + Some(editor.focus_handle.clone()), + |_, cx| { + register_actions(&editor_handle, cx); + + // We call with_z_index to establish a new stacking context. + cx.with_z_index(0, |cx| { + cx.with_content_mask(Some(ContentMask { bounds }), |cx| { + // Paint mouse listeners first, so any elements we paint on top of the editor + // take precedence. + self.paint_mouse_listeners( + bounds, + gutter_bounds, + text_bounds, + &layout, + cx, + ); + let input_handler = ElementInputHandler::new(bounds, editor_handle, cx); + cx.handle_input(&editor.focus_handle, input_handler); + + self.paint_background(gutter_bounds, text_bounds, &layout, cx); + if layout.gutter_size.width > Pixels::ZERO { + self.paint_gutter(gutter_bounds, &mut layout, editor, cx); + } + self.paint_text(text_bounds, &mut layout, editor, cx); - if !layout.blocks.is_empty() { - cx.with_element_id(Some("editor_blocks"), |cx| { - self.paint_blocks(bounds, &mut layout, editor, cx); - }) - } + if !layout.blocks.is_empty() { + cx.with_element_id(Some("editor_blocks"), |cx| { + self.paint_blocks(bounds, &mut layout, editor, cx); + }) + } + }); }); - }); - }, - ) + }, + ) + }) } } -impl RenderOnce for EditorElement { +impl RenderOnce for EditorElement { type Element = Self; fn element_id(&self) -> Option { - Some(self.editor_id.into()) + self.editor.element_id() } fn render_once(self) -> Self::Element { @@ -3106,17 +3132,17 @@ pub struct LayoutState { show_scrollbars: bool, is_singleton: bool, max_row: u32, - context_menu: Option<(DisplayPoint, AnyElement)>, + context_menu: Option<(DisplayPoint, AnyElement)>, code_actions_indicator: Option, - // hover_popovers: Option<(DisplayPoint, Vec>)>, - fold_indicators: Vec>>, + // hover_popovers: Option<(DisplayPoint, Vec)>, + fold_indicators: Vec>, tab_invisible: ShapedLine, space_invisible: ShapedLine, } struct CodeActionsIndicator { row: u32, - button: IconButton, + button: IconButton, } struct PositionMap { @@ -3201,7 +3227,7 @@ impl PositionMap { struct BlockLayout { row: u32, - element: AnyElement, + element: AnyElement, available_space: Size, style: BlockStyle, } @@ -3906,187 +3932,191 @@ fn scale_horizontal_mouse_autoscroll_delta(delta: Pixels) -> f32 { // } // } -fn register_actions(cx: &mut ViewContext) { - register_action(cx, Editor::move_left); - register_action(cx, Editor::move_right); - register_action(cx, Editor::move_down); - register_action(cx, Editor::move_up); +fn register_actions(view: &View, cx: &mut WindowContext) { + register_action(view, cx, Editor::move_left); + register_action(view, cx, Editor::move_right); + register_action(view, cx, Editor::move_down); + register_action(view, cx, Editor::move_up); // on_action(cx, Editor::new_file); todo!() // on_action(cx, Editor::new_file_in_direction); todo!() - register_action(cx, Editor::cancel); - register_action(cx, Editor::newline); - register_action(cx, Editor::newline_above); - register_action(cx, Editor::newline_below); - register_action(cx, Editor::backspace); - register_action(cx, Editor::delete); - register_action(cx, Editor::tab); - register_action(cx, Editor::tab_prev); - register_action(cx, Editor::indent); - register_action(cx, Editor::outdent); - register_action(cx, Editor::delete_line); - register_action(cx, Editor::join_lines); - register_action(cx, Editor::sort_lines_case_sensitive); - register_action(cx, Editor::sort_lines_case_insensitive); - register_action(cx, Editor::reverse_lines); - register_action(cx, Editor::shuffle_lines); - register_action(cx, Editor::convert_to_upper_case); - register_action(cx, Editor::convert_to_lower_case); - register_action(cx, Editor::convert_to_title_case); - register_action(cx, Editor::convert_to_snake_case); - register_action(cx, Editor::convert_to_kebab_case); - register_action(cx, Editor::convert_to_upper_camel_case); - register_action(cx, Editor::convert_to_lower_camel_case); - register_action(cx, Editor::delete_to_previous_word_start); - register_action(cx, Editor::delete_to_previous_subword_start); - register_action(cx, Editor::delete_to_next_word_end); - register_action(cx, Editor::delete_to_next_subword_end); - register_action(cx, Editor::delete_to_beginning_of_line); - register_action(cx, Editor::delete_to_end_of_line); - register_action(cx, Editor::cut_to_end_of_line); - register_action(cx, Editor::duplicate_line); - register_action(cx, Editor::move_line_up); - register_action(cx, Editor::move_line_down); - register_action(cx, Editor::transpose); - register_action(cx, Editor::cut); - register_action(cx, Editor::copy); - register_action(cx, Editor::paste); - register_action(cx, Editor::undo); - register_action(cx, Editor::redo); - register_action(cx, Editor::move_page_up); - register_action(cx, Editor::move_page_down); - register_action(cx, Editor::next_screen); - register_action(cx, Editor::scroll_cursor_top); - register_action(cx, Editor::scroll_cursor_center); - register_action(cx, Editor::scroll_cursor_bottom); - register_action(cx, |editor, _: &LineDown, cx| { + register_action(view, cx, Editor::cancel); + register_action(view, cx, Editor::newline); + register_action(view, cx, Editor::newline_above); + register_action(view, cx, Editor::newline_below); + register_action(view, cx, Editor::backspace); + register_action(view, cx, Editor::delete); + register_action(view, cx, Editor::tab); + register_action(view, cx, Editor::tab_prev); + register_action(view, cx, Editor::indent); + register_action(view, cx, Editor::outdent); + register_action(view, cx, Editor::delete_line); + register_action(view, cx, Editor::join_lines); + register_action(view, cx, Editor::sort_lines_case_sensitive); + register_action(view, cx, Editor::sort_lines_case_insensitive); + register_action(view, cx, Editor::reverse_lines); + register_action(view, cx, Editor::shuffle_lines); + register_action(view, cx, Editor::convert_to_upper_case); + register_action(view, cx, Editor::convert_to_lower_case); + register_action(view, cx, Editor::convert_to_title_case); + register_action(view, cx, Editor::convert_to_snake_case); + register_action(view, cx, Editor::convert_to_kebab_case); + register_action(view, cx, Editor::convert_to_upper_camel_case); + register_action(view, cx, Editor::convert_to_lower_camel_case); + register_action(view, cx, Editor::delete_to_previous_word_start); + register_action(view, cx, Editor::delete_to_previous_subword_start); + register_action(view, cx, Editor::delete_to_next_word_end); + register_action(view, cx, Editor::delete_to_next_subword_end); + register_action(view, cx, Editor::delete_to_beginning_of_line); + register_action(view, cx, Editor::delete_to_end_of_line); + register_action(view, cx, Editor::cut_to_end_of_line); + register_action(view, cx, Editor::duplicate_line); + register_action(view, cx, Editor::move_line_up); + register_action(view, cx, Editor::move_line_down); + register_action(view, cx, Editor::transpose); + register_action(view, cx, Editor::cut); + register_action(view, cx, Editor::copy); + register_action(view, cx, Editor::paste); + register_action(view, cx, Editor::undo); + register_action(view, cx, Editor::redo); + register_action(view, cx, Editor::move_page_up); + register_action(view, cx, Editor::move_page_down); + register_action(view, cx, Editor::next_screen); + register_action(view, cx, Editor::scroll_cursor_top); + register_action(view, cx, Editor::scroll_cursor_center); + register_action(view, cx, Editor::scroll_cursor_bottom); + register_action(view, cx, |editor, _: &LineDown, cx| { editor.scroll_screen(&ScrollAmount::Line(1.), cx) }); - register_action(cx, |editor, _: &LineUp, cx| { + register_action(view, cx, |editor, _: &LineUp, cx| { editor.scroll_screen(&ScrollAmount::Line(-1.), cx) }); - register_action(cx, |editor, _: &HalfPageDown, cx| { + register_action(view, cx, |editor, _: &HalfPageDown, cx| { editor.scroll_screen(&ScrollAmount::Page(0.5), cx) }); - register_action(cx, |editor, _: &HalfPageUp, cx| { + register_action(view, cx, |editor, _: &HalfPageUp, cx| { editor.scroll_screen(&ScrollAmount::Page(-0.5), cx) }); - register_action(cx, |editor, _: &PageDown, cx| { + register_action(view, cx, |editor, _: &PageDown, cx| { editor.scroll_screen(&ScrollAmount::Page(1.), cx) }); - register_action(cx, |editor, _: &PageUp, cx| { + register_action(view, cx, |editor, _: &PageUp, cx| { editor.scroll_screen(&ScrollAmount::Page(-1.), cx) }); - register_action(cx, Editor::move_to_previous_word_start); - register_action(cx, Editor::move_to_previous_subword_start); - register_action(cx, Editor::move_to_next_word_end); - register_action(cx, Editor::move_to_next_subword_end); - register_action(cx, Editor::move_to_beginning_of_line); - register_action(cx, Editor::move_to_end_of_line); - register_action(cx, Editor::move_to_start_of_paragraph); - register_action(cx, Editor::move_to_end_of_paragraph); - register_action(cx, Editor::move_to_beginning); - register_action(cx, Editor::move_to_end); - register_action(cx, Editor::select_up); - register_action(cx, Editor::select_down); - register_action(cx, Editor::select_left); - register_action(cx, Editor::select_right); - register_action(cx, Editor::select_to_previous_word_start); - register_action(cx, Editor::select_to_previous_subword_start); - register_action(cx, Editor::select_to_next_word_end); - register_action(cx, Editor::select_to_next_subword_end); - register_action(cx, Editor::select_to_beginning_of_line); - register_action(cx, Editor::select_to_end_of_line); - register_action(cx, Editor::select_to_start_of_paragraph); - register_action(cx, Editor::select_to_end_of_paragraph); - register_action(cx, Editor::select_to_beginning); - register_action(cx, Editor::select_to_end); - register_action(cx, Editor::select_all); - register_action(cx, |editor, action, cx| { + register_action(view, cx, Editor::move_to_previous_word_start); + register_action(view, cx, Editor::move_to_previous_subword_start); + register_action(view, cx, Editor::move_to_next_word_end); + register_action(view, cx, Editor::move_to_next_subword_end); + register_action(view, cx, Editor::move_to_beginning_of_line); + register_action(view, cx, Editor::move_to_end_of_line); + register_action(view, cx, Editor::move_to_start_of_paragraph); + register_action(view, cx, Editor::move_to_end_of_paragraph); + register_action(view, cx, Editor::move_to_beginning); + register_action(view, cx, Editor::move_to_end); + register_action(view, cx, Editor::select_up); + register_action(view, cx, Editor::select_down); + register_action(view, cx, Editor::select_left); + register_action(view, cx, Editor::select_right); + register_action(view, cx, Editor::select_to_previous_word_start); + register_action(view, cx, Editor::select_to_previous_subword_start); + register_action(view, cx, Editor::select_to_next_word_end); + register_action(view, cx, Editor::select_to_next_subword_end); + register_action(view, cx, Editor::select_to_beginning_of_line); + register_action(view, cx, Editor::select_to_end_of_line); + register_action(view, cx, Editor::select_to_start_of_paragraph); + register_action(view, cx, Editor::select_to_end_of_paragraph); + register_action(view, cx, Editor::select_to_beginning); + register_action(view, cx, Editor::select_to_end); + register_action(view, cx, Editor::select_all); + register_action(view, cx, |editor, action, cx| { editor.select_all_matches(action, cx).log_err(); }); - register_action(cx, Editor::select_line); - register_action(cx, Editor::split_selection_into_lines); - register_action(cx, Editor::add_selection_above); - register_action(cx, Editor::add_selection_below); - register_action(cx, |editor, action, cx| { + register_action(view, cx, Editor::select_line); + register_action(view, cx, Editor::split_selection_into_lines); + register_action(view, cx, Editor::add_selection_above); + register_action(view, cx, Editor::add_selection_below); + register_action(view, cx, |editor, action, cx| { editor.select_next(action, cx).log_err(); }); - register_action(cx, |editor, action, cx| { + register_action(view, cx, |editor, action, cx| { editor.select_previous(action, cx).log_err(); }); - register_action(cx, Editor::toggle_comments); - register_action(cx, Editor::select_larger_syntax_node); - register_action(cx, Editor::select_smaller_syntax_node); - register_action(cx, Editor::move_to_enclosing_bracket); - register_action(cx, Editor::undo_selection); - register_action(cx, Editor::redo_selection); - register_action(cx, Editor::go_to_diagnostic); - register_action(cx, Editor::go_to_prev_diagnostic); - register_action(cx, Editor::go_to_hunk); - register_action(cx, Editor::go_to_prev_hunk); - register_action(cx, Editor::go_to_definition); - register_action(cx, Editor::go_to_definition_split); - register_action(cx, Editor::go_to_type_definition); - register_action(cx, Editor::go_to_type_definition_split); - register_action(cx, Editor::fold); - register_action(cx, Editor::fold_at); - register_action(cx, Editor::unfold_lines); - register_action(cx, Editor::unfold_at); - register_action(cx, Editor::fold_selected_ranges); - register_action(cx, Editor::show_completions); - register_action(cx, Editor::toggle_code_actions); + register_action(view, cx, Editor::toggle_comments); + register_action(view, cx, Editor::select_larger_syntax_node); + register_action(view, cx, Editor::select_smaller_syntax_node); + register_action(view, cx, Editor::move_to_enclosing_bracket); + register_action(view, cx, Editor::undo_selection); + register_action(view, cx, Editor::redo_selection); + register_action(view, cx, Editor::go_to_diagnostic); + register_action(view, cx, Editor::go_to_prev_diagnostic); + register_action(view, cx, Editor::go_to_hunk); + register_action(view, cx, Editor::go_to_prev_hunk); + register_action(view, cx, Editor::go_to_definition); + register_action(view, cx, Editor::go_to_definition_split); + register_action(view, cx, Editor::go_to_type_definition); + register_action(view, cx, Editor::go_to_type_definition_split); + register_action(view, cx, Editor::fold); + register_action(view, cx, Editor::fold_at); + register_action(view, cx, Editor::unfold_lines); + register_action(view, cx, Editor::unfold_at); + register_action(view, cx, Editor::fold_selected_ranges); + register_action(view, cx, Editor::show_completions); + register_action(view, cx, Editor::toggle_code_actions); // on_action(cx, Editor::open_excerpts); todo!() - register_action(cx, Editor::toggle_soft_wrap); - register_action(cx, Editor::toggle_inlay_hints); - register_action(cx, Editor::reveal_in_finder); - register_action(cx, Editor::copy_path); - register_action(cx, Editor::copy_relative_path); - register_action(cx, Editor::copy_highlight_json); - register_action(cx, |editor, action, cx| { + register_action(view, cx, Editor::toggle_soft_wrap); + register_action(view, cx, Editor::toggle_inlay_hints); + register_action(view, cx, Editor::reveal_in_finder); + register_action(view, cx, Editor::copy_path); + register_action(view, cx, Editor::copy_relative_path); + register_action(view, cx, Editor::copy_highlight_json); + register_action(view, cx, |editor, action, cx| { editor .format(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - register_action(cx, Editor::restart_language_server); - register_action(cx, Editor::show_character_palette); + register_action(view, cx, Editor::restart_language_server); + register_action(view, cx, Editor::show_character_palette); // on_action(cx, Editor::confirm_completion); todo!() - register_action(cx, |editor, action, cx| { + register_action(view, cx, |editor, action, cx| { editor .confirm_code_action(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - register_action(cx, |editor, action, cx| { + register_action(view, cx, |editor, action, cx| { editor .rename(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - register_action(cx, |editor, action, cx| { + register_action(view, cx, |editor, action, cx| { editor .confirm_rename(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - register_action(cx, |editor, action, cx| { + register_action(view, cx, |editor, action, cx| { editor .find_all_references(action, cx) .map(|task| task.detach_and_log_err(cx)); }); - register_action(cx, Editor::next_copilot_suggestion); - register_action(cx, Editor::previous_copilot_suggestion); - register_action(cx, Editor::copilot_suggest); - register_action(cx, Editor::context_menu_first); - register_action(cx, Editor::context_menu_prev); - register_action(cx, Editor::context_menu_next); - register_action(cx, Editor::context_menu_last); + register_action(view, cx, Editor::next_copilot_suggestion); + register_action(view, cx, Editor::previous_copilot_suggestion); + register_action(view, cx, Editor::copilot_suggest); + register_action(view, cx, Editor::context_menu_first); + register_action(view, cx, Editor::context_menu_prev); + register_action(view, cx, Editor::context_menu_next); + register_action(view, cx, Editor::context_menu_last); } fn register_action( - cx: &mut ViewContext, + view: &View, + cx: &mut WindowContext, listener: impl Fn(&mut Editor, &T, &mut ViewContext) + 'static, ) { - cx.on_action(TypeId::of::(), move |editor, action, phase, cx| { + let view = view.clone(); + cx.on_action(TypeId::of::(), move |action, phase, cx| { let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Bubble { - listener(editor, action, cx); + view.update(cx, |editor, cx| { + listener(editor, action, cx); + }) } }) } diff --git a/crates/editor2/src/hover_popover.rs b/crates/editor2/src/hover_popover.rs index 5c8f403d4f7d768d764f5665f45e31863b00e733..07d108cd6525babd12bf55404ba1b561cf2d67f4 100644 --- a/crates/editor2/src/hover_popover.rs +++ b/crates/editor2/src/hover_popover.rs @@ -422,7 +422,7 @@ impl HoverState { visible_rows: Range, workspace: Option>, cx: &mut ViewContext, - ) -> Option<(DisplayPoint, Vec>)> { + ) -> Option<(DisplayPoint, Vec)> { todo!("old version below") } // // If there is a diagnostic, position the popovers based on that. @@ -504,7 +504,7 @@ pub struct DiagnosticPopover { } impl DiagnosticPopover { - pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext) -> AnyElement { + pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext) -> AnyElement { todo!() // enum PrimaryDiagnostic {} diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index d503ac9f5c50053ec92e31dcda8efc37b5e38e79..01d8d437a3dc83c29d3482eac165d947ac830fdb 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -10,7 +10,7 @@ use futures::future::try_join_all; use gpui::{ div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter, FocusHandle, Model, ParentElement, Pixels, SharedString, Styled, Subscription, Task, View, - ViewContext, VisualContext, WeakView, + ViewContext, VisualContext, WeakView, WindowContext, }; use language::{ proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, OffsetRangeExt, @@ -584,7 +584,7 @@ impl Item for Editor { Some(path.to_string_lossy().to_string().into()) } - fn tab_content(&self, detail: Option, cx: &AppContext) -> AnyElement { + fn tab_content(&self, detail: Option, cx: &WindowContext) -> AnyElement { let theme = cx.theme(); AnyElement::new( diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 2e7655298a4ddd151bc89222f4e34cb1722c6c1d..0b9157bb4ffbcbca8a8d84ee57594ed553dbb342 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -117,8 +117,8 @@ impl FocusableView for FileFinder { self.picker.focus_handle(cx) } } -impl Render for FileFinder { - type Element = Div; +impl Render for FileFinder { + type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { v_stack().w_96().child(self.picker.clone()) @@ -530,7 +530,7 @@ impl FileFinderDelegate { } impl PickerDelegate for FileFinderDelegate { - type ListItem = Div>; + type ListItem = Div; fn placeholder_text(&self) -> Arc { "Search project files...".into() diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index 9b3666ea5c02df827b0d575a8c0c2dee9395e9f6..4ba605c3c96a39e77709758fdf19a91317810090 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -144,15 +144,15 @@ impl GoToLine { } } -impl Render for GoToLine { - type Element = Div; +impl Render for GoToLine { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() .elevation_2(cx) .key_context("GoToLine") - .on_action(Self::cancel) - .on_action(Self::confirm) + .on_action(cx.listener(Self::cancel)) + .on_action(cx.listener(Self::confirm)) .w_96() .child( v_stack() diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index ff601db37262e57bc08436c4344e024c24b59f42..f64512970656909cf3f1a003a9b04acd3cc58eda 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -424,7 +424,7 @@ impl AppContext { /// Opens a new window with the given option and the root view returned by the given function. /// The function is invoked with a `WindowContext`, which can be used to interact with window-specific /// functionality. - pub fn open_window>( + pub fn open_window( &mut self, options: crate::WindowOptions, build_root_view: impl FnOnce(&mut WindowContext) -> View, diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index 3fdff1102adfc5a18dc88d04dbbf93f76ad377f1..cc3b0ace57b37d639656ef06fbc5a2c2344b7877 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -115,7 +115,7 @@ impl AsyncAppContext { build_root_view: impl FnOnce(&mut WindowContext) -> View, ) -> Result> where - V: 'static + Render, + V: 'static + Render, { let app = self .app @@ -286,7 +286,7 @@ impl VisualContext for AsyncWindowContext { build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { self.window .update(self, |_, cx| cx.build_view(build_view_state)) @@ -306,7 +306,7 @@ impl VisualContext for AsyncWindowContext { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { self.window .update(self, |_, cx| cx.replace_root_view(build_view)) diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index ee1c4602ee12ecfd20b103059bcfb394c514b7bb..8fad38c1205088d268280dc03bbc5708a1e4196c 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -126,7 +126,7 @@ impl TestAppContext { pub fn add_window(&mut self, build_window: F) -> WindowHandle where F: FnOnce(&mut ViewContext) -> V, - V: 'static + Render, + V: 'static + Render, { let mut cx = self.app.borrow_mut(); cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window)) @@ -143,7 +143,7 @@ impl TestAppContext { pub fn add_window_view(&mut self, build_window: F) -> (View, &mut VisualTestContext) where F: FnOnce(&mut ViewContext) -> V, - V: 'static + Render, + V: 'static + Render, { let mut cx = self.app.borrow_mut(); let window = cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window)); @@ -569,7 +569,7 @@ impl<'a> VisualContext for VisualTestContext<'a> { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { self.window .update(self.cx, |_, cx| cx.build_view(build_view)) @@ -591,7 +591,7 @@ impl<'a> VisualContext for VisualTestContext<'a> { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { self.window .update(self.cx, |_, cx| cx.replace_root_view(build_view)) @@ -619,7 +619,7 @@ impl<'a> VisualContext for VisualTestContext<'a> { } impl AnyWindowHandle { - pub fn build_view + 'static>( + pub fn build_view( &self, cx: &mut TestAppContext, build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, @@ -630,8 +630,8 @@ impl AnyWindowHandle { pub struct EmptyView {} -impl Render for EmptyView { - type Element = Div; +impl Render for EmptyView { + type Element = Div; fn render(&mut self, _cx: &mut crate::ViewContext) -> Self::Element { div() diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 990de68b063ec3c22bc39dabce0ff4c1d64cb968..5cd015503d2ccb2e9792d0e797b19c12b534b9fc 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,24 +1,25 @@ use crate::{ AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext, + WindowContext, }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; -use std::{any::Any, fmt::Debug, marker::PhantomData}; +use std::{any::Any, fmt::Debug}; -pub trait Render: 'static + Sized { - type Element: Element + 'static; +pub trait Render: 'static + Sized { + type Element: Element + 'static; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element; + fn render(&mut self, cx: &mut ViewContext) -> Self::Element; } -pub trait RenderOnce: Sized { - type Element: Element + 'static; +pub trait RenderOnce: Sized { + type Element: Element + 'static; fn element_id(&self) -> Option; fn render_once(self) -> Self::Element; - fn render_into_any(self) -> AnyElement { + fn render_into_any(self) -> AnyElement { self.render_once().into_any() } @@ -26,9 +27,8 @@ pub trait RenderOnce: Sized { self, origin: Point, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, - f: impl FnOnce(&mut >::State, &mut ViewContext) -> R, + cx: &mut WindowContext, + f: impl FnOnce(&mut ::State, &mut WindowContext) -> R, ) -> R where T: Clone + Default + Debug + Into, @@ -39,13 +39,9 @@ pub trait RenderOnce: Sized { element: Some(element), phase: ElementDrawPhase::Start, }; - let frame_state = DrawableElement::draw( - element, - origin, - available_space.map(Into::into), - view_state, - cx, - ); + + let frame_state = + DrawableElement::draw(element, origin, available_space.map(Into::into), cx); if let Some(mut frame_state) = frame_state { f(&mut frame_state, cx) @@ -61,7 +57,7 @@ pub trait RenderOnce: Sized { fn map(self, f: impl FnOnce(Self) -> U) -> U where Self: Sized, - U: RenderOnce, + U: RenderOnce, { f(self) } @@ -87,70 +83,55 @@ pub trait RenderOnce: Sized { } } -pub trait Element: 'static + RenderOnce { +pub trait Element: 'static + RenderOnce { type State: 'static; fn layout( &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, + state: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State); - fn paint( - self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ); + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext); - fn into_any(self) -> AnyElement { + fn into_any(self) -> AnyElement { AnyElement::new(self) } } -pub trait Component: 'static { - type Rendered: RenderOnce; +pub trait Component: 'static { + type Rendered: RenderOnce; - fn render(self, view: &mut V, cx: &mut ViewContext) -> Self::Rendered; + fn render(self, cx: &mut WindowContext) -> Self::Rendered; } -pub struct CompositeElement { +pub struct CompositeElement { component: Option, - view_type: PhantomData, } -pub struct CompositeElementState> { - rendered_element: Option<>::Element>, - rendered_element_state: <>::Element as Element>::State, +pub struct CompositeElementState { + rendered_element: Option<::Element>, + rendered_element_state: <::Element as Element>::State, } -impl CompositeElement { +impl CompositeElement { pub fn new(component: C) -> Self { CompositeElement { component: Some(component), - view_type: PhantomData, } } } -impl> Element for CompositeElement { - type State = CompositeElementState; +impl Element for CompositeElement { + type State = CompositeElementState; fn layout( &mut self, - view: &mut V, state: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - let mut element = self - .component - .take() - .unwrap() - .render(view, cx) - .render_once(); - let (layout_id, state) = element.layout(view, state.map(|s| s.rendered_element_state), cx); + let mut element = self.component.take().unwrap().render(cx).render_once(); + let (layout_id, state) = element.layout(state.map(|s| s.rendered_element_state), cx); let state = CompositeElementState { rendered_element: Some(element), rendered_element_state: state, @@ -158,23 +139,16 @@ impl> Element for CompositeElement { (layout_id, state) } - fn paint( - self, - bounds: Bounds, - view: &mut V, - state: &mut Self::State, - cx: &mut ViewContext, - ) { - state.rendered_element.take().unwrap().paint( - bounds, - view, - &mut state.rendered_element_state, - cx, - ); + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + state + .rendered_element + .take() + .unwrap() + .paint(bounds, &mut state.rendered_element_state, cx); } } -impl> RenderOnce for CompositeElement { +impl RenderOnce for CompositeElement { type Element = Self; fn element_id(&self) -> Option { @@ -189,10 +163,10 @@ impl> RenderOnce for CompositeElement { #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] pub struct GlobalElementId(SmallVec<[ElementId; 32]>); -pub trait ParentElement { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; +pub trait ParentElement { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; - fn child(mut self, child: impl RenderOnce) -> Self + fn child(mut self, child: impl RenderOnce) -> Self where Self: Sized, { @@ -200,7 +174,7 @@ pub trait ParentElement { self } - fn children(mut self, children: impl IntoIterator>) -> Self + fn children(mut self, children: impl IntoIterator) -> Self where Self: Sized, { @@ -213,26 +187,28 @@ pub trait ParentElement { } } -trait ElementObject { +trait ElementObject { fn element_id(&self) -> Option; - fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId; - fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext); + + fn layout(&mut self, cx: &mut WindowContext) -> LayoutId; + + fn paint(&mut self, cx: &mut WindowContext); + fn measure( &mut self, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Size; + fn draw( &mut self, origin: Point, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ); } -pub struct DrawableElement> { +pub struct DrawableElement { element: Option, phase: ElementDrawPhase, } @@ -253,7 +229,7 @@ enum ElementDrawPhase { } /// A wrapper around an implementer of [Element] that allows it to be drawn in a window. -impl> DrawableElement { +impl DrawableElement { fn new(element: E) -> Self { DrawableElement { element: Some(element), @@ -265,18 +241,15 @@ impl> DrawableElement { self.element.as_ref()?.element_id() } - fn layout(&mut self, state: &mut V, cx: &mut ViewContext) -> LayoutId { + fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id() { let layout_id = cx.with_element_state(id, |element_state, cx| { - self.element - .as_mut() - .unwrap() - .layout(state, element_state, cx) + self.element.as_mut().unwrap().layout(element_state, cx) }); (layout_id, None) } else { - let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(state, None, cx); + let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(None, cx); (layout_id, Some(frame_state)) }; @@ -287,7 +260,7 @@ impl> DrawableElement { layout_id } - fn paint(mut self, view_state: &mut V, cx: &mut ViewContext) -> Option { + fn paint(mut self, cx: &mut WindowContext) -> Option { match self.phase { ElementDrawPhase::LayoutRequested { layout_id, @@ -304,7 +277,7 @@ impl> DrawableElement { self.element .take() .unwrap() - .paint(bounds, view_state, &mut frame_state, cx); + .paint(bounds, &mut frame_state, cx); Some(frame_state) } else { let element_id = self @@ -315,12 +288,10 @@ impl> DrawableElement { .expect("if we don't have frame state, we should have element state"); cx.with_element_state(element_id, |element_state, cx| { let mut element_state = element_state.unwrap(); - self.element.take().unwrap().paint( - bounds, - view_state, - &mut element_state, - cx, - ); + self.element + .take() + .unwrap() + .paint(bounds, &mut element_state, cx); ((), element_state) }); None @@ -334,11 +305,10 @@ impl> DrawableElement { fn measure( &mut self, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Size { if matches!(&self.phase, ElementDrawPhase::Start) { - self.layout(view_state, cx); + self.layout(cx); } let layout_id = match &mut self.phase { @@ -376,22 +346,20 @@ impl> DrawableElement { mut self, origin: Point, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Option { - self.measure(available_space, view_state, cx); - cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx)) + self.measure(available_space, cx); + cx.with_absolute_element_offset(origin, |cx| self.paint(cx)) } } -// impl> Element for DrawableElement { -// type State = >::State; +// impl Element for DrawableElement { +// type State = ::State; // fn layout( // &mut self, -// view_state: &mut V, // element_state: Option, -// cx: &mut ViewContext, +// cx: &mut WindowContext, // ) -> (LayoutId, Self::State) { // } @@ -399,15 +367,14 @@ impl> DrawableElement { // fn paint( // self, // bounds: Bounds, -// view_state: &mut V, // element_state: &mut Self::State, -// cx: &mut ViewContext, +// cx: &mut WindowContext, // ) { // todo!() // } // } -// impl> RenderOnce for DrawableElement { +// impl RenderOnce for DrawableElement { // type Element = Self; // fn element_id(&self) -> Option { @@ -419,81 +386,71 @@ impl> DrawableElement { // } // } -impl ElementObject for Option> +impl ElementObject for Option> where - E: Element, + E: Element, E::State: 'static, { fn element_id(&self) -> Option { self.as_ref().unwrap().element_id() } - fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId { - DrawableElement::layout(self.as_mut().unwrap(), view_state, cx) + fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { + DrawableElement::layout(self.as_mut().unwrap(), cx) } - fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext) { - DrawableElement::paint(self.take().unwrap(), view_state, cx); + fn paint(&mut self, cx: &mut WindowContext) { + DrawableElement::paint(self.take().unwrap(), cx); } fn measure( &mut self, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Size { - DrawableElement::measure(self.as_mut().unwrap(), available_space, view_state, cx) + DrawableElement::measure(self.as_mut().unwrap(), available_space, cx) } fn draw( &mut self, origin: Point, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { - DrawableElement::draw( - self.take().unwrap(), - origin, - available_space, - view_state, - cx, - ); + DrawableElement::draw(self.take().unwrap(), origin, available_space, cx); } } -pub struct AnyElement(Box>); +pub struct AnyElement(Box); -impl AnyElement { +impl AnyElement { pub fn new(element: E) -> Self where - V: 'static, - E: 'static + Element, + E: 'static + Element, E::State: Any, { - AnyElement(Box::new(Some(DrawableElement::new(element))) as Box>) + AnyElement(Box::new(Some(DrawableElement::new(element))) as Box) } pub fn element_id(&self) -> Option { self.0.element_id() } - pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId { - self.0.layout(view_state, cx) + pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { + self.0.layout(cx) } - pub fn paint(mut self, view_state: &mut V, cx: &mut ViewContext) { - self.0.paint(view_state, cx) + pub fn paint(mut self, cx: &mut WindowContext) { + self.0.paint(cx) } /// Initializes this element and performs layout within the given available space to determine its size. pub fn measure( &mut self, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Size { - self.0.measure(available_space, view_state, cx) + self.0.measure(available_space, cx) } /// Initializes this element and performs layout in the available space, then paints it at the given origin. @@ -501,43 +458,35 @@ impl AnyElement { mut self, origin: Point, available_space: Size, - view_state: &mut V, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { - self.0.draw(origin, available_space, view_state, cx) + self.0.draw(origin, available_space, cx) } /// Converts this `AnyElement` into a trait object that can be stored and manipulated. - pub fn into_any(self) -> AnyElement { + pub fn into_any(self) -> AnyElement { AnyElement::new(self) } } -impl Element for AnyElement { +impl Element for AnyElement { type State = (); fn layout( &mut self, - view_state: &mut V, _: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - let layout_id = self.layout(view_state, cx); + let layout_id = self.layout(cx); (layout_id, ()) } - fn paint( - self, - _bounds: Bounds, - view_state: &mut V, - _: &mut Self::State, - cx: &mut ViewContext, - ) { - self.paint(view_state, cx); + fn paint(self, _: Bounds, _: &mut Self::State, cx: &mut WindowContext) { + self.paint(cx); } } -impl RenderOnce for AnyElement { +impl RenderOnce for AnyElement { type Element = Self; fn element_id(&self) -> Option { @@ -549,13 +498,13 @@ impl RenderOnce for AnyElement { } } -// impl Element for Option +// impl Element for Option // where // V: 'static, -// E: Element, -// F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static, +// E: Element, +// F: FnOnce(&mut V, &mut WindowContext<'_, V>) -> E + 'static, // { -// type State = Option>; +// type State = Option; // fn element_id(&self) -> Option { // None @@ -563,9 +512,8 @@ impl RenderOnce for AnyElement { // fn layout( // &mut self, -// view_state: &mut V, // _: Option, -// cx: &mut ViewContext, +// cx: &mut WindowContext, // ) -> (LayoutId, Self::State) { // let render = self.take().unwrap(); // let mut element = (render)(view_state, cx).into_any(); @@ -576,19 +524,18 @@ impl RenderOnce for AnyElement { // fn paint( // self, // _bounds: Bounds, -// view_state: &mut V, // rendered_element: &mut Self::State, -// cx: &mut ViewContext, +// cx: &mut WindowContext, // ) { // rendered_element.take().unwrap().paint(view_state, cx); // } // } -// impl RenderOnce for Option +// impl RenderOnce for Option // where // V: 'static, -// E: Element, -// F: FnOnce(&mut V, &mut ViewContext) -> E + 'static, +// E: Element, +// F: FnOnce(&mut V, &mut WindowContext) -> E + 'static, // { // type Element = Self; diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 8838e5f6edfa0593c0ba24ac59b979a4765a9f61..630b368b9518aa8c8b46708f4f65e4c45bf01928 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -3,7 +3,7 @@ use crate::{ BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, RenderOnce, ScrollWheelEvent, SharedString, - Size, Style, StyleRefinement, Styled, Task, View, ViewContext, Visibility, + Size, Style, StyleRefinement, Styled, Task, View, Visibility, WindowContext, }; use collections::HashMap; use refineable::Refineable; @@ -12,7 +12,6 @@ use std::{ any::{Any, TypeId}, cell::RefCell, fmt::Debug, - marker::PhantomData, mem, rc::Rc, time::Duration, @@ -28,30 +27,24 @@ pub struct GroupStyle { pub style: StyleRefinement, } -pub trait InteractiveElement: Sized + Element { - fn interactivity(&mut self) -> &mut Interactivity; +pub trait InteractiveElement: Sized + Element { + fn interactivity(&mut self) -> &mut Interactivity; fn group(mut self, group: impl Into) -> Self { self.interactivity().group = Some(group.into()); self } - fn id(mut self, id: impl Into) -> Stateful { + fn id(mut self, id: impl Into) -> Stateful { self.interactivity().element_id = Some(id.into()); - Stateful { - element: self, - view_type: PhantomData, - } + Stateful { element: self } } - fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable { + fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable { self.interactivity().focusable = true; self.interactivity().tracked_focus_handle = Some(focus_handle.clone()); - Focusable { - element: self, - view_type: PhantomData, - } + Focusable { element: self } } fn key_context(mut self, key_context: C) -> Self @@ -85,15 +78,15 @@ pub trait InteractiveElement: Sized + Element { fn on_mouse_down( mut self, button: MouseButton, - handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button && bounds.contains_point(&event.position) { - handler(view, event, cx) + (listener)(event, cx) } }, )); @@ -102,12 +95,12 @@ pub trait InteractiveElement: Sized + Element { fn on_any_mouse_down( mut self, - handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx) + (listener)(event, cx) } }, )); @@ -117,43 +110,43 @@ pub trait InteractiveElement: Sized + Element { fn on_mouse_up( mut self, button: MouseButton, - handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_up_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + self.interactivity() + .mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button && bounds.contains_point(&event.position) { - handler(view, event, cx) + (listener)(event, cx) } - }, - )); + })); self } fn on_any_mouse_up( mut self, - handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_up_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + self.interactivity() + .mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx) + (listener)(event, cx) } - }, - )); + })); self } fn on_mouse_down_out( mut self, - handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + move |event, bounds, phase, cx| { if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) { - handler(view, event, cx) + (listener)(event, cx) } }, )); @@ -163,29 +156,29 @@ pub trait InteractiveElement: Sized + Element { fn on_mouse_up_out( mut self, button: MouseButton, - handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_up_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + self.interactivity() + .mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { if phase == DispatchPhase::Capture && event.button == button && !bounds.contains_point(&event.position) { - handler(view, event, cx); + (listener)(event, cx); } - }, - )); + })); self } fn on_mouse_move( mut self, - handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext) + 'static, + listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity().mouse_move_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx); + (listener)(event, cx); } }, )); @@ -194,29 +187,29 @@ pub trait InteractiveElement: Sized + Element { fn on_scroll_wheel( mut self, - handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext) + 'static, + listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity().scroll_wheel_listeners.push(Box::new( - move |view, event, bounds, phase, cx| { + move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx); + (listener)(event, cx); } }, )); self } - /// Capture the given action, fires during the capture phase + /// Capture the given action, before normal action dispatch can fire fn capture_action( mut self, - listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, + listener: impl Fn(&A, &mut WindowContext) + 'static, ) -> Self { self.interactivity().action_listeners.push(( TypeId::of::(), - Box::new(move |view, action, phase, cx| { + Box::new(move |action, phase, cx| { let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Capture { - listener(view, action, cx) + (listener)(action, cx) } }), )); @@ -224,10 +217,7 @@ pub trait InteractiveElement: Sized + Element { } /// Add a listener for the given action, fires during the bubble event phase - fn on_action( - mut self, - listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, - ) -> Self { + fn on_action(mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) -> Self { // NOTE: this debug assert has the side-effect of working around // a bug where a crate consisting only of action definitions does // not register the actions in debug builds: @@ -244,10 +234,10 @@ pub trait InteractiveElement: Sized + Element { // ); self.interactivity().action_listeners.push(( TypeId::of::(), - Box::new(move |view, action, phase, cx| { + Box::new(move |action, phase, cx| { let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Bubble { - listener(view, action, cx) + (listener)(action, cx) } }), )); @@ -256,24 +246,53 @@ pub trait InteractiveElement: Sized + Element { fn on_key_down( mut self, - listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext) + 'static, + listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity() .key_down_listeners - .push(Box::new(move |view, event, phase, cx| { - listener(view, event, phase, cx) + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Bubble { + (listener)(event, cx) + } })); self } - fn on_key_up( + fn capture_key_down( mut self, - listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext) + 'static, + listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static, + ) -> Self { + self.interactivity() + .key_down_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Capture { + listener(event, cx) + } + })); + self + } + + fn on_key_up(mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) -> Self { + self.interactivity() + .key_up_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Bubble { + listener(event, cx) + } + })); + self + } + + fn capture_key_up( + mut self, + listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static, ) -> Self { self.interactivity() .key_up_listeners - .push(Box::new(move |view, event, phase, cx| { - listener(view, event, phase, cx) + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Capture { + listener(event, cx) + } })); self } @@ -302,25 +321,22 @@ pub trait InteractiveElement: Sized + Element { fn on_drop( mut self, - listener: impl Fn(&mut V, View, &mut ViewContext) + 'static, + listener: impl Fn(&View, &mut WindowContext) + 'static, ) -> Self { self.interactivity().drop_listeners.push(( TypeId::of::(), - Box::new(move |view, dragged_view, cx| { - listener(view, dragged_view.downcast().unwrap(), cx); + Box::new(move |dragged_view, cx| { + listener(&dragged_view.downcast().unwrap(), cx); }), )); self } } -pub trait StatefulInteractiveElement>: InteractiveElement { - fn focusable(mut self) -> Focusable { +pub trait StatefulInteractiveElement: InteractiveElement { + fn focusable(mut self) -> Focusable { self.interactivity().focusable = true; - Focusable { - element: self, - view_type: PhantomData, - } + Focusable { element: self } } fn overflow_scroll(mut self) -> Self { @@ -362,40 +378,33 @@ pub trait StatefulInteractiveElement>: InteractiveElem self } - fn on_click( - mut self, - listener: impl Fn(&mut V, &ClickEvent, &mut ViewContext) + 'static, - ) -> Self + fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self where Self: Sized, { self.interactivity() .click_listeners - .push(Box::new(move |view, event, cx| listener(view, event, cx))); + .push(Box::new(move |event, cx| listener(event, cx))); self } - fn on_drag( - mut self, - listener: impl Fn(&mut V, &mut ViewContext) -> View + 'static, - ) -> Self + fn on_drag(mut self, listener: impl Fn(&mut WindowContext) -> View + 'static) -> Self where Self: Sized, - W: 'static + Render, + W: 'static + Render, { debug_assert!( self.interactivity().drag_listener.is_none(), "calling on_drag more than once on the same element is not supported" ); - self.interactivity().drag_listener = - Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag { - view: listener(view_state, cx).into(), - cursor_offset, - })); + self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag { + view: listener(cx).into(), + cursor_offset, + })); self } - fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext)) -> Self + fn on_hover(mut self, listener: impl Fn(&bool, &mut WindowContext) + 'static) -> Self where Self: Sized, { @@ -407,10 +416,7 @@ pub trait StatefulInteractiveElement>: InteractiveElem self } - fn tooltip( - mut self, - build_tooltip: impl Fn(&mut V, &mut ViewContext) -> AnyView + 'static, - ) -> Self + fn tooltip(mut self, build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self where Self: Sized, { @@ -418,14 +424,13 @@ pub trait StatefulInteractiveElement>: InteractiveElem self.interactivity().tooltip_builder.is_none(), "calling tooltip more than once on the same element is not supported" ); - self.interactivity().tooltip_builder = - Some(Rc::new(move |view_state, cx| build_tooltip(view_state, cx))); + self.interactivity().tooltip_builder = Some(Rc::new(build_tooltip)); self } } -pub trait FocusableElement: InteractiveElement { +pub trait FocusableElement: InteractiveElement { fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self where Self: Sized, @@ -442,49 +447,41 @@ pub trait FocusableElement: InteractiveElement { self } - fn on_focus( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self + fn on_focus(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self where Self: Sized, { - self.interactivity().focus_listeners.push(Box::new( - move |view, focus_handle, event, cx| { + self.interactivity() + .focus_listeners + .push(Box::new(move |focus_handle, event, cx| { if event.focused.as_ref() == Some(focus_handle) { - listener(view, event, cx) + listener(event, cx) } - }, - )); + })); self } - fn on_blur( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self + fn on_blur(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self where Self: Sized, { - self.interactivity().focus_listeners.push(Box::new( - move |view, focus_handle, event, cx| { + self.interactivity() + .focus_listeners + .push(Box::new(move |focus_handle, event, cx| { if event.blurred.as_ref() == Some(focus_handle) { - listener(view, event, cx) + listener(event, cx) } - }, - )); + })); self } - fn on_focus_in( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self + fn on_focus_in(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self where Self: Sized, { - self.interactivity().focus_listeners.push(Box::new( - move |view, focus_handle, event, cx| { + self.interactivity() + .focus_listeners + .push(Box::new(move |focus_handle, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -495,22 +492,19 @@ pub trait FocusableElement: InteractiveElement { .map_or(false, |focused| focus_handle.contains(focused, cx)); if !descendant_blurred && descendant_focused { - listener(view, event, cx) + listener(event, cx) } - }, - )); + })); self } - fn on_focus_out( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self + fn on_focus_out(mut self, listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static) -> Self where Self: Sized, { - self.interactivity().focus_listeners.push(Box::new( - move |view, focus_handle, event, cx| { + self.interactivity() + .focus_listeners + .push(Box::new(move |focus_handle, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -520,93 +514,79 @@ pub trait FocusableElement: InteractiveElement { .as_ref() .map_or(false, |focused| focus_handle.contains(focused, cx)); if descendant_blurred && !descendant_focused { - listener(view, event, cx) + listener(event, cx) } - }, - )); + })); self } } -pub type FocusListeners = SmallVec<[FocusListener; 2]>; +pub type FocusListeners = SmallVec<[FocusListener; 2]>; -pub type FocusListener = - Box) + 'static>; +pub type FocusListener = Box; -pub type MouseDownListener = Box< - dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; -pub type MouseUpListener = Box< - dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; +pub type MouseDownListener = + Box, DispatchPhase, &mut WindowContext) + 'static>; +pub type MouseUpListener = + Box, DispatchPhase, &mut WindowContext) + 'static>; -pub type MouseMoveListener = Box< - dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; +pub type MouseMoveListener = + Box, DispatchPhase, &mut WindowContext) + 'static>; -pub type ScrollWheelListener = Box< - dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) - + 'static, ->; +pub type ScrollWheelListener = + Box, DispatchPhase, &mut WindowContext) + 'static>; -pub type ClickListener = Box) + 'static>; +pub type ClickListener = Box; -pub type DragListener = - Box, &mut ViewContext) -> AnyDrag + 'static>; +pub type DragListener = Box, &mut WindowContext) -> AnyDrag + 'static>; -type DropListener = dyn Fn(&mut V, AnyView, &mut ViewContext) + 'static; +type DropListener = dyn Fn(AnyView, &mut WindowContext) + 'static; -pub type HoverListener = Box) + 'static>; +pub type TooltipBuilder = Rc AnyView + 'static>; -pub type TooltipBuilder = Rc) -> AnyView + 'static>; +pub type KeyDownListener = Box; -pub type KeyDownListener = - Box) + 'static>; +pub type KeyUpListener = Box; -pub type KeyUpListener = - Box) + 'static>; +pub type ActionListener = Box; -pub type ActionListener = - Box) + 'static>; - -pub fn div() -> Div { +pub fn div() -> Div { Div { interactivity: Interactivity::default(), children: SmallVec::default(), } } -pub struct Div { - interactivity: Interactivity, - children: SmallVec<[AnyElement; 2]>, +pub struct Div { + interactivity: Interactivity, + children: SmallVec<[AnyElement; 2]>, } -impl Styled for Div { +impl Styled for Div { fn style(&mut self) -> &mut StyleRefinement { &mut self.interactivity.base_style } } -impl InteractiveElement for Div { - fn interactivity(&mut self) -> &mut Interactivity { +impl InteractiveElement for Div { + fn interactivity(&mut self) -> &mut Interactivity { &mut self.interactivity } } -impl ParentElement for Div { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { +impl ParentElement for Div { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } } -impl Element for Div { +impl Element for Div { type State = DivState; fn layout( &mut self, - view_state: &mut V, element_state: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { let mut child_layout_ids = SmallVec::new(); let mut interactivity = mem::take(&mut self.interactivity); @@ -618,7 +598,7 @@ impl Element for Div { child_layout_ids = self .children .iter_mut() - .map(|child| child.layout(view_state, cx)) + .map(|child| child.layout(cx)) .collect::>(); cx.request_layout(&style, child_layout_ids.iter().copied()) }) @@ -637,9 +617,8 @@ impl Element for Div { fn paint( self, bounds: Bounds, - view_state: &mut V, element_state: &mut Self::State, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let mut child_min = point(Pixels::MAX, Pixels::MAX); let mut child_max = Point::default(); @@ -675,7 +654,7 @@ impl Element for Div { cx.with_content_mask(style.overflow_mask(bounds), |cx| { cx.with_element_offset(scroll_offset, |cx| { for child in self.children { - child.paint(view_state, cx); + child.paint(cx); } }) }) @@ -687,7 +666,7 @@ impl Element for Div { } } -impl RenderOnce for Div { +impl RenderOnce for Div { type Element = Self; fn element_id(&self) -> Option { @@ -710,12 +689,12 @@ impl DivState { } } -pub struct Interactivity { +pub struct Interactivity { pub element_id: Option, pub key_context: KeyContext, pub focusable: bool, pub tracked_focus_handle: Option, - pub focus_listeners: FocusListeners, + pub focus_listeners: FocusListeners, pub group: Option, pub base_style: StyleRefinement, pub focus_style: StyleRefinement, @@ -726,29 +705,26 @@ pub struct Interactivity { pub group_active_style: Option, pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, - pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, - pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, - pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, - pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, - pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, - pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - pub drop_listeners: SmallVec<[(TypeId, Box>); 2]>, - pub click_listeners: SmallVec<[ClickListener; 2]>, - pub drag_listener: Option>, - pub hover_listener: Option>, - pub tooltip_builder: Option>, + pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, + pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, + pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, + pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, + pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, + pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, + pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, + pub drop_listeners: SmallVec<[(TypeId, Box); 2]>, + pub click_listeners: SmallVec<[ClickListener; 2]>, + pub drag_listener: Option, + pub hover_listener: Option>, + pub tooltip_builder: Option, } -impl Interactivity -where - V: 'static, -{ +impl Interactivity { pub fn layout( &mut self, element_state: Option, - cx: &mut ViewContext, - f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, + cx: &mut WindowContext, + f: impl FnOnce(Style, &mut WindowContext) -> LayoutId, ) -> (LayoutId, InteractiveElementState) { let mut element_state = element_state.unwrap_or_default(); @@ -774,8 +750,8 @@ where bounds: Bounds, content_size: Size, element_state: &mut InteractiveElementState, - cx: &mut ViewContext, - f: impl FnOnce(Style, Point, &mut ViewContext), + cx: &mut WindowContext, + f: impl FnOnce(Style, Point, &mut WindowContext), ) { let style = self.compute_style(Some(bounds), element_state, cx); @@ -786,27 +762,27 @@ where } } - for listener in self.mouse_down_listeners { - cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); + for listener in self.mouse_down_listeners.drain(..) { + cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { + listener(event, &bounds, phase, cx); }) } - for listener in self.mouse_up_listeners { - cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); + for listener in self.mouse_up_listeners.drain(..) { + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { + listener(event, &bounds, phase, cx); }) } - for listener in self.mouse_move_listeners { - cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); + for listener in self.mouse_move_listeners.drain(..) { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + listener(event, &bounds, phase, cx); }) } - for listener in self.scroll_wheel_listeners { - cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); + for listener in self.scroll_wheel_listeners.drain(..) { + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + listener(event, &bounds, phase, cx); }) } @@ -817,7 +793,7 @@ where if let Some(group_bounds) = hover_group_bounds { let hovered = group_bounds.contains_point(&cx.mouse_position()); - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase == DispatchPhase::Capture { if group_bounds.contains_point(&event.position) != hovered { cx.notify(); @@ -830,7 +806,7 @@ where || (cx.active_drag.is_some() && !self.drag_over_styles.is_empty()) { let hovered = bounds.contains_point(&cx.mouse_position()); - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase == DispatchPhase::Capture { if bounds.contains_point(&event.position) != hovered { cx.notify(); @@ -840,8 +816,8 @@ where } if cx.active_drag.is_some() { - let drop_listeners = self.drop_listeners; - cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| { + let drop_listeners = mem::take(&mut self.drop_listeners); + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { if let Some(drag_state_type) = cx.active_drag.as_ref().map(|drag| drag.view.entity_type()) @@ -852,7 +828,7 @@ where .active_drag .take() .expect("checked for type drag state type above"); - listener(view, drag.view.clone(), cx); + listener(drag.view.clone(), cx); cx.notify(); cx.stop_propagation(); } @@ -872,7 +848,7 @@ where if let Some(drag_listener) = drag_listener { let active_state = element_state.clicked_state.clone(); - cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if cx.active_drag.is_some() { if phase == DispatchPhase::Capture { cx.notify(); @@ -883,7 +859,7 @@ where { *active_state.borrow_mut() = ElementClickedState::default(); let cursor_offset = event.position - bounds.origin; - let drag = drag_listener(view_state, cursor_offset, cx); + let drag = drag_listener(cursor_offset, cx); cx.active_drag = Some(drag); cx.notify(); cx.stop_propagation(); @@ -891,21 +867,21 @@ where }); } - cx.on_mouse_event(move |view_state, event: &MouseUpEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { let mouse_click = ClickEvent { down: mouse_down.clone(), up: event.clone(), }; for listener in &click_listeners { - listener(view_state, &mouse_click, cx); + listener(&mouse_click, cx); } } *pending_mouse_down.borrow_mut() = None; cx.notify(); }); } else { - cx.on_mouse_event(move |_view_state, event: &MouseDownEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { *pending_mouse_down.borrow_mut() = Some(event.clone()); cx.notify(); @@ -918,7 +894,7 @@ where let was_hovered = element_state.hover_state.clone(); let has_mouse_down = element_state.pending_mouse_down.clone(); - cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } @@ -930,7 +906,7 @@ where *was_hovered = is_hovered; drop(was_hovered); - hover_listener(view_state, is_hovered, cx); + hover_listener(&is_hovered, cx); } }); } @@ -939,7 +915,7 @@ where let active_tooltip = element_state.active_tooltip.clone(); let pending_mouse_down = element_state.pending_mouse_down.clone(); - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } @@ -956,12 +932,12 @@ where let active_tooltip = active_tooltip.clone(); let tooltip_builder = tooltip_builder.clone(); - move |view, mut cx| async move { + move |mut cx| async move { cx.background_executor().timer(TOOLTIP_DELAY).await; - view.update(&mut cx, move |view_state, cx| { + cx.update(|_, cx| { active_tooltip.borrow_mut().replace(ActiveTooltip { tooltip: Some(AnyTooltip { - view: tooltip_builder(view_state, cx), + view: tooltip_builder(cx), cursor_offset: cx.mouse_position(), }), _task: None, @@ -979,7 +955,7 @@ where }); let active_tooltip = element_state.active_tooltip.clone(); - cx.on_mouse_event(move |_, _: &MouseDownEvent, _, _| { + cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { active_tooltip.borrow_mut().take(); }); @@ -992,7 +968,7 @@ where let active_state = element_state.clicked_state.clone(); if !active_state.borrow().is_clicked() { - cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { + cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Capture { *active_state.borrow_mut() = ElementClickedState::default(); cx.notify(); @@ -1003,7 +979,7 @@ where .group_active_style .as_ref() .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); - cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| { + cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Bubble { let group = active_group_bounds .map_or(false, |bounds| bounds.contains_point(&down.position)); @@ -1025,7 +1001,7 @@ where let line_height = cx.line_height(); let scroll_max = (content_size - bounds.size).max(&Size::default()); - cx.on_mouse_event(move |_, event: &ScrollWheelEvent, phase, cx| { + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { let mut scroll_offset = scroll_offset.borrow_mut(); let old_scroll_offset = *scroll_offset; @@ -1062,15 +1038,15 @@ where self.key_context.clone(), element_state.focus_handle.clone(), |_, cx| { - for listener in self.key_down_listeners { - cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { - listener(state, event, phase, cx); + for listener in self.key_down_listeners.drain(..) { + cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { + listener(event, phase, cx); }) } - for listener in self.key_up_listeners { - cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { - listener(state, event, phase, cx); + for listener in self.key_up_listeners.drain(..) { + cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { + listener(event, phase, cx); }) } @@ -1081,9 +1057,7 @@ where if let Some(focus_handle) = element_state.focus_handle.as_ref() { for listener in self.focus_listeners { let focus_handle = focus_handle.clone(); - cx.on_focus_changed(move |view, event, cx| { - listener(view, &focus_handle, event, cx) - }); + cx.on_focus_changed(move |event, cx| listener(&focus_handle, event, cx)); } } @@ -1100,7 +1074,7 @@ where &self, bounds: Option>, element_state: &mut InteractiveElementState, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> Style { let mut style = Style::default(); style.refine(&self.base_style); @@ -1171,7 +1145,7 @@ where } } -impl Default for Interactivity { +impl Default for Interactivity { fn default() -> Self { Self { element_id: None, @@ -1259,31 +1233,25 @@ impl GroupBounds { } } -pub struct Focusable { +pub struct Focusable { element: E, - view_type: PhantomData, } -impl, E: InteractiveElement> FocusableElement for Focusable {} +impl FocusableElement for Focusable {} -impl InteractiveElement for Focusable +impl InteractiveElement for Focusable where - V: 'static + Render, - E: InteractiveElement, + E: InteractiveElement, { - fn interactivity(&mut self) -> &mut Interactivity { + fn interactivity(&mut self) -> &mut Interactivity { self.element.interactivity() } } -impl, E: StatefulInteractiveElement> StatefulInteractiveElement - for Focusable -{ -} +impl StatefulInteractiveElement for Focusable {} -impl Styled for Focusable +impl Styled for Focusable where - V: 'static, E: Styled, { fn style(&mut self) -> &mut StyleRefinement { @@ -1291,67 +1259,55 @@ where } } -impl Element for Focusable +impl Element for Focusable where - V: 'static + Render, - E: Element, + E: Element, { type State = E::State; fn layout( &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, + state: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.element.layout(view_state, element_state, cx) + self.element.layout(state, cx) } - fn paint( - self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ) { - self.element.paint(bounds, view_state, element_state, cx) + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + self.element.paint(bounds, state, cx) } } -impl RenderOnce for Focusable +impl RenderOnce for Focusable where - V: 'static + Render, - E: Element, + E: Element, { - type Element = Self; + type Element = E; fn element_id(&self) -> Option { self.element.element_id() } fn render_once(self) -> Self::Element { - self + self.element } } -impl ParentElement for Focusable +impl ParentElement for Focusable where - V: 'static, - E: ParentElement, + E: ParentElement, { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { self.element.children_mut() } } -pub struct Stateful { +pub struct Stateful { element: E, - view_type: PhantomData, } -impl Styled for Stateful +impl Styled for Stateful where - V: 'static, E: Styled, { fn style(&mut self) -> &mut StyleRefinement { @@ -1359,57 +1315,46 @@ where } } -impl StatefulInteractiveElement for Stateful +impl StatefulInteractiveElement for Stateful where - V: 'static, - E: Element, - Self: InteractiveElement, + E: Element, + Self: InteractiveElement, { } -impl InteractiveElement for Stateful +impl InteractiveElement for Stateful where - V: 'static, - E: InteractiveElement, + E: InteractiveElement, { - fn interactivity(&mut self) -> &mut Interactivity { + fn interactivity(&mut self) -> &mut Interactivity { self.element.interactivity() } } -impl> FocusableElement for Stateful {} +impl FocusableElement for Stateful {} -impl Element for Stateful +impl Element for Stateful where - V: 'static, - E: Element, + E: Element, { type State = E::State; fn layout( &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, + state: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.element.layout(view_state, element_state, cx) + self.element.layout(state, cx) } - fn paint( - self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ) { - self.element.paint(bounds, view_state, element_state, cx) + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + self.element.paint(bounds, state, cx) } } -impl RenderOnce for Stateful +impl RenderOnce for Stateful where - V: 'static, - E: Element, + E: Element, { type Element = Self; @@ -1422,12 +1367,11 @@ where } } -impl ParentElement for Stateful +impl ParentElement for Stateful where - V: 'static, - E: ParentElement, + E: ParentElement, { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { self.element.children_mut() } } diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index a6579b022a649fc5cce99a4b188a9bb017cb4a47..3c0f4c00be852ed2df5295ce83d47b583582f747 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -1,17 +1,17 @@ use crate::{ - BorrowWindow, Bounds, Element, InteractiveElement, InteractiveElementState, Interactivity, - LayoutId, Pixels, RenderOnce, SharedString, StyleRefinement, Styled, ViewContext, + Bounds, Element, InteractiveElement, InteractiveElementState, Interactivity, LayoutId, Pixels, + RenderOnce, SharedString, StyleRefinement, Styled, WindowContext, }; use futures::FutureExt; use util::ResultExt; -pub struct Img { - interactivity: Interactivity, +pub struct Img { + interactivity: Interactivity, uri: Option, grayscale: bool, } -pub fn img() -> Img { +pub fn img() -> Img { Img { interactivity: Interactivity::default(), uri: None, @@ -19,10 +19,7 @@ pub fn img() -> Img { } } -impl Img -where - V: 'static, -{ +impl Img { pub fn uri(mut self, uri: impl Into) -> Self { self.uri = Some(uri.into()); self @@ -34,14 +31,13 @@ where } } -impl Element for Img { +impl Element for Img { type State = InteractiveElementState; fn layout( &mut self, - _view_state: &mut V, element_state: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { self.interactivity.layout(element_state, cx, |style, cx| { cx.request_layout(&style, None) @@ -51,9 +47,8 @@ impl Element for Img { fn paint( self, bounds: Bounds, - _view_state: &mut V, element_state: &mut Self::State, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { self.interactivity.paint( bounds, @@ -78,7 +73,7 @@ impl Element for Img { .log_err() }); } else { - cx.spawn(|_, mut cx| async move { + cx.spawn(|mut cx| async move { if image_future.await.ok().is_some() { cx.on_next_frame(|cx| cx.notify()); } @@ -91,7 +86,7 @@ impl Element for Img { } } -impl RenderOnce for Img { +impl RenderOnce for Img { type Element = Self; fn element_id(&self) -> Option { @@ -103,14 +98,14 @@ impl RenderOnce for Img { } } -impl Styled for Img { +impl Styled for Img { fn style(&mut self) -> &mut StyleRefinement { &mut self.interactivity.base_style } } -impl InteractiveElement for Img { - fn interactivity(&mut self) -> &mut Interactivity { +impl InteractiveElement for Img { + fn interactivity(&mut self) -> &mut Interactivity { &mut self.interactivity } } diff --git a/crates/gpui2/src/elements/overlay.rs b/crates/gpui2/src/elements/overlay.rs index 79a3643bdc2bb6e3921e85d9171979bbc8634507..29ac2f00c46b2807c9417a9cbeccfa6dd866ca07 100644 --- a/crates/gpui2/src/elements/overlay.rs +++ b/crates/gpui2/src/elements/overlay.rs @@ -3,15 +3,15 @@ use taffy::style::{Display, Position}; use crate::{ point, AnyElement, BorrowWindow, Bounds, Element, LayoutId, ParentElement, Pixels, Point, - RenderOnce, Size, Style, + RenderOnce, Size, Style, WindowContext, }; pub struct OverlayState { child_layout_ids: SmallVec<[LayoutId; 4]>, } -pub struct Overlay { - children: SmallVec<[AnyElement; 2]>, +pub struct Overlay { + children: SmallVec<[AnyElement; 2]>, anchor_corner: AnchorCorner, fit_mode: OverlayFitMode, // todo!(); @@ -21,7 +21,7 @@ pub struct Overlay { /// overlay gives you a floating element that will avoid overflowing the window bounds. /// Its children should have no margin to avoid measurement issues. -pub fn overlay() -> Overlay { +pub fn overlay() -> Overlay { Overlay { children: SmallVec::new(), anchor_corner: AnchorCorner::TopLeft, @@ -30,7 +30,7 @@ pub fn overlay() -> Overlay { } } -impl Overlay { +impl Overlay { /// Sets which corner of the overlay should be anchored to the current position. pub fn anchor(mut self, anchor: AnchorCorner) -> Self { self.anchor_corner = anchor; @@ -51,25 +51,24 @@ impl Overlay { } } -impl ParentElement for Overlay { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { +impl ParentElement for Overlay { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } } -impl Element for Overlay { +impl Element for Overlay { type State = OverlayState; fn layout( &mut self, - view_state: &mut V, _: Option, - cx: &mut crate::ViewContext, + cx: &mut WindowContext, ) -> (crate::LayoutId, Self::State) { let child_layout_ids = self .children .iter_mut() - .map(|child| child.layout(view_state, cx)) + .map(|child| child.layout(cx)) .collect::>(); let mut overlay_style = Style::default(); @@ -84,9 +83,8 @@ impl Element for Overlay { fn paint( self, bounds: crate::Bounds, - view_state: &mut V, element_state: &mut Self::State, - cx: &mut crate::ViewContext, + cx: &mut WindowContext, ) { if element_state.child_layout_ids.is_empty() { return; @@ -147,13 +145,13 @@ impl Element for Overlay { cx.with_element_offset(desired.origin - bounds.origin, |cx| { for child in self.children { - child.paint(view_state, cx); + child.paint(cx); } }) } } -impl RenderOnce for Overlay { +impl RenderOnce for Overlay { type Element = Self; fn element_id(&self) -> Option { diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index 0940bdd1eb2bf52c18cacc56ba9f8d2776ab43e7..c24e4d9b8b88be501e8744e86982a0cbbc542f76 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -1,49 +1,43 @@ use crate::{ Bounds, Element, ElementId, InteractiveElement, InteractiveElementState, Interactivity, - LayoutId, Pixels, RenderOnce, SharedString, StyleRefinement, Styled, ViewContext, + LayoutId, Pixels, RenderOnce, SharedString, StyleRefinement, Styled, WindowContext, }; use util::ResultExt; -pub struct Svg { - interactivity: Interactivity, +pub struct Svg { + interactivity: Interactivity, path: Option, } -pub fn svg() -> Svg { +pub fn svg() -> Svg { Svg { interactivity: Interactivity::default(), path: None, } } -impl Svg { +impl Svg { pub fn path(mut self, path: impl Into) -> Self { self.path = Some(path.into()); self } } -impl Element for Svg { +impl Element for Svg { type State = InteractiveElementState; fn layout( &mut self, - _view_state: &mut V, element_state: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { self.interactivity.layout(element_state, cx, |style, cx| { cx.request_layout(&style, None) }) } - fn paint( - self, - bounds: Bounds, - _view_state: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ) where + fn paint(self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext) + where Self: Sized, { self.interactivity @@ -55,7 +49,7 @@ impl Element for Svg { } } -impl RenderOnce for Svg { +impl RenderOnce for Svg { type Element = Self; fn element_id(&self) -> Option { @@ -67,14 +61,14 @@ impl RenderOnce for Svg { } } -impl Styled for Svg { +impl Styled for Svg { fn style(&mut self) -> &mut StyleRefinement { &mut self.interactivity.base_style } } -impl InteractiveElement for Svg { - fn interactivity(&mut self) -> &mut Interactivity { +impl InteractiveElement for Svg { + fn interactivity(&mut self) -> &mut Interactivity { &mut self.interactivity } } diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index c68684c8d39dc676294a62cfdd98da8e81bb27b3..05ab85ca63353fa69f76a89b12e421aaf5c31267 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -1,6 +1,6 @@ use crate::{ - BorrowWindow, Bounds, Element, ElementId, LayoutId, Pixels, RenderOnce, SharedString, Size, - TextRun, ViewContext, WindowContext, WrappedLine, + Bounds, Element, ElementId, LayoutId, Pixels, RenderOnce, SharedString, Size, TextRun, + WindowContext, WrappedLine, }; use anyhow::anyhow; use parking_lot::{Mutex, MutexGuard}; @@ -8,32 +8,25 @@ use smallvec::SmallVec; use std::{cell::Cell, rc::Rc, sync::Arc}; use util::ResultExt; -impl Element for &'static str { +impl Element for &'static str { type State = TextState; fn layout( &mut self, - _: &mut V, _: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { let mut state = TextState::default(); let layout_id = state.layout(SharedString::from(*self), None, cx); (layout_id, state) } - fn paint( - self, - bounds: Bounds, - _: &mut V, - state: &mut TextState, - cx: &mut ViewContext, - ) { + fn paint(self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { state.paint(bounds, self, cx) } } -impl RenderOnce for &'static str { +impl RenderOnce for &'static str { type Element = Self; fn element_id(&self) -> Option { @@ -45,37 +38,30 @@ impl RenderOnce for &'static str { } } -impl Element for SharedString { +impl Element for SharedString { type State = TextState; fn layout( &mut self, - _: &mut V, _: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { let mut state = TextState::default(); let layout_id = state.layout(self.clone(), None, cx); (layout_id, state) } - fn paint( - self, - bounds: Bounds, - _: &mut V, - state: &mut TextState, - cx: &mut ViewContext, - ) { + fn paint(self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { let text_str: &str = self.as_ref(); state.paint(bounds, text_str, cx) } } -impl RenderOnce for SharedString { +impl RenderOnce for SharedString { type Element = Self; fn element_id(&self) -> Option { - Some(self.clone().into()) + None } fn render_once(self) -> Self::Element { @@ -102,110 +88,25 @@ impl StyledText { } } -impl Element for StyledText { +impl Element for StyledText { type State = TextState; fn layout( &mut self, - _view: &mut V, - element_state: Option, - cx: &mut ViewContext, + _: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - let element_state = element_state.unwrap_or_default(); - let text_system = cx.text_system().clone(); - let text_style = cx.text_style(); - let font_size = text_style.font_size.to_pixels(cx.rem_size()); - let line_height = text_style - .line_height - .to_pixels(font_size.into(), cx.rem_size()); - let text = self.text.clone(); - - let rem_size = cx.rem_size(); - - let runs = if let Some(runs) = self.runs.take() { - runs - } else { - vec![text_style.to_run(text.len())] - }; - - let layout_id = cx.request_measured_layout(Default::default(), rem_size, { - let element_state = element_state.clone(); - move |known_dimensions, available_space| { - let wrap_width = known_dimensions.width.or(match available_space.width { - crate::AvailableSpace::Definite(x) => Some(x), - _ => None, - }); - - if let Some(text_state) = element_state.0.lock().as_ref() { - if text_state.size.is_some() - && (wrap_width.is_none() || wrap_width == text_state.wrap_width) - { - return text_state.size.unwrap(); - } - } - - let Some(lines) = text_system - .shape_text( - &text, - font_size, - &runs[..], - wrap_width, // Wrap if we know the width. - ) - .log_err() - else { - element_state.lock().replace(TextStateInner { - lines: Default::default(), - line_height, - wrap_width, - size: Some(Size::default()), - }); - return Size::default(); - }; - - let mut size: Size = Size::default(); - for line in &lines { - let line_size = line.size(line_height); - size.height += line_size.height; - size.width = size.width.max(line_size.width); - } - - element_state.lock().replace(TextStateInner { - lines, - line_height, - wrap_width, - size: Some(size), - }); - - size - } - }); - - (layout_id, element_state) + let mut state = TextState::default(); + let layout_id = state.layout(self.text.clone(), self.runs.take(), cx); + (layout_id, state) } - fn paint( - self, - bounds: Bounds, - _: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ) { - let element_state = element_state.lock(); - let element_state = element_state - .as_ref() - .ok_or_else(|| anyhow!("measurement has not been performed on {}", &self.text)) - .unwrap(); - - let line_height = element_state.line_height; - let mut line_origin = bounds.origin; - for line in &element_state.lines { - line.paint(line_origin, line_height, cx).log_err(); - line_origin.y += line.size(line_height).height; - } + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + state.paint(bounds, &self.text, cx) } } -impl RenderOnce for StyledText { +impl RenderOnce for StyledText { type Element = Self; fn element_id(&self) -> Option { @@ -327,7 +228,7 @@ impl TextState { } struct InteractiveText { - id: ElementId, + element_id: ElementId, text: StyledText, } @@ -336,28 +237,27 @@ struct InteractiveTextState { clicked_range_ixs: Rc>>, } -impl Element for InteractiveText { +impl Element for InteractiveText { type State = InteractiveTextState; fn layout( &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, + state: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { if let Some(InteractiveTextState { text_state, clicked_range_ixs, - }) = element_state + }) = state { - let (layout_id, text_state) = self.text.layout(view_state, Some(text_state), cx); + let (layout_id, text_state) = self.text.layout(Some(text_state), cx); let element_state = InteractiveTextState { text_state, clicked_range_ixs, }; (layout_id, element_state) } else { - let (layout_id, text_state) = self.text.layout(view_state, None, cx); + let (layout_id, text_state) = self.text.layout(None, cx); let element_state = InteractiveTextState { text_state, clicked_range_ixs: Rc::default(), @@ -366,23 +266,16 @@ impl Element for InteractiveText { } } - fn paint( - self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::State, - cx: &mut ViewContext, - ) { - self.text - .paint(bounds, view_state, &mut element_state.text_state, cx) + fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + self.text.paint(bounds, &mut state.text_state, cx) } } -impl RenderOnce for InteractiveText { +impl RenderOnce for InteractiveText { type Element = Self; fn element_id(&self) -> Option { - Some(self.id.clone()) + Some(self.element_id.clone()) } fn render_once(self) -> Self::Element { diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index caf18962ec03f76b9c88298b8642109c2ac350dc..b24b3935fab874ff4b8443262170f1fb30248df5 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -1,7 +1,7 @@ use crate::{ - point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Element, ElementId, - InteractiveElement, InteractiveElementState, Interactivity, LayoutId, Pixels, Point, - RenderOnce, Size, StyleRefinement, Styled, ViewContext, + point, px, size, AnyElement, AvailableSpace, Bounds, Element, ElementId, InteractiveElement, + InteractiveElementState, Interactivity, LayoutId, Pixels, Point, Render, RenderOnce, Size, + StyleRefinement, Styled, View, ViewContext, WindowContext, }; use smallvec::SmallVec; use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; @@ -10,31 +10,36 @@ use taffy::style::Overflow; /// uniform_list provides lazy rendering for a set of items that are of uniform height. /// When rendered into a container with overflow-y: hidden and a fixed (or max) height, /// uniform_list will only render the visibile subset of items. -pub fn uniform_list( +pub fn uniform_list( + view: View, id: I, item_count: usize, - f: impl 'static + Fn(&mut V, Range, &mut ViewContext) -> Vec, -) -> UniformList + f: impl 'static + Fn(&mut V, Range, &mut ViewContext) -> Vec, +) -> UniformList where I: Into, - V: 'static, - E: Element, + R: RenderOnce, + V: Render, { let id = id.into(); let mut style = StyleRefinement::default(); style.overflow.y = Some(Overflow::Hidden); + let render_range = move |range, cx: &mut WindowContext| { + view.update(cx, |this, cx| { + f(this, range, cx) + .into_iter() + .map(|component| component.render_into_any()) + .collect() + }) + }; + UniformList { id: id.clone(), style, item_count, item_to_measure_index: 0, - render_items: Box::new(move |view, visible_range, cx| { - f(view, visible_range, cx) - .into_iter() - .map(|component| component.into_any()) - .collect() - }), + render_items: Box::new(render_range), interactivity: Interactivity { element_id: Some(id.into()), ..Default::default() @@ -43,19 +48,14 @@ where } } -pub struct UniformList { +pub struct UniformList { id: ElementId, style: StyleRefinement, item_count: usize, item_to_measure_index: usize, - render_items: Box< - dyn for<'a> Fn( - &'a mut V, - Range, - &'a mut ViewContext, - ) -> SmallVec<[AnyElement; 64]>, - >, - interactivity: Interactivity, + render_items: + Box Fn(Range, &'a mut WindowContext) -> SmallVec<[AnyElement; 64]>>, + interactivity: Interactivity, scroll_handle: Option, } @@ -89,7 +89,7 @@ impl UniformListScrollHandle { } } -impl Styled for UniformList { +impl Styled for UniformList { fn style(&mut self) -> &mut StyleRefinement { &mut self.style } @@ -101,25 +101,24 @@ pub struct UniformListState { item_size: Size, } -impl Element for UniformList { +impl Element for UniformList { type State = UniformListState; fn layout( &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, + state: Option, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { let max_items = self.item_count; let rem_size = cx.rem_size(); - let item_size = element_state + let item_size = state .as_ref() .map(|s| s.item_size) - .unwrap_or_else(|| self.measure_item(view_state, None, cx)); + .unwrap_or_else(|| self.measure_item(None, cx)); let (layout_id, interactive) = self.interactivity - .layout(element_state.map(|s| s.interactive), cx, |style, cx| { + .layout(state.map(|s| s.interactive), cx, |style, cx| { cx.request_measured_layout( style, rem_size, @@ -157,9 +156,8 @@ impl Element for UniformList { fn paint( self, bounds: Bounds, - view_state: &mut V, element_state: &mut Self::State, - cx: &mut ViewContext, + cx: &mut WindowContext, ) { let style = self.interactivity @@ -185,9 +183,7 @@ impl Element for UniformList { .get_or_insert_with(Rc::default) .clone(); - let item_height = self - .measure_item(view_state, Some(padded_bounds.size.width), cx) - .height; + let item_height = self.measure_item(Some(padded_bounds.size.width), cx).height; self.interactivity.paint( bounds, @@ -229,7 +225,7 @@ impl Element for UniformList { self.item_count, ); - let items = (self.render_items)(view_state, visible_range.clone(), cx); + let items = (self.render_items)(visible_range.clone(), cx); cx.with_z_index(1, |cx| { for (item, ix) in items.into_iter().zip(visible_range) { let item_origin = padded_bounds.origin @@ -238,7 +234,7 @@ impl Element for UniformList { AvailableSpace::Definite(padded_bounds.size.width), AvailableSpace::Definite(item_height), ); - item.draw(item_origin, available_space, view_state, cx); + item.draw(item_origin, available_space, cx); } }); } @@ -248,7 +244,7 @@ impl Element for UniformList { } } -impl RenderOnce for UniformList { +impl RenderOnce for UniformList { type Element = Self; fn element_id(&self) -> Option { @@ -260,24 +256,19 @@ impl RenderOnce for UniformList { } } -impl UniformList { +impl UniformList { pub fn with_width_from_item(mut self, item_index: Option) -> Self { self.item_to_measure_index = item_index.unwrap_or(0); self } - fn measure_item( - &self, - view_state: &mut V, - list_width: Option, - cx: &mut ViewContext, - ) -> Size { + fn measure_item(&self, list_width: Option, cx: &mut WindowContext) -> Size { if self.item_count == 0 { return Size::default(); } let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1); - let mut items = (self.render_items)(view_state, item_ix..item_ix + 1, cx); + let mut items = (self.render_items)(item_ix..item_ix + 1, cx); let mut item_to_measure = items.pop().unwrap(); let available_space = size( list_width.map_or(AvailableSpace::MinContent, |width| { @@ -285,7 +276,7 @@ impl UniformList { }), AvailableSpace::MinContent, ); - item_to_measure.measure(available_space, view_state, cx) + item_to_measure.measure(available_space, cx) } pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self { @@ -294,8 +285,8 @@ impl UniformList { } } -impl InteractiveElement for UniformList { - fn interactivity(&mut self) -> &mut crate::Interactivity { +impl InteractiveElement for UniformList { + fn interactivity(&mut self) -> &mut crate::Interactivity { &mut self.interactivity } } diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 98e1c043cd32b4ef168512e58a32d710277731b6..984859f1b005f8fa2edd3256de75c1aa3010ce2b 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -121,7 +121,7 @@ pub trait VisualContext: Context { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render; + V: 'static + Render; fn update_view( &mut self, @@ -134,7 +134,7 @@ pub trait VisualContext: Context { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render; + V: 'static + Render; fn focus_view(&mut self, view: &View) -> Self::Result<()> where diff --git a/crates/gpui2/src/input.rs b/crates/gpui2/src/input.rs index 140f72441794d3b66b562ba4bbc22b74e4131d4d..8592eeffeb3573e4d77e55e252a814630d3c959d 100644 --- a/crates/gpui2/src/input.rs +++ b/crates/gpui2/src/input.rs @@ -1,4 +1,6 @@ -use crate::{AsyncWindowContext, Bounds, Pixels, PlatformInputHandler, View, ViewContext}; +use crate::{ + AsyncWindowContext, Bounds, Pixels, PlatformInputHandler, View, ViewContext, WindowContext, +}; use std::ops::Range; /// Implement this trait to allow views to handle textual input when implementing an editor, field, etc. @@ -43,9 +45,9 @@ pub struct ElementInputHandler { impl ElementInputHandler { /// Used in [Element::paint] with the element's bounds and a view context for its /// containing view. - pub fn new(element_bounds: Bounds, cx: &mut ViewContext) -> Self { + pub fn new(element_bounds: Bounds, view: View, cx: &mut WindowContext) -> Self { ElementInputHandler { - view: cx.view().clone(), + view, element_bounds, cx: cx.to_async(), } diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index e988697ca70a9a3e27e33ece81ccc63b9e95d58f..3dfe0c3b436dda921b8fe10727fdcd548a114e3e 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1,5 +1,6 @@ use crate::{ - div, point, Div, Element, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, ViewContext, + div, point, Div, Element, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, RenderOnce, + ViewContext, }; use smallvec::SmallVec; use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf}; @@ -63,24 +64,24 @@ pub struct Drag where R: Fn(&mut V, &mut ViewContext) -> E, V: 'static, - E: Element<()>, + E: RenderOnce, { pub state: S, pub render_drag_handle: R, - view_type: PhantomData, + view_element_types: PhantomData<(V, E)>, } impl Drag where R: Fn(&mut V, &mut ViewContext) -> E, V: 'static, - E: Element<()>, + E: Element, { pub fn new(state: S, render_drag_handle: R) -> Self { Drag { state, render_drag_handle, - view_type: PhantomData, + view_element_types: Default::default(), } } } @@ -192,8 +193,8 @@ impl Deref for MouseExitEvent { #[derive(Debug, Clone, Default)] pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>); -impl Render for ExternalPaths { - type Element = Div; +impl Render for ExternalPaths { + type Element = Div; fn render(&mut self, _: &mut ViewContext) -> Self::Element { div() // Intentionally left empty because the platform will render icons for the dragged files @@ -286,7 +287,7 @@ pub struct FocusEvent { mod test { use crate::{ self as gpui, div, Div, FocusHandle, InteractiveElement, KeyBinding, Keystroke, - ParentElement, Render, Stateful, TestAppContext, VisualContext, + ParentElement, Render, RenderOnce, Stateful, TestAppContext, VisualContext, }; struct TestView { @@ -297,16 +298,25 @@ mod test { actions!(TestAction); - impl Render for TestView { - type Element = Stateful>; + impl Render for TestView { + type Element = Stateful
; - fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( div() .key_context("parent") - .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) - .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) - .child(div().key_context("nested").track_focus(&self.focus_handle)), + .on_key_down(cx.listener(|this, _, _| this.saw_key_down = true)) + .on_action( + cx.listener(|this: &mut TestView, _: &TestAction, _| { + this.saw_action = true + }), + ) + .child( + div() + .key_context("nested") + .track_focus(&self.focus_handle) + .render_once(), + ), ) } } diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 1b0cabb40154575f60ead9d8404bfa7c0fb5ee34..f958b8b44cc3fbfbdcae462905c936d234643581 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -2,7 +2,7 @@ use crate::{ black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, - SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, + SharedString, Size, SizeRefinement, Styled, TextRun, WindowContext, }; use refineable::{Cascade, Refineable}; use smallvec::SmallVec; @@ -313,7 +313,7 @@ impl Style { } /// Paints the background of an element styled with this style. - pub fn paint(&self, bounds: Bounds, cx: &mut ViewContext) { + pub fn paint(&self, bounds: Bounds, cx: &mut WindowContext) { let rem_size = cx.rem_size(); cx.with_z_index(0, |cx| { diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index a1ed8373c5e18d8ba7c46bd172e8dff314957a91..efa40627ace6ae151c94ff3cc28c7072ede68450 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::{Context, Result}; use std::{ - any::{Any, TypeId}, + any::TypeId, hash::{Hash, Hasher}, }; @@ -59,15 +59,15 @@ impl View { self.model.read(cx) } - pub fn render_with(&self, component: E) -> RenderViewWith - where - E: 'static + Element, - { - RenderViewWith { - view: self.clone(), - element: Some(component), - } - } + // pub fn render_with(&self, component: E) -> RenderViewWith + // where + // E: 'static + Element, + // { + // RenderViewWith { + // view: self.clone(), + // element: Some(component), + // } + // } pub fn focus_handle(&self, cx: &AppContext) -> FocusHandle where @@ -77,6 +77,24 @@ impl View { } } +impl Element for View { + type State = Option; + + fn layout( + &mut self, + _state: Option, + cx: &mut WindowContext, + ) -> (LayoutId, Self::State) { + let mut element = self.update(cx, |view, cx| view.render(cx).into_any()); + let layout_id = element.layout(cx); + (layout_id, Some(element)) + } + + fn paint(self, _: Bounds, element: &mut Self::State, cx: &mut WindowContext) { + element.take().unwrap().paint(cx); + } +} + impl Clone for View { fn clone(&self) -> Self { Self { @@ -151,8 +169,8 @@ impl Eq for WeakView {} #[derive(Clone, Debug)] pub struct AnyView { model: AnyModel, - layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box), - paint: fn(&AnyView, Box, &mut WindowContext), + layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), + paint: fn(&AnyView, AnyElement, &mut WindowContext), } impl AnyView { @@ -199,7 +217,7 @@ impl AnyView { } } -impl> From> for AnyView { +impl From> for AnyView { fn from(value: View) -> Self { AnyView { model: value.model.into_any(), @@ -209,36 +227,24 @@ impl> From> for AnyView { } } -impl, ParentV: 'static> Element for View { - type State = Option>; +impl Element for AnyView { + type State = Option; fn layout( &mut self, - _parent_view: &mut ParentV, _state: Option, - cx: &mut ViewContext, + cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.update(cx, |view, cx| { - let mut element = view.render(cx).into_any(); - let layout_id = element.layout(view, cx); - (layout_id, Some(element)) - }) + let (layout_id, state) = (self.layout)(self, cx); + (layout_id, Some(state)) } - fn paint( - self, - _: Bounds, - _parent: &mut ParentV, - element: &mut Self::State, - cx: &mut ViewContext, - ) { - self.update(cx, |view, cx| { - element.take().unwrap().paint(view, cx); - }); + fn paint(self, _: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + (self.paint)(&self, state.take().unwrap(), cx) } } -impl, ParentV: 'static> RenderOnce for View { +impl RenderOnce for View { type Element = View; fn element_id(&self) -> Option { @@ -250,31 +256,7 @@ impl, ParentV: 'static> RenderOnce for View { } } -impl Element for AnyView { - type State = Option>; - - fn layout( - &mut self, - _view_state: &mut V, - _element_state: Option, - cx: &mut ViewContext, - ) -> (LayoutId, Self::State) { - let (layout_id, rendered_element) = (self.layout)(self, cx); - (layout_id, Some(rendered_element)) - } - - fn paint( - mut self, - _bounds: Bounds, - _view_state: &mut V, - rendered_element: &mut Self::State, - cx: &mut ViewContext, - ) { - (self.paint)(&mut self, rendered_element.take().unwrap(), cx) - } -} - -impl RenderOnce for AnyView { +impl RenderOnce for AnyView { type Element = Self; fn element_id(&self) -> Option { @@ -288,8 +270,8 @@ impl RenderOnce for AnyView { pub struct AnyWeakView { model: AnyWeakModel, - layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box), - paint: fn(&AnyView, Box, &mut WindowContext), + layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), + paint: fn(&AnyView, AnyElement, &mut WindowContext), } impl AnyWeakView { @@ -303,7 +285,7 @@ impl AnyWeakView { } } -impl> From> for AnyWeakView { +impl From> for AnyWeakView { fn from(view: WeakView) -> Self { Self { model: view.model.into(), @@ -313,88 +295,40 @@ impl> From> for AnyWeakView { } } -pub struct RenderViewWith { - view: View, - element: Option, -} - -impl Element for RenderViewWith +impl Render for T where - E: 'static + Element, - ParentV: 'static, - V: 'static, + T: 'static + FnMut(&mut WindowContext) -> E, + E: 'static + Send + Element, { - type State = Option>; + type Element = E; - fn layout( - &mut self, - _: &mut ParentV, - _: Option, - cx: &mut ViewContext, - ) -> (LayoutId, Self::State) { - self.view.update(cx, |view, cx| { - let mut element = self.element.take().unwrap().into_any(); - let layout_id = element.layout(view, cx); - (layout_id, Some(element)) - }) - } - - fn paint( - self, - _: Bounds, - _: &mut ParentV, - element: &mut Self::State, - cx: &mut ViewContext, - ) { - self.view - .update(cx, |view, cx| element.take().unwrap().paint(view, cx)) - } -} - -impl RenderOnce for RenderViewWith -where - E: 'static + Element, - V: 'static, - ParentV: 'static, -{ - type Element = Self; - - fn element_id(&self) -> Option { - self.element.as_ref().unwrap().element_id() - } - - fn render_once(self) -> Self::Element { - self + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + (self)(cx) } } mod any_view { - use crate::{AnyElement, AnyView, BorrowWindow, LayoutId, Render, WindowContext}; - use std::any::Any; + use crate::{AnyElement, AnyView, BorrowWindow, Element, LayoutId, Render, WindowContext}; - pub(crate) fn layout>( + pub(crate) fn layout( view: &AnyView, cx: &mut WindowContext, - ) -> (LayoutId, Box) { + ) -> (LayoutId, AnyElement) { cx.with_element_id(Some(view.model.entity_id), |cx| { let view = view.clone().downcast::().unwrap(); - view.update(cx, |view, cx| { - let mut element = AnyElement::new(view.render(cx)); - let layout_id = element.layout(view, cx); - (layout_id, Box::new(element) as Box) - }) + let mut element = view.update(cx, |view, cx| view.render(cx).into_any()); + let layout_id = element.layout(cx); + (layout_id, element) }) } - pub(crate) fn paint>( + pub(crate) fn paint( view: &AnyView, - element: Box, + element: AnyElement, cx: &mut WindowContext, ) { cx.with_element_id(Some(view.model.entity_id), |cx| { - let view = view.clone().downcast::().unwrap(); - let element = element.downcast::>().unwrap(); - view.update(cx, |view, cx| element.paint(view, cx)) + element.paint(cx); }) } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index c17e7e06f4cf103f7ec23e621ea6f47a57885b9c..483a8fdbee41515f635c2bd3a85baaaa26c3afd8 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -187,7 +187,7 @@ impl Drop for FocusHandle { /// FocusableView allows users of your view to easily /// focus it (using cx.focus_view(view)) -pub trait FocusableView: 'static + Render { +pub trait FocusableView: 'static + Render { fn focus_handle(&self, cx: &AppContext) -> FocusHandle; } @@ -1436,6 +1436,82 @@ impl<'a> WindowContext<'a> { .dispatch_tree .bindings_for_action(action) } + + pub fn listener_for( + &self, + view: &View, + f: impl Fn(&mut V, &E, &mut ViewContext) + 'static, + ) -> impl Fn(&E, &mut WindowContext) + 'static { + let view = view.downgrade(); + move |e: &E, cx: &mut WindowContext| { + view.update(cx, |view, cx| f(view, e, cx)).ok(); + } + } + + pub fn constructor_for( + &self, + view: &View, + f: impl Fn(&mut V, &mut ViewContext) -> R + 'static, + ) -> impl Fn(&mut WindowContext) -> R + 'static { + let view = view.clone(); + move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx)) + } + + //========== ELEMENT RELATED FUNCTIONS =========== + pub fn with_key_dispatch( + &mut self, + context: KeyContext, + focus_handle: Option, + f: impl FnOnce(Option, &mut Self) -> R, + ) -> R { + let window = &mut self.window; + window + .current_frame + .dispatch_tree + .push_node(context.clone()); + if let Some(focus_handle) = focus_handle.as_ref() { + window + .current_frame + .dispatch_tree + .make_focusable(focus_handle.id); + } + let result = f(focus_handle, self); + + self.window.current_frame.dispatch_tree.pop_node(); + + result + } + + /// Register a focus listener for the current frame only. It will be cleared + /// on the next frame render. You should use this method only from within elements, + /// and we may want to enforce that better via a different context type. + // todo!() Move this to `FrameContext` to emphasize its individuality? + pub fn on_focus_changed( + &mut self, + listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static, + ) { + self.window + .current_frame + .focus_listeners + .push(Box::new(move |event, cx| { + listener(event, cx); + })); + } + + /// Set an input handler, such as [ElementInputHandler], which interfaces with the + /// platform to receive textual input with proper integration with concerns such + /// as IME interactions. + pub fn handle_input( + &mut self, + focus_handle: &FocusHandle, + input_handler: impl PlatformInputHandler, + ) { + if focus_handle.is_focused(self) { + self.window + .platform_window + .set_input_handler(Box::new(input_handler)); + } + } } impl Context for WindowContext<'_> { @@ -1520,7 +1596,7 @@ impl VisualContext for WindowContext<'_> { build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { let slot = self.app.entities.reserve(); let view = View { @@ -1559,7 +1635,7 @@ impl VisualContext for WindowContext<'_> { build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V, ) -> Self::Result> where - V: 'static + Render, + V: 'static + Render, { let slot = self.app.entities.reserve(); let view = View { @@ -1617,6 +1693,10 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { self.borrow_mut() } + fn app(&self) -> &AppContext { + self.borrow() + } + fn window(&self) -> &Window { self.borrow() } @@ -2124,49 +2204,6 @@ impl<'a, V: 'static> ViewContext<'a, V> { ) } - /// Register a focus listener for the current frame only. It will be cleared - /// on the next frame render. You should use this method only from within elements, - /// and we may want to enforce that better via a different context type. - // todo!() Move this to `FrameContext` to emphasize its individuality? - pub fn on_focus_changed( - &mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) { - let handle = self.view().downgrade(); - self.window - .current_frame - .focus_listeners - .push(Box::new(move |event, cx| { - handle - .update(cx, |view, cx| listener(view, event, cx)) - .log_err(); - })); - } - - pub fn with_key_dispatch( - &mut self, - context: KeyContext, - focus_handle: Option, - f: impl FnOnce(Option, &mut Self) -> R, - ) -> R { - let window = &mut self.window; - window - .current_frame - .dispatch_tree - .push_node(context.clone()); - if let Some(focus_handle) = focus_handle.as_ref() { - window - .current_frame - .dispatch_tree - .make_focusable(focus_handle.id); - } - let result = f(focus_handle, self); - - self.window.current_frame.dispatch_tree.pop_node(); - - result - } - pub fn spawn( &mut self, f: impl FnOnce(WeakView, AsyncWindowContext) -> Fut, @@ -2243,21 +2280,6 @@ impl<'a, V: 'static> ViewContext<'a, V> { }); } - /// Set an input handler, such as [ElementInputHandler], which interfaces with the - /// platform to receive textual input with proper integration with concerns such - /// as IME interactions. - pub fn handle_input( - &mut self, - focus_handle: &FocusHandle, - input_handler: impl PlatformInputHandler, - ) { - if focus_handle.is_focused(self) { - self.window - .platform_window - .set_input_handler(Box::new(input_handler)); - } - } - pub fn emit(&mut self, event: Evt) where Evt: 'static, @@ -2284,6 +2306,16 @@ impl<'a, V: 'static> ViewContext<'a, V> { { self.defer(|_, cx| cx.emit(Manager::Dismiss)) } + + pub fn listener( + &self, + f: impl Fn(&mut V, &E, &mut ViewContext) + 'static, + ) -> impl Fn(&E, &mut WindowContext) + 'static { + let view = self.view().downgrade(); + move |e: &E, cx: &mut WindowContext| { + view.update(cx, |view, cx| f(view, e, cx)).ok(); + } + } } impl Context for ViewContext<'_, V> { @@ -2335,7 +2367,7 @@ impl Context for ViewContext<'_, V> { } impl VisualContext for ViewContext<'_, V> { - fn build_view + 'static>( + fn build_view( &mut self, build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W, ) -> Self::Result> { @@ -2355,7 +2387,7 @@ impl VisualContext for ViewContext<'_, V> { build_view: impl FnOnce(&mut ViewContext<'_, W>) -> W, ) -> Self::Result> where - W: 'static + Render, + W: 'static + Render, { self.window_cx.replace_root_view(build_view) } @@ -2400,7 +2432,7 @@ pub struct WindowHandle { state_type: PhantomData, } -impl> WindowHandle { +impl WindowHandle { pub fn new(id: WindowId) -> Self { WindowHandle { any_handle: AnyWindowHandle { diff --git a/crates/gpui2_macros/src/derive_render_once.rs b/crates/gpui2_macros/src/derive_render_once.rs index 732f2df21f10ebf409935ed04ce17ea5553d9321..efe6aab0bb9c43776a4f9da26d084c2577ca367f 100644 --- a/crates/gpui2_macros/src/derive_render_once.rs +++ b/crates/gpui2_macros/src/derive_render_once.rs @@ -1,37 +1,17 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, parse_quote, DeriveInput}; +use syn::{parse_macro_input, DeriveInput}; pub fn derive_render_once(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); let type_name = &ast.ident; - - let mut trait_generics = ast.generics.clone(); - let view_type = if let Some(view_type) = specified_view_type(&ast) { - quote! { #view_type } - } else { - if let Some(first_type_param) = ast.generics.params.iter().find_map(|param| { - if let syn::GenericParam::Type(type_param) = param { - Some(type_param.ident.clone()) - } else { - None - } - }) { - quote! { #first_type_param } - } else { - trait_generics.params.push(parse_quote! { V: 'static }); - quote! { V } - } - }; - - let (impl_generics, _, where_clause) = trait_generics.split_for_impl(); - let (_, type_generics, _) = ast.generics.split_for_impl(); + let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl(); let gen = quote! { - impl #impl_generics gpui::RenderOnce<#view_type> for #type_name #type_generics + impl #impl_generics gpui::RenderOnce for #type_name #type_generics #where_clause { - type Element = gpui::CompositeElement<#view_type, Self>; + type Element = gpui::CompositeElement; fn element_id(&self) -> Option { None @@ -45,20 +25,3 @@ pub fn derive_render_once(input: TokenStream) -> TokenStream { gen.into() } - -fn specified_view_type(ast: &DeriveInput) -> Option { - ast.attrs.iter().find_map(|attr| { - if attr.path.is_ident("view") { - if let Ok(syn::Meta::NameValue(meta_name_value)) = attr.parse_meta() { - if let syn::Lit::Str(lit_str) = meta_name_value.lit { - return Some( - lit_str - .parse::() - .expect("Failed to parse view_type"), - ); - } - } - } - None - }) -} diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index f29312234c42f69286ffd120b07dac63b5031aff..786e641ee86d0c511bb88908d5a620bf4535548e 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,7 +1,7 @@ use editor::Editor; use gpui::{ div, prelude::*, uniform_list, AppContext, Div, FocusHandle, FocusableView, MouseButton, - Render, Task, UniformListScrollHandle, View, ViewContext, WindowContext, + MouseDownEvent, Render, Task, UniformListScrollHandle, View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; use ui::{prelude::*, v_stack, Divider, Label, TextColor}; @@ -15,7 +15,7 @@ pub struct Picker { } pub trait PickerDelegate: Sized + 'static { - type ListItem: RenderOnce>; + type ListItem: RenderOnce; fn match_count(&self) -> usize; fn selected_index(&self) -> usize; @@ -180,21 +180,21 @@ impl Picker { } } -impl Render for Picker { - type Element = Div; +impl Render for Picker { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() .key_context("picker") .size_full() .elevation_2(cx) - .on_action(Self::select_next) - .on_action(Self::select_prev) - .on_action(Self::select_first) - .on_action(Self::select_last) - .on_action(Self::cancel) - .on_action(Self::confirm) - .on_action(Self::secondary_confirm) + .on_action(cx.listener(Self::select_next)) + .on_action(cx.listener(Self::select_prev)) + .on_action(cx.listener(Self::select_first)) + .on_action(cx.listener(Self::select_last)) + .on_action(cx.listener(Self::cancel)) + .on_action(cx.listener(Self::confirm)) + .on_action(cx.listener(Self::secondary_confirm)) .child( v_stack() .py_0p5() @@ -208,31 +208,37 @@ impl Render for Picker { .p_1() .grow() .child( - uniform_list("candidates", self.delegate.match_count(), { - move |this: &mut Self, visible_range, cx| { - let selected_ix = this.delegate.selected_index(); - visible_range - .map(|ix| { - div() - .on_mouse_down( - MouseButton::Left, - move |this: &mut Self, event, cx| { - this.handle_click( - ix, - event.modifiers.command, - cx, - ) - }, - ) - .child(this.delegate.render_match( - ix, - ix == selected_ix, - cx, - )) - }) - .collect() - } - }) + uniform_list( + cx.view().clone(), + "candidates", + self.delegate.match_count(), + { + let selected_index = self.delegate.selected_index(); + + move |picker, visible_range, cx| { + visible_range + .map(|ix| { + div() + .on_mouse_down( + MouseButton::Left, + cx.listener(move |this, event: &MouseDownEvent, cx| { + this.handle_click( + ix, + event.modifiers.command, + cx, + ) + }), + ) + .child(picker.delegate.render_match( + ix, + ix == selected_index, + cx, + )) + }) + .collect() + } + }, + ) .track_scroll(self.scroll_handle.clone()), ) .max_h_72() diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index da3ada4c10936a626f143f0392544724787b7217..4d1a6ee8f73d5df2f8f00f3ee904dc255feeebfb 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -10,9 +10,9 @@ use anyhow::{anyhow, Result}; use gpui::{ actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, - Model, MouseButton, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, Stateful, - StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, - VisualContext as _, WeakView, WindowContext, + Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, + RenderOnce, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, + ViewContext, VisualContext as _, WeakView, WindowContext, }; use menu::{Confirm, SelectNext, SelectPrev}; use project::{ @@ -1339,7 +1339,7 @@ impl ProjectPanel { editor: Option<&View>, padding: Pixels, cx: &mut ViewContext, - ) -> Div { + ) -> Div { let show_editor = details.is_editing && !details.is_processing; let theme = cx.theme(); @@ -1378,7 +1378,7 @@ impl ProjectPanel { details: EntryDetails, // dragged_entry_destination: &mut Option>, cx: &mut ViewContext, - ) -> Stateful> { + ) -> Stateful
{ let kind = details.kind; let settings = ProjectPanelSettings::get_global(cx); const INDENT_SIZE: Pixels = px(16.0); @@ -1396,7 +1396,7 @@ impl ProjectPanel { this.bg(cx.theme().colors().element_selected) }) .hover(|style| style.bg(cx.theme().colors().element_hover)) - .on_click(move |this, event, cx| { + .on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| { if !show_editor { if kind.is_dir() { this.toggle_expanded(entry_id, cx); @@ -1408,10 +1408,13 @@ impl ProjectPanel { } } } - }) - .on_mouse_down(MouseButton::Right, move |this, event, cx| { - this.deploy_context_menu(event.position, entry_id, cx); - }) + })) + .on_mouse_down( + MouseButton::Right, + cx.listener(move |this, event: &MouseDownEvent, cx| { + this.deploy_context_menu(event.position, entry_id, cx); + }), + ) // .on_drop::(|this, event, cx| { // this.move_entry( // *dragged_entry, @@ -1423,10 +1426,10 @@ impl ProjectPanel { } } -impl Render for ProjectPanel { - type Element = Focusable>>; +impl Render for ProjectPanel { + type Element = Focusable>; - fn render(&mut self, _cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let has_worktree = self.visible_entries.len() != 0; if has_worktree { @@ -1434,40 +1437,43 @@ impl Render for ProjectPanel { .id("project-panel") .size_full() .key_context("ProjectPanel") - .on_action(Self::select_next) - .on_action(Self::select_prev) - .on_action(Self::expand_selected_entry) - .on_action(Self::collapse_selected_entry) - .on_action(Self::collapse_all_entries) - .on_action(Self::new_file) - .on_action(Self::new_directory) - .on_action(Self::rename) - .on_action(Self::delete) - .on_action(Self::confirm) - .on_action(Self::open_file) - .on_action(Self::cancel) - .on_action(Self::cut) - .on_action(Self::copy) - .on_action(Self::copy_path) - .on_action(Self::copy_relative_path) - .on_action(Self::paste) - .on_action(Self::reveal_in_finder) - .on_action(Self::open_in_terminal) - .on_action(Self::new_search_in_directory) + .on_action(cx.listener(Self::select_next)) + .on_action(cx.listener(Self::select_prev)) + .on_action(cx.listener(Self::expand_selected_entry)) + .on_action(cx.listener(Self::collapse_selected_entry)) + .on_action(cx.listener(Self::collapse_all_entries)) + .on_action(cx.listener(Self::new_file)) + .on_action(cx.listener(Self::new_directory)) + .on_action(cx.listener(Self::rename)) + .on_action(cx.listener(Self::delete)) + .on_action(cx.listener(Self::confirm)) + .on_action(cx.listener(Self::open_file)) + .on_action(cx.listener(Self::cancel)) + .on_action(cx.listener(Self::cut)) + .on_action(cx.listener(Self::copy)) + .on_action(cx.listener(Self::copy_path)) + .on_action(cx.listener(Self::copy_relative_path)) + .on_action(cx.listener(Self::paste)) + .on_action(cx.listener(Self::reveal_in_finder)) + .on_action(cx.listener(Self::open_in_terminal)) + .on_action(cx.listener(Self::new_search_in_directory)) .track_focus(&self.focus_handle) .child( uniform_list( + cx.view().clone(), "entries", self.visible_entries .iter() .map(|(_, worktree_entries)| worktree_entries.len()) .sum(), - |this: &mut Self, range, cx| { - let mut items = Vec::new(); - this.for_each_visible_entry(range, cx, |id, details, cx| { - items.push(this.render_entry(id, details, cx)); - }); - items + { + |this, range, cx| { + let mut items = Vec::new(); + this.for_each_visible_entry(range, cx, |id, details, cx| { + items.push(this.render_entry(id, details, cx)); + }); + items + } }, ) .size_full() diff --git a/crates/rich_text2/src/rich_text.rs b/crates/rich_text2/src/rich_text.rs index 48b530b7c578819c424f42f52459fa9498cb1603..4f64654bd3cdb759901afc20d20a805ad21a2d02 100644 --- a/crates/rich_text2/src/rich_text.rs +++ b/crates/rich_text2/src/rich_text.rs @@ -56,12 +56,12 @@ pub struct Mention { } impl RichText { - pub fn element( + pub fn element( &self, // syntax: Arc, // style: RichTextStyle, // cx: &mut ViewContext, - ) -> AnyElement { + ) -> AnyElement { todo!(); // let mut region_id = 0; diff --git a/crates/storybook2/src/stories/colors.rs b/crates/storybook2/src/stories/colors.rs index b690435e01417a2ced66a685f85db4fd9c0cfba1..8a628a01da903b2c0bcbb2ab32b913e00d45670e 100644 --- a/crates/storybook2/src/stories/colors.rs +++ b/crates/storybook2/src/stories/colors.rs @@ -5,8 +5,8 @@ use ui::prelude::*; pub struct ColorsStory; -impl Render for ColorsStory { - type Element = Div; +impl Render for ColorsStory { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let color_scales = default_color_scales(); diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index 12c7ea81a063181791b0873500242f56a36337b8..7ddeec08bfc27cd1de13b16714458be6534662dc 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -27,7 +27,7 @@ impl FocusStory { } impl Render for FocusStory { - type Element = Focusable>>; + type Element = Focusable>; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let theme = cx.theme(); @@ -42,18 +42,20 @@ impl Render for FocusStory { .id("parent") .focusable() .key_context("parent") - .on_action(|_, action: &ActionA, cx| { + .on_action(cx.listener(|_, action: &ActionA, cx| { println!("Action A dispatched on parent"); - }) - .on_action(|_, action: &ActionB, cx| { + })) + .on_action(cx.listener(|_, action: &ActionB, cx| { println!("Action B dispatched on parent"); - }) - .on_focus(|_, _, _| println!("Parent focused")) - .on_blur(|_, _, _| println!("Parent blurred")) - .on_focus_in(|_, _, _| println!("Parent focus_in")) - .on_focus_out(|_, _, _| println!("Parent focus_out")) - .on_key_down(|_, event, phase, _| println!("Key down on parent {:?}", event)) - .on_key_up(|_, event, phase, _| println!("Key up on parent {:?}", event)) + })) + .on_focus(cx.listener(|_, _, _| println!("Parent focused"))) + .on_blur(cx.listener(|_, _, _| println!("Parent blurred"))) + .on_focus_in(cx.listener(|_, _, _| println!("Parent focus_in"))) + .on_focus_out(cx.listener(|_, _, _| println!("Parent focus_out"))) + .on_key_down( + cx.listener(|_, event, phase, _| println!("Key down on parent {:?}", event)), + ) + .on_key_up(cx.listener(|_, event, phase, _| println!("Key up on parent {:?}", event))) .size_full() .bg(color_1) .focus(|style| style.bg(color_2)) @@ -61,38 +63,42 @@ impl Render for FocusStory { div() .track_focus(&self.child_1_focus) .key_context("child-1") - .on_action(|_, action: &ActionB, cx| { + .on_action(cx.listener(|_, action: &ActionB, cx| { println!("Action B dispatched on child 1 during"); - }) + })) .w_full() .h_6() .bg(color_4) .focus(|style| style.bg(color_5)) .in_focus(|style| style.bg(color_6)) - .on_focus(|_, _, _| println!("Child 1 focused")) - .on_blur(|_, _, _| println!("Child 1 blurred")) - .on_focus_in(|_, _, _| println!("Child 1 focus_in")) - .on_focus_out(|_, _, _| println!("Child 1 focus_out")) - .on_key_down(|_, event, phase, _| println!("Key down on child 1 {:?}", event)) - .on_key_up(|_, event, phase, _| println!("Key up on child 1 {:?}", event)) + .on_focus(cx.listener(|_, _, _| println!("Child 1 focused"))) + .on_blur(cx.listener(|_, _, _| println!("Child 1 blurred"))) + .on_focus_in(cx.listener(|_, _, _| println!("Child 1 focus_in"))) + .on_focus_out(cx.listener(|_, _, _| println!("Child 1 focus_out"))) + .on_key_down( + cx.listener(|_, event, _| println!("Key down on child 1 {:?}", event)), + ) + .on_key_up(cx.listener(|_, event, _| println!("Key up on child 1 {:?}", event))) .child("Child 1"), ) .child( div() .track_focus(&self.child_2_focus) .key_context("child-2") - .on_action(|_, action: &ActionC, cx| { + .on_action(cx.listener(|_, action: &ActionC, cx| { println!("Action C dispatched on child 2"); - }) + })) .w_full() .h_6() .bg(color_4) - .on_focus(|_, _, _| println!("Child 2 focused")) - .on_blur(|_, _, _| println!("Child 2 blurred")) - .on_focus_in(|_, _, _| println!("Child 2 focus_in")) - .on_focus_out(|_, _, _| println!("Child 2 focus_out")) - .on_key_down(|_, event, phase, _| println!("Key down on child 2 {:?}", event)) - .on_key_up(|_, event, phase, _| println!("Key up on child 2 {:?}", event)) + .on_focus(cx.listener(|_, _, _| println!("Child 2 focused"))) + .on_blur(cx.listener(|_, _, _| println!("Child 2 blurred"))) + .on_focus_in(cx.listener(|_, _, _| println!("Child 2 focus_in"))) + .on_focus_out(cx.listener(|_, _, _| println!("Child 2 focus_out"))) + .on_key_down( + cx.listener(|_, event, _| println!("Key down on child 2 {:?}", event)), + ) + .on_key_up(cx.listener(|_, event, _| println!("Key up on child 2 {:?}", event))) .child("Child 2"), ) } diff --git a/crates/storybook2/src/stories/kitchen_sink.rs b/crates/storybook2/src/stories/kitchen_sink.rs index 2d31cefed6e15cf51a7e368ef6b1aab99b11639b..b59e00bf25d84fc7d0144fd020c60217dffcf7f3 100644 --- a/crates/storybook2/src/stories/kitchen_sink.rs +++ b/crates/storybook2/src/stories/kitchen_sink.rs @@ -11,8 +11,8 @@ impl KitchenSinkStory { } } -impl Render for KitchenSinkStory { - type Element = Stateful>; +impl Render for KitchenSinkStory { + type Element = Stateful
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let component_stories = ComponentStory::iter() diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index 716004dea7132f87c16b6aebe393aa8d662d7cca..c26e5fd3f1adc78aa3e9e8bf99f8c8f26666db78 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -11,8 +11,8 @@ impl TextStory { } } -impl Render for TextStory { - type Element = Div; +impl Render for TextStory { + type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { v_stack() diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index 46885913ed97e29e8ec948d9475cae80a8a3a32e..b6582b07b194331f0e33f7e5b6b70557bfa50cbc 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -335,8 +335,8 @@ impl TerminalPanel { impl EventEmitter for TerminalPanel {} -impl Render for TerminalPanel { - type Element = Div; +impl Render for TerminalPanel { + type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { div().child(self.pane.clone()) diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 0d813986273e18e1f6e6ebe69ea007b95762125b..c61afb0b944bb2dfe2b4e38248ec8aad970692f0 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -9,10 +9,10 @@ pub mod terminal_panel; // use crate::terminal_element::TerminalElement; use editor::{scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - actions, div, Action, AnyElement, AppContext, DispatchPhase, Div, Element, EventEmitter, - FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView, InputHandler, - InteractiveElement, KeyDownEvent, Keystroke, Model, MouseButton, ParentElement, Pixels, Render, - SharedString, Styled, Task, View, ViewContext, VisualContext, WeakView, + actions, div, Action, AnyElement, AppContext, Div, Element, EventEmitter, FocusEvent, + FocusHandle, Focusable, FocusableElement, FocusableView, InputHandler, InteractiveElement, + KeyDownEvent, Keystroke, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Render, + SharedString, Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::Bias; use persistence::TERMINAL_DB; @@ -63,7 +63,6 @@ pub struct SendKeystroke(String); actions!(Clear, Copy, Paste, ShowCharacterPalette, SearchTest); pub fn init(cx: &mut AppContext) { - workspace::ui::init(cx); terminal_panel::init(cx); terminal::init(cx); @@ -84,7 +83,7 @@ pub struct TerminalView { has_new_content: bool, //Currently using iTerm bell, show bell emoji in tab until input is received has_bell: bool, - context_menu: Option>>, + context_menu: Option>, blink_state: bool, blinking_on: bool, blinking_paused: bool, @@ -505,12 +504,7 @@ pub fn regex_search_for_query(query: &project::search::SearchQuery) -> Option, - ) { + fn key_down(&mut self, event: &KeyDownEvent, cx: &mut ViewContext) { self.clear_bel(cx); self.pause_cursor_blinking(cx); @@ -537,8 +531,8 @@ impl TerminalView { } } -impl Render for TerminalView { - type Element = Focusable>; +impl Render for TerminalView { + type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let terminal_handle = self.terminal.clone().downgrade(); @@ -552,14 +546,14 @@ impl Render for TerminalView { div() .z_index(0) .absolute() - .on_key_down(Self::key_down) - .on_action(TerminalView::send_text) - .on_action(TerminalView::send_keystroke) - .on_action(TerminalView::copy) - .on_action(TerminalView::paste) - .on_action(TerminalView::clear) - .on_action(TerminalView::show_character_palette) - .on_action(TerminalView::select_all) + .on_key_down(cx.listener(Self::key_down)) + .on_action(cx.listener(TerminalView::send_text)) + .on_action(cx.listener(TerminalView::send_keystroke)) + .on_action(cx.listener(TerminalView::copy)) + .on_action(cx.listener(TerminalView::paste)) + .on_action(cx.listener(TerminalView::clear)) + .on_action(cx.listener(TerminalView::show_character_palette)) + .on_action(cx.listener(TerminalView::select_all)) // todo!() .child( "TERMINAL HERE", // TerminalElement::new( @@ -569,10 +563,13 @@ impl Render for TerminalView { // self.can_navigate_to_selected_word, // ) ) - .on_mouse_down(MouseButton::Right, |this, event, cx| { - this.deploy_context_menu(event.position, cx); - cx.notify(); - }), + .on_mouse_down( + MouseButton::Right, + cx.listener(|this, event: &MouseDownEvent, cx| { + this.deploy_context_menu(event.position, cx); + cx.notify(); + }), + ), ) .children( self.context_menu @@ -580,8 +577,8 @@ impl Render for TerminalView { .map(|context_menu| div().z_index(1).absolute().child(context_menu)), ) .track_focus(&self.focus_handle) - .on_focus_in(Self::focus_in) - .on_focus_out(Self::focus_out) + .on_focus_in(cx.listener(Self::focus_in)) + .on_focus_out(cx.listener(Self::focus_out)) } } @@ -746,11 +743,7 @@ impl Item for TerminalView { Some(self.terminal().read(cx).title().into()) } - fn tab_content( - &self, - _detail: Option, - cx: &gpui::AppContext, - ) -> AnyElement { + fn tab_content(&self, _detail: Option, cx: &WindowContext) -> AnyElement { let title = self.terminal().read(cx).title(); div() diff --git a/crates/theme2/src/story.rs b/crates/theme2/src/story.rs index e0c802fcc72ac3cbd234cfda1bb65e7224e47cdd..5e484e12cd5268833bafa18442fffeca20c4af1e 100644 --- a/crates/theme2/src/story.rs +++ b/crates/theme2/src/story.rs @@ -1,11 +1,11 @@ -use gpui::{div, Div, Element, ParentElement, SharedString, Styled, ViewContext}; +use gpui::{div, Div, Element, ParentElement, SharedString, Styled, WindowContext}; use crate::ActiveTheme; pub struct Story {} impl Story { - pub fn container(cx: &mut ViewContext) -> Div { + pub fn container(cx: &mut WindowContext) -> Div { div() .size_full() .flex() @@ -16,21 +16,18 @@ impl Story { .bg(cx.theme().colors().background) } - pub fn title(cx: &mut ViewContext, title: SharedString) -> impl Element { + pub fn title(cx: &mut WindowContext, title: SharedString) -> impl Element { div() .text_xl() .text_color(cx.theme().colors().text) .child(title) } - pub fn title_for(cx: &mut ViewContext) -> impl Element { + pub fn title_for(cx: &mut WindowContext) -> impl Element { Self::title(cx, std::any::type_name::().into()) } - pub fn label( - cx: &mut ViewContext, - label: impl Into, - ) -> impl Element { + pub fn label(cx: &mut WindowContext, label: impl Into) -> impl Element { div() .mt_4() .mb_2() diff --git a/crates/theme2/src/styles/players.rs b/crates/theme2/src/styles/players.rs index 726e4bac56c7d05646c2c0d30e9c0f8df254b116..a4734d1c00c7d1d63c5719585974c45f1bae887c 100644 --- a/crates/theme2/src/styles/players.rs +++ b/crates/theme2/src/styles/players.rs @@ -147,8 +147,8 @@ mod stories { pub struct PlayerStory; - impl Render for PlayerStory { - type Element = Div; + impl Render for PlayerStory { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx).child( @@ -156,7 +156,7 @@ mod stories { .flex() .flex_col() .gap_4() - .child(Story::title_for::<_, PlayerColors>(cx)) + .child(Story::title_for::(cx)) .child(Story::label(cx, "Player Colors")) .child( div() diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index fb89604865630e2a8f47f712dc8c8d8a2509127f..39c5924fb94bafe58cdc5a203104b8ddd6aac494 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -63,6 +63,12 @@ impl ActiveTheme for AppContext { } } +// impl<'a> ActiveTheme for WindowContext<'a> { +// fn theme(&self) -> &Arc { +// &ThemeSettings::get_global(self.app()).active_theme +// } +// } + pub struct ThemeFamily { pub id: String, pub name: SharedString, diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index da76a95cfa8cc5c7b6842802d626a94d567b8652..ab79352f86ed13f70650d78d2596519b1f85279a 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -7,10 +7,10 @@ pub struct Avatar { shape: Shape, } -impl Component for Avatar { - type Rendered = Img; +impl Component for Avatar { + type Rendered = Img; - fn render(self, _view: &mut V, cx: &mut ViewContext) -> Self::Rendered { + fn render(self, _: &mut WindowContext) -> Self::Rendered { let mut img = img(); if self.shape == Shape::Circle { @@ -51,12 +51,12 @@ mod stories { pub struct AvatarStory; - impl Render for AvatarStory { - type Element = Div; + impl Render for AvatarStory { + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) - .child(Story::title_for::<_, Avatar>(cx)) + .child(Story::title_for::(cx)) .child(Story::label(cx, "Default")) .child(Avatar::new( "https://avatars.githubusercontent.com/u/1714999?v=4", diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index efbb4c9e72e3fc5ff5a7f4a37873cee4bf2e167d..3d92cebec55c8a6ee524299b9fcc5cfb4fdb6b5b 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -1,7 +1,7 @@ -use std::sync::Arc; +use std::rc::Rc; use gpui::{ - DefiniteLength, Div, Hsla, MouseButton, RenderOnce, Stateful, StatefulInteractiveElement, + DefiniteLength, Div, Hsla, MouseButton, MouseDownEvent, RenderOnce, StatefulInteractiveElement, WindowContext, }; @@ -10,19 +10,19 @@ use crate::{h_stack, Icon, IconButton, IconElement, Label, LineHeightStyle, Text /// Provides the flexibility to use either a standard /// button or an icon button in a given context. -pub enum ButtonOrIconButton { - Button(Button), - IconButton(IconButton), +pub enum ButtonOrIconButton { + Button(Button), + IconButton(IconButton), } -impl From> for ButtonOrIconButton { - fn from(value: Button) -> Self { +impl From