egui_treeize/ui/viewer.rs
1use egui::{Painter, Pos2, Rect, Style, Ui, emath::TSTransform};
2
3use crate::{InPin, InPinId, NodeId, OutPin, OutPinId, Treeize};
4
5use super::{
6 BackgroundPattern, NodeLayout, TreeizeStyle,
7 pin::{AnyPins, TreeizePin},
8};
9
10/// `TreeizeViewer` is a trait for viewing a Treeize.
11///
12/// It can extract necessary data from the nodes and controls their
13/// response to certain events.
14pub trait TreeizeViewer<T> {
15 /// Returns title of the node.
16 fn title(&mut self, node: &T) -> String;
17
18 /// Returns the node's frame.
19 /// All node's elements will be rendered inside this frame.
20 /// Except for pins if they are configured to be rendered outside of the frame.
21 ///
22 /// Returns `default` by default.
23 /// `default` frame is taken from the [`TreeizeStyle::node_frame`] or constructed if it's `None`.
24 ///
25 /// Override this method to customize the frame for specific nodes.
26 fn node_frame(
27 &mut self,
28 default: egui::Frame,
29 node: NodeId,
30 inputs: &[InPin],
31 outputs: &[OutPin],
32 treeize: &Treeize<T>,
33 ) -> egui::Frame {
34 let _ = (node, inputs, outputs, treeize);
35 default
36 }
37
38 /// Returns the node's header frame.
39 ///
40 /// This frame would be placed on top of the node's frame.
41 /// And header UI (see [`show_header`]) will be placed inside this frame.
42 ///
43 /// Returns `default` by default.
44 /// `default` frame is taken from the [`TreeizeStyle::header_frame`],
45 /// or [`TreeizeStyle::node_frame`] with removed shadow if `None`,
46 /// or constructed if both are `None`.
47 fn header_frame(
48 &mut self,
49 default: egui::Frame,
50 node: NodeId,
51 inputs: &[InPin],
52 outputs: &[OutPin],
53 treeize: &Treeize<T>,
54 ) -> egui::Frame {
55 let _ = (node, inputs, outputs, treeize);
56 default
57 }
58 /// Checks if node has a custom egui style.
59 #[inline]
60 fn has_node_style(
61 &mut self,
62 node: NodeId,
63 inputs: &[InPin],
64 outputs: &[OutPin],
65 treeize: &Treeize<T>,
66 ) -> bool {
67 let _ = (node, inputs, outputs, treeize);
68 false
69 }
70
71 /// Modifies the node's egui style
72 fn apply_node_style(
73 &mut self,
74 style: &mut Style,
75 node: NodeId,
76 inputs: &[InPin],
77 outputs: &[OutPin],
78 treeize: &Treeize<T>,
79 ) {
80 let _ = (style, node, inputs, outputs, treeize);
81 }
82
83 /// Returns elements layout for the node.
84 ///
85 /// Node consists of 4 parts: header, body, input pins and output pins.
86 /// See [`NodeLayout`] for available placements.
87 ///
88 /// Returns `default` by default.
89 /// `default` layout is taken from the [`TreeizeStyle::node_layout`] or constructed if it's `None`.
90 /// Override this method to customize the layout for specific nodes.
91 #[inline]
92 fn node_layout(
93 &mut self,
94 default: NodeLayout,
95 node: NodeId,
96 inputs: &[InPin],
97 outputs: &[OutPin],
98 treeize: &Treeize<T>,
99 ) -> NodeLayout {
100 let _ = (node, inputs, outputs, treeize);
101 default
102 }
103
104 /// Renders elements inside the node's header frame.
105 ///
106 /// This is the good place to show the node's title and controls related to the whole node.
107 ///
108 /// By default it shows the node's title.
109 #[inline]
110 fn show_header(&mut self, node: NodeId, ui: &mut Ui, treeize: &mut Treeize<T>) {
111 let _ = node;
112 ui.label(self.title(&treeize[node]));
113 }
114
115 /// Returns true if node has an input pin.
116 fn has_input(&mut self, node: &T) -> bool;
117
118 /// Returns true if node has an output pin.
119 fn has_output(&mut self, node: &T) -> bool;
120
121 /// Renders one specified node's input element and returns drawer for the corresponding pin.
122 fn show_input(
123 &mut self,
124 pin: &InPin,
125 ui: &mut Ui,
126 treeize: &mut Treeize<T>,
127 ) -> impl TreeizePin + 'static;
128
129 /// Renders the node's output.
130 fn show_output(
131 &mut self,
132 pin: &OutPin,
133 ui: &mut Ui,
134 treeize: &mut Treeize<T>,
135 ) -> impl TreeizePin + 'static;
136
137 /// Checks if node has something to show in body - between input and output pins.
138 #[inline]
139 fn has_body(&mut self, node: &T) -> bool {
140 let _ = node;
141 false
142 }
143
144 /// Renders the node's body.
145 #[inline]
146 fn show_body(&mut self, node: NodeId, ui: &mut Ui, treeize: &mut Treeize<T>) {
147 let _ = (node, ui, treeize);
148 }
149
150 /// Reports the final node's rect after rendering.
151 ///
152 /// It aimed to be used for custom positioning of nodes that requires node dimensions for calculations.
153 /// Node's position can be modified directly in this method.
154 #[inline]
155 fn final_node_rect(&mut self, node: NodeId, rect: Rect, ui: &mut Ui, treeize: &mut Treeize<T>) {
156 let _ = (node, rect, ui, treeize);
157 }
158
159 /// Checks if node has something to show in on-hover popup.
160 #[inline]
161 fn has_on_hover_popup(&mut self, node: &T) -> bool {
162 let _ = node;
163 false
164 }
165
166 /// Renders the node's on-hover popup.
167 #[inline]
168 fn show_on_hover_popup(
169 &mut self,
170 node: NodeId,
171 inputs: &[InPin],
172 outputs: &[OutPin],
173 ui: &mut Ui,
174 treeize: &mut Treeize<T>,
175 ) {
176 let _ = (node, inputs, outputs, ui, treeize);
177 }
178
179 /// Checks if wire has something to show in widget.
180 /// This may not be called if wire is invisible.
181 #[inline]
182 fn has_wire_widget(&mut self, from: &OutPinId, to: &InPinId, treeize: &Treeize<T>) -> bool {
183 let _ = (from, to, treeize);
184 false
185 }
186
187 /// Renders the wire's widget.
188 /// This may not be called if wire is invisible.
189 #[inline]
190 fn show_wire_widget(&mut self, from: &OutPin, to: &InPin, ui: &mut Ui, treeize: &mut Treeize<T>) {
191 let _ = (from, to, ui, treeize);
192 }
193
194 /// Checks if the treeize has something to show in context menu if right-clicked or long-touched on empty space at `pos`.
195 #[inline]
196 fn has_graph_menu(&mut self, pos: Pos2, treeize: &mut Treeize<T>) -> bool {
197 let _ = (pos, treeize);
198 false
199 }
200
201 /// Show context menu for the treeize.
202 ///
203 /// This can be used to implement menu for adding new nodes.
204 #[inline]
205 fn show_graph_menu(&mut self, pos: Pos2, ui: &mut Ui, treeize: &mut Treeize<T>) {
206 let _ = (pos, ui, treeize);
207 }
208
209 /// Checks if the treeize has something to show in context menu if wire drag is stopped at `pos`.
210 #[inline]
211 fn has_dropped_wire_menu(&mut self, src_pins: AnyPins, treeize: &mut Treeize<T>) -> bool {
212 let _ = (src_pins, treeize);
213 false
214 }
215
216 /// Show context menu for the treeize. This menu is opened when releasing a pin to empty
217 /// space. It can be used to implement menu for adding new node, and directly
218 /// connecting it to the released wire.
219 #[inline]
220 fn show_dropped_wire_menu(
221 &mut self,
222 pos: Pos2,
223 ui: &mut Ui,
224 src_pins: AnyPins,
225 treeize: &mut Treeize<T>,
226 ) {
227 let _ = (pos, ui, src_pins, treeize);
228 }
229
230 /// Checks if the node has something to show in context menu if right-clicked or long-touched on the node.
231 #[inline]
232 fn has_node_menu(&mut self, node: &T) -> bool {
233 let _ = node;
234 false
235 }
236
237 /// Show context menu for the treeize.
238 ///
239 /// This can be used to implement menu for adding new nodes.
240 #[inline]
241 fn show_node_menu(
242 &mut self,
243 node: NodeId,
244 inputs: &[InPin],
245 outputs: &[OutPin],
246 ui: &mut Ui,
247 treeize: &mut Treeize<T>,
248 ) {
249 let _ = (node, inputs, outputs, ui, treeize);
250 }
251
252 /// Asks the viewer to connect two pins.
253 ///
254 /// This is usually happens when user drags a wire from one node's output pin to another node's input pin or vice versa.
255 /// By default this method connects the pins and returns `Ok(())`.
256 #[inline]
257 fn connect(&mut self, from: &OutPin, to: &InPin, treeize: &mut Treeize<T>) {
258 treeize.connect(from.id, to.id);
259 }
260
261 /// Asks the viewer to disconnect two pins.
262 #[inline]
263 fn disconnect(&mut self, from: &OutPin, to: &InPin, treeize: &mut Treeize<T>) {
264 treeize.disconnect(from.id, to.id);
265 }
266
267 /// Asks the viewer to disconnect all wires from the output pin.
268 ///
269 /// This is usually happens when right-clicking on an output pin.
270 /// By default this method disconnects the pins and returns `Ok(())`.
271 #[inline]
272 fn drop_outputs(&mut self, pin: &OutPin, treeize: &mut Treeize<T>) {
273 treeize.drop_outputs(pin.id);
274 }
275
276 /// Asks the viewer to disconnect all wires from the input pin.
277 ///
278 /// This is usually happens when right-clicking on an input pin.
279 /// By default this method disconnects the pins and returns `Ok(())`.
280 #[inline]
281 fn drop_inputs(&mut self, pin: &InPin, treeize: &mut Treeize<T>) {
282 treeize.drop_inputs(pin.id);
283 }
284
285 /// Draws background of the treeize view.
286 ///
287 /// By default it draws the background pattern using [`BackgroundPattern::draw`].
288 ///
289 /// If you want to draw the background yourself, you can override this method.
290 #[inline]
291 fn draw_background(
292 &mut self,
293 background: Option<&BackgroundPattern>,
294 viewport: &Rect,
295 treeize_style: &TreeizeStyle,
296 style: &Style,
297 painter: &Painter,
298 treeize: &Treeize<T>,
299 ) {
300 let _ = treeize;
301
302 if let Some(background) = background {
303 background.draw(viewport, treeize_style, style, painter);
304 }
305 }
306
307 /// Informs the viewer what is the current transform of the treeize view
308 /// and allows viewer to override it.
309 ///
310 /// This method is called in the beginning of the graph rendering.
311 ///
312 /// By default it does nothing.
313 #[inline]
314 fn current_transform(&mut self, to_global: &mut TSTransform, treeize: &mut Treeize<T>) {
315 let _ = (to_global, treeize);
316 }
317}