diff --git a/src/coordinator/mod.rs b/src/coordinator/mod.rs index f359fc7..806791e 100644 --- a/src/coordinator/mod.rs +++ b/src/coordinator/mod.rs @@ -42,6 +42,7 @@ pub enum ApplicationEvent { StartSocket(String), SocketMessage(Message), MoveEvent(MoveEvent, ConnectionType), + EnableAutomatic(bool), } struct CoordState<'a> { @@ -234,6 +235,11 @@ pub async fn start_coordinator( state.socket_send(socket_message).await; } + ApplicationEvent::EnableAutomatic(do_enable) => { + if let Ok(mut ts) = state.tracker_state.lock() { + ts.enabled = do_enable; + } + }, ApplicationEvent::MoveEvent(coord, priority) => { // If Automatic control, but local event happens, override the automatice events for 2 seconds if priority <= state.current_priority diff --git a/src/remote_sources/mod.rs b/src/remote_sources/mod.rs index 7367ed6..c4079f2 100644 --- a/src/remote_sources/mod.rs +++ b/src/remote_sources/mod.rs @@ -27,9 +27,9 @@ pub mod shared_video_pipe; use crate::coordinator::{ApplicationEvent, ConnectionType}; pub struct TrackerState { - pub has_active_connection: bool, pub tracking_id: u32, pub last_detect: Instant, + pub enabled: bool, } pub async fn start_socketserver( diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 1c58ea8..a3c4489 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,23 +1,23 @@ -use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::time::Instant; use gtk::cairo::Context; -use gtk::ffi::gtk_picture_set_keep_aspect_ratio; use gtk::gdk::Paintable; -use gtk::{glib, prelude::*, AspectFrame, Box, Entry, Label, ListBox}; -use gtk::{Application, ApplicationWindow, Button}; +use gtk::{glib, prelude::*, AspectFrame, Label, ListBox}; +use gtk::{Application, ApplicationWindow}; use log::{info, error}; use serde::{Deserialize, Serialize}; use tokio::runtime::Handle; -use tokio_tungstenite::tungstenite::Message; -use crate::config::{load_config, save_config}; +use crate::config::load_config; use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent}; use crate::remote_sources::TrackerState; mod socket_panel; +mod tracker_panel; + use socket_panel::SocketPanel; +use tracker_panel::TrackerPanel; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct AppState { @@ -89,7 +89,7 @@ pub fn build_ui(app: &Application, runtime: Handle) { let tracker_state = Arc::new(Mutex::new(TrackerState { tracking_id: 0, last_detect: Instant::now(), - has_active_connection: false, + enabled: true, })); @@ -109,12 +109,17 @@ pub fn build_ui(app: &Application, runtime: Handle) { .build(); let tabpanel = gtk::Notebook::builder() + .enable_popup(true) .build(); let socket_panel = Arc::new(SocketPanel::new(&initial_settings)); socket_panel.connect_button_callback(to_mec.clone()); tabpanel.append_page(socket_panel.get_top_level(), Some(>k::Label::new(Some("Cam Connection")))); + let tracker_panel = TrackerPanel::new(); + tracker_panel.connect_button_callback(to_mec.clone()); + tabpanel.append_page(tracker_panel.get_top_level(), Some(&Label::new(Some("Auto Settings")))); + let axis_label = Label::builder() .label("X: 0 Y: )") .justify(gtk::Justification::Center) @@ -156,7 +161,7 @@ pub fn build_ui(app: &Application, runtime: Handle) { glib::spawn_future_local( - glib::clone!(@weak axis_label, @weak conn_status_label, @strong socket_panel, @strong gui_recv, @weak drawable => async move { + glib::clone!(@weak axis_label, @weak conn_status_label, @weak tabpanel, @strong socket_panel, @strong gui_recv, @weak drawable => async move { while let Ok(d) = gui_recv.recv().await { drawable.queue_draw(); match d { @@ -169,9 +174,12 @@ pub fn build_ui(app: &Application, runtime: Handle) { let label = { if v { socket_panel.set_sensitive(false); + // tabpanel.set_show_tabs(true); "Currently Connected" } else { socket_panel.set_sensitive(true); + tabpanel.set_page(0); + // tabpanel.set_show_tabs(false); "Currently Disconnected" } }; diff --git a/src/ui/socket_panel.rs b/src/ui/socket_panel.rs index bc8b688..9720638 100644 --- a/src/ui/socket_panel.rs +++ b/src/ui/socket_panel.rs @@ -1,5 +1,5 @@ use async_channel::Sender; -use gtk::{glib::{self, GString}, prelude::{BoxExt, ButtonExt, EditableExt, WidgetExt}, Box, Button, Entry}; +use gtk::{glib, prelude::{BoxExt, ButtonExt, EditableExt, WidgetExt}, Box, Button, Entry}; use log::error; use crate::{config::save_config, coordinator::ApplicationEvent}; @@ -63,14 +63,6 @@ impl SocketPanel { self.connect_button.set_label(new_label); } - pub fn get_ip_text(&self) -> GString { - self.ip_entry.text() - } - - pub fn get_port_text(&self) -> GString { - self.port_entry.text() - } - pub fn connect_button_callback(&self, to_mec: Sender) { let ip_entry = &self.ip_entry; diff --git a/src/ui/tracker_panel.rs b/src/ui/tracker_panel.rs new file mode 100644 index 0000000..ee4270c --- /dev/null +++ b/src/ui/tracker_panel.rs @@ -0,0 +1,59 @@ +use async_channel::Sender; +use gtk::{prelude::{BoxExt, ButtonExt, ToggleButtonExt}, Box, Label, ToggleButton}; +use log::error; + +use crate::coordinator::ApplicationEvent; + + +pub struct TrackerPanel { + top_level: Box, + + enable_disable: ToggleButton, + current_id: Label, + +} + +impl TrackerPanel { + pub fn new() -> TrackerPanel { + + let top_level = Box::builder() + .orientation(gtk::Orientation::Vertical) + .spacing(5) + .margin_top(24) + .margin_start(24) + .margin_end(24) + .margin_bottom(12) + .build(); + + let enable_disable = ToggleButton::with_label("Enable Automatic Tracking"); + + let current_id = Label::builder() + .label("") + .can_focus(false) + .can_target(false) + .build(); + + top_level.append(&enable_disable); + top_level.append(¤t_id); + + TrackerPanel { + top_level, + + enable_disable, + current_id, + } + } + + pub fn get_top_level(&self) -> &Box { + &self.top_level + } + + pub fn connect_button_callback(&self, to_mec: Sender) { + + self.enable_disable.connect_clicked(move |button| { + if let Err(e) = to_mec.send_blocking(ApplicationEvent::EnableAutomatic(button.is_active())) { + error!("Could not send message to the MEC: {e}"); + } + }); + } +} \ No newline at end of file