aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorRubén Beltrán del Río <jj@r.bdr.sh>2026-01-17 11:22:22 +0100
committerRubén Beltrán del Río <jj@r.bdr.sh>2026-01-17 12:24:45 +0100
commit88d6bf80f5cdbbb90ead197bd41a67eb8c44e50e (patch)
tree401549b24fe8a747ef6739389b1b38f33ef016bb /src/main.rs
parent17898fbabde35ab346c133114e78614e707c0eca (diff)
Make clippy stricter and fix
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs239
1 files changed, 145 insertions, 94 deletions
diff --git a/src/main.rs b/src/main.rs
index c15ffc2..4feef3b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -28,6 +28,7 @@ mod stages;
mod ui_helpers;
mod icon_names {
+ #![allow(clippy::doc_markdown)] // Generated code from relm4_icons_build
include!(concat!(env!("OUT_DIR"), "/icon_names.rs"));
}
@@ -93,7 +94,7 @@ macro_rules! register_action {
}};
}
-fn setup_actions(window: gtk::Window, sender: ComponentSender<AppModel>) {
+fn setup_actions(window: &gtk::Window, sender: &ComponentSender<AppModel>) {
let application = relm4::main_application();
let mut action_group = RelmActionGroup::<WindowActionGroup>::new();
@@ -179,11 +180,12 @@ fn setup_actions(window: gtk::Window, sender: ComponentSender<AppModel>) {
);
let sender = sender.clone();
- let action: RelmAction<NewFromTemplateAction> = RelmAction::new_with_target_value(move |_, template_id| {
- sender.input(Action::NewFromTemplateById(template_id))
- });
+ let action: RelmAction<NewFromTemplateAction> =
+ RelmAction::new_with_target_value(move |_, template_id| {
+ sender.input(Action::NewFromTemplateById(template_id));
+ });
action_group.add_action(action);
- action_group.register_for_widget(&window);
+ action_group.register_for_widget(window);
}
struct AppInit {
@@ -219,12 +221,15 @@ struct AppModel {
}
impl AppModel {
+ #[allow(clippy::cast_possible_truncation)]
fn update_image(&mut self) {
- if let Ok(surface) =
- render_to_surface(&self.map, &self.stage_type.to_localized(), &self.render_configuration)
- {
- self.surface_width = (surface.width() as f64 * self.zoom).round() as i32;
- self.surface_height = (surface.height() as f64 * self.zoom).round() as i32;
+ if let Ok(surface) = render_to_surface(
+ &self.map,
+ &self.stage_type.to_localized(),
+ &self.render_configuration,
+ ) {
+ self.surface_width = (f64::from(surface.width()) * self.zoom).round() as i32;
+ self.surface_height = (f64::from(surface.height()) * self.zoom).round() as i32;
self.surface = surface;
let zoom = self.zoom;
@@ -272,6 +277,7 @@ impl AppModel {
self.source.set_text(content);
}
+ #[allow(clippy::cast_possible_truncation)]
fn apply_preferences(&mut self) {
self.source_view
.set_wrap_mode(if self.preferences.soft_wrap_lines {
@@ -325,8 +331,7 @@ impl AppModel {
}
for stage_type in &stage_types {
- self.stage_type_list
- .append(&stage_type.localized_name());
+ self.stage_type_list.append(&stage_type.localized_name());
}
self.available_stage_types = stage_types;
@@ -337,7 +342,7 @@ impl AppModel {
for template in &self.preferences.map_templates {
self.templates_menu.append(
Some(&template.name),
- Some(&format!("window.new-from-template::{}", template.id))
+ Some(&format!("window.new-from-template::{}", template.id)),
);
}
}
@@ -358,6 +363,121 @@ impl AppModel {
file_registry::store_controller(controller);
}
+
+ fn init_stage_type_list() -> gtk::StringList {
+ let stage_types: Vec<String> = ALL_STAGE_TYPES
+ .iter()
+ .map(stages::LocalizedStageType::localized_name)
+ .collect();
+ let stage_type_refs: Vec<&str> = stage_types
+ .iter()
+ .map(std::string::String::as_str)
+ .collect();
+ gtk::StringList::new(&stage_type_refs)
+ }
+
+ fn init_source_buffer(
+ init: &AppInit,
+ sender: &ComponentSender<Self>,
+ ) -> (sourceview5::Buffer, String, Option<PathBuf>) {
+ let source = sourceview5::Buffer::new(None);
+ source.set_highlight_syntax(true);
+
+ let language_manager = LanguageManager::default();
+ if let Some(language) = language_manager.language("wmap") {
+ source.set_language(Some(&language));
+ }
+
+ let (initial_content, current_file) = if let Some(ref path) = init.file_path {
+ match std::fs::read_to_string(path) {
+ Ok(content) => (content, Some(path.clone())),
+ Err(_) => (String::new(), None),
+ }
+ } else {
+ (init.initial_content.clone().unwrap_or_default(), None)
+ };
+
+ source.set_text(&initial_content);
+
+ {
+ let sender = sender.clone();
+ source.connect_changed(move |_| {
+ sender.input(Action::SourceChanged);
+ });
+ }
+
+ (source, initial_content, current_file)
+ }
+
+ fn init_drawing_area(
+ initial_content: &str,
+ ) -> (
+ gtk::DrawingArea,
+ Map,
+ Configuration,
+ StageType,
+ ImageSurface,
+ ) {
+ let drawing_area = gtk::DrawingArea::new();
+ let map = parse(initial_content);
+ let mut render_configuration = Configuration::default();
+ let stage_type = StageType::Activities;
+ render_configuration.options.smart_label_positioning = true;
+ let surface = render_to_surface(&map, &stage_type.to_localized(), &render_configuration)
+ .or_else(|_| ImageSurface::create(cairo::Format::ARgb32, 1, 1))
+ .unwrap_or_else(|e| {
+ eprintln!("Fatal: Cairo failed to create surface: {e}");
+ std::process::exit(1);
+ });
+
+ (drawing_area, map, render_configuration, stage_type, surface)
+ }
+
+ fn init_main_menu(prefs: &preferences::UserPreferences) -> (gio::Menu, gio::Menu) {
+ let templates_menu = gio::Menu::new();
+ for template in &prefs.map_templates {
+ templates_menu.append(
+ Some(&template.name),
+ Some(&format!("window.new-from-template::{}", template.id)),
+ );
+ }
+
+ let main_menu = gio::Menu::new();
+ main_menu.append(Some(&tr!("command.file.new")), Some("window.new"));
+ main_menu.append_submenu(
+ Some(&tr!("command.file.new_from_template")),
+ &templates_menu,
+ );
+ main_menu.append(Some(&tr!("command.file.open")), Some("window.open"));
+ main_menu.append(Some(&tr!("command.file.save")), Some("window.save"));
+ main_menu.append(Some(&tr!("command.file.save_as")), Some("window.save-as"));
+ main_menu.append(Some(&tr!("command.file.close")), Some("window.close"));
+ main_menu.append(
+ Some(&tr!("command.file.export")),
+ Some("window.export-image"),
+ );
+
+ let layout_section = gio::Menu::new();
+ layout_section.append(
+ Some(&tr!("command.view.use_vertical_layout")),
+ Some("window.change-orientation"),
+ );
+ main_menu.append_section(None, &layout_section);
+
+ let zoom_section = gio::Menu::new();
+ zoom_section.append(Some(&tr!("command.view.zoom_in")), Some("window.zoom-in"));
+ zoom_section.append(Some(&tr!("command.view.zoom_out")), Some("window.zoom-out"));
+ main_menu.append_section(None, &zoom_section);
+
+ let prefs_section = gio::Menu::new();
+ prefs_section.append(
+ Some(&tr!("command.application.preferences")),
+ Some("window.preferences"),
+ );
+ main_menu.append_section(None, &prefs_section);
+
+ (templates_menu, main_menu)
+ }
}
#[relm4::component]
@@ -496,40 +616,11 @@ impl SimpleComponent for AppModel {
root: Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
- let stage_types: Vec<String> = ALL_STAGE_TYPES
- .iter()
- .map(|stage_type| stage_type.localized_name())
- .collect();
- let stage_type_refs: Vec<&str> = stage_types.iter().map(|s| s.as_str()).collect();
- let stage_type_list = gtk::StringList::new(&stage_type_refs);
+ let stage_type_list = Self::init_stage_type_list();
- let source = sourceview5::Buffer::new(None);
- source.set_highlight_syntax(true);
-
- let language_manager = LanguageManager::default();
- if let Some(language) = language_manager.language("wmap") {
- source.set_language(Some(&language));
- }
-
- let (initial_content, current_file) = if let Some(ref path) = init.file_path {
- match std::fs::read_to_string(path) {
- Ok(content) => (content, Some(path.clone())),
- Err(_) => (String::new(), None),
- }
- } else {
- (init.initial_content.unwrap_or_default(), None)
- };
-
- source.set_text(&initial_content);
-
- {
- let sender = sender.clone();
- source.connect_changed(move |_| {
- sender.input(Action::SourceChanged);
- });
- }
+ let (source, initial_content, current_file) = Self::init_source_buffer(&init, &sender);
- setup_actions(root.clone(), sender.clone());
+ setup_actions(&root, &sender);
let source_view = sourceview5::View::with_buffer(&source);
source_view.set_monospace(true);
@@ -540,55 +631,15 @@ impl SimpleComponent for AppModel {
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
- let drawing_area = gtk::DrawingArea::new();
- let map = parse(&initial_content);
- let mut render_configuration = Configuration::default();
- let stage_type = StageType::Activities;
- render_configuration.options.smart_label_positioning = true;
- let surface =
- render_to_surface(&map, &stage_type.to_localized(), &render_configuration).unwrap_or_else(|_| {
- ImageSurface::create(cairo::Format::ARgb32, 1, 1)
- .expect("errors.render.failed_to_create_surface")
- });
+ let (drawing_area, map, render_configuration, stage_type, surface) =
+ Self::init_drawing_area(&initial_content);
if let Some(ref path) = current_file {
file_registry::register_file(path, &root);
}
let prefs = preferences::storage::load();
-
- let templates_menu = gio::Menu::new();
- for template in &prefs.map_templates {
- templates_menu.append(
- Some(&template.name),
- Some(&format!("window.new-from-template::{}", template.id))
- );
- }
-
- let main_menu = gio::Menu::new();
- main_menu.append(Some(&tr!("command.file.new")), Some("window.new"));
- main_menu.append_submenu(Some(&tr!("command.file.new_from_template")), &templates_menu);
- main_menu.append(Some(&tr!("command.file.open")), Some("window.open"));
- main_menu.append(Some(&tr!("command.file.save")), Some("window.save"));
- main_menu.append(Some(&tr!("command.file.save_as")), Some("window.save-as"));
- main_menu.append(Some(&tr!("command.file.close")), Some("window.close"));
- main_menu.append(Some(&tr!("command.file.export")), Some("window.export-image"));
-
- let layout_section = gio::Menu::new();
- layout_section.append(
- Some(&tr!("command.view.use_vertical_layout")),
- Some("window.change-orientation"),
- );
- main_menu.append_section(None, &layout_section);
-
- let zoom_section = gio::Menu::new();
- zoom_section.append(Some(&tr!("command.view.zoom_in")), Some("window.zoom-in"));
- zoom_section.append(Some(&tr!("command.view.zoom_out")), Some("window.zoom-out"));
- main_menu.append_section(None, &zoom_section);
-
- let prefs_section = gio::Menu::new();
- prefs_section.append(Some(&tr!("command.application.preferences")), Some("window.preferences"));
- main_menu.append_section(None, &prefs_section);
+ let (templates_menu, main_menu) = Self::init_main_menu(&prefs);
let mut model = AppModel {
orientation: gtk::Orientation::Horizontal,
@@ -663,10 +714,10 @@ impl SimpleComponent for AppModel {
Action::ZoomOut => handlers::zoom::zoom_out(self),
Action::ExportImage => {
- dialogs::show_export_dialog(&self.window, self.current_file.clone(), sender)
+ dialogs::show_export_dialog(&self.window, self.current_file.as_ref(), sender);
}
Action::ExportToFile { path, format } => {
- handlers::export::export_to_file(self, path, format)
+ handlers::export::export_to_file(self, &path, format);
}
Action::New => {
@@ -687,18 +738,18 @@ impl SimpleComponent for AppModel {
}
}
Action::Open => {
- dialogs::show_open_dialog(&self.window, self.is_empty_document(), sender)
+ dialogs::show_open_dialog(&self.window, self.is_empty_document(), sender);
}
Action::Save { close_after } => handlers::file::save(self, close_after, &sender),
Action::SaveAs { close_after } => dialogs::show_save_dialog(
&self.window,
- self.current_file.clone(),
+ self.current_file.as_ref(),
close_after,
sender,
),
Action::LoadFile(path) => handlers::file::load_file(self, path),
Action::SaveToFile { path, close_after } => {
- handlers::file::save_to_file(self, path, close_after)
+ handlers::file::save_to_file(self, path, close_after);
}
Action::CloseWindow => handlers::file::close_window(self, &sender),
@@ -729,7 +780,7 @@ impl SimpleComponent for AppModel {
self.rebuild_stage_type_list();
self.rebuild_templates_menu();
self.update_image();
- file_registry::broadcast_to_all_windows(Action::ReloadPreferences);
+ file_registry::broadcast_to_all_windows(&Action::ReloadPreferences);
}
Action::PreferencesWindowClosed => {
self.preferences_window = None;