prepare for layouting

This commit is contained in:
Daniel Bulant 2023-10-19 10:06:10 +02:00
parent 68cf25da3f
commit 8ca035e6ff
3 changed files with 88 additions and 16 deletions

View file

@ -22,7 +22,7 @@ use glutin::{
};
use taffy::Taffy;
use weak_table::PtrWeakKeyHashMap;
use crate::nodes::{Node, render_recursively, RenderContext};
use crate::nodes::{layout_recursively, Node, render_recursively, RenderContext};
mod nodes;
@ -48,7 +48,9 @@ fn main() {
taffy_map.insert(root.clone(), root_node);
let mut context = RenderContext {
canvas
canvas,
taffy_map,
taffy
};
event_loop.run(move |event, _target, control_flow| match event {
@ -66,7 +68,16 @@ fn main() {
_ => {}
},
Event::RedrawRequested(_) => {
render(&buffer_context, &surface, &window, &mut context, &root, &taffy_map, &taffy);
layout_recursively(&root, &mut context);
let src_nodes = context.taffy_map.values().map(|v| v.to_owned()).collect::<Vec<_>>();
context.taffy_map.remove_expired();
let dst_nodes = context.taffy_map.values().map(|v| v.to_owned()).collect::<Vec<_>>();
for src_node in src_nodes {
if !dst_nodes.contains(&src_node) {
context.taffy.remove(src_node).unwrap();
}
}
render(&buffer_context, &surface, &window, &mut context, &root);
},
_ => {}
})
@ -115,9 +126,7 @@ fn render(
surface: &Surface<WindowSurface>,
window: &Window,
context: &mut RenderContext<OpenGl>,
root_node: &Arc<GNode>,
taffy_map: &TaffyMap,
taffy: &Taffy
root_node: &Arc<GNode>
) {
// Make sure the canvas has the right size:
let size = window.inner_size();
@ -126,7 +135,7 @@ fn render(
context.canvas.clear_rect(0, 0, size.width, size.height, Color::black());
// Do the render passes here
render_recursively(root_node, context, taffy_map, taffy);
render_recursively(root_node, context);
// Tell renderer to execute all drawing commands
context.canvas.flush();

32
src/nodes/layout.rs Normal file
View file

@ -0,0 +1,32 @@
use femtovg::Renderer;
use crate::nodes::{Node, NodeChildren, Overflow, RenderContext, Style};
use taffy::style::{Style as TaffyStyle};
pub struct Layout<T> {
style: Style,
children: NodeChildren<T>
}
impl<T: Renderer> Layout<T> {
pub(crate) fn new() -> Layout<T> {
Layout {
style: Style {
layout: TaffyStyle::default(),
overflow: Overflow::Visible
},
children: NodeChildren::new()
}
}
}
impl<T: Renderer> Node<T> for Layout<T> {
fn style(&self) -> &Style {
&self.style
}
fn children(&self) -> Option<&NodeChildren<T>> {
Some(&self.children)
}
fn render(&self, context: &mut RenderContext<T>, _layout: taffy::layout::Layout, render_children: &dyn Fn(&mut RenderContext<T>)) {
render_children(context);
}
}

View file

@ -1,3 +1,5 @@
pub mod layout;
use std::sync::Arc;
use femtovg::{Canvas, Color, Renderer};
use femtovg::renderer::OpenGl;
@ -9,7 +11,9 @@ use taffy::Taffy;
use crate::{GNode, TaffyMap};
pub struct RenderContext<T: Renderer> {
pub(crate) canvas: Canvas<T>,
pub canvas: Canvas<T>,
pub taffy_map: TaffyMap,
pub taffy: Taffy
}
#[derive(Copy, Clone, Default)]
@ -39,14 +43,41 @@ pub trait Node<T: Renderer> {
fn children(&self) -> Option<&NodeChildren<T>>;
/// Render the node and its children. render_children gets ['children'] and calls this function there as well. When drawing, the canvas is translated to the node's location.
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
fn render(&self, context: &mut RenderContext<T>, layout: &Layout, render_children: &dyn Fn(&mut RenderContext<T>));
fn render(&self, context: &mut RenderContext<T>, layout: Layout, render_children: &dyn Fn(&mut RenderContext<T>));
}
pub fn render_recursively(selfref: &Arc<GNode>, context: &mut RenderContext<OpenGl>, taffy_map: &TaffyMap, taffy: &Taffy) {
let styles = selfref.style();
let node = taffy_map.get(selfref).unwrap();
let layout = taffy.layout(*node).unwrap();
let sself = selfref.clone();
pub fn layout_recursively(node: &Arc<GNode>, context: &mut RenderContext<OpenGl>) -> taffy::node::Node {
let taffy_node = context.taffy_map.get(node);
let taffy_node = match taffy_node {
Some(taffy_node) => taffy_node,
None => {
let taffy_node = context.taffy.new_leaf(node.style().layout.to_owned()).unwrap();
context.taffy_map.insert(node.clone(), taffy_node);
context.taffy_map.get(node).unwrap()
}
};
let taffy_node = taffy_node.to_owned();
match node.children() {
None => {},
Some(children) => {
let mut t_children = Vec::with_capacity(children.len());
for child in children {
t_children.push(layout_recursively(child, context).to_owned());
}
context.taffy.set_children(taffy_node, t_children.as_slice()).unwrap();
}
}
taffy_node
}
pub fn render_recursively(node: &Arc<GNode>, context: &mut RenderContext<OpenGl>) {
let styles = node.style();
let taffy_node = context.taffy_map.get(node).unwrap();
let layout = *context.taffy.layout(*taffy_node).unwrap();
let sself = node.clone();
context.canvas.save();
context.canvas.translate(layout.location.x, layout.location.y);
match styles.overflow {
@ -63,7 +94,7 @@ pub fn render_recursively(selfref: &Arc<GNode>, context: &mut RenderContext<Open
sself.render(context, layout, & (|context| {
if let Some(children) = sself.children() {
for child in children {
render_recursively(child, context, taffy_map, taffy);
render_recursively(child, context);
}
}
}));
@ -98,7 +129,7 @@ impl<T: Renderer> Node<T> for RedBoxDemo {
fn children(&self) -> Option<&NodeChildren<T>> {
None
}
fn render<'a>(&self, context: &mut RenderContext<T>, _layout: &Layout, _render_children: &dyn Fn(&mut RenderContext<T>)) {
fn render(&self, context: &mut RenderContext<T>, _layout: Layout, _render_children: &dyn Fn(&mut RenderContext<T>)) {
context.canvas.clear_rect(
0,
0,