Skip to content

Commit

Permalink
Add types and methods for intrinsic sizing protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
LPGhatguy committed Oct 21, 2024
1 parent 2db986f commit d5b92aa
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
15 changes: 14 additions & 1 deletion crates/yakui-core/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use crate::event::EventInterest;
use crate::geometry::{Constraints, Rect};
use crate::id::WidgetId;
use crate::input::{InputState, MouseInterest};
use crate::widget::LayoutContext;
use crate::types::Axis;
use crate::widget::{IntrinsicSizeContext, LayoutContext};

/// Contains information on how each widget in the DOM is laid out and what
/// events they're interested in.
Expand Down Expand Up @@ -199,6 +200,18 @@ impl LayoutDom {
size
}

/// Calculates the intrinsic size of the given widget along the given axis.
pub fn intrinsic_size(&self, dom: &Dom, id: WidgetId, axis: Axis) -> f32 {
dom.enter(id);
let dom_node = dom.get(id).unwrap();

let context = IntrinsicSizeContext { dom, layout: self };
let size = dom_node.widget.intrinsic_size(context, axis);

dom.exit(id);
size
}

/// Enables clipping for the currently active widget.
pub fn enable_clipping(&mut self, dom: &Dom) {
self.clip_stack.push(dom.current());
Expand Down
18 changes: 18 additions & 0 deletions crates/yakui-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,21 @@ impl Pivot {
pub const BOTTOM_CENTER: Self = Self::new(0.5, 1.0);
pub const BOTTOM_RIGHT: Self = Self::new(1.0, 1.0);
}

/// Defines an axis usable by the UI.
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Axis {
X,
Y,
}

impl Axis {
/// Return the component of a [`Vec2`] that matches this axis.
pub fn select(self, v: Vec2) -> f32 {
match self {
Axis::X => v.x,
Axis::Y => v.y,
}
}
}
45 changes: 44 additions & 1 deletion crates/yakui-core/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ use crate::dom::Dom;
use crate::event::EventResponse;
use crate::event::{EventInterest, WidgetEvent};
use crate::geometry::{Constraints, FlexFit};
use crate::id::WidgetId;
use crate::input::{InputState, NavDirection};
use crate::layout::LayoutDom;
use crate::paint::PaintDom;
use crate::{Flow, WidgetId};
use crate::types::{Axis, Flow};

/// Trait that's automatically implemented for all widget props.
///
Expand All @@ -38,6 +39,26 @@ impl<'dom> LayoutContext<'dom> {
self.layout
.calculate(self.dom, self.input, widget, constraints)
}

/// Calculates the intrinsic size for the given widget on the given axis.
pub fn intrinsic_size(&self, widget: WidgetId, axis: Axis) -> f32 {
self.layout.intrinsic_size(self.dom, widget, axis)
}
}

/// Information available to a widget during the layout phase.
#[non_exhaustive]
#[allow(missing_docs)]
pub struct IntrinsicSizeContext<'dom> {
pub dom: &'dom Dom,
pub layout: &'dom LayoutDom,
}

impl<'dom> IntrinsicSizeContext<'dom> {
/// Calculates the intrinsic size for the given widget on the given axis.
pub fn intrinsic_size(&self, widget: WidgetId, axis: Axis) -> f32 {
self.layout.intrinsic_size(self.dom, widget, axis)
}
}

/// Information available to a widget during the paint phase.
Expand Down Expand Up @@ -134,6 +155,21 @@ pub trait Widget: 'static + fmt::Debug {
constraints.constrain_min(size)
}

/// Tells the intrinsic size on one axis of the object, which is its size
/// along that axis if the widget were given unbounded constraints on the
/// other axis.
fn intrinsic_size(&self, ctx: IntrinsicSizeContext<'_>, axis: Axis) -> f32 {
let node = ctx.dom.get_current();
let mut size: f32 = 0.0;

for &child in &node.children {
let child_size = ctx.intrinsic_size(child, axis);
size = size.max(child_size);
}

size
}

/// Paint the widget based on its current state.
///
/// The default implementation will paint all of the widget's children.
Expand Down Expand Up @@ -180,6 +216,9 @@ pub trait ErasedWidget: Any + fmt::Debug {
/// See [`Widget::layout`].
fn layout(&self, ctx: LayoutContext<'_>, constraints: Constraints) -> Vec2;

/// See [`Widget::intrinsic_size`].
fn intrinsic_size(&self, ctx: IntrinsicSizeContext<'_>, axis: Axis) -> f32;

/// See [`Widget::flex`].
fn flex(&self) -> (u32, FlexFit);

Expand Down Expand Up @@ -207,6 +246,10 @@ where
<T as Widget>::layout(self, ctx, constraints)
}

fn intrinsic_size(&self, ctx: IntrinsicSizeContext<'_>, axis: Axis) -> f32 {
<T as Widget>::intrinsic_size(self, ctx, axis)
}

fn flex(&self) -> (u32, FlexFit) {
<T as Widget>::flex(self)
}
Expand Down

0 comments on commit d5b92aa

Please sign in to comment.