Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate View and Model #137

Merged
merged 13 commits into from
Apr 27, 2024
3 changes: 2 additions & 1 deletion data/resources/ui/combo-entry.blp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Gtk 4.0;
using GtkSource 5;
using Granite 7.0;

// Choices of case types
Gtk.StringList case_list {
Expand Down Expand Up @@ -44,6 +43,7 @@ template $ComboEntry : Gtk.Box {
// Info about current choice of case type
Gtk.Image case_info_button_icon {
icon-name: "dialog-information-symbolic";
tooltip-text: bind template.model as <$ComboEntryModel>.case-description;
}

// Button to copy text in the text view
Expand All @@ -56,6 +56,7 @@ template $ComboEntry : Gtk.Box {
// Text area
Gtk.ScrolledWindow {
GtkSource.View source_view {
buffer: bind template.model as <$ComboEntryModel>.buffer;
wrap-mode: word_char;
hexpand: true;
vexpand: true;
Expand Down
17 changes: 15 additions & 2 deletions data/resources/ui/main-window.blp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ menu main_menu {
}
}

$ComboEntryModel source_model {
text-type: source;
}

$ComboEntryModel result_model {
text-type: result;
}

$MainWindowModel window_model {
source-model: source_model;
result-model: result_model;
}

/**
* MainWindow: The app window
*/
Expand Down Expand Up @@ -54,7 +67,7 @@ template $MainWindow : Gtk.ApplicationWindow {

// Left pane for input text
$ComboEntry source_combo_entry {
id: "source";
model: source_model;
description: _("Convert from:");
editable: true;
}
Expand All @@ -66,7 +79,7 @@ template $MainWindow : Gtk.ApplicationWindow {

// Right pane for output text
$ComboEntry result_combo_entry {
id: "result";
model: result_model;
description: _("Convert to:");
// Make the text view uneditable, otherwise the app freezes
editable: false;
Expand Down
2 changes: 1 addition & 1 deletion po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ data/konbucase.desktop.in
data/konbucase.metainfo.xml.in
data/resources/ui/combo-entry.blp
data/resources/ui/main-window.blp
src/ComboEntry.vala
src/Model/ComboEntryModel.vala
136 changes: 0 additions & 136 deletions src/ComboEntry.vala

This file was deleted.

10 changes: 10 additions & 0 deletions src/Define.vala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ namespace Define {
public const string DARK = "dark";
}

/**
* Type of the text.
*/
public enum TextType {
/** Text that is converted. */
SOURCE,
/** Text after conversion. */
RESULT,
}

// Make sure to match with source-type enum in the gschema
public enum CaseType {
SPACE_SEPARATED = ChCase.Case.SPACE_SEPARATED,
Expand Down
31 changes: 0 additions & 31 deletions src/MainWindow.vala

This file was deleted.

84 changes: 84 additions & 0 deletions src/Model/ComboEntryModel.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2020-2024 Ryo Nakano <[email protected]>
*/

public class ComboEntryModel : Object {
public Define.TextType text_type { get; construct; }
public Define.CaseType case_type { get; set; }
public string case_description { get; set; }
public GtkSource.Buffer buffer { get; private set; }
public string text { get; set; }

private GtkSource.StyleSchemeManager style_scheme_manager;
private Gtk.Settings gtk_settings;

private struct TextTypeData {
/** GSettings key name that stores last case type. */
string key_case_type;
/** GSettings key name that stores last text. */
string key_text;
}
private const TextTypeData[] TEXT_TYPE_DATA_TABLE = {
{ "source-case-type", "source-text" }, // Define.TextType.SOURCE
{ "result-case-type", "result-text" }, // Define.TextType.RESULT
};

private struct CaseTypeData {
string description;
}
private const CaseTypeData[] CASE_TYPE_DATA_TBL = {
{ N_("Each word is separated by a space") }, // Define.CaseType.SPACE_SEPARATED
{ N_("The first character of compound words is in lowercase") }, // Define.CaseType.CAMEL
{ N_("The first character of compound words is in uppercase") }, // Define.CaseType.PASCAL
{ N_("Each word is separated by an underscore") }, // Define.CaseType.SNAKE
{ N_("Each word is separated by a hyphen") }, // Define.CaseType.KEBAB
{ N_("The first character of the first word in the sentence is in uppercase") }, // Define.CaseType.SENTENCE
};

public ComboEntryModel (Define.TextType text_type) {
Object (
text_type: text_type
);
}

construct {
case_type = (Define.CaseType) Application.settings.get_enum (TEXT_TYPE_DATA_TABLE[text_type].key_case_type);

buffer = new GtkSource.Buffer (null);

style_scheme_manager = new GtkSource.StyleSchemeManager ();
gtk_settings = Gtk.Settings.get_default ();

// Sync with buffer text
buffer.bind_property ("text", this, "text", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);

// Apply theme changes to the source view
gtk_settings.bind_property ("gtk-application-prefer-dark-theme", buffer, "style-scheme",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE,
(binding, from_value, ref to_value) => {
var prefer_dark = (bool) from_value;
if (prefer_dark) {
to_value.set_object (style_scheme_manager.get_scheme ("solarized-dark"));
} else {
to_value.set_object (style_scheme_manager.get_scheme ("solarized-light"));
}

return true;
});

Application.settings.bind (TEXT_TYPE_DATA_TABLE[text_type].key_text, this, "text", SettingsBindFlags.DEFAULT);

bind_property ("case-type", this, "case-description",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE,
(binding, from_value, ref to_value) => {
var case_type = (Define.CaseType) from_value;
to_value.set_string (_(CASE_TYPE_DATA_TBL[case_type].description));
return true;
});

notify["case-type"].connect (() => {
Application.settings.set_enum (TEXT_TYPE_DATA_TABLE[text_type].key_case_type, case_type);
});
}
}
48 changes: 48 additions & 0 deletions src/Model/MainWindowModel.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2020-2024 Ryo Nakano <[email protected]>
*/

public class MainWindowModel : Object {
public ComboEntryModel source_model { get; construct; }
public ComboEntryModel result_model { get; construct; }

private ChCase.Converter converter;

public MainWindowModel (ComboEntryModel source_model, ComboEntryModel result_model) {
Object (
source_model: source_model,
result_model: result_model
);
}

construct {
converter = new ChCase.Converter ();
}

public void do_convert () {
set_case_type (source_model.case_type, result_model.case_type);
result_model.text = convert_case (source_model.text);
}

/**
* Set case type of source and result texts.
*
* @param source_case case type of source text
* @param result_case case type of result text
*/
private void set_case_type (Define.CaseType source_case, Define.CaseType result_case) {
converter.source_case = Util.to_chcase_case (source_case);
converter.result_case = Util.to_chcase_case (result_case);
}

/**
* Convert case of source_text to the case set with {@link set_case_type}.
*
* @param source_text text that is converted
* @return text after conversion
*/
private string convert_case (string source_text) {
return converter.convert_case (source_text);
}
}
Loading