diff --git a/src/graph.rs b/src/graph.rs index 0a32253..3bb77fb 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -5,18 +5,6 @@ use std::rc::Rc; use std::cell::RefCell; use std::collections::HashMap; -pub struct Graph { - pub area: DrawingArea, - pub scale_x_start: f64, - pub scale_x_size: f64, - pub scale_y_start: f64, - pub scale_y_size: f64, - pub draw_patch: bool, - pub auto_adjust_y: bool, - pub lines: HashMap, - pub pankti_sankya: f64 -} - pub struct Line { pub points: Vec<(f64,f64)>, pub color: (f64, f64, f64) @@ -30,14 +18,45 @@ impl Line { } } } +pub struct Graph { + pub area: DrawingArea, + pub scale_x_start: f64, + pub scale_x_size: f64, + pub scale_y_start: f64, + pub scale_y_size: f64, + pub draw_patch: bool, + pub draw_baarik_box: bool, + pub draw_box: bool, + pub auto_adjust_y: bool, + pub lines: HashMap, + pub pankti_sankya: f64 +} impl Graph { + fn draw_boxes(ctx: &cairo::Context, area_width: f64, area_height: f64, src_x: f64, src_y: f64, cell_size: f64, color: f64) { + ctx.set_source_rgb(color, color, color); + ctx.set_line_width(1.0); + for x in 1..math::round::ceil(area_width/cell_size, 0) as i32 { + let xi = x as f64 * cell_size + src_x; + ctx.move_to(xi, 0.0); + ctx.line_to(xi, area_height - src_y); + } + for y in 1..math::round::ceil(area_height/cell_size, 0) as i32 { + let yi = area_height - y as f64 * cell_size - src_y; + ctx.move_to(src_x, yi); + ctx.line_to(area_width, yi); + } + ctx.stroke(); + } + pub fn new(area: DrawingArea, scale_x_start: f64, scale_x_size: f64, scale_y_start: f64, scale_y_size: f64, draw_patch: bool, + draw_baarik_box: bool, + draw_box: bool, auto_adjust_y: bool, lines: HashMap, pankti_sankya: f64) -> Rc> { @@ -49,6 +68,8 @@ impl Graph { scale_y_start, scale_y_size, draw_patch, + draw_baarik_box: draw_baarik_box, + draw_box, auto_adjust_y, lines, pankti_sankya @@ -67,33 +88,34 @@ impl Graph { ctx: &cairo::Context, graph: &Rc>) { + let graph = graph.borrow(); + ctx.set_source_rgb(0.1, 0.5, 0.5); ctx.paint(); let width = area.get_allocated_width() as f64; let height = area.get_allocated_height() as f64; - if graph.borrow().auto_adjust_y { - graph.borrow_mut().adjust_scale_automatic_y(); + if graph.draw_box { + if graph.draw_baarik_box { + Graph::draw_boxes(ctx, width, height, 40.0, 20.0, 5.0, 0.3); + } + + Graph::draw_boxes(ctx, width, height, 40.0, 20.0, 50.0, 0.1); } - graph.borrow_mut().adjust_scale_automatic_x(); - graph.borrow_mut().trim_lines(); - - Graph::draw_boxes(ctx, width, height, 40.0, 20.0, 5.0, 0.3); - Graph::draw_boxes(ctx, width, height, 40.0, 20.0, 50.0, 0.1); let cell_size = 50.0; - + let v_bars = math::round::ceil(width/cell_size, 0) as i32; let h_bars= math::round::ceil(height/cell_size, 0) as i32; - let h_scale = (graph.borrow().scale_x_size)/(v_bars - 1) as f64; // ms - let v_scale = (graph.borrow().scale_y_size)/(h_bars - 1) as f64; // ms + let h_scale = (graph.scale_x_size)/(v_bars - 1) as f64; // ms + let v_scale = (graph.scale_y_size)/(h_bars - 1) as f64; // ms ctx.set_line_width(2.0); ctx.set_line_cap(cairo::LineCap::Round); - let draw_patch = graph.borrow().draw_patch; - for (_,line) in graph.borrow().lines.iter() { + let draw_patch = graph.draw_patch; + for (_,line) in graph.lines.iter() { for p in line.points.iter().enumerate() { let xp = if p.0 < line.points.len() - 1 { line.points[p.0 + 1] @@ -101,13 +123,13 @@ impl Graph { line.points[p.0] }; ctx.set_source_rgb(line.color.0, line.color.1, line.color.2); - ctx.move_to(((cell_size as f64)*(xp.0 - graph.borrow().scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(xp.1 - graph.borrow().scale_y_start))/v_scale - 20.0); - ctx.line_to(((cell_size as f64)*(p.1.0 - graph.borrow().scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(p.1.1 - graph.borrow().scale_y_start))/v_scale - 20.0); + ctx.move_to(((cell_size as f64)*(xp.0 - graph.scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(xp.1 - graph.scale_y_start))/v_scale - 20.0); + ctx.line_to(((cell_size as f64)*(p.1.0 - graph.scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(p.1.1 - graph.scale_y_start))/v_scale - 20.0); ctx.stroke(); if draw_patch { ctx.set_source_rgb(0.0, 0.0, 1.0); - ctx.arc(((cell_size as f64)*(p.1.0 - graph.borrow().scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(p.1.1 - graph.borrow().scale_y_start))/v_scale - 20.0, 5.0, 0.0, std::f64::consts::PI * 2.0); + ctx.arc(((cell_size as f64)*(p.1.0 - graph.scale_x_start))/h_scale + 40.0, height - ((cell_size as f64)*(p.1.1 - graph.scale_y_start))/v_scale - 20.0, 5.0, 0.0, std::f64::consts::PI * 2.0); ctx.stroke(); } } @@ -120,116 +142,95 @@ impl Graph { ctx.set_source_rgb(1.0, 1.0, 1.0); for x in 0..v_bars { - let text = math::round::floor(x as f64 * h_scale + graph.borrow().scale_x_start, 1).to_string(); + let text = math::round::floor(x as f64 * h_scale + graph.scale_x_start, 1).to_string(); let f = ctx.text_extents(&text); ctx.move_to(40.0 + x as f64 * cell_size - f.width, height - 10.0); ctx.show_text(&text); } for y in (0..h_bars).rev() { - let text = math::round::floor(y as f64 * v_scale + graph.borrow().scale_y_start, 1).to_string(); + let text = math::round::floor(y as f64 * v_scale + graph.scale_y_start, 1).to_string(); let f = ctx.text_extents(&text); ctx.move_to(40.0 - f.width, height - y as f64 * cell_size - f.height - 15.0); ctx.show_text(&text); } } - fn draw_boxes(ctx: &cairo::Context, area_width: f64, area_height: f64, src_x: f64, src_y: f64, cell_size: f64, color: f64) { - ctx.set_source_rgb(color, color, color); - ctx.set_line_width(1.0); - for x in 1..math::round::ceil(area_width/cell_size, 0) as i32 { - let xi = x as f64 * cell_size + src_x; - ctx.move_to(xi, 0.0); - ctx.line_to(xi, area_height - src_y); - } - for y in 1..math::round::ceil(area_height/cell_size, 0) as i32 { - let yi = area_height - y as f64 * cell_size - src_y; - ctx.move_to(src_x, yi); - ctx.line_to(area_width, yi); - } - ctx.stroke(); - } + pub fn redraw(&mut self) { + let (mx_x, mi_x, mx_y, mi_y) = self.get_extremes(); - pub fn adjust_scale_automatic_y(&mut self) { - if self.lines.len() == 0 { - return; - } - - let mut mx:Option = None; - let mut mi:Option = None; - - for (_, line) in self.lines.iter() { - if line.points.len() == 0 { - mx = Some(0.0); - mi = Some(0.0); - continue; - } - - if let None = mx { - mx = Some(line.points[0].1); - } - - if let None = mi { - mi = Some(line.points[0].1); - } - - for (_,y) in line.points.iter().skip(1) { - mx = Some(f64::max(mx.unwrap(), *y)); - mi = Some(f64::min(mi.unwrap(), *y)); - } - } - - let mx = mx.unwrap(); - let mi = mi.unwrap(); - - let spread = (mx - mi).abs(); + // stambh + if self.auto_adjust_y { + let spread = (mx_y - mi_y).abs(); - self.scale_y_start = mi - spread * 0.1; - self.scale_y_size = spread * 1.2; - } - - pub fn adjust_scale_automatic_x(&mut self) { - if self.lines.len() == 0 { - return; + self.scale_y_start = mi_y - spread * 0.1; + self.scale_y_size = spread * 1.2; } - - let mut mx:Option = None; - let mut mi:Option = None; - for (_, line) in self.lines.iter() { - if line.points.len() == 0 { - mx = Some(0.0); - mi = Some(0.0); - continue; - } - - if let None = mx { - mx = Some(line.points[0].0); - } - - if let None = mi { - mi = Some(line.points[0].0); - } - - for (x,_) in line.points.iter().skip(1) { - mx = Some(f64::max(mx.unwrap(), *x)); - mi = Some(f64::min(mi.unwrap(), *x)); - } - } - - let spread = (mx.unwrap() - mi.unwrap()).abs(); + // pankti + let spread = (mx_x - mi_x).abs(); if spread < self.scale_x_size { - self.scale_x_start = mi.unwrap(); + self.scale_x_start = mi_x; } else { - self.scale_x_start = mx.unwrap() - self.scale_x_size; + self.scale_x_start = mx_x - self.scale_x_size; } + + self.trim_lines(); + self.area.queue_draw(); + } + + pub fn get_extremes(&self) -> (f64, f64, f64, f64){ + if self.lines.len() == 0 { + return (0.0,0.0,0.0,0.0); + } + + let mut mx_x:Option = None; + let mut mi_x:Option = None; + let mut mx_y:Option = None; + let mut mi_y:Option = None; + + for (_, line) in self.lines.iter() { + if line.points.len() == 0 { + mx_x = Some(0.0); + mi_x = Some(0.0); + mx_y = Some(0.0); + mi_y = Some(0.0); + continue; + } + + if let None = mx_x { + mx_x = Some(line.points[0].0); + } + + if let None = mi_x { + mi_x = Some(line.points[0].0); + } + + if let None = mx_y { + mx_y = Some(line.points[0].1); + } + + if let None = mi_y { + mi_y = Some(line.points[0].1); + } + + for (x,y) in line.points.iter().skip(1) { + mx_x = Some(f64::max(mx_x.unwrap(), *x)); + mi_x = Some(f64::min(mi_x.unwrap(), *x)); + mx_y = Some(f64::max(mx_y.unwrap(), *y)); + mi_y = Some(f64::min(mi_y.unwrap(), *y)); + } + } + + (mx_x.unwrap(), mi_x.unwrap(), mx_y.unwrap(), mi_y.unwrap()) } pub fn trim_lines(&mut self) { for (_, line) in self.lines.iter_mut() { let mut i = 0; while i < line.points.len() { + match line.points.get(i + 2) { Some(_) => { if line.points[i+1].0 < self.scale_x_start { diff --git a/src/lib.rs b/src/lib.rs index 9eac61b..0800d70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use rand::Rng; use std::{collections::HashMap, sync::{Arc, Mutex}}; use std::rc::Rc; +use std::cell::RefCell; use std::io::prelude::*; use std::io::BufReader; @@ -48,7 +49,9 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { builder.get_object::("draw_area").expect("Resource file missing!"), 0.0, 100.0, 0.0, 100.0, - true, + false, + false, + false, true, HashMap::new(), 0.0 @@ -74,15 +77,21 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { }); // save_log + // let save_log = builder.get_object::("save_log").expect("Resource file missing!"); + // let tmp_log_area = log_area.clone(); + // save_log.connect_activate(move |_|{ + + // }); // pankti let pankti = builder.get_object::("pankti").expect("Resource file missing!"); let tmp_graph = Rc::clone(&graph); pankti.connect_value_changed(move |btn| { - tmp_graph.borrow_mut().scale_x_size = btn.get_value(); - tmp_graph.borrow().area.queue_draw(); + let mut tmp_graph = tmp_graph.borrow_mut(); + tmp_graph.scale_x_size = btn.get_value(); + tmp_graph.redraw(); }); // stambh_1 @@ -90,12 +99,13 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { let tmp_graph = Rc::clone(&graph); stambh_1.connect_changed(move |entry| { + let mut tmp_graph = tmp_graph.borrow_mut(); let val = entry.get_text().parse::().unwrap_or(0.0); - let purana_y_start = tmp_graph.borrow().scale_y_start; - let y_size = tmp_graph.borrow().scale_y_size; - tmp_graph.borrow_mut().scale_y_start = val; - tmp_graph.borrow_mut().scale_y_size = y_size + (purana_y_start - val); - tmp_graph.borrow().area.queue_draw(); + let purana_y_start = tmp_graph.scale_y_start; + let y_size = tmp_graph.scale_y_size; + tmp_graph.scale_y_start = val; + tmp_graph.scale_y_size = y_size + (purana_y_start - val); + tmp_graph.redraw(); }); // stambh_2 @@ -103,10 +113,11 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { let tmp_graph = Rc::clone(&graph); stambh_2.connect_changed(move |entry| { + let mut tmp_graph = tmp_graph.borrow_mut(); let val = entry.get_text().parse::().unwrap_or(0.0); - let y_start = tmp_graph.borrow().scale_y_start; - tmp_graph.borrow_mut().scale_y_size = (val - y_start).abs(); - tmp_graph.borrow().area.queue_draw(); + let y_start = tmp_graph.scale_y_start; + tmp_graph.scale_y_size = (val - y_start).abs(); + tmp_graph.redraw(); }); // nimna_stambh @@ -124,8 +135,29 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { let tmp_graph = Rc::clone(&graph); draw_patches.connect_clicked(move |btn| { - tmp_graph.borrow_mut().draw_patch = btn.get_active(); - tmp_graph.borrow().area.queue_draw(); + let mut tmp_graph = tmp_graph.borrow_mut(); + tmp_graph.draw_patch = btn.get_active(); + tmp_graph.redraw(); + }); + + // draw_baarik_box + let draw_baarik_box = builder.get_object::("draw_baarik_box").expect("Resource file missing!"); + + let tmp_graph = Rc::clone(&graph); + draw_baarik_box.connect_clicked(move |btn| { + let mut tmp_graph = tmp_graph.borrow_mut(); + tmp_graph.draw_baarik_box = btn.get_active(); + tmp_graph.redraw(); + }); + + // draw_box + let draw_box = builder.get_object::("draw_box").expect("Resource file missing!"); + + let tmp_graph = Rc::clone(&graph); + draw_box.connect_clicked(move |btn| { + let mut tmp_graph = tmp_graph.borrow_mut(); + tmp_graph.draw_box = btn.get_active(); + tmp_graph.redraw(); }); // Bondrate @@ -188,7 +220,7 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { clear_graph.connect_clicked(move |_ | { tmp_graph.borrow_mut().pankti_sankya = 0.0; tmp_graph.borrow_mut().lines.clear(); - tmp_graph.borrow().area.queue_draw(); + tmp_graph.borrow_mut().redraw(); }); // jagrit_btn @@ -202,7 +234,7 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { Ok(mut config) => { tmp_graph.borrow_mut().pankti_sankya = 0.0; tmp_graph.borrow_mut().lines.clear(); - tmp_graph.borrow().area.queue_draw(); + tmp_graph.borrow_mut().redraw(); tmp_bar.push(1, "Jagrit"); config.status = Status::PARIVARTIT; }, Err(_) => { @@ -261,41 +293,7 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { let mut bufread: Option>> = None; let mut buf = String::new(); loop { - match tmp_config.lock() { - Ok(mut config) => { - match config.status { - Status::AVRODTIH => { - bufread = None; - config.status = Status::SAYAN; - }, - Status::JAGRIT => { - if let Some(read) = &mut bufread { - if let Ok(_) = read.read_line(&mut buf) { - sender.send(Message::Msg(buf.clone())).unwrap(); - buf.clear(); - } - } - }, - Status::NIKAS => {}, - Status::PARIVARTIT => { - let p = match serialport::new(&config.port, config.bondrate).open() { - Ok(p) => p, - Err(_) => { - continue; - } - }; - - bufread = Some(BufReader::new(p)); - config.status = Status::JAGRIT; - }, - Status::SAYAN => {} - } - - }, Err(_) => { - sender.send(Message::Status("Faild prepare for communication!".to_owned())).unwrap(); - return; - } - }; + serial_thread_work(&tmp_config, &mut bufread, &sender, &mut buf); } }); @@ -304,68 +302,7 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { receiver.attach(None, move |msg| { match msg { Message::Msg(text) => { - if text.starts_with("#") { - tmp_graph.borrow_mut().pankti_sankya += 1.0; - for (index, line) in text[1..].split(" ").enumerate() { - let part = line.split("="); - let part = part.into_iter().collect::>(); - if part.len() == 1 { - let num = match part[0].trim().parse::() { - Ok(val) => val, - Err(_) => { - continue; - } - }; - let mut gp = tmp_graph.borrow_mut(); - - let sankhya = gp.pankti_sankya; - match gp.lines.get_mut(&index.to_string()) { - Some(val) => { - val.points.push((sankhya, num)); - } None => { - let v = vec![(sankhya, num)]; - - let mut rng = rand::thread_rng(); - gp.lines.insert(index.to_string(), graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v)); - } - } - gp.area.queue_draw(); - } else if part.len() == 2 { - let num = match part[1].trim().parse::() { - Ok(val) => val, - Err(_) => { - continue; - } - }; - let mut gp = tmp_graph.borrow_mut(); - - let sankhya = gp.pankti_sankya; - match gp.lines.get_mut(part[0]) { - Some(val) => { - val.points.push((sankhya, num)); - } None => { - let v = vec![(sankhya, num)]; - - let mut rng = rand::thread_rng(); - gp.lines.insert(part[0].to_owned(), graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v)); - } - } - gp.area.queue_draw(); - } - } - - if full_log.get_active(){ - let buf = log_area.get_buffer() - .expect("Couldn't get log_area"); - buf.insert(&mut buf.get_end_iter(), &text); - log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0); - } - } else { - let buf = log_area.get_buffer() - .expect("Couldn't get log_area"); - buf.insert(&mut buf.get_end_iter(), &text); - log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0); - } + receiver_for_msg(text, &tmp_graph, &full_log, &log_area); }, Message::Status(text) => { bar.push(1, &text); @@ -385,11 +322,120 @@ pub fn build_ui(app: >k::Application, config: Arc::>) { // receiver.attach(None, move |_| { // // println!("{:?}", tmp_graph.borrow_mut().lines[0].points); // tmp_graph.borrow_mut().scale_x_start += 1.0; - // tmp_graph.borrow().area.queue_draw(); + // tmp_graph.borrow_mut().redraw(); // glib::Continue(true) // }); } +fn serial_thread_work( + config: &Arc>, + bufread: &mut Option>>, + sender: &glib::Sender, + buf: &mut String) { + match config.lock() { + Ok(mut config) => { + match config.status { + Status::AVRODTIH => { + *bufread = None; + config.status = Status::SAYAN; + }, + Status::JAGRIT => { + if let Some(read) = bufread { + if let Ok(_) = read.read_line(buf) { + sender.send(Message::Msg(buf.clone())).unwrap(); + buf.clear(); + } + } + }, + Status::NIKAS => {}, + Status::PARIVARTIT => { + let p = match serialport::new(&config.port, config.bondrate).open() { + Ok(p) => p, + Err(_) => { + return; + } + }; + + *bufread = Some(BufReader::new(p)); + config.status = Status::JAGRIT; + }, + Status::SAYAN => {} + } + + }, Err(_) => { + sender.send(Message::Status("Faild prepare for communication!".to_owned())).unwrap(); + return; + } + }; +} + +fn receiver_for_msg(text: String, graph: &Rc>, full_log: >k::CheckButton, log_area: >k::TextView) { + if text.starts_with("#") { + graph.borrow_mut().pankti_sankya += 1.0; + for (index, line) in text[1..].split(" ").enumerate() { + let part = line.split("="); + let part = part.into_iter().collect::>(); + if part.len() == 1 { + let num = match part[0].trim().parse::() { + Ok(val) => val, + Err(_) => { + continue; + } + }; + let mut gp = graph.borrow_mut(); + + let sankhya = gp.pankti_sankya; + match gp.lines.get_mut(&index.to_string()) { + Some(val) => { + val.points.push((sankhya, num)); + } None => { + let v = vec![(sankhya, num)]; + + let mut rng = rand::thread_rng(); + gp.lines.insert(index.to_string(), graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v)); + } + } + gp.redraw(); + } else if part.len() == 2 { + let num = match part[1].trim().parse::() { + Ok(val) => val, + Err(_) => { + continue; + } + }; + let mut gp = graph.borrow_mut(); + + let sankhya = gp.pankti_sankya; + match gp.lines.get_mut(part[0]) { + Some(val) => { + val.points.push((sankhya, num)); + } None => { + let v = vec![(sankhya, num)]; + + let mut rng = rand::thread_rng(); + gp.lines.insert(part[0].to_owned(), graph::Line::new(rng.gen_range(0.0..1.0), 0.0, rng.gen_range(0.0..1.0), v)); + } + } + gp.redraw(); + } + } + + if full_log.get_active(){ + let buf = log_area.get_buffer() + .expect("Couldn't get log_area"); + buf.insert(&mut buf.get_end_iter(), &text); + log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0); + log_area.queue_draw(); + } + } else { + let buf = log_area.get_buffer() + .expect("Couldn't get log_area"); + buf.insert(&mut buf.get_end_iter(), &text); + log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0); + log_area.queue_draw(); + } +} + fn send_text(config: &Arc>, entry: >k::Entry, bar: >k::Statusbar) { match config.lock() { Ok(config) => { diff --git a/ui/main_window.glade b/ui/main_window.glade index ff44941..1b73215 100644 --- a/ui/main_window.glade +++ b/ui/main_window.glade @@ -58,7 +58,7 @@ False Trangam - 800 + 850 600 @@ -259,7 +259,44 @@ True True False - True + True + + + + + False + True + + + + + True + False + + + box + True + True + False + True + + + + + False + True + + + + + True + False + + + baarik box + True + True + False True diff --git a/ui/main_window.glade~ b/ui/main_window.glade~ index ea6ea31..1b73215 100644 --- a/ui/main_window.glade~ +++ b/ui/main_window.glade~ @@ -58,7 +58,7 @@ False Trangam - 800 + 850 600 @@ -80,7 +80,7 @@ True False - + Save Log True False @@ -259,7 +259,44 @@ True True False - True + True + + + + + False + True + + + + + True + False + + + box + True + True + False + True + + + + + False + True + + + + + True + False + + + baarik box + True + True + False True