Skip to content

Commit 7c71ae3

Browse files
authored
pan with lmb and flex example (#200)
* pan with lmb * flex size nodes example for #196
1 parent 4384939 commit 7c71ae3

File tree

9 files changed

+309
-27
lines changed

9 files changed

+309
-27
lines changed

Cargo.lock

Lines changed: 20 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "egui_graphs"
3-
version = "0.21.0"
3+
version = "0.21.1"
44
authors = ["Dmitrii Samsonov <blitzarx1@gmail.com>"]
55
license = "MIT"
66
homepage = "https://github.com/blitzarx1/egui_graphs"

examples/custom_draw/src/node.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl IsClockwise for NodeData {
2121
}
2222
}
2323

24-
/// Rotates node whent the node is being dragged.
24+
/// Rotates node when the node is being dragged.
2525
#[derive(Clone)]
2626
pub struct NodeShapeAnimated {
2727
label: String,
@@ -152,9 +152,8 @@ impl<N: Clone + IsClockwise, E: Clone, Ty: EdgeType, Ix: IndexType> DisplayNode<
152152
}
153153

154154
fn find_intersection(center: Pos2, size: f32, direction: Vec2) -> Pos2 {
155-
// Determine the intersection side based on the direction
156155
if direction.x.abs() > direction.y.abs() {
157-
// Intersects left or right side
156+
// intersects left or right side
158157
let x = if direction.x > 0.0 {
159158
center.x + size / 2.0
160159
} else {
@@ -163,7 +162,7 @@ fn find_intersection(center: Pos2, size: f32, direction: Vec2) -> Pos2 {
163162
let y = center.y + direction.y / direction.x * (x - center.x);
164163
Pos2::new(x, y)
165164
} else {
166-
// Intersects top or bottom side
165+
// intersects top or bottom side
167166
let y = if direction.y > 0.0 {
168167
center.y + size / 2.0
169168
} else {
@@ -179,22 +178,22 @@ fn rotate_point_around(center: Pos2, point: Pos2, angle: f32) -> Pos2 {
179178
let sin_angle = angle.sin();
180179
let cos_angle = angle.cos();
181180

182-
// Translate point back to origin
181+
// translate point back to origin
183182
let translated_point = point - center;
184183

185-
// Rotate point
184+
// rotate point
186185
let rotated_x = translated_point.x * cos_angle - translated_point.y * sin_angle;
187186
let rotated_y = translated_point.x * sin_angle + translated_point.y * cos_angle;
188187

189-
// Translate point back
188+
// translate point back
190189
Pos2::new(rotated_x, rotated_y) + center.to_vec2()
191190
}
192191

193192
fn rect_to_points(rect: Rect) -> Vec<Pos2> {
194193
let top_left = rect.min;
195194
let bottom_right = rect.max;
196195

197-
// Calculate the other two corners
196+
// calculate the other two corners
198197
let top_right = Pos2::new(bottom_right.x, top_left.y);
199198
let bottom_left = Pos2::new(top_left.x, bottom_right.y);
200199

@@ -216,7 +215,7 @@ mod tests {
216215
fn test_intersection_right_side() {
217216
let center = Pos2::new(0.0, 0.0);
218217
let size = 10.;
219-
let direction = Vec2::new(1.0, 0.0); // Directly to the right
218+
let direction = Vec2::new(1.0, 0.0);
220219
let expected = Pos2::new(5.0, 0.0);
221220
assert_eq!(find_intersection(center, size, direction), expected);
222221
}
@@ -225,7 +224,7 @@ mod tests {
225224
fn test_intersection_top_side() {
226225
let center = Pos2::new(0.0, 0.0);
227226
let size = 10.;
228-
let direction = Vec2::new(0.0, 1.0); // Directly upwards
227+
let direction = Vec2::new(0.0, 1.0);
229228
let expected = Pos2::new(0.0, 5.0);
230229
assert_eq!(find_intersection(center, size, direction), expected);
231230
}

examples/flex_nodes/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "flex_nodes"
3+
version = "0.1.0"
4+
authors = ["Dmitrii Samsonov <blitzarx1@gmail.com>"]
5+
license = "MIT"
6+
edition = "2021"
7+
8+
[dependencies]
9+
egui_graphs = { path = "../../" }
10+
egui = "0.28"
11+
eframe = "0.28"
12+
petgraph = "0.6"

examples/flex_nodes/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Flex nodes
2+
Example demonstrates how to use custom drawing functions for nodes with flexible size which depends on their label size.
3+
4+
## run
5+
```bash
6+
cargo run --release -p flex_nodes
7+
```

examples/flex_nodes/src/main.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use eframe::{run_native, App, CreationContext};
2+
use egui::{CentralPanel, Context, SidePanel, TextEdit};
3+
use egui_graphs::{
4+
DefaultEdgeShape, Graph, GraphView, SettingsInteraction, SettingsNavigation, SettingsStyle,
5+
};
6+
use node::NodeShapeFlex;
7+
use petgraph::{
8+
stable_graph::{DefaultIx, EdgeIndex, NodeIndex, StableGraph},
9+
Directed,
10+
};
11+
12+
mod node;
13+
14+
pub struct FlexNodesApp {
15+
g: Graph<(), (), Directed, DefaultIx, NodeShapeFlex, DefaultEdgeShape>,
16+
label_input: String,
17+
selected_node: Option<NodeIndex>,
18+
selected_edge: Option<EdgeIndex>,
19+
}
20+
21+
impl FlexNodesApp {
22+
fn new(_: &CreationContext<'_>) -> Self {
23+
let g = generate_graph();
24+
Self {
25+
g: Graph::from(&g),
26+
label_input: String::default(),
27+
selected_node: Option::default(),
28+
selected_edge: Option::default(),
29+
}
30+
}
31+
32+
fn read_data(&mut self) {
33+
if !self.g.selected_nodes().is_empty() {
34+
let idx = self.g.selected_nodes().first().unwrap();
35+
self.selected_node = Some(*idx);
36+
self.selected_edge = None;
37+
self.label_input = self.g.node(*idx).unwrap().label();
38+
}
39+
if !self.g.selected_edges().is_empty() {
40+
let idx = self.g.selected_edges().first().unwrap();
41+
self.selected_edge = Some(*idx);
42+
self.selected_node = None;
43+
self.label_input = self.g.edge(*idx).unwrap().label();
44+
}
45+
}
46+
47+
fn render(&mut self, ctx: &Context) {
48+
SidePanel::right("right_panel").show(ctx, |ui| {
49+
ui.label("Change Label");
50+
ui.add_enabled_ui(
51+
self.selected_node.is_some() || self.selected_edge.is_some(),
52+
|ui| {
53+
TextEdit::singleline(&mut self.label_input)
54+
.hint_text("select node or edge")
55+
.show(ui)
56+
},
57+
);
58+
if ui.button("reset").clicked() {
59+
self.reset()
60+
}
61+
});
62+
CentralPanel::default().show(ctx, |ui| {
63+
let widget =
64+
&mut GraphView::<_, _, _, _, NodeShapeFlex, DefaultEdgeShape>::new(&mut self.g)
65+
.with_interactions(
66+
&SettingsInteraction::default()
67+
.with_dragging_enabled(true)
68+
.with_node_selection_enabled(true)
69+
.with_edge_selection_enabled(true),
70+
)
71+
.with_navigations(
72+
&SettingsNavigation::default()
73+
.with_fit_to_screen_enabled(false)
74+
.with_zoom_and_pan_enabled(true),
75+
);
76+
ui.add(widget);
77+
});
78+
}
79+
80+
fn update_data(&mut self) {
81+
if self.selected_node.is_none() && self.selected_edge.is_none() {
82+
return;
83+
}
84+
85+
if self.selected_node.is_some() {
86+
let idx = self.selected_node.unwrap();
87+
if idx.index().to_string() == self.label_input {
88+
return;
89+
}
90+
91+
self.g
92+
.node_mut(idx)
93+
.unwrap()
94+
.set_label(self.label_input.clone());
95+
}
96+
97+
if self.selected_edge.is_some() {
98+
let idx = self.selected_edge.unwrap();
99+
if idx.index().to_string() == self.label_input {
100+
return;
101+
}
102+
103+
self.g
104+
.edge_mut(idx)
105+
.unwrap()
106+
.set_label(self.label_input.clone());
107+
}
108+
}
109+
110+
fn reset(&mut self) {
111+
let g = generate_graph();
112+
*self = Self {
113+
g: Graph::from(&g),
114+
label_input: String::default(),
115+
selected_node: Option::default(),
116+
selected_edge: Option::default(),
117+
};
118+
}
119+
}
120+
121+
impl App for FlexNodesApp {
122+
fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) {
123+
self.read_data();
124+
self.render(ctx);
125+
self.update_data();
126+
}
127+
}
128+
129+
fn generate_graph() -> StableGraph<(), ()> {
130+
let mut g = StableGraph::new();
131+
132+
let a = g.add_node(());
133+
let b = g.add_node(());
134+
let c = g.add_node(());
135+
136+
g.add_edge(a, b, ());
137+
g.add_edge(b, c, ());
138+
g.add_edge(c, a, ());
139+
140+
g
141+
}
142+
143+
fn main() {
144+
let native_options = eframe::NativeOptions::default();
145+
run_native(
146+
"egui_graphs_flex_nodes_demo",
147+
native_options,
148+
Box::new(|cc| Ok(Box::new(FlexNodesApp::new(cc)))),
149+
)
150+
.unwrap();
151+
}

0 commit comments

Comments
 (0)