Skip to repository content125 lines · 4.1 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T05:59:42.345Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
class_diagram.rs
1use anyhow::Result;
2use quick_xml::events::Event;
3
4use super::{
5 AccentStackEntry, NodeTracker, accent_class_name, add_class, add_to_event,
6 is_foreign_object_fallback_group, parse_translate,
7};
8
9pub(crate) struct ClassDiagramAccents {
10 accent_count: usize,
11 accent_g_stack: Vec<AccentStackEntry>,
12 node_counter: usize,
13 nodes: NodeTracker,
14 current_text_accent: Option<usize>,
15}
16
17impl ClassDiagramAccents {
18 pub(super) fn new(accent_count: usize) -> Self {
19 Self {
20 accent_count,
21 accent_g_stack: Vec::new(),
22 node_counter: 0,
23 nodes: NodeTracker::default(),
24 current_text_accent: None,
25 }
26 }
27
28 pub(super) fn process_event<'a>(&mut self, event: Event<'a>) -> Result<Event<'a>> {
29 if self.accent_count == 0 {
30 return Ok(event);
31 }
32
33 match &event {
34 Event::Start(e) if e.name().as_ref() == b"g" => {
35 if is_foreign_object_fallback_group(e)? {
36 self.accent_g_stack.push(AccentStackEntry::none());
37 return Ok(event);
38 }
39
40 let is_node = if let Some(class_attr) = e.try_get_attribute("class")? {
41 let class = class_attr.unescape_value()?;
42 class
43 .split_whitespace()
44 .any(|token| token == "node" || token == "stateGroup")
45 } else {
46 false
47 };
48
49 if is_node {
50 let accent_idx = self.node_counter % self.accent_count;
51 self.node_counter += 1;
52
53 let tracks_node = if let Some((cx, cy)) = parse_translate(e) {
54 self.nodes.start_node(cx, cy, 30.0, accent_idx);
55 true
56 } else {
57 false
58 };
59
60 self.accent_g_stack
61 .push(AccentStackEntry::accent(accent_idx, tracks_node));
62 let new_elem = add_class(e, &accent_class_name(accent_idx))?;
63 return Ok(Event::Start(new_elem));
64 }
65
66 self.accent_g_stack.push(AccentStackEntry::none());
67 Ok(event)
68 }
69
70 Event::End(e) if e.name().as_ref() == b"g" => {
71 if let Some(entry) = self.accent_g_stack.pop() {
72 if entry.tracks_node() {
73 self.nodes.maybe_finish_node();
74 }
75 }
76 Ok(event)
77 }
78
79 Event::Start(e) | Event::Empty(e)
80 if matches!(
81 e.name().as_ref(),
82 b"rect" | b"path" | b"circle" | b"polygon" | b"ellipse"
83 ) =>
84 {
85 if e.name().as_ref() == b"path" {
86 self.nodes.update_half_height(e);
87 }
88
89 Ok(event)
90 }
91
92 Event::Start(e) | Event::Empty(e)
93 if e.name().as_ref() == b"text" || e.name().as_ref() == b"tspan" =>
94 {
95 let is_start = matches!(event, Event::Start(_));
96 let is_text = e.name().as_ref() == b"text";
97
98 let accent_idx = if is_text {
99 self.nodes
100 .lookup_accent(e)
101 .or_else(|| super::current_stack_accent(&self.accent_g_stack))
102 } else {
103 self.current_text_accent
104 };
105
106 if let Some(idx) = accent_idx {
107 if is_text && is_start {
108 self.current_text_accent = Some(idx);
109 }
110 return add_to_event(&event, e, &accent_class_name(idx));
111 }
112
113 Ok(event)
114 }
115
116 Event::End(e) if e.name().as_ref() == b"text" => {
117 self.current_text_accent = None;
118 Ok(event)
119 }
120
121 _ => Ok(event),
122 }
123 }
124}
125