node.rs

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