Skip to content

Commit 9d87621

Browse files
Made sidebars configurable
1 parent 6c7afd5 commit 9d87621

11 files changed

Lines changed: 150 additions & 38 deletions

File tree

build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ fn main() {
22
slint_build::compile_with_config(
33
"ui/main.slint",
44
slint_build::CompilerConfiguration::new()
5-
.with_style("material-dark".into())
5+
.with_style("material".into())
66
.embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer),
77
)
88
.expect("Slint build failed");

example_configs/simulator.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@ port = 7125
88

99
[heater_presets]
1010
extruder = [ 200, 240, 280 ]
11-
heater_bed = [ 60, 70 ]
11+
heater_bed = [ 60, 70 ]
12+
13+
[ui]
14+
dark_mode = false
15+
left_sidebar = ["files", "temperature", "move", "emergency_stop"]
16+
right_sidebar = ["fan", "macros", "console", "settings"]

src/config/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
22

3-
use crate::config::{MoonrakerConfig, OptionalGcodeCommands};
3+
use crate::config::{MoonrakerConfig, OptionalGcodeCommands, OptionalUiConfig};
44
use moonraker_rs::printer_objects::TemperatureConfiguration;
55
use serde::Deserialize;
66

@@ -12,4 +12,5 @@ pub struct Config {
1212
pub moonraker: Option<MoonrakerConfig>,
1313
pub heater_presets: Option<HashMap<String, Vec<u32>>>,
1414
pub gcode_commands: Option<OptionalGcodeCommands>,
15+
pub ui: Option<OptionalUiConfig>,
1516
}

src/config/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod display_default;
66
pub mod display_fb;
77
pub mod moonraker;
88
pub mod gcode_commands;
9+
pub mod ui;
910

1011
pub use cli::*;
1112
pub use config::*;
@@ -15,3 +16,4 @@ pub use display_default::*;
1516
pub use display_fb::*;
1617
pub use moonraker::*;
1718
pub use gcode_commands::*;
19+
pub use ui::*;

src/config/ui.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use optional_struct::optional_struct;
2+
use serde::Deserialize;
3+
4+
#[optional_struct]
5+
#[derive(Deserialize, Debug)]
6+
pub struct UiConfig {
7+
pub dark_mode: bool,
8+
pub left_sidebar: Vec<String>,
9+
pub right_sidebar: Vec<String>,
10+
}
11+
12+
impl UiConfig {
13+
pub fn from_optional(ui_config : &OptionalUiConfig) -> UiConfig {
14+
UiConfig {
15+
dark_mode: ui_config.dark_mode.unwrap_or(UiConfig::default().dark_mode),
16+
left_sidebar: ui_config.left_sidebar.clone().unwrap_or(UiConfig::default().left_sidebar),
17+
right_sidebar: ui_config.right_sidebar.clone().unwrap_or(UiConfig::default().right_sidebar),
18+
}
19+
}
20+
}
21+
22+
impl Default for UiConfig {
23+
fn default() -> Self {
24+
Self {
25+
dark_mode: true,
26+
left_sidebar: vec![
27+
"files".into(),
28+
"temperature".into(),
29+
"move".into(),
30+
"emergency_stop".into(),
31+
],
32+
right_sidebar: vec![
33+
"fan".into(),
34+
"macros".into(),
35+
"console".into(),
36+
"settings".into(),
37+
],
38+
}
39+
}
40+
}

src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use moonraker_rs::{
88
cache::Cache, connector::{read_deserialize::OptionalPrinterEvent}, printer_objects::{NamedOptionalTemperatureFan, OptionalExtruder, OptionalHeaterBed, OptionalTemperatureFan, TemperatureConfiguration},
99
};
1010

11-
use crate::{config::{MoonrakerConfig, OptionalGcodeCommands}, event_loop::EventLoop, hardware::init_display, ui_functions::*};
11+
use crate::{config::{MoonrakerConfig, OptionalGcodeCommands, OptionalUiConfig}, event_loop::EventLoop, hardware::init_display, ui_functions::*};
1212

1313
mod application_error;
1414
mod config;
@@ -101,6 +101,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
101101
register_extruder_load_filament(&ui, &moonraker_connection, gcode_command_config);
102102
register_extruder_unload_filament(&ui, &moonraker_connection, gcode_command_config);
103103

104+
let ui_settings = &config.ui.unwrap_or(OptionalUiConfig::default());
105+
register_set_ui_settings(&ui, &ui_settings);
106+
104107
tokio::task::block_in_place(|| {
105108
ui.run().unwrap();
106109
});

src/ui_functions/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod printer_restart;
99
pub mod printer_firmware_restart;
1010
pub mod printer_execute_gcode_command;
1111
pub mod util_create_temperature_list;
12+
pub mod settings_set_ui_settings;
1213

1314
pub use util_format_bytes::*;
1415
pub use filesystem_download_thumbnail::*;
@@ -20,4 +21,5 @@ pub use printer_emergency_stop::*;
2021
pub use printer_restart::*;
2122
pub use printer_firmware_restart::*;
2223
pub use printer_execute_gcode_command::*;
23-
pub use util_create_temperature_list::*;
24+
pub use util_create_temperature_list::*;
25+
pub use settings_set_ui_settings::*;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use std::sync::Arc;
2+
3+
use moonraker_rs::{moonraker_connection::MoonrakerConnection, requests::PrinterAdministrationRequestHandler};
4+
use slint::{ComponentHandle, ModelRc, VecModel};
5+
6+
use crate::{config::{OptionalUiConfig, UiConfig}, AppWindow, PrinterAdministration, UiSettings};
7+
8+
9+
pub fn name_to_id(name : &str) -> i32
10+
{
11+
match name {
12+
"files" => 0,
13+
"temperature" => 1,
14+
"move" => 2,
15+
"emergency_stop" => 3,
16+
"fan" => 4,
17+
"macros" => 5,
18+
"console" => 6,
19+
"settings" => 7,
20+
_ => panic!("Unknown menu {} for left/right sidebar", name)
21+
}
22+
}
23+
24+
pub fn register_set_ui_settings(ui : &AppWindow, configuration : &OptionalUiConfig)
25+
{
26+
let configuration = UiConfig::from_optional(configuration);
27+
28+
let left_sidebar: Vec<i32> = configuration.left_sidebar.iter().map(|f| name_to_id(f)).collect();
29+
let right_sidebar: Vec<i32> = configuration.right_sidebar.iter().map(|f| name_to_id(f)).collect();
30+
31+
ui.global::<UiSettings>().set_dark_mode(configuration.dark_mode);
32+
ui.global::<UiSettings>().set_left_sidebar(ModelRc::new(VecModel::from(left_sidebar)));
33+
ui.global::<UiSettings>().set_right_sidebar(ModelRc::new(VecModel::from(right_sidebar)));
34+
}

ui/app-window.slint

Lines changed: 0 additions & 18 deletions
This file was deleted.

ui/main.slint

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ProgressIndicator, Button, StyleMetrics, Palette, ScrollView, Slider, ComboBox, TabWidget } from "std-widgets.slint";
22
import { VirtualKeyboardButton } from "virtual_keyboard.slint";
33
import "../AdwaitaSans-Regular.ttf";
4-
import { TemperatureSensors, DisplayStatus, PrinterAdministration, GcodeCommands, Filesystem, Utils, Webhooks } from "state.slint";
4+
import { TemperatureSensors, DisplayStatus, PrinterAdministration, GcodeCommands, Filesystem, Utils, Webhooks, UiSettings } from "state.slint";
55
import { Heater, TemperatureSensor, MoonrakerFile } from "types.slint";
66
import { Icons } from "constants.slint";
77
import { Page } from "components/page.slint";
@@ -89,20 +89,34 @@ component MainView inherits Rectangle
8989
property <bool> is_emergency_prompt_open: false;
9090
background: Palette.alternate-background;
9191

92+
93+
9294
VerticalLayout {
9395
TopBar {
9496

9597
}
9698

9799
HorizontalLayout {
98-
VerticalLayout {
100+
if UiSettings.left-sidebar.length > 0: VerticalLayout {
99101
min-width: 50px;
100102
spacing: 5px;
101103

102-
LeftSideIconButton { icon: Icons.print; checked: root.current-page == 0; clicked => { root.current-page = 0; } }
103-
LeftSideIconButton { icon: Icons.temperature; checked: root.current-page == 1; clicked => { root.current-page = 1; } }
104-
LeftSideIconButton { icon: Icons.move; checked: root.current-page == 2; clicked => { root.current-page = 2; } }
105-
LeftSideIconButton { icon: Icons.emergency_stop; checked: root.current-page == 3; clicked => { is_emergency_prompt_open = true; } foreground: red; }
104+
for component in UiSettings.left-sidebar: LeftSideIconButton {
105+
icon: UiSettings.id-to-image[component];
106+
checked: root.current-page == component;
107+
clicked => {
108+
if (component == 3) {
109+
is_emergency_prompt_open = true;
110+
} else {
111+
current-page = component;
112+
}
113+
}
114+
foreground: component == 3
115+
? red
116+
: root.current-page == component
117+
? Palette.accent-foreground
118+
: Palette.foreground;
119+
}
106120
}
107121

108122
Rectangle {
@@ -118,14 +132,26 @@ component MainView inherits Rectangle
118132
if root.current-page == 6: ExtruderPage {}
119133
}
120134

121-
VerticalLayout {
135+
if UiSettings.right-sidebar.length > 0:VerticalLayout {
122136
spacing: 5px;
123137
min-width: 50px;
124138

125-
RightSideIconButton { icon: Icons.fan; checked: root.current-page == 4; clicked => { root.current-page = 4; } }
126-
RightSideIconButton { icon: Icons.quick_action; checked: root.current-page == 5; clicked => { root.current-page = 5; }}
127-
RightSideIconButton { icon: Icons.console; checked: root.current-page == 6; clicked => { root.current-page = 6; } }
128-
RightSideIconButton { icon: Icons.settings; checked: root.current-page == 7; clicked => { root.current-page = 7; } }
139+
for component in UiSettings.right-sidebar: RightSideIconButton {
140+
icon: UiSettings.id-to-image[component];
141+
checked: root.current-page == component;
142+
clicked => {
143+
if (component == 3) {
144+
is_emergency_prompt_open = true;
145+
} else {
146+
current-page = component;
147+
}
148+
}
149+
foreground: component == 3
150+
? red
151+
: root.current-page == component
152+
? Palette.accent-foreground
153+
: Palette.foreground;
154+
}
129155
}
130156
}
131157

0 commit comments

Comments
 (0)