Skip to content

Commit

Permalink
Refactored changes flow (#15)
Browse files Browse the repository at this point in the history
* refactored changes flow

* fixed bug with deselect

* updated version and readme
  • Loading branch information
blitzarx1 authored Apr 26, 2023
1 parent f321b4c commit 0cda36b
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 111 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "egui_graphs"
version = "0.0.19"
version = "0.0.20"
authors = ["Dmitrii Samsonov <[email protected]>"]
license = "MIT"
homepage = "https://github.com/blitzarx1/egui_graphs"
Expand Down
37 changes: 17 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,25 +75,23 @@ By using the `apply_changes` method and providing custom callback functions, we
![ezgif-4-3e4e4469e6](https://user-images.githubusercontent.com/32969427/233863786-11459176-b741-4343-8b42-7d9b3a8239ee.gif)

### Basic
#### Step 1: Setting up the ExampleApp struct.
#### Step 1: Setting up the BasicApp struct.

First, let's define the `ExampleApp` struct that will hold the graph elements and settings. The struct contains two fields: `elements` and `settings`. The elements field stores the graph's nodes and edges, while settings contains the configuration options for the GraphView widget.
First, let's define the `BasicApp` struct that will hold the graph elements and settings. The struct contains two fields: `elements` and `settings`. The elements field stores the graph's nodes and edges, while settings contains the configuration options for the GraphView widget.
```rust
pub struct ExampleApp {
pub struct BasicApp {
elements: Elements,
settings: Settings,
}
```

#### Step 2: Implementing the new() function.

Next, implement the `new()` function for the `ExampleApp` struct. This function initializes the graph settings with default values and generates the graph elements.
Next, implement the `new()` function for the `BasicApp` struct. This function initializes the graph settings with default values and generates the graph elements.
```rust
impl ExampleApp {
impl BasicApp {
fn new(_: &CreationContext<'_>) -> Self {
let settings = Settings::default();
let elements = generate_graph();
Self { settings, elements }
Self { elements }
}
}
```
Expand All @@ -104,43 +102,42 @@ Create a helper function called `generate_graph()` that initializes the nodes an
```rust
fn generate_graph() -> Elements {
let mut nodes = HashMap::new();
nodes.insert(0, Node::new(0, egui::Vec2::new(0., 30.)));
nodes.insert(1, Node::new(1,egui::Vec2::new(-30., 0.)));
nodes.insert(2, Node::new(2,egui::Vec2::new(30., 0.)));
nodes.insert(0, Node::new(0, egui::Vec2::new(0., SIDE_SIZE)));
nodes.insert(1, Node::new(1, egui::Vec2::new(-SIDE_SIZE, 0.)));
nodes.insert(2, Node::new(2, egui::Vec2::new(SIDE_SIZE, 0.)));

let mut edges = HashMap::new();
edges.insert((0, 1), vec![Edge::new(0, 1, 0)]);
edges.insert((1, 2), vec![Edge::new(1, 2, 0)]);
edges.insert((2, 0), vec![Edge::new(2, 0, 0)]);
edges.insert((2, 0), vec![Edge::new(2, 0, 0)]);

Elements::new(nodes, edges)
}
```

#### Step 4: Implementing the update() function.

Now, implement the `update()` function for the `ExampleApp`. This function creates a `GraphView` widget with the `elements` and `settings`, and adds it to the central panel using the `ui.add()` function.
Now, implement the `update()` function for the `BasicApp`. This function creates a `GraphView` widget with the `elements`, and adds it to the central panel using the `ui.add()` function.
```rust
impl App for ExampleApp {
impl App for BasicApp {
fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) {
let widget = &GraphView::new(&self.elements, &self.settings);
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(widget);
ui.add(GraphView::new(&self.elements));
});
}
}
```

#### Step 5: Running the application.

Finally, run the application using the `run_native()` function with the specified native options and the `ExampleApp`.
Finally, run the application using the `run_native()` function with the specified native options and the `BasicApp`.
```rust
fn main() {
let native_options = eframe::NativeOptions::default();
run_native(
"egui_graphs_basic_demo",
native_options,
Box::new(|cc| Box::new(ExampleApp::new(cc))),
Box::new(|cc| Box::new(BasicApp::new(cc))),
)
.unwrap();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/basic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "basic"
version = "0.0.19"
version = "0.0.20"
authors = ["Dmitrii Samsonov <[email protected]>"]
license = "MIT"
edition = "2021"
Expand Down
9 changes: 3 additions & 6 deletions examples/basic/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,25 @@ use std::collections::HashMap;

use eframe::{run_native, App, CreationContext};
use egui::Context;
use egui_graphs::{Edge, Elements, GraphView, Node, Settings};
use egui_graphs::{Edge, Elements, GraphView, Node};

const SIDE_SIZE: f32 = 50.;

pub struct BasicApp {
elements: Elements,
settings: Settings,
}

impl BasicApp {
fn new(_: &CreationContext<'_>) -> Self {
let settings = Settings::default();
let elements = generate_graph();
Self { settings, elements }
Self { elements }
}
}

impl App for BasicApp {
fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) {
let widget = &GraphView::new(&self.elements, &self.settings);
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(widget);
ui.add(GraphView::new(&self.elements));
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/interactive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "interactive"
version = "0.0.19"
version = "0.0.20"
authors = ["Dmitrii Samsonov <[email protected]>"]
license = "MIT"
edition = "2021"
Expand Down
48 changes: 28 additions & 20 deletions examples/interactive/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::sync::mpsc::{Receiver, Sender};
use std::{collections::HashMap, time::Instant};

use eframe::{run_native, App, CreationContext};
use egui::plot::{Line, Plot, PlotPoints};
use egui::{CollapsingHeader, Color32, Context, ScrollArea, Vec2};
use egui_graphs::{Changes, Edge, Elements, GraphView, Node, Settings};
use egui_graphs::{Changes, Edge, Elements, GraphView, InteractionsSettings, Node};
use fdg_sim::glam::Vec3;
use fdg_sim::{ForceGraph, ForceGraphHelper, Simulation, SimulationParameters};
use petgraph::stable_graph::NodeIndex;
Expand All @@ -19,7 +20,7 @@ const FPS_LINE_COLOR: Color32 = Color32::from_rgb(255, 255, 255);
pub struct InteractiveApp {
simulation: Simulation<usize, String>,
elements: Elements,
settings: Settings,
interaction_settings: InteractionsSettings,

selected_nodes: Vec<Node>,
selected_edges: Vec<Edge>,
Expand All @@ -30,16 +31,23 @@ pub struct InteractiveApp {
fps_history: Vec<f64>,
last_update_time: Instant,
frames_last_time_span: usize,

changes_receiver: Receiver<Changes>,
changes_sender: Sender<Changes>,
}

impl InteractiveApp {
fn new(_: &CreationContext<'_>) -> Self {
let settings = Settings::default();
let settings = InteractionsSettings::default();
let (simulation, elements) = construct_simulation(NODE_COUNT, EDGE_COUNT);
let (changes_sender, changes_receiver) = std::sync::mpsc::channel();
Self {
simulation,
elements,
settings,
interaction_settings: settings,

changes_receiver,
changes_sender,

selected_nodes: Default::default(),
selected_edges: Default::default(),
Expand Down Expand Up @@ -162,18 +170,18 @@ impl App for InteractiveApp {
ui.separator();

if ui
.checkbox(&mut self.settings.fit_to_screen, "autofit")
.checkbox(&mut self.interaction_settings.fit_to_screen, "autofit")
.changed()
&& self.settings.fit_to_screen
&& self.interaction_settings.fit_to_screen
{
self.settings.zoom_and_pan = false
self.interaction_settings.zoom_and_pan = false
};
ui.label("Enable autofit to fit the graph to the screen on every frame.");

ui.add_space(5.);

ui.add_enabled_ui(!self.settings.fit_to_screen, |ui| {
ui.checkbox(&mut self.settings.zoom_and_pan, "pan & zoom")
ui.add_enabled_ui(!self.interaction_settings.fit_to_screen, |ui| {
ui.checkbox(&mut self.interaction_settings.zoom_and_pan, "pan & zoom")
.on_disabled_hover_text("disabled autofit to enable pan & zoom");
ui.label("Enable pan and zoom. To pan use LMB + drag and to zoom use Ctrl + Mouse Wheel.");
});
Expand All @@ -183,18 +191,18 @@ impl App for InteractiveApp {
ui.label("Interactions");
ui.separator();

ui.checkbox(&mut self.settings.node_drag, "drag");
ui.checkbox(&mut self.interaction_settings.node_drag, "drag");
ui.label("Enable drag. To drag use LMB + drag on a node.");

ui.add_space(5.);

ui.checkbox(&mut self.settings.node_select, "select");
ui.checkbox(&mut self.interaction_settings.node_select, "select");
ui.label("Enable select to select nodes with LMB click. If node is selected clicking on it again will deselect it.");

ui.add_space(5.);

ui.add_enabled_ui(self.settings.node_select, |ui| {
ui.checkbox(&mut self.settings.node_multiselect, "multiselect")
ui.add_enabled_ui(self.interaction_settings.node_select, |ui| {
ui.checkbox(&mut self.interaction_settings.node_multiselect, "multiselect")
.on_disabled_hover_text("enable select to enable multiselect");
ui.label("Enable multiselect to select multiple nodes.");
});
Expand Down Expand Up @@ -266,16 +274,16 @@ impl App for InteractiveApp {
});
});
});
let widget = &GraphView::new(&self.elements, &self.settings);
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(widget);
ui.add(
GraphView::new(&self.elements)
.interactive(&self.interaction_settings, &self.changes_sender),
);
});

apply_changes(
&widget.last_changes(),
&mut self.simulation,
&mut self.elements,
);
self.changes_receiver.try_iter().for_each(|changes| {
apply_changes(&changes, &mut self.simulation, &mut self.elements);
});
}
}

Expand Down
Loading

0 comments on commit 0cda36b

Please sign in to comment.