diff --git a/src/cli.rs b/src/cli.rs deleted file mode 100644 index 3b2626b..0000000 --- a/src/cli.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod display; - -pub use display::display_plot; diff --git a/src/cli/display.rs b/src/cli/display.rs deleted file mode 100644 index d8f1a3a..0000000 --- a/src/cli/display.rs +++ /dev/null @@ -1,61 +0,0 @@ -use rand::Rng; - -pub fn display_plot(circles: Vec) -> anyhow::Result<()> { //TODO: Save Button - let options = eframe::NativeOptions::default(); - eframe::run_native( - "Encoded Message", - options, - Box::new(|_cc| Ok(Box::::new( - PlotDisplay::new(circles, 1000) - ))) - ).map_err(crate::Error::from)?; - Ok(()) -} - -struct PlotDisplay { - circles: Vec, - circle_length: usize, - line_colors: Vec, -} - -impl PlotDisplay { - fn new(circles: Vec, circle_length: usize) -> Self { - let line_colors: Vec = (0..circles.len()) - .map(|_|random_color()).collect(); - Self { - circles, - circle_length, - line_colors, - } - } -} - -impl eframe::App for PlotDisplay { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - egui::CentralPanel::default().show(ctx, |ui| { - ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| { - save_button(ui); - crate::plot(ui, &mut self.circles, &self.circle_length, &self.line_colors); - }); - }); - } -} - -fn save_button(ui: &mut egui::Ui) { - if ui.button("Save").clicked() { - //TODO: Open file dialog - // Get destination path - // save screenshot of plot to path - } -} - -fn random_color() -> egui::Color32 { - let mut rng = rand::thread_rng(); - let range = 0..=255; - - egui::Color32::from_rgb( - rng.gen_range(range.clone()), - rng.gen_range(range.clone()), - rng.gen_range(range) - ) -} diff --git a/src/gui.rs b/src/gui.rs index e18ac5e..6ce35c0 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,36 +1,47 @@ +mod views; + pub struct Error(eframe::Error); -pub fn gui() -> anyhow::Result<()> { +pub fn gui(message: &mut crate::Message, circle_length: &mut usize, inputs: bool) -> anyhow::Result<()> { let options = eframe::NativeOptions::default(); eframe::run_native( "Encoded Message", options, Box::new(|_cc| Ok(Box::::new( - Default::default() + Gui::new(message, circle_length, inputs) ))) ).map_err(crate::Error::from)?; Ok(()) } -#[derive(Default)] -struct Gui { - message: Option, - circle_length: Option, + +struct Gui<'a> { + display: views::Display<'a>, +} +impl<'a> Gui<'a> { + fn new(message: &'a mut crate::Message, circle_length: &'a mut usize, inputs: bool) -> Self { + let circles = crate::encrypt_message(message, circle_length); + let line_colors: Vec = (0..circles.len()) + .map(|_|views::random_color()).collect(); + + Self { + display: match inputs { + true => views::display_gui(), + false => views::display_plot(circles, circle_length, line_colors), + }, + + } + } + } -impl eframe::App for Gui { +impl eframe::App for Gui<'_> { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - egui::CentralPanel::default().show(ctx, |ui| { - //TODO: UI (on unfocus update values) - // Message Content input - // start shift input - // circle length input - // generate button (if pressed, generate plot with details) - }); + egui::CentralPanel::default().show(ctx,|ui| { + (self.display)(ui) + }); } } - - impl From for Error { fn from(err: eframe::Error) -> Self { Error(err) diff --git a/src/gui/views.rs b/src/gui/views.rs new file mode 100644 index 0000000..0283694 --- /dev/null +++ b/src/gui/views.rs @@ -0,0 +1,43 @@ +pub fn save_button(ui: &mut egui::Ui) { + if ui.button("Save").clicked() { + //TODO: Open file dialog + //Get destination path + //save screenshot of plot to path + } +} + +pub type Display<'a> = Box; + +pub fn display_plot<'a>(mut circles: Vec, circle_length: &'a usize, line_colors: Vec) -> Display<'a> { + Box::new(move |ui| { + ui.with_layout(egui::Layout::bottom_up(egui::Align::Center), |ui| { + save_button(ui); + crate::plot(ui, &mut circles, &circle_length, &line_colors); + }); + }) +} + + +pub fn display_gui() -> Display<'static> { + Box::new(move |ui| { + //TODO: UI (on unfocus update values) + // Message Content input + // start shift input + // circle length input + // generate button (if pressed, generate plot with details) + }) +} + +pub fn random_color() -> egui::Color32 { + use rand::Rng; + + let mut rng = rand::thread_rng(); + let range = 0..=255; + + egui::Color32::from_rgb( + rng.gen_range(range.clone()), + rng.gen_range(range.clone()), + rng.gen_range(range) + ) +} + diff --git a/src/lib.rs b/src/lib.rs index 3644e1c..d9e793d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,23 +2,45 @@ use clap::{Parser, Subcommand}; use std::path::PathBuf; -mod cli; mod encoding; -mod gui; +pub mod gui; mod message; mod plotting; +pub fn run() -> anyhow::Result<()> { + let mut args = Args::parse(); + let mut message = Message::new(args.message, args.start_shift); + + match args.mode { + crate::Mode::Gui => gui::gui(&mut message, &mut args.circle_length, true), + crate::Mode::Encode { output } => encode( + &mut message, + &mut args.circle_length, + output), + } +} + +fn encode(message: &mut crate::Message, circle_length: &mut usize, output: crate::OutputMode) -> anyhow::Result<()> { + match output { + crate::OutputMode::Display => crate::gui::gui(message, circle_length, false), + crate::OutputMode::Save { path } => Ok(()), //TODO: Create plot and save + } +} #[derive(Parser)] #[command(version, about, long_about = None)] pub struct Args { + /// Which mode to run the program in #[command(subcommand)] pub mode: Mode, - #[arg(short, long)] + /// The message to be encrypted + #[arg(short, long, default_value = "")] pub message: String, - #[arg(short, long)] - pub start_shift: String, - #[arg(short, long)] + /// The starting value for the caesar shift + #[arg(short, long, default_value_t = 0)] + pub start_shift: u8, + /// The number of characters in each circle + #[arg(short, long, default_value_t = 127)] pub circle_length: usize, } @@ -35,12 +57,11 @@ pub enum Mode { pub enum OutputMode { Display, Save { - #[arg(short, long)] + #[arg(short, long, default_value = "./message")] path: PathBuf, } } -pub use cli::display_plot; pub use encoding::caesar_shift; pub use encoding::Circle; pub use encoding::circle_to_points; diff --git a/src/main.rs b/src/main.rs index b8c14a3..d2a404f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,3 @@ - -fn main() { - let mut message = circle_cipher::Message::new("Hello".to_string(), 12); - let _ = circle_cipher::display_plot( - circle_cipher::encrypt_message(&mut message, &127) - ); +fn main() -> anyhow::Result<()> { + circle_cipher::run() } diff --git a/src/message.rs b/src/message.rs index 98acabe..278f6d2 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,5 +1,6 @@ use std::vec::IntoIter; +#[derive(Clone)] pub struct Message { pub parts: Parts, pub combined: String, @@ -24,6 +25,7 @@ impl Message { ).collect() } } +#[derive(Clone)] pub struct Parts { pub content: String, pub start_shift: u8,