aboutsummaryrefslogtreecommitdiff
path: root/src/ui/graph.rs
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2024-01-21 17:02:00 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2024-01-21 17:02:00 +0100
commitb9b32972afda261020dd207b4ea2b44b7b697b83 (patch)
treedba426aabaa569952e2aa0dda0f5e1e836bae55f /src/ui/graph.rs
parent53a48a778af34bd25963881539e6f66f47dc5580 (diff)
add multiple functions to canvas
Diffstat (limited to 'src/ui/graph.rs')
-rw-r--r--src/ui/graph.rs74
1 files changed, 47 insertions, 27 deletions
diff --git a/src/ui/graph.rs b/src/ui/graph.rs
index 63e1c43..83d90f8 100644
--- a/src/ui/graph.rs
+++ b/src/ui/graph.rs
@@ -16,17 +16,16 @@ use crate::{
#[derive(Default)]
pub struct GraphCanvas {
graph: Cache,
- pub func: Mutex<FunctionCache>,
- pub ctx: Context,
+ funcs: Mutex<Vec<Option<FunctionCache>>>,
+ ctx: Context,
}
impl GraphCanvas {
- pub fn new(fstr: &String) -> Self {
+ pub fn new() -> Self {
let ctx = Context::commonsense();
- let func = ExpressionFunction::from_string(fstr.clone(), ctx.operations());
Self {
graph: Cache::default(),
- func: Mutex::new(FunctionCache::new(func)),
+ funcs: Mutex::new(Vec::new()),
ctx,
}
}
@@ -34,6 +33,26 @@ impl GraphCanvas {
pub fn clear(&self) {
self.graph.clear();
}
+
+ pub fn push(&mut self, f: &str) {
+ if let Ok(f) = ExpressionFunction::from_string(f.to_string(), self.ctx.operations()) {
+ self.funcs.lock().unwrap().push(Some(FunctionCache::new(f)));
+ } else {
+ self.funcs.lock().unwrap().push(None);
+ }
+ }
+
+ pub fn set(&mut self, i: usize, f: &str) {
+ if let Ok(f) = ExpressionFunction::from_string(f.to_string(), self.ctx.operations()) {
+ self.funcs.lock().unwrap()[i] = Some(FunctionCache::new(f));
+ } else {
+ self.funcs.lock().unwrap().push(None);
+ }
+ }
+
+ pub fn remove(&mut self, i: usize) {
+ self.funcs.lock().unwrap().remove(i);
+ }
}
#[derive(Copy, Clone)]
@@ -190,28 +209,29 @@ impl canvas::Program<Message, Renderer> for GraphCanvas {
});
let step = (step / 10).max(1);
- let mut y1 = self
- .func
+
+ for func in self
+ .funcs
.lock()
.unwrap()
- .eval(Complex::new(rect.x as f64, 0.0), &self.ctx)
- .real as f32;
- for x in (rect.x as i64..(rect.x + rect.width) as i64).step_by(step) {
- for d in 0..10 {
- let d = d as f32 / 10.0;
- let x1 = x as f32 + d * step as f32;
- let x2 = x as f32 + (d + 0.1) * step as f32;
- let y2 = self
- .func
- .lock()
- .unwrap()
- .eval(Complex::new(x2 as f64, 0.0), &self.ctx)
- .real as f32;
- if y1.is_finite() && !y1.is_nan() && y2.is_finite() && !y2.is_nan() {
- let line = Path::line(state.map_coords(x1, y1), state.map_coords(x2, y2));
- frame.stroke(&line, graphline.clone())
+ .iter_mut()
+ .filter(|f| f.is_some())
+ .map(|f| f.as_mut().unwrap())
+ {
+ let mut y1 = func.eval(Complex::new(rect.x as f64, 0.0), &self.ctx).real as f32;
+ for x in (rect.x as i64..(rect.x + rect.width) as i64).step_by(step) {
+ for d in 0..10 {
+ let d = d as f32 / 10.0;
+ let x1 = x as f32 + d * step as f32;
+ let x2 = x as f32 + (d + 0.1) * step as f32;
+ let y2 = func.eval(Complex::new(x2 as f64, 0.0), &self.ctx).real as f32;
+ if y1.is_finite() && !y1.is_nan() && y2.is_finite() && !y2.is_nan() {
+ let line =
+ Path::line(state.map_coords(x1, y1), state.map_coords(x2, y2));
+ frame.stroke(&line, graphline.clone())
+ }
+ y1 = y2;
}
- y1 = y2;
}
}
});
@@ -232,7 +252,7 @@ impl canvas::Program<Message, Renderer> for GraphCanvas {
if let canvas::Event::Mouse(mouse::Event::ButtonPressed(_)) = event {
state.interaction = Interaction::Grabbing;
state.last_position = cursor.position();
- return (event::Status::Captured, Some(Message::UpdateScreen));
+ return (event::Status::Captured, Some(Message::RefreshGraphCanvas));
}
if let canvas::Event::Mouse(mouse::Event::CursorMoved { position }) = event {
@@ -242,7 +262,7 @@ impl canvas::Program<Message, Renderer> for GraphCanvas {
state.center.y += position.y - lp.y;
}
state.last_position = Some(position);
- return (event::Status::Captured, Some(Message::UpdateScreen));
+ return (event::Status::Captured, Some(Message::RefreshGraphCanvas));
}
}
@@ -259,7 +279,7 @@ impl canvas::Program<Message, Renderer> for GraphCanvas {
state.scale *= 1.1;
}
state.scale = state.scale.max(0.000001);
- return (event::Status::Captured, Some(Message::UpdateScreen));
+ return (event::Status::Captured, Some(Message::RefreshGraphCanvas));
}
_ => {}
}