// Map, wardley map editor for linux // Copyright (C) 2026 Rubén Beltrán del Río // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use std::path::PathBuf; use gtk::prelude::*; use relm4::{ComponentSender, gtk}; use crate::AppModel; use crate::actions::Action; use crate::constants; use crate::dialogs; use crate::file_registry; /// Loads a file into the current document, updating the file registry. pub fn load_file(model: &mut AppModel, path: PathBuf) { match std::fs::read_to_string(&path) { Ok(content) => { unregister_current_file(model); model.set_source_text(&content); file_registry::register_file(&path, &model.window); model.current_file = Some(path); model.modified = false; } Err(error) => { dialogs::show_error(&model.window, "Error Opening File", &error.to_string()); } } } /// Saves the document to the specified path, optionally closing after. pub fn save_to_file(model: &mut AppModel, path: PathBuf, close_after: bool) { let content = model.source_text(); let path = ensure_wmap_extension(path); match std::fs::write(&path, content.as_str()) { Ok(()) => { if close_after { file_registry::unregister_file(&path); model.modified = false; model.window.close(); } else { update_file_registration(model, &path); model.current_file = Some(path); model.modified = false; } } Err(error) => { dialogs::show_error(&model.window, "Error Saving File", &error.to_string()); } } } /// Handles window close, prompting for unsaved changes if needed. pub fn close_window(model: &mut AppModel, sender: &ComponentSender) { if model.modified { dialogs::show_unsaved_changes_dialog( &model.window, model.current_file.clone(), sender.clone(), ); } else { unregister_current_file(model); model.window.destroy(); } } /// Dispatches save action based on whether file already has a path. pub fn save(model: &AppModel, close_after: bool, sender: &ComponentSender) { if let Some(path) = model.current_file.clone() { sender.input(Action::SaveToFile { path, close_after }); } else { sender.input(Action::SaveAs { close_after }); } } // === Helper Functions === /// Unregisters the current file from the registry if one is open. fn unregister_current_file(model: &AppModel) { if let Some(ref path) = model.current_file { file_registry::unregister_file(path); } } /// Updates file registration when saving to a new path. fn update_file_registration(model: &mut AppModel, new_path: &PathBuf) { if model.current_file.as_ref() != Some(new_path) { unregister_current_file(model); file_registry::register_file(new_path, &model.window); } } /// Ensures the path has the .wmap extension. fn ensure_wmap_extension(path: PathBuf) -> PathBuf { if path.extension().is_none() || path.extension().unwrap_or_default() != constants::FILE_EXTENSION { path.with_extension(constants::FILE_EXTENSION) } else { path } }