Skip to content

Commit

Permalink
feat: Absolute positioning
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Nov 5, 2023
1 parent 7db5f05 commit 7f7d447
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 22 deletions.
35 changes: 18 additions & 17 deletions crates/dom/src/dom_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,30 @@ impl<'a> DioxusDOMAdapter<'a> {
impl DOMAdapter<NodeId> for DioxusDOMAdapter<'_> {
fn get_node(&self, node_id: &NodeId) -> Option<Node> {
let node = self.rdom.get(*node_id)?;
let mut size = node.get::<LayoutState>().unwrap().clone();
let mut layout = node.get::<LayoutState>().unwrap().clone();

// The root node expands by default
if *node_id == self.rdom.root_id() {
size.width = Size::Percentage(Length::new(100.0));
size.height = Size::Percentage(Length::new(100.0));
layout.width = Size::Percentage(Length::new(100.0));
layout.height = Size::Percentage(Length::new(100.0));
}

Some(Node {
width: size.width,
height: size.height,
minimum_width: size.minimum_width,
minimum_height: size.minimum_height,
maximum_width: size.maximum_width,
maximum_height: size.maximum_height,
direction: size.direction,
padding: size.padding,
margin: size.margin,
main_alignment: size.main_alignment,
cross_alignment: size.cross_alignment,
offset_x: Length::new(size.offset_x),
offset_y: Length::new(size.offset_y),
has_layout_references: size.node_ref.is_some(),
width: layout.width,
height: layout.height,
minimum_width: layout.minimum_width,
minimum_height: layout.minimum_height,
maximum_width: layout.maximum_width,
maximum_height: layout.maximum_height,
direction: layout.direction,
padding: layout.padding,
margin: layout.margin,
main_alignment: layout.main_alignment,
cross_alignment: layout.cross_alignment,
offset_x: Length::new(layout.offset_x),
offset_y: Length::new(layout.offset_y),
has_layout_references: layout.node_ref.is_some(),
position: layout.position,
})
}

Expand Down
1 change: 1 addition & 0 deletions crates/elements/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ builder_constructors! {
name: String,
focusable: String,
margin: String,
position: String,
};
label {
color: String,
Expand Down
9 changes: 9 additions & 0 deletions crates/state/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct LayoutState {
pub offset_x: f32,
pub main_alignment: Alignment,
pub cross_alignment: Alignment,
pub position: Position,
pub node_ref: Option<UnboundedSender<NodeReferenceLayout>>,
}

Expand Down Expand Up @@ -57,6 +58,7 @@ impl State<CustomAttributeValues> for LayoutState {
"cross_align",
"reference",
"margin",
"position",
]))
.with_tag()
.with_text();
Expand Down Expand Up @@ -190,6 +192,13 @@ impl State<CustomAttributeValues> for LayoutState {
}
}
}
"position" => {
if let Some(value) = attr.value.as_text() {
if let Ok(position) = Position::parse(value) {
layout.position = position;
}
}
}
"reference" => {
if let OwnedAttributeValue::Custom(CustomAttributeValues::Reference(
reference,
Expand Down
2 changes: 2 additions & 0 deletions crates/state/src/values/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod font;
mod gaps;
mod gradient;
mod overflow;
mod position;
mod shadow;
mod size;
mod text_shadow;
Expand All @@ -26,6 +27,7 @@ pub use font::*;
pub use gaps::*;
pub use gradient::*;
pub use overflow::*;
pub use position::*;
pub use shadow::*;
pub use size::*;
pub use text_shadow::*;
16 changes: 16 additions & 0 deletions crates/state/src/values/position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::Parse;
use torin::position::Position;

#[derive(Debug, PartialEq, Eq)]
pub struct ParsePositionError;

impl Parse for Position {
type Err = ParsePositionError;

fn parse(value: &str) -> Result<Self, Self::Err> {
Ok(match value {
"absolute" => Position::Absolute,
_ => Position::Stacked,
})
}
}
17 changes: 14 additions & 3 deletions crates/torin/src/measure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
geometry::{Area, Size2D},
measure_mode::MeasureMode,
node::Node,
prelude::{AlignmentDirection, AreaModel, Torin},
prelude::{AlignmentDirection, AreaModel, Position, Torin},
size::Size,
};

Expand All @@ -29,9 +29,14 @@ pub fn measure_node<Key: NodeKey>(
) -> (bool, NodeAreas) {
let must_run = layout.dirty.contains(&node_id) || layout.results.get(&node_id).is_none();
if must_run {
let origin = match node.position {
Position::Stacked => available_parent_area.origin,
Position::Absolute => parent_area.origin,
};

// 1. Create the initial Node area
let mut area = Rect::new(
available_parent_area.origin,
origin,
Size2D::new(node.padding.horizontal(), node.padding.vertical()),
);

Expand Down Expand Up @@ -253,7 +258,13 @@ pub fn measure_inner_nodes<Key: NodeKey>(
);

// Stack the child into its parent
mode.stack_into_node(parent_node, available_area, &child_areas.area, inner_sizes);
mode.stack_into_node(
parent_node,
available_area,
&child_areas.area,
inner_sizes,
&child_data,
);

// Cache the child layout if it was mutated and inner nodes must be cache
if child_revalidated && must_cache_inner_nodes {
Expand Down
8 changes: 7 additions & 1 deletion crates/torin/src/measure_mode.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::prelude::{
get_align_axis, AlignAxis, AlignmentDirection, Area, DirectionMode, Node, Size, Size2D,
get_align_axis, AlignAxis, AlignmentDirection, Area, DirectionMode, Node, Position, Size,
Size2D,
};

/// Measurement data for the inner Nodes of a Node
Expand Down Expand Up @@ -134,7 +135,12 @@ impl<'a> MeasureMode<'a> {
available_area: &mut Area,
content_area: &Area,
inner_sizes: &mut Size2D,
node_data: &Node,
) {
if node_data.position == Position::Absolute {
return;
}

match parent_node.direction {
DirectionMode::Horizontal => {
// Move the available area
Expand Down
5 changes: 4 additions & 1 deletion crates/torin/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
pub use euclid::Rect;

use crate::{
alignment::Alignment, direction::DirectionMode, gaps::Gaps, geometry::Length, size::Size,
alignment::Alignment, direction::DirectionMode, gaps::Gaps, geometry::Length,
prelude::Position, size::Size,
};

/// Node layout configuration
Expand Down Expand Up @@ -36,6 +37,8 @@ pub struct Node {
/// Direction in which it's inner Nodes will be stacked
pub direction: DirectionMode,

pub position: Position,

/// A Node might depend on inner sizes but have a fixed position, like scroll views.
pub has_layout_references: bool,
}
Expand Down
2 changes: 2 additions & 0 deletions crates/torin/src/values/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
pub mod alignment;
pub mod direction;
pub mod gaps;
pub mod position;
pub mod size;

pub mod prelude {
pub use crate::alignment::*;
pub use crate::direction::*;
pub use crate::gaps::*;
pub use crate::position::*;
pub use crate::size::*;
}
7 changes: 7 additions & 0 deletions crates/torin/src/values/position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[derive(Default, PartialEq, Eq, Debug, Clone)]
pub enum Position {
#[default]
Stacked,

Absolute,
}
41 changes: 41 additions & 0 deletions examples/position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

use freya::prelude::*;

fn main() {
launch_with_props(app, "Position", (400.0, 350.0));
}

fn app(cx: Scope) -> Element {
render!(
rect {
height: "100%",
width: "100%",
rect {
height: "20%",
width: "100%",
background: "green",
}
rect {
height: "100",
width: "100",
background: "red",
position: "absolute",
layer: "-1"
}
rect {
height: "20%",
width: "100%",
background: "orange",
}
rect {
height: "20%",
width: "100%",
background: "yellow",
}
}
)
}

0 comments on commit 7f7d447

Please sign in to comment.