use crate::ui::{
asset_tree::{AssetTree, TreeSelection},
window_common::{gled_window_frame, raise, tool_window_builder},
};
use egui::{ComboBox, Id, TextEdit, Ui, Vec2, ViewportId};
use gled_model::{
asset::{
Asset,
output_device::{OutputDevice, OutputDeviceKind},
},
collection::Collections,
};
use strum::IntoEnumIterator;
#[derive(Debug, Default)]
pub(crate) struct OutputDevicesWindow {
open: bool,
raise: bool,
dirty: bool,
tree: AssetTree<OutputDevice>,
device_strings: DeviceStrings,
}
#[derive(Debug, Default)]
struct DeviceStrings {
ip: Option<String>,
universes: Option<String>,
}
impl OutputDevicesWindow {
#[cfg_attr(feature = "profiling", profiling::function)]
pub(crate) fn update(&mut self, ctx: &egui::Context, collections: &mut Collections) {
if !self.open {
return;
}
ctx.show_viewport_immediate(
ViewportId(Id::new("output devices window")),
tool_window_builder("Output Devices")
.with_inner_size(Vec2::new(570.0, 500.0))
.with_min_inner_size(Vec2::new(570.0, 500.0)),
|ctx, _viewport_class| {
raise(ctx, &mut self.raise);
ctx.input(|input| {
if input.viewport().close_requested()
|| crate::ui::window_common::embedded_close_clicked("Output Devices")
{
self.open = false;
}
});
gled_window_frame(ctx, "Output Devices", |ui| {
egui::Panel::left("output devices tree")
.exact_size(200.0)
.resizable(false)
.show(ui, |ui| {
if self.tree.show(
ui,
ui.make_persistent_id("output_devices_tree"),
collections,
) {
self.dirty = false;
self.device_strings = Default::default();
}
});
egui::CentralPanel::default().show(ui, |ui| {
self.tree.common_settings(ui, &mut self.dirty, collections);
if let TreeSelection::Asset(output_device) = &mut self.tree.selected() {
output_device_editor(
ui,
output_device,
&mut self.dirty,
&mut self.device_strings,
);
}
});
});
},
);
}
pub(crate) fn open(&mut self) {
self.open = true;
self.raise = true;
}
}
fn output_device_editor(
ui: &mut Ui,
output_device: &mut Asset<OutputDevice>,
dirty: &mut bool,
device_strings: &mut DeviceStrings,
) {
let mut kind = OutputDeviceKind::from(&output_device.data);
let id = output_device.id;
ui.label("Kind");
ComboBox::new(format!("{id}_kind"), "")
.selected_text(<&'static str>::from(kind))
.width(290.0)
.show_ui(ui, |ui| {
for k in OutputDeviceKind::iter() {
if ui
.selectable_value(&mut kind, k, <&'static str>::from(k))
.changed()
{
match kind {
OutputDeviceKind::Artnet => {
output_device.data = OutputDevice::Artnet {
ip: [127, 0, 0, 1].into(),
universes: vec![],
}
}
OutputDeviceKind::EnttecDmxUsbPro => {
output_device.data = OutputDevice::EnttecDmxUsbPro {
serial_number: String::new(),
}
}
}
*device_strings = Default::default();
*dirty = true;
}
}
});
if let Some(ip) = output_device.data.ip() {
ui.heading("IP-Address");
let ip = device_strings.ip.get_or_insert_with(|| ip.to_string());
if ui.add(TextEdit::singleline(ip)).changed()
&& let Ok(ip) = ip.parse()
{
output_device.data.set_ip(ip);
*dirty = true;
}
}
if let OutputDevice::Artnet { universes, .. } = &output_device.data {
ui.heading("Universes:");
let universes = device_strings.universes.get_or_insert_with(|| {
universes
.iter()
.map(|universe| universe.to_string())
.collect::<Vec<_>>()
.join(", ")
});
if ui.add(TextEdit::singleline(universes)).changed() {
let universes = universes
.split(',')
.map(|universe| universe.trim().parse().unwrap_or_default())
.collect();
output_device.data.set_univeres(universes);
*dirty = true;
}
}
if let OutputDevice::EnttecDmxUsbPro { serial_number } = &output_device.data {
ui.heading("Serial Number:");
let mut serial_number = serial_number.clone();
ComboBox::new(format!("{id}_serial_number"), "")
.selected_text(serial_number.clone())
.width(290.0)
.show_ui(ui, |ui| {
for sn in crate::ui::frame_requests::devices().enttec {
if ui
.selectable_value(&mut serial_number, sn.clone(), sn)
.changed()
{
output_device.data = OutputDevice::EnttecDmxUsbPro {
serial_number: serial_number.clone(),
};
*dirty = true;
}
}
});
}
}