don't do a linked list lol

rust-rewrite
Patrick Cleavelin 2024-02-24 22:23:38 -06:00
parent 24c0e24d5f
commit 4beed39921
2 changed files with 157 additions and 101 deletions

View File

@ -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;
} }

View File

@ -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();
/*************************/ /*************************/