feat(stardust): start/stop & server settings

This commit is contained in:
Gabriele Musco 2023-12-06 21:30:04 +00:00
parent 468fd9a269
commit eb7fdb2b08
2 changed files with 213 additions and 13 deletions

View file

@ -17,6 +17,7 @@ use crate::ui::app::{
BuildProfileDebugAction, ConfigFbtAction, DebugViewToggleAction,
};
use crate::ui::profile_editor::ProfileEditorInit;
use crate::ui::stardust::stardust_view::StardustViewInit;
use crate::ui::util::{limit_dropdown_width, warning_heading};
use crate::xr_devices::XRDevice;
use gtk::prelude::*;
@ -49,7 +50,7 @@ pub struct MainView {
#[tracker::do_not_track]
root_win: gtk::Window,
#[tracker::do_not_track]
stardust_view: Controller<StardustView>
stardust_view: Controller<StardustView>,
}
#[derive(Debug)]
@ -382,7 +383,7 @@ impl SimpleComponent for MainView {
set_title: Some("XR"),
set_icon_name: Some("org.gabmus.envision-symbolic"),
},
add_titled_with_icon: (model.stardust_view.widget(), Some("stardust_view"), "Stardust", "starred-symbolic"),
add_titled_with_icon: (model.stardust_view.widget(), Some("stardust_view"), "Stardust XR", "starred-symbolic"),
},
add_bottom_bar: bottom_bar = &gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
@ -661,7 +662,7 @@ impl SimpleComponent for MainView {
profile_delete_confirm_dialog,
root_win: init.root_win.clone(),
profile_editor: None,
stardust_view: StardustView::builder().launch(()).detach(),
stardust_view: StardustView::builder().launch(StardustViewInit {}).detach(),
tracker: 0,
};
let widgets = view_output!();

View file

@ -1,34 +1,211 @@
use relm4::prelude::*;
use crate::{stateless_action, withclones};
use gtk::prelude::*;
use adw::prelude::*;
use relm4::{
actions::{ActionGroupName, RelmAction, RelmActionGroup},
new_action_group, new_stateless_action,
prelude::*,
};
#[derive(Debug)]
pub enum StardustViewMsg {}
pub enum StardustViewMsg {
BuildStardust,
UpdateStardust,
StartClicked,
StopClicked,
RestartClicked,
AutostartChanged(bool),
StartAsOvelayChanged(bool),
OverlayPriorityChanged(u32),
DisableControllerChanged(bool),
RepoChanged(String),
}
#[derive(Debug)]
pub enum StardustViewOutMsg {}
#[derive(Debug)]
pub struct StardustViewInit {}
#[tracker::track]
pub struct StardustView {}
pub struct StardustView {
stardust_service_active: bool,
}
#[relm4::component(pub)]
impl SimpleComponent for StardustView {
type Init = ();
type Init = StardustViewInit;
type Input = StardustViewMsg;
type Output = StardustViewOutMsg;
menu! {
stardust_menu: {
section! {
"_Build" => BuildStardustAction,
"_Update" => UpdateStardustAction,
}
}
}
view! {
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
gtk::Label {
set_label: "Stardust",
},
#[root]
gtk::ScrolledWindow {
set_hscrollbar_policy: gtk::PolicyType::Never,
set_hexpand: true,
set_vexpand: true,
adw::Clamp {
set_maximum_size: 600,
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 12,
set_margin_all: 12,
// service inactive
gtk::Box {
add_css_class: "linked",
set_orientation: gtk::Orientation::Horizontal,
set_hexpand: true,
set_vexpand: false,
#[track = "model.changed(Self::stardust_service_active())"]
set_visible: !model.stardust_service_active,
gtk::Button {
add_css_class: "suggested-action",
set_label: "Start",
set_hexpand: true,
connect_clicked[sender] => move |_| {
sender.input(Self::Input::StartClicked);
},
},
gtk::MenuButton {
set_icon_name: "view-more-symbolic",
set_menu_model: Some(&stardust_menu),
},
},
// service active
gtk::Box {
add_css_class: "linked",
set_orientation: gtk::Orientation::Horizontal,
set_hexpand: true,
set_vexpand: false,
#[track = "model.changed(Self::stardust_service_active())"]
set_visible: model.stardust_service_active,
gtk::Button {
add_css_class: "destructive-action",
set_label: "Stop",
set_hexpand: true,
connect_clicked[sender] => move |_| {
sender.input(Self::Input::StopClicked);
},
},
gtk::Button {
set_icon_name: "view-refresh-symbolic",
set_tooltip_text: Some("Restart"),
connect_clicked[sender] => move |_| {
sender.input(Self::Input::RestartClicked);
},
},
},
gtk::ListBox {
add_css_class: "boxed-list",
set_selection_mode: gtk::SelectionMode::None,
adw::SwitchRow {
set_title: "Autostart with XR Service",
// TODO: settings
// set_active: model.settings.autostart,
connect_active_notify[sender] => move |row| {
sender.input(Self::Input::AutostartChanged(row.is_active()));
}
},
adw::SwitchRow {
set_title: "Start as an overlay",
// TODO: settings
// set_active: model.settings.overlay,
connect_active_notify[sender] => move |row| {
sender.input(Self::Input::StartAsOvelayChanged(row.is_active()));
}
},
adw::SpinRow {
set_title: "Overlay priority",
set_digits: 0,
set_snap_to_ticks: true,
// TODO: settings -- here or in adj?
// set_value: model.settings.priority,
#[wrap(Some)]
set_adjustment: overlay_priority_adj = &gtk::Adjustment {
set_lower: 0.0,
set_upper: f64::from(u32::MAX),
set_value: 0.0,
set_page_increment: 10.0,
set_step_increment: 1.0,
// TODO: settings
// set_value: model.settings.priority,
},
set_range: (0.0, f64::from(u32::MAX)),
connect_value_notify[sender] => move |row| {
sender.input(Self::Input::OverlayPriorityChanged(row.value() as u32));
}
},
// WARN: negative logic, maybe switch it to positive instead?
adw::SwitchRow {
set_title: "Disable controller",
set_subtitle_lines: 0,
set_subtitle: "Necessary if you plan on using hand tracking",
// TODO: settings
// set_active: model.settings.autostart,
connect_active_notify[sender] => move |row| {
sender.input(Self::Input::DisableControllerChanged(row.is_active()));
}
},
adw::EntryRow {
set_title: "Repository#git ref",
// TODO: settings
// set_text: model.settings.repo,
set_text: "https://github.com/StardustXR/server#main",
connect_changed[sender] => move |row| {
sender.input(Self::Input::RepoChanged(row.text().into()));
}
},
},
}
}
}
}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
self.reset();
match message {}
match message {
Self::Input::BuildStardust => {
println!("Build");
},
Self::Input::UpdateStardust => {
println!("Update");
},
Self::Input::StartClicked => {
println!("Start");
},
Self::Input::StopClicked => {
println!("Stop");
},
Self::Input::RestartClicked => {
println!("Restart");
},
Self::Input::AutostartChanged(val) => {
println!("Autostart: {}", val);
}
Self::Input::StartAsOvelayChanged(val) => {
println!("StartAsOvelayChanged: {}", val);
}
Self::Input::OverlayPriorityChanged(val) => {
println!("OverlayPriorityChanged: {}", val);
}
Self::Input::DisableControllerChanged(val) => {
println!("DisableControllerChanged: {}", val);
}
Self::Input::RepoChanged(val) => {
println!("RepoChanged: {}", val);
}
};
}
fn init(
@ -37,11 +214,33 @@ impl SimpleComponent for StardustView {
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = Self {
stardust_service_active: false,
tracker: 0,
};
let widgets = view_output!();
let mut actions = RelmActionGroup::<StardustActionGroup>::new();
{
withclones![sender];
stateless_action!(actions, BuildStardustAction, {
sender.input_sender().emit(Self::Input::BuildStardust);
});
}
{
withclones![sender];
stateless_action!(actions, UpdateStardustAction, {
sender.input_sender().emit(Self::Input::UpdateStardust);
});
}
root.insert_action_group(StardustActionGroup::NAME, Some(&actions.into_action_group()));
ComponentParts { model, widgets }
}
}
new_action_group!(StardustActionGroup, "stardust");
new_stateless_action!(BuildStardustAction, StardustActionGroup, "build");
new_stateless_action!(UpdateStardustAction, StardustActionGroup, "update");