diff options
author | metamuffin <yvchraiqi@protonmail.com> | 2022-08-16 18:06:43 +0200 |
---|---|---|
committer | metamuffin <yvchraiqi@protonmail.com> | 2022-08-16 18:06:43 +0200 |
commit | 32bfbe158ab695c9258c13e6f32a619b780d8930 (patch) | |
tree | dcb09c291f31250e0a2ada3f09230fa47cb817b7 | |
parent | 9a306095aa701f372242f3dcbb76a09b4694762d (diff) | |
download | karlender-32bfbe158ab695c9258c13e6f32a619b780d8930.tar karlender-32bfbe158ab695c9258c13e6f32a619b780d8930.tar.bz2 karlender-32bfbe158ab695c9258c13e6f32a619b780d8930.tar.zst |
stuff
-rw-r--r-- | karld/src/interface.rs | 4 | ||||
-rw-r--r-- | karld/src/main.rs | 2 | ||||
-rw-r--r-- | karlgui/src/client.rs | 14 | ||||
-rw-r--r-- | karlgui/src/edit.rs | 233 | ||||
-rw-r--r-- | karlgui/src/main.rs | 199 |
5 files changed, 267 insertions, 185 deletions
diff --git a/karld/src/interface.rs b/karld/src/interface.rs index 750f307..f283733 100644 --- a/karld/src/interface.rs +++ b/karld/src/interface.rs @@ -7,6 +7,10 @@ use std::os::unix::net::{UnixListener, UnixStream}; use std::thread; pub fn network_loop() { + if std::fs::try_exists(socket_path()).unwrap() { + info!("delete old socket"); + std::fs::remove_file(socket_path()).unwrap(); + } let listener = UnixListener::bind(socket_path()).unwrap(); info!("listening."); let mut id_counter = 0; diff --git a/karld/src/main.rs b/karld/src/main.rs index 414b1e6..10130d7 100644 --- a/karld/src/main.rs +++ b/karld/src/main.rs @@ -1,4 +1,5 @@ #![feature(box_syntax)] +#![feature(fs_try_exists)] pub mod condition; pub mod helper; @@ -126,6 +127,7 @@ lazy_static::lazy_static! { } pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<ClientboundPacket>) { + std::thread::sleep(std::time::Duration::from_millis(75)); match packet { ServerboundPacket::Sync => { let _ = responder.send(ClientboundPacket::Sync); diff --git a/karlgui/src/client.rs b/karlgui/src/client.rs index 9f2dfc7..b027cdc 100644 --- a/karlgui/src/client.rs +++ b/karlgui/src/client.rs @@ -9,6 +9,7 @@ use std::{ pub struct Client { socket: UnixStream, + pub busy: bool, pub receiver: Receiver<ClientboundPacket>, } @@ -27,10 +28,15 @@ impl Client { sender.send(p).unwrap(); } }); - let mut c = Self { receiver, socket }; + let mut c = Self { + receiver, + socket, + busy: true, + }; c.send(ServerboundPacket::Handshake { version: version!(), }); + c.send(ServerboundPacket::Sync); return c; } @@ -40,4 +46,10 @@ impl Client { .write_fmt(format_args!("{}\n", serde_json::to_string(&p).unwrap())) .unwrap() } + + pub fn send_sync(&mut self, p: ServerboundPacket) { + self.busy = true; + self.send(p); + self.send(ServerboundPacket::Sync); + } } 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))) + } + }); +} diff --git a/karlgui/src/main.rs b/karlgui/src/main.rs index b92d95b..3832044 100644 --- a/karlgui/src/main.rs +++ b/karlgui/src/main.rs @@ -1,17 +1,13 @@ pub mod client; +pub mod edit; use crate::client::Client; +use edit::ShowOrEdit; use eframe::CreationContext; -use egui::{text::LayoutJob, CentralPanel, Color32, DragValue, Response, TextFormat, Ui, Widget}; -use karlcommon::{ - socket_path, ClientboundPacket, Condition, Property, Schedule, ServerboundPacket, Task, -}; +use egui::CentralPanel; +use karlcommon::{socket_path, ClientboundPacket, ServerboundPacket, Task}; use log::{error, info}; -use std::{ - ops::{Deref, DerefMut, Range}, - os::unix::net::UnixStream, - process::exit, -}; +use std::{os::unix::net::UnixStream, process::exit}; fn main() { env_logger::init(); @@ -55,6 +51,9 @@ impl App { ClientboundPacket::TaskList(t) => { self.tasks = t.into_iter().map(|t| ShowOrEdit::new(t, false)).collect() } + ClientboundPacket::Sync => { + self.client.busy = false; + } _ => {} } } @@ -65,183 +64,15 @@ impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { self.update_network(); CentralPanel::default().show(ctx, |ui| { - for t in &mut self.tasks { - t.ui(ui); - ui.separator(); - } - }); - } -} - -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 ui(&mut self, ui: &mut Ui) { - match self.edit { - true => { - if ui.button("💾 Save").clicked() { - self.edit = false; - } - } - false => { - if ui.button("✏ Edit").clicked() { - self.edit = true; - } - } - } - self.inner.ui(ui, self.edit); - } -} - -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) = &self.description { - ui.label(d); - } - ui.horizontal(|ui| { - ui.label("Tags:"); - for t in &self.tags { - ui.colored_label(Color32::LIGHT_GREEN, t); + ui.add_enabled_ui(!self.client.busy, |ui| { + for t in &mut self.tasks { + if t.changed(ui) { + self.client + .send_sync(ServerboundPacket::UpdateTask(t.inner.clone())) + } + ui.separator(); } }); - self.schedule.ui(ui, edit); }); } } - -impl EditableWidget for Schedule { - fn ui(&mut self, ui: &mut Ui, edit: bool) { - match self { - Schedule::Never => { - let mut j = LayoutJob::default(); - j.append( - "No schedule", - 0.0, - TextFormat { - italics: true, - ..Default::default() - }, - ); - ui.label(j); - } - 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); - }); - } - Condition::Or(cs) => { - ui.vertical(|ui| { - for (i, c) in cs.iter_mut().enumerate() { - ui.push_id(i, |ui| { - ui.horizontal(|ui| { - ui.label(if i != 0 { "or " } else { " " }); - c.ui(ui, edit); - }); - }); - } - }); - } - Condition::And(cs) => { - ui.vertical(|ui| { - for (i, c) in cs.iter_mut().enumerate() { - ui.push_id(i, |ui| { - ui.horizontal(|ui| { - ui.label(if i != 0 { "and" } else { "" }); - c.ui(ui, edit); - }); - }); - } - }); - } - Condition::Invert(c) => { - ui.horizontal(|ui| { - ui.label("not when"); - c.ui(ui, edit); - }); - } - 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(&format!("{:?}", prop)); - } - 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"); - } -} |