// 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 .
// Suppress warnings from relm4 view! macro internals
mod actions;
mod components;
mod constants;
mod dialogs;
mod file_registry;
mod handlers;
mod i18n;
mod preferences;
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"));
}
use std::cell::RefCell;
use std::convert::identity;
use std::path::PathBuf;
use crate::actions::Action;
use adw::prelude::*;
use cairo::ImageSurface;
use gtk::glib;
use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup};
use relm4::prelude::*;
use sourceview5::LanguageManager;
use sourceview5::prelude::*;
use stages::LocalizedStageType;
use wmap_parser::{Map, parse};
use wmap_renderer::{Configuration, StageType, render_to_surface};
use components::footer::{Footer, FooterInit};
use components::header::{Header, HeaderInit};
/// Macro to reduce boilerplate when registering actions with accelerators.
macro_rules! register_action {
($group:expr, $app:expr, $sender:expr, $action_type:ty, $message:expr, $accelerators:expr) => {{
let sender = $sender.clone();
let action: RelmAction<$action_type> = RelmAction::new_stateless(move |_| {
let _ = sender.input($message);
});
$group.add_action(action.clone());
$app.set_accelerators_for_action::<$action_type>($accelerators);
action
}};
}
/// Macro to further reduce the boilerplate, by allowing terser registration.
macro_rules! register_actions {
($group:expr, $app:expr, $sender:expr, [
$( $action_type:ty => $message:expr, $accelerators:expr );+ $(;)?
]) => {{
$(
register_action!(
$group, $app, $sender,
$action_type, $message, $accelerators
);
)+
}};
}
// Action group and action type declarations
relm4::new_action_group!(WindowActionGroup, "window");
relm4::new_stateless_action!(NewAction, WindowActionGroup, "new");
relm4::new_stateless_action!(OpenAction, WindowActionGroup, "open");
relm4::new_stateless_action!(SaveAction, WindowActionGroup, "save");
relm4::new_stateless_action!(SaveAsAction, WindowActionGroup, "save-as");
relm4::new_stateless_action!(CloseAction, WindowActionGroup, "close");
relm4::new_stateless_action!(ExportImageAction, WindowActionGroup, "export-image");
relm4::new_stateless_action!(
ChangeOrientationAction,
WindowActionGroup,
"change-orientation"
);
relm4::new_stateless_action!(ZoomInAction, WindowActionGroup, "zoom-in");
relm4::new_stateless_action!(ZoomOutAction, WindowActionGroup, "zoom-out");
relm4::new_stateless_action!(PreferencesAction, WindowActionGroup, "preferences");
struct NewFromTemplateAction;
impl relm4::actions::ActionName for NewFromTemplateAction {
type Group = WindowActionGroup;
type Target = String;
type State = ();
const NAME: &'static str = "new-from-template";
}
struct AppInit {
zoom: f64,
orientation: gtk::Orientation,
file_path: Option,
initial_content: Option,
}
struct AppModel {
orientation: gtk::Orientation,
stage_type: StageType,
source: sourceview5::Buffer,
source_view: sourceview5::View,
map: Map,
zoom: f64,
render_configuration: Configuration,
surface: ImageSurface,
surface_width: i32,
surface_height: i32,
drawing_area: gtk::DrawingArea,
current_file: Option,
modified: bool,
pending_load_events: RefCell,
initialized: bool,
window: adw::Window,
preferences: preferences::UserPreferences,
preferences_window: Option>,
editor_css_provider: gtk::CssProvider,
horizontal_layout_enabled: bool,
// Child Components
header: Controller,
footer: Controller