787 lines · 20.4 KB · Rust
RawDownload
mod align;mod canvas;mod clipped;mod component;mod constrained_box;mod container;mod empty;mod expanded;mod flex;mod hook;mod image;mod keystroke_label;mod label;mod list;mod mouse_event_handler;mod overlay;mod resizable;mod stack;mod svg;mod text;mod tooltip;mod uniform_list; pub use self::{    align::*, canvas::*, component::*, constrained_box::*, container::*, empty::*, flex::*,    hook::*, image::*, keystroke_label::*, label::*, list::*, mouse_event_handler::*, overlay::*,    resizable::*, stack::*, svg::*, text::*, tooltip::*, uniform_list::*,};pub use crate::window::ChildView; use self::{clipped::Clipped, expanded::Expanded};use crate::{    geometry::{        rect::RectF,        vector::{vec2f, Vector2F},    },    json, Action, Entity, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, TypeTag, View,    ViewContext, WeakViewHandle, WindowContext,};use anyhow::{anyhow, Result};use collections::HashMap;use core::panic;use json::ToJson;use smallvec::SmallVec;use std::{    any::{type_name, Any},    borrow::Cow,    mem,    ops::Range,}; pub trait Element<V: 'static>: 'static {    type LayoutState;    type PaintState;     fn view_name(&self) -> &'static str {        type_name::<V>()    }     fn layout(        &mut self,        constraint: SizeConstraint,        view: &mut V,        cx: &mut LayoutContext<V>,    ) -> (Vector2F, Self::LayoutState);     fn paint(        &mut self,        scene: &mut SceneBuilder,        bounds: RectF,        visible_bounds: RectF,        layout: &mut Self::LayoutState,        view: &mut V,        cx: &mut PaintContext<V>,    ) -> Self::PaintState;     fn rect_for_text_range(        &self,        range_utf16: Range<usize>,        bounds: RectF,        visible_bounds: RectF,        layout: &Self::LayoutState,        paint: &Self::PaintState,        view: &V,        cx: &ViewContext<V>,    ) -> Option<RectF>;     fn metadata(&self) -> Option<&dyn Any> {        None    }     fn debug(        &self,        bounds: RectF,        layout: &Self::LayoutState,        paint: &Self::PaintState,        view: &V,        cx: &ViewContext<V>,    ) -> serde_json::Value;     fn into_any(self) -> AnyElement<V>    where        Self: 'static + Sized,    {        AnyElement {            state: Box::new(ElementState::Init { element: self }),            name: None,        }    }     fn into_any_named(self, name: impl Into<Cow<'static, str>>) -> AnyElement<V>    where        Self: 'static + Sized,    {        AnyElement {            state: Box::new(ElementState::Init { element: self }),            name: Some(name.into()),        }    }     fn into_root_element(self, cx: &ViewContext<V>) -> RootElement<V>    where        Self: 'static + Sized,    {        RootElement {            element: self.into_any(),            view: cx.handle().downgrade(),        }    }     fn constrained(self) -> ConstrainedBox<V>    where        Self: 'static + Sized,    {        ConstrainedBox::new(self.into_any())    }     fn aligned(self) -> Align<V>    where        Self: 'static + Sized,    {        Align::new(self.into_any())    }     fn clipped(self) -> Clipped<V>    where        Self: 'static + Sized,    {        Clipped::new(self.into_any())    }     fn contained(self) -> Container<V>    where        Self: 'static + Sized,    {        Container::new(self.into_any())    }     fn expanded(self) -> Expanded<V>    where        Self: 'static + Sized,    {        Expanded::new(self.into_any())    }     fn flex(self, flex: f32, expanded: bool) -> FlexItem<V>    where        Self: 'static + Sized,    {        FlexItem::new(self.into_any()).flex(flex, expanded)    }     fn flex_float(self) -> FlexItem<V>    where        Self: 'static + Sized,    {        FlexItem::new(self.into_any()).float()    }     fn with_dynamic_tooltip(        self,        tag: TypeTag,        id: usize,        text: impl Into<Cow<'static, str>>,        action: Option<Box<dyn Action>>,        style: TooltipStyle,        cx: &mut ViewContext<V>,    ) -> Tooltip<V>    where        Self: 'static + Sized,    {        Tooltip::new_dynamic(tag, id, text, action, style, self.into_any(), cx)    }    fn with_tooltip<Tag: 'static>(        self,        id: usize,        text: impl Into<Cow<'static, str>>,        action: Option<Box<dyn Action>>,        style: TooltipStyle,        cx: &mut ViewContext<V>,    ) -> Tooltip<V>    where        Self: 'static + Sized,    {        Tooltip::new::<Tag>(id, text, action, style, self.into_any(), cx)    }     /// Uses the the given element to calculate resizes for the given tag    fn provide_resize_bounds<Tag: 'static>(self) -> BoundsProvider<V, Tag>    where        Self: 'static + Sized,    {        BoundsProvider::<_, Tag>::new(self.into_any())    }     /// Calls the given closure with the new size of the element whenever the    /// handle is dragged. This will be calculated in relation to the bounds    /// provided by the given tag    fn resizable<Tag: 'static>(        self,        side: HandleSide,        size: f32,        on_resize: impl 'static + FnMut(&mut V, Option<f32>, &mut ViewContext<V>),    ) -> Resizable<V>    where        Self: 'static + Sized,    {        Resizable::new::<Tag>(self.into_any(), side, size, on_resize)    }     fn mouse<Tag: 'static>(self, region_id: usize) -> MouseEventHandler<V>    where        Self: Sized,    {        MouseEventHandler::for_child::<Tag>(self.into_any(), region_id)    }     fn component(self) -> StatelessElementAdapter    where        Self: Sized,    {        StatelessElementAdapter::new(self.into_any())    }     fn stateful_component(self) -> StatefulElementAdapter<V>    where        Self: Sized,    {        StatefulElementAdapter::new(self.into_any())    }     fn styleable_component(self) -> StylableAdapter<StatelessElementAdapter>    where        Self: Sized,    {        StatelessElementAdapter::new(self.into_any()).stylable()    }} trait AnyElementState<V> {    fn layout(        &mut self,        constraint: SizeConstraint,        view: &mut V,        cx: &mut LayoutContext<V>,    ) -> Vector2F;     fn paint(        &mut self,        scene: &mut SceneBuilder,        origin: Vector2F,        visible_bounds: RectF,        view: &mut V,        cx: &mut PaintContext<V>,    );     fn rect_for_text_range(        &self,        range_utf16: Range<usize>,        view: &V,        cx: &ViewContext<V>,    ) -> Option<RectF>;     fn debug(&self, view: &V, cx: &ViewContext<V>) -> serde_json::Value;     fn size(&self) -> Vector2F;     fn metadata(&self) -> Option<&dyn Any>;} enum ElementState<V: 'static, E: Element<V>> {    Empty,    Init {        element: E,    },    PostLayout {        element: E,        constraint: SizeConstraint,        size: Vector2F,        layout: E::LayoutState,    },    PostPaint {        element: E,        constraint: SizeConstraint,        bounds: RectF,        visible_bounds: RectF,        layout: E::LayoutState,        paint: E::PaintState,    },} impl<V, E: Element<V>> AnyElementState<V> for ElementState<V, E> {    fn layout(        &mut self,        constraint: SizeConstraint,        view: &mut V,        cx: &mut LayoutContext<V>,    ) -> Vector2F {        let result;        *self = match mem::take(self) {            ElementState::Empty => unreachable!(),            ElementState::Init { mut element }            | ElementState::PostLayout { mut element, .. }            | ElementState::PostPaint { mut element, .. } => {                let (size, layout) = element.layout(constraint, view, cx);                debug_assert!(                    size.x().is_finite(),                    "Element for {:?} had infinite x size after layout",                    element.view_name()                );                debug_assert!(                    size.y().is_finite(),                    "Element for {:?} had infinite y size after layout",                    element.view_name()                );                 result = size;                ElementState::PostLayout {                    element,                    constraint,                    size,                    layout,                }            }        };        result    }     fn paint(        &mut self,        scene: &mut SceneBuilder,        origin: Vector2F,        visible_bounds: RectF,        view: &mut V,        cx: &mut PaintContext<V>,    ) {        *self = match mem::take(self) {            ElementState::PostLayout {                mut element,                constraint,                size,                mut layout,            } => {                let bounds = RectF::new(origin, size);                let paint = element.paint(                    scene,                    bounds,                    visible_bounds,                    &mut layout,                    view,                    &mut PaintContext::new(cx),                );                ElementState::PostPaint {                    element,                    constraint,                    bounds,                    visible_bounds,                    layout,                    paint,                }            }            ElementState::PostPaint {                mut element,                constraint,                bounds,                mut layout,                ..            } => {                let bounds = RectF::new(origin, bounds.size());                let paint = element.paint(                    scene,                    bounds,                    visible_bounds,                    &mut layout,                    view,                    &mut PaintContext::new(cx),                );                ElementState::PostPaint {                    element,                    constraint,                    bounds,                    visible_bounds,                    layout,                    paint,                }            }            ElementState::Empty => panic!("invalid element lifecycle state"),            ElementState::Init { .. } => {                panic!("invalid element lifecycle state, paint called before layout")            }        }    }     fn rect_for_text_range(        &self,        range_utf16: Range<usize>,        view: &V,        cx: &ViewContext<V>,    ) -> Option<RectF> {        if let ElementState::PostPaint {            element,            bounds,            visible_bounds,            layout,            paint,            ..        } = self        {            element.rect_for_text_range(                range_utf16,                *bounds,                *visible_bounds,                layout,                paint,                view,                cx,            )        } else {            None        }    }     fn size(&self) -> Vector2F {        match self {            ElementState::Empty | ElementState::Init { .. } => {                panic!("invalid element lifecycle state")            }            ElementState::PostLayout { size, .. } => *size,            ElementState::PostPaint { bounds, .. } => bounds.size(),        }    }     fn metadata(&self) -> Option<&dyn Any> {        match self {            ElementState::Empty => unreachable!(),            ElementState::Init { element }            | ElementState::PostLayout { element, .. }            | ElementState::PostPaint { element, .. } => element.metadata(),        }    }     fn debug(&self, view: &V, cx: &ViewContext<V>) -> serde_json::Value {        match self {            ElementState::PostPaint {                element,                constraint,                bounds,                visible_bounds,                layout,                paint,            } => {                let mut value = element.debug(*bounds, layout, paint, view, cx);                if let json::Value::Object(map) = &mut value {                    let mut new_map: crate::json::Map<String, serde_json::Value> =                        Default::default();                    if let Some(typ) = map.remove("type") {                        new_map.insert("type".into(), typ);                    }                    new_map.insert("constraint".into(), constraint.to_json());                    new_map.insert("bounds".into(), bounds.to_json());                    new_map.insert("visible_bounds".into(), visible_bounds.to_json());                    new_map.append(map);                    json::Value::Object(new_map)                } else {                    value                }            }             _ => panic!("invalid element lifecycle state"),        }    }} impl<V, E: Element<V>> Default for ElementState<V, E> {    fn default() -> Self {        Self::Empty    }} pub struct AnyElement<V> {

Lines 1–500 of 787.