diff options
Diffstat (limited to 'karlgui/src/views')
-rw-r--r-- | karlgui/src/views/calendar.rs | 34 | ||||
-rw-r--r-- | karlgui/src/views/edit.rs | 313 | ||||
-rw-r--r-- | karlgui/src/views/mod.rs | 2 |
3 files changed, 349 insertions, 0 deletions
diff --git a/karlgui/src/views/calendar.rs b/karlgui/src/views/calendar.rs new file mode 100644 index 0000000..b216504 --- /dev/null +++ b/karlgui/src/views/calendar.rs @@ -0,0 +1,34 @@ +use crate::{helper::weekday_to_str, Globals}; +use egui::Ui; +use egui_extras::TableBuilder; + +#[derive(Default)] +pub struct Calendar; + +impl Calendar { + pub fn ui(&mut self, ui: &mut Ui, _g: &mut Globals) { + TableBuilder::new(ui) + .column(egui_extras::Size::exact(50.0)) + .columns(egui_extras::Size::remainder(), 7) + .header(25.0, |mut ui| { + ui.col(|_| {}); + for d in 0..7 { + ui.col(|ui| { + ui.heading(weekday_to_str(d)); + }); + } + }) + .body(|ui| { + ui.rows(50.0, 24, |h, mut ui| { + ui.col(|ui| { + ui.heading(&format!("{h:02}:00")); + }); + for d in 0..7 { + ui.col(|ui| { + ui.label(&format!("day {d} at {h}:00")); + }); + } + }) + }) + } +} diff --git a/karlgui/src/views/edit.rs b/karlgui/src/views/edit.rs new file mode 100644 index 0000000..04146dd --- /dev/null +++ b/karlgui/src/views/edit.rs @@ -0,0 +1,313 @@ +use std::ops::Range; + +use egui::{Color32, DragValue, TextEdit, Ui}; +use karlcommon::{Condition, Property, Schedule, ServerboundPacket, Task}; + +use crate::{ + helper::{edit_value, format_value}, + Globals, +}; + +#[derive(Default)] +pub struct ShowAndEdit { + edit: Option<u64>, +} + +impl ShowAndEdit { + pub fn ui(&mut self, ui: &mut Ui, g: &mut Globals) { + for t in &mut g.tasks { + let edit = self.edit == Some(t.id); + let changed = if edit { + if ui.button("πΎ Save").clicked() { + self.edit = None; + true + } else { + false + } + } else { + ui.add_enabled_ui(self.edit.is_none(), |ui| { + if ui + .button("β Edit") + .on_disabled_hover_text( + "Some other task is still being edited, save that one first.", + ) + .clicked() + { + self.edit = Some(t.id); + } + }); + false + }; + if changed { + g.client.send_sync(ServerboundPacket::UpdateTask(t.clone())); + } + t.ui(ui, edit); + ui.separator(); + } + } +} + +pub trait EditableWidget { + fn ui(&mut self, ui: &mut Ui, edit: bool); +} + +impl EditableWidget for Task { + fn ui(&mut self, ui: &mut Ui, edit: bool) { + ui.heading(&self.name); + ui.indent((), |ui| { + if let Some(d) = &mut self.description { + if edit { + ui.text_edit_singleline(d); + } else { + ui.label(&*d); + } + } + if self.tags.len() != 0 || edit { + ui.horizontal(|ui| { + ui.label("Tags:"); + let mut remove = None; + for (i, t) in self.tags.iter_mut().enumerate() { + if edit { + TextEdit::singleline(t).desired_width(50.0).show(ui); + if ui.button("π").clicked() { + remove = Some(i); + } + } else { + ui.colored_label(Color32::LIGHT_GREEN, t); + } + } + if edit { + if ui.button("β").clicked() { + self.tags.push(String::from("blub")) + } + } + if let Some(remove) = remove { + self.tags.remove(remove); + } + }); + } + self.schedule.ui(ui, edit); + }); + } +} + +impl EditableWidget for Schedule { + fn ui(&mut self, ui: &mut Ui, edit: bool) { + match self { + Schedule::Never => { + ui.label("No schedule"); + } + Schedule::Dynamic { + priority, + scheduled, + duration, + condition, + } => { + ui.horizontal(|ui| { + ui.label("Dynamic with priority"); + match edit { + true => ui.add(DragValue::new(priority)), + false => ui.label(&format!("{}", priority)), + }; + ui.label("and duration"); + match edit { + true => ui.add(DragValue::new(duration)), + false => ui.label(&format!("{}", duration)), + }; + ui.label("seconds"); + if let Some(scheduled) = scheduled { + ui.label("at "); + scheduled.ui(ui, false) + } + ui.label("during"); + condition.ui(ui, edit); + }); + } + Schedule::Condition(c) => c.ui(ui, edit), + Schedule::Static(t) => t.ui(ui, edit), + } + } +} + +impl EditableWidget for Condition { + fn ui(&mut self, ui: &mut Ui, edit: bool) { + let res = ui + .group(|ui| match self { + Condition::Never => { + ui.label("never"); + } + Condition::From(c) => { + ui.horizontal(|ui| { + ui.label("Starting from"); + c.ui(ui, edit); + if edit { + ui.menu_button("β Change type", |ui| { + add_condition(ui, |d| *c = Box::new(d)) + }); + } + }); + } + Condition::Invert(c) => { + ui.horizontal(|ui| { + ui.label("not when"); + c.ui(ui, edit); + if edit { + ui.menu_button("β Change type", |ui| { + add_condition(ui, |d| *c = Box::new(d)) + }); + } + }); + } + Condition::Or(cs) => combine_condition(ui, edit, "or", cs), + Condition::And(cs) => combine_condition(ui, edit, "and", cs), + Condition::Equal { + prop, + value, + modulus: _, + } => { + ui.horizontal(|ui| { + ui.label("when"); + if edit { + egui::ComboBox::from_id_source(ui.id()) + .selected_text(prop.to_str()) + .show_ui(ui, |ui| { + for v in Property::VALUES { + ui.selectable_value(prop, *v, v.to_str()); + } + }); + } else { + ui.label(prop.to_str()); + } + ui.label("="); + if edit { + ui.push_id(0, |ui| edit_value(ui, *prop, value)); + } else { + ui.label(&format!("{}", format_value(*prop, *value))); + } + }); + } + Condition::Range { + prop, + min, + max, + modulus: _, + } => { + ui.horizontal(|ui| { + ui.label("when"); + match edit { + true => drop(ui.push_id(0, |ui| edit_value(ui, *prop, min))), + false => drop(ui.label(&format!("{}", format_value(*prop, *min)))), + } + ui.label("β€"); + if edit { + egui::ComboBox::from_id_source(ui.id()) + .selected_text(prop.to_str()) + .show_ui(ui, |ui| { + for v in Property::VALUES { + ui.selectable_value(prop, *v, v.to_str()); + } + }); + } else { + ui.label(prop.to_str()); + } + ui.label("<"); + match edit { + true => drop(ui.push_id(1, |ui| edit_value(ui, *prop, max))), + false => drop(ui.label(&format!("{}", format_value(*prop, *max)))), + } + }); + } + }) + .response; + if edit { + res.context_menu(|ui| { + ui.menu_button("Replace withβ¦", |ui| { + add_condition(ui, |c| { + *self = c; + }) + }); + }); + } + } +} + +impl EditableWidget for Range<i64> { + fn ui(&mut self, ui: &mut Ui, _edit: bool) { + ui.label("todo"); + } +} + +fn combine_condition(ui: &mut Ui, edit: bool, combinator: &str, cs: &mut Vec<Condition>) { + ui.vertical(|ui| { + let mut remove = None; + for (i, c) in cs.iter_mut().enumerate() { + ui.push_id(i, |ui| { + ui.horizontal(|ui| { + ui.label(if i != 0 { combinator } else { "" }); + c.ui(ui, edit); + if edit { + if ui.button("π").clicked() { + remove = Some(i); + } + } + }); + }); + } + if edit { + ui.menu_button("β Add condition", |ui| { + add_condition(ui, |e| { + cs.push(e); + }) + }); + } + if let Some(remove) = remove { + cs.remove(remove); + } + }); +} + +fn add_condition(ui: &mut Ui, mut add: impl FnMut(Condition) -> ()) { + ui.menu_button("Combinators", |ui| { + if ui.button("And").clicked() { + ui.close_menu(); + add(Condition::And(vec![])) + } + if ui.button("Or").clicked() { + ui.close_menu(); + add(Condition::Or(vec![])) + } + }); + ui.menu_button("Constraints", |ui| { + if ui.button("Equal").clicked() { + ui.close_menu(); + add(Condition::Equal { + modulus: None, + prop: Property::Unix, + value: 0, + }) + } + if ui.button("Range").clicked() { + ui.close_menu(); + add(Condition::Range { + prop: Property::Unix, + min: 0, + max: 10, + modulus: None, + }) + } + if ui.button("Never").clicked() { + ui.close_menu(); + add(Condition::Never) + } + }); + ui.menu_button("Modifier", |ui| { + if ui.button("Invert").clicked() { + ui.close_menu(); + add(Condition::Invert(Box::new(Condition::Never))) + } + if ui.button("Starting from").clicked() { + ui.close_menu(); + add(Condition::From(Box::new(Condition::Never))) + } + }); +} diff --git a/karlgui/src/views/mod.rs b/karlgui/src/views/mod.rs new file mode 100644 index 0000000..9c6ea7c --- /dev/null +++ b/karlgui/src/views/mod.rs @@ -0,0 +1,2 @@ +pub mod edit; +pub mod calendar; |