From 415c9863e67c1d94b8f50e621576ccb1d77540d8 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 31 Dec 2023 19:46:23 -0500 Subject: [PATCH] Improve GUI --- Cargo.lock | 57 +++++++++++++++++++ Cargo.toml | 4 +- src/bin/gui/app.rs | 135 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 173 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06bedab..7decabb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -945,7 +945,9 @@ dependencies = [ "csv", "eframe", "egui", + "egui_extras", "env_logger", + "getrandom", "libc", "log", "rand", @@ -1035,6 +1037,19 @@ dependencies = [ "winit", ] +[[package]] +name = "egui_extras" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97624eaf17a16058265d3a3e712e167798655baf7c8f693de25be75cdd6c57b5" +dependencies = [ + "egui", + "enum-map", + "log", + "mime_guess2", + "serde", +] + [[package]] name = "egui_glow" version = "0.24.1" @@ -1081,6 +1096,27 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", + "serde", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.43", +] + [[package]] name = "enumflags2" version = "0.7.8" @@ -1386,8 +1422,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1877,6 +1915,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess2" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a3333bb1609500601edc766a39b4c1772874a4ce26022f4d866854dc020c41" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -3111,6 +3159,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.14" diff --git a/Cargo.toml b/Cargo.toml index a3e8927..eac0a5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,16 +33,18 @@ log = "0.4.20" rand = "0.8.5" rayon = "1.8.0" reqwest = { version = "0.11.20", features = ["blocking", "json"] } -rustyline = { version = "12.0.0", features = ["derive", "with-file-history"] } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" toml = "0.8.1" tree-sitter = "0.20.10" +egui_extras = "0.24.2" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] env_logger = "0.10" +rustyline = { version = "12.0.0", features = ["derive", "with-file-history"] } [target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = ["js"] } wasm-bindgen-futures = "0.4" [build-dependencies] diff --git a/src/bin/gui/app.rs b/src/bin/gui/app.rs index 14d9e80..98a30f4 100644 --- a/src/bin/gui/app.rs +++ b/src/bin/gui/app.rs @@ -1,7 +1,8 @@ use std::{fs::read_to_string, path::PathBuf}; use dust_lang::{Interpreter, Map, Result, Value}; -use egui::{Align, Color32, Layout, RichText}; +use egui::{Align, Color32, Layout, RichText, ScrollArea}; +use egui_extras::{Column, TableBuilder}; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] @@ -12,6 +13,7 @@ pub struct App { #[serde(skip)] interpreter: Interpreter, output: Result, + error: Option, } impl App { @@ -33,6 +35,7 @@ impl App { context, interpreter, output, + error: None, } } @@ -77,30 +80,50 @@ impl eframe::App for App { }); egui::CentralPanel::default().show(ctx, |ui| { - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { - ui.with_layout(Layout::top_down(Align::Min).with_main_justify(true), |ui| { - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.columns(2, |columns| { + ScrollArea::vertical() + .id_source("source") + .show(&mut columns[0], |ui| { + if let Some(error) = &self.error { + ui.label(RichText::new(error).color(Color32::LIGHT_RED)); + } + ui.text_edit_singleline(&mut self.path); + ui.code_editor(&mut self.source); if ui.button("read").clicked() { - self.source = read_to_string(&self.path).unwrap(); + match read_to_string(&self.path) { + Ok(source) => { + self.source = source; + self.error = None; + } + Err(error) => self.error = Some(error.to_string()), + } } if ui.button("run").clicked() { self.output = self.interpreter.run(&self.source); } }); - ui.code_editor(&mut self.source); - }); + ScrollArea::vertical() + .id_source("output") + .show(&mut columns[1], |ui| match &self.output { + Ok(value) => display_value(value, ui), + Err(error) => { + ui.label(RichText::new(error.to_string()).color(Color32::LIGHT_RED)); - match &self.output { - Ok(value) => { - display_value(value, ui); - } - Err(error) => { - ui.label(error.to_string()); - } - } + display_value(&Value::Map(self.context.clone()), ui); + + match &self.output { + Ok(value) => { + display_value(value, ui); + } + Err(error) => { + ui.label(error.to_string()); + } + } + } + }); }); }); } @@ -109,13 +132,57 @@ impl eframe::App for App { fn display_value(value: &Value, ui: &mut egui::Ui) { match value { Value::List(list) => { - ui.collapsing("list", |ui| { - for value in list.items().iter() { - display_value(value, ui); - } - }); + let table = TableBuilder::new(ui) + .striped(true) + .resizable(true) + .column(Column::auto()) + .column(Column::auto()); + + table + .header(20.0, |mut header| { + header.col(|ui| { + ui.strong("index"); + }); + }) + .body(|mut body| { + for (index, value) in list.items().iter().enumerate() { + body.row(20.0, |mut row| { + row.col(|ui| { + ui.label(index.to_string()); + }); + row.col(|ui| { + display_value(value, ui); + }); + }); + } + }); + } + Value::Map(map) => { + let table = TableBuilder::new(ui) + .striped(true) + .resizable(true) + .column(Column::auto()) + .column(Column::auto()); + + table + .header(20.0, |mut header| { + header.col(|ui| { + ui.strong("key"); + }); + }) + .body(|mut body| { + for (key, (value, _)) in map.variables().unwrap().iter() { + body.row(20.0, |mut row| { + row.col(|ui| { + ui.label(key); + }); + row.col(|ui| { + display_value(value, ui); + }); + }); + } + }); } - Value::Map(_) => todo!(), Value::Function(function) => { ui.label(function.to_string()); } @@ -131,6 +198,30 @@ fn display_value(value: &Value, ui: &mut egui::Ui) { Value::Boolean(boolean) => { ui.label(RichText::new(boolean.to_string()).color(Color32::RED)); } - Value::Option(_) => todo!(), + Value::Option(option) => match option { + Some(value) => { + let table = TableBuilder::new(ui) + .striped(true) + .resizable(true) + .column(Column::auto()); + + table + .header(20.0, |mut header| { + header.col(|ui| { + ui.strong("some"); + }); + }) + .body(|mut body| { + body.row(20.0, |mut row| { + row.col(|ui| { + display_value(value, ui); + }); + }); + }); + } + None => { + ui.label("none"); + } + }, } }