diff --git a/.gitignore b/.gitignore index dbffa0f829cffe77c976a95d13f339be367e8840..15a0a9f5f2f02bee670d6b23dbfc4116ccd20448 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/target +**/cargo-target /zed.xcworkspace .DS_Store /plugins/bin diff --git a/Cargo.lock b/Cargo.lock index d1cd868eaac92ed3456f00394e7337bc8ff88a0b..775e1d2b8e3139b32e9b712f813977e93ebebefd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3163,6 +3163,7 @@ dependencies = [ "sqlez", "sum_tree", "taffy", + "thiserror", "time 0.3.27", "tiny-skia", "usvg", @@ -3171,6 +3172,36 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "gpui2" +version = "0.1.0" +dependencies = [ + "anyhow", + "derive_more", + "futures 0.3.28", + "gpui", + "gpui2_macros", + "log", + "parking_lot 0.11.2", + "refineable", + "rust-embed", + "serde", + "settings", + "simplelog", + "smallvec", + "theme", + "util", +] + +[[package]] +name = "gpui2_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "gpui_macros" version = "0.1.0" @@ -5231,33 +5262,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "playground" -version = "0.1.0" -dependencies = [ - "anyhow", - "derive_more", - "gpui", - "log", - "parking_lot 0.11.2", - "playground_macros", - "refineable", - "serde", - "simplelog", - "smallvec", - "taffy", - "util", -] - -[[package]] -name = "playground_macros" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "plist" version = "1.5.0" @@ -7367,6 +7371,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "storybook" +version = "0.1.0" +dependencies = [ + "anyhow", + "gpui2", + "log", + "rust-embed", + "serde", + "settings", + "simplelog", + "theme", + "util", +] + [[package]] name = "stringprep" version = "0.1.3" @@ -7566,7 +7585,7 @@ dependencies = [ [[package]] name = "taffy" version = "0.3.11" -source = "git+https://github.com/DioxusLabs/taffy?rev=dab541d6104d58e2e10ce90c4a1dad0b703160cd#dab541d6104d58e2e10ce90c4a1dad0b703160cd" +source = "git+https://github.com/DioxusLabs/taffy?rev=4fb530bdd71609bb1d3f76c6a8bde1ba82805d5e#4fb530bdd71609bb1d3f76c6a8bde1ba82805d5e" dependencies = [ "arrayvec 0.7.4", "grid", diff --git a/Cargo.toml b/Cargo.toml index c233c74b55816334347c88208624b294abd921f5..96070658b9351e4539818c7b83c73d9979da6eb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,9 +32,9 @@ members = [ "crates/git", "crates/go_to_line", "crates/gpui", - "crates/gpui/playground", - "crates/gpui/playground_macros", "crates/gpui_macros", + "crates/gpui2", + "crates/gpui2_macros", "crates/install_cli", "crates/journal", "crates/language", @@ -63,6 +63,7 @@ members = [ "crates/sqlez", "crates/sqlez_macros", "crates/feature_flags", + "crates/storybook", "crates/sum_tree", "crates/terminal", "crates/text", diff --git a/assets/icons/Icons/exit.svg b/assets/icons/Icons/exit.svg new file mode 100644 index 0000000000000000000000000000000000000000..6d768492482d6c62e1ec10b5f10054796c89cbb7 --- /dev/null +++ b/assets/icons/Icons/exit.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/stop_sharing.svg b/assets/icons/stop_sharing.svg new file mode 100644 index 0000000000000000000000000000000000000000..e9aa7eac5a481ed3f6ae9253fc8c9c8c3a0785e6 --- /dev/null +++ b/assets/icons/stop_sharing.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index fba10c61bad9b31b145e3b515423891bedae6972..8e0252ec608a6e113db5b39fefb86b99e95ed07c 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -2434,14 +2434,14 @@ fn render_tree_branch( let cap_height = row_style.cap_height(font_cache); let baseline_offset = row_style.baseline_offset(font_cache) + (size.y() - line_height) / 2.; - Canvas::new(move |scene, bounds, _, _, _| { - scene.paint_layer(None, |scene| { + Canvas::new(move |bounds, _, _, cx| { + cx.paint_layer(None, |cx| { let start_x = bounds.min_x() + (bounds.width() / 2.) - (branch_style.width / 2.); let end_x = bounds.max_x(); let start_y = bounds.min_y(); let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.); - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, start_y), vec2f( @@ -2453,7 +2453,7 @@ fn render_tree_branch( border: gpui::Border::default(), corner_radii: (0.).into(), }); - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, end_y), vec2f(end_x, end_y + branch_style.width), diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 6c34b7021ee37b51843015642f6f5f05166868ed..f0e09e139e648d21381bddc54eecfe541bb43a74 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -13,8 +13,8 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AppContext, Entity, ImageData, LayoutContext, ModelHandle, PaintContext, SceneBuilder, - Subscription, View, ViewContext, ViewHandle, WeakViewHandle, + AppContext, Entity, ImageData, ModelHandle, Subscription, View, ViewContext, ViewHandle, + WeakViewHandle, }; use picker::PickerEvent; use project::{Project, RepositoryEntry}; @@ -1165,19 +1165,18 @@ impl Element for AvatarRibbon { &mut self, constraint: gpui::SizeConstraint, _: &mut CollabTitlebarItem, - _: &mut LayoutContext, + _: &mut ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { (constraint.max, ()) } fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, _: RectF, _: &mut Self::LayoutState, _: &mut CollabTitlebarItem, - _: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let mut path = PathBuilder::new(); path.reset(bounds.lower_left()); @@ -1188,7 +1187,7 @@ impl Element for AvatarRibbon { path.line_to(bounds.upper_right() - vec2f(bounds.height(), 0.)); path.curve_to(bounds.lower_right(), bounds.upper_right()); path.line_to(bounds.lower_left()); - scene.push_path(path.build(self.color, None)); + cx.scene().push_path(path.build(self.color, None)); } fn rect_for_text_range( diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index a86b2576869b5d2e3b695ae41d073bf6fa631812..5017666f7b05d64423260e63da86c951cec5955d 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -7,7 +7,7 @@ use gpui::{ }, json::ToJson, serde_json::{self, json}, - AnyElement, Axis, Element, LayoutContext, PaintContext, SceneBuilder, View, ViewContext, + AnyElement, Axis, Element, View, ViewContext, }; pub(crate) struct FacePile { @@ -32,7 +32,7 @@ impl Element for FacePile { &mut self, constraint: gpui::SizeConstraint, view: &mut V, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY); @@ -53,12 +53,11 @@ impl Element for FacePile { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _layout: &mut Self::LayoutState, view: &mut V, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); @@ -69,9 +68,10 @@ impl Element for FacePile { let size = face.size(); origin_x -= size.x(); let origin_y = origin_y + (bounds.height() - size.y()) / 2.0; - scene.paint_layer(None, |scene| { - face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); - }); + + cx.scene().push_layer(None); + face.paint(vec2f(origin_x, origin_y), visible_bounds, view, cx); + cx.scene().pop_layer(); origin_x += self.overlap; } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 90fe6ccc52338fe5eb5df34b72b180852b39470b..b7e34fda5377d6370d33cdec35087a4e544cd7d9 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -32,8 +32,8 @@ use gpui::{ json::{self, ToJson}, platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, text_layout::{self, Line, RunStyle, TextLayoutCache}, - AnyElement, Axis, Border, CursorRegion, Element, EventContext, FontCache, LayoutContext, - MouseRegion, PaintContext, Quad, SceneBuilder, SizeConstraint, ViewContext, WindowContext, + AnyElement, Axis, CursorRegion, Element, EventContext, FontCache, MouseRegion, Quad, + SizeConstraint, ViewContext, WindowContext, }; use itertools::Itertools; use json::json; @@ -131,7 +131,6 @@ impl EditorElement { } fn attach_mouse_handlers( - scene: &mut SceneBuilder, position_map: &Arc, has_popovers: bool, visible_bounds: RectF, @@ -141,124 +140,124 @@ impl EditorElement { cx: &mut ViewContext, ) { enum EditorElementMouseHandlers {} - scene.push_mouse_region( - MouseRegion::new::( - cx.view_id(), - cx.view_id(), - visible_bounds, - ) - .on_down(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_down( - editor, - event.platform_event, - position_map.as_ref(), - text_bounds, - gutter_bounds, - cx, - ) { - cx.propagate_event(); - } - } - }) - .on_down(MouseButton::Right, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_right_down( - editor, - event.position, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event(); + let view_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, view_id, visible_bounds) + .on_down(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_down( + editor, + event.platform_event, + position_map.as_ref(), + text_bounds, + gutter_bounds, + cx, + ) { + cx.propagate_event(); + } } - } - }) - .on_up(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_up( - editor, - event.position, - event.cmd, - event.shift, - event.alt, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event() + }) + .on_down(MouseButton::Right, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_right_down( + editor, + event.position, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event(); + } } - } - }) - .on_drag(MouseButton::Left, { - let position_map = position_map.clone(); - move |event, editor, cx| { - if event.end { - return; + }) + .on_up(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_up( + editor, + event.position, + event.cmd, + event.shift, + event.alt, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event() + } } + }) + .on_drag(MouseButton::Left, { + let position_map = position_map.clone(); + move |event, editor, cx| { + if event.end { + return; + } - if !Self::mouse_dragged( - editor, - event.platform_event, - position_map.as_ref(), - text_bounds, - cx, - ) { - cx.propagate_event() + if !Self::mouse_dragged( + editor, + event.platform_event, + position_map.as_ref(), + text_bounds, + cx, + ) { + cx.propagate_event() + } } - } - }) - .on_move({ - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::mouse_moved( - editor, - event.platform_event, - &position_map, - text_bounds, - cx, - ) { - cx.propagate_event() + }) + .on_move({ + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::mouse_moved( + editor, + event.platform_event, + &position_map, + text_bounds, + cx, + ) { + cx.propagate_event() + } } - } - }) - .on_move_out(move |_, editor: &mut Editor, cx| { - if has_popovers { - hide_hover(editor, cx); - } - }) - .on_scroll({ - let position_map = position_map.clone(); - move |event, editor, cx| { - if !Self::scroll( - editor, - event.position, - *event.delta.raw(), - event.delta.precise(), - &position_map, - bounds, - cx, - ) { - cx.propagate_event() + }) + .on_move_out(move |_, editor: &mut Editor, cx| { + if has_popovers { + hide_hover(editor, cx); } - } - }), + }) + .on_scroll({ + let position_map = position_map.clone(); + move |event, editor, cx| { + if !Self::scroll( + editor, + event.position, + *event.delta.raw(), + event.delta.precise(), + &position_map, + bounds, + cx, + ) { + cx.propagate_event() + } + } + }), ); enum GutterHandlers {} - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), cx.view_id() + 1, gutter_bounds) - .on_hover(|hover, editor: &mut Editor, cx| { + let view_id = cx.view_id(); + let region_id = cx.view_id() + 1; + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, region_id, gutter_bounds).on_hover( + |hover, editor: &mut Editor, cx| { editor.gutter_hover( &GutterHover { hovered: hover.started, }, cx, ); - }), + }, + ), ) } @@ -528,24 +527,24 @@ impl EditorElement { fn paint_background( &self, - scene: &mut SceneBuilder, gutter_bounds: RectF, text_bounds: RectF, layout: &LayoutState, + cx: &mut ViewContext, ) { let bounds = gutter_bounds.union_rect(text_bounds); let scroll_top = layout.position_map.snapshot.scroll_position().y() * layout.position_map.line_height; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: gutter_bounds, background: Some(self.style.gutter_background), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: Default::default(), }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: text_bounds, background: Some(self.style.background), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: Default::default(), }); @@ -570,10 +569,10 @@ impl EditorElement { bounds.width(), layout.position_map.line_height * (end_row - start_row + 1) as f32, ); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(origin, size), background: Some(self.style.active_line_background), - border: Border::default(), + border: Border::default().into(), corner_radii: Default::default(), }); } @@ -590,10 +589,10 @@ impl EditorElement { bounds.width(), layout.position_map.line_height * highlighted_rows.len() as f32, ); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(origin, size), background: Some(self.style.highlighted_line_background), - border: Border::default(), + border: Border::default().into(), corner_radii: Default::default(), }); } @@ -617,13 +616,13 @@ impl EditorElement { } else { self.style.wrap_guide }; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new( vec2f(x, text_bounds.origin_y()), vec2f(1., text_bounds.height()), ), background: Some(color), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: Default::default(), }); } @@ -632,12 +631,11 @@ impl EditorElement { fn paint_gutter( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let line_height = layout.position_map.line_height; @@ -650,7 +648,7 @@ impl EditorElement { ); if show_gutter { - Self::paint_diff_hunks(scene, bounds, layout, cx); + Self::paint_diff_hunks(bounds, layout, cx); } for (ix, line) in layout.line_number_layouts.iter().enumerate() { @@ -661,7 +659,7 @@ impl EditorElement { ix as f32 * line_height - (scroll_top % line_height), ); - line.paint(scene, line_origin, visible_bounds, line_height, cx); + line.paint(line_origin, visible_bounds, line_height, cx); } } @@ -678,7 +676,7 @@ impl EditorElement { let indicator_origin = bounds.origin() + position + centering_offset; - indicator.paint(scene, indicator_origin, visible_bounds, editor, cx); + indicator.paint(indicator_origin, visible_bounds, editor, cx); } } @@ -687,22 +685,11 @@ impl EditorElement { let mut y = *row as f32 * line_height - scroll_top; x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.; y += (line_height - indicator.size().y()) / 2.; - indicator.paint( - scene, - bounds.origin() + vec2f(x, y), - visible_bounds, - editor, - cx, - ); + indicator.paint(bounds.origin() + vec2f(x, y), visible_bounds, editor, cx); } } - fn paint_diff_hunks( - scene: &mut SceneBuilder, - bounds: RectF, - layout: &mut LayoutState, - cx: &mut ViewContext, - ) { + fn paint_diff_hunks(bounds: RectF, layout: &mut LayoutState, cx: &mut ViewContext) { let diff_style = &theme::current(cx).editor.diff.clone(); let line_height = layout.position_map.line_height; @@ -721,10 +708,10 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(diff_style.modified), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: (1. * line_height).into(), }); @@ -754,10 +741,10 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(diff_style.deleted), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: (1. * line_height).into(), }); @@ -776,10 +763,10 @@ impl EditorElement { let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_bounds = RectF::new(highlight_origin, highlight_size); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: highlight_bounds, background: Some(color), - border: Border::new(0., Color::transparent_black()), + border: Border::new(0., Color::transparent_black()).into(), corner_radii: (diff_style.corner_radius * line_height).into(), }); } @@ -787,12 +774,11 @@ impl EditorElement { fn paint_text( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let style = &self.style; let scroll_position = layout.position_map.snapshot.scroll_position(); @@ -804,9 +790,9 @@ impl EditorElement { let line_end_overshoot = 0.15 * layout.position_map.line_height; let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces; - scene.push_layer(Some(bounds)); + cx.scene().push_layer(Some(bounds)); - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds, style: if !editor.link_go_to_definition_state.definitions.is_empty() { CursorStyle::PointingHand @@ -819,7 +805,6 @@ impl EditorElement { self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; for (id, range, color) in layout.fold_ranges.iter() { self.paint_highlighted_range( - scene, range.clone(), *color, fold_corner_radius, @@ -829,6 +814,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); for bound in range_to_bounds( @@ -840,7 +826,7 @@ impl EditorElement { line_end_overshoot, &layout.position_map, ) { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: bound, style: CursorStyle::PointingHand, }); @@ -851,8 +837,9 @@ impl EditorElement { .to_point(&layout.position_map.snapshot.display_snapshot) .row; - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), *id as usize, bound) + let view_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(view_id, *id as usize, bound) .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| { editor.unfold_at(&UnfoldAt { buffer_row }, cx) }) @@ -864,7 +851,6 @@ impl EditorElement { for (range, color) in &layout.highlighted_ranges { self.paint_highlighted_range( - scene, range.clone(), *color, 0., @@ -874,6 +860,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); } @@ -891,7 +878,6 @@ impl EditorElement { for selection in selections { self.paint_highlighted_range( - scene, selection.range.clone(), selection_style.selection, corner_radius, @@ -901,6 +887,7 @@ impl EditorElement { scroll_top, scroll_left, bounds, + cx, ); if selection.is_local && !selection.range.is_empty() { @@ -980,7 +967,6 @@ impl EditorElement { layout, row, scroll_top, - scene, content_origin, scroll_left, visible_text_bounds, @@ -992,14 +978,14 @@ impl EditorElement { } } - scene.paint_layer(Some(bounds), |scene| { - for cursor in cursors { - cursor.paint(scene, content_origin, cx); - } - }); + cx.scene().push_layer(Some(bounds)); + for cursor in cursors { + cursor.paint(content_origin, cx); + } + cx.scene().pop_layer(); if let Some((position, context_menu)) = layout.context_menu.as_mut() { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); let cursor_row_layout = &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; @@ -1019,18 +1005,17 @@ impl EditorElement { } context_menu.paint( - scene, list_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, cx, ); - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); } if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { - scene.push_stacking_context(None, None); + cx.scene().push_stacking_context(None, None); // This is safe because we check on layout whether the required row is available let hovered_row_layout = @@ -1061,7 +1046,6 @@ impl EditorElement { } hover_popover.paint( - scene, popover_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, @@ -1083,7 +1067,6 @@ impl EditorElement { } hover_popover.paint( - scene, popover_origin, RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor editor, @@ -1094,10 +1077,10 @@ impl EditorElement { } } - scene.pop_stacking_context(); + cx.scene().pop_stacking_context(); } - scene.pop_layer(); + cx.scene().pop_layer(); } fn scrollbar_left(&self, bounds: &RectF) -> f32 { @@ -1106,11 +1089,10 @@ impl EditorElement { fn paint_scrollbar( &mut self, - scene: &mut SceneBuilder, bounds: RectF, layout: &mut LayoutState, - cx: &mut ViewContext, editor: &Editor, + cx: &mut ViewContext, ) { enum ScrollbarMouseHandlers {} if layout.mode != EditorMode::Full { @@ -1147,9 +1129,9 @@ impl EditorElement { let thumb_bounds = RectF::from_points(vec2f(left, thumb_top), vec2f(right, thumb_bottom)); if layout.show_scrollbars { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: track_bounds, - border: style.track.border, + border: style.track.border.into(), background: style.track.background_color, ..Default::default() }); @@ -1177,10 +1159,10 @@ impl EditorElement { } let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(color), - border, + border: border.into(), corner_radii: style.thumb.corner_radii.into(), }) }; @@ -1237,29 +1219,30 @@ impl EditorElement { left: true, }; - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(color), - border, + border: border.into(), corner_radii: style.thumb.corner_radii.into(), }) } } - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: thumb_bounds, - border: style.thumb.border, + border: style.thumb.border.into(), background: style.thumb.background_color, corner_radii: style.thumb.corner_radii.into(), }); } - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds: track_bounds, style: CursorStyle::Arrow, }); - scene.push_mouse_region( - MouseRegion::new::(cx.view_id(), cx.view_id(), track_bounds) + let region_id = cx.view_id(); + cx.scene().push_mouse_region( + MouseRegion::new::(region_id, region_id, track_bounds) .on_move(move |event, editor: &mut Editor, cx| { if event.pressed_button.is_none() { editor.scroll_manager.show_scrollbar(cx); @@ -1305,7 +1288,6 @@ impl EditorElement { #[allow(clippy::too_many_arguments)] fn paint_highlighted_range( &self, - scene: &mut SceneBuilder, range: Range, color: Color, corner_radius: f32, @@ -1315,6 +1297,7 @@ impl EditorElement { scroll_top: f32, scroll_left: f32, bounds: RectF, + cx: &mut ViewContext, ) { let start_row = layout.visible_display_row_range.start; let end_row = layout.visible_display_row_range.end; @@ -1358,18 +1341,17 @@ impl EditorElement { .collect(), }; - highlighted_range.paint(bounds, scene); + highlighted_range.paint(bounds, cx); } } fn paint_blocks( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) { let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_left = scroll_position.x() * layout.position_map.em_width; @@ -1384,9 +1366,7 @@ impl EditorElement { if !matches!(block.style, BlockStyle::Sticky) { origin += vec2f(-scroll_left, 0.); } - block - .element - .paint(scene, origin, visible_bounds, editor, cx); + block.element.paint(origin, visible_bounds, editor, cx); } } @@ -1690,7 +1670,7 @@ impl EditorElement { style: &EditorStyle, line_layouts: &[LineWithInvisibles], editor: &mut Editor, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (f32, Vec) { let mut block_id = 0; let scroll_x = snapshot.scroll_anchor.offset.x(); @@ -2022,7 +2002,6 @@ impl LineWithInvisibles { layout: &LayoutState, row: u32, scroll_top: f32, - scene: &mut SceneBuilder, content_origin: Vector2F, scroll_left: f32, visible_text_bounds: RectF, @@ -2035,7 +2014,6 @@ impl LineWithInvisibles { let line_y = row as f32 * line_height - scroll_top; self.line.paint( - scene, content_origin + vec2f(-scroll_left, line_y), visible_text_bounds, line_height, @@ -2049,7 +2027,6 @@ impl LineWithInvisibles { scroll_left, line_y, row, - scene, visible_bounds, line_height, whitespace_setting, @@ -2065,7 +2042,6 @@ impl LineWithInvisibles { scroll_left: f32, line_y: f32, row: u32, - scene: &mut SceneBuilder, visible_bounds: RectF, line_height: f32, whitespace_setting: ShowWhitespaceSetting, @@ -2097,7 +2073,7 @@ impl LineWithInvisibles { continue; } } - invisible_symbol.paint(scene, origin, visible_bounds, line_height, cx); + invisible_symbol.paint(origin, visible_bounds, line_height, cx); } } } @@ -2116,7 +2092,7 @@ impl Element for EditorElement { &mut self, constraint: SizeConstraint, editor: &mut Editor, - cx: &mut LayoutContext, + cx: &mut ViewContext, ) -> (Vector2F, Self::LayoutState) { let mut size = constraint.max; if size.x().is_infinite() { @@ -2590,15 +2566,14 @@ impl Element for EditorElement { fn paint( &mut self, - scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, editor: &mut Editor, - cx: &mut PaintContext, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - scene.push_layer(Some(visible_bounds)); + cx.scene().push_layer(Some(visible_bounds)); let gutter_bounds = RectF::new(bounds.origin(), layout.gutter_size); let text_bounds = RectF::new( @@ -2607,7 +2582,6 @@ impl Element for EditorElement { ); Self::attach_mouse_handlers( - scene, &layout.position_map, layout.hover_popovers.is_some(), visible_bounds, @@ -2617,20 +2591,19 @@ impl Element for EditorElement { cx, ); - self.paint_background(scene, gutter_bounds, text_bounds, layout); + self.paint_background(gutter_bounds, text_bounds, layout, cx); if layout.gutter_size.x() > 0. { - self.paint_gutter(scene, gutter_bounds, visible_bounds, layout, editor, cx); + self.paint_gutter(gutter_bounds, visible_bounds, layout, editor, cx); } - self.paint_text(scene, text_bounds, visible_bounds, layout, editor, cx); + self.paint_text(text_bounds, visible_bounds, layout, editor, cx); - scene.push_layer(Some(bounds)); + cx.scene().push_layer(Some(bounds)); if !layout.blocks.is_empty() { - self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx); + self.paint_blocks(bounds, visible_bounds, layout, editor, cx); } - self.paint_scrollbar(scene, bounds, layout, cx, &editor); - scene.pop_layer(); - - scene.pop_layer(); + self.paint_scrollbar(bounds, layout, &editor, cx); + cx.scene().pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( @@ -2873,7 +2846,7 @@ impl Cursor { ) } - pub fn paint(&self, scene: &mut SceneBuilder, origin: Vector2F, cx: &mut WindowContext) { + pub fn paint(&self, origin: Vector2F, cx: &mut WindowContext) { let bounds = match self.shape { CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)), CursorShape::Block | CursorShape::Hollow => RectF::new( @@ -2888,14 +2861,14 @@ impl Cursor { //Draw background or border quad if matches!(self.shape, CursorShape::Hollow) { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: None, - border: Border::all(1., self.color), + border: Border::all(1., self.color).into(), corner_radii: Default::default(), }); } else { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(self.color), border: Default::default(), @@ -2904,7 +2877,7 @@ impl Cursor { } if let Some(block_text) = &self.block_text { - block_text.paint(scene, self.origin + origin, bounds, self.line_height, cx); + block_text.paint(self.origin + origin, bounds, self.line_height, cx); } } @@ -2929,17 +2902,17 @@ pub struct HighlightedRangeLine { } impl HighlightedRange { - pub fn paint(&self, bounds: RectF, scene: &mut SceneBuilder) { + pub fn paint(&self, bounds: RectF, cx: &mut WindowContext) { if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x { - self.paint_lines(self.start_y, &self.lines[0..1], bounds, scene); + self.paint_lines(self.start_y, &self.lines[0..1], bounds, cx); self.paint_lines( self.start_y + self.line_height, &self.lines[1..], bounds, - scene, + cx, ); } else { - self.paint_lines(self.start_y, &self.lines, bounds, scene); + self.paint_lines(self.start_y, &self.lines, bounds, cx); } } @@ -2948,7 +2921,7 @@ impl HighlightedRange { start_y: f32, lines: &[HighlightedRangeLine], bounds: RectF, - scene: &mut SceneBuilder, + cx: &mut WindowContext, ) { if lines.is_empty() { return; @@ -3046,7 +3019,7 @@ impl HighlightedRange { } path.line_to(first_top_right - top_curve_width); - scene.push_path(path.build(self.color, Some(bounds))); + cx.scene().push_path(path.build(self.color, Some(bounds))); } } @@ -3204,18 +3177,10 @@ mod tests { Point::new(5, 6)..Point::new(6, 0), ]); }); - let mut new_parents = Default::default(); - let mut notify_views_if_parents_change = Default::default(); - let mut layout_cx = LayoutContext::new( - cx, - &mut new_parents, - &mut notify_views_if_parents_change, - false, - ); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); assert_eq!(state.selections.len(), 1); @@ -3296,18 +3261,10 @@ mod tests { DisplayPoint::new(10, 0)..DisplayPoint::new(13, 0), ]); }); - let mut new_parents = Default::default(); - let mut notify_views_if_parents_change = Default::default(); - let mut layout_cx = LayoutContext::new( - cx, - &mut new_parents, - &mut notify_views_if_parents_change, - false, - ); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); @@ -3363,18 +3320,10 @@ mod tests { let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx))); let (size, mut state) = editor.update(cx, |editor, cx| { - let mut new_parents = Default::default(); - let mut notify_views_if_parents_change = Default::default(); - let mut layout_cx = LayoutContext::new( - cx, - &mut new_parents, - &mut notify_views_if_parents_change, - false, - ); element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), editor, - &mut layout_cx, + cx, ) }); @@ -3389,17 +3338,9 @@ mod tests { ); // Don't panic. - let mut scene = SceneBuilder::new(1.0); let bounds = RectF::new(Default::default(), size); editor.update(cx, |editor, cx| { - element.paint( - &mut scene, - bounds, - bounds, - &mut state, - editor, - &mut PaintContext::new(cx), - ); + element.paint(bounds, bounds, &mut state, editor, cx); }); } @@ -3567,18 +3508,10 @@ mod tests { editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx); editor.set_wrap_width(Some(editor_width), cx); - let mut new_parents = Default::default(); - let mut notify_views_if_parents_change = Default::default(); - let mut layout_cx = LayoutContext::new( - cx, - &mut new_parents, - &mut notify_views_if_parents_change, - false, - ); element.layout( SizeConstraint::new(vec2f(editor_width, 500.), vec2f(editor_width, 500.)), editor, - &mut layout_cx, + cx, ) }); diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 2f278ce262f6dd3e0910b022e6956f26c9bdfa6b..3d5b1d21134c90554cbb273f7d058e3db621ad07 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -691,15 +691,15 @@ impl InfoPopover { .with_highlights(rendered_content.highlights.clone()) .with_custom_runs( rendered_content.region_ranges.clone(), - move |ix, bounds, scene, _| { + move |ix, bounds, cx| { region_id += 1; let region = regions[ix].clone(); if let Some(url) = region.link_url { - scene.push_cursor_region(CursorRegion { + cx.scene().push_cursor_region(CursorRegion { bounds, style: CursorStyle::PointingHand, }); - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(view_id, region_id, bounds) .on_click::( MouseButton::Left, @@ -708,7 +708,7 @@ impl InfoPopover { ); } if region.code { - scene.push_quad(gpui::Quad { + cx.scene().push_quad(gpui::Quad { bounds, background: Some(code_span_background_color), border: Default::default(), diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 24397f619357a5454f333c21ef96e4ac369c6397..705feb351d170efdd845537a24bd9b6c219ef08e 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -48,7 +48,8 @@ serde_derive.workspace = true serde_json.workspace = true smallvec.workspace = true smol.workspace = true -taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd", features = ["flexbox"] } +taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "4fb530bdd71609bb1d3f76c6a8bde1ba82805d5e" } +thiserror.workspace = true time.workspace = true tiny-skia = "0.5" usvg = { version = "0.14", features = [] } diff --git a/crates/gpui/examples/corner_radii.rs b/crates/gpui/examples/corner_radii.rs index 1f33917529e55545a2d290699b255b1587cf32c5..75ea3aeec6579bfa2b5b0e2afe78b8dcfc0a75d5 100644 --- a/crates/gpui/examples/corner_radii.rs +++ b/crates/gpui/examples/corner_radii.rs @@ -42,29 +42,28 @@ impl gpui::Element for CornersElement { &mut self, constraint: gpui::SizeConstraint, _: &mut V, - _: &mut gpui::LayoutContext, + _: &mut gpui::ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { (constraint.max, ()) } fn paint( &mut self, - scene: &mut gpui::SceneBuilder, bounds: pathfinder_geometry::rect::RectF, _: pathfinder_geometry::rect::RectF, _: &mut Self::LayoutState, _: &mut V, - _: &mut gpui::PaintContext, + cx: &mut gpui::ViewContext, ) -> Self::PaintState { - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds, background: Some(Color::white()), ..Default::default() }); - scene.push_layer(None); + cx.scene().push_layer(None); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(100., 100.), vec2f(100., 100.)), background: Some(Color::red()), border: Default::default(), @@ -74,7 +73,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(200., 100.), vec2f(100., 100.)), background: Some(Color::green()), border: Default::default(), @@ -84,7 +83,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(100., 200.), vec2f(100., 100.)), background: Some(Color::blue()), border: Default::default(), @@ -94,7 +93,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_quad(Quad { + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(200., 200.), vec2f(100., 100.)), background: Some(Color::yellow()), border: Default::default(), @@ -104,7 +103,7 @@ impl gpui::Element for CornersElement { }, }); - scene.push_shadow(Shadow { + cx.scene().push_shadow(Shadow { bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)), corner_radii: gpui::scene::CornerRadii { bottom_right: 20., @@ -114,8 +113,8 @@ impl gpui::Element for CornersElement { color: Color::black(), }); - scene.push_layer(None); - scene.push_quad(Quad { + cx.scene().push_layer(None); + cx.scene().push_quad(Quad { bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)), background: Some(Color::red()), border: Default::default(), @@ -125,8 +124,8 @@ impl gpui::Element for CornersElement { }, }); - scene.pop_layer(); - scene.pop_layer(); + cx.scene().pop_layer(); + cx.scene().pop_layer(); } fn rect_for_text_range( diff --git a/crates/gpui/examples/text.rs b/crates/gpui/examples/text.rs index bda70a49dc00954c5872d580c4dbadb58ce86e42..bc62d75ec26e4a4f8a1b6a95fa60dddf28298dd8 100644 --- a/crates/gpui/examples/text.rs +++ b/crates/gpui/examples/text.rs @@ -62,12 +62,12 @@ impl gpui::View for TextView { }, ) .with_highlights(vec![(17..26, underline), (34..40, underline)]) - .with_custom_runs(vec![(17..26), (34..40)], move |ix, bounds, scene, _| { - scene.push_cursor_region(CursorRegion { + .with_custom_runs(vec![(17..26), (34..40)], move |ix, bounds, cx| { + cx.scene().push_cursor_region(CursorRegion { bounds, style: CursorStyle::PointingHand, }); - scene.push_mouse_region( + cx.scene().push_mouse_region( MouseRegion::new::(view_id, ix, bounds).on_click::( MouseButton::Left, move |_, _, _| { diff --git a/crates/gpui/playground/Cargo.toml b/crates/gpui/playground/Cargo.toml deleted file mode 100644 index 3e5a5e5606a5e3351104a9587f881ab3caf2fccc..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "playground" -version = "0.1.0" -edition = "2021" -publish = false - -[[bin]] -name = "playground" -path = "src/playground.rs" - -[dependencies] -anyhow.workspace = true -derive_more.workspace = true -gpui = { path = ".." } -log.workspace = true -playground_macros = { path = "../playground_macros" } -parking_lot.workspace = true -refineable.workspace = true -serde.workspace = true -simplelog = "0.9" -smallvec.workspace = true -taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd", features = ["flexbox"] } -util = { path = "../../util" } - -[dev-dependencies] -gpui = { path = "..", features = ["test-support"] } diff --git a/crates/gpui/playground/src/div.rs b/crates/gpui/playground/src/div.rs deleted file mode 100644 index 8efe3590258a4249abd9bb69a359f95692b6a6a0..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/div.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::{ - element::{AnyElement, Element, Layout, ParentElement}, - interactive::{InteractionHandlers, Interactive}, - layout_context::LayoutContext, - paint_context::PaintContext, - style::{Style, StyleHelpers, StyleRefinement, Styleable}, -}; -use anyhow::Result; -use gpui::LayoutId; -use smallvec::SmallVec; - -pub struct Div { - style: StyleRefinement, - handlers: InteractionHandlers, - children: SmallVec<[AnyElement; 2]>, -} - -pub fn div() -> Div { - Div { - style: Default::default(), - handlers: Default::default(), - children: Default::default(), - } -} - -impl Element for Div { - type Layout = (); - - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> - where - Self: Sized, - { - let children = self - .children - .iter_mut() - .map(|child| child.layout(view, cx)) - .collect::>>()?; - - cx.add_layout_node(self.style(), (), children) - } - - fn paint(&mut self, view: &mut V, layout: &mut Layout, cx: &mut PaintContext) - where - Self: Sized, - { - let style = self.style(); - - style.paint_background::(layout, cx); - for child in &mut self.children { - child.paint(view, cx); - } - } -} - -impl Styleable for Div { - type Style = Style; - - fn declared_style(&mut self) -> &mut StyleRefinement { - &mut self.style - } -} - -impl StyleHelpers for Div {} - -impl Interactive for Div { - fn interaction_handlers(&mut self) -> &mut InteractionHandlers { - &mut self.handlers - } -} - -impl ParentElement for Div { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { - &mut self.children - } -} - -#[test] -fn test() { - // let elt = div().w_auto(); -} - -// trait Element { -// type Style; - -// fn layout() -// } - -// trait Stylable: Element { -// type Style; - -// fn with_style(self, style: Self::Style) -> Self; -// } - -// pub struct HoverStyle { -// default: S, -// hovered: S, -// } - -// struct Hover> { -// child: C, -// style: HoverStyle, -// } - -// impl> Hover { -// fn new(child: C, style: HoverStyle) -> Self { -// Self { child, style } -// } -// } diff --git a/crates/gpui/playground/src/element.rs b/crates/gpui/playground/src/element.rs deleted file mode 100644 index 082f3b02b06522f3c12b435e6d02febd4a319390..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/element.rs +++ /dev/null @@ -1,158 +0,0 @@ -use anyhow::Result; -use derive_more::{Deref, DerefMut}; -use gpui::{geometry::rect::RectF, EngineLayout}; -use smallvec::SmallVec; -use std::marker::PhantomData; -use util::ResultExt; - -pub use crate::layout_context::LayoutContext; -pub use crate::paint_context::PaintContext; - -type LayoutId = gpui::LayoutId; - -pub trait Element: 'static { - type Layout; - - fn layout( - &mut self, - view: &mut V, - cx: &mut LayoutContext, - ) -> Result> - where - Self: Sized; - - fn paint( - &mut self, - view: &mut V, - layout: &mut Layout, - cx: &mut PaintContext, - ) where - Self: Sized; - - fn into_any(self) -> AnyElement - where - Self: 'static + Sized, - { - AnyElement(Box::new(ElementState { - element: self, - layout: None, - })) - } -} - -/// Used to make ElementState into a trait object, so we can wrap it in AnyElement. -trait ElementStateObject { - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result; - fn paint(&mut self, view: &mut V, cx: &mut PaintContext); -} - -/// A wrapper around an element that stores its layout state. -struct ElementState> { - element: E, - layout: Option>, -} - -/// We blanket-implement the object-safe ElementStateObject interface to make ElementStates into trait objects -impl> ElementStateObject for ElementState { - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result { - let layout = self.element.layout(view, cx)?; - let layout_id = layout.id; - self.layout = Some(layout); - Ok(layout_id) - } - - fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { - let layout = self.layout.as_mut().expect("paint called before layout"); - if layout.engine_layout.is_none() { - layout.engine_layout = cx.computed_layout(layout.id).log_err() - } - self.element.paint(view, layout, cx) - } -} - -/// A dynamic element. -pub struct AnyElement(Box>); - -impl AnyElement { - pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result { - self.0.layout(view, cx) - } - - pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { - self.0.paint(view, cx) - } -} - -#[derive(Deref, DerefMut)] -pub struct Layout { - id: LayoutId, - engine_layout: Option, - #[deref] - #[deref_mut] - element_data: D, - view_type: PhantomData, -} - -impl Layout { - pub fn new(id: LayoutId, element_data: D) -> Self { - Self { - id, - engine_layout: None, - element_data: element_data, - view_type: PhantomData, - } - } - - pub fn bounds(&mut self, cx: &mut PaintContext) -> RectF { - self.engine_layout(cx).bounds - } - - pub fn order(&mut self, cx: &mut PaintContext) -> u32 { - self.engine_layout(cx).order - } - - fn engine_layout(&mut self, cx: &mut PaintContext<'_, '_, '_, '_, V>) -> &mut EngineLayout { - self.engine_layout - .get_or_insert_with(|| cx.computed_layout(self.id).log_err().unwrap_or_default()) - } -} - -impl Layout>> { - pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { - let mut element = self.element_data.take().unwrap(); - element.paint(view, cx); - self.element_data = Some(element); - } -} - -pub trait ParentElement { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; - - fn child(mut self, child: impl IntoElement) -> Self - where - Self: Sized, - { - self.children_mut().push(child.into_element().into_any()); - self - } - - fn children(mut self, children: I) -> Self - where - I: IntoIterator, - E: IntoElement, - Self: Sized, - { - self.children_mut().extend( - children - .into_iter() - .map(|child| child.into_element().into_any()), - ); - self - } -} - -pub trait IntoElement { - type Element: Element; - - fn into_element(self) -> Self::Element; -} diff --git a/crates/gpui/playground/src/hoverable.rs b/crates/gpui/playground/src/hoverable.rs deleted file mode 100644 index 5545155a60c4e55e15bc534843c76a0e6f543d36..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/hoverable.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::{ - element::{Element, Layout}, - layout_context::LayoutContext, - paint_context::PaintContext, - style::{StyleRefinement, Styleable}, -}; -use anyhow::Result; -use gpui::platform::MouseMovedEvent; -use refineable::Refineable; -use std::{cell::Cell, marker::PhantomData}; - -pub struct Hoverable + Styleable> { - hovered: Cell, - child_style: StyleRefinement, - hovered_style: StyleRefinement, - child: E, - view_type: PhantomData, -} - -pub fn hoverable + Styleable>(mut child: E) -> Hoverable { - Hoverable { - hovered: Cell::new(false), - child_style: child.declared_style().clone(), - hovered_style: Default::default(), - child, - view_type: PhantomData, - } -} - -impl + Styleable> Styleable for Hoverable { - type Style = E::Style; - - fn declared_style(&mut self) -> &mut crate::style::StyleRefinement { - self.child.declared_style() - } -} - -impl + Styleable> Element for Hoverable { - type Layout = E::Layout; - - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> - where - Self: Sized, - { - self.child.layout(view, cx) - } - - fn paint( - &mut self, - view: &mut V, - layout: &mut Layout, - cx: &mut PaintContext, - ) where - Self: Sized, - { - if self.hovered.get() { - // If hovered, refine the child's style with this element's style. - self.child.declared_style().refine(&self.hovered_style); - } else { - // Otherwise, set the child's style back to its original style. - *self.child.declared_style() = self.child_style.clone(); - } - - let bounds = layout.bounds(cx); - let order = layout.order(cx); - self.hovered.set(bounds.contains_point(cx.mouse_position())); - let was_hovered = self.hovered.clone(); - cx.on_event(order, move |view, event: &MouseMovedEvent, cx| { - let is_hovered = bounds.contains_point(event.position); - if is_hovered != was_hovered.get() { - was_hovered.set(is_hovered); - cx.repaint(); - } - }); - } -} diff --git a/crates/gpui/playground/src/interactive.rs b/crates/gpui/playground/src/interactive.rs deleted file mode 100644 index 8debcb1692cc5bcd42a8e65e82aa27ad6a02d4a0..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/interactive.rs +++ /dev/null @@ -1,34 +0,0 @@ -use gpui::{platform::MouseMovedEvent, EventContext}; -use smallvec::SmallVec; -use std::rc::Rc; - -pub trait Interactive { - fn interaction_handlers(&mut self) -> &mut InteractionHandlers; - - fn on_mouse_move(mut self, handler: H) -> Self - where - H: 'static + Fn(&mut V, &MouseMovedEvent, bool, &mut EventContext), - Self: Sized, - { - self.interaction_handlers() - .mouse_moved - .push(Rc::new(move |view, event, hit_test, cx| { - handler(view, event, hit_test, cx); - cx.bubble - })); - self - } -} - -pub struct InteractionHandlers { - mouse_moved: - SmallVec<[Rc) -> bool>; 2]>, -} - -impl Default for InteractionHandlers { - fn default() -> Self { - Self { - mouse_moved: Default::default(), - } - } -} diff --git a/crates/gpui/playground/src/layout_context.rs b/crates/gpui/playground/src/layout_context.rs deleted file mode 100644 index 7c9f13e7f08519c13a7ac78c2f90bd628e8fd3a8..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/layout_context.rs +++ /dev/null @@ -1,54 +0,0 @@ -use anyhow::{anyhow, Result}; -use derive_more::{Deref, DerefMut}; -pub use gpui::LayoutContext as LegacyLayoutContext; -use gpui::{RenderContext, ViewContext}; -pub use taffy::tree::NodeId; - -use crate::{element::Layout, style::Style}; - -#[derive(Deref, DerefMut)] -pub struct LayoutContext<'a, 'b, 'c, 'd, V> { - #[deref] - #[deref_mut] - pub(crate) legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>, -} - -impl<'a, 'b, V> RenderContext<'a, 'b, V> for LayoutContext<'a, 'b, '_, '_, V> { - fn text_style(&self) -> gpui::fonts::TextStyle { - self.legacy_cx.text_style() - } - - fn push_text_style(&mut self, style: gpui::fonts::TextStyle) { - self.legacy_cx.push_text_style(style) - } - - fn pop_text_style(&mut self) { - self.legacy_cx.pop_text_style() - } - - fn as_view_context(&mut self) -> &mut ViewContext<'a, 'b, V> { - &mut self.view_context - } -} - -impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> { - pub fn new(legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>) -> Self { - Self { legacy_cx } - } - - pub fn add_layout_node( - &mut self, - style: Style, - element_data: D, - children: impl IntoIterator, - ) -> Result> { - let rem_size = self.rem_pixels(); - let id = self - .legacy_cx - .layout_engine() - .ok_or_else(|| anyhow!("no layout engine"))? - .add_node(style.to_taffy(rem_size), children)?; - - Ok(Layout::new(id, element_data)) - } -} diff --git a/crates/gpui/playground/src/paint_context.rs b/crates/gpui/playground/src/paint_context.rs deleted file mode 100644 index d853aff7f85ff4b8b434dffb6e99caca9f91d0d2..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/paint_context.rs +++ /dev/null @@ -1,71 +0,0 @@ -use anyhow::{anyhow, Result}; -use derive_more::{Deref, DerefMut}; -use gpui::{scene::EventHandler, EngineLayout, EventContext, LayoutId, RenderContext, ViewContext}; -pub use gpui::{LayoutContext, PaintContext as LegacyPaintContext}; -use std::{any::TypeId, rc::Rc}; -pub use taffy::tree::NodeId; - -#[derive(Deref, DerefMut)] -pub struct PaintContext<'a, 'b, 'c, 'd, V> { - #[deref] - #[deref_mut] - pub(crate) legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, - pub(crate) scene: &'d mut gpui::SceneBuilder, -} - -impl<'a, 'b, V> RenderContext<'a, 'b, V> for PaintContext<'a, 'b, '_, '_, V> { - fn text_style(&self) -> gpui::fonts::TextStyle { - self.legacy_cx.text_style() - } - - fn push_text_style(&mut self, style: gpui::fonts::TextStyle) { - self.legacy_cx.push_text_style(style) - } - - fn pop_text_style(&mut self) { - self.legacy_cx.pop_text_style() - } - - fn as_view_context(&mut self) -> &mut ViewContext<'a, 'b, V> { - &mut self.view_context - } -} - -impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { - pub fn new( - legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, - scene: &'d mut gpui::SceneBuilder, - ) -> Self { - Self { legacy_cx, scene } - } - - pub fn on_event( - &mut self, - order: u32, - handler: impl Fn(&mut V, &E, &mut ViewContext) + 'static, - ) { - let view = self.weak_handle(); - - self.scene.event_handlers.push(EventHandler { - order, - handler: Rc::new(move |event, window_cx| { - if let Some(view) = view.upgrade(window_cx) { - view.update(window_cx, |view, view_cx| { - let mut event_cx = EventContext::new(view_cx); - handler(view, event.downcast_ref().unwrap(), &mut event_cx); - event_cx.bubble - }) - } else { - true - } - }), - event_type: TypeId::of::(), - }) - } - - pub(crate) fn computed_layout(&mut self, layout_id: LayoutId) -> Result { - self.layout_engine() - .ok_or_else(|| anyhow!("no layout engine present"))? - .computed_layout(layout_id) - } -} diff --git a/crates/gpui/playground/src/playground.rs b/crates/gpui/playground/src/playground.rs deleted file mode 100644 index 2462ac99f59e412cdbd16d3b616503dcb7810660..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/playground.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![allow(dead_code, unused_variables)] -use crate::{color::black, style::StyleHelpers}; -use element::Element; -use gpui::{ - geometry::{rect::RectF, vector::vec2f}, - platform::WindowOptions, -}; -use log::LevelFilter; -use simplelog::SimpleLogger; -use themes::{rose_pine, ThemeColors}; -use view::view; - -mod adapter; -mod color; -mod components; -mod div; -mod element; -mod hoverable; -mod interactive; -mod layout_context; -mod paint_context; -mod style; -mod text; -mod themes; -mod view; - -fn main() { - SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger"); - - gpui::App::new(()).unwrap().run(|cx| { - cx.add_window( - WindowOptions { - bounds: gpui::platform::WindowBounds::Fixed(RectF::new( - vec2f(0., 0.), - vec2f(400., 300.), - )), - center: true, - ..Default::default() - }, - |_| view(|_| playground(&rose_pine::moon())), - ); - cx.platform().activate(true); - }); -} - -fn playground(theme: &ThemeColors) -> impl Element { - use div::div; - - div() - .text_color(black()) - .h_full() - .w_1_2() - .fill(theme.success(0.5)) - // .hover() - // .fill(theme.error(0.5)) - // .child(button().label("Hello").click(|_, _, _| println!("click!"))) -} - -// todo!() -// // column() -// // .size(auto()) -// // .fill(theme.base(0.5)) -// // .text_color(theme.text(0.5)) -// // .child(title_bar(theme)) -// // .child(stage(theme)) -// // .child(status_bar(theme)) -// } - -// fn title_bar(theme: &ThemeColors) -> impl Element { -// row() -// .fill(theme.base(0.2)) -// .justify(0.) -// .width(auto()) -// .child(text("Zed Playground")) -// } - -// fn stage(theme: &ThemeColors) -> impl Element { -// row().fill(theme.surface(0.9)) -// } - -// fn status_bar(theme: &ThemeColors) -> impl Element { -// row().fill(theme.surface(0.1)) -// } diff --git a/crates/gpui/playground/src/style.rs b/crates/gpui/playground/src/style.rs deleted file mode 100644 index 9216702f7fab3a50cc4a27502ebd3a383db5134f..0000000000000000000000000000000000000000 --- a/crates/gpui/playground/src/style.rs +++ /dev/null @@ -1,286 +0,0 @@ -use crate::{ - color::Hsla, - element::{Element, Layout}, - paint_context::PaintContext, -}; -use gpui::{ - fonts::TextStyleRefinement, - geometry::{ - AbsoluteLength, DefiniteLength, Edges, EdgesRefinement, Length, Point, PointRefinement, - Size, SizeRefinement, - }, -}; -use playground_macros::styleable_helpers; -use refineable::Refineable; -pub use taffy::style::{ - AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, - Overflow, Position, -}; - -#[derive(Clone, Refineable)] -pub struct Style { - /// What layout strategy should be used? - pub display: Display, - - // Overflow properties - /// How children overflowing their container should affect layout - #[refineable] - pub overflow: Point, - /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes. - pub scrollbar_width: f32, - - // Position properties - /// What should the `position` value of this struct use as a base offset? - pub position: Position, - /// How should the position of this element be tweaked relative to the layout defined? - #[refineable] - pub inset: Edges, - - // Size properies - /// Sets the initial size of the item - #[refineable] - pub size: Size, - /// Controls the minimum size of the item - #[refineable] - pub min_size: Size, - /// Controls the maximum size of the item - #[refineable] - pub max_size: Size, - /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height. - pub aspect_ratio: Option, - - // Spacing Properties - /// How large should the margin be on each side? - #[refineable] - pub margin: Edges, - /// How large should the padding be on each side? - #[refineable] - pub padding: Edges, - /// How large should the border be on each side? - #[refineable] - pub border: Edges, - - // Alignment properties - /// How this node's children aligned in the cross/block axis? - pub align_items: Option, - /// How this node should be aligned in the cross/block axis. Falls back to the parents [`AlignItems`] if not set - pub align_self: Option, - /// How should content contained within this item be aligned in the cross/block axis - pub align_content: Option, - /// How should contained within this item be aligned in the main/inline axis - pub justify_content: Option, - /// How large should the gaps between items in a flex container be? - #[refineable] - pub gap: Size, - - // Flexbox properies - /// Which direction does the main axis flow in? - pub flex_direction: FlexDirection, - /// Should elements wrap, or stay in a single line? - pub flex_wrap: FlexWrap, - /// Sets the initial main axis size of the item - pub flex_basis: Length, - /// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive. - pub flex_grow: f32, - /// The relative rate at which this item shrinks when it is contracting to fit into space, 1.0 is the default value, and this value must be positive. - pub flex_shrink: f32, - - /// The fill color of this element - pub fill: Option, - /// The radius of the corners of this element - #[refineable] - pub corner_radii: CornerRadii, - /// The color of text within this element. Cascades to children unless overridden. - pub text_color: Option, -} - -impl Style { - pub fn to_taffy(&self, rem_size: f32) -> taffy::style::Style { - taffy::style::Style { - display: self.display, - overflow: self.overflow.clone().into(), - scrollbar_width: self.scrollbar_width, - position: self.position, - inset: self.inset.to_taffy(rem_size), - size: self.size.to_taffy(rem_size), - min_size: self.min_size.to_taffy(rem_size), - max_size: self.max_size.to_taffy(rem_size), - aspect_ratio: self.aspect_ratio, - margin: self.margin.to_taffy(rem_size), - padding: self.padding.to_taffy(rem_size), - border: self.border.to_taffy(rem_size), - align_items: self.align_items, - align_self: self.align_self, - align_content: self.align_content, - justify_content: self.justify_content, - gap: self.gap.to_taffy(rem_size), - flex_direction: self.flex_direction, - flex_wrap: self.flex_wrap, - flex_basis: self.flex_basis.to_taffy(rem_size).into(), - flex_grow: self.flex_grow, - flex_shrink: self.flex_shrink, - ..Default::default() // Ignore grid properties for now - } - } - - /// Paints the background of an element styled with this style. - /// Return the bounds in which to paint the content. - pub fn paint_background>( - &self, - layout: &mut Layout, - cx: &mut PaintContext, - ) { - let bounds = layout.bounds(cx); - let rem_size = cx.rem_pixels(); - if let Some(color) = self.fill.as_ref().and_then(Fill::color) { - cx.scene.push_quad(gpui::Quad { - bounds, - background: Some(color.into()), - corner_radii: self.corner_radii.to_gpui(rem_size), - border: Default::default(), - }); - } - } -} - -impl Default for Style { - fn default() -> Self { - Style { - display: Display::DEFAULT, - overflow: Point { - x: Overflow::Visible, - y: Overflow::Visible, - }, - scrollbar_width: 0.0, - position: Position::Relative, - inset: Edges::auto(), - margin: Edges::::zero(), - padding: Edges::::zero(), - border: Edges::::zero(), - size: Size::auto(), - min_size: Size::auto(), - max_size: Size::auto(), - aspect_ratio: None, - gap: Size::zero(), - // Aligment - align_items: None, - align_self: None, - align_content: None, - justify_content: None, - // Flexbox - flex_direction: FlexDirection::Row, - flex_wrap: FlexWrap::NoWrap, - flex_grow: 0.0, - flex_shrink: 1.0, - flex_basis: Length::Auto, - fill: None, - text_color: None, - corner_radii: CornerRadii::default(), - } - } -} - -impl StyleRefinement { - pub fn text_style(&self) -> Option { - self.text_color.map(|color| TextStyleRefinement { - color: Some(color.into()), - ..Default::default() - }) - } -} - -pub struct OptionalTextStyle { - color: Option, -} - -impl OptionalTextStyle { - pub fn apply(&self, style: &mut gpui::fonts::TextStyle) { - if let Some(color) = self.color { - style.color = color.into(); - } - } -} - -#[derive(Clone)] -pub enum Fill { - Color(Hsla), -} - -impl Fill { - pub fn color(&self) -> Option { - match self { - Fill::Color(color) => Some(*color), - } - } -} - -impl Default for Fill { - fn default() -> Self { - Self::Color(Hsla::default()) - } -} - -impl From for Fill { - fn from(color: Hsla) -> Self { - Self::Color(color) - } -} - -#[derive(Clone, Refineable, Default)] -pub struct CornerRadii { - top_left: AbsoluteLength, - top_right: AbsoluteLength, - bottom_left: AbsoluteLength, - bottom_right: AbsoluteLength, -} - -impl CornerRadii { - pub fn to_gpui(&self, rem_size: f32) -> gpui::scene::CornerRadii { - gpui::scene::CornerRadii { - top_left: self.top_left.to_pixels(rem_size), - top_right: self.top_right.to_pixels(rem_size), - bottom_left: self.bottom_left.to_pixels(rem_size), - bottom_right: self.bottom_right.to_pixels(rem_size), - } - } -} - -pub trait Styleable { - type Style: refineable::Refineable; - - fn declared_style(&mut self) -> &mut playground::style::StyleRefinement; - - fn style(&mut self) -> playground::style::Style { - let mut style = playground::style::Style::default(); - style.refine(self.declared_style()); - style - } -} - -// Helpers methods that take and return mut self. This includes tailwind style methods for standard sizes etc. -// -// Example: -// // Sets the padding to 0.5rem, just like class="p-2" in Tailwind. -// fn p_2(mut self) -> Self where Self: Sized; -use crate as playground; // Macro invocation references this crate as playground. -pub trait StyleHelpers: Styleable