moved socket controls ui to seperate file
This commit is contained in:
parent
3cb560093c
commit
b286aedd03
3 changed files with 123 additions and 68 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
@ -15,6 +16,9 @@ use crate::config::{load_config, save_config};
|
||||||
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
||||||
use crate::remote_sources::TrackerState;
|
use crate::remote_sources::TrackerState;
|
||||||
|
|
||||||
|
mod socket_panel;
|
||||||
|
use socket_panel::SocketPanel;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub ip: String,
|
pub ip: String,
|
||||||
|
@ -73,8 +77,8 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
let window = ApplicationWindow::builder()
|
let window = ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.title("VCC Camera Controller")
|
.title("VCC Camera Controller")
|
||||||
// .default_width(840)
|
.default_width(840)
|
||||||
// .default_height(480)
|
.default_height(480)
|
||||||
.child(&main_box)
|
.child(&main_box)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -104,31 +108,12 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
.can_focus(true)
|
.can_focus(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let content_box = Box::builder()
|
let tabpanel = gtk::Notebook::builder()
|
||||||
.orientation(gtk::Orientation::Vertical)
|
|
||||||
.spacing(10)
|
|
||||||
.margin_top(12)
|
|
||||||
.margin_start(24)
|
|
||||||
.margin_end(24)
|
|
||||||
.margin_bottom(12)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let ip_entry = Entry::builder()
|
let socket_panel = Arc::new(SocketPanel::new(&initial_settings));
|
||||||
.placeholder_text("IP Address")
|
socket_panel.connect_button_callback(to_mec.clone());
|
||||||
.text(initial_settings.ip)
|
tabpanel.append_page(socket_panel.get_top_level(), Some(>k::Label::new(Some("Cam Connection"))));
|
||||||
.can_focus(true)
|
|
||||||
.build();
|
|
||||||
let port_entry = Entry::builder()
|
|
||||||
.placeholder_text("Port")
|
|
||||||
.text(initial_settings.port.to_string())
|
|
||||||
.can_focus(true)
|
|
||||||
.build();
|
|
||||||
let button = Button::builder().margin_top(12).build();
|
|
||||||
let button2 = Button::builder().margin_top(12).build();
|
|
||||||
|
|
||||||
content_box.append(&ip_entry);
|
|
||||||
content_box.append(&port_entry);
|
|
||||||
content_box.append(&button);
|
|
||||||
|
|
||||||
let axis_label = Label::builder()
|
let axis_label = Label::builder()
|
||||||
.label("X: 0 Y: )")
|
.label("X: 0 Y: )")
|
||||||
|
@ -136,16 +121,14 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
.css_classes(vec!["JoystickCurrent"])
|
.css_classes(vec!["JoystickCurrent"])
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
left_box.append(&conn_status_label);
|
left_box.append(&conn_status_label);
|
||||||
left_box.append(&content_box);
|
left_box.append(&tabpanel);
|
||||||
left_box.append(&axis_label);
|
left_box.append(&axis_label);
|
||||||
left_box.append(&button2);
|
|
||||||
|
|
||||||
main_box.append(&left_box);
|
main_box.append(&left_box);
|
||||||
|
|
||||||
let webcam_picture = gtk::Picture::builder()
|
let webcam_picture = gtk::Picture::builder()
|
||||||
// .height_request(270)
|
|
||||||
.width_request(640)
|
|
||||||
.can_focus(false)
|
.can_focus(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -171,40 +154,9 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
overlay_box.set_child(Some(&webcam_picture));
|
overlay_box.set_child(Some(&webcam_picture));
|
||||||
overlay_box.add_overlay(&drawable);
|
overlay_box.add_overlay(&drawable);
|
||||||
|
|
||||||
// Connect to "clicked" signal of `button`
|
|
||||||
button.connect_clicked(glib::clone!(@weak ip_entry, @weak port_entry, @strong to_mec => move |_button| {
|
|
||||||
let ip_text = ip_entry.text();
|
|
||||||
let port_text = port_entry.text();
|
|
||||||
|
|
||||||
if ip_text.len() == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let Ok(val) = port_text.parse::<u32>() {
|
|
||||||
if let Err(error) = save_config(&AppState {
|
|
||||||
ip: ip_text.to_string(),
|
|
||||||
port: val
|
|
||||||
}) {
|
|
||||||
error!("{error}");
|
|
||||||
};
|
|
||||||
|
|
||||||
match to_mec.try_send(ApplicationEvent::StartSocket(
|
|
||||||
format!("ws://{}:{}", ip_text, val),
|
|
||||||
)) {
|
|
||||||
Ok(_) => {},
|
|
||||||
Err(async_channel::TrySendError::Closed(_)) => panic!("Coordinator MEC is closed. Unrecoverable error."),
|
|
||||||
Err(e) => error!("There was an error sending to the MEC: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
button2.connect_clicked(glib::clone!(@strong to_mec => move |_button| {
|
|
||||||
if let Err(e) = to_mec.try_send(ApplicationEvent::SocketMessage(Message::text("U45:L10"))) {
|
|
||||||
panic!("There was an error in connect clicked: {e}");
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
glib::spawn_future_local(
|
glib::spawn_future_local(
|
||||||
glib::clone!(@weak axis_label, @weak button, @weak conn_status_label, @weak ip_entry, @weak port_entry, @strong gui_recv, @weak drawable => async move {
|
glib::clone!(@weak axis_label, @weak conn_status_label, @strong socket_panel, @strong gui_recv, @weak drawable => async move {
|
||||||
while let Ok(d) = gui_recv.recv().await {
|
while let Ok(d) = gui_recv.recv().await {
|
||||||
drawable.queue_draw();
|
drawable.queue_draw();
|
||||||
match d {
|
match d {
|
||||||
|
@ -216,24 +168,22 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
GuiUpdate::SocketState(v) => {
|
GuiUpdate::SocketState(v) => {
|
||||||
let label = {
|
let label = {
|
||||||
if v {
|
if v {
|
||||||
ip_entry.set_sensitive(false);
|
socket_panel.set_sensitive(false);
|
||||||
port_entry.set_sensitive(false);
|
|
||||||
"Currently Connected"
|
"Currently Connected"
|
||||||
} else {
|
} else {
|
||||||
ip_entry.set_sensitive(true);
|
socket_panel.set_sensitive(true);
|
||||||
port_entry.set_sensitive(true);
|
|
||||||
"Currently Disconnected"
|
"Currently Disconnected"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
button.set_label(label);
|
socket_panel.button_label(label);
|
||||||
conn_status_label.set_label(label);
|
conn_status_label.set_label(label);
|
||||||
if v {
|
if v {
|
||||||
conn_status_label.set_css_classes(&["YesConnection"]);
|
conn_status_label.set_css_classes(&["YesConnection"]);
|
||||||
button.set_css_classes(&["YesConnection"]);
|
// button.set_css_classes(&["YesConnection"]);
|
||||||
} else {
|
} else {
|
||||||
conn_status_label.set_css_classes(&["NoConnection"]);
|
conn_status_label.set_css_classes(&["NoConnection"]);
|
||||||
button.set_css_classes(&["NoConnection"]);
|
// button.set_css_classes(&["NoConnection"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GuiUpdate::UpdatePaintable(sink) => {
|
GuiUpdate::UpdatePaintable(sink) => {
|
||||||
|
|
104
src/ui/socket_panel.rs
Normal file
104
src/ui/socket_panel.rs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
use async_channel::Sender;
|
||||||
|
use gtk::{glib::{self, GString}, prelude::{BoxExt, ButtonExt, EditableExt, WidgetExt}, Box, Button, Entry};
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
use crate::{config::save_config, coordinator::ApplicationEvent};
|
||||||
|
|
||||||
|
use super::AppState;
|
||||||
|
|
||||||
|
pub struct SocketPanel {
|
||||||
|
top_level: Box,
|
||||||
|
|
||||||
|
ip_entry: Entry,
|
||||||
|
port_entry: Entry,
|
||||||
|
connect_button: Button,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SocketPanel {
|
||||||
|
pub fn new(initial_settings: &crate::ui::AppState) -> SocketPanel {
|
||||||
|
|
||||||
|
let content_box = Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Vertical)
|
||||||
|
.spacing(10)
|
||||||
|
.margin_top(12)
|
||||||
|
.margin_start(24)
|
||||||
|
.margin_end(24)
|
||||||
|
.margin_bottom(12)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let ip_entry = Entry::builder()
|
||||||
|
.placeholder_text("IP Address")
|
||||||
|
.text(&initial_settings.ip)
|
||||||
|
.can_focus(true)
|
||||||
|
.build();
|
||||||
|
let port_entry = Entry::builder()
|
||||||
|
.placeholder_text("Port")
|
||||||
|
.text(&initial_settings.port.to_string())
|
||||||
|
.can_focus(true)
|
||||||
|
.build();
|
||||||
|
let button = Button::builder().margin_top(12).build();
|
||||||
|
|
||||||
|
content_box.append(&ip_entry);
|
||||||
|
content_box.append(&port_entry);
|
||||||
|
content_box.append(&button);
|
||||||
|
|
||||||
|
SocketPanel {
|
||||||
|
top_level: content_box,
|
||||||
|
ip_entry,
|
||||||
|
port_entry,
|
||||||
|
connect_button: button,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_top_level(&self) -> &Box {
|
||||||
|
&self.top_level
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sensitive(&self, is_sensitive: bool) {
|
||||||
|
self.ip_entry.set_sensitive(is_sensitive);
|
||||||
|
self.port_entry.set_sensitive(is_sensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_label(&self, new_label: &str) {
|
||||||
|
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<ApplicationEvent>) {
|
||||||
|
|
||||||
|
let ip_entry = &self.ip_entry;
|
||||||
|
let port_entry = &self.port_entry;
|
||||||
|
|
||||||
|
self.connect_button.connect_clicked(glib::clone!(@weak ip_entry, @weak port_entry, @strong to_mec => move |_button| {
|
||||||
|
let ip_text = ip_entry.text();
|
||||||
|
let port_text = port_entry.text();
|
||||||
|
|
||||||
|
if ip_text.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Ok(val) = port_text.parse::<u32>() {
|
||||||
|
if let Err(error) = save_config(&AppState {
|
||||||
|
ip: ip_text.to_string(),
|
||||||
|
port: val
|
||||||
|
}) {
|
||||||
|
error!("{error}");
|
||||||
|
};
|
||||||
|
|
||||||
|
match to_mec.try_send(ApplicationEvent::StartSocket(
|
||||||
|
format!("ws://{}:{}", ip_text, val),
|
||||||
|
)) {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(async_channel::TrySendError::Closed(_)) => panic!("Coordinator MEC is closed. Unrecoverable error."),
|
||||||
|
Err(e) => error!("There was an error sending to the MEC: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
entry {
|
entry {
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue