-
Notifications
You must be signed in to change notification settings - Fork 2
feat(app_gui): add destruction section #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| use std::{ | ||
| collections::HashMap, | ||
| fmt::{self, Write}, | ||
| fs::{self}, | ||
| mem, | ||
| path::{Path, PathBuf}, | ||
| sync::{ | ||
| Arc, RwLock, | ||
| mpsc::{self, channel}, | ||
| }, | ||
| thread::{self, JoinHandle}, | ||
| time, | ||
| }; | ||
|
|
||
| use anyhow::{Result, anyhow}; | ||
| use app_cli::{ | ||
| Config, CraftedItem, ProductionType, Recipe, commit_item, craft_item, load_item, log_init, | ||
| }; | ||
| use common::load_dotenv; | ||
| use egui::{Color32, Frame, Label, RichText, Ui}; | ||
| use itertools::Itertools; | ||
| use pod2::{ | ||
| backends::plonky2::primitives::merkletree::MerkleProof, | ||
| middleware::{ | ||
| Hash, Params, RawValue, Statement, StatementArg, TypedValue, Value, containers::Set, | ||
| }, | ||
| }; | ||
| use tokio::runtime::Runtime; | ||
| use tracing::{error, info}; | ||
|
|
||
| use crate::{App, Committing, ItemView, Request, Response, TaskStatus, utils::result2text}; | ||
|
|
||
| #[derive(Default)] | ||
| pub struct Destruction { | ||
| pub item_index: Option<usize>, | ||
| pub result: Option<Result<PathBuf>>, | ||
| } | ||
|
|
||
| impl App { | ||
| // UI for the destruction of items. | ||
| pub(crate) fn ui_destroy(&mut self, ctx: &egui::Context, ui: &mut Ui) { | ||
| let all_items = self.all_items(); | ||
| egui::Grid::new("destruction").show(ui, |ui| { | ||
| ui.set_min_height(32.0); | ||
| ui.heading("Destroy"); | ||
| ui.end_row(); | ||
| }); | ||
| ui.separator(); | ||
| let frame = Frame::default().inner_margin(4.0); | ||
| let (_, dropped_payload) = | ||
| ui.dnd_drop_zone::<usize, ()>(frame, |ui| match &self.destruction.item_index { | ||
| Some(i) => { | ||
| if let Some(name) = self.items.get(*i).map(|item| item.name.to_string()) { | ||
| self.destruction.result = None; | ||
| ui.label(name); | ||
| } else { | ||
| self.destruction.result = Some(Err(anyhow!( | ||
| "Item '{}' has already been used or destroyed!", | ||
| all_items[*i].name | ||
| ))); | ||
| ui.label("..."); | ||
| } | ||
| } | ||
| _ => { | ||
| ui.label("..."); | ||
| } | ||
| }); | ||
| ui.end_row(); | ||
| if let Some(i) = dropped_payload { | ||
| self.destruction.item_index = Some(*i); | ||
| } | ||
|
|
||
| let mut button_destroy_clicked = false; | ||
|
|
||
| egui::Grid::new("destruction buttons").show(ui, |ui| { | ||
| if let (Some(i), None) = (self.destruction.item_index, &self.destruction.result) { | ||
| button_destroy_clicked = ui.button("Destroy").clicked(); | ||
|
|
||
| if button_destroy_clicked { | ||
| let item = all_items[i].path.clone(); | ||
| self.task_req_tx | ||
| .send(Request::Destroy { | ||
| params: self.params.clone(), | ||
| cfg: self.cfg.clone(), | ||
| item, | ||
| }) | ||
| .unwrap(); | ||
| } | ||
| } | ||
| ui.label(result2text(&self.destruction.result)); | ||
| ui.end_row(); | ||
| }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,9 @@ use std::{ | |
| }; | ||
|
|
||
| use anyhow::{Result, anyhow}; | ||
| use app_cli::{Config, CraftedItem, Recipe, commit_item, craft_item, load_item, log_init}; | ||
| use app_cli::{ | ||
| Config, CraftedItem, ProductionType, Recipe, commit_item, craft_item, load_item, log_init, | ||
| }; | ||
| use common::load_dotenv; | ||
| use egui::{Color32, Frame, Label, RichText, Ui}; | ||
| use itertools::Itertools; | ||
|
|
@@ -34,12 +36,14 @@ use tracing::{error, info}; | |
|
|
||
| mod app; | ||
| mod crafting; | ||
| mod destruction; | ||
| mod item_view; | ||
| mod task_system; | ||
| mod utils; | ||
|
|
||
| use app::*; | ||
| use crafting::*; | ||
| use destruction::*; | ||
| use item_view::*; | ||
| use task_system::*; | ||
|
|
||
|
|
@@ -66,9 +70,7 @@ fn main() -> Result<()> { | |
| }), | ||
| ) | ||
| .map_err(|e| anyhow::anyhow!("{e}"))?; | ||
| // app.task_handler | ||
| // .join() | ||
| // .map_err(|e| anyhow::anyhow!("{e:?}"))?; | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
|
|
@@ -92,22 +94,15 @@ impl eframe::App for App { | |
| self.crafting.craft_result = Some(r) | ||
| } | ||
| Response::Commit(r) => self.crafting.commit_result = Some(r), | ||
| Response::Destroy(r) => { | ||
| self.refresh_items().unwrap(); | ||
| self.destruction.item_index = None; | ||
| self.destruction.result = Some(r) | ||
| } | ||
| Response::Null => {} | ||
| } | ||
| } | ||
|
|
||
| // If the task is busy, display a spinner and the task name | ||
| let task_status = self.task_status.read().unwrap().clone(); | ||
| if let Some(task) = task_status.busy { | ||
| egui::CentralPanel::default().show(ctx, |ui| { | ||
| ui.vertical_centered(|ui| { | ||
| ui.spinner(); | ||
| ui.heading(task); | ||
| }); | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| // Left side panel "Item list" | ||
| egui::SidePanel::left("item list").show(ctx, |ui| { | ||
| ui.horizontal(|ui| { | ||
|
|
@@ -142,16 +137,24 @@ impl eframe::App for App { | |
| }); | ||
| }); | ||
|
|
||
| egui::CentralPanel::default().show(ctx, |ui| { | ||
| ui.columns_const(|[item_view_ui, crafting_ui]| { | ||
| item_view_ui.vertical(|ui| { | ||
| self.update_item_view_ui(ui); | ||
| }); | ||
| egui::CentralPanel::default().show(ctx, |ui| self.update_item_view_ui(ui)); | ||
|
|
||
| crafting_ui.vertical(|ui| { | ||
| self.update_crafting_ui(ctx, ui); | ||
| // If the task is busy, display a spinner and the task name, | ||
| // else display the action UI. | ||
| let task_status = self.task_status.read().unwrap().clone(); | ||
| egui::SidePanel::right("actions").show(ctx, |ui| { | ||
| if let Some(task) = task_status.busy { | ||
| ui.horizontal_centered(|ui| { | ||
| ui.spinner(); | ||
| ui.heading(task); | ||
| }); | ||
| }); | ||
| } else { | ||
| self.update_action_ui(ctx, ui); | ||
| } | ||
| // Display window(s). | ||
| if self.modal_new_predicates { | ||
| self.ui_new_predicate(ctx, ui); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -161,3 +164,47 @@ impl eframe::App for App { | |
| thread::sleep(time::Duration::from_millis(100)); | ||
| } | ||
| } | ||
|
|
||
| impl App { | ||
| pub fn update_action_ui(&mut self, ctx: &egui::Context, ui: &mut Ui) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to request a minimum width of this right panel so that the predicates don't wrap (too much). I tried to implement it and wasn't able to get it working reliably so instead I want to request the removal of the Grid which allows the panel to be resizable (so that we can resize it to avoid the wrapping of predicates): diff --git a/app_gui/src/main.rs b/app_gui/src/main.rs
index bf47292..da9cf02 100644
--- a/app_gui/src/main.rs
+++ b/app_gui/src/main.rs
@@ -167,47 +167,43 @@ impl eframe::App for App {
impl App {
pub fn update_action_ui(&mut self, ctx: &egui::Context, ui: &mut Ui) {
- egui::Grid::new("action UI").show(ui, |ui| {
- ui.set_min_height(32.0);
- ui.vertical(|ui| {
- ui.horizontal(|ui| {
- if ui
- .selectable_label(self.selected_tab == 0, "Mine")
- .clicked()
- {
- self.crafting.selected_recipe = None;
- self.selected_tab = 0;
- }
- if ui
- .selectable_label(self.selected_tab == 1, "Craft")
- .clicked()
- {
- self.crafting.selected_recipe = None;
- self.selected_tab = 1;
- }
- if ui
- .selectable_label(self.selected_tab == 2, "Destroy")
- .clicked()
- {
- self.destruction.item_index = None;
- self.selected_tab = 2;
- }
- if ui
- .selectable_label(self.modal_new_predicates, "+ New Predicate")
- .clicked()
- {
- self.modal_new_predicates = true;
- }
- });
- ui.separator();
- match self.selected_tab {
- 0 => self.ui_produce(ctx, ui, ProductionType::Mine),
- 1 => self.ui_produce(ctx, ui, ProductionType::Craft),
- 2 => self.ui_destroy(ctx, ui),
- _ => {}
+ ui.vertical(|ui| {
+ ui.horizontal(|ui| {
+ if ui
+ .selectable_label(self.selected_tab == 0, "Mine")
+ .clicked()
+ {
+ self.crafting.selected_recipe = None;
+ self.selected_tab = 0;
+ }
+ if ui
+ .selectable_label(self.selected_tab == 1, "Craft")
+ .clicked()
+ {
+ self.crafting.selected_recipe = None;
+ self.selected_tab = 1;
+ }
+ if ui
+ .selectable_label(self.selected_tab == 2, "Destroy")
+ .clicked()
+ {
+ self.destruction.item_index = None;
+ self.selected_tab = 2;
+ }
+ if ui
+ .selectable_label(self.modal_new_predicates, "+ New Predicate")
+ .clicked()
+ {
+ self.modal_new_predicates = true;
}
});
- ui.end_row();
+ ui.separator();
+ match self.selected_tab {
+ 0 => self.ui_produce(ctx, ui, ProductionType::Mine),
+ 1 => self.ui_produce(ctx, ui, ProductionType::Craft),
+ 2 => self.ui_destroy(ctx, ui),
+ _ => {}
+ }
});
}
} |
||
| ui.vertical(|ui| { | ||
| ui.horizontal(|ui| { | ||
| if ui | ||
| .selectable_label(self.selected_tab == 0, "Mine") | ||
| .clicked() | ||
| { | ||
| self.crafting.selected_recipe = None; | ||
| self.selected_tab = 0; | ||
| } | ||
| if ui | ||
| .selectable_label(self.selected_tab == 1, "Craft") | ||
| .clicked() | ||
| { | ||
| self.crafting.selected_recipe = None; | ||
| self.selected_tab = 1; | ||
| } | ||
| if ui | ||
| .selectable_label(self.selected_tab == 2, "Destroy") | ||
| .clicked() | ||
| { | ||
| self.destruction.item_index = None; | ||
| self.selected_tab = 2; | ||
| } | ||
| if ui | ||
| .selectable_label(self.modal_new_predicates, "+ New Predicate") | ||
| .clicked() | ||
| { | ||
| self.modal_new_predicates = true; | ||
| } | ||
| }); | ||
| ui.separator(); | ||
| match self.selected_tab { | ||
| 0 => self.ui_produce(ctx, ui, ProductionType::Mine), | ||
| 1 => self.ui_produce(ctx, ui, ProductionType::Craft), | ||
| 2 => self.ui_destroy(ctx, ui), | ||
| _ => {} | ||
| } | ||
| }); | ||
| ui.end_row(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently in the dropdown menu of items to be destructed, the ones in the
used_itemslist appear too; but those items have been already been nullified.Maybe here we can just list the non-used items?