Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pivot to reflow #144

Merged
merged 1 commit into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions crates/yakui-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,40 @@ impl Alignment {
pub const BOTTOM_CENTER: Self = Self::new(0.5, 1.0);
pub const BOTTOM_RIGHT: Self = Self::new(1.0, 1.0);
}

/// Defines a reference point for a widget.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Pivot {
x: f32,
y: f32,
}

impl Pivot {
/// Create a new `Pivot` given an anchor point.
///
/// `0.0, 0.0` is the top left corner of the widget, while `1.0, 1.0` is
/// the bottom right corner.
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}

/// Returns the point for a pivot value.
pub const fn as_vec2(&self) -> Vec2 {
Vec2::new(self.x, self.y)
}
}

#[allow(missing_docs)]
impl Pivot {
pub const TOP_LEFT: Self = Self::new(0.0, 0.0);
pub const TOP_CENTER: Self = Self::new(0.5, 0.0);
pub const TOP_RIGHT: Self = Self::new(1.0, 0.0);

pub const CENTER_LEFT: Self = Self::new(0.0, 0.5);
pub const CENTER: Self = Self::new(0.5, 0.5);
pub const CENTER_RIGHT: Self = Self::new(1.0, 0.5);

pub const BOTTOM_LEFT: Self = Self::new(0.0, 1.0);
pub const BOTTOM_CENTER: Self = Self::new(0.5, 1.0);
pub const BOTTOM_RIGHT: Self = Self::new(1.0, 1.0);
}
5 changes: 3 additions & 2 deletions crates/yakui-widgets/src/shorthand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::borrow::Cow;

use yakui_core::geometry::{Color, Constraints, Dim2, Vec2};
use yakui_core::widget::PaintContext;
use yakui_core::{Alignment, ManagedTextureId, Response, TextureId};
use yakui_core::{Alignment, ManagedTextureId, Pivot, Response, TextureId};

use crate::widgets::{
Align, AlignResponse, Button, ButtonResponse, Canvas, CanvasResponse, Checkbox,
Expand Down Expand Up @@ -170,10 +170,11 @@ pub fn slider(value: f64, min: f64, max: f64) -> Response<SliderResponse> {
/// See [Reflow].
pub fn reflow(
anchor: Alignment,
pivot: Pivot,
offset: Dim2,
children: impl FnOnce(),
) -> Response<ReflowResponse> {
Reflow::new(anchor, offset).show(children)
Reflow::new(anchor, pivot, offset).show(children)
}

/// See [Opaque].
Expand Down
20 changes: 16 additions & 4 deletions crates/yakui-widgets/src/widgets/reflow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use yakui_core::geometry::{Constraints, Dim2, Vec2};
use yakui_core::widget::{LayoutContext, Widget};
use yakui_core::{Alignment, Flow, Response};
use yakui_core::{Alignment, Flow, Pivot, Response};

use crate::util::widget_children;

Expand All @@ -12,12 +12,17 @@ or table layouts.
#[non_exhaustive]
pub struct Reflow {
pub anchor: Alignment,
pub pivot: Pivot,
pub offset: Dim2,
}

impl Reflow {
pub fn new(anchor: Alignment, offset: Dim2) -> Self {
Self { anchor, offset }
pub fn new(anchor: Alignment, pivot: Pivot, offset: Dim2) -> Self {
Self {
anchor,
pivot,
offset,
}
}

pub fn show<F: FnOnce()>(self, children: F) -> Response<ReflowResponse> {
Expand All @@ -40,6 +45,7 @@ impl Widget for ReflowWidget {
Self {
props: Reflow {
anchor: Alignment::TOP_LEFT,
pivot: Pivot::TOP_LEFT,
offset: Dim2::ZERO,
},
}
Expand All @@ -58,8 +64,14 @@ impl Widget for ReflowWidget {

fn layout(&self, mut ctx: LayoutContext<'_>, _constraints: Constraints) -> Vec2 {
let node = ctx.dom.get_current();
let mut size = Vec2::ZERO;
for &child in &node.children {
size = size.max(ctx.calculate_layout(child, Constraints::none()));
}

let pivot_offset = -size * self.props.pivot.as_vec2();
for &child in &node.children {
ctx.calculate_layout(child, Constraints::none());
ctx.layout.set_pos(child, pivot_offset);
}

Vec2::ZERO
Expand Down
15 changes: 10 additions & 5 deletions crates/yakui-widgets/tests/snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use yakui::{Constraints, CrossAxisAlignment, Dim2, MainAxisAlignment, MainAxisSize, Vec2};
use yakui_core::geometry::Color;
use yakui_core::Alignment;
use yakui_core::{Alignment, Pivot};
use yakui_test::{run, Test};
use yakui_widgets::widgets::{Button, List, Pad, UnconstrainedBox};
use yakui_widgets::{
Expand Down Expand Up @@ -351,13 +351,18 @@ fn row_reflow() {
colored_box(Color::RED, [50.0, 50.0]);
colored_box(Color::GREEN, [50.0, 50.0]);

reflow(Alignment::BOTTOM_RIGHT, Dim2::ZERO, || {
reflow(Alignment::BOTTOM_RIGHT, Pivot::TOP_LEFT, Dim2::ZERO, || {
colored_box(Color::BLUE, [100.0, 50.0]);
});

reflow(Alignment::BOTTOM_RIGHT, Dim2::pixels(0.0, 50.0), || {
colored_box(Color::WHITE, [100.0, 100.0]);
});
reflow(
Alignment::BOTTOM_RIGHT,
Pivot::TOP_LEFT,
Dim2::pixels(0.0, 50.0),
|| {
colored_box(Color::WHITE, [100.0, 100.0]);
},
);
});
});
});
Expand Down
3 changes: 2 additions & 1 deletion crates/yakui/examples/dropdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use yakui::widgets::Layer;
use yakui::{align, button, column, reflow, use_state, widgets::Pad, Alignment, Dim2};
use yakui_core::Pivot;

pub fn run() {
let open = use_state(|| false);
Expand All @@ -25,7 +26,7 @@ pub fn run() {
if open.get() {
Pad::ZERO.show(|| {
Layer::new().show(|| {
reflow(Alignment::BOTTOM_LEFT, Dim2::ZERO, || {
reflow(Alignment::BOTTOM_LEFT, Pivot::TOP_LEFT, Dim2::ZERO, || {
column(|| {
let current = selected.get();
for (i, option) in options.iter().enumerate() {
Expand Down
Loading