// 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 gtk::prelude::*;
use relm4::prelude::*;
use crate::icon_names::shipped::RIGHT;
use crate::preferences::models::Template;
use crate::tr;
#[derive(Debug)]
pub struct TemplateRow {
pub template: Template,
focus_controller: gtk::EventControllerFocus,
is_arrow_shown: bool,
}
#[derive(Debug, Clone)]
pub enum TemplateRowAction {
ShowArrow,
HideArrow,
}
#[derive(Debug)]
pub enum TemplateRowOutput {
SetDefault(DynamicIndex),
SetName(DynamicIndex, String),
Focus(DynamicIndex),
Activate(DynamicIndex),
}
#[relm4::factory(pub)]
impl FactoryComponent for TemplateRow {
type Init = Template;
type Input = TemplateRowAction;
type Output = TemplateRowOutput;
type CommandOutput = ();
type ParentWidget = gtk::ListBox;
view! {
#[root]
gtk::ListBoxRow {
set_focus_on_click: true,
gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
set_margin_all: 5,
set_spacing: 5,
gtk::Button {
add_css_class: "flat",
#[watch]
set_icon_name: if self.template.is_default { "radio-checked-symbolic" } else { "radio-symbolic" },
#[watch]
set_tooltip_text: Some(&if self.template.is_default { tr!("preferences.templates.help.default") } else { tr!("preferences.templates.help.set_as_default") }),
connect_clicked[sender, index] => move |_| {
sender.output(TemplateRowOutput::SetDefault(index.clone())).ok();
}
},
#[name="entry"]
gtk::Entry {
set_text: &self.template.name,
set_hexpand: true,
connect_changed[sender, index] => move |entry| {
sender.output(TemplateRowOutput::SetName(
index.clone(),
entry.text().to_string()
)).ok();
},
add_controller: self.focus_controller.clone()
},
gtk::Button::from_icon_name(RIGHT) {
set_tooltip_text: Some(&tr!("preferences.templates.help.activate")),
#[watch]
set_visible: self.is_arrow_shown,
connect_clicked[sender, index] => move |_| {
sender.output(TemplateRowOutput::Activate(index.clone())).ok();
}
}
},
}
}
fn init_model(template: Self::Init, index: &DynamicIndex, sender: FactorySender) -> Self {
let focus_controller = gtk::EventControllerFocus::new();
{
let sender = sender.clone();
let index = index.clone();
focus_controller.connect_enter(move |_| {
sender.output(TemplateRowOutput::Focus(index.clone())).ok();
});
}
Self {
template,
focus_controller,
is_arrow_shown: true,
}
}
fn update(&mut self, message: Self::Input, _sender: FactorySender) {
match message {
TemplateRowAction::ShowArrow => self.is_arrow_shown = true,
TemplateRowAction::HideArrow => self.is_arrow_shown = false,
}
}
}