major change

This commit is contained in:
Piyush मिश्रः 2021-01-15 20:12:55 +05:30
parent f6753f2af9
commit 1652209386
4 changed files with 221 additions and 141 deletions

View File

@ -1,10 +1,12 @@
//! This part do manage most of work realted to drawing graph
use gtk::prelude::*; use gtk::prelude::*;
use gtk::DrawingArea; use gtk::DrawingArea;
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
/// A single line
pub struct Line { pub struct Line {
pub points: Vec<(f64,f64)>, pub points: Vec<(f64,f64)>,
pub color: (f64, f64, f64) pub color: (f64, f64, f64)
@ -18,45 +20,30 @@ impl Line {
} }
} }
} }
/// Tools to draw Graph
pub struct Graph { pub struct Graph {
pub area: DrawingArea, pub area: DrawingArea,
pub scale_x_start: f64, pub scale_x_start: f64, // start of x on pankti
pub scale_x_size: f64, pub scale_x_size: f64, // size of pankti to show
pub scale_y_start: f64, pub scale_y_start: f64, // start of y on stambh
pub scale_y_size: f64, pub scale_y_size: f64, // size of stambh to show
pub draw_patch: bool, pub draw_patch: bool, // enable to draw circle spot on line
pub draw_baarik_box: bool, pub draw_box: bool, // enable to show boxes linke graph paper
pub draw_box: bool, pub draw_baarik_box: bool, // enable to show baarik(similar meaning to smaller) linke graph paper
pub auto_adjust_y: bool, pub auto_adjust_y: bool, // enable to automatically adjust y axis
pub lines: HashMap<String, Line>, pub lines: HashMap<String, Line>,
pub pankti_sankya: f64 pub pankti_sankya: f64 // use used while adding to point in lines to see last count of graphable input
} }
impl Graph { 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, pub fn new(area: DrawingArea,
scale_x_start: f64, scale_x_start: f64,
scale_x_size: f64, scale_x_size: f64,
scale_y_start: f64, scale_y_start: f64,
scale_y_size: f64, scale_y_size: f64,
draw_patch: bool, draw_patch: bool,
draw_baarik_box: bool,
draw_box: bool, draw_box: bool,
draw_baarik_box: bool,
auto_adjust_y: bool, auto_adjust_y: bool,
lines: HashMap<String, Line>, lines: HashMap<String, Line>,
pankti_sankya: f64) -> Rc<RefCell<Self>> { pankti_sankya: f64) -> Rc<RefCell<Self>> {
@ -68,8 +55,8 @@ impl Graph {
scale_y_start, scale_y_start,
scale_y_size, scale_y_size,
draw_patch, draw_patch,
draw_baarik_box: draw_baarik_box,
draw_box, draw_box,
draw_baarik_box,
auto_adjust_y, auto_adjust_y,
lines, lines,
pankti_sankya pankti_sankya
@ -84,6 +71,44 @@ impl Graph {
graph graph
} }
/// used to draw box and baarik box
fn draw_boxes(ctx: &cairo::Context, area_width: f64, area_height: f64, src_x: f64, cell_size: f64, color: f64) {
ctx.set_source_rgb(color, color, color);
ctx.set_line_width(1.0);
// lines parallel to stambh
for i in 1..math::round::ceil(area_width/cell_size, 0) as i32 {
let xi = i as f64 * cell_size + src_x;
ctx.move_to(xi, 0.0);
ctx.line_to(xi, area_height);
}
// lines parallel to pankti
for i in 1..math::round::ceil(area_height/cell_size, 0) as i32 {
let yi = area_height - i as f64 * cell_size;
ctx.move_to(src_x, yi);
ctx.line_to(area_width + src_x, yi);
}
ctx.stroke();
}
/// transform point to show on graph
fn transform_on_graph(
p_start: f64,
s_start: f64,
p: f64,
s: f64,
aa_dumm_pankti: f64,
aa_dumm_stambh: f64,
scale_x_size: f64,
scale_y_size: f64,
height: f64,
stambh_scale_width: f64) -> (f64, f64){
(
((p - p_start) * aa_dumm_pankti)/scale_x_size + stambh_scale_width,
height - ((s - s_start) * aa_dumm_stambh) / scale_y_size
)
}
/// callback of drawing area to draw graph
fn draw(area: &gtk::DrawingArea, fn draw(area: &gtk::DrawingArea,
ctx: &cairo::Context, ctx: &cairo::Context,
graph: &Rc<RefCell<Graph>>) { graph: &Rc<RefCell<Graph>>) {
@ -93,94 +118,139 @@ impl Graph {
ctx.set_source_rgb(0.1, 0.5, 0.5); ctx.set_source_rgb(0.1, 0.5, 0.5);
ctx.paint(); ctx.paint();
let width = area.get_allocated_width() as f64; let pankti_scale_height = 50.0;
let height = area.get_allocated_height() as f64; let stambh_scale_width = 60.0;
let width = area.get_allocated_width() as f64 - stambh_scale_width;
let height = area.get_allocated_height() as f64 - pankti_scale_height;
let manjusa_maap = 50.0;
let rekha_sankhya_pankti = math::round::floor(width / manjusa_maap, 0);
let rekha_sankhya_stambh = math::round::floor(height / manjusa_maap, 0);
let aa_dumm_pankti = rekha_sankhya_pankti * manjusa_maap;
let aa_dumm_stambh = rekha_sankhya_stambh * manjusa_maap;
let anupat_pankti = (manjusa_maap * graph.scale_x_size) / aa_dumm_pankti;
let anupat_stambh = (manjusa_maap * graph.scale_y_size) / aa_dumm_stambh;
// drawing boxes to show area as graph paper
if graph.draw_box { if graph.draw_box {
if graph.draw_baarik_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, stambh_scale_width, 5.0, 0.3);
} }
Graph::draw_boxes(ctx, width, height, stambh_scale_width, 50.0, 0.1);
Graph::draw_boxes(ctx, width, height, 40.0, 20.0, 50.0, 0.1);
} }
let cell_size = 50.0; // Drawing point and line on graph area
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.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_width(2.0);
ctx.set_line_cap(cairo::LineCap::Round); ctx.set_line_cap(cairo::LineCap::Round);
let draw_patch = graph.draw_patch; let draw_patch = graph.draw_patch;
for (_,line) in graph.lines.iter() { for (_,line) in graph.lines.iter() {
for p in line.points.iter().enumerate() { for (i, (p,s)) in line.points.iter().enumerate() {
let xp = if p.0 < line.points.len() - 1 { // check if point is last poin on line
line.points[p.0 + 1] let (p_dumm, s_dumm) = if i < line.points.len() - 1 {
line.points[i + 1]
} else { } else {
line.points[p.0] line.points[i]
}; };
let bindu_t = Graph::transform_on_graph(
graph.scale_x_start,
graph.scale_y_start,
*p,
*s,
aa_dumm_pankti,
aa_dumm_stambh,
graph.scale_x_size,
graph.scale_y_size,
height,
stambh_scale_width,
);
let bindu_dumm_t = Graph::transform_on_graph(
graph.scale_x_start,
graph.scale_y_start,
p_dumm,
s_dumm,
aa_dumm_pankti,
aa_dumm_stambh,
graph.scale_x_size,
graph.scale_y_size,
height,
stambh_scale_width,
);
ctx.set_source_rgb(line.color.0, line.color.1, line.color.2); ctx.set_source_rgb(line.color.0, line.color.1, line.color.2);
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.move_to(bindu_dumm_t.0, bindu_dumm_t.1);
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.line_to(bindu_t.0, bindu_t.1);
ctx.stroke(); ctx.stroke();
// draw circle over point
if draw_patch { if draw_patch {
ctx.set_source_rgb(0.0, 0.0, 1.0); ctx.set_source_rgb(0.0, 0.0, 1.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.arc(bindu_dumm_t.0, bindu_dumm_t.1,
5.0, 0.0, std::f64::consts::PI * 2.0);
ctx.stroke(); ctx.stroke();
} }
} }
} }
// draw darker recragle over scales
ctx.set_source_rgb(0.1, 0.4, 0.4); ctx.set_source_rgb(0.1, 0.4, 0.4);
ctx.rectangle(0.0, 0.0, 40.0, height); ctx.rectangle(0.0, 0.0, stambh_scale_width, height + pankti_scale_height);
ctx.rectangle(0.0, height - 20.0, width, 20.0); ctx.rectangle(stambh_scale_width, height, width, pankti_scale_height);
ctx.fill(); ctx.fill();
ctx.set_source_rgb(1.0, 1.0, 1.0); ctx.set_source_rgb(1.0, 1.0, 1.0);
for x in 0..v_bars { // write numbers on pankti scale
let text = math::round::floor(x as f64 * h_scale + graph.scale_x_start, 1).to_string(); for i in 0..(rekha_sankhya_pankti as i32 + 1) {
let text = math::round::floor(i as f64 * anupat_pankti + graph.scale_x_start, 4).to_string();
let f = ctx.text_extents(&text); let f = ctx.text_extents(&text);
ctx.move_to(40.0 + x as f64 * cell_size - f.width, height - 10.0); ctx.move_to(i as f64 * manjusa_maap - f.width + stambh_scale_width + f.height / 0.866, height + f.width * 0.5 + f.height);
ctx.save();
ctx.rotate(std::f64::consts::PI / -6.0);
ctx.show_text(&text); ctx.show_text(&text);
ctx.restore();
} }
// write numbers on stambh scale
for y in (0..h_bars).rev() { for i in (0..aa_dumm_stambh as i32 + 1).rev() {
let text = math::round::floor(y as f64 * v_scale + graph.scale_y_start, 1).to_string(); let text = math::round::floor(i as f64 * anupat_stambh + graph.scale_y_start, 4).to_string();
let f = ctx.text_extents(&text); let f = ctx.text_extents(&text);
ctx.move_to(40.0 - f.width, height - y as f64 * cell_size - f.height - 15.0); ctx.move_to(stambh_scale_width - f.width + f.height / 1.732, height - i as f64 * manjusa_maap + f.width * 0.5);
ctx.save();
ctx.rotate(std::f64::consts::PI / -6.0);
ctx.show_text(&text); ctx.show_text(&text);
ctx.restore();
} }
} }
/// Adjust stambh and pankti as needed , trim lines and redraws
pub fn redraw(&mut self) { pub fn redraw(&mut self) {
let (mx_x, mi_x, mx_y, mi_y) = self.get_extremes(); let (mx_x, mi_x, mx_y, mi_y) = self.get_extremes();
// stambh // stambh
if self.auto_adjust_y { if self.auto_adjust_y {
let spread = (mx_y - mi_y).abs(); let spread = (mx_y - mi_y).abs();
self.scale_y_start = mi_y - spread * 0.1; self.scale_y_start = mi_y - spread * 0.1;
self.scale_y_size = spread * 1.2; self.scale_y_size = spread * 1.2;
} }
// pankti // pankti
let spread = (mx_x - mi_x).abs(); let spread = (mx_x - mi_x).abs();
if spread < self.scale_x_size { if spread < self.scale_x_size {
self.scale_x_start = mi_x; self.scale_x_start = mi_x;
} else { } else {
self.scale_x_start = mx_x - self.scale_x_size; self.scale_x_start = mx_x - self.scale_x_size;
} }
self.trim_lines(); self.trim_lines(); // trim
self.area.queue_draw(); self.area.queue_draw(); // redraw
} }
/// find minimun and maximum value from all lines
pub fn get_extremes(&self) -> (f64, f64, f64, f64){ pub fn get_extremes(&self) -> (f64, f64, f64, f64){
// trick to avoid no lines
if self.lines.len() == 0 { if self.lines.len() == 0 {
return (0.0,0.0,0.0,0.0); return (0.0,0.0,0.0,0.0);
} }
@ -199,6 +269,10 @@ impl Graph {
continue; continue;
} }
// keeping these in here is a good idea than picking line[0].point[0]
// because consider if 0th line have no points and 1st too than that fails
// and also if we keep 0 as default value to start then a graph with
// 100 to 200 will have 0 as minimum
if let None = mx_x { if let None = mx_x {
mx_x = Some(line.points[0].0); mx_x = Some(line.points[0].0);
} }
@ -226,6 +300,8 @@ impl Graph {
(mx_x.unwrap(), mi_x.unwrap(), mx_y.unwrap(), mi_y.unwrap()) (mx_x.unwrap(), mi_x.unwrap(), mx_y.unwrap(), mi_y.unwrap())
} }
// tims line form left side of line. Why left?? to avoid wasting time in ponits in range
// it skips i point out of screen to keep a non terminating line experience
pub fn trim_lines(&mut self) { pub fn trim_lines(&mut self) {
for (_, line) in self.lines.iter_mut() { for (_, line) in self.lines.iter_mut() {
let mut i = 0; let mut i = 0;

View File

@ -12,8 +12,9 @@ use std::io::BufReader;
use graph::Graph; use graph::Graph;
pub enum Status { /// Status of Serial reading
JAGRIT, SAYAN, AVRODTIH, PARIVARTIT, NIKAS enum Status {
JAGRIT, SAYAN, AVRODTIH, PARIVARTIT
} }
pub struct Config { pub struct Config {
@ -22,6 +23,7 @@ pub struct Config {
port: String port: String
} }
//
impl Config { impl Config {
pub fn new() -> Config { pub fn new() -> Config {
Config { Config {
@ -50,7 +52,7 @@ pub fn build_ui(app: &gtk::Application, config: Arc::<Mutex::<Config>>) {
0.0, 100.0, 0.0, 100.0,
0.0, 100.0, 0.0, 100.0,
false, false,
false, true,
false, false,
true, true,
HashMap::new(), HashMap::new(),
@ -72,6 +74,10 @@ pub fn build_ui(app: &gtk::Application, config: Arc::<Mutex::<Config>>) {
let about_menu = builder.get_object::<gtk::MenuItem>("about_menu").expect("Resource file missing!"); let about_menu = builder.get_object::<gtk::MenuItem>("about_menu").expect("Resource file missing!");
let about = builder.get_object::<gtk::AboutDialog>("about").expect("Resource file missing!"); let about = builder.get_object::<gtk::AboutDialog>("about").expect("Resource file missing!");
about.connect_close(|a| {
a.hide();
});
about_menu.connect_activate(move |_|{ about_menu.connect_activate(move |_|{
about.show_all(); about.show_all();
}); });
@ -155,6 +161,7 @@ pub fn build_ui(app: &gtk::Application, config: Arc::<Mutex::<Config>>) {
let tmp_graph = Rc::clone(&graph); let tmp_graph = Rc::clone(&graph);
draw_box.connect_clicked(move |btn| { draw_box.connect_clicked(move |btn| {
draw_baarik_box.set_sensitive(btn.get_active());
let mut tmp_graph = tmp_graph.borrow_mut(); let mut tmp_graph = tmp_graph.borrow_mut();
tmp_graph.draw_box = btn.get_active(); tmp_graph.draw_box = btn.get_active();
tmp_graph.redraw(); tmp_graph.redraw();
@ -311,21 +318,6 @@ pub fn build_ui(app: &gtk::Application, config: Arc::<Mutex::<Config>>) {
} }
glib::Continue(true) glib::Continue(true)
}); });
// Time ke hisab se pankti ko aage bhadhay
// let (sender, receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
// glib::timeout_add(300, move || {
// sender.send(()).unwrap();
// glib::Continue(true)
// });
// let tmp_graph = Rc::clone(&graph);
// receiver.attach(None, move |_| {
// // println!("{:?}", tmp_graph.borrow_mut().lines[0].points);
// tmp_graph.borrow_mut().scale_x_start += 1.0;
// tmp_graph.borrow_mut().redraw();
// glib::Continue(true)
// });
} }
fn serial_thread_work( fn serial_thread_work(
@ -333,6 +325,7 @@ fn serial_thread_work(
bufread: &mut Option<BufReader<Box<dyn serialport::SerialPort>>>, bufread: &mut Option<BufReader<Box<dyn serialport::SerialPort>>>,
sender: &glib::Sender<MessageSerialThread>, sender: &glib::Sender<MessageSerialThread>,
buf: &mut String) { buf: &mut String) {
let mut do_sleep = false;
match config.lock() { match config.lock() {
Ok(mut config) => { Ok(mut config) => {
match config.status { match config.status {
@ -348,7 +341,6 @@ fn serial_thread_work(
} }
} }
}, },
Status::NIKAS => {},
Status::PARIVARTIT => { Status::PARIVARTIT => {
let p = match serialport::new(&config.port, config.bondrate).open() { let p = match serialport::new(&config.port, config.bondrate).open() {
Ok(p) => p, Ok(p) => p,
@ -360,80 +352,92 @@ fn serial_thread_work(
*bufread = Some(BufReader::new(p)); *bufread = Some(BufReader::new(p));
config.status = Status::JAGRIT; config.status = Status::JAGRIT;
}, },
Status::SAYAN => {} Status::SAYAN => {
do_sleep = true;
}
} }
}, Err(_) => { }, Err(_) => {
sender.send(MessageSerialThread::Status("Faild prepare for communication!".to_owned())).unwrap(); sender.send(MessageSerialThread::Status("Faild prepare for communication!".to_owned())).unwrap();
return; return;
} }
}; };
// Hack for smooth performance
if do_sleep {
std::thread::sleep(std::time::Duration::from_millis(100));
} else {
std::thread::sleep(std::time::Duration::from_nanos(1));
}
} }
fn receiver_for_msg(text: String, graph: &Rc<RefCell<Graph>>, full_log: &gtk::CheckButton, log_area: &gtk::TextView) { fn receiver_for_msg(text: String, graph: &Rc<RefCell<Graph>>, full_log: &gtk::CheckButton, log_area: &gtk::TextView) {
if text.starts_with("#") { for text in text.lines() {
graph.borrow_mut().pankti_sankya += 1.0; if text.len() == 0 {
for (index, line) in text[1..].split(" ").enumerate() { return;
let part = line.split("="); } else if text.starts_with("#") {
let part = part.into_iter().collect::<Vec<&str>>(); graph.borrow_mut().pankti_sankya += 1.0;
if part.len() == 1 { for (index, line) in text[1..].split(" ").enumerate() {
let num = match part[0].trim().parse::<f64>() { let part = line.split("=");
Ok(val) => val, let part = part.into_iter().collect::<Vec<&str>>();
Err(_) => { if part.len() == 1 {
continue; let num = match part[0].trim().parse::<f64>() {
} Ok(val) => val,
}; Err(_) => {
let mut gp = graph.borrow_mut(); continue;
}
};
let mut gp = graph.borrow_mut();
let sankhya = gp.pankti_sankya; let sankhya = gp.pankti_sankya;
match gp.lines.get_mut(&index.to_string()) { match gp.lines.get_mut(&index.to_string()) {
Some(val) => { Some(val) => {
val.points.push((sankhya, num)); val.points.push((sankhya, num));
} None => { } None => {
let v = vec![(sankhya, num)]; let v = vec![(sankhya, num)];
let mut rng = rand::thread_rng(); 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.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::<f64>() {
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();
} }
gp.redraw();
} else if part.len() == 2 {
let num = match part[1].trim().parse::<f64>() {
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(){ if full_log.get_active(){
let buf = log_area.get_buffer()
.expect("Couldn't get log_area");
buf.insert(&mut buf.get_end_iter(), &format!("{}\n",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() let buf = log_area.get_buffer()
.expect("Couldn't get log_area"); .expect("Couldn't get log_area");
buf.insert(&mut buf.get_end_iter(), &text); buf.insert(&mut buf.get_end_iter(), &format!("{}\n",text));
log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0); log_area.scroll_to_iter(&mut buf.get_end_iter(), 0.4, true, 0.0, 0.0);
log_area.queue_draw(); 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();
} }
} }

View File

@ -8,7 +8,6 @@
<property name="program-name">Tarangam (तरंगम्)</property> <property name="program-name">Tarangam (तरंगम्)</property>
<property name="comments" translatable="yes">A simple serial plotter. <property name="comments" translatable="yes">A simple serial plotter.
एक सरल सीरीय्ल पलौटर।</property> एक सरल सीरीय्ल पलौटर।</property>
<property name="authors">Piyush Mishra</property>
<property name="logo-icon-name">image-missing</property> <property name="logo-icon-name">image-missing</property>
<child internal-child="vbox"> <child internal-child="vbox">
<object class="GtkBox"> <object class="GtkBox">
@ -278,6 +277,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">False</property> <property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property> <property name="draw-indicator">True</property>
</object> </object>
</child> </child>

View File

@ -8,7 +8,6 @@
<property name="program-name">Tarangam (तरंगम्)</property> <property name="program-name">Tarangam (तरंगम्)</property>
<property name="comments" translatable="yes">A simple serial plotter. <property name="comments" translatable="yes">A simple serial plotter.
एक सरल सीरीय्ल पलौटर।</property> एक सरल सीरीय्ल पलौटर।</property>
<property name="authors">Piyush Mishra</property>
<property name="logo-icon-name">image-missing</property> <property name="logo-icon-name">image-missing</property>
<child internal-child="vbox"> <child internal-child="vbox">
<object class="GtkBox"> <object class="GtkBox">
@ -278,6 +277,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">False</property> <property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property> <property name="draw-indicator">True</property>
</object> </object>
</child> </child>