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}