diff --git a/gpui/src/elements/container.rs b/gpui/src/elements/container.rs index 31cbdff1c8..eca434e383 100644 --- a/gpui/src/elements/container.rs +++ b/gpui/src/elements/container.rs @@ -1,6 +1,9 @@ +use pathfinder_geometry::rect::RectF; + use crate::{ color::ColorU, geometry::vector::{vec2f, Vector2F}, + scene::{Border, Quad}, AfterLayoutContext, AppContext, Element, Event, EventContext, LayoutContext, MutableAppContext, PaintContext, SizeConstraint, }; @@ -141,110 +144,13 @@ impl Element for Container { } fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext, app: &AppContext) { - // self.origin = Some(origin); - - // let canvas = &mut ctx.canvas; - // let size = self.size.unwrap() - self.margin_size() - // + vec2f(self.overdraw.right, self.overdraw.bottom); - // let origin = origin + vec2f(self.margin.left, self.margin.top) - // - vec2f(self.overdraw.left, self.overdraw.top); - // let rect = RectF::new(origin, size); - - // let mut path = Path2D::new(); - // if self.corner_radius > 0.0 { - // path.move_to(rect.upper_right() - vec2f(self.corner_radius, 0.0)); - // path.arc_to( - // rect.upper_right(), - // rect.upper_right() + vec2f(0.0, self.corner_radius), - // self.corner_radius, - // ); - // path.line_to(rect.lower_right() - vec2f(0.0, self.corner_radius)); - // path.arc_to( - // rect.lower_right(), - // rect.lower_right() - vec2f(self.corner_radius, 0.0), - // self.corner_radius, - // ); - // path.line_to(rect.lower_left() + vec2f(self.corner_radius, 0.0)); - // path.arc_to( - // rect.lower_left(), - // rect.lower_left() - vec2f(0.0, self.corner_radius), - // self.corner_radius, - // ); - // path.line_to(origin + vec2f(0.0, self.corner_radius)); - // path.arc_to( - // origin, - // origin + vec2f(self.corner_radius, 0.0), - // self.corner_radius, - // ); - // path.close_path(); - // } else { - // path.rect(rect); - // } - - // canvas.save(); - // if let Some(shadow) = self.shadow.as_ref() { - // canvas.set_shadow_offset(shadow.offset); - // canvas.set_shadow_blur(shadow.blur); - // canvas.set_shadow_color(shadow.color); - // } - - // if let Some(background_color) = self.background_color { - // canvas.set_fill_style(FillStyle::Color(background_color)); - // canvas.fill_path(path.clone(), FillRule::Winding); - // } - - // canvas.set_line_width(self.border.width); - // canvas.set_stroke_style(FillStyle::Color(self.border.color)); - - // let border_rect = rect.contract(self.border.width / 2.0); - - // // For now, we ignore the corner radius unless we draw a border on all sides. - // // This could be improved. - // if self.border.all_sides() { - // let mut path = Path2D::new(); - // path.rect(border_rect); - // canvas.stroke_path(path); - // } else { - // canvas.set_line_cap(LineCap::Square); - - // if self.border.top { - // let mut path = Path2D::new(); - // path.move_to(border_rect.origin()); - // path.line_to(border_rect.upper_right()); - // canvas.stroke_path(path); - // } - - // if self.border.left { - // let mut path = Path2D::new(); - // path.move_to(border_rect.origin()); - // path.line_to(border_rect.lower_left()); - // canvas.stroke_path(path); - // } - - // if self.border.bottom { - // let mut path = Path2D::new(); - // path.move_to(border_rect.lower_left()); - // path.line_to(border_rect.lower_right()); - // canvas.stroke_path(path); - // } - - // if self.border.right { - // let mut path = Path2D::new(); - // path.move_to(border_rect.upper_right()); - // path.line_to(border_rect.lower_right()); - // canvas.stroke_path(path); - // } - // } - // canvas.restore(); - - // let mut child_origin = origin + vec2f(self.padding.left, self.padding.top); - // if self.border.left { - // child_origin.set_x(child_origin.x() + self.border.width); - // } - // if self.border.top { - // child_origin.set_y(child_origin.y() + self.border.width); - // } - // self.child.paint(child_origin, ctx, app); + ctx.scene.push_quad(Quad { + bounds: RectF::new(origin, self.size.unwrap()), + background: self.background_color, + border: self.border, + corder_radius: self.corner_radius, + }); + self.child.paint(origin, ctx, app); } fn dispatch_event(&self, event: &Event, ctx: &mut EventContext, app: &AppContext) -> bool { @@ -280,76 +186,6 @@ pub struct Overdraw { right: f32, } -#[derive(Default)] -pub struct Border { - width: f32, - color: ColorU, - pub top: bool, - pub left: bool, - pub bottom: bool, - pub right: bool, -} - -impl Border { - pub fn new(width: f32, color: impl Into) -> Self { - Self { - width, - color: color.into(), - top: false, - left: false, - bottom: false, - right: false, - } - } - - pub fn all(width: f32, color: impl Into) -> Self { - Self { - width, - color: color.into(), - top: true, - left: true, - bottom: true, - right: true, - } - } - - pub fn top(width: f32, color: impl Into) -> Self { - let mut border = Self::new(width, color); - border.top = true; - border - } - - pub fn left(width: f32, color: impl Into) -> Self { - let mut border = Self::new(width, color); - border.left = true; - border - } - - pub fn bottom(width: f32, color: impl Into) -> Self { - let mut border = Self::new(width, color); - border.bottom = true; - border - } - - pub fn right(width: f32, color: impl Into) -> Self { - let mut border = Self::new(width, color); - border.right = true; - border - } - - pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self { - self.top = top; - self.left = left; - self.bottom = bottom; - self.right = right; - self - } - - fn all_sides(&self) -> bool { - self.top && self.left && self.bottom && self.right - } -} - #[derive(Default)] pub struct Shadow { offset: Vector2F, diff --git a/gpui/src/elements/empty.rs b/gpui/src/elements/empty.rs index 493968167c..75db1ffa9e 100644 --- a/gpui/src/elements/empty.rs +++ b/gpui/src/elements/empty.rs @@ -25,7 +25,7 @@ impl Element for Empty { _: &mut LayoutContext, _: &AppContext, ) -> Vector2F { - self.size = Some(constraint.min); + self.size = Some(constraint.max); constraint.max } diff --git a/gpui/src/lib.rs b/gpui/src/lib.rs index d55b402971..800bfaba18 100644 --- a/gpui/src/lib.rs +++ b/gpui/src/lib.rs @@ -7,7 +7,7 @@ pub mod fonts; pub use fonts::FontCache; mod presenter; mod scene; -pub use scene::Scene; +pub use scene::{Border, Scene}; pub mod text_layout; pub use text_layout::TextLayoutCache; mod util; diff --git a/gpui/src/presenter.rs b/gpui/src/presenter.rs index f4bd495b88..71fedbc1b8 100644 --- a/gpui/src/presenter.rs +++ b/gpui/src/presenter.rs @@ -52,10 +52,23 @@ impl Presenter { scale_factor: f32, app: &mut MutableAppContext, ) -> Scene { - self.layout(window_size, app.downgrade()); - self.after_layout(app); - let scene = self.paint(window_size, scale_factor, app.downgrade()); - self.text_layout_cache.finish_frame(); + let mut scene = Scene::new(scale_factor); + + if let Some(root_view_id) = app.root_view_id(self.window_id) { + self.layout(window_size, app.downgrade()); + self.after_layout(app); + let mut paint_ctx = PaintContext { + scene: &mut scene, + font_cache: &self.font_cache, + text_layout_cache: &self.text_layout_cache, + rendered_views: &mut self.rendered_views, + }; + paint_ctx.paint(root_view_id, Vector2F::zero(), app.downgrade()); + self.text_layout_cache.finish_frame(); + } else { + log::error!("could not find root_view_id for window {}", self.window_id); + } + scene } @@ -84,24 +97,6 @@ impl Presenter { } } - fn paint(&mut self, _size: Vector2F, _scale_factor: f32, _app: &AppContext) -> Scene { - // let mut canvas = Canvas::new(size * scale_factor).get_context_2d(self.font_context.clone()); - // canvas.scale(scale_factor); - - // if let Some(root_view_id) = app.root_view_id(self.window_id) { - // let mut paint_ctx = PaintContext { - // canvas: &mut canvas, - // font_cache: &self.font_cache, - // text_layout_cache: &self.text_layout_cache, - // rendered_views: &mut self.rendered_views, - // }; - // paint_ctx.paint(root_view_id, Vector2F::zero(), app); - // } - - // canvas.into_canvas().into_scene() - Scene {} - } - pub fn responder_chain(&self, app: &AppContext) -> Option> { app.focused_view_id(self.window_id).map(|mut view_id| { let mut chain = vec![view_id]; @@ -173,7 +168,7 @@ impl<'a> AfterLayoutContext<'a> { pub struct PaintContext<'a> { rendered_views: &'a mut HashMap>, - // pub canvas: &'a mut CanvasRenderingContext2D, + pub scene: &'a mut Scene, pub font_cache: &'a FontCache, pub text_layout_cache: &'a TextLayoutCache, } diff --git a/gpui/src/scene.rs b/gpui/src/scene.rs index c894078ad2..85e1f788d4 100644 --- a/gpui/src/scene.rs +++ b/gpui/src/scene.rs @@ -1 +1,121 @@ -pub struct Scene; +use crate::{color::ColorU, geometry::rect::RectF}; +pub struct Scene { + scale_factor: f32, + layers: Vec, + active_layer_stack: Vec, +} + +#[derive(Default)] +struct Layer { + clip_bounds: Option, + quads: Vec, +} + +#[derive(Default)] +pub struct Quad { + pub bounds: RectF, + pub background: Option, + pub border: Border, + pub corder_radius: f32, +} + +#[derive(Clone, Copy, Default)] +pub struct Border { + pub width: f32, + pub color: Option, + pub top: bool, + pub right: bool, + pub bottom: bool, + pub left: bool, +} + +impl Scene { + pub fn new(scale_factor: f32) -> Self { + Scene { + scale_factor, + layers: vec![Layer::default()], + active_layer_stack: vec![0], + } + } + + pub fn push_layer(&mut self, clip_bounds: Option) {} + + pub fn pop_layer(&mut self) { + assert!(self.active_layer_stack.len() > 1); + self.active_layer_stack.pop(); + } + + pub fn push_quad(&mut self, quad: Quad) { + self.active_layer().push_quad(quad) + } + + fn active_layer(&mut self) -> &mut Layer { + &mut self.layers[*self.active_layer_stack.last().unwrap()] + } +} + +impl Layer { + fn push_quad(&mut self, quad: Quad) { + self.quads.push(quad); + } +} + +impl Border { + pub fn new(width: f32, color: impl Into) -> Self { + Self { + width, + color: Some(color.into()), + top: false, + left: false, + bottom: false, + right: false, + } + } + + pub fn all(width: f32, color: impl Into) -> Self { + Self { + width, + color: Some(color.into()), + top: true, + left: true, + bottom: true, + right: true, + } + } + + pub fn top(width: f32, color: impl Into) -> Self { + let mut border = Self::new(width, color); + border.top = true; + border + } + + pub fn left(width: f32, color: impl Into) -> Self { + let mut border = Self::new(width, color); + border.left = true; + border + } + + pub fn bottom(width: f32, color: impl Into) -> Self { + let mut border = Self::new(width, color); + border.bottom = true; + border + } + + pub fn right(width: f32, color: impl Into) -> Self { + let mut border = Self::new(width, color); + border.right = true; + border + } + + pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self { + self.top = top; + self.left = left; + self.bottom = bottom; + self.right = right; + self + } + + fn all_sides(&self) -> bool { + self.top && self.left && self.bottom && self.right + } +} diff --git a/zed/src/main.rs b/zed/src/main.rs index 576e9b919a..ee9e22e8db 100644 --- a/zed/src/main.rs +++ b/zed/src/main.rs @@ -2,7 +2,7 @@ use fs::OpenOptions; use gpui::platform::{current as platform, Runner as _}; use log::LevelFilter; use simplelog::SimpleLogger; -use std::{fs, mem, path::PathBuf}; +use std::{fs, path::PathBuf}; use zed::{ assets, editor, settings, workspace::{self, OpenParams}, diff --git a/zed/src/workspace/pane.rs b/zed/src/workspace/pane.rs index 5857ef6cfc..49aed9967f 100644 --- a/zed/src/workspace/pane.rs +++ b/zed/src/workspace/pane.rs @@ -1,7 +1,7 @@ use super::{ItemViewHandle, SplitDirection}; use crate::{settings::Settings, watch}; use gpui::{ - color::ColorU, elements::*, keymap::Binding, App, AppContext, ChildView, Entity, View, + color::ColorU, elements::*, keymap::Binding, App, AppContext, Border, ChildView, Entity, View, ViewContext, }; use std::cmp; diff --git a/zed/src/workspace/pane_group.rs b/zed/src/workspace/pane_group.rs index 5a3e3df09f..96e85634ce 100644 --- a/zed/src/workspace/pane_group.rs +++ b/zed/src/workspace/pane_group.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Result}; use gpui::{ color::{rgbu, ColorU}, elements::*, - Axis, ChildView, + Axis, Border, ChildView, }; #[derive(Clone, Debug, Eq, PartialEq)]