aboutsummaryrefslogtreecommitdiff
path: root/karlgui/src/views/edit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'karlgui/src/views/edit.rs')
-rw-r--r--karlgui/src/views/edit.rs313
1 files changed, 313 insertions, 0 deletions
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)))
+ }
+ });
+}