aboutsummaryrefslogtreecommitdiff
path: root/src/components/preference_pages/editor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/preference_pages/editor.rs')
-rw-r--r--src/components/preference_pages/editor.rs223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/components/preference_pages/editor.rs b/src/components/preference_pages/editor.rs
new file mode 100644
index 0000000..28a8302
--- /dev/null
+++ b/src/components/preference_pages/editor.rs
@@ -0,0 +1,223 @@
+// 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 <http://www.gnu.org/licenses/>.
+
+use gtk::prelude::*;
+use relm4::prelude::*;
+
+use crate::tr;
+
+use crate::actions::PreferencesAction;
+use crate::components::switch;
+
+const DEFAULT_FONT_SIZE: f64 = 14.0;
+
+pub struct EditorInit {
+ pub font_size: f64,
+ pub soft_wrap: bool,
+ pub use_custom_font: bool,
+ pub custom_font: String,
+}
+pub struct Editor {
+ soft_wrap_switch: Controller<switch::Switch>,
+ custom_font_switch: Controller<switch::Switch>,
+ soft_wrap: bool,
+ use_custom_font: bool,
+ font_size: f64,
+ custom_font: String,
+}
+#[derive(Debug, Clone)]
+pub enum EditorAction {
+ SetFontSize(f64),
+ SetSoftWrap(bool),
+ SetUseCustomFont(bool),
+ SetCustomFont(String),
+
+ // Internal
+ ChangeFontSize(f64),
+ ChangeSoftWrap(bool),
+ ChangeUseCustomFont(bool),
+ ChangeFontDescription(gtk::FontDialogButton),
+}
+
+#[relm4::component(pub)]
+impl SimpleComponent for Editor {
+ type Init = EditorInit;
+ type Input = EditorAction;
+ type Output = PreferencesAction;
+ view! {
+ gtk::Box {
+ set_orientation: gtk::Orientation::Vertical,
+ set_margin_all: 20,
+ set_spacing: 20,
+ set_valign: gtk::Align::Start,
+
+ gtk::Box {
+ set_orientation: gtk::Orientation::Vertical,
+ set_spacing: 10,
+
+ gtk::Label {
+ set_label: &tr!("preferences.editor.font_size.title"),
+ add_css_class: "heading",
+ set_halign: gtk::Align::Start,
+ },
+
+ // TODO: Remove magic numbers.
+ gtk::Scale::with_range(gtk::Orientation::Horizontal, 7.0, 21.0, 1.0) {
+ #[watch]
+ #[block_signal(size_handler)]
+ set_value: model.font_size,
+ set_draw_value: true,
+ set_hexpand: true,
+
+ set_format_value_func => |_, value| {
+ #[allow(clippy::cast_possible_truncation)]
+ #[allow(clippy::float_cmp)]
+ if value == DEFAULT_FONT_SIZE {
+ format!(
+ "{} ({})",
+ value as i32,
+ tr!("preferences.editor.default_font_size")
+ )
+ } else {
+ format!("{}", value as i32)
+ }
+ },
+
+ connect_value_changed[sender] => move |scale| {
+ sender.input(EditorAction::ChangeFontSize(scale.value()));
+ } @size_handler,
+ }
+ },
+
+ gtk::Label {
+ set_label: &tr!("preferences.editor.editor_style.title"),
+ add_css_class: "heading",
+ set_halign: gtk::Align::Start,
+ set_margin_top: 10,
+ },
+
+ model.soft_wrap_switch.widget(),
+ model.custom_font_switch.widget(),
+
+ gtk::Box {
+ set_orientation: gtk::Orientation::Horizontal,
+ set_spacing: 10,
+
+ gtk::Label {
+ set_label: &tr!("preferences.editor.font"),
+ },
+
+ gtk::FontDialogButton::new(Some(gtk::FontDialog::new())) {
+ #[watch]
+ #[block_signal(font_handler)]
+ set_font_desc: &gtk::pango::FontDescription::from_string(&format!(
+ "{} {}",
+ model.custom_font, model.font_size as i32
+ )),
+ #[watch]
+ set_sensitive: model.use_custom_font,
+ set_hexpand: true,
+ set_use_font: true,
+ set_use_size: false,
+
+ connect_font_desc_notify[sender] => move |button| {
+ sender.input(EditorAction::ChangeFontDescription(button.clone()));
+ } @font_handler,
+ }
+ }
+ }
+ }
+
+ fn init(
+ init: Self::Init,
+ root: Self::Root,
+ sender: ComponentSender<Self>,
+ ) -> ComponentParts<Self> {
+ let soft_wrap_switch = switch::Switch::builder()
+ .launch(switch::SwitchInit {
+ label: tr!("preferences.editor.editor_style.soft_wrap_lines"),
+ state: init.soft_wrap,
+ })
+ .forward(sender.input_sender(), move |output| match output {
+ switch::SwitchOutput::SetState(state) => EditorAction::ChangeSoftWrap(state),
+ });
+
+ let custom_font_switch = switch::Switch::builder()
+ .launch(switch::SwitchInit {
+ label: tr!("preferences.editor.editor_style.use_custom_font"),
+ state: init.use_custom_font,
+ })
+ .forward(sender.input_sender(), move |output| match output {
+ switch::SwitchOutput::SetState(state) => EditorAction::ChangeUseCustomFont(state),
+ });
+
+ let model = Self {
+ font_size: init.font_size,
+ soft_wrap: init.soft_wrap,
+ use_custom_font: init.use_custom_font,
+ custom_font: init.custom_font,
+ soft_wrap_switch,
+ custom_font_switch,
+ };
+
+ let widgets = view_output!();
+ ComponentParts { model, widgets }
+ }
+
+ fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
+ match message {
+ EditorAction::SetFontSize(font_size) => self.font_size = font_size,
+ EditorAction::SetSoftWrap(soft_wrap) => self.soft_wrap = soft_wrap,
+ EditorAction::SetUseCustomFont(use_custom_font) => {
+ self.use_custom_font = use_custom_font
+ }
+ EditorAction::SetCustomFont(custom_font) => self.custom_font = custom_font,
+
+ EditorAction::ChangeFontSize(size) => {
+ sender
+ .output(PreferencesAction::SetEditorFontSize(size))
+ .ok();
+ }
+ EditorAction::ChangeFontDescription(button) => {
+ if let Some(font) = button.font_desc() {
+ if let Some(family) = font.family() {
+ sender
+ .output(PreferencesAction::SetCustomEditorFontName(
+ family.to_string(),
+ ))
+ .ok();
+ }
+ let size = font.size() / gtk::pango::SCALE;
+ if size > 0 {
+ sender
+ .output(PreferencesAction::SetEditorFontSize(f64::from(size)))
+ .ok();
+ }
+ }
+ }
+ EditorAction::ChangeSoftWrap(state) => {
+ sender
+ .output(PreferencesAction::SetSoftWrapLines(state))
+ .ok();
+ }
+ EditorAction::ChangeUseCustomFont(state) => {
+ sender
+ .output(PreferencesAction::SetUseCustomEditorFont(state))
+ .ok();
+ }
+ }
+ }
+}