diff --git a/widget/src/show_popup.rs b/widget/src/show_popup.rs index ba03184..eb1e50b 100644 --- a/widget/src/show_popup.rs +++ b/widget/src/show_popup.rs @@ -12,6 +12,7 @@ use i_slint_backend_winit::{ slint::include_modules!(); +/// Derive temperature unit symbol for the configured units fn unit_symbol(units: &str) -> char { match units { "metric" => 'C', @@ -21,58 +22,6 @@ fn unit_symbol(units: &str) -> char { } } -pub fn show_popup(resp: &WeatherResponse, cfg: &Config) -> Result<(), Box> { - // Closure that adjusts winit WindowAttributes before Slint creates the window. - let window_attrs = |attrs: WindowAttributes| { - // Mark the X11 window as a DOCK so the WM treats it as a top bar/panel. - attrs.with_x11_window_type(vec![WindowType::Dock]) - }; - - // Build a Slint backend that applies this attribute hook to all windows. - let backend = Backend::builder() - .with_window_attributes_hook(window_attrs) // Register the hook - .build()?; // Construct backend - - // Activate this customized backend for all Slint window creation and events. - slint::platform::set_platform(Box::new(backend))?; - - let ui = MainWindow::new()?; - - let city = resp.name.clone().unwrap_or_else(|| "Unknown".into()); - let country = resp - .sys - .as_ref() - .and_then(|s| s.country.clone()) - .unwrap_or_default(); - - let (weather_main, weather_description, icon_code) = resp.weather.first().map_or_else( - || ("N/A".into(), "N/A".into(), String::new()), - |w| (w.main.clone(), w.description.clone(), w.icon.clone()), - ); - - let temp = resp.main.as_ref().and_then(|m| m.temp).unwrap_or(0.0); - let temperature = format!("{temp:.1}"); - - let unit_symbol = unit_symbol(cfg.query_params.units.as_str()); - - ui.set_city(SharedString::from(city)); - ui.set_country(SharedString::from(country)); - ui.set_weather_main(SharedString::from(weather_main)); - ui.set_weather_description(SharedString::from(weather_description)); - ui.set_weather_icon(SharedString::from(icon_to_nerd_font(&icon_code))); - ui.set_temperature(SharedString::from(temperature)); - ui.set_unit(SharedString::from(unit_symbol)); - - #[allow(clippy::cast_precision_loss)] - ui.window().set_size(LogicalSize::new(300.0, 124.0)); - - // Position the window (bar) at the top-left. - ui.window().set_position(LogicalPosition::new(0.0, 0.0)); - - ui.run()?; - Ok(()) -} - /// Convert OWM icon codes (e.g. "01d", "09n") to Nerd Font weather glyphs. fn icon_to_nerd_font(code: &str) -> String { match code { @@ -90,3 +39,68 @@ fn icon_to_nerd_font(code: &str) -> String { } .into() } + +/// Set Slint properties from weather data +fn set_ui_props(ui: &MainWindow, resp: &WeatherResponse, cfg: &Config) { + // Extract data + let city = resp.name.clone().unwrap_or_else(|| "Unknown".into()); + let country = resp + .sys + .as_ref() + .and_then(|s| s.country.clone()) + .unwrap_or_default(); + + let (weather_main, weather_description, icon_code) = resp.weather.first().map_or_else( + || ("N/A".into(), "N/A".into(), String::new()), + |w| (w.main.clone(), w.description.clone(), w.icon.clone()), + ); + + let temp = resp.main.as_ref().and_then(|m| m.temp).unwrap_or(0.0); + let temperature = format!("{temp:.1}"); + + let unit = unit_symbol(cfg.query_params.units.as_str()); + + // Set UI elements + ui.set_city(SharedString::from(city)); + ui.set_country(SharedString::from(country)); + ui.set_weather_main(SharedString::from(weather_main)); + ui.set_weather_description(SharedString::from(weather_description)); + ui.set_weather_icon(SharedString::from(icon_to_nerd_font(&icon_code))); + ui.set_temperature(SharedString::from(temperature)); + ui.set_unit(SharedString::from(unit)); + + // Window size (width, height): pixels + #[allow(clippy::cast_precision_loss)] + ui.window().set_size(LogicalSize::new(300.0, 124.0)); + + // Window position (x,y): pixels + ui.window().set_position(LogicalPosition::new(1610.0, 32.0)); +} + +/// Create and show the Window UI +pub fn show_popup(resp: &WeatherResponse, cfg: &Config) -> Result<(), Box> { + // Closure that adjusts winit WindowAttributes before Slint creates the window. + let window_attrs = |attrs: WindowAttributes| { + // Mark the X11 window as a DOCK so the WM doesn't treat it as a normal window + attrs.with_x11_window_type(vec![WindowType::Dock]) + }; + + // Build a Slint backend that applies this attribute hook to all windows. + let backend = Backend::builder() + .with_window_attributes_hook(window_attrs) // Register the hook + .build()?; // Construct backend + + // Activate this customized backend for all Slint window creation and events. + slint::platform::set_platform(Box::new(backend))?; + + // Create window + let ui = MainWindow::new()?; + + // Send the weather data to the UI as properties + set_ui_props(&ui, resp, cfg); + + // Run the UI + ui.run()?; + + Ok(()) +}