node.rs

   1#![allow(unused_variables, dead_code)]
   2
   3use derive_more::{Add, Deref, DerefMut};
   4use gpui::elements::layout_highlighted_chunks;
   5use gpui::Entity;
   6use gpui::{
   7    color::Color,
   8    fonts::HighlightStyle,
   9    geometry::{
  10        rect::RectF,
  11        vector::{vec2f, Vector2F},
  12    },
  13    json::{json, ToJson},
  14    scene,
  15    serde_json::Value,
  16    text_layout::{Line, ShapedBoundary},
  17    AnyElement, AppContext, Element, LayoutContext, PaintContext, Quad, SceneBuilder,
  18    SizeConstraint, View, ViewContext,
  19};
  20use length::{Length, Rems};
  21use log::warn;
  22use optional_struct::*;
  23use std::{any::Any, borrow::Cow, f32, ops::Range, sync::Arc};
  24
  25use crate::color::Rgba;
  26
  27pub struct Node<V: View> {
  28    style: NodeStyle,
  29    children: Vec<AnyElement<V>>,
  30    id: Option<Cow<'static, str>>,
  31}
  32
  33pub fn column<V: View>() -> Node<V> {
  34    Node::default()
  35}
  36
  37pub fn row<V: View>() -> Node<V> {
  38    Node {
  39        style: NodeStyle {
  40            axis: Axis3d::X,
  41            ..Default::default()
  42        },
  43        ..Default::default()
  44    }
  45}
  46
  47pub fn stack<V: View>() -> Node<V> {
  48    Node {
  49        style: NodeStyle {
  50            axis: Axis3d::Z,
  51            ..Default::default()
  52        },
  53        ..Default::default()
  54    }
  55}
  56
  57impl<V: View> Default for Node<V> {
  58    fn default() -> Self {
  59        Self {
  60            style: Default::default(),
  61            children: Default::default(),
  62            id: None,
  63        }
  64    }
  65}
  66
  67impl<V: View> Element<V> for Node<V> {
  68    type LayoutState = NodeLayout;
  69    type PaintState = ();
  70
  71    fn layout(
  72        &mut self,
  73        constraint: SizeConstraint,
  74        view: &mut V,
  75        cx: &mut LayoutContext<V>,
  76    ) -> (Vector2F, Self::LayoutState) {
  77        let layout = if let Some(axis) = self.style.axis.to_2d() {
  78            self.layout_xy(axis, constraint, cx.rem_pixels(), view, cx)
  79        } else {
  80            todo!()
  81        };
  82
  83        (layout.size.max(constraint.min), layout)
  84    }
  85
  86    fn paint(
  87        &mut self,
  88        scene: &mut SceneBuilder,
  89        bounds: RectF,
  90        visible_bounds: RectF,
  91        layout: &mut NodeLayout,
  92        view: &mut V,
  93        cx: &mut PaintContext<V>,
  94    ) -> Self::PaintState {
  95        dbg!(self.id_string());
  96        dbg!(bounds.origin(), bounds.size());
  97
  98        let bounds_center = dbg!(bounds.size()) / 2.;
  99        let bounds_target = bounds_center + (bounds_center * self.style.align.0);
 100        let layout_center = dbg!(layout.size) / 2.;
 101        let layout_target = layout_center + layout_center * self.style.align.0;
 102        let delta = bounds_target - layout_target;
 103
 104        let aligned_bounds = RectF::new(bounds.origin() + delta, layout.size);
 105        dbg!(aligned_bounds.origin(), aligned_bounds.size());
 106        let margined_bounds = RectF::from_points(
 107            aligned_bounds.origin() + vec2f(layout.margins.left, layout.margins.top),
 108            aligned_bounds.lower_right() - vec2f(layout.margins.right, layout.margins.bottom),
 109        );
 110        dbg!(margined_bounds.origin(), margined_bounds.size());
 111
 112        // Paint drop shadow
 113        for shadow in &self.style.shadows {
 114            scene.push_shadow(scene::Shadow {
 115                bounds: margined_bounds + shadow.offset,
 116                corner_radius: self.style.corner_radius,
 117                sigma: shadow.blur,
 118                color: shadow.color,
 119            });
 120        }
 121
 122        // // Paint cursor style
 123        // if let Some(hit_bounds) = content_bounds.intersection(visible_bounds) {
 124        //     if let Some(style) = self.style.cursor {
 125        //         scene.push_cursor_region(CursorRegion {
 126        //             bounds: hit_bounds,
 127        //             style,
 128        //         });
 129        //     }
 130        // }
 131
 132        // Render the background and/or the border.
 133        let Fill::Color(fill_color) = self.style.fill;
 134        let is_fill_visible = fill_color.a > 0.;
 135        if is_fill_visible || self.style.borders.is_visible() {
 136            scene.push_quad(Quad {
 137                bounds: margined_bounds,
 138                background: is_fill_visible.then_some(fill_color.into()),
 139                border: scene::Border {
 140                    width: self.style.borders.width,
 141                    color: self.style.borders.color,
 142                    overlay: false,
 143                    top: self.style.borders.top,
 144                    right: self.style.borders.right,
 145                    bottom: self.style.borders.bottom,
 146                    left: self.style.borders.left,
 147                },
 148                corner_radius: self.style.corner_radius,
 149            });
 150        }
 151
 152        if !self.children.is_empty() {
 153            // Account for padding first.
 154            let borders = &self.style.borders;
 155            let padded_bounds = RectF::from_points(
 156                margined_bounds.origin()
 157                    + vec2f(
 158                        borders.left_width() + layout.padding.left,
 159                        borders.top_width() + layout.padding.top,
 160                    ),
 161                margined_bounds.lower_right()
 162                    - vec2f(
 163                        layout.padding.right + borders.right_width(),
 164                        layout.padding.bottom + borders.bottom_width(),
 165                    ),
 166            );
 167
 168            if let Some(axis) = self.style.axis.to_2d() {
 169                // let parent_size = padded_bounds.size();
 170                let mut child_origin = padded_bounds.origin();
 171
 172                for child in &mut self.children {
 173                    child.paint(scene, child_origin, visible_bounds, view, cx);
 174
 175                    // Advance along the primary axis by the size of this child
 176                    child_origin.set(axis, child_origin.get(axis) + child.size().get(axis));
 177                }
 178            } else {
 179                todo!();
 180            }
 181        }
 182    }
 183
 184    fn rect_for_text_range(
 185        &self,
 186        range_utf16: Range<usize>,
 187        _: RectF,
 188        _: RectF,
 189        _: &Self::LayoutState,
 190        _: &Self::PaintState,
 191        view: &V,
 192        cx: &ViewContext<V>,
 193    ) -> Option<RectF> {
 194        self.children
 195            .iter()
 196            .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
 197    }
 198
 199    fn debug(
 200        &self,
 201        bounds: RectF,
 202        _: &Self::LayoutState,
 203        _: &Self::PaintState,
 204        view: &V,
 205        cx: &ViewContext<V>,
 206    ) -> Value {
 207        json!({
 208            "type": "Node",
 209            "bounds": bounds.to_json(),
 210            // TODO!
 211            // "children": self.content.iter().map(|child| child.debug(view, cx)).collect::<Vec<Value>>()
 212        })
 213    }
 214
 215    fn metadata(&self) -> Option<&dyn Any> {
 216        Some(&self.style)
 217    }
 218}
 219
 220impl<V: View> Node<V> {
 221    pub fn id(mut self, id: impl Into<Cow<'static, str>>) -> Self {
 222        self.id = Some(id.into());
 223        self
 224    }
 225
 226    pub fn child(mut self, child: impl Element<V>) -> Self {
 227        self.children.push(child.into_any());
 228        self
 229    }
 230
 231    pub fn children<I, E>(mut self, children: I) -> Self
 232    where
 233        I: IntoIterator<Item = E>,
 234        E: Element<V>,
 235    {
 236        self.children
 237            .extend(children.into_iter().map(|child| child.into_any()));
 238        self
 239    }
 240
 241    pub fn width(mut self, width: impl Into<Length>) -> Self {
 242        self.style.size.width = width.into();
 243        self
 244    }
 245
 246    pub fn height(mut self, height: impl Into<Length>) -> Self {
 247        self.style.size.height = height.into();
 248        self
 249    }
 250
 251    pub fn fill(mut self, fill: impl Into<Fill>) -> Self {
 252        self.style.fill = fill.into();
 253        self
 254    }
 255
 256    pub fn text_size(mut self, text_size: Rems) -> Self {
 257        self.style.text.size = Some(text_size);
 258        self
 259    }
 260
 261    pub fn margins(mut self, margins: impl Into<Edges<Length>>) -> Self {
 262        self.style.margins = margins.into();
 263        self
 264    }
 265
 266    pub fn margin_x(mut self, margin: impl Into<Length>) -> Self {
 267        self.style.margins.set_x(margin.into());
 268        self
 269    }
 270
 271    pub fn margin_y(mut self, margin: impl Into<Length>) -> Self {
 272        self.style.margins.set_y(margin.into());
 273        self
 274    }
 275
 276    pub fn margin_top(mut self, top: Length) -> Self {
 277        self.style.margins.top = top;
 278        self
 279    }
 280
 281    pub fn margin_bottom(mut self, bottom: Length) -> Self {
 282        self.style.margins.bottom = bottom;
 283        self
 284    }
 285
 286    pub fn margin_left(mut self, left: impl Into<Length>) -> Self {
 287        self.style.margins.left = left.into();
 288        self
 289    }
 290
 291    pub fn margin_right(mut self, right: impl Into<Length>) -> Self {
 292        self.style.margins.right = right.into();
 293        self
 294    }
 295
 296    pub fn align(mut self, alignment: f32) -> Self {
 297        let cross_axis = self
 298            .style
 299            .axis
 300            .to_2d()
 301            .map(Axis2d::rotate)
 302            .unwrap_or(Axis2d::Y);
 303        self.style.align.set(cross_axis, alignment);
 304        self
 305    }
 306
 307    pub fn justify(mut self, alignment: f32) -> Self {
 308        let axis = self.style.axis.to_2d().unwrap_or(Axis2d::X);
 309        self.style.align.set(axis, alignment);
 310        self
 311    }
 312
 313    fn id_string(&self) -> String {
 314        self.id.as_deref().unwrap_or("<anonymous>").to_string()
 315    }
 316
 317    fn layout_xy(
 318        &mut self,
 319        primary_axis: Axis2d,
 320        constraint: SizeConstraint,
 321        rem_pixels: f32,
 322        view: &mut V,
 323        cx: &mut LayoutContext<V>,
 324    ) -> NodeLayout {
 325        let cross_axis = primary_axis.rotate();
 326        let total_flex = self.style.flex();
 327        let mut layout = NodeLayout {
 328            size: Default::default(),
 329            padding: self.style.padding.fixed_pixels(rem_pixels),
 330            margins: self.style.margins.fixed_pixels(rem_pixels),
 331            borders: self.style.borders.edges(),
 332        };
 333        let fixed_padding_size = layout.padding.size();
 334        let fixed_margin_size = layout.margins.size();
 335        let borders_size = layout.borders.size();
 336        let fixed_constraint = constraint - fixed_margin_size - borders_size - fixed_padding_size;
 337
 338        // Determine the child constraints in each dimension based on the styled size
 339        let mut child_constraint = SizeConstraint::default();
 340        for axis in [Axis2d::X, Axis2d::Y] {
 341            let length = self.style.size.get(axis);
 342            let content_length = match length {
 343                Length::Hug => {
 344                    // Tell the children not to expand
 345                    0.
 346                }
 347                Length::Fixed(fixed_length) => {
 348                    // Tell the children to expand up to the fixed length minus the padding.
 349                    fixed_length.to_pixels(rem_pixels) - fixed_padding_size.get(axis)
 350                }
 351                Length::Auto { .. } => {
 352                    // Tell the children to expand to fill their share of the flex space in this node.
 353                    length.flex_pixels(
 354                        rem_pixels,
 355                        &mut total_flex.get(axis),
 356                        &mut fixed_constraint.max.get(axis),
 357                    )
 358                }
 359            };
 360            child_constraint.max.set(axis, content_length);
 361            if axis == cross_axis {
 362                child_constraint.min.set(axis, content_length);
 363            }
 364        }
 365
 366        // Lay out inflexible children. Total up flex of flexible children for
 367        // use in a second pass.
 368        let mut remaining_length = child_constraint.max.get(primary_axis);
 369        let mut remaining_flex = 0.;
 370        let mut total_length = 0.;
 371        let mut cross_axis_max: f32 = 0.;
 372
 373        for child in &mut self.children {
 374            if let Some(child_flex) = child
 375                .metadata::<NodeStyle>()
 376                .map(|style| style.flex().get(primary_axis))
 377            {
 378                if child_flex > 0. {
 379                    remaining_flex += child_flex;
 380                    continue;
 381                }
 382            }
 383
 384            let child_size = child.layout(child_constraint, view, cx);
 385            let child_length = child_size.get(primary_axis);
 386            remaining_length -= child_length;
 387            total_length += child_length;
 388            cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
 389        }
 390
 391        // Distribute the remaining length among the flexible children.
 392        for child in &mut self.children {
 393            if let Some(child_flex) = child
 394                .metadata::<NodeStyle>()
 395                .map(|style| style.flex().get(primary_axis))
 396            {
 397                if child_flex > 0. {
 398                    let max_child_length = (child_flex / remaining_flex) * remaining_length;
 399                    child_constraint.max.set(primary_axis, max_child_length);
 400
 401                    let child_size = child.layout(child_constraint, view, cx);
 402                    let child_length = child_size.get(primary_axis);
 403                    total_length += child_length;
 404                    remaining_length -= child_length;
 405                    remaining_flex -= child_flex;
 406                    cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
 407                }
 408            }
 409        }
 410
 411        let content_size = match primary_axis {
 412            Axis2d::X => vec2f(total_length, cross_axis_max),
 413            Axis2d::Y => vec2f(cross_axis_max, total_length),
 414        };
 415
 416        // Distribute remaining space to flexible padding and margins.
 417        for axis in [Axis2d::X, Axis2d::Y] {
 418            let length = self.style.size.get(axis);
 419            match length {
 420                Length::Hug => {
 421                    let mut remaining_flex = total_flex.get(axis);
 422                    let mut remaining_length =
 423                        fixed_constraint.min.get(axis) - content_size.get(axis);
 424
 425                    layout.padding.compute_flex_edges(
 426                        &self.style.padding,
 427                        axis,
 428                        &mut remaining_flex,
 429                        &mut remaining_length,
 430                        rem_pixels,
 431                    );
 432                    layout.margins.compute_flex_edges(
 433                        &self.style.margins,
 434                        axis,
 435                        &mut remaining_flex,
 436                        &mut remaining_length,
 437                        rem_pixels,
 438                    );
 439                    layout.size.set(
 440                        axis,
 441                        content_size.get(axis)
 442                            + layout.padding.size().get(axis)
 443                            + layout.borders.size().get(axis)
 444                            + layout.margins.size().get(axis),
 445                    );
 446                }
 447                Length::Fixed(fixed_length) => {
 448                    let fixed_length = fixed_length.to_pixels(rem_pixels);
 449
 450                    // With a fixed length, we can only distribute the space in the fixed-length container
 451                    // not consumed by the content.
 452                    let mut padding_flex = self.style.padding.flex().get(axis);
 453                    let mut max_padding_length = (fixed_length - content_size.get(axis)).max(0.);
 454                    layout.padding.compute_flex_edges(
 455                        &self.style.padding,
 456                        axis,
 457                        &mut padding_flex,
 458                        &mut max_padding_length,
 459                        rem_pixels,
 460                    );
 461
 462                    // Similarly, distribute the available space for margins so we preserve the fixed length
 463                    // of the container.
 464                    let mut margin_flex = self.style.margins.flex().get(axis);
 465                    let mut max_margin_length = constraint.max.get(axis) - fixed_length;
 466                    layout.margins.compute_flex_edges(
 467                        &self.style.margins,
 468                        axis,
 469                        &mut margin_flex,
 470                        &mut max_margin_length,
 471                        rem_pixels,
 472                    );
 473
 474                    layout
 475                        .size
 476                        .set(axis, fixed_length + layout.margins.size().get(axis))
 477                }
 478                Length::Auto { .. } => {
 479                    let mut remaining_flex = total_flex.get(axis);
 480                    let mut remaining_length = fixed_constraint.max.get(axis);
 481                    let flex_length =
 482                        length.flex_pixels(rem_pixels, &mut remaining_flex, &mut remaining_length);
 483
 484                    layout.padding.compute_flex_edges(
 485                        &self.style.padding,
 486                        axis,
 487                        &mut remaining_flex,
 488                        &mut remaining_length,
 489                        rem_pixels,
 490                    );
 491
 492                    layout.margins.compute_flex_edges(
 493                        &self.style.margins,
 494                        axis,
 495                        &mut remaining_flex,
 496                        &mut remaining_length,
 497                        rem_pixels,
 498                    );
 499
 500                    layout.size.set(
 501                        axis,
 502                        flex_length
 503                            + layout.padding.size().get(axis)
 504                            + layout.borders.size().get(axis)
 505                            + layout.margins.size().get(axis),
 506                    )
 507                }
 508            }
 509        }
 510
 511        dbg!(self.id_string());
 512        dbg!(layout)
 513    }
 514}
 515
 516pub struct TopBottom {
 517    top: Length,
 518    bottom: Length,
 519}
 520
 521impl<T: Into<Length>> From<(T, T)> for TopBottom {
 522    fn from((top, bottom): (T, T)) -> Self {
 523        Self {
 524            top: top.into(),
 525            bottom: bottom.into(),
 526        }
 527    }
 528}
 529
 530impl<T: Copy + Into<Length>> From<T> for TopBottom {
 531    fn from(both: T) -> Self {
 532        Self {
 533            top: both.into(),
 534            bottom: both.into(),
 535        }
 536    }
 537}
 538
 539pub struct LeftRight {
 540    left: Length,
 541    right: Length,
 542}
 543
 544impl From<(Length, Length)> for LeftRight {
 545    fn from((left, right): (Length, Length)) -> Self {
 546        Self { left, right }
 547    }
 548}
 549
 550impl From<Length> for LeftRight {
 551    fn from(both: Length) -> Self {
 552        Self {
 553            left: both,
 554            right: both,
 555        }
 556    }
 557}
 558
 559struct Interactive<Style> {
 560    default: Style,
 561    hovered: Style,
 562    active: Style,
 563    disabled: Style,
 564}
 565
 566#[derive(Clone, Default)]
 567pub struct NodeStyle {
 568    axis: Axis3d,
 569    wrap: bool,
 570    align: Alignment,
 571    overflow_x: Overflow,
 572    overflow_y: Overflow,
 573    gap_x: Gap,
 574    gap_y: Gap,
 575
 576    size: Size<Length>,
 577    margins: Edges<Length>,
 578    padding: Edges<Length>,
 579    text: OptionalTextStyle,
 580    opacity: f32,
 581    fill: Fill,
 582    borders: Borders,
 583    corner_radius: f32,
 584    shadows: Vec<Shadow>,
 585}
 586
 587impl NodeStyle {
 588    fn flex(&self) -> Vector2F {
 589        self.size.flex() + self.padding.flex() + self.margins.flex()
 590    }
 591}
 592
 593#[optional_struct]
 594struct TextStyle {
 595    size: Rems,
 596    font_family: Arc<str>,
 597    weight: FontWeight,
 598    style: FontStyle,
 599}
 600
 601#[derive(Add, Default, Clone)]
 602struct Size<T> {
 603    width: T,
 604    height: T,
 605}
 606
 607impl<T: Copy> Size<T> {
 608    fn get(&self, axis: Axis2d) -> T {
 609        match axis {
 610            Axis2d::X => self.width,
 611            Axis2d::Y => self.height,
 612        }
 613    }
 614}
 615
 616impl Size<Length> {
 617    fn fixed_pixels(&self, rem_pixels: f32) -> Size<f32> {
 618        Size {
 619            width: self.width.fixed_pixels(rem_pixels),
 620            height: self.height.fixed_pixels(rem_pixels),
 621        }
 622    }
 623
 624    pub fn fixed(&self) -> Size<Rems> {
 625        Size {
 626            width: self.width.fixed().unwrap_or_default(),
 627            height: self.height.fixed().unwrap_or_default(),
 628        }
 629    }
 630
 631    pub fn flex(&self) -> Vector2F {
 632        vec2f(
 633            self.width.flex().unwrap_or(0.),
 634            self.height.flex().unwrap_or(0.),
 635        )
 636    }
 637}
 638
 639impl Size<Rems> {
 640    pub fn to_pixels(&self, rem_size: f32) -> Vector2F {
 641        vec2f(
 642            self.width.to_pixels(rem_size),
 643            self.height.to_pixels(rem_size),
 644        )
 645    }
 646}
 647
 648#[derive(Clone, Default, Debug)]
 649pub struct Edges<T> {
 650    top: T,
 651    bottom: T,
 652    left: T,
 653    right: T,
 654}
 655
 656impl<T> Edges<T> {
 657    fn start(&self, axis: Axis2d) -> &T {
 658        match axis {
 659            Axis2d::X => &self.left,
 660            Axis2d::Y => &self.top,
 661        }
 662    }
 663
 664    fn start_mut(&mut self, axis: Axis2d) -> &mut T {
 665        match axis {
 666            Axis2d::X => &mut self.left,
 667            Axis2d::Y => &mut self.top,
 668        }
 669    }
 670
 671    fn end(&self, axis: Axis2d) -> &T {
 672        match axis {
 673            Axis2d::X => &self.right,
 674            Axis2d::Y => &self.bottom,
 675        }
 676    }
 677
 678    fn end_mut(&mut self, axis: Axis2d) -> &mut T {
 679        match axis {
 680            Axis2d::X => &mut self.right,
 681            Axis2d::Y => &mut self.bottom,
 682        }
 683    }
 684}
 685
 686impl<T: Clone> Edges<T> {
 687    pub fn set_x(&mut self, value: T) {
 688        self.left = value.clone();
 689        self.right = value
 690    }
 691
 692    pub fn set_y(&mut self, value: T) {
 693        self.top = value.clone();
 694        self.bottom = value
 695    }
 696}
 697
 698impl Edges<f32> {
 699    fn size(&self) -> Vector2F {
 700        vec2f(self.left + self.right, self.top + self.bottom)
 701    }
 702
 703    fn compute_flex_edges(
 704        &mut self,
 705        style_edges: &Edges<Length>,
 706        axis: Axis2d,
 707        remaining_flex: &mut f32,
 708        remaining_length: &mut f32,
 709        rem_pixels: f32,
 710    ) {
 711        *self.start_mut(axis) +=
 712            style_edges
 713                .start(axis)
 714                .flex_pixels(rem_pixels, remaining_flex, remaining_length);
 715        *self.end_mut(axis) +=
 716            style_edges
 717                .end(axis)
 718                .flex_pixels(rem_pixels, remaining_flex, remaining_length);
 719    }
 720}
 721
 722impl Edges<Length> {
 723    fn fixed_pixels(&self, rem_pixels: f32) -> Edges<f32> {
 724        Edges {
 725            top: self.top.fixed_pixels(rem_pixels),
 726            bottom: self.bottom.fixed_pixels(rem_pixels),
 727            left: self.left.fixed_pixels(rem_pixels),
 728            right: self.right.fixed_pixels(rem_pixels),
 729        }
 730    }
 731
 732    fn flex_pixels(
 733        &self,
 734        rem_pixels: f32,
 735        remaining_flex: &mut f32,
 736        remaining_length: &mut f32,
 737    ) -> Edges<f32> {
 738        Edges {
 739            top: self
 740                .top
 741                .flex_pixels(rem_pixels, remaining_flex, remaining_length),
 742            bottom: self
 743                .bottom
 744                .flex_pixels(rem_pixels, remaining_flex, remaining_length),
 745            left: self
 746                .left
 747                .flex_pixels(rem_pixels, remaining_flex, remaining_length),
 748            right: self
 749                .right
 750                .flex_pixels(rem_pixels, remaining_flex, remaining_length),
 751        }
 752    }
 753
 754    // pub fn fixed(&self) -> Size<Rems> {
 755    //     let mut size = Size::default();
 756    //     size.width += self.left.fixed().unwrap_or_default();
 757    //     size.width += self.right.fixed().unwrap_or_default();
 758    //     size
 759    // }
 760
 761    pub fn flex(&self) -> Vector2F {
 762        vec2f(
 763            self.left.flex().unwrap_or(0.) + self.right.flex().unwrap_or(0.),
 764            self.top.flex().unwrap_or(0.) + self.bottom.flex().unwrap_or(0.),
 765        )
 766    }
 767}
 768
 769impl Edges<Rems> {
 770    pub fn to_pixels(&self, rem_size: f32) -> Edges<f32> {
 771        Edges {
 772            top: self.top.to_pixels(rem_size),
 773            bottom: self.bottom.to_pixels(rem_size),
 774            left: self.left.to_pixels(rem_size),
 775            right: self.right.to_pixels(rem_size),
 776        }
 777    }
 778}
 779
 780impl<L> From<L> for Edges<Length>
 781where
 782    L: Into<Length>,
 783{
 784    fn from(uniform: L) -> Self {
 785        let uniform = uniform.into();
 786        Edges {
 787            top: uniform,
 788            bottom: uniform,
 789            left: uniform,
 790            right: uniform,
 791        }
 792    }
 793}
 794
 795impl<Vertical, Horizontal> From<(Vertical, Horizontal)> for Edges<Length>
 796where
 797    Vertical: Into<Length>,
 798    Horizontal: Into<Length>,
 799{
 800    fn from((vertical, horizontal): (Vertical, Horizontal)) -> Self {
 801        let vertical = vertical.into();
 802        let horizontal = horizontal.into();
 803        Edges {
 804            top: vertical,
 805            bottom: vertical,
 806            left: horizontal,
 807            right: horizontal,
 808        }
 809    }
 810}
 811
 812impl<Top, Bottom, Left, Right> From<(Top, Bottom, Left, Right)> for Edges<Length>
 813where
 814    Top: Into<Length>,
 815    Bottom: Into<Length>,
 816    Left: Into<Length>,
 817    Right: Into<Length>,
 818{
 819    fn from((top, bottom, left, right): (Top, Bottom, Left, Right)) -> Self {
 820        Edges {
 821            top: top.into(),
 822            bottom: bottom.into(),
 823            left: left.into(),
 824            right: right.into(),
 825        }
 826    }
 827}
 828
 829struct CornerRadii {
 830    top_left: f32,
 831    top_right: f32,
 832    bottom_right: f32,
 833    bottom_left: f32,
 834}
 835
 836#[derive(Clone)]
 837pub enum Fill {
 838    Color(Rgba),
 839}
 840
 841impl<C: Into<Rgba>> From<C> for Fill {
 842    fn from(value: C) -> Self {
 843        Fill::Color(value.into())
 844    }
 845}
 846
 847impl Default for Fill {
 848    fn default() -> Self {
 849        Fill::Color(Rgba::default())
 850    }
 851}
 852
 853#[derive(Clone, Default)]
 854struct Borders {
 855    color: Color,
 856    width: f32,
 857    top: bool,
 858    bottom: bool,
 859    left: bool,
 860    right: bool,
 861}
 862
 863impl Borders {
 864    fn is_visible(&self) -> bool {
 865        self.width > 0.
 866            && !self.color.is_fully_transparent()
 867            && (self.top || self.bottom || self.left || self.right)
 868    }
 869
 870    fn top_width(&self) -> f32 {
 871        if self.top {
 872            self.width
 873        } else {
 874            0.
 875        }
 876    }
 877
 878    fn bottom_width(&self) -> f32 {
 879        if self.bottom {
 880            self.width
 881        } else {
 882            0.
 883        }
 884    }
 885
 886    fn left_width(&self) -> f32 {
 887        if self.left {
 888            self.width
 889        } else {
 890            0.
 891        }
 892    }
 893
 894    fn right_width(&self) -> f32 {
 895        if self.right {
 896            self.width
 897        } else {
 898            0.
 899        }
 900    }
 901
 902    fn edges(&self) -> Edges<f32> {
 903        let mut edges = Edges::default();
 904        if self.width > 0. {
 905            if self.top {
 906                edges.top = self.width;
 907            }
 908            if self.bottom {
 909                edges.bottom = self.width;
 910            }
 911            if self.left {
 912                edges.left = self.width;
 913            }
 914            if self.right {
 915                edges.right = self.width;
 916            }
 917        }
 918        edges
 919    }
 920
 921    fn size(&self) -> Vector2F {
 922        let width =
 923            if self.left { self.width } else { 0. } + if self.right { self.width } else { 0. };
 924        let height =
 925            if self.top { self.width } else { 0. } + if self.bottom { self.width } else { 0. };
 926
 927        vec2f(width, height)
 928    }
 929}
 930
 931pub mod length {
 932    use derive_more::{Add, AddAssign, Into};
 933
 934    #[derive(Add, AddAssign, Into, Clone, Copy, Default, Debug, PartialEq)]
 935    pub struct Rems(f32);
 936
 937    pub fn rems(rems: f32) -> Rems {
 938        Rems(rems)
 939    }
 940
 941    impl Rems {
 942        pub fn to_pixels(&self, rem_pixels: f32) -> f32 {
 943            self.0 * rem_pixels
 944        }
 945    }
 946
 947    #[derive(Clone, Copy, Default, Debug)]
 948    pub enum Length {
 949        #[default]
 950        Hug,
 951        Fixed(Rems),
 952        Auto {
 953            flex: f32,
 954            min: Rems,
 955            max: Rems,
 956        },
 957    }
 958
 959    impl From<Rems> for Length {
 960        fn from(value: Rems) -> Self {
 961            Length::Fixed(value)
 962        }
 963    }
 964
 965    pub fn auto() -> Length {
 966        flex(1.)
 967    }
 968
 969    pub fn flex(flex: f32) -> Length {
 970        Length::Auto {
 971            flex,
 972            min: Default::default(),
 973            max: rems(f32::INFINITY),
 974        }
 975    }
 976
 977    pub fn constrained(flex: f32, min: Option<Rems>, max: Option<Rems>) -> Length {
 978        Length::Auto {
 979            flex,
 980            min: min.unwrap_or(Default::default()),
 981            max: max.unwrap_or(rems(f32::INFINITY)),
 982        }
 983    }
 984
 985    impl Length {
 986        pub fn flex_pixels(
 987            &self,
 988            rem_pixels: f32,
 989            remaining_flex: &mut f32,
 990            remaining_length: &mut f32,
 991        ) -> f32 {
 992            match self {
 993                Length::Auto { flex, min, max } => {
 994                    let flex_length = *remaining_length / *remaining_flex;
 995                    let length = (flex * flex_length)
 996                        .clamp(min.to_pixels(rem_pixels), max.to_pixels(rem_pixels));
 997                    *remaining_flex -= flex;
 998                    *remaining_length -= length;
 999                    length
1000                }
1001                _ => 0.,
1002            }
1003        }
1004
1005        pub fn fixed_pixels(&self, rem: f32) -> f32 {
1006            match self {
1007                Length::Fixed(rems) => rems.to_pixels(rem),
1008                _ => 0.,
1009            }
1010        }
1011
1012        pub fn flex(&self) -> Option<f32> {
1013            match self {
1014                Length::Auto { flex, .. } => Some(*flex),
1015                _ => None,
1016            }
1017        }
1018
1019        pub fn fixed(&self) -> Option<Rems> {
1020            match self {
1021                Length::Fixed(rems) => Some(*rems),
1022                _ => None,
1023            }
1024        }
1025    }
1026}
1027
1028#[derive(Clone, Deref, DerefMut)]
1029struct Alignment(Vector2F);
1030
1031impl Default for Alignment {
1032    fn default() -> Self {
1033        Self(vec2f(-1., -1.))
1034    }
1035}
1036
1037#[derive(Clone, Copy, Default)]
1038enum Axis3d {
1039    X,
1040    #[default]
1041    Y,
1042    Z,
1043}
1044
1045impl Axis3d {
1046    fn to_2d(self) -> Option<Axis2d> {
1047        match self {
1048            Axis3d::X => Some(Axis2d::X),
1049            Axis3d::Y => Some(Axis2d::Y),
1050            Axis3d::Z => None,
1051        }
1052    }
1053}
1054
1055#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
1056pub enum Axis2d {
1057    X,
1058    #[default]
1059    Y,
1060}
1061
1062impl Axis2d {
1063    fn rotate(self) -> Self {
1064        match self {
1065            Axis2d::X => Axis2d::Y,
1066            Axis2d::Y => Axis2d::X,
1067        }
1068    }
1069}
1070
1071#[derive(Clone, Copy, Default)]
1072enum Overflow {
1073    #[default]
1074    Visible,
1075    Hidden,
1076    Auto,
1077}
1078
1079#[derive(Clone, Copy)]
1080enum Gap {
1081    Fixed(f32),
1082    Around,
1083    Between,
1084    Even,
1085}
1086
1087impl Default for Gap {
1088    fn default() -> Self {
1089        Gap::Fixed(0.)
1090    }
1091}
1092
1093#[derive(Clone, Copy, Default)]
1094struct Shadow {
1095    offset: Vector2F,
1096    blur: f32,
1097    color: Color,
1098}
1099
1100#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
1101enum FontStyle {
1102    #[default]
1103    Normal,
1104    Italic,
1105    Oblique,
1106}
1107
1108#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
1109enum FontWeight {
1110    Thin,
1111    ExtraLight,
1112    Light,
1113    #[default]
1114    Normal,
1115    Medium,
1116    Semibold,
1117    Bold,
1118    ExtraBold,
1119    Black,
1120}
1121
1122#[derive(Default)]
1123pub struct Text {
1124    text: Cow<'static, str>,
1125    highlights: Option<Box<[(Range<usize>, HighlightStyle)]>>,
1126    custom_runs: Option<(
1127        Box<[Range<usize>]>,
1128        Box<dyn FnMut(usize, RectF, &mut SceneBuilder, &mut AppContext)>,
1129    )>,
1130}
1131
1132pub fn text<V: View>(text: impl Into<Cow<'static, str>>) -> Node<V> {
1133    row().child(Text {
1134        text: text.into(),
1135        ..Default::default()
1136    })
1137}
1138
1139#[derive(Default, Debug)]
1140pub struct NodeLayout {
1141    size: Vector2F,
1142    padding: Edges<f32>,
1143    borders: Edges<f32>,
1144    margins: Edges<f32>,
1145}
1146
1147impl<V: View> Element<V> for Text {
1148    type LayoutState = TextLayout;
1149    type PaintState = ();
1150
1151    fn layout(
1152        &mut self,
1153        constraint: SizeConstraint,
1154        _: &mut V,
1155        cx: &mut LayoutContext<V>,
1156    ) -> (Vector2F, Self::LayoutState) {
1157        // Convert the string and highlight ranges into an iterator of highlighted chunks.
1158        let mut offset = 0;
1159        let mut highlight_ranges = self
1160            .highlights
1161            .as_ref()
1162            .map_or(Default::default(), AsRef::as_ref)
1163            .iter()
1164            .peekable();
1165        let chunks = std::iter::from_fn(|| {
1166            let result;
1167            if let Some((range, highlight_style)) = highlight_ranges.peek() {
1168                if offset < range.start {
1169                    result = Some((&self.text[offset..range.start], None));
1170                    offset = range.start;
1171                } else if range.end <= self.text.len() {
1172                    result = Some((&self.text[range.clone()], Some(*highlight_style)));
1173                    highlight_ranges.next();
1174                    offset = range.end;
1175                } else {
1176                    warn!(
1177                        "Highlight out of text range. Text len: {}, Highlight range: {}..{}",
1178                        self.text.len(),
1179                        range.start,
1180                        range.end
1181                    );
1182                    result = None;
1183                }
1184            } else if offset < self.text.len() {
1185                result = Some((&self.text[offset..], None));
1186                offset = self.text.len();
1187            } else {
1188                result = None;
1189            }
1190            result
1191        });
1192
1193        let style = cx.text_style();
1194
1195        // Perform shaping on these highlighted chunks
1196        let shaped_lines = layout_highlighted_chunks(
1197            chunks,
1198            &style,
1199            cx.text_layout_cache(),
1200            &cx.font_cache,
1201            usize::MAX,
1202            self.text.matches('\n').count() + 1,
1203        );
1204
1205        // If line wrapping is enabled, wrap each of the shaped lines.
1206        let font_id = style.font_id;
1207        let mut line_count = 0;
1208        let mut max_line_width = 0_f32;
1209        let mut wrap_boundaries = Vec::new();
1210        let mut wrapper = cx.font_cache.line_wrapper(font_id, style.font_size);
1211        for (line, shaped_line) in self.text.split('\n').zip(&shaped_lines) {
1212            if style.soft_wrap {
1213                let boundaries = wrapper
1214                    .wrap_shaped_line(line, shaped_line, constraint.max.x())
1215                    .collect::<Vec<_>>();
1216                line_count += boundaries.len() + 1;
1217                wrap_boundaries.push(boundaries);
1218            } else {
1219                line_count += 1;
1220            }
1221            max_line_width = max_line_width.max(shaped_line.width());
1222        }
1223
1224        let line_height = cx.font_cache.line_height(style.font_size);
1225        let size = vec2f(
1226            max_line_width
1227                .ceil()
1228                .max(constraint.min.x())
1229                .min(constraint.max.x()),
1230            (line_height * line_count as f32).ceil(),
1231        );
1232        (
1233            size,
1234            TextLayout {
1235                shaped_lines,
1236                wrap_boundaries,
1237                line_height,
1238            },
1239        )
1240    }
1241
1242    fn paint(
1243        &mut self,
1244        scene: &mut SceneBuilder,
1245        bounds: RectF,
1246        visible_bounds: RectF,
1247        layout: &mut Self::LayoutState,
1248        _: &mut V,
1249        cx: &mut PaintContext<V>,
1250    ) -> Self::PaintState {
1251        let mut origin = bounds.origin();
1252        let empty = Vec::new();
1253        let mut callback = |_, _, _: &mut SceneBuilder, _: &mut AppContext| {};
1254
1255        let mouse_runs;
1256        let custom_run_callback;
1257        if let Some((runs, build_region)) = &mut self.custom_runs {
1258            mouse_runs = runs.iter();
1259            custom_run_callback = build_region.as_mut();
1260        } else {
1261            mouse_runs = [].iter();
1262            custom_run_callback = &mut callback;
1263        }
1264        let mut custom_runs = mouse_runs.enumerate().peekable();
1265
1266        let mut offset = 0;
1267        for (ix, line) in layout.shaped_lines.iter().enumerate() {
1268            let wrap_boundaries = layout.wrap_boundaries.get(ix).unwrap_or(&empty);
1269            let boundaries = RectF::new(
1270                origin,
1271                vec2f(
1272                    bounds.width(),
1273                    (wrap_boundaries.len() + 1) as f32 * layout.line_height,
1274                ),
1275            );
1276
1277            let style = cx.text_style();
1278            if boundaries.intersects(visible_bounds) {
1279                if style.soft_wrap {
1280                    line.paint_wrapped(
1281                        scene,
1282                        origin,
1283                        visible_bounds,
1284                        layout.line_height,
1285                        wrap_boundaries,
1286                        cx,
1287                    );
1288                } else {
1289                    line.paint(scene, origin, visible_bounds, layout.line_height, cx);
1290                }
1291            }
1292
1293            // Paint any custom runs that intersect this line.
1294            let end_offset = offset + line.len();
1295            if let Some((custom_run_ix, custom_run_range)) = custom_runs.peek().cloned() {
1296                if custom_run_range.start < end_offset {
1297                    let mut current_custom_run = None;
1298                    if custom_run_range.start <= offset {
1299                        current_custom_run = Some((custom_run_ix, custom_run_range.end, origin));
1300                    }
1301
1302                    let mut glyph_origin = origin;
1303                    let mut prev_position = 0.;
1304                    let mut wrap_boundaries = wrap_boundaries.iter().copied().peekable();
1305                    for (run_ix, glyph_ix, glyph) in
1306                        line.runs().iter().enumerate().flat_map(|(run_ix, run)| {
1307                            run.glyphs()
1308                                .iter()
1309                                .enumerate()
1310                                .map(move |(ix, glyph)| (run_ix, ix, glyph))
1311                        })
1312                    {
1313                        glyph_origin.set_x(glyph_origin.x() + glyph.position.x() - prev_position);
1314                        prev_position = glyph.position.x();
1315
1316                        // If we've reached a soft wrap position, move down one line. If there
1317                        // is a custom run in-progress, paint it.
1318                        if wrap_boundaries
1319                            .peek()
1320                            .map_or(false, |b| b.run_ix == run_ix && b.glyph_ix == glyph_ix)
1321                        {
1322                            if let Some((run_ix, _, run_origin)) = &mut current_custom_run {
1323                                let bounds = RectF::from_points(
1324                                    *run_origin,
1325                                    glyph_origin + vec2f(0., layout.line_height),
1326                                );
1327                                custom_run_callback(*run_ix, bounds, scene, cx);
1328                                *run_origin =
1329                                    vec2f(origin.x(), glyph_origin.y() + layout.line_height);
1330                            }
1331                            wrap_boundaries.next();
1332                            glyph_origin = vec2f(origin.x(), glyph_origin.y() + layout.line_height);
1333                        }
1334
1335                        // If we've reached the end of the current custom run, paint it.
1336                        if let Some((run_ix, run_end_offset, run_origin)) = current_custom_run {
1337                            if offset + glyph.index == run_end_offset {
1338                                current_custom_run.take();
1339                                let bounds = RectF::from_points(
1340                                    run_origin,
1341                                    glyph_origin + vec2f(0., layout.line_height),
1342                                );
1343                                custom_run_callback(run_ix, bounds, scene, cx);
1344                                custom_runs.next();
1345                            }
1346
1347                            if let Some((_, run_range)) = custom_runs.peek() {
1348                                if run_range.start >= end_offset {
1349                                    break;
1350                                }
1351                                if run_range.start == offset + glyph.index {
1352                                    current_custom_run =
1353                                        Some((run_ix, run_range.end, glyph_origin));
1354                                }
1355                            }
1356                        }
1357
1358                        // If we've reached the start of a new custom run, start tracking it.
1359                        if let Some((run_ix, run_range)) = custom_runs.peek() {
1360                            if offset + glyph.index == run_range.start {
1361                                current_custom_run = Some((*run_ix, run_range.end, glyph_origin));
1362                            }
1363                        }
1364                    }
1365
1366                    // If a custom run extends beyond the end of the line, paint it.
1367                    if let Some((run_ix, run_end_offset, run_origin)) = current_custom_run {
1368                        let line_end = glyph_origin + vec2f(line.width() - prev_position, 0.);
1369                        let bounds = RectF::from_points(
1370                            run_origin,
1371                            line_end + vec2f(0., layout.line_height),
1372                        );
1373                        custom_run_callback(run_ix, bounds, scene, cx);
1374                        if end_offset == run_end_offset {
1375                            custom_runs.next();
1376                        }
1377                    }
1378                }
1379            }
1380
1381            offset = end_offset + 1;
1382            origin.set_y(boundaries.max_y());
1383        }
1384    }
1385
1386    fn rect_for_text_range(
1387        &self,
1388        _: Range<usize>,
1389        _: RectF,
1390        _: RectF,
1391        _: &Self::LayoutState,
1392        _: &Self::PaintState,
1393        _: &V,
1394        _: &ViewContext<V>,
1395    ) -> Option<RectF> {
1396        None
1397    }
1398
1399    fn debug(
1400        &self,
1401        bounds: RectF,
1402        _: &Self::LayoutState,
1403        _: &Self::PaintState,
1404        _: &V,
1405        _: &ViewContext<V>,
1406    ) -> Value {
1407        json!({
1408            "type": "Text",
1409            "bounds": bounds.to_json(),
1410            "text": &self.text,
1411        })
1412    }
1413}
1414
1415pub struct TextLayout {
1416    shaped_lines: Vec<Line>,
1417    wrap_boundaries: Vec<Vec<ShapedBoundary>>,
1418    line_height: f32,
1419}
1420
1421trait Vector2FExt {
1422    fn infinity() -> Self;
1423    fn get(self, axis: Axis2d) -> f32;
1424    fn set(&mut self, axis: Axis2d, value: f32);
1425    fn increment_x(&mut self, delta: f32) -> f32;
1426    fn increment_y(&mut self, delta: f32) -> f32;
1427}
1428
1429impl Vector2FExt for Vector2F {
1430    fn infinity() -> Self {
1431        vec2f(f32::INFINITY, f32::INFINITY)
1432    }
1433
1434    fn get(self, axis: Axis2d) -> f32 {
1435        match axis {
1436            Axis2d::X => self.x(),
1437            Axis2d::Y => self.y(),
1438        }
1439    }
1440
1441    fn set(&mut self, axis: Axis2d, value: f32) {
1442        match axis {
1443            Axis2d::X => self.set_x(value),
1444            Axis2d::Y => self.set_y(value),
1445        }
1446    }
1447
1448    fn increment_x(&mut self, delta: f32) -> f32 {
1449        self.set_x(self.x() + delta);
1450        self.x()
1451    }
1452
1453    fn increment_y(&mut self, delta: f32) -> f32 {
1454        self.set_y(self.y() + delta);
1455        self.y()
1456    }
1457}
1458
1459trait ElementExt<V: View> {
1460    fn margin_left(self, margin_left: impl Into<Length>) -> Node<V>
1461    where
1462        Self: Element<V> + Sized,
1463    {
1464        column().child(self).margin_left(margin_left)
1465    }
1466}
1467
1468impl<V, E> ElementExt<V> for E
1469where
1470    V: View,
1471    E: Element<V>,
1472{
1473    fn margin_left(self, margin_left: impl Into<Length>) -> Node<V>
1474    where
1475        Self: Sized,
1476    {
1477        column().child(self).margin_left(margin_left)
1478    }
1479}
1480
1481pub fn view<F, E>(mut function: F) -> ViewFn
1482where
1483    F: 'static + FnMut(&mut ViewContext<ViewFn>) -> E,
1484    E: Element<ViewFn>,
1485{
1486    ViewFn(Box::new(move |cx| (function)(cx).into_any()))
1487}
1488
1489pub struct ViewFn(Box<dyn FnMut(&mut ViewContext<ViewFn>) -> AnyElement<ViewFn>>);
1490
1491impl Entity for ViewFn {
1492    type Event = ();
1493}
1494
1495impl View for ViewFn {
1496    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
1497        (self.0)(cx)
1498    }
1499}
1500
1501#[cfg(test)]
1502mod tests {
1503    use super::{
1504        length::{auto, rems},
1505        *,
1506    };
1507    use crate::themes::rose_pine;
1508    use gpui::TestAppContext;
1509
1510    #[gpui::test]
1511    fn test_layout(cx: &mut TestAppContext) {
1512        let window = cx.add_window(|_| {
1513            view(|_| {
1514                let theme = rose_pine::dawn();
1515                column()
1516                    .width(auto())
1517                    .height(auto())
1518                    .justify(1.)
1519                    .child(
1520                        row()
1521                            .width(auto())
1522                            .height(rems(10.))
1523                            .fill(theme.foam)
1524                            .justify(1.)
1525                            .child(row().width(rems(10.)).height(auto()).fill(theme.gold)),
1526                    )
1527                    .child(row())
1528            });
1529        });
1530
1531        window.update(cx, |cx| {
1532            let root = cx.root_element();
1533            dbg!(root.debug(cx).unwrap());
1534        });
1535
1536        // tree.layout(
1537        //     SizeConstraint::strict(vec2f(100., 100.)),
1538        //     &mut (),
1539        //     LayoutContext::test(),
1540        // );
1541
1542        // LayoutContext::new(
1543        //     cx,
1544        //     new_parents,
1545        //     views_to_notify_if_ancestors_change,
1546        //     refreshing,
1547        // )
1548
1549        // tree.layout(SizeConstraint::strict(vec2f(100., 100.)), &mut (), cx)
1550    }
1551}