From a577144e57b15ec7a84e66a3664475a48aa618e6 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Sat, 10 Dec 2022 21:31:00 +0100 Subject: [PATCH 1/8] added nfa reading from string --- Cargo.toml | 1 + src/automata/nfa.rs | 2 + src/automata/nfa/from_string.rs | 132 ++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 src/automata/nfa/from_string.rs diff --git a/Cargo.toml b/Cargo.toml index a9042c2..43c634f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ log = "0.4.17" eframe = "0.19.0" egui = "0.19.0" wasm-bindgen = "0.2.83" +nom = "7.1.1" diff --git a/src/automata/nfa.rs b/src/automata/nfa.rs index 4a0340b..2fb677b 100644 --- a/src/automata/nfa.rs +++ b/src/automata/nfa.rs @@ -5,6 +5,8 @@ use crate::automata::regular_expression as RE; use crate::display::DisplayGraph; use crate::utils::Graph; +mod from_string; + #[derive(Debug)] pub struct NFA { start_state: usize, diff --git a/src/automata/nfa/from_string.rs b/src/automata/nfa/from_string.rs new file mode 100644 index 0000000..6efa0f4 --- /dev/null +++ b/src/automata/nfa/from_string.rs @@ -0,0 +1,132 @@ +use super::NFA; + +use nom::{ + bytes::complete::take, + bytes::complete::take_while1, + bytes::streaming::tag, + character::complete::{char, one_of}, + character::complete::{digit1, multispace0}, + combinator::{map_res, opt}, + multi::separated_list0, + sequence::{delimited, preceded, tuple}, + IResult, +}; + +fn decimal(input: &str) -> IResult<&str, &str> { + take_while1(move |c: char| c.is_digit(10))(input) +} + +fn str_to_usize(input: &str) -> Result { + usize::from_str_radix(input, 10) +} + +fn read_num(input: &str) -> IResult<&str, usize> { + map_res(digit1, |digit_str: &str| digit_str.parse::())(input) +} + +fn custom_label<'a>( + label: &str, +) -> impl Fn(&'a str) -> IResult<&'a str, (&'a str, &'a str, &'a str, &'a str)> + '_ { + move |input| tuple((tag(label), multispace0, tag(":"), multispace0))(input) +} + +fn read_start_stete(input: &str) -> IResult<&str, usize> { + preceded(custom_label("start_state"), read_num)(input) +} +fn read_num_states(input: &str) -> IResult<&str, usize> { + preceded(custom_label("num_states"), read_num)(input) +} + +const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + +fn read_char(input: &str) -> IResult<&str, char> { + preceded( + multispace0, + delimited(char('\''), one_of(ALPHABET), char('\'')), + )(input) +} + +fn read_num_array(input: &str) -> IResult<&str, Vec> { + delimited( + tag("["), + separated_list0(tag(","), delimited(multispace0, read_num, multispace0)), + tag("]"), + )(input) +} + +fn read_finish_states(input: &str) -> IResult<&str, Vec> { + preceded(custom_label("num_states"), read_num_array)(input) +} + +fn read_transiction(input: &str) -> IResult<&str, (usize, usize, char)> { + // 1 -- 'a' --> 3 + let (input, from) = delimited(multispace0, read_num, multispace0)(input)?; + let (input, _) = tag("--")(input)?; + let (input, ch) = opt(read_char)(input)?; + let (input, _) = preceded(multispace0, tag("-->"))(input)?; + let (input, to) = preceded(multispace0, read_num)(input)?; + //TODO aggiungere espilon + Ok((input, (from, to, ch.unwrap_or('ε')))) +} + +impl From for NFA { + fn from(input: String) -> Self { + //let (input,start_state) = start_state(input.as_str())?; + //let (inuput,num_states) ; + //let (input,end_states); + Self { + start_state: todo!(), + num_states: todo!(), + end_states: todo!(), + transitions: todo!(), + used_alphabet: todo!(), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_edge() { + assert_eq!(read_transiction(" 1 ----> 3"), Ok(("", (1, 3, 'ε')))); + assert_eq!(read_transiction(" 2 -- 'a'--> 3"), Ok(("", (2, 3, 'a')))); + assert_eq!(read_transiction(" 2-- 'a' --> 3 "), Ok((" ", (2, 3, 'a')))); + assert_eq!(read_transiction("2 ----> 3"), Ok(("", (2, 3, 'ε')))); + } + + #[test] + fn test_number_list() { + assert_eq!( + read_num_array("[ 10, 20 , 30 ]"), + Ok(("", vec![10, 20, 30])) + ); + } + #[test] + fn test_number() { + assert_eq!(read_num("10"), Ok(("", 10))); + assert_eq!(read_num("1234"), Ok(("", 1234))); + } + + #[test] + fn test_label() { + assert_eq!( + custom_label("start_state")("start_state : 20"), + Ok(("20", ("start_state", " ", ":", " "))) + ); + assert_eq!( + custom_label("start_state")("start_state: 30"), + Ok(("30", ("start_state", "", ":", " "))) + ); + assert_eq!( + custom_label("start_state")("start_state : 10"), + Ok(("10", ("start_state", " ", ":", " "))) + ); + assert_eq!( + custom_label("start_state")("start_state :10"), + Ok(("10", ("start_state", " ", ":", ""))) + ); + assert_eq!(read_start_stete("start_state : 100\n"), Ok(("\n", 100))); + } +} From 30817906f12e07689cfef850f289def458781d60 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Sun, 11 Dec 2022 15:00:42 +0100 Subject: [PATCH 2/8] from string to nfa --- src/automata/nfa/from_string.rs | 93 +++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/src/automata/nfa/from_string.rs b/src/automata/nfa/from_string.rs index 6efa0f4..a114274 100644 --- a/src/automata/nfa/from_string.rs +++ b/src/automata/nfa/from_string.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use super::NFA; use nom::{ @@ -26,8 +28,8 @@ fn read_num(input: &str) -> IResult<&str, usize> { fn custom_label<'a>( label: &str, -) -> impl Fn(&'a str) -> IResult<&'a str, (&'a str, &'a str, &'a str, &'a str)> + '_ { - move |input| tuple((tag(label), multispace0, tag(":"), multispace0))(input) +) -> impl Fn(&'a str) -> IResult<&'a str, (&'a str, &'a str, &'a str, &'a str, &'a str)> + '_ { + move |input| tuple((multispace0, tag(label), multispace0, tag(":"), multispace0))(input) } fn read_start_stete(input: &str) -> IResult<&str, usize> { @@ -59,27 +61,55 @@ fn read_finish_states(input: &str) -> IResult<&str, Vec> { } fn read_transiction(input: &str) -> IResult<&str, (usize, usize, char)> { - // 1 -- 'a' --> 3 let (input, from) = delimited(multispace0, read_num, multispace0)(input)?; let (input, _) = tag("--")(input)?; let (input, ch) = opt(read_char)(input)?; let (input, _) = preceded(multispace0, tag("-->"))(input)?; let (input, to) = preceded(multispace0, read_num)(input)?; - //TODO aggiungere espilon + Ok((input, (from, to, ch.unwrap_or('ε')))) } -impl From for NFA { - fn from(input: String) -> Self { - //let (input,start_state) = start_state(input.as_str())?; - //let (inuput,num_states) ; - //let (input,end_states); - Self { - start_state: todo!(), - num_states: todo!(), - end_states: todo!(), - transitions: todo!(), - used_alphabet: todo!(), +fn read_all_transictions(input: &str) -> IResult<&str, Vec<(usize, usize, char)>> { + separated_list0(multispace0, read_transiction)(input) +} + +impl TryFrom<&str> for NFA { + // TODO: maybe we can change it + type Error = String; + + fn try_from(value: &str) -> Result { + let out = tuple(( + read_start_stete, + read_finish_states, + read_num_states, + read_all_transictions, + ))(value); + + if let Ok((input, (start_state, end_states, num_states, all_transitions))) = out { + let mut transitions: Vec>> = + (0..num_states).map(|_| BTreeMap::new()).collect(); + for (from, to, ch) in all_transitions.into_iter() { + if from >= num_states { + return Err(String::from("from out of num_state")); + } else if to >= num_states { + return Err(String::from("to out of num_state")); + } else { + transitions[from] + .entry(ch) + .and_modify(|x| x.push(to)) + .or_insert(vec![to]); + } + } + Ok(Self { + start_state, + num_states, + end_states, + transitions, + used_alphabet: ALPHABET.chars().collect(), + }) + } else { + Err(String::from("error while reading nfa")) } } } @@ -88,14 +118,34 @@ impl From for NFA { mod test { use super::*; + #[test] + fn string_to_nfa() { + //todo + NFA::try_from(concat!( + "start_state: 0\n", + "finish_states: [ 2 ]\n", + " num_states: 5\n", + "0 --'b'--> 1\n", + "1 ----> 2\n", + "1 ----> 3\n", + "3 -- 'a' --> 4\n", + "4 ----> 3\n", + "4 ----> 2\n" + )); + } + #[test] fn test_edge() { assert_eq!(read_transiction(" 1 ----> 3"), Ok(("", (1, 3, 'ε')))); assert_eq!(read_transiction(" 2 -- 'a'--> 3"), Ok(("", (2, 3, 'a')))); - assert_eq!(read_transiction(" 2-- 'a' --> 3 "), Ok((" ", (2, 3, 'a')))); + assert_eq!(read_transiction(" 2-- 'a' --> 3 "), Ok((" ", (2, 3, 'a')))); assert_eq!(read_transiction("2 ----> 3"), Ok(("", (2, 3, 'ε')))); } + #[test] + fn test_start_state() { + assert_eq!(read_start_stete("start_state : 100\n"), Ok(("\n", 100))); + } #[test] fn test_number_list() { assert_eq!( @@ -113,20 +163,19 @@ mod test { fn test_label() { assert_eq!( custom_label("start_state")("start_state : 20"), - Ok(("20", ("start_state", " ", ":", " "))) + Ok(("20", ("", "start_state", " ", ":", " "))) ); assert_eq!( - custom_label("start_state")("start_state: 30"), - Ok(("30", ("start_state", "", ":", " "))) + custom_label("start_state")(" start_state: 30"), + Ok(("30", (" ", "start_state", "", ":", " "))) ); assert_eq!( custom_label("start_state")("start_state : 10"), - Ok(("10", ("start_state", " ", ":", " "))) + Ok(("10", ("", "start_state", " ", ":", " "))) ); assert_eq!( custom_label("start_state")("start_state :10"), - Ok(("10", ("start_state", " ", ":", ""))) + Ok(("10", ("", "start_state", " ", ":", ""))) ); - assert_eq!(read_start_stete("start_state : 100\n"), Ok(("\n", 100))); } } From 8eca4bbb4b9acc0028964378f54358462231dc66 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Wed, 14 Dec 2022 17:54:24 +0100 Subject: [PATCH 3/8] temp --- src/app.rs | 119 +++------------------------- src/automata/dfa.rs | 6 +- src/automata/nfa.rs | 6 +- src/automata/nfa/from_string.rs | 1 + src/automata/regular_expression.rs | 6 +- src/display/display_graph.rs | 2 + src/display/mod.rs | 4 +- src/display/regular_language_gui.rs | 100 +++++++++++++++++++++++ src/display/visualizer.rs | 97 ++++++++++++++++++++--- src/utils/graph.rs | 4 + 10 files changed, 214 insertions(+), 131 deletions(-) create mode 100644 src/display/regular_language_gui.rs diff --git a/src/app.rs b/src/app.rs index c6a695d..fae50e2 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,40 +1,19 @@ use eframe::egui; -use egui::{emath, Color32, Frame, Pos2, Rect, RichText, Window}; +use egui::SidePanel; + +use crate::display::RegularLanguageGui; -use crate::automata::DFA; -use crate::automata::NFA; -use crate::automata::ReOperator; -use crate::display::DisplayGraphParameter; -use crate::display::Visualizer; -use crate::utils::Graph; -pub struct EguiApp { - error: Option, - regex_text: String, - // This is indexed accordingly - // 0: Regex - // 1: NFA - // 2: DFA - // 3: Minimized DFA - // a union structure would be useful for accessing the Visualizers - // with both indixes and names, but it's problematic how to do it - // in rust. - to_visualize: [Visualizer; 4], +pub struct EguiApp { + leftpanel:RegularLanguageGui, } impl Default for EguiApp { fn default() -> Self { Self { - error: None, - regex_text: String::new(), + leftpanel:RegularLanguageGui::new() - to_visualize: [ - Visualizer::new("Regex Syntax Tree".to_string()), - Visualizer::new("NFA".to_string()), - Visualizer::new("DFA".to_string()), - Visualizer::new("Minimized DFA".to_string()), - ], } } } @@ -44,92 +23,14 @@ impl EguiApp { Self::default() } - pub fn get_converter(index: i32) -> impl Fn(ReOperator) -> Graph { - match index { - 0 => |re: ReOperator| re.into(), - 1 => |re: ReOperator| NFA::from(&re).into(), - 2 => |re: ReOperator| DFA::from(&NFA::from(&re)).into(), - 3 => |re: ReOperator| DFA::from(&NFA::from(&re)).get_minimized_dfa().into(), - _ => panic!("Invalid index"), - } - } } + impl eframe::App for EguiApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - egui::SidePanel::left("Main").show(ctx, |ui| { - for (index, visualizer) in self.to_visualize.iter_mut().enumerate() { - ui.heading(&visualizer.box_title); - if index == 0 { - ui.horizontal(|ui| { - ui.label("inserisci la regex"); - ui.text_edit_singleline(&mut self.regex_text) - .on_hover_text("Enter a regular expression"); - }); - } - if ui - .button(format!("Generate {}", visualizer.box_title)) - .clicked() - { - match ReOperator::from_string(&self.regex_text) { - Ok(re) => { - visualizer.set_graph(Self::get_converter(index as i32)(re).into()); - self.error = None; - } - - Err(e) => { - self.error = Some(e.to_string()); - } - }; - } - - ui.collapsing( - format!("{} visualizer option", visualizer.box_title), - |ui| { - ui.add( - egui::Slider::new(&mut visualizer.padding_x, 10.0..=100.0) - .text("padding x"), - ); - ui.add( - egui::Slider::new(&mut visualizer.padding_y, 10.0..=100.0) - .text("padding y"), - ); - ui.add( - egui::Slider::new(&mut visualizer.size_node, 10.0..=100.0) - .text("node size"), - ); - }, - ); - } - if let Some(err) = &self.error { - ui.label(RichText::new(err).color(Color32::RED)); - } + SidePanel::left("Main").show(ctx, |ui| { + self.leftpanel.draw_left_panel(ui); }); - for visualizer in self.to_visualize.iter_mut() { - visualizer.check_open(); - let syntaxTree = Window::new(format!("{}", visualizer.box_title)); - let syntaxTree = syntaxTree.open(&mut visualizer.is_win_open); - let syntaxTree = syntaxTree.scroll2([true, true]); - syntaxTree.show(ctx, |ui| { - Frame::canvas(ui.style()).show(ui, |ui| { - if let Some(tree) = &mut visualizer.graph { - let scren_size = tree.position(DisplayGraphParameter { - padding_x: visualizer.padding_x, - padding_y: visualizer.padding_y, - node_size: visualizer.size_node, - }); - let (mut response, painter) = - ui.allocate_painter(scren_size, egui::Sense::hover()); - - let to_screen = emath::RectTransform::from_to( - Rect::from_min_size(Pos2::ZERO, response.rect.size()), - response.rect, - ); - tree.drag_nodes(to_screen, ui, &mut response); - tree.draw(&painter, to_screen, &ui); - } - }) - }); - } + self.leftpanel.draw_visualizer_windows(ctx); } } diff --git a/src/automata/dfa.rs b/src/automata/dfa.rs index a84d982..e1539cd 100644 --- a/src/automata/dfa.rs +++ b/src/automata/dfa.rs @@ -5,7 +5,7 @@ use crate::automata::regular_expression as RE; use crate::utils::{Graph, IndEdge, IndNode}; use crate::utils::DisjointUnionFind; -type NfaStates = BTreeSet; +pub type NfaStates = BTreeSet; #[derive(Debug, Clone)] pub struct DFA { @@ -276,8 +276,8 @@ impl From<&RE::ReOperator> for DFA { } } -impl Into for DFA { - fn into(self) -> Graph { +impl IntoGraph for DFA { + fn into_graph(&self) -> Graph { let mut graph = Graph::new(); let finals_nodes = self diff --git a/src/automata/nfa.rs b/src/automata/nfa.rs index 2fb677b..bc99056 100644 --- a/src/automata/nfa.rs +++ b/src/automata/nfa.rs @@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet}; use crate::automata::regular_expression as RE; use crate::display::DisplayGraph; -use crate::utils::Graph; +use crate::utils::{Graph, IntoGraph}; mod from_string; @@ -215,8 +215,8 @@ impl From<&RE::ReOperator> for NFA { } } -impl Into for NFA { - fn into(self) -> Graph { +impl IntoGraph for NFA { + fn into_graph(&self) -> Graph { let mut graph = Graph::new(); let finals_nodes = self diff --git a/src/automata/nfa/from_string.rs b/src/automata/nfa/from_string.rs index a114274..4a579f6 100644 --- a/src/automata/nfa/from_string.rs +++ b/src/automata/nfa/from_string.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; + use super::NFA; use nom::{ diff --git a/src/automata/regular_expression.rs b/src/automata/regular_expression.rs index 835690c..53092b1 100644 --- a/src/automata/regular_expression.rs +++ b/src/automata/regular_expression.rs @@ -3,7 +3,7 @@ use std::iter::Peekable; use std::str::Chars; use crate::error::{InvalidCharacter, InvalidTokenError, UnvalidParentesis}; -use crate::utils::{Graph, IndNode}; +use crate::utils::{Graph, IndNode, IntoGraph}; /// Structure that represents a regular expression parse tree /// The current regular expression is defined by the following grammar: @@ -283,8 +283,8 @@ impl ReOperator { } } -impl Into for ReOperator { - fn into(self) -> Graph { +impl IntoGraph for ReOperator { + fn into_graph(&self) -> Graph { let mut graph= Graph::new(); self.build_recursive_graph(&mut graph); graph diff --git a/src/display/display_graph.rs b/src/display/display_graph.rs index cddc07e..4315277 100644 --- a/src/display/display_graph.rs +++ b/src/display/display_graph.rs @@ -13,6 +13,7 @@ const COLOR_NODES: Color32 = Color32::WHITE; const COLOR_LABEL_EDGE: Color32 = Color32::GRAY; const COLOR_LABEL_NODE: Color32 = Color32::BLACK; + /// Rapresent the edges types pub enum EdgeType { /// the edge point to it's self @@ -349,3 +350,4 @@ impl DisplayGraph { self.draw_nodes(painter, to_screen, ui); } } + diff --git a/src/display/mod.rs b/src/display/mod.rs index b04c95f..46d771b 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,5 +1,7 @@ mod display_graph; mod visualizer; +mod regular_language_gui; +pub use regular_language_gui::*; pub use display_graph::*; -pub use visualizer::*; \ No newline at end of file +pub use visualizer::*; diff --git a/src/display/regular_language_gui.rs b/src/display/regular_language_gui.rs new file mode 100644 index 0000000..8d2736a --- /dev/null +++ b/src/display/regular_language_gui.rs @@ -0,0 +1,100 @@ +use crate::automata::{NfaStates, ReOperator, DFA, NFA}; +use egui::{Context, Ui}; + +use std::collections::VecDeque; + +use crate::display::Visualizer; + +pub type RegularGrammarObjects = ( + Option, + Option, + Option>, + Option>, +); + +pub struct RegularLanguageGui { + object_copy: RegularGrammarObjects, + error_log: VecDeque, + visualizers: [Visualizer; 4], +} + +const MAX_LOG_QUEUE: usize = 5; + +impl RegularLanguageGui { + fn get_regular_expression_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist( + "Regular Expression", + vec![|ui, reg, input,log| { + ui.text_edit_singleline(input); + if ui.button("Regular Expression").click() { + match ReOperator::from_string(input.as_str()) { + Ok(elem) => { + reg.0 = elem; + return elem.into(); + } + Err(error) => { + log.push_back("Impossibile creare la regular expression"); + } + }; + } + None + }], + ) + } + + fn get_visualizers() -> [Visualizer; 4] { + [ + Self::get_regular_expression_visualizer(), + Visualizer::from_title_and_fromlist("NFA", vec![]), + Visualizer::from_title_and_fromlist("DFA", vec![]), + Visualizer::from_title_and_fromlist("DFA Minimize", vec![]), + ] + } + + pub fn new() -> Self { + Self { + object_copy: (None, None, None, None), + error_log: VecDeque::new(), + visualizers: Self::get_visualizers(), + } + } + pub fn draw_visualizer_windows(&mut self, ctx: &Context) { + for visualizer in &mut self.visualizers { + visualizer.display_visualization(ctx); + } + } + pub fn draw_left_panel(&mut self, ui: &mut Ui) { + for visualizer in &mut self.visualizers { + visualizer.display_left_panel_graphics(ui, &mut self.object_copy, &mut self.error_log); + } + } +} + +// +// +// pub fn get_converter(index: i32) -> impl Fn(ReOperator) -> Graph { +// match index { +// 0 => |re: ReOperator| re.into(), +// 1 => |re: ReOperator| NFA::from(&re).into(), +// 2 => |re: ReOperator| DFA::from(&NFA::from(&re)).into(), +// 3 => |re: ReOperator| DFA::from(&NFA::from(&re)).get_minimized_dfa().into(), +// _ => panic!("Invalid index"), +// } +// } + +// visualizer.display_left_panel_graphics(ui,); +// if ui +// .button(format!("Generate {}", visualizer.box_title)) +// .clicked() +// { +// match ReOperator::from_string(&self.regex_text) { +// Ok(re) => { +// visualizer.set_graph(Self::get_converter(index as i32)(re).into()); +// self.error = None; +// } + +// Err(e) => { +// self.error = Some(e.to_string()); +// } +// }; +// } diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs index f74603c..ee2c8d9 100644 --- a/src/display/visualizer.rs +++ b/src/display/visualizer.rs @@ -1,28 +1,61 @@ -use crate::display::DisplayGraph; +use std::collections::VecDeque; +use egui::{emath, Frame, Pos2, Rect, Ui, Window}; + +use crate::{display::DisplayGraph }; + +use super::DisplayGraphParameter; +use crate::display::RegularGrammarObjects; /// this struct rappresent a visualizer of a graph /// it contains the information to show the window and display the graph + +// if Return a String it return an error +type FromFunction = Box< + dyn Fn( + &mut Ui, + &mut RegularGrammarObjects, + &mut String, + &mut VecDeque + ) -> Option, +>; + pub struct Visualizer { pub box_title: String, pub graph: Option, - pub size_node: f32, - pub padding_y: f32, - pub padding_x: f32, + pub display_parameters: DisplayGraphParameter, pub is_win_open: bool, - - // we can add a lot of paramters such color of nodes, etc.. + pub from: Vec, + pub from_input_string: String, } impl Visualizer { - pub fn new(box_title: String) -> Self { + pub fn from_title_and_fromlist(box_title: &str, from_list: Vec) -> Self { Self { - box_title: box_title, - graph: None, + box_title: String::from(box_title), is_win_open: false, - padding_x: 40., - padding_y: 40., - size_node: 30., + display_parameters: DisplayGraphParameter { + padding_x: 40., + padding_y: 40., + node_size: 30., + }, + graph: None, + from: from_list, + from_input_string: String::new(), + } + } + + pub fn display_left_panel_graphics( + &mut self, + ui: &mut Ui, + other_obj: &mut RegularGrammarObjects, + error_log: &mut VecDeque, + ) { + ui.heading(self.box_title); + for fun in self.from.iter() { + if let Some(res) = fun(ui, &mut other_obj, &mut self.from_input_string,&mut error_log) { + self.graph = Some(res); + } } } @@ -39,4 +72,44 @@ impl Visualizer { self.graph = Some(graph); self.is_win_open = true; } + + fn display_parameters(display_parameters: &mut DisplayGraphParameter, ui: &mut Ui) { + let par = display_parameters; + ui.collapsing(format!("visualizer option",), |ui| { + ui.add(egui::Slider::new(&mut par.padding_x, 10.0..=100.0).text("padding x")); + ui.add(egui::Slider::new(&mut par.padding_y, 10.0..=100.0).text("padding y")); + ui.add(egui::Slider::new(&mut par.node_size, 10.0..=100.0).text("node size")); + }); + } + + fn display_graph( + graph: &mut DisplayGraph, + display_parameters: DisplayGraphParameter, + ui: &mut Ui, + ) { + Frame::canvas(ui.style()).show(ui, |canvas_ui| { + if let Some(tree) = &mut graph { + let scren_size = tree.position(display_parameters); + let (mut response, painter) = ui.allocate_painter(scren_size, egui::Sense::hover()); + + let to_screen = emath::RectTransform::from_to( + Rect::from_min_size(Pos2::ZERO, response.rect.size()), + response.rect, + ); + tree.drag_nodes(to_screen, ui, &mut response); + tree.draw(&painter, to_screen, &ui); + } + }) + } + + pub fn display_visualization(&mut self, ctx: &egui::Context) { + self.check_open(); + let syntaxTree = Window::new(format!("{}", self.box_title)); + let syntaxTree = syntaxTree.open(&mut self.is_win_open); + let syntaxTree = syntaxTree.scroll2([true, true]); + syntaxTree.show(ctx, |ui| { + Self::display_parameters(&mut self.display_parameters, ui); + Self::display_graph(&mut self.graph, self.display_parameters, ui); + }); + } } diff --git a/src/utils/graph.rs b/src/utils/graph.rs index 66a964a..0d0425b 100644 --- a/src/utils/graph.rs +++ b/src/utils/graph.rs @@ -9,6 +9,10 @@ pub type IndNode = usize; /// Index of a edge, this type makes soure that is returned by the graph pub type IndEdge = usize; +pub trait IntoGraph { + fn into_graph(&self) -> Graph; +} + pub struct Edge { // maybe label can be set to a generic type From 44d8903f96041a9e219cbf3a249dc0e6802480ec Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Tue, 20 Dec 2022 23:10:58 +0100 Subject: [PATCH 4/8] prova con srede, finata la ui --- Cargo.toml | 3 + src/automata/dfa.rs | 1 + src/automata/nfa.rs | 9 +- .../{from_string.rs => string_transform.rs} | 73 ++++---- src/automata/regular_expression.rs | 15 +- src/display/regular_language_gui.rs | 158 ++++++++++++++++-- src/display/visualizer.rs | 39 ++--- 7 files changed, 214 insertions(+), 84 deletions(-) rename src/automata/nfa/{from_string.rs => string_transform.rs} (73%) diff --git a/Cargo.toml b/Cargo.toml index 43c634f..d546dae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ eframe = "0.19.0" egui = "0.19.0" wasm-bindgen = "0.2.83" nom = "7.1.1" +serde = { version = "1.0.151", features = ["derive"] } +serde_yaml = "0.9.16" +serde_json = "1.0.91" diff --git a/src/automata/dfa.rs b/src/automata/dfa.rs index e1539cd..f9bd03d 100644 --- a/src/automata/dfa.rs +++ b/src/automata/dfa.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use crate::automata::NFA; use crate::automata::regular_expression as RE; +use crate::utils::IntoGraph; use crate::utils::{Graph, IndEdge, IndNode}; use crate::utils::DisjointUnionFind; diff --git a/src/automata/nfa.rs b/src/automata/nfa.rs index bc99056..f6dafb1 100644 --- a/src/automata/nfa.rs +++ b/src/automata/nfa.rs @@ -1,13 +1,15 @@ use log::info; use std::collections::{BTreeMap, BTreeSet}; +use serde::{Serialize, Deserialize}; + use crate::automata::regular_expression as RE; use crate::display::DisplayGraph; use crate::utils::{Graph, IntoGraph}; -mod from_string; +mod string_transform; -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct NFA { start_state: usize, num_states: usize, @@ -266,6 +268,7 @@ mod test { Box::new(RE::ReOperator::Char('b')), ); let nfa = NFA::from(®ex); - println!("{:?}", nfa); + let out = serde_json::to_string(&nfa); + panic!("{:?}\n", out.unwrap()); } } diff --git a/src/automata/nfa/from_string.rs b/src/automata/nfa/string_transform.rs similarity index 73% rename from src/automata/nfa/from_string.rs rename to src/automata/nfa/string_transform.rs index 4a579f6..c6b76db 100644 --- a/src/automata/nfa/from_string.rs +++ b/src/automata/nfa/string_transform.rs @@ -1,8 +1,8 @@ use std::collections::BTreeMap; - use super::NFA; +//TODO rifare tutto con strade use nom::{ bytes::complete::take, bytes::complete::take_while1, @@ -15,13 +15,12 @@ use nom::{ IResult, }; -fn decimal(input: &str) -> IResult<&str, &str> { - take_while1(move |c: char| c.is_digit(10))(input) -} +const START_STATE_LABEL:&str= "start_state"; +const NUM_STATE_LABEL:&str= "num_states"; +const END_STATES_LABEL:&str= "end_states"; +const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + -fn str_to_usize(input: &str) -> Result { - usize::from_str_radix(input, 10) -} fn read_num(input: &str) -> IResult<&str, usize> { map_res(digit1, |digit_str: &str| digit_str.parse::())(input) @@ -34,13 +33,12 @@ fn custom_label<'a>( } fn read_start_stete(input: &str) -> IResult<&str, usize> { - preceded(custom_label("start_state"), read_num)(input) + preceded(custom_label(START_STATE_LABEL), read_num)(input) } fn read_num_states(input: &str) -> IResult<&str, usize> { - preceded(custom_label("num_states"), read_num)(input) + preceded(custom_label(NUM_STATE_LABEL), read_num)(input) } -const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; fn read_char(input: &str) -> IResult<&str, char> { preceded( @@ -58,7 +56,7 @@ fn read_num_array(input: &str) -> IResult<&str, Vec> { } fn read_finish_states(input: &str) -> IResult<&str, Vec> { - preceded(custom_label("num_states"), read_num_array)(input) + preceded(custom_label(END_STATES_LABEL), read_num_array)(input) } fn read_transiction(input: &str) -> IResult<&str, (usize, usize, char)> { @@ -75,6 +73,7 @@ fn read_all_transictions(input: &str) -> IResult<&str, Vec<(usize, usize, char)> separated_list0(multispace0, read_transiction)(input) } + impl TryFrom<&str> for NFA { // TODO: maybe we can change it type Error = String; @@ -87,30 +86,31 @@ impl TryFrom<&str> for NFA { read_all_transictions, ))(value); - if let Ok((input, (start_state, end_states, num_states, all_transitions))) = out { - let mut transitions: Vec>> = - (0..num_states).map(|_| BTreeMap::new()).collect(); - for (from, to, ch) in all_transitions.into_iter() { - if from >= num_states { - return Err(String::from("from out of num_state")); - } else if to >= num_states { - return Err(String::from("to out of num_state")); - } else { - transitions[from] - .entry(ch) - .and_modify(|x| x.push(to)) - .or_insert(vec![to]); + match out { + Ok((_, (start_state, end_states, num_states, all_transitions))) => { + let mut transitions: Vec>> = + (0..num_states).map(|_| BTreeMap::new()).collect(); + for (from, to, ch) in all_transitions.into_iter() { + if from >= num_states { + return Err(String::from("from out of num_state")); + } else if to >= num_states { + return Err(String::from("to out of num_state")); + } else { + transitions[from] + .entry(ch) + .and_modify(|x| x.push(to)) + .or_insert(vec![to]); + } } + Ok(Self { + start_state, + num_states, + end_states, + transitions, + used_alphabet: ALPHABET.chars().collect(), + }) } - Ok(Self { - start_state, - num_states, - end_states, - transitions, - used_alphabet: ALPHABET.chars().collect(), - }) - } else { - Err(String::from("error while reading nfa")) + Err(e) => Err(e.to_string()), } } } @@ -122,7 +122,7 @@ mod test { #[test] fn string_to_nfa() { //todo - NFA::try_from(concat!( + if let Ok(_) = NFA::try_from(concat!( "start_state: 0\n", "finish_states: [ 2 ]\n", " num_states: 5\n", @@ -132,7 +132,10 @@ mod test { "3 -- 'a' --> 4\n", "4 ----> 3\n", "4 ----> 2\n" - )); + )) { + } else { + assert!(false); + } } #[test] diff --git a/src/automata/regular_expression.rs b/src/automata/regular_expression.rs index 53092b1..43ce44b 100644 --- a/src/automata/regular_expression.rs +++ b/src/automata/regular_expression.rs @@ -28,6 +28,14 @@ pub enum ReOperator { KleeneStar(Box), } +impl IntoGraph for ReOperator { + fn into_graph(&self) -> Graph { + let mut graph= Graph::new(); + self.build_recursive_graph(&mut graph); + graph + } +} + impl PartialEq for ReOperator { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -283,13 +291,6 @@ impl ReOperator { } } -impl IntoGraph for ReOperator { - fn into_graph(&self) -> Graph { - let mut graph= Graph::new(); - self.build_recursive_graph(&mut graph); - graph - } -} #[cfg(test)] mod test { diff --git a/src/display/regular_language_gui.rs b/src/display/regular_language_gui.rs index 8d2736a..4ca2759 100644 --- a/src/display/regular_language_gui.rs +++ b/src/display/regular_language_gui.rs @@ -1,16 +1,29 @@ use crate::automata::{NfaStates, ReOperator, DFA, NFA}; +use crate::display::DisplayGraph; +use crate::utils::IntoGraph; use egui::{Context, Ui}; use std::collections::VecDeque; use crate::display::Visualizer; -pub type RegularGrammarObjects = ( - Option, - Option, - Option>, - Option>, -); +pub struct RegularGrammarObjects { + regular_expression: Option, + nfa: Option, + dfa: Option>, + min_dfa: Option>, +} + +impl RegularGrammarObjects { + fn new() -> Self { + Self { + regular_expression: None, + nfa: None, + dfa: None, + min_dfa: None, + } + } +} pub struct RegularLanguageGui { object_copy: RegularGrammarObjects, @@ -24,16 +37,117 @@ impl RegularLanguageGui { fn get_regular_expression_visualizer() -> Visualizer { Visualizer::from_title_and_fromlist( "Regular Expression", - vec![|ui, reg, input,log| { + vec![|ui, reg, input, log| { ui.text_edit_singleline(input); - if ui.button("Regular Expression").click() { - match ReOperator::from_string(input.as_str()) { + if ui.button("Regular Expression").clicked() { + match ReOperator::from_string(input) { Ok(elem) => { - reg.0 = elem; - return elem.into(); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.regular_expression = Some(elem); + return Some(display_graph); + } + Err(_) => { + log.push_back(String::from("Impossibile creare la regular expression")); + } + }; + } + None + }], + ) + } + fn get_NFA_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist( + "NFA", + vec![ + |ui, reg, input, log| { + ui.text_edit_multiline(input); + if ui.button("From Input Text").clicked() { + match serde_json::from_str::(input.as_str()) { + Ok(elem) => { + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.nfa = Some(elem); + return Some(display_graph); + } + Err(e) => { + log.push_back(e.to_string()); + } + }; + } + if ui.button("Set Input Text As The Current NFA").clicked() { + match reg.nfa { + Some(ref nfa) => { + match serde_json::to_string(nfa) { + Ok(fr) => { + *input = String::from(fr); + } + Err(e) => { + log.push_back(e.to_string()); + } + }; + } + None => { + log.push_back(String::from("Nessun NFA è Settato")); + } } - Err(error) => { - log.push_back("Impossibile creare la regular expression"); + } + None + }, + |ui, reg, _, log| { + if ui.button("From Regular Expression").clicked() { + match ®.regular_expression { + Some(elem) => { + let elem=NFA::from(elem); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.nfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from( + "Try to visualize a regular Expression First", + )); + } + }; + } + None + }, + ], + ) + } + fn get_DFA_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist( + "DFA", + vec![|ui, reg, _, log| { + if ui.button("From NFA").clicked() { + match ®.nfa { + Some(elem) => { +let elem=DFA::from(elem); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.dfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from("Try to visualize a NFA first")); + } + }; + } + None + }], + ) + } + fn get_DFA_Minimized_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist( + "Minimized DFA", + vec![|ui, reg, _, log| { + if ui.button("From DFA").clicked() { + match ®.dfa { + Some(elem) => { + let elem=elem.get_minimized_dfa(); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.min_dfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from("Try to visualize a regular DFA")); } }; } @@ -45,15 +159,15 @@ impl RegularLanguageGui { fn get_visualizers() -> [Visualizer; 4] { [ Self::get_regular_expression_visualizer(), - Visualizer::from_title_and_fromlist("NFA", vec![]), - Visualizer::from_title_and_fromlist("DFA", vec![]), - Visualizer::from_title_and_fromlist("DFA Minimize", vec![]), + Self::get_NFA_visualizer(), + Self::get_DFA_visualizer(), + Self::get_DFA_Minimized_visualizer(), ] } pub fn new() -> Self { Self { - object_copy: (None, None, None, None), + object_copy: RegularGrammarObjects::new(), error_log: VecDeque::new(), visualizers: Self::get_visualizers(), } @@ -63,10 +177,19 @@ impl RegularLanguageGui { visualizer.display_visualization(ctx); } } + pub fn draw_left_panel(&mut self, ui: &mut Ui) { for visualizer in &mut self.visualizers { visualizer.display_left_panel_graphics(ui, &mut self.object_copy, &mut self.error_log); } + while self.error_log.len() > MAX_LOG_QUEUE { + self.error_log.pop_front(); + } + egui::ScrollArea::vertical().show(ui, |ui| { + for error in self.error_log.iter() { + ui.label(egui::RichText::new(error).color(egui::Color32::RED)); + } + }); } } @@ -97,4 +220,5 @@ impl RegularLanguageGui { // self.error = Some(e.to_string()); // } // }; +// ε\":[2,4]},{},{\"a\":[3]},{\"ε\":[1]},{\"b\":[5]},{\"ε\":[1]}],\"used_alphabet\":[\"a\",\"b\"]}" // } diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs index ee2c8d9..bea26b1 100644 --- a/src/display/visualizer.rs +++ b/src/display/visualizer.rs @@ -2,7 +2,7 @@ use std::collections::VecDeque; use egui::{emath, Frame, Pos2, Rect, Ui, Window}; -use crate::{display::DisplayGraph }; +use crate::display::DisplayGraph; use super::DisplayGraphParameter; use crate::display::RegularGrammarObjects; @@ -11,14 +11,12 @@ use crate::display::RegularGrammarObjects; /// it contains the information to show the window and display the graph // if Return a String it return an error -type FromFunction = Box< - dyn Fn( - &mut Ui, - &mut RegularGrammarObjects, - &mut String, - &mut VecDeque - ) -> Option, ->; +type FromFunction = fn( + &mut Ui, + &mut RegularGrammarObjects, + &mut String, + &mut VecDeque, +) -> Option; pub struct Visualizer { pub box_title: String, @@ -51,10 +49,11 @@ impl Visualizer { other_obj: &mut RegularGrammarObjects, error_log: &mut VecDeque, ) { - ui.heading(self.box_title); + ui.heading(self.box_title.clone()); for fun in self.from.iter() { - if let Some(res) = fun(ui, &mut other_obj, &mut self.from_input_string,&mut error_log) { + if let Some(res) = fun(ui, other_obj, &mut self.from_input_string, error_log) { self.graph = Some(res); + self.is_win_open = true; } } } @@ -68,11 +67,6 @@ impl Visualizer { } } - pub fn set_graph(&mut self, graph: DisplayGraph) { - self.graph = Some(graph); - self.is_win_open = true; - } - fn display_parameters(display_parameters: &mut DisplayGraphParameter, ui: &mut Ui) { let par = display_parameters; ui.collapsing(format!("visualizer option",), |ui| { @@ -83,23 +77,24 @@ impl Visualizer { } fn display_graph( - graph: &mut DisplayGraph, + graph: &mut Option, display_parameters: DisplayGraphParameter, ui: &mut Ui, ) { Frame::canvas(ui.style()).show(ui, |canvas_ui| { - if let Some(tree) = &mut graph { + if let Some(tree) = graph { let scren_size = tree.position(display_parameters); - let (mut response, painter) = ui.allocate_painter(scren_size, egui::Sense::hover()); + let (mut response, painter) = + canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); let to_screen = emath::RectTransform::from_to( Rect::from_min_size(Pos2::ZERO, response.rect.size()), response.rect, ); - tree.drag_nodes(to_screen, ui, &mut response); - tree.draw(&painter, to_screen, &ui); + tree.drag_nodes(to_screen, canvas_ui, &mut response); + tree.draw(&painter, to_screen, canvas_ui); } - }) + }); } pub fn display_visualization(&mut self, ctx: &egui::Context) { From ec321a6611a36a312edb87ab12fbdd8a291ceb96 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Sat, 24 Dec 2022 17:32:02 +0100 Subject: [PATCH 5/8] added comments, split files,and add self visualizator --- src/display/regular_language_gui.rs | 188 +++--------------- src/display/regular_language_gui/dfa.rs | 39 ++++ src/display/regular_language_gui/min_dfa.rs | 38 ++++ src/display/regular_language_gui/nfa.rs | 80 ++++++++ .../regular_expression.rs | 42 ++++ src/display/visualizer.rs | 2 +- 6 files changed, 225 insertions(+), 164 deletions(-) create mode 100644 src/display/regular_language_gui/dfa.rs create mode 100644 src/display/regular_language_gui/min_dfa.rs create mode 100644 src/display/regular_language_gui/nfa.rs create mode 100644 src/display/regular_language_gui/regular_expression.rs diff --git a/src/display/regular_language_gui.rs b/src/display/regular_language_gui.rs index 4ca2759..b6b5c4b 100644 --- a/src/display/regular_language_gui.rs +++ b/src/display/regular_language_gui.rs @@ -1,12 +1,22 @@ use crate::automata::{NfaStates, ReOperator, DFA, NFA}; -use crate::display::DisplayGraph; -use crate::utils::IntoGraph; use egui::{Context, Ui}; use std::collections::VecDeque; use crate::display::Visualizer; +mod dfa; +mod min_dfa; +mod nfa; +mod regular_expression; + +use dfa::get_DFA_visualizer; +use min_dfa::get_DFA_Minimized_visualizer; +use nfa::get_NFA_visualizer; +use regular_expression::get_regular_expression_visualizer; + +/// This struct contains re,nfa,dfa,min dfa (maybe in a funture a regular grammar), +/// so it store all the object diplayed so we can transform object to each other pub struct RegularGrammarObjects { regular_expression: Option, nfa: Option, @@ -25,6 +35,8 @@ impl RegularGrammarObjects { } } +/// It's the menu where you can modify the regular object conteinded in `RegularGrammarObjects` +/// and transoform each object to others pub struct RegularLanguageGui { object_copy: RegularGrammarObjects, error_log: VecDeque, @@ -34,142 +46,11 @@ pub struct RegularLanguageGui { const MAX_LOG_QUEUE: usize = 5; impl RegularLanguageGui { - fn get_regular_expression_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist( - "Regular Expression", - vec![|ui, reg, input, log| { - ui.text_edit_singleline(input); - if ui.button("Regular Expression").clicked() { - match ReOperator::from_string(input) { - Ok(elem) => { - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.regular_expression = Some(elem); - return Some(display_graph); - } - Err(_) => { - log.push_back(String::from("Impossibile creare la regular expression")); - } - }; - } - None - }], - ) - } - fn get_NFA_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist( - "NFA", - vec![ - |ui, reg, input, log| { - ui.text_edit_multiline(input); - if ui.button("From Input Text").clicked() { - match serde_json::from_str::(input.as_str()) { - Ok(elem) => { - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.nfa = Some(elem); - return Some(display_graph); - } - Err(e) => { - log.push_back(e.to_string()); - } - }; - } - if ui.button("Set Input Text As The Current NFA").clicked() { - match reg.nfa { - Some(ref nfa) => { - match serde_json::to_string(nfa) { - Ok(fr) => { - *input = String::from(fr); - } - Err(e) => { - log.push_back(e.to_string()); - } - }; - } - None => { - log.push_back(String::from("Nessun NFA è Settato")); - } - } - } - None - }, - |ui, reg, _, log| { - if ui.button("From Regular Expression").clicked() { - match ®.regular_expression { - Some(elem) => { - let elem=NFA::from(elem); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.nfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from( - "Try to visualize a regular Expression First", - )); - } - }; - } - None - }, - ], - ) - } - fn get_DFA_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist( - "DFA", - vec![|ui, reg, _, log| { - if ui.button("From NFA").clicked() { - match ®.nfa { - Some(elem) => { -let elem=DFA::from(elem); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.dfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from("Try to visualize a NFA first")); - } - }; - } - None - }], - ) - } - fn get_DFA_Minimized_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist( - "Minimized DFA", - vec![|ui, reg, _, log| { - if ui.button("From DFA").clicked() { - match ®.dfa { - Some(elem) => { - let elem=elem.get_minimized_dfa(); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.min_dfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from("Try to visualize a regular DFA")); - } - }; - } - None - }], - ) - } - - fn get_visualizers() -> [Visualizer; 4] { - [ - Self::get_regular_expression_visualizer(), - Self::get_NFA_visualizer(), - Self::get_DFA_visualizer(), - Self::get_DFA_Minimized_visualizer(), - ] - } - pub fn new() -> Self { Self { object_copy: RegularGrammarObjects::new(), error_log: VecDeque::new(), - visualizers: Self::get_visualizers(), + visualizers: get_visualizers(), } } pub fn draw_visualizer_windows(&mut self, ctx: &Context) { @@ -182,6 +63,8 @@ let elem=DFA::from(elem); for visualizer in &mut self.visualizers { visualizer.display_left_panel_graphics(ui, &mut self.object_copy, &mut self.error_log); } + + ui.label(format!("currently you have saved in memory: ")); while self.error_log.len() > MAX_LOG_QUEUE { self.error_log.pop_front(); } @@ -193,32 +76,11 @@ let elem=DFA::from(elem); } } -// -// -// pub fn get_converter(index: i32) -> impl Fn(ReOperator) -> Graph { -// match index { -// 0 => |re: ReOperator| re.into(), -// 1 => |re: ReOperator| NFA::from(&re).into(), -// 2 => |re: ReOperator| DFA::from(&NFA::from(&re)).into(), -// 3 => |re: ReOperator| DFA::from(&NFA::from(&re)).get_minimized_dfa().into(), -// _ => panic!("Invalid index"), -// } -// } - -// visualizer.display_left_panel_graphics(ui,); -// if ui -// .button(format!("Generate {}", visualizer.box_title)) -// .clicked() -// { -// match ReOperator::from_string(&self.regex_text) { -// Ok(re) => { -// visualizer.set_graph(Self::get_converter(index as i32)(re).into()); -// self.error = None; -// } - -// Err(e) => { -// self.error = Some(e.to_string()); -// } -// }; -// ε\":[2,4]},{},{\"a\":[3]},{\"ε\":[1]},{\"b\":[5]},{\"ε\":[1]}],\"used_alphabet\":[\"a\",\"b\"]}" -// } +fn get_visualizers() -> [Visualizer; 4] { + [ + get_regular_expression_visualizer(), + get_NFA_visualizer(), + get_DFA_visualizer(), + get_DFA_Minimized_visualizer(), + ] +} diff --git a/src/display/regular_language_gui/dfa.rs b/src/display/regular_language_gui/dfa.rs new file mode 100644 index 0000000..68575b1 --- /dev/null +++ b/src/display/regular_language_gui/dfa.rs @@ -0,0 +1,39 @@ +use crate::{ + automata::DFA, + display::{DisplayGraph, FromFunction, Visualizer}, + utils::IntoGraph, +}; + +pub fn get_DFA_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist("DFA", vec![visualize_self(), from_nfa()]) +} + +fn visualize_self() -> FromFunction { + |ui, grammar_objects, _, _| { + if let Some(reg) = &grammar_objects.dfa { + if ui.button("Visuzlize the last DFA Saved").clicked() { + return Some(DisplayGraph::from(reg.into_graph())); + } + } + None + } +} + +fn from_nfa() -> FromFunction { + |ui, reg, _, log| { + if ui.button("From NFA").clicked() { + match ®.nfa { + Some(elem) => { + let elem = DFA::from(elem); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.dfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from("Try to visualize a NFA first")); + } + }; + } + None + } +} diff --git a/src/display/regular_language_gui/min_dfa.rs b/src/display/regular_language_gui/min_dfa.rs new file mode 100644 index 0000000..fc0e3a8 --- /dev/null +++ b/src/display/regular_language_gui/min_dfa.rs @@ -0,0 +1,38 @@ +use crate::{ + display::{DisplayGraph, FromFunction, Visualizer}, + utils::IntoGraph, +}; + +pub fn get_DFA_Minimized_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist("Minimized DFA", vec![visualize_self(), from_dfa()]) +} + +fn visualize_self() -> FromFunction { + |ui, grammar_objects, _, _| { + if let Some(reg) = &grammar_objects.min_dfa { + if ui.button("Visuzlize the last Min DFA Saved").clicked() { + return Some(DisplayGraph::from(reg.into_graph())); + } + } + None + } +} + +fn from_dfa() -> FromFunction { + |ui, reg, _, log| { + if ui.button("From DFA").clicked() { + match ®.dfa { + Some(elem) => { + let elem = elem.get_minimized_dfa(); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.min_dfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from("Try to visualize a regular DFA")); + } + }; + } + None + } +} diff --git a/src/display/regular_language_gui/nfa.rs b/src/display/regular_language_gui/nfa.rs new file mode 100644 index 0000000..a301bc0 --- /dev/null +++ b/src/display/regular_language_gui/nfa.rs @@ -0,0 +1,80 @@ +use crate::{ + automata::NFA, + display::{DisplayGraph, FromFunction, Visualizer}, + utils::IntoGraph, +}; + +pub fn get_NFA_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist( + "NFA", + vec![ + visualize_self(), + from_input_text(), + from_regular_expression(), + ], + ) +} + +fn visualize_self() -> FromFunction { + |ui, grammar_objects, _, _| { + if let Some(reg) = &grammar_objects.nfa { + if ui.button("Visuzlize the last NFA Saved").clicked() { + return Some(DisplayGraph::from(reg.into_graph())); + } + } + None + } +} +fn from_regular_expression() -> FromFunction { + |ui, reg, _, log| { + if ui.button("From Regular Expression").clicked() { + match ®.regular_expression { + Some(elem) => { + let elem = NFA::from(elem); + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.nfa = Some(elem); + return Some(display_graph); + } + None => { + log.push_back(String::from("Try to visualize a regular Expression First")); + } + }; + } + None + } +} +fn from_input_text() -> FromFunction { + |ui, reg, input, log| { + ui.text_edit_multiline(input); + if ui.button("From Input Text").clicked() { + match serde_json::from_str::(input.as_str()) { + Ok(elem) => { + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.nfa = Some(elem); + return Some(display_graph); + } + Err(e) => { + log.push_back(e.to_string()); + } + }; + } + if ui.button("Set Input Text As The Current NFA").clicked() { + match reg.nfa { + Some(ref nfa) => { + match serde_json::to_string(nfa) { + Ok(fr) => { + *input = String::from(fr); + } + Err(e) => { + log.push_back(e.to_string()); + } + }; + } + None => { + log.push_back(String::from("Nessun NFA è Settato")); + } + } + } + None + } +} diff --git a/src/display/regular_language_gui/regular_expression.rs b/src/display/regular_language_gui/regular_expression.rs new file mode 100644 index 0000000..45dadfb --- /dev/null +++ b/src/display/regular_language_gui/regular_expression.rs @@ -0,0 +1,42 @@ +use crate::{ + automata::ReOperator, + display::{DisplayGraph, FromFunction, Visualizer}, + utils::IntoGraph, +}; + +pub fn get_regular_expression_visualizer() -> Visualizer { + Visualizer::from_title_and_fromlist("Regular Expression", vec![visualize_self(), from_input()]) +} + +fn visualize_self() -> FromFunction { + |ui, grammar_objects, _, _| { + if let Some(reg) = &grammar_objects.regular_expression { + if ui + .button("Visuzlize the last Regular Expression Saved") + .clicked() + { + return Some(DisplayGraph::from(reg.into_graph())); + } + } + None + } +} + +fn from_input() -> FromFunction { + |ui, reg, input, log| { + ui.text_edit_singleline(input); + if ui.button("Regular Expression").clicked() { + match ReOperator::from_string(input) { + Ok(elem) => { + let display_graph = DisplayGraph::from(elem.into_graph()); + reg.regular_expression = Some(elem); + return Some(display_graph); + } + Err(_) => { + log.push_back(String::from("Impossibile creare la regular expression")); + } + }; + } + None + } +} diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs index bea26b1..c7aa478 100644 --- a/src/display/visualizer.rs +++ b/src/display/visualizer.rs @@ -11,7 +11,7 @@ use crate::display::RegularGrammarObjects; /// it contains the information to show the window and display the graph // if Return a String it return an error -type FromFunction = fn( +pub type FromFunction = fn( &mut Ui, &mut RegularGrammarObjects, &mut String, From 74a5b1fe44d5d9184e01cf92ae53d6e93b230980 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Thu, 6 Apr 2023 15:37:13 +0200 Subject: [PATCH 6/8] sync computer --- src/app.rs | 25 +- src/automata/dfa.rs | 18 +- src/automata/nfa.rs | 6 +- src/automata/nfa/string_transform.rs | 12 +- src/display/mod.rs | 8 +- src/display/regular_gui.rs | 71 ++++++ src/display/regular_language_gui.rs | 86 ------- src/display/regular_language_gui/dfa.rs | 39 ---- src/display/regular_language_gui/min_dfa.rs | 38 ---- src/display/regular_language_gui/nfa.rs | 80 ------- .../regular_expression.rs | 42 ---- src/display/visualizer.rs | 215 +++++++++--------- 12 files changed, 211 insertions(+), 429 deletions(-) create mode 100644 src/display/regular_gui.rs delete mode 100644 src/display/regular_language_gui.rs delete mode 100644 src/display/regular_language_gui/dfa.rs delete mode 100644 src/display/regular_language_gui/min_dfa.rs delete mode 100644 src/display/regular_language_gui/nfa.rs delete mode 100644 src/display/regular_language_gui/regular_expression.rs diff --git a/src/app.rs b/src/app.rs index fae50e2..e2151d7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,19 +1,16 @@ use eframe::egui; -use egui::SidePanel; - -use crate::display::RegularLanguageGui; - +use egui::{CentralPanel, SidePanel}; +use crate::display::RegularGui; pub struct EguiApp { - leftpanel:RegularLanguageGui, + regular_gui: RegularGui, } impl Default for EguiApp { fn default() -> Self { Self { - leftpanel:RegularLanguageGui::new() - + regular_gui: RegularGui::new(), } } } @@ -22,15 +19,19 @@ impl EguiApp { pub fn new(_cc: &eframe::CreationContext) -> Self { Self::default() } - } - impl eframe::App for EguiApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - SidePanel::left("Main").show(ctx, |ui| { - self.leftpanel.draw_left_panel(ui); + SidePanel::left("Left").show(ctx, |ui| { + self.regular_gui.draw_left_panel(ui); + }); + SidePanel::right("Right").show(ctx, |ui| { + self.regular_gui.draw_right_panel(ui); + }); + + CentralPanel::default().show(ctx, |ui| { + self.regular_gui.center_panel(ui); }); - self.leftpanel.draw_visualizer_windows(ctx); } } diff --git a/src/automata/dfa.rs b/src/automata/dfa.rs index f9bd03d..c66ce3b 100644 --- a/src/automata/dfa.rs +++ b/src/automata/dfa.rs @@ -1,10 +1,10 @@ use std::collections::{BTreeMap, BTreeSet}; -use crate::automata::NFA; use crate::automata::regular_expression as RE; +use crate::automata::NFA; +use crate::utils::DisjointUnionFind; use crate::utils::IntoGraph; use crate::utils::{Graph, IndEdge, IndNode}; -use crate::utils::DisjointUnionFind; pub type NfaStates = BTreeSet; @@ -23,7 +23,7 @@ pub struct DFA { const INVALID_STATE: i32 = -1; impl DFA { - fn new() -> Self { + pub fn new() -> Self { Self { num_states: 0, start_state: 0, @@ -107,7 +107,7 @@ impl DFA { new_transitions[*idx].insert(*transition_ch, *head_to_idx.get(&dest_head).unwrap()); } } - + // create new end states, these should be unique let mut new_end_states = BTreeSet::new(); for end_state in self.end_states.iter() { @@ -118,7 +118,9 @@ impl DFA { Self { num_states, - start_state: *head_to_idx.get(&unequal_sets.find(self.start_state)).unwrap(), + start_state: *head_to_idx + .get(&unequal_sets.find(self.start_state)) + .unwrap(), end_states: new_end_states.into_iter().collect(), transitions: new_transitions, alphabet: self.alphabet.clone(), @@ -218,12 +220,14 @@ impl DFA { fn add_state(dfa: &mut DFA, states: T) -> usize { dfa.transitions.push(BTreeMap::new()); - if let Some(map) = &mut dfa.idx_to_data { map.insert(dfa.num_states, states); } else { dfa.idx_to_data = Some(BTreeMap::new()); - dfa.idx_to_data.as_mut().unwrap().insert(dfa.num_states, states); + dfa.idx_to_data + .as_mut() + .unwrap() + .insert(dfa.num_states, states); } dfa.num_states += 1; diff --git a/src/automata/nfa.rs b/src/automata/nfa.rs index f6dafb1..adbbb54 100644 --- a/src/automata/nfa.rs +++ b/src/automata/nfa.rs @@ -1,10 +1,8 @@ -use log::info; +use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet}; -use serde::{Serialize, Deserialize}; - use crate::automata::regular_expression as RE; -use crate::display::DisplayGraph; + use crate::utils::{Graph, IntoGraph}; mod string_transform; diff --git a/src/automata/nfa/string_transform.rs b/src/automata/nfa/string_transform.rs index c6b76db..3948cad 100644 --- a/src/automata/nfa/string_transform.rs +++ b/src/automata/nfa/string_transform.rs @@ -4,8 +4,6 @@ use super::NFA; //TODO rifare tutto con strade use nom::{ - bytes::complete::take, - bytes::complete::take_while1, bytes::streaming::tag, character::complete::{char, one_of}, character::complete::{digit1, multispace0}, @@ -15,13 +13,11 @@ use nom::{ IResult, }; -const START_STATE_LABEL:&str= "start_state"; -const NUM_STATE_LABEL:&str= "num_states"; -const END_STATES_LABEL:&str= "end_states"; +const START_STATE_LABEL: &str = "start_state"; +const NUM_STATE_LABEL: &str = "num_states"; +const END_STATES_LABEL: &str = "end_states"; const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - - fn read_num(input: &str) -> IResult<&str, usize> { map_res(digit1, |digit_str: &str| digit_str.parse::())(input) } @@ -39,7 +35,6 @@ fn read_num_states(input: &str) -> IResult<&str, usize> { preceded(custom_label(NUM_STATE_LABEL), read_num)(input) } - fn read_char(input: &str) -> IResult<&str, char> { preceded( multispace0, @@ -73,7 +68,6 @@ fn read_all_transictions(input: &str) -> IResult<&str, Vec<(usize, usize, char)> separated_list0(multispace0, read_transiction)(input) } - impl TryFrom<&str> for NFA { // TODO: maybe we can change it type Error = String; diff --git a/src/display/mod.rs b/src/display/mod.rs index 46d771b..1b85dbd 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,7 +1,7 @@ mod display_graph; -mod visualizer; -mod regular_language_gui; +mod regular_gui; +// mod visualizer; -pub use regular_language_gui::*; pub use display_graph::*; -pub use visualizer::*; +pub use regular_gui::*; +// pub use visualizer::*; diff --git a/src/display/regular_gui.rs b/src/display/regular_gui.rs new file mode 100644 index 0000000..0e26ccf --- /dev/null +++ b/src/display/regular_gui.rs @@ -0,0 +1,71 @@ +use egui::{Response, Ui}; + +use crate::automata::{NfaStates, ReOperator, DFA, NFA}; + +pub struct RegularGui { + dfa: Vec<(String, DFA)>, + nfa: Vec<(String, NFA)>, + regex: Vec<(String, ReOperator)>, + current_workspace: CurrentWorkspace, + object_created: i32, +} + +enum CurrentWorkspace { + NFA(NFA), + DFA(DFA), + REGEX(ReOperator), +} + +impl RegularGui { + pub fn new() -> Self { + return RegularGui { + dfa: Vec::new(), + nfa: Vec::new(), + regex: Vec::new(), + current_workspace: CurrentWorkspace::REGEX(ReOperator::Char('a')), + object_created: 0, + }; + } + + pub fn draw_left_panel(&mut self, ui: &mut Ui) {} + + pub fn center_panel(&mut self, ui: &mut Ui) {} + + pub fn draw_right_panel(&mut self, ui: &mut Ui) { + ui.heading("ReOperator"); + if ui.button("New").clicked() { + self.regex.push(( + String::from("Regex ") + self.object_created.to_string().as_str(), + ReOperator::Char('a'), + )); + self.object_created += 1; + } + + self.regex.iter_mut().for_each(|(s, _obj)| { + Self::gen_snapshot_row( + ui, + s, + || {}, + |ui| { + if ui.button("Open...").clicked() { + ui.close_menu(); + } + }, + ) + }); + } + + fn gen_snapshot_row(ui: &mut Ui, title: &mut String, load: F1, menu_fun: F2) + where + F1: Fn(), + F2: FnOnce(&mut Ui), + { + ui.horizontal(|ui| { + ui.add(egui::TextEdit::singleline(title).desired_width(120.0)); + if ui.button("load").clicked() { + load(); + } + ui.button("⋮").menu_button(menu_fun); + }); + } +} diff --git a/src/display/regular_language_gui.rs b/src/display/regular_language_gui.rs deleted file mode 100644 index b6b5c4b..0000000 --- a/src/display/regular_language_gui.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::automata::{NfaStates, ReOperator, DFA, NFA}; -use egui::{Context, Ui}; - -use std::collections::VecDeque; - -use crate::display::Visualizer; - -mod dfa; -mod min_dfa; -mod nfa; -mod regular_expression; - -use dfa::get_DFA_visualizer; -use min_dfa::get_DFA_Minimized_visualizer; -use nfa::get_NFA_visualizer; -use regular_expression::get_regular_expression_visualizer; - -/// This struct contains re,nfa,dfa,min dfa (maybe in a funture a regular grammar), -/// so it store all the object diplayed so we can transform object to each other -pub struct RegularGrammarObjects { - regular_expression: Option, - nfa: Option, - dfa: Option>, - min_dfa: Option>, -} - -impl RegularGrammarObjects { - fn new() -> Self { - Self { - regular_expression: None, - nfa: None, - dfa: None, - min_dfa: None, - } - } -} - -/// It's the menu where you can modify the regular object conteinded in `RegularGrammarObjects` -/// and transoform each object to others -pub struct RegularLanguageGui { - object_copy: RegularGrammarObjects, - error_log: VecDeque, - visualizers: [Visualizer; 4], -} - -const MAX_LOG_QUEUE: usize = 5; - -impl RegularLanguageGui { - pub fn new() -> Self { - Self { - object_copy: RegularGrammarObjects::new(), - error_log: VecDeque::new(), - visualizers: get_visualizers(), - } - } - pub fn draw_visualizer_windows(&mut self, ctx: &Context) { - for visualizer in &mut self.visualizers { - visualizer.display_visualization(ctx); - } - } - - pub fn draw_left_panel(&mut self, ui: &mut Ui) { - for visualizer in &mut self.visualizers { - visualizer.display_left_panel_graphics(ui, &mut self.object_copy, &mut self.error_log); - } - - ui.label(format!("currently you have saved in memory: ")); - while self.error_log.len() > MAX_LOG_QUEUE { - self.error_log.pop_front(); - } - egui::ScrollArea::vertical().show(ui, |ui| { - for error in self.error_log.iter() { - ui.label(egui::RichText::new(error).color(egui::Color32::RED)); - } - }); - } -} - -fn get_visualizers() -> [Visualizer; 4] { - [ - get_regular_expression_visualizer(), - get_NFA_visualizer(), - get_DFA_visualizer(), - get_DFA_Minimized_visualizer(), - ] -} diff --git a/src/display/regular_language_gui/dfa.rs b/src/display/regular_language_gui/dfa.rs deleted file mode 100644 index 68575b1..0000000 --- a/src/display/regular_language_gui/dfa.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{ - automata::DFA, - display::{DisplayGraph, FromFunction, Visualizer}, - utils::IntoGraph, -}; - -pub fn get_DFA_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist("DFA", vec![visualize_self(), from_nfa()]) -} - -fn visualize_self() -> FromFunction { - |ui, grammar_objects, _, _| { - if let Some(reg) = &grammar_objects.dfa { - if ui.button("Visuzlize the last DFA Saved").clicked() { - return Some(DisplayGraph::from(reg.into_graph())); - } - } - None - } -} - -fn from_nfa() -> FromFunction { - |ui, reg, _, log| { - if ui.button("From NFA").clicked() { - match ®.nfa { - Some(elem) => { - let elem = DFA::from(elem); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.dfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from("Try to visualize a NFA first")); - } - }; - } - None - } -} diff --git a/src/display/regular_language_gui/min_dfa.rs b/src/display/regular_language_gui/min_dfa.rs deleted file mode 100644 index fc0e3a8..0000000 --- a/src/display/regular_language_gui/min_dfa.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::{ - display::{DisplayGraph, FromFunction, Visualizer}, - utils::IntoGraph, -}; - -pub fn get_DFA_Minimized_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist("Minimized DFA", vec![visualize_self(), from_dfa()]) -} - -fn visualize_self() -> FromFunction { - |ui, grammar_objects, _, _| { - if let Some(reg) = &grammar_objects.min_dfa { - if ui.button("Visuzlize the last Min DFA Saved").clicked() { - return Some(DisplayGraph::from(reg.into_graph())); - } - } - None - } -} - -fn from_dfa() -> FromFunction { - |ui, reg, _, log| { - if ui.button("From DFA").clicked() { - match ®.dfa { - Some(elem) => { - let elem = elem.get_minimized_dfa(); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.min_dfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from("Try to visualize a regular DFA")); - } - }; - } - None - } -} diff --git a/src/display/regular_language_gui/nfa.rs b/src/display/regular_language_gui/nfa.rs deleted file mode 100644 index a301bc0..0000000 --- a/src/display/regular_language_gui/nfa.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::{ - automata::NFA, - display::{DisplayGraph, FromFunction, Visualizer}, - utils::IntoGraph, -}; - -pub fn get_NFA_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist( - "NFA", - vec![ - visualize_self(), - from_input_text(), - from_regular_expression(), - ], - ) -} - -fn visualize_self() -> FromFunction { - |ui, grammar_objects, _, _| { - if let Some(reg) = &grammar_objects.nfa { - if ui.button("Visuzlize the last NFA Saved").clicked() { - return Some(DisplayGraph::from(reg.into_graph())); - } - } - None - } -} -fn from_regular_expression() -> FromFunction { - |ui, reg, _, log| { - if ui.button("From Regular Expression").clicked() { - match ®.regular_expression { - Some(elem) => { - let elem = NFA::from(elem); - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.nfa = Some(elem); - return Some(display_graph); - } - None => { - log.push_back(String::from("Try to visualize a regular Expression First")); - } - }; - } - None - } -} -fn from_input_text() -> FromFunction { - |ui, reg, input, log| { - ui.text_edit_multiline(input); - if ui.button("From Input Text").clicked() { - match serde_json::from_str::(input.as_str()) { - Ok(elem) => { - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.nfa = Some(elem); - return Some(display_graph); - } - Err(e) => { - log.push_back(e.to_string()); - } - }; - } - if ui.button("Set Input Text As The Current NFA").clicked() { - match reg.nfa { - Some(ref nfa) => { - match serde_json::to_string(nfa) { - Ok(fr) => { - *input = String::from(fr); - } - Err(e) => { - log.push_back(e.to_string()); - } - }; - } - None => { - log.push_back(String::from("Nessun NFA è Settato")); - } - } - } - None - } -} diff --git a/src/display/regular_language_gui/regular_expression.rs b/src/display/regular_language_gui/regular_expression.rs deleted file mode 100644 index 45dadfb..0000000 --- a/src/display/regular_language_gui/regular_expression.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::{ - automata::ReOperator, - display::{DisplayGraph, FromFunction, Visualizer}, - utils::IntoGraph, -}; - -pub fn get_regular_expression_visualizer() -> Visualizer { - Visualizer::from_title_and_fromlist("Regular Expression", vec![visualize_self(), from_input()]) -} - -fn visualize_self() -> FromFunction { - |ui, grammar_objects, _, _| { - if let Some(reg) = &grammar_objects.regular_expression { - if ui - .button("Visuzlize the last Regular Expression Saved") - .clicked() - { - return Some(DisplayGraph::from(reg.into_graph())); - } - } - None - } -} - -fn from_input() -> FromFunction { - |ui, reg, input, log| { - ui.text_edit_singleline(input); - if ui.button("Regular Expression").clicked() { - match ReOperator::from_string(input) { - Ok(elem) => { - let display_graph = DisplayGraph::from(elem.into_graph()); - reg.regular_expression = Some(elem); - return Some(display_graph); - } - Err(_) => { - log.push_back(String::from("Impossibile creare la regular expression")); - } - }; - } - None - } -} diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs index c7aa478..bcce4cb 100644 --- a/src/display/visualizer.rs +++ b/src/display/visualizer.rs @@ -1,110 +1,109 @@ -use std::collections::VecDeque; - -use egui::{emath, Frame, Pos2, Rect, Ui, Window}; - -use crate::display::DisplayGraph; - -use super::DisplayGraphParameter; -use crate::display::RegularGrammarObjects; - -/// this struct rappresent a visualizer of a graph -/// it contains the information to show the window and display the graph +// use std::collections::VecDeque; +// +// use egui::{emath, Frame, Pos2, Rect, Ui, Window}; +// +// use crate::display::DisplayGraph; +// +// use super::DisplayGraphParameter; +// /// this struct rappresent a visualizer of a graph +// /// it contains the information to show the window and display the graph +// // if Return a String it return an error -pub type FromFunction = fn( - &mut Ui, - &mut RegularGrammarObjects, - &mut String, - &mut VecDeque, -) -> Option; - -pub struct Visualizer { - pub box_title: String, - pub graph: Option, - pub display_parameters: DisplayGraphParameter, - pub is_win_open: bool, - pub from: Vec, - pub from_input_string: String, -} - -impl Visualizer { - pub fn from_title_and_fromlist(box_title: &str, from_list: Vec) -> Self { - Self { - box_title: String::from(box_title), - is_win_open: false, - display_parameters: DisplayGraphParameter { - padding_x: 40., - padding_y: 40., - node_size: 30., - }, - graph: None, - from: from_list, - from_input_string: String::new(), - } - } - - pub fn display_left_panel_graphics( - &mut self, - ui: &mut Ui, - other_obj: &mut RegularGrammarObjects, - error_log: &mut VecDeque, - ) { - ui.heading(self.box_title.clone()); - for fun in self.from.iter() { - if let Some(res) = fun(ui, other_obj, &mut self.from_input_string, error_log) { - self.graph = Some(res); - self.is_win_open = true; - } - } - } - - pub fn check_open(&mut self) { - if let None = self.graph { - self.is_win_open = false; - } - if !self.is_win_open { - self.graph = None; - } - } - - fn display_parameters(display_parameters: &mut DisplayGraphParameter, ui: &mut Ui) { - let par = display_parameters; - ui.collapsing(format!("visualizer option",), |ui| { - ui.add(egui::Slider::new(&mut par.padding_x, 10.0..=100.0).text("padding x")); - ui.add(egui::Slider::new(&mut par.padding_y, 10.0..=100.0).text("padding y")); - ui.add(egui::Slider::new(&mut par.node_size, 10.0..=100.0).text("node size")); - }); - } - - fn display_graph( - graph: &mut Option, - display_parameters: DisplayGraphParameter, - ui: &mut Ui, - ) { - Frame::canvas(ui.style()).show(ui, |canvas_ui| { - if let Some(tree) = graph { - let scren_size = tree.position(display_parameters); - let (mut response, painter) = - canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); - - let to_screen = emath::RectTransform::from_to( - Rect::from_min_size(Pos2::ZERO, response.rect.size()), - response.rect, - ); - tree.drag_nodes(to_screen, canvas_ui, &mut response); - tree.draw(&painter, to_screen, canvas_ui); - } - }); - } - - pub fn display_visualization(&mut self, ctx: &egui::Context) { - self.check_open(); - let syntaxTree = Window::new(format!("{}", self.box_title)); - let syntaxTree = syntaxTree.open(&mut self.is_win_open); - let syntaxTree = syntaxTree.scroll2([true, true]); - syntaxTree.show(ctx, |ui| { - Self::display_parameters(&mut self.display_parameters, ui); - Self::display_graph(&mut self.graph, self.display_parameters, ui); - }); - } -} +// pub type FromFunction = fn( +// &mut Ui, +// &mut RegularGrammarObjects, +// &mut String, +// &mut VecDeque, +// ) -> Option; +// +// pub struct Visualizer { +// pub box_title: String, +// pub graph: Option, +// pub display_parameters: DisplayGraphParameter, +// pub is_win_open: bool, +// pub from: Vec, +// pub from_input_string: String, +// } +// +// impl Visualizer { +// pub fn from_title_and_fromlist(box_title: &str, from_list: Vec) -> Self { +// Self { +// box_title: String::from(box_title), +// is_win_open: false, +// display_parameters: DisplayGraphParameter { +// padding_x: 40., +// padding_y: 40., +// node_size: 30., +// }, +// graph: None, +// from: from_list, +// from_input_string: String::new(), +// } +// } +// +// pub fn display_left_panel_graphics( +// &mut self, +// ui: &mut Ui, +// other_obj: &mut RegularGrammarObjects, +// error_log: &mut VecDeque, +// ) { +// ui.heading(self.box_title.clone()); +// for fun in self.from.iter() { +// if let Some(res) = fun(ui, other_obj, &mut self.from_input_string, error_log) { +// self.graph = Some(res); +// self.is_win_open = true; +// } +// } +// } +// +// pub fn check_open(&mut self) { +// if let None = self.graph { +// self.is_win_open = false; +// } +// if !self.is_win_open { +// self.graph = None; +// } +// } +// +// fn display_parameters(display_parameters: &mut DisplayGraphParameter, ui: &mut Ui) { +// let par = display_parameters; +// ui.collapsing(format!("visualizer option",), |ui| { +// ui.add(egui::Slider::new(&mut par.padding_x, 10.0..=100.0).text("padding x")); +// ui.add(egui::Slider::new(&mut par.padding_y, 10.0..=100.0).text("padding y")); +// ui.add(egui::Slider::new(&mut par.node_size, 10.0..=100.0).text("node size")); +// }); +// } +// +// fn display_graph( +// graph: &mut Option, +// display_parameters: DisplayGraphParameter, +// ui: &mut Ui, +// ) { +// Frame::canvas(ui.style()).show(ui, |canvas_ui| { +// if let Some(tree) = graph { +// let scren_size = tree.position(display_parameters); +// let (mut response, painter) = +// canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); +// +// let to_screen = emath::RectTransform::from_to( +// Rect::from_min_size(Pos2::ZERO, response.rect.size()), +// response.rect, +// ); +// tree.drag_nodes(to_screen, canvas_ui, &mut response); +// tree.draw(&painter, to_screen, canvas_ui); +// } +// }); +// } +// +// pub fn display_visualization(&mut self, ctx: &egui::Context) { +// self.check_open(); +// let syntaxTree = Window::new(format!("{}", self.box_title)); +// let syntaxTree = syntaxTree.open(&mut self.is_win_open); +// let syntaxTree = syntaxTree.scroll2([true, true]); +// syntaxTree.show(ctx, |ui| { +// Self::display_parameters(&mut self.display_parameters, ui); +// Self::display_graph(&mut self.graph, self.display_parameters, ui); +// }); +// } +// } From cca478ff06719797920235d54d1a220713c55950 Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Thu, 6 Apr 2023 17:47:07 +0200 Subject: [PATCH 7/8] finished right side bar --- src/automata/nfa.rs | 2 +- src/display/display_graph.rs | 5 -- src/display/regular_gui.rs | 106 +++++++++++++++++++++++++++++------ src/display/visualizer.rs | 4 +- src/utils/graph.rs | 1 - 5 files changed, 92 insertions(+), 26 deletions(-) diff --git a/src/automata/nfa.rs b/src/automata/nfa.rs index adbbb54..4bd3c5f 100644 --- a/src/automata/nfa.rs +++ b/src/automata/nfa.rs @@ -20,7 +20,7 @@ pub struct NFA { } impl NFA { - fn new() -> Self { + pub fn new() -> Self { Self { num_states: 0, start_state: 0, diff --git a/src/display/display_graph.rs b/src/display/display_graph.rs index 4315277..7f62bb7 100644 --- a/src/display/display_graph.rs +++ b/src/display/display_graph.rs @@ -13,7 +13,6 @@ const COLOR_NODES: Color32 = Color32::WHITE; const COLOR_LABEL_EDGE: Color32 = Color32::GRAY; const COLOR_LABEL_NODE: Color32 = Color32::BLACK; - /// Rapresent the edges types pub enum EdgeType { /// the edge point to it's self @@ -190,8 +189,6 @@ impl DisplayGraph { painter.line_segment([tip, tip + tip_length * (rot.inverse() * dir)], stroke); } - - //TODO refactor for legibilities fn draw_edge_and_get_label_pos( &self, @@ -344,10 +341,8 @@ impl DisplayGraph { } } - pub fn draw(&self, painter: &egui::Painter, to_screen: RectTransform, ui: &egui::Ui) { self.draw_edge(painter, to_screen, ui); self.draw_nodes(painter, to_screen, ui); } } - diff --git a/src/display/regular_gui.rs b/src/display/regular_gui.rs index 0e26ccf..2566a69 100644 --- a/src/display/regular_gui.rs +++ b/src/display/regular_gui.rs @@ -1,7 +1,11 @@ -use egui::{Response, Ui}; +use egui::{emath, Frame, Pos2, Rect, Ui}; use crate::automata::{NfaStates, ReOperator, DFA, NFA}; +use crate::utils::{Graph, IntoGraph}; + +use super::{DisplayGraph, DisplayGraphParameter}; + pub struct RegularGui { dfa: Vec<(String, DFA)>, nfa: Vec<(String, NFA)>, @@ -29,9 +33,92 @@ impl RegularGui { pub fn draw_left_panel(&mut self, ui: &mut Ui) {} - pub fn center_panel(&mut self, ui: &mut Ui) {} + pub fn center_panel(&mut self, ui: &mut Ui) { + let tree: Graph = match &self.current_workspace { + CurrentWorkspace::NFA(nfa) => nfa.into_graph(), + CurrentWorkspace::DFA(dfa) => dfa.into_graph(), + CurrentWorkspace::REGEX(re) => re.into_graph(), + }; + let mut tree: DisplayGraph = tree.into(); + Frame::canvas(ui.style()).show(ui, |canvas_ui| { + let scren_size = tree.position(DisplayGraphParameter { + padding_x: 40., + padding_y: 40., + node_size: 30., + }); + let (mut response, painter) = + canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); + + let to_screen = emath::RectTransform::from_to( + Rect::from_min_size(Pos2::ZERO, response.rect.size()), + response.rect, + ); + tree.drag_nodes(to_screen, canvas_ui, &mut response); + tree.draw(&painter, to_screen, canvas_ui); + }); + } pub fn draw_right_panel(&mut self, ui: &mut Ui) { + self.draw_re_operator_menu(ui); + self.draw_nfa_menu(ui); + self.draw_dfa_menu(ui); + } + + fn gen_snapshot_row(ui: &mut Ui, title: &mut String, load: F1, menu_fun: F2) + where + F1: Fn(), + F2: FnOnce(&mut Ui), + { + ui.horizontal(|ui| { + ui.add(egui::TextEdit::singleline(title).desired_width(120.0)); + ui.menu_button("Option", menu_fun); + if ui.button("load").clicked() { + load(); + } + }); + } + + fn draw_nfa_menu(&mut self, ui: &mut Ui) { + ui.heading("NFA"); + if ui.button("New").clicked() { + self.nfa.push(( + String::from("NFA ") + self.object_created.to_string().as_str(), + NFA::new(), + )); + self.object_created += 1; + } + self.nfa.iter_mut().for_each(|(s, _obj)| { + Self::gen_snapshot_row( + ui, + s, + || {}, + |ui| { + if ui.button("Open...").clicked() { + ui.close_menu(); + } + }, + ) + }); + } + fn draw_dfa_menu(&mut self, ui: &mut Ui) { + ui.heading("DFA"); + if ui.button("New").clicked() { + self.object_created += 1; + } + self.dfa.iter_mut().for_each(|(s, _obj)| { + Self::gen_snapshot_row( + ui, + s, + || {}, + |ui| { + if ui.button("Open...").clicked() { + ui.close_menu(); + } + }, + ) + }); + } + fn draw_re_operator_menu(&mut self, ui: &mut Ui) { ui.heading("ReOperator"); if ui.button("New").clicked() { self.regex.push(( @@ -40,7 +127,6 @@ impl RegularGui { )); self.object_created += 1; } - self.regex.iter_mut().for_each(|(s, _obj)| { Self::gen_snapshot_row( ui, @@ -54,18 +140,4 @@ impl RegularGui { ) }); } - - fn gen_snapshot_row(ui: &mut Ui, title: &mut String, load: F1, menu_fun: F2) - where - F1: Fn(), - F2: FnOnce(&mut Ui), - { - ui.horizontal(|ui| { - ui.add(egui::TextEdit::singleline(title).desired_width(120.0)); - if ui.button("load").clicked() { - load(); - } - ui.button("⋮").menu_button(menu_fun); - }); - } } diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs index bcce4cb..399aecb 100644 --- a/src/display/visualizer.rs +++ b/src/display/visualizer.rs @@ -5,11 +5,11 @@ // use crate::display::DisplayGraph; // // use super::DisplayGraphParameter; - +// // /// this struct rappresent a visualizer of a graph // /// it contains the information to show the window and display the graph // -// if Return a String it return an error +// /// if Return a String it return an error // pub type FromFunction = fn( // &mut Ui, // &mut RegularGrammarObjects, diff --git a/src/utils/graph.rs b/src/utils/graph.rs index 0d0425b..c9b70a3 100644 --- a/src/utils/graph.rs +++ b/src/utils/graph.rs @@ -13,7 +13,6 @@ pub trait IntoGraph { fn into_graph(&self) -> Graph; } - pub struct Edge { // maybe label can be set to a generic type pub id: IndEdge, From 3173320a417712f4c7d9e2af50fc64a80e2635cf Mon Sep 17 00:00:00 2001 From: Giovanni Spadaccini Date: Fri, 7 Apr 2023 22:43:54 +0200 Subject: [PATCH 8/8] added the visualizer graph, and parameter --- src/app.rs | 6 +- src/display/display_graph.rs | 8 ++- src/display/input_gui.rs | 9 +++ src/display/regular_gui.rs | 59 ++++++++++++++----- src/display/visualizer.rs | 109 ----------------------------------- 5 files changed, 61 insertions(+), 130 deletions(-) create mode 100644 src/display/input_gui.rs delete mode 100644 src/display/visualizer.rs diff --git a/src/app.rs b/src/app.rs index e2151d7..2104f8d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,5 @@ use eframe::egui; -use egui::{CentralPanel, SidePanel}; +use egui::{panel::TopBottomSide, CentralPanel, SidePanel, TopBottomPanel}; use crate::display::RegularGui; @@ -29,7 +29,9 @@ impl eframe::App for EguiApp { SidePanel::right("Right").show(ctx, |ui| { self.regular_gui.draw_right_panel(ui); }); - + TopBottomPanel::bottom("Visualizer").show(ctx, |ui| { + self.regular_gui.draw_bottom_panel(ui); + }); CentralPanel::default().show(ctx, |ui| { self.regular_gui.center_panel(ui); }); diff --git a/src/display/display_graph.rs b/src/display/display_graph.rs index 7f62bb7..a363722 100644 --- a/src/display/display_graph.rs +++ b/src/display/display_graph.rs @@ -4,7 +4,7 @@ use egui::{ emath::RectTransform, epaint::CubicBezierShape, Color32, Painter, Pos2, Rect, Sense, Stroke, Vec2, }; -use std::collections::BTreeMap; +use std::{cmp::max, collections::BTreeMap}; const ARROW_TIP_LENGHT: f32 = 10.; const ARROW_WIDTH: f32 = 3.; @@ -39,6 +39,7 @@ pub struct DisplayGraphParameter { pub padding_x: f32, pub padding_y: f32, pub node_size: f32, + pub canvas_size: Vec2, // we can add more parameters here as we need them or like the color of node edge etc.. } @@ -48,6 +49,7 @@ impl DisplayGraphParameter { padding_x: -1., padding_y: -1., node_size: -1., + canvas_size: Vec2::new(0., 0.), } } } @@ -118,8 +120,8 @@ impl DisplayGraph { bfs_depth as f32 * (params.node_size + params.padding_y) + params.padding_y; Vec2 { - x: width_painting_area, - y: height_painting_area, + x: width_painting_area.max(params.canvas_size.x), + y: height_painting_area.max(params.canvas_size.y), } } diff --git a/src/display/input_gui.rs b/src/display/input_gui.rs new file mode 100644 index 0000000..41abbd3 --- /dev/null +++ b/src/display/input_gui.rs @@ -0,0 +1,9 @@ +pub enum InputGui { + NFA(), + DFA(), + REGEX(), +} + +impl InputGui { + pub fn from() {} +} diff --git a/src/display/regular_gui.rs b/src/display/regular_gui.rs index 2566a69..1cd9687 100644 --- a/src/display/regular_gui.rs +++ b/src/display/regular_gui.rs @@ -1,4 +1,4 @@ -use egui::{emath, Frame, Pos2, Rect, Ui}; +use egui::{emath, Frame, Pos2, Rect, Ui, Vec2}; use crate::automata::{NfaStates, ReOperator, DFA, NFA}; @@ -12,6 +12,9 @@ pub struct RegularGui { regex: Vec<(String, ReOperator)>, current_workspace: CurrentWorkspace, object_created: i32, + display_graph: Option, + display_params: DisplayGraphParameter, + input_gui: InputGui, } enum CurrentWorkspace { @@ -28,26 +31,50 @@ impl RegularGui { regex: Vec::new(), current_workspace: CurrentWorkspace::REGEX(ReOperator::Char('a')), object_created: 0, + display_graph: None, + display_params: DisplayGraphParameter { + padding_x: 40., + padding_y: 40., + node_size: 30., + canvas_size: Vec2::new(0., 0.), + }, }; } pub fn draw_left_panel(&mut self, ui: &mut Ui) {} - pub fn center_panel(&mut self, ui: &mut Ui) { - let tree: Graph = match &self.current_workspace { - CurrentWorkspace::NFA(nfa) => nfa.into_graph(), - CurrentWorkspace::DFA(dfa) => dfa.into_graph(), - CurrentWorkspace::REGEX(re) => re.into_graph(), - }; - let mut tree: DisplayGraph = tree.into(); - Frame::canvas(ui.style()).show(ui, |canvas_ui| { - let scren_size = tree.position(DisplayGraphParameter { - padding_x: 40., - padding_y: 40., - node_size: 30., - }); + pub fn draw_bottom_panel(&mut self, ui: &mut Ui) { + ui.heading("Visualizer Parameter"); + + ui.add( + egui::Slider::new(&mut self.display_params.padding_x, 10.0..=200.0).text("padding x"), + ); + ui.add( + egui::Slider::new(&mut self.display_params.padding_y, 10.0..=200.0).text("padding y"), + ); + ui.add( + egui::Slider::new(&mut self.display_params.node_size, 10.0..=200.0).text("node size"), + ); + if ui.button("Reset").clicked() { + self.display_graph = None; + } + } + + pub fn center_panel(&mut self, canvas_ui: &mut Ui) { + if let None = self.display_graph { + let tree: Graph = match &self.current_workspace { + CurrentWorkspace::NFA(nfa) => nfa.into_graph(), + CurrentWorkspace::DFA(dfa) => dfa.into_graph(), + CurrentWorkspace::REGEX(re) => re.into_graph(), + }; + let tree: DisplayGraph = tree.into(); + self.display_graph = Some(tree); + } + if let Some(tree) = &mut self.display_graph { + self.display_params.canvas_size = canvas_ui.available_size(); + let screen_size = tree.position(self.display_params.clone()); let (mut response, painter) = - canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); + canvas_ui.allocate_painter(screen_size, egui::Sense::hover()); let to_screen = emath::RectTransform::from_to( Rect::from_min_size(Pos2::ZERO, response.rect.size()), @@ -55,7 +82,7 @@ impl RegularGui { ); tree.drag_nodes(to_screen, canvas_ui, &mut response); tree.draw(&painter, to_screen, canvas_ui); - }); + } } pub fn draw_right_panel(&mut self, ui: &mut Ui) { diff --git a/src/display/visualizer.rs b/src/display/visualizer.rs deleted file mode 100644 index 399aecb..0000000 --- a/src/display/visualizer.rs +++ /dev/null @@ -1,109 +0,0 @@ -// use std::collections::VecDeque; -// -// use egui::{emath, Frame, Pos2, Rect, Ui, Window}; -// -// use crate::display::DisplayGraph; -// -// use super::DisplayGraphParameter; -// -// /// this struct rappresent a visualizer of a graph -// /// it contains the information to show the window and display the graph -// -// /// if Return a String it return an error -// pub type FromFunction = fn( -// &mut Ui, -// &mut RegularGrammarObjects, -// &mut String, -// &mut VecDeque, -// ) -> Option; -// -// pub struct Visualizer { -// pub box_title: String, -// pub graph: Option, -// pub display_parameters: DisplayGraphParameter, -// pub is_win_open: bool, -// pub from: Vec, -// pub from_input_string: String, -// } -// -// impl Visualizer { -// pub fn from_title_and_fromlist(box_title: &str, from_list: Vec) -> Self { -// Self { -// box_title: String::from(box_title), -// is_win_open: false, -// display_parameters: DisplayGraphParameter { -// padding_x: 40., -// padding_y: 40., -// node_size: 30., -// }, -// graph: None, -// from: from_list, -// from_input_string: String::new(), -// } -// } -// -// pub fn display_left_panel_graphics( -// &mut self, -// ui: &mut Ui, -// other_obj: &mut RegularGrammarObjects, -// error_log: &mut VecDeque, -// ) { -// ui.heading(self.box_title.clone()); -// for fun in self.from.iter() { -// if let Some(res) = fun(ui, other_obj, &mut self.from_input_string, error_log) { -// self.graph = Some(res); -// self.is_win_open = true; -// } -// } -// } -// -// pub fn check_open(&mut self) { -// if let None = self.graph { -// self.is_win_open = false; -// } -// if !self.is_win_open { -// self.graph = None; -// } -// } -// -// fn display_parameters(display_parameters: &mut DisplayGraphParameter, ui: &mut Ui) { -// let par = display_parameters; -// ui.collapsing(format!("visualizer option",), |ui| { -// ui.add(egui::Slider::new(&mut par.padding_x, 10.0..=100.0).text("padding x")); -// ui.add(egui::Slider::new(&mut par.padding_y, 10.0..=100.0).text("padding y")); -// ui.add(egui::Slider::new(&mut par.node_size, 10.0..=100.0).text("node size")); -// }); -// } -// -// fn display_graph( -// graph: &mut Option, -// display_parameters: DisplayGraphParameter, -// ui: &mut Ui, -// ) { -// Frame::canvas(ui.style()).show(ui, |canvas_ui| { -// if let Some(tree) = graph { -// let scren_size = tree.position(display_parameters); -// let (mut response, painter) = -// canvas_ui.allocate_painter(scren_size, egui::Sense::hover()); -// -// let to_screen = emath::RectTransform::from_to( -// Rect::from_min_size(Pos2::ZERO, response.rect.size()), -// response.rect, -// ); -// tree.drag_nodes(to_screen, canvas_ui, &mut response); -// tree.draw(&painter, to_screen, canvas_ui); -// } -// }); -// } -// -// pub fn display_visualization(&mut self, ctx: &egui::Context) { -// self.check_open(); -// let syntaxTree = Window::new(format!("{}", self.box_title)); -// let syntaxTree = syntaxTree.open(&mut self.is_win_open); -// let syntaxTree = syntaxTree.scroll2([true, true]); -// syntaxTree.show(ctx, |ui| { -// Self::display_parameters(&mut self.display_parameters, ui); -// Self::display_graph(&mut self.graph, self.display_parameters, ui); -// }); -// } -// }