don't do a linked list lol
parent
24c0e24d5f
commit
4beed39921
|
@ -1,7 +1,11 @@
|
||||||
|
// TODO: remove when things are actully used
|
||||||
|
#![allow(dead_code)]
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const ROOT_NODE: &str = "root";
|
const ROOT_NODE: &str = "root";
|
||||||
|
|
||||||
|
type NodeIndex = usize;
|
||||||
|
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct NodeKey(String);
|
pub struct NodeKey(String);
|
||||||
impl std::fmt::Display for NodeKey {
|
impl std::fmt::Display for NodeKey {
|
||||||
|
@ -22,172 +26,222 @@ impl NodeKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(cx: &Context, label: &str) -> Self {
|
pub fn new(cx: &Context, label: &str) -> Self {
|
||||||
NodeKey(format!("{}:{label}", cx.current_parent))
|
NodeKey(format!("{}:{label}", cx.node_ref(cx.current_parent).label))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
enum SemanticSize {
|
||||||
|
#[default]
|
||||||
|
FitText,
|
||||||
|
ChildrenSum,
|
||||||
|
Fill,
|
||||||
|
Exact(i32),
|
||||||
|
PercentOfParent(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
enum Axis {
|
||||||
|
#[default]
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct PersistentNodeData {
|
||||||
|
axis: Axis,
|
||||||
|
semantic_size: [SemanticSize; 2],
|
||||||
|
computed_size: [i32; 2],
|
||||||
|
computed_pos: [i32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Node {
|
struct FrameNode {
|
||||||
first: Option<NodeKey>,
|
key: NodeKey,
|
||||||
last: Option<NodeKey>,
|
|
||||||
next: Option<NodeKey>,
|
|
||||||
prev: Option<NodeKey>,
|
|
||||||
|
|
||||||
parent: Option<NodeKey>,
|
|
||||||
|
|
||||||
label: String,
|
label: String,
|
||||||
|
|
||||||
|
first: Option<NodeIndex>,
|
||||||
|
last: Option<NodeIndex>,
|
||||||
|
next: Option<NodeIndex>,
|
||||||
|
prev: Option<NodeIndex>,
|
||||||
|
parent: Option<NodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context {
|
impl FrameNode {
|
||||||
persistent_nodes: HashMap<NodeKey, Node>,
|
fn root() -> Self {
|
||||||
|
Self {
|
||||||
current_parent: NodeKey,
|
key: NodeKey::root(),
|
||||||
root_node: NodeKey,
|
label: "root".to_string(),
|
||||||
}
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut nodes = HashMap::new();
|
|
||||||
nodes.insert(
|
|
||||||
NodeKey::root(),
|
|
||||||
Node {
|
|
||||||
first: None,
|
first: None,
|
||||||
last: None,
|
last: None,
|
||||||
next: None,
|
next: None,
|
||||||
prev: None,
|
prev: None,
|
||||||
parent: None,
|
parent: None,
|
||||||
label: "root".to_string(),
|
}
|
||||||
},
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
|
pub struct Context {
|
||||||
|
persistent: HashMap<NodeKey, PersistentNodeData>,
|
||||||
|
frame_nodes: Vec<FrameNode>,
|
||||||
|
|
||||||
|
current_parent: NodeIndex,
|
||||||
|
root_node: NodeIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut nodes = HashMap::new();
|
||||||
|
nodes.insert(NodeKey::root(), PersistentNodeData::default());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
persistent_nodes: nodes,
|
persistent: nodes,
|
||||||
current_parent: NodeKey::root(),
|
frame_nodes: vec![FrameNode::root()],
|
||||||
root_node: NodeKey::root(),
|
current_parent: 0,
|
||||||
|
root_node: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_key(&self, key: &NodeKey) -> Option<NodeKey> {
|
// TODO: refactor to not panic, return option
|
||||||
self.persistent_nodes
|
/// Panics on out-of-bounds index
|
||||||
.get(key)
|
fn node_ref(&self, index: NodeIndex) -> &FrameNode {
|
||||||
.and_then(|n| n.parent.clone())
|
self.frame_nodes
|
||||||
}
|
.get(index)
|
||||||
fn first_key(&self, key: &NodeKey) -> Option<NodeKey> {
|
.expect("this is a bug, index should be valid")
|
||||||
self.first_key_ref(key).cloned()
|
|
||||||
}
|
|
||||||
fn last_key(&self, key: &NodeKey) -> Option<NodeKey> {
|
|
||||||
self.persistent_nodes.get(key).and_then(|n| n.last.clone())
|
|
||||||
}
|
|
||||||
fn next_key(&self, key: &NodeKey) -> Option<NodeKey> {
|
|
||||||
self.next_key_ref(key).cloned()
|
|
||||||
}
|
|
||||||
fn prev_key(&self, key: &NodeKey) -> Option<NodeKey> {
|
|
||||||
self.persistent_nodes.get(key).and_then(|n| n.prev.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_key_ref(&self, key: &NodeKey) -> Option<&NodeKey> {
|
// TODO: refactor to not panic, return option
|
||||||
self.persistent_nodes
|
/// Panics on out-of-bounds index
|
||||||
.get(key)
|
fn node_ref_mut(&mut self, index: NodeIndex) -> &mut FrameNode {
|
||||||
.and_then(|n| n.first.as_ref())
|
self.frame_nodes
|
||||||
}
|
.get_mut(index)
|
||||||
fn next_key_ref(&self, key: &NodeKey) -> Option<&NodeKey> {
|
.expect("this is a bug, index should be valid")
|
||||||
self.persistent_nodes.get(key).and_then(|n| n.next.as_ref())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_node(&mut self, label: impl ToString) -> NodeKey {
|
fn node_first_ref_mut(&mut self, index: NodeIndex) -> Option<&mut FrameNode> {
|
||||||
|
self.node_ref_mut(index)
|
||||||
|
.first
|
||||||
|
.map(|index| self.node_ref_mut(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_last_ref_mut(&mut self, index: NodeIndex) -> Option<&mut FrameNode> {
|
||||||
|
self.node_ref_mut(index)
|
||||||
|
.last
|
||||||
|
.map(|index| self.node_ref_mut(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_next_ref_mut(&mut self, index: NodeIndex) -> Option<&mut FrameNode> {
|
||||||
|
self.node_ref_mut(index)
|
||||||
|
.next
|
||||||
|
.map(|index| self.node_ref_mut(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_prev_ref_mut(&mut self, index: NodeIndex) -> Option<&mut FrameNode> {
|
||||||
|
self.node_ref_mut(index)
|
||||||
|
.prev
|
||||||
|
.map(|index| self.node_ref_mut(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_node(&mut self, label: impl ToString) -> NodeIndex {
|
||||||
let label = label.to_string();
|
let label = label.to_string();
|
||||||
let key = NodeKey::new(self, &label);
|
let key = NodeKey::new(self, &label);
|
||||||
|
|
||||||
if let Some(_node) = self.persistent_nodes.get(&key) {
|
if let Some(_node) = self.persistent.get(&key) {
|
||||||
// TODO: check for last_interacted_index
|
// TODO: check for last_interacted_index and invalidate persistent data
|
||||||
} else {
|
} else {
|
||||||
let node = Node {
|
self.persistent
|
||||||
|
.insert(key.clone(), PersistentNodeData::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
let frame_node = FrameNode {
|
||||||
|
key,
|
||||||
|
label,
|
||||||
first: None,
|
first: None,
|
||||||
last: None,
|
last: None,
|
||||||
next: None,
|
next: None,
|
||||||
prev: self.last_key(&self.current_parent),
|
prev: self.node_ref(self.current_parent).last,
|
||||||
parent: Some(self.current_parent.clone()),
|
parent: Some(self.current_parent),
|
||||||
|
|
||||||
label,
|
|
||||||
};
|
};
|
||||||
self.persistent_nodes.insert(key.clone(), node);
|
self.frame_nodes.push(frame_node);
|
||||||
|
let this_index = self.frame_nodes.len() - 1;
|
||||||
|
|
||||||
|
if let Some(parent_last) = self.node_last_ref_mut(self.current_parent) {
|
||||||
|
parent_last.next = Some(this_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update tree references
|
let parent_node = self.node_ref_mut(self.current_parent);
|
||||||
if let Some(parent_node) = self.persistent_nodes.get_mut(&self.current_parent) {
|
|
||||||
if parent_node.first.is_none() {
|
if parent_node.first.is_none() {
|
||||||
parent_node.first = Some(key.clone());
|
parent_node.first = Some(this_index);
|
||||||
|
}
|
||||||
|
parent_node.last = Some(this_index);
|
||||||
|
|
||||||
|
this_index
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(pcleavelin): `parent_node.last` must be updated before the below mutable
|
pub fn push_parent(&mut self, key: NodeIndex) {
|
||||||
// borrow so the mutable reference above is un-borrowed by then
|
|
||||||
let last_before_update = parent_node.last.clone();
|
|
||||||
parent_node.last = Some(key.clone());
|
|
||||||
|
|
||||||
if let Some(parent_node_last) = last_before_update {
|
|
||||||
if let Some(last_node) = self.persistent_nodes.get_mut(&parent_node_last) {
|
|
||||||
last_node.next = Some(key.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
key
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_parent(&mut self, key: NodeKey) {
|
|
||||||
self.current_parent = key;
|
self.current_parent = key;
|
||||||
}
|
}
|
||||||
pub fn pop_parent(&mut self) {
|
pub fn pop_parent(&mut self) {
|
||||||
self.current_parent = self
|
self.current_parent = self.node_ref(self.current_parent).parent.unwrap_or(0);
|
||||||
.parent_key(&self.current_parent)
|
|
||||||
.unwrap_or(NodeKey::root());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_print(&self) {
|
pub fn debug_print(&self) {
|
||||||
let root_node = NodeKey::root();
|
let iter = NodeIter::from_index(&self.frame_nodes, 0);
|
||||||
let iter = NodeIter::from_key(self, self.first_key_ref(&root_node).unwrap());
|
|
||||||
|
|
||||||
for node in iter {
|
for node in iter {
|
||||||
eprintln!("{node:?}");
|
eprintln!("{node:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_layout(&mut self) {
|
||||||
|
let iter = NodeIter::from_index(&self.frame_nodes, 0);
|
||||||
|
for node in iter {
|
||||||
|
let Some(persistent) = self.persistent.get_mut(&node.key) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(parent_index) = node.parent {
|
||||||
|
let parent_node = self.node_ref(parent_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeIter<'a> {
|
struct NodeIter<'a> {
|
||||||
cx: &'a Context,
|
frame_nodes: &'a [FrameNode],
|
||||||
current_key: &'a NodeKey,
|
index: NodeIndex,
|
||||||
reached_end: bool,
|
reached_end: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeIter<'a> {
|
impl<'a> NodeIter<'a> {
|
||||||
fn from_key(cx: &'a Context, key: &'a NodeKey) -> Self {
|
fn from_index(frame_nodes: &'a [FrameNode], index: NodeIndex) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
frame_nodes,
|
||||||
current_key: key,
|
index,
|
||||||
reached_end: false,
|
reached_end: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for NodeIter<'a> {
|
impl<'a> Iterator for NodeIter<'a> {
|
||||||
type Item = &'a Node;
|
type Item = &'a FrameNode;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.reached_end {
|
if self.reached_end {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(node) = self.cx.persistent_nodes.get(self.current_key) {
|
if let Some(node) = self.frame_nodes.get(self.index) {
|
||||||
if let Some(first) = node.first.as_ref() {
|
if let Some(first) = node.first {
|
||||||
self.current_key = first;
|
self.index = first;
|
||||||
} else if let Some(next) = node.next.as_ref() {
|
} else if let Some(next) = node.next {
|
||||||
self.current_key = next;
|
self.index = next;
|
||||||
} else if let Some(parent) = node.parent.as_ref() {
|
} else if let Some(parent_next) = node
|
||||||
if let Some(parent_next) = self.cx.next_key_ref(parent) {
|
.parent
|
||||||
self.current_key = parent_next;
|
.and_then(|index| self.frame_nodes.get(index))
|
||||||
} else {
|
.and_then(|node| node.next)
|
||||||
self.reached_end = true;
|
{
|
||||||
}
|
self.index = parent_next;
|
||||||
} else {
|
} else {
|
||||||
self.reached_end = true;
|
self.reached_end = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
cx.pop_parent();
|
cx.pop_parent();
|
||||||
cx.make_node("fourth child");
|
cx.make_node("fourth child");
|
||||||
|
|
||||||
|
cx.debug_print();
|
||||||
|
cx.update_layout();
|
||||||
cx.debug_print();
|
cx.debug_print();
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
|
|
Loading…
Reference in New Issue