From 0043a8aa675b526017f2350b30935707b8c8aa9a Mon Sep 17 00:00:00 2001 From: Ryo Nakano Date: Sat, 14 Dec 2024 11:41:11 +0900 Subject: [PATCH] Use Vala instead of Blueprint for the main UI (#176) --- data/resources/konbucase.gresource.xml.in | 2 - data/resources/meson.build | 2 - data/resources/ui/main-window.blp | 65 -------------------- data/resources/ui/text-pane.blp | 68 --------------------- po/POTFILES | 2 - src/View/MainWindow.vala | 73 ++++++++++++++++------- src/View/TextPane.vala | 63 +++++++++++++++---- 7 files changed, 106 insertions(+), 169 deletions(-) delete mode 100644 data/resources/ui/main-window.blp delete mode 100644 data/resources/ui/text-pane.blp diff --git a/data/resources/konbucase.gresource.xml.in b/data/resources/konbucase.gresource.xml.in index dc763c4..76df8ee 100644 --- a/data/resources/konbucase.gresource.xml.in +++ b/data/resources/konbucase.gresource.xml.in @@ -1,8 +1,6 @@ - ui/text-pane.ui - ui/main-window.ui gtk/help-overlay.ui ../@APP_ID@.metainfo.xml diff --git a/data/resources/meson.build b/data/resources/meson.build index a4a634f..fbd9926 100644 --- a/data/resources/meson.build +++ b/data/resources/meson.build @@ -1,7 +1,5 @@ blueprints = custom_target('blueprints', input: files( - 'ui/text-pane.blp', - 'ui/main-window.blp', 'gtk/help-overlay.blp', ), output: '.', diff --git a/data/resources/ui/main-window.blp b/data/resources/ui/main-window.blp deleted file mode 100644 index d9f731d..0000000 --- a/data/resources/ui/main-window.blp +++ /dev/null @@ -1,65 +0,0 @@ -using Gtk 4.0; -using Adw 1; - -$TextPaneModel source_model { - text-type: source; -} - -$TextPaneModel result_model { - text-type: result; -} - -$MainWindowModel window_model { - source-model: source_model; - result-model: result_model; -} - -/** - * MainWindow: The app window - */ -template $MainWindow : Adw.ApplicationWindow { - width-request: 700; - height-request: 500; - title: "KonbuCase"; - - Adw.ToolbarView { - [top] - Adw.HeaderBar { - [end] - Gtk.MenuButton { - tooltip-text: _("Main Menu"); - icon-name: "open-menu"; - menu-model: bind template.main_menu; - primary: true; - } - } - - // Use overlay for the toast - content: Adw.ToastOverlay overlay { - Gtk.Box { - orientation: horizontal; - spacing: 0; - - // Left pane for input text - $TextPane source_pane { - model: source_model; - header-label: _("Convert _From:"); - editable: true; - } - - Gtk.Separator { - orientation: vertical; - vexpand: true; - } - - // Right pane for output text - $TextPane result_pane { - model: result_model; - header-label: _("Convert _To:"); - // Make the text view uneditable, otherwise the app freezes - editable: false; - } - } - }; - } -} diff --git a/data/resources/ui/text-pane.blp b/data/resources/ui/text-pane.blp deleted file mode 100644 index bc48a35..0000000 --- a/data/resources/ui/text-pane.blp +++ /dev/null @@ -1,68 +0,0 @@ -using Gtk 4.0; -using GtkSource 5; - -// Choices of case types -Gtk.StringList case_list { - strings [ - _("Space separated"), - "camelCase", - "PascalCase", - "snake_case", - "kebab-case", - "Sentence case", - ] -} - -/** - * TextPane: Common pane for input/output texts - */ -template $TextPane : Gtk.Box { - orientation: vertical; - spacing: 0; - - // Toolbar - Gtk.Box { - orientation: horizontal; - spacing: 12; - valign: center; - margin-top: 6; - margin-bottom: 6; - margin-start: 6; - margin-end: 6; - - // Header label for the DropDown - Label { - label: bind template.header-label; - use-underline: true; - mnemonic-widget: case_dropdown; - } - - // DropDown to choose case type - Gtk.DropDown case_dropdown { - model: case_list; - } - - // Info about current choice of case type - Gtk.Image case_info_button_icon { - icon-name: "dialog-information-symbolic"; - tooltip-text: bind template.model as <$TextPaneModel>.case-description; - } - - // Button to copy text in the text view - Gtk.Button copy_clipboard_button { - icon-name: "edit-copy"; - tooltip-text: _("Copy to Clipboard"); - } - } - - // Text area - Gtk.ScrolledWindow { - GtkSource.View source_view { - buffer: bind template.model as <$TextPaneModel>.buffer; - wrap-mode: word_char; - hexpand: true; - vexpand: true; - editable: bind template.editable; - } - } -} diff --git a/po/POTFILES b/po/POTFILES index 02876e3..d3c3d35 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1,8 +1,6 @@ data/resources/gtk/help-overlay.ui data/konbucase.desktop.in.in data/konbucase.metainfo.xml.in.in -data/resources/ui/main-window.blp -data/resources/ui/text-pane.blp src/Application.vala src/Model/TextPaneModel.vala src/View/MainWindow.vala diff --git a/src/View/MainWindow.vala b/src/View/MainWindow.vala index 9766d9a..6bf031b 100644 --- a/src/View/MainWindow.vala +++ b/src/View/MainWindow.vala @@ -3,28 +3,13 @@ * SPDX-FileCopyrightText: 2020-2024 Ryo Nakano */ -[GtkTemplate (ui = "/com/github/ryonakano/konbucase/ui/main-window.ui")] public class MainWindow : Adw.ApplicationWindow { - // Main menu model - public Menu main_menu { get; private set; } - - [GtkChild] - private unowned Adw.ToastOverlay overlay; - [GtkChild] - private unowned TextPane source_pane; - [GtkChild] - private unowned TextPane result_pane; - - [GtkChild] - private unowned TextPaneModel source_model; - [GtkChild] - private unowned TextPaneModel result_model; - [GtkChild] - private unowned MainWindowModel window_model; + private Adw.ToastOverlay overlay; public MainWindow (Application app) { Object ( - application: app + application: app, + title: "KonbuCase" ); } @@ -39,7 +24,7 @@ public class MainWindow : Adw.ApplicationWindow { style_submenu.append (_("_Light"), "app.color-scheme(\"force-light\")"); style_submenu.append (_("_Dark"), "app.color-scheme(\"force-dark\")"); - main_menu = new Menu (); + var main_menu = new Menu (); main_menu.append_submenu (_("_Style"), style_submenu); main_menu.append (_("Keyboard Shortcuts"), "win.show-help-overlay"); // Pantheon prefers AppCenter instead of an about dialog for app details, so prevent it from being shown on Pantheon @@ -48,9 +33,57 @@ public class MainWindow : Adw.ApplicationWindow { main_menu.append (_("_About KonbuCase"), "app.about"); } + var menu_button = new Gtk.MenuButton () { + tooltip_text = _("Main Menu"), + icon_name = "open-menu", + menu_model = main_menu, + primary = true + }; + + var header = new Adw.HeaderBar (); + header.pack_end (menu_button); + + var source_model = new TextPaneModel (Define.TextType.SOURCE); + var result_model = new TextPaneModel (Define.TextType.RESULT); + var window_model = new MainWindowModel (source_model, result_model); + + var source_pane = new TextPane ( + source_model, + _("Convert _From:"), + true + ); + + var separator = new Gtk.Separator (Gtk.Orientation.VERTICAL) { + vexpand = true + }; + + var result_pane = new TextPane ( + result_model, + _("Convert _To:"), + // Make the text view uneditable, otherwise the app freezes + false + ); + + var content_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); + content_box.append (source_pane); + content_box.append (separator); + content_box.append (result_pane); + + overlay = new Adw.ToastOverlay () { + child = content_box + }; + + var toolbar_view = new Adw.ToolbarView (); + toolbar_view.add_top_bar (header); + toolbar_view.set_content (overlay); + + content = toolbar_view; + width_request = 700; + height_request = 500; + // The action users most frequently take is to input the source text. // So, forcus to the source view by default. - source_pane.get_source_view ().grab_focus (); + source_pane.focus_source_view (); // Perform conversion when: // diff --git a/src/View/TextPane.vala b/src/View/TextPane.vala index 0f9c04c..12796dd 100644 --- a/src/View/TextPane.vala +++ b/src/View/TextPane.vala @@ -3,7 +3,6 @@ * SPDX-FileCopyrightText: 2020-2024 Ryo Nakano */ -[GtkTemplate (ui = "/com/github/ryonakano/konbucase/ui/text-pane.ui")] public class TextPane : Gtk.Box { public signal void dropdown_changed (); public signal void copy_button_clicked (); @@ -12,12 +11,7 @@ public class TextPane : Gtk.Box { public string header_label { get; construct; } public bool editable { get; construct; } - [GtkChild] - private unowned Gtk.DropDown case_dropdown; - [GtkChild] - private unowned Gtk.Button copy_clipboard_button; - [GtkChild] - private unowned GtkSource.View source_view; + private GtkSource.View source_view; public TextPane (TextPaneModel model, string header_label, bool editable) { Object ( @@ -28,8 +22,58 @@ public class TextPane : Gtk.Box { } construct { + orientation = Gtk.Orientation.VERTICAL; + spacing = 0; + + var case_dropdown = new Gtk.DropDown.from_strings ({ + _("Space separated"), + "camelCase", + "PascalCase", + "snake_case", + "kebab-case", + "Sentence case", + }); case_dropdown.selected = model.case_type; + var case_label = new Gtk.Label (header_label) { + use_underline = true, + mnemonic_widget = case_dropdown + }; + + var case_info_button_icon = new Gtk.Image.from_icon_name ("dialog-information-symbolic") { + tooltip_text = model.case_description + }; + + var copy_clipboard_button = new Gtk.Button.from_icon_name ("edit-copy") { + tooltip_text = _("Copy to Clipboard") + }; + + var toolbar = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { + valign = Gtk.Align.CENTER, + margin_top = 6, + margin_bottom = 6, + margin_start = 6, + margin_end = 6 + }; + toolbar.append (case_label); + toolbar.append (case_dropdown); + toolbar.append (case_info_button_icon); + toolbar.append (copy_clipboard_button); + + source_view = new GtkSource.View.with_buffer (model.buffer) { + wrap_mode = Gtk.WrapMode.WORD_CHAR, + hexpand = true, + vexpand = true, + editable = editable + }; + + var scrolled = new Gtk.ScrolledWindow () { + child = source_view + }; + + append (toolbar); + append (scrolled); + case_dropdown.notify["selected"].connect (() => { model.case_type = (Define.CaseType) case_dropdown.selected; @@ -52,8 +96,7 @@ public class TextPane : Gtk.Box { ); } - // UI elements defined in .ui files can't be a property, so defines a getter method instead - public unowned GtkSource.View get_source_view () { - return source_view; + public void focus_source_view () { + source_view.grab_focus (); } }