diff --git a/src/gui.rs b/src/gui.rs index 5c78fcc..943a947 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,4 +1,4 @@ -use eframe::egui::{self, RichText}; +use eframe::egui::{self, Color32, RichText}; use serde_json::Value; use std::sync::mpsc; use std::thread; @@ -10,6 +10,92 @@ fn pretty_json(text: &str) -> String { } } +#[derive(Clone, Copy, PartialEq, Eq)] +enum GuiTheme { + Ocean, + Cyberpunk, + Venom, + Rick, +} + +impl GuiTheme { + fn all() -> &'static [GuiTheme] { + &[GuiTheme::Ocean, GuiTheme::Cyberpunk, GuiTheme::Venom, GuiTheme::Rick] + } + fn name(&self) -> &'static str { + match self { + GuiTheme::Ocean => "Ocean", + GuiTheme::Cyberpunk => "Cyberpunk 2077", + GuiTheme::Venom => "Venom", + GuiTheme::Rick => "Rick", + } + } + fn colors(&self) -> (Color32, Color32, Color32, Color32, Color32, Color32) { + match self { + GuiTheme::Ocean => ( + Color32::from_rgb(0x0a, 0x0a, 0x0f), + Color32::from_rgb(0x12, 0x12, 0x1a), + Color32::from_rgb(0x1a, 0x1a, 0x24), + Color32::from_rgb(0x2a, 0x2a, 0x3a), + Color32::from_rgb(0x00, 0xe5, 0xff), + Color32::from_rgb(0xe0, 0xe0, 0xe8), + ), + GuiTheme::Cyberpunk => ( + Color32::from_rgb(0x0a, 0x02, 0x08), + Color32::from_rgb(0x0f, 0x04, 0x16), + Color32::from_rgb(0x1a, 0x0a, 0x24), + Color32::from_rgb(0x2b, 0x4e, 0x76), + Color32::from_rgb(0xa7, 0x21, 0xbe), + Color32::from_rgb(0xe8, 0xe0, 0xea), + ), + GuiTheme::Venom => ( + Color32::from_rgb(0x00, 0x00, 0x00), + Color32::from_rgb(0x05, 0x05, 0x05), + Color32::from_rgb(0x0e, 0x0e, 0x0e), + Color32::from_rgb(0x1a, 0x1a, 0x1a), + Color32::from_rgb(0xea, 0xea, 0xea), + Color32::from_rgb(0xea, 0xea, 0xea), + ), + GuiTheme::Rick => ( + Color32::from_rgb(0x00, 0x00, 0x00), + Color32::from_rgb(0x02, 0x04, 0x02), + Color32::from_rgb(0x08, 0x0a, 0x06), + Color32::from_rgb(0x1a, 0x30, 0x14), + Color32::from_rgb(0x9d, 0xd6, 0x3b), + Color32::from_rgb(0xda, 0xf0, 0xc8), + ), + } + } + fn apply(&self, ctx: &egui::Context) { + let (bg, surface, surface2, border, accent, text) = self.colors(); + let mut v = egui::Visuals::dark(); + v.override_text_color = Some(text); + v.extreme_bg_color = bg; + v.window_fill = surface; + v.panel_fill = surface; + v.faint_bg_color = surface2; + v.code_bg_color = surface2; + v.hyperlink_color = accent; + v.selection = egui::style::Selection { + bg_fill: accent.linear_multiply(0.3), + stroke: egui::Stroke::new(1.0, accent), + }; + v.widgets.noninteractive.bg_fill = surface2; + v.widgets.noninteractive.weak_bg_fill = surface; + v.widgets.noninteractive.bg_stroke = egui::Stroke::new(1.0, border); + v.widgets.inactive.bg_fill = surface2; + v.widgets.inactive.weak_bg_fill = surface; + v.widgets.inactive.bg_stroke = egui::Stroke::new(1.0, border); + v.widgets.hovered.bg_fill = accent.linear_multiply(0.15); + v.widgets.hovered.bg_stroke = egui::Stroke::new(1.0, accent); + v.widgets.hovered.fg_stroke = egui::Stroke::new(1.5, accent); + v.widgets.active.bg_fill = accent.linear_multiply(0.25); + v.widgets.active.bg_stroke = egui::Stroke::new(1.0, accent); + v.widgets.active.fg_stroke = egui::Stroke::new(2.0, accent); + ctx.set_visuals(v); + } +} + pub fn run_gui(server_url: &str) { let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() @@ -71,6 +157,7 @@ type Msg = (String, GuiMsg); struct AirustGui { server_url: String, mode: AppMode, + theme: GuiTheme, active_tab: Tab, chat_input: String, chat_log: String, @@ -106,6 +193,7 @@ impl AirustGui { Self { server_url: server_url.to_string(), mode: AppMode::Startup, + theme: GuiTheme::Ocean, active_tab: Tab::Chat, chat_input: String::new(), chat_log: String::from("AiRust — Cyber Operator\n\n"), @@ -187,6 +275,8 @@ impl AirustGui { impl eframe::App for AirustGui { fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) { + self.theme.apply(ui.ctx()); + while let Ok((label, msg)) = self.rx.try_recv() { let target = match msg { GuiMsg::Set(t) => t, @@ -284,6 +374,19 @@ impl AirustGui { *active = *tab; } } + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + ui.label(RichText::new("Theme:").size(12.0)); + egui::ComboBox::from_id_salt("theme_combo") + .selected_text(self.theme.name()) + .width(130.0) + .show_ui(ui, |ui| { + for t in GuiTheme::all() { + if ui.selectable_label(*t == self.theme, t.name()).clicked() { + self.theme = *t; + } + } + }); + }); }); }); diff --git a/target/debug/.fingerprint/AiRust-301136bf2d3c6683/dep-bin-AiRust-cli b/target/debug/.fingerprint/AiRust-301136bf2d3c6683/dep-bin-AiRust-cli index d5f7b2d..7c075dc 100644 Binary files a/target/debug/.fingerprint/AiRust-301136bf2d3c6683/dep-bin-AiRust-cli and b/target/debug/.fingerprint/AiRust-301136bf2d3c6683/dep-bin-AiRust-cli differ diff --git a/target/debug/AiRust-cli.exe b/target/debug/AiRust-cli.exe index 87a8389..3294ab0 100644 Binary files a/target/debug/AiRust-cli.exe and b/target/debug/AiRust-cli.exe differ diff --git a/target/debug/AiRust_cli.pdb b/target/debug/AiRust_cli.pdb index 3b819e2..b7ce770 100644 Binary files a/target/debug/AiRust_cli.pdb and b/target/debug/AiRust_cli.pdb differ diff --git a/target/debug/deps/AiRust_cli.exe b/target/debug/deps/AiRust_cli.exe index 87a8389..3294ab0 100644 Binary files a/target/debug/deps/AiRust_cli.exe and b/target/debug/deps/AiRust_cli.exe differ diff --git a/target/debug/deps/AiRust_cli.pdb b/target/debug/deps/AiRust_cli.pdb index 3b819e2..b7ce770 100644 Binary files a/target/debug/deps/AiRust_cli.pdb and b/target/debug/deps/AiRust_cli.pdb differ