mirror of
https://github.com/danbulant/mangui
synced 2026-06-20 23:01:11 +00:00
prepare for layouting
This commit is contained in:
parent
68cf25da3f
commit
8ca035e6ff
3 changed files with 88 additions and 16 deletions
23
src/main.rs
23
src/main.rs
|
|
@ -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
32
src/nodes/layout.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue