diff options
| author | Rubén Beltrán del Río <jj@r.bdr.sh> | 2026-03-26 23:18:11 +0100 |
|---|---|---|
| committer | Rubén Beltrán del Río <jj@r.bdr.sh> | 2026-03-26 23:26:01 +0100 |
| commit | 1f28cbdf1dbe26e4c7da27323a0202a3276cb3a7 (patch) | |
| tree | f5a707ed5671d0345b21c935f5a46099b12b8f19 /src | |
| parent | 9a472115e594e28f4e3bd95b10800bf2b690febf (diff) | |
Move footer to its own component
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/footer.rs | 97 | ||||
| -rw-r--r-- | src/components/mod.rs | 1 | ||||
| -rw-r--r-- | src/handlers/zoom.rs | 10 | ||||
| -rw-r--r-- | src/main.rs | 59 |
4 files changed, 117 insertions, 50 deletions
diff --git a/src/components/footer.rs b/src/components/footer.rs new file mode 100644 index 0000000..2576163 --- /dev/null +++ b/src/components/footer.rs @@ -0,0 +1,97 @@ +use gtk::prelude::*; +use relm4::prelude::*; +use relm4::actions::ActionablePlus; + +use crate::tr; +use crate::constants; + +use crate::{ + ZoomInAction, ZoomOutAction, actions::Action +}; +use crate::icon_names::shipped::{ ZOOM_IN_REGULAR, ZOOM_OUT_REGULAR }; + +// Model and Input Messages + +pub struct Footer { + zoom: f64, +} + +pub struct FooterInit { + pub zoom: f64, +} + +#[derive(Debug, Clone)] +pub enum FooterAction { + SetZoom(f64) +} + +#[relm4::component(pub)] +impl SimpleComponent for Footer { + type Init = FooterInit; + type Input = FooterAction; + type Output = Action; + + view! { + >k::ActionBar { + pack_end = >k::Box { + set_orientation: gtk::Orientation::Horizontal, + + gtk::Label { + #[watch] + set_label: &format!("{:.1}x", model.zoom), + set_margin_end: 5 + }, + + gtk::Button::with_label(&tr!("command.view.zoom_out")) { + set_icon_name: ZOOM_OUT_REGULAR, + set_margin_end: 5, + add_css_class: "flat", + add_css_class: "zoom", + add_css_class: "zoom-out", + ActionablePlus::set_stateless_action::<ZoomOutAction>: &(), + }, + + gtk::Scale { + set_orientation: gtk::Orientation::Horizontal, + set_range: (constants::MIN_ZOOM, constants::MAX_ZOOM), + #[watch] + set_value: model.zoom, + set_draw_value: false, + set_increments: (constants::ZOOM_STEP, constants::ZOOM_STEP), + set_value_pos: gtk::PositionType::Left, + set_width_request: 100, + connect_value_changed[sender] => move |scale| { + let _ = sender.output(Action::Zoom(scale.value())); + } + }, + + gtk::Button::with_label(&tr!("command.view.zoom_in")) { + set_icon_name: ZOOM_IN_REGULAR, + add_css_class: "flat", + add_css_class: "zoom", + add_css_class: "zoom-in", + ActionablePlus::set_stateless_action::<ZoomInAction>: &(), + }, + } + } + } + + fn init( + init: Self::Init, + root: Self::Root, + sender: ComponentSender<Self>, + ) -> ComponentParts<Self> { + let model = Footer { + zoom: init.zoom + }; + let widgets = view_output!(); + + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) { + match message { + FooterAction::SetZoom(zoom) => self.zoom = zoom + } + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index d32bbea..1194b9f 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -13,4 +13,5 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +pub mod footer; pub mod header; diff --git a/src/handlers/zoom.rs b/src/handlers/zoom.rs index 575f5f9..59a54a7 100644 --- a/src/handlers/zoom.rs +++ b/src/handlers/zoom.rs @@ -13,28 +13,30 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +use relm4::prelude::*; + use crate::AppModel; use crate::constants; +use crate::components::footer::FooterAction; /// Sets the zoom level and updates the rendered image. pub fn zoom(model: &mut AppModel, level: f64) { model.zoom = level; model.update_image(); + model.footer.emit(FooterAction::SetZoom(level)); } /// Decreases zoom by one step if above minimum. pub fn zoom_out(model: &mut AppModel) { let new_zoom = model.zoom - constants::ZOOM_STEP; if new_zoom >= constants::MIN_ZOOM { - model.zoom = new_zoom; - model.update_image(); + zoom(model, new_zoom); } } /// Increases zoom by one step if below maximum. pub fn zoom_in(model: &mut AppModel) { if model.zoom < constants::MAX_ZOOM { - model.zoom += constants::ZOOM_STEP; - model.update_image(); + zoom(model, model.zoom + constants::ZOOM_STEP); } } diff --git a/src/main.rs b/src/main.rs index c9393f4..f661df9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,11 +38,10 @@ use std::convert::identity; use std::path::PathBuf; use crate::actions::Action; -use crate::icon_names::shipped::{ ZOOM_IN_REGULAR, ZOOM_OUT_REGULAR }; use cairo::ImageSurface; use gtk::glib; use relm4::prelude::*; -use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup}; +use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup}; use adw::prelude::*; use sourceview5::LanguageManager; @@ -53,6 +52,7 @@ use wmap_parser::{Map, parse}; use wmap_renderer::{Configuration, StageType, render_to_surface}; use components::header::{Header, HeaderInit}; +use components::footer::{Footer, FooterInit}; /// Macro to reduce boilerplate when registering actions with accelerators. macro_rules! register_action { @@ -136,7 +136,8 @@ struct AppModel { editor_css_provider: gtk::CssProvider, horizontal_layout_enabled: bool, // Child Components - header: Controller<Header> + header: Controller<Header>, + footer: Controller<Footer>, } impl AppModel { @@ -355,48 +356,7 @@ impl SimpleComponent for AppModel { } }, - add_bottom_bar = >k::ActionBar { - pack_end = >k::Box { - set_orientation: gtk::Orientation::Horizontal, - - gtk::Label { - #[watch] - set_label: &format!("{:.1}x", model.zoom), - set_margin_end: 5 - }, - - gtk::Button::with_label(&tr!("command.view.zoom_out")) { - set_icon_name: ZOOM_OUT_REGULAR, - set_margin_end: 5, - add_css_class: "flat", - add_css_class: "zoom", - add_css_class: "zoom-out", - ActionablePlus::set_stateless_action::<ZoomOutAction>: &(), - }, - - gtk::Scale { - set_orientation: gtk::Orientation::Horizontal, - #[watch] - set_value: model.zoom, - set_draw_value: false, - set_range: (constants::MIN_ZOOM, constants::MAX_ZOOM), - set_increments: (constants::ZOOM_STEP, constants::ZOOM_STEP), - set_value_pos: gtk::PositionType::Left, - set_width_request: 100, - connect_value_changed[sender] => move |scale| { - sender.input(Action::Zoom(scale.value())); - } - }, - - gtk::Button::with_label(&tr!("command.view.zoom_in")) { - set_icon_name: ZOOM_IN_REGULAR, - add_css_class: "flat", - add_css_class: "zoom", - add_css_class: "zoom-in", - ActionablePlus::set_stateless_action::<ZoomInAction>: &(), - }, - } - } + add_bottom_bar = model.footer.widget(), } } } @@ -478,6 +438,12 @@ impl SimpleComponent for AppModel { }) .forward(sender.input_sender(), identity); + let footer = Footer::builder() + .launch(FooterInit { + zoom: init.zoom + }) + .forward(sender.input_sender(), identity); + let mut model = AppModel { orientation, stage_type, @@ -499,7 +465,8 @@ impl SimpleComponent for AppModel { preferences_window: None, editor_css_provider, horizontal_layout_enabled: true, - header + header, + footer }; model.apply_preferences(); |