Skip to content

Commit

Permalink
basic UI
Browse files Browse the repository at this point in the history
  • Loading branch information
rfuzzo committed Mar 10, 2024
1 parent 0477618 commit b04f5c0
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 15 deletions.
123 changes: 110 additions & 13 deletions gui/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::env;

use egui::{Color32, RichText};
use log::error;
use plox::{
detect_game, download_latest_rules, gather_mods, get_default_rules_dir,
parser::{self, Parser},
parser::{self, Parser, Warning},
rules::EWarningRule,
sorter::{new_stable_sorter, Sorter},
};

Expand All @@ -17,11 +19,19 @@ pub struct TemplateApp {
#[serde(skip)]
sorter: Sorter,

// plugins
#[serde(skip)]
mods: Vec<String>,

#[serde(skip)]
new_order: Vec<String>,

// notes
#[serde(skip)]
warnings: Vec<Warning>,

#[serde(skip)]
plugin_warning_map: Vec<(String, usize)>,
}

impl Default for TemplateApp {
Expand All @@ -31,6 +41,8 @@ impl Default for TemplateApp {
sorter: new_stable_sorter(),
mods: vec![],
new_order: vec![],
warnings: vec![],
plugin_warning_map: vec![],
}
}
}
Expand Down Expand Up @@ -64,6 +76,7 @@ impl eframe::App for TemplateApp {
// For inspiration and more examples, go to https://emilk.github.io/egui

// first setup
let mut warning = String::new();
let mut render_warning_only = false;
if self.parser.is_none() {
// init parser
Expand All @@ -83,12 +96,20 @@ impl eframe::App for TemplateApp {
let mut parser = parser::get_parser(game);
if let Err(e) = parser.init(rules_dir) {
error!("Parser init failed: {}", e);
// TODO do something, render some warning only

render_warning_only = true;
warning = format!("Parser init failed: {}", e);
}

// evaluate
parser.evaluate_plugins(&self.mods);
self.warnings = parser.warnings.clone();

for (i, w) in self.warnings.iter().enumerate() {
for p in &w.get_plugins() {
self.plugin_warning_map.push((p.clone(), i));
}
}

// sort
match self.sorter.topo_sort(&self.mods, &parser.order_rules) {
Expand All @@ -97,16 +118,18 @@ impl eframe::App for TemplateApp {
}
Err(e) => {
error!("error sorting: {e:?}");
// TODO do something, render some warning only

render_warning_only = true;
warning = format!("error sorting: {e:?}");
}
}

self.parser = Some(parser);
} else {
error!("No game detected");
// TODO do something, render some warning only

render_warning_only = true;
warning = "No game detected".to_string();
}
}

Expand All @@ -129,23 +152,88 @@ impl eframe::App for TemplateApp {
});
});

egui::CentralPanel::default().show(ctx, |ui| {
// The central panel the region left after adding TopPanel's and SidePanel's
ui.heading("PLOX");

if render_warning_only {
// TODO some warning
// warning only UI
if render_warning_only {
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("WARNING");
ui.label(warning);

ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
powered_by_egui_and_eframe(ui);
egui::warn_if_debug_build(ui);
});
});

return;
}
return;
}

// TODO main UI
egui::SidePanel::left("side_panel")
.min_width(200_f32)
.show(ctx, |ui| {
ui.heading("New Order");
for m in &self.new_order {
let notes: Vec<_> = self
.plugin_warning_map
.iter()
.filter(|(p, _)| p.to_lowercase() == *m.to_lowercase())
.collect();

let text = if !notes.is_empty() {
let i = notes[0].1;
let background_color = get_color_for_rule(&self.warnings[i].rule);
// make it more transparent

RichText::new(m).background_color(background_color.gamma_multiply(0.5))
} else {
RichText::new(m)
};

// TODO main UI
ui.horizontal(|ui| {
ui.label(text);
if ui.button("X").clicked() {
// TODO filter all
}
});
}
});

egui::CentralPanel::default().show(ctx, |ui| {
// The central panel the region left after adding TopPanel's and SidePanel's
ui.heading("PLOX");

// display warnings
if !self.warnings.is_empty() {
for (i, w) in self.warnings.iter().enumerate() {
let mut frame = egui::Frame::default().inner_margin(4.0).begin(ui);
{
// create itemview
let color = get_color_for_rule(&w.rule);
frame.content_ui.colored_label(color, w.get_rule_name());

frame.content_ui.label(w.get_comment());

frame.content_ui.push_id(i, |ui| {
ui.collapsing("Plugins Affected", |ui| {
for plugin in &w.get_plugins() {
ui.label(plugin);
}
});
});
}
let response = frame.allocate_space(ui);
if response.hovered() {
let mut bg_color = egui::Color32::LIGHT_GRAY;
// if theme is dark, make it darker
if ctx.style().visuals.dark_mode {
bg_color = Color32::DARK_GRAY;
}

frame.frame.fill = bg_color;
}
frame.paint(ui);
}
}

ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
powered_by_egui_and_eframe(ui);
Expand All @@ -155,6 +243,15 @@ impl eframe::App for TemplateApp {
}
}

fn get_color_for_rule(rule: &EWarningRule) -> Color32 {
match rule {
EWarningRule::Note(_) => Color32::DARK_GREEN,
EWarningRule::Conflict(_) => Color32::RED,
EWarningRule::Requires(_) => Color32::YELLOW,
EWarningRule::Patch(_) => Color32::BLUE,
}
}

fn powered_by_egui_and_eframe(ui: &mut egui::Ui) {
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
Expand Down
20 changes: 18 additions & 2 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,28 @@ impl ChunkWrapper {
}
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Warning {
pub rule: EWarningRule, //TODO consider using a reference here
}

impl Warning {
pub fn get_comment(&self) -> String {
self.rule.get_comment().to_owned()
}
pub fn get_plugins(&self) -> Vec<String> {
self.rule.get_plugins()
}
pub fn get_rule_name(&self) -> String {
match self.rule {
EWarningRule::Conflict(_) => "Conflict".to_owned(),
EWarningRule::Note(_) => "Note".to_owned(),
EWarningRule::Patch(_) => "Patch".to_owned(),
EWarningRule::Requires(_) => "Requires".to_owned(),
}
}
}

pub struct Parser {
pub game: ESupportedGame,
pub ext: Vec<String>,
Expand Down Expand Up @@ -183,7 +200,6 @@ impl Parser {
R: Read + BufRead + Seek,
{
// pre-parse into rule blocks
// TODO, do it properly and stop on new rule start, not newline
let mut chunks: Vec<ChunkWrapper> = vec![];
let mut chunk: Option<ChunkWrapper> = None;
for (idx, line) in reader.lines().map_while(Result::ok).enumerate() {
Expand Down
26 changes: 26 additions & 0 deletions src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum EWarningRule {
pub trait TWarningRule {
/// every rule may have a comment describing why it failed
fn get_comment(&self) -> &str;
fn get_plugins(&self) -> Vec<String>;

fn set_comment(&mut self, comment: String);
/// every rule may be evaluated
fn eval(&mut self, items: &[String]) -> bool;
Expand All @@ -60,6 +62,15 @@ impl TWarningRule for EWarningRule {
}
}

fn get_plugins(&self) -> Vec<String> {
match self {
EWarningRule::Note(x) => x.get_plugins(),
EWarningRule::Conflict(x) => x.get_plugins(),
EWarningRule::Requires(x) => x.get_plugins(),
EWarningRule::Patch(x) => x.get_plugins(),
}
}

fn set_comment(&mut self, comment: String) {
match self {
EWarningRule::Note(x) => x.set_comment(comment),
Expand Down Expand Up @@ -412,6 +423,10 @@ impl TWarningRule for Note {
fn get_comment(&self) -> &str {
self.comment.as_str()
}
fn get_plugins(&self) -> Vec<String> {
self.plugins.clone()
}

fn set_comment(&mut self, comment: String) {
self.comment = comment;
}
Expand Down Expand Up @@ -488,6 +503,9 @@ impl TWarningRule for Conflict {
fn get_comment(&self) -> &str {
self.comment.as_str()
}
fn get_plugins(&self) -> Vec<String> {
self.plugins.clone()
}
fn set_comment(&mut self, comment: String) {
self.comment = comment;
}
Expand Down Expand Up @@ -566,6 +584,10 @@ impl TWarningRule for Requires {
fn get_comment(&self) -> &str {
self.comment.as_str()
}
fn get_plugins(&self) -> Vec<String> {
self.plugins.clone()
}

fn set_comment(&mut self, comment: String) {
self.comment = comment;
}
Expand Down Expand Up @@ -654,6 +676,10 @@ impl TWarningRule for Patch {
fn get_comment(&self) -> &str {
self.comment.as_str()
}
fn get_plugins(&self) -> Vec<String> {
self.plugins.clone()
}

fn set_comment(&mut self, comment: String) {
self.comment = comment;
}
Expand Down

0 comments on commit b04f5c0

Please sign in to comment.