aboutsummaryrefslogtreecommitdiff
path: root/karlgui/src/edit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'karlgui/src/edit.rs')
-rw-r--r--karlgui/src/edit.rs233
1 files changed, 233 insertions, 0 deletions
diff --git a/karlgui/src/edit.rs b/karlgui/src/edit.rs
new file mode 100644
index 0000000..d2f7150
--- /dev/null
+++ b/karlgui/src/edit.rs
@@ -0,0 +1,233 @@
+use std::ops::Range;
+
+use egui::{Color32, DragValue, RichText, Ui};
+use karlcommon::{Condition, Property, Schedule, Task};
+
+pub struct ShowOrEdit<T> {
+ pub inner: T,
+ pub edit: bool,
+}
+
+impl<T: EditableWidget> ShowOrEdit<T> {
+ pub fn new(inner: T, edit: bool) -> ShowOrEdit<T> {
+ Self { inner, edit }
+ }
+ pub fn changed(&mut self, ui: &mut Ui) -> bool {
+ let changed = match self.edit {
+ true => {
+ if ui.button("💾 Save").clicked() {
+ self.edit = false;
+ true
+ } else {
+ false
+ }
+ }
+ false => {
+ if ui.button("✏ Edit").clicked() {
+ self.edit = true;
+ }
+ false
+ }
+ };
+ self.inner.ui(ui, self.edit);
+ changed
+ }
+}
+
+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);
+ }
+ }
+ ui.horizontal(|ui| {
+ ui.label("Tags:");
+ for t in &self.tags {
+ ui.colored_label(Color32::LIGHT_GREEN, t);
+ }
+ });
+ 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");
+ ui.label(&format!(" {} ", priority));
+ });
+ }
+ 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) {
+ 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.add(DragValue::new(value));
+ } else {
+ ui.label(&format!("{}", value));
+ }
+ });
+ }
+ Condition::Range {
+ prop,
+ min,
+ max,
+ modulus: _,
+ } => {
+ ui.horizontal(|ui| {
+ ui.label("when ");
+ ui.label(&format!("{}", min));
+ ui.label("≤");
+ ui.label(&format!("{:?}", prop));
+ ui.label("<");
+ ui.label(&format!("{}", max))
+ });
+ }
+ });
+ }
+}
+
+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(RichText::from("🗑").color(Color32::RED)).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() {
+ add(Condition::And(vec![]))
+ }
+ if ui.button("Or").clicked() {
+ add(Condition::Or(vec![]))
+ }
+ });
+ ui.menu_button("Constraints", |ui| {
+ if ui.button("Equal").clicked() {
+ add(Condition::Equal {
+ modulus: None,
+ prop: Property::Unix,
+ value: 0,
+ })
+ }
+ if ui.button("Range").clicked() {
+ add(Condition::Range {
+ prop: Property::Unix,
+ min: 0,
+ max: 10,
+ modulus: None,
+ })
+ }
+ if ui.button("Never").clicked() {
+ add(Condition::Never)
+ }
+ });
+ ui.menu_button("Modifier", |ui| {
+ if ui.button("Invert").clicked() {
+ add(Condition::Invert(Box::new(Condition::Never)))
+ }
+ if ui.button("Starting from").clicked() {
+ add(Condition::From(Box::new(Condition::Never)))
+ }
+ });
+}