From 6319682fd34705536ec1a552db1b216aeded93a1 Mon Sep 17 00:00:00 2001 From: jeremy Date: Sat, 17 Feb 2018 17:39:12 +0000 Subject: [PATCH] Use property bindings for AppMenu instead of signals --- src/Gnonogram_controller.vala | 60 ++++++-------- src/Gnonogram_view.vala | 137 ++++++++------------------------ src/widgets/AppMenu.vala | 102 ++++++++++-------------- src/widgets/ViewModeButton.vala | 58 +++++++------- 4 files changed, 125 insertions(+), 232 deletions(-) diff --git a/src/Gnonogram_controller.vala b/src/Gnonogram_controller.vala index 58b1172..7ebace1 100644 --- a/src/Gnonogram_controller.vala +++ b/src/Gnonogram_controller.vala @@ -30,24 +30,30 @@ public class Controller : GLib.Object { return (Gtk.Window)view; } } - + public GameState game_state {get; set;} + public Dimensions dimensions {get; set;} public Difficulty generator_grade {get; set;} construct { model = new Model (); - bind_property ("dimensions", model, "dimensions"); view = new View (model); - bind_property ("dimensions", view, "dimensions"); - bind_property ("generator_grade", view, "generator_grade"); + + bind_property ("dimensions", model, "dimensions"); + bind_property ("game-state", model, "game-state"); + + /* Need bidirectional bindings so AppMenu can update controller without request*/ + var binding_flags = BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE; + bind_property ("dimensions", view, "dimensions", binding_flags); + bind_property ("generator-grade", view, "generator-grade", binding_flags); + bind_property ("game-state", view, "game-state", binding_flags); + history = new Gnonograms.History (); /* Connect signals. Must be done before restoring settings so that e.g. * dimensions of model are set. */ - view.resize_request.connect (on_view_resize_request); view.moved.connect (on_moved); view.next_move_request.connect (on_next_move_request); view.previous_move_request.connect (on_previous_move_request); - view.mode_change_request.connect (on_view_mode_change_request); view.check_errors_request.connect (on_count_errors_request); view.rewind_request.connect (on_rewind_request); view.delete_event.connect (on_view_deleted); @@ -57,6 +63,17 @@ public class Controller : GLib.Object { view.solve_this_request.connect (on_solve_this_request); view.restart_request.connect (on_restart_request); + notify["game-state"].connect (() => { + if (game_state == GameState.GENERATING) { + on_new_random_request (); + } + }); + + notify["dimensions"].connect (() => { + clear (); + game_state = GameState.SETTING; + }); + var schema_source = GLib.SettingsSchemaSource.get_default (); if (schema_source.lookup ("com.github.jeremypw.gnonograms.settings", true) != null && schema_source.lookup ("com.github.jeremypw.gnonograms.saved-state", true) != null) { @@ -153,27 +170,6 @@ public class Controller : GLib.Object { } } - private GameState _game_state; - public GameState game_state { - get { - return _game_state; - } - - set { - if (_game_state != value) { - _game_state = value; - view.game_state = value; - model.game_state = value; - - if (value == GameState.GENERATING) { - on_new_random_request (); - } - } - } - } - - public Dimensions dimensions {get; set;} - private bool is_solving { get { return game_state == GameState.SOLVING; @@ -601,16 +597,6 @@ public class Controller : GLib.Object { rewind_until_correct (); } - private void on_view_resize_request (Dimensions dim) { - clear (); - dimensions = dim; - game_state = GameState.SETTING; - } - - private void on_view_mode_change_request (GameState gs) { - game_state = gs; - } - private bool on_view_deleted () { quit (); return false; diff --git a/src/Gnonogram_view.vala b/src/Gnonogram_view.vala index 57cdc44..7c25de8 100644 --- a/src/Gnonogram_view.vala +++ b/src/Gnonogram_view.vala @@ -34,51 +34,13 @@ public class View : Gtk.ApplicationWindow { public signal void open_game_request (); public signal void solve_this_request (); public signal void restart_request (); - public signal void resize_request (Dimensions dim); public signal void moved (Cell cell); - public signal void mode_change_request (GameState gs); - public Model model { get; construct; } - - private string? _game_name = null; - public string game_name { - get { - if (_game_name == null || _game_name == "") { - return Gnonograms.UNTITLED_NAME; - } else { - return _game_name; - } - } - - set { - _game_name = value; - if (value != Gnonograms.UNTITLED_NAME) { - app_menu.title = value; - } - - update_header_bar (); - } - } - - private Dimensions _dimensions; - public Dimensions dimensions { - private get { - return _dimensions; - } - - set { - if (value != _dimensions) { - _dimensions = value; - - row_clue_box.dimensions = dimensions; - column_clue_box.dimensions = dimensions; - fontheight = get_default_fontheight_from_dimensions (); - - } - - queue_draw (); - } - } + public Model model {private get; construct; } + public Dimensions dimensions {get; set;} + public Difficulty generator_grade {get; set;} + public GameState game_state {get; set;} + public string game_name {get; set; default = "";} private Difficulty _game_grade = Difficulty.UNDEFINED; public Difficulty game_grade { // Difficulty of game actually loaded @@ -88,21 +50,10 @@ public class View : Gtk.ApplicationWindow { set { _game_grade = value; - update_header_bar (); + header_bar.subtitle = game_grade.to_string ();; } } - private Difficulty _generator_grade; - public Difficulty generator_grade { // Grade setting - get { - return _generator_grade; - } - - set { - _generator_grade = value; - app_menu.grade_val = (uint)_generator_grade; - } - } private bool _readonly; public bool readonly { @@ -146,19 +97,6 @@ public class View : Gtk.ApplicationWindow { } } - public GameState game_state { - private get { - return mode_switch.mode; - } - - set { - mode_switch.mode = value; - cell_grid.game_state = value; - - update_header_bar (); - } - } - private bool _can_go_back; public bool can_go_back { get { @@ -302,15 +240,12 @@ public class View : Gtk.ApplicationWindow { auto_solve_button.sensitive = false; app_menu = new AppMenu (); - /* Ensure values match view before showing */ - app_menu.clicked.connect (() => { - app_menu.row_val = dimensions.rows (); - app_menu.column_val = dimensions.cols (); - app_menu.grade_val = (uint)_generator_grade; - app_menu.title = game_name; - }); + bind_property ("dimensions", app_menu, "dimensions", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); + bind_property ("generator-grade", app_menu, "grade", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); + bind_property ("game-name", app_menu, "title", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); mode_switch = new ViewModeButton (); + bind_property ("game-state", mode_switch, "mode", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); progress_indicator = new Gnonograms.Progress_indicator (); progress_indicator.get_style_context ().add_class ("progress"); @@ -342,6 +277,9 @@ public class View : Gtk.ApplicationWindow { row_clue_box = new LabelBox (Gtk.Orientation.VERTICAL); column_clue_box = new LabelBox (Gtk.Orientation.HORIZONTAL); + bind_property ("dimensions", row_clue_box, "dimensions"); + bind_property ("dimensions", column_clue_box, "dimensions"); + cell_grid = new CellGrid (model); main_grid = new Gtk.Grid (); @@ -366,12 +304,9 @@ public class View : Gtk.ApplicationWindow { add (overlay); /* Connect signal handlers */ - mode_switch.mode_changed.connect (on_mode_switch_changed); key_press_event.connect (on_key_press_event); key_release_event.connect (on_key_release_event); - app_menu.apply.connect (on_app_menu_apply); - load_game_button.clicked.connect (on_load_game_button_clicked); save_game_button.clicked.connect (on_save_game_button_clicked); save_game_as_button.clicked.connect (on_save_game_as_button_clicked); @@ -380,6 +315,26 @@ public class View : Gtk.ApplicationWindow { redo_button.clicked.connect (on_redo_button_pressed); restart_button.clicked.connect (on_restart_button_pressed); auto_solve_button.clicked.connect (on_auto_solve_button_pressed); + + notify["game-state"].connect (() => { + cell_grid.game_state = game_state; + update_header_bar (); + queue_draw (); + }); + + notify["dimensions"].connect (() => { + row_clue_box.dimensions = dimensions; + column_clue_box.dimensions = dimensions; + fontheight = get_default_fontheight_from_dimensions (); + }); + + notify["generator-grade"].connect (() => { + mode_switch.grade = generator_grade; + }); + + notify["game-name"].connect (() => { + update_header_bar (); + }); } public string[] get_row_clues () { @@ -595,14 +550,11 @@ public class View : Gtk.ApplicationWindow { set_buttons_sensitive (true); } else if (gs == GameState.SOLVING) { header_bar.title = _("Solving %s").printf (game_name); - header_bar.subtitle = game_grade.to_string (); restart_button.tooltip_text = _("Restart solving"); set_buttons_sensitive (true); } else if (gs == GameState.GENERATING) { set_buttons_sensitive (false); } - - mode_switch.grade = generator_grade; } private void set_buttons_sensitive (bool sensitive) { @@ -921,10 +873,6 @@ public class View : Gtk.ApplicationWindow { only_control_pressed = control_pressed && !other_mod_pressed; /* Shift can be pressed */ } - private void on_mode_switch_changed (Gtk.Widget widget) { - mode_change_request (mode_switch.mode); - } - private void on_save_game_button_clicked () { if (shift_pressed) { save_game_as_request (); @@ -973,25 +921,6 @@ public class View : Gtk.ApplicationWindow { restart_request (); } - private void on_app_menu_apply () { - game_name = app_menu.title; - - var grade = (Difficulty)(app_menu.grade_val); - var rows = (uint)app_menu.row_val; - var cols = (uint)app_menu.column_val; - - if (grade >= Difficulty.CHALLENGING && - (rows < 15 || cols < 15)) { - - send_notification (_("Minimum size 15 for this difficulty")); - return; - } else { - generator_grade = grade; - Dimensions dim = {cols, rows}; - resize_request (dim); - } - } - private void zoom_out () { int min, nat; header_bar.get_preferred_width (out min, out nat); diff --git a/src/widgets/AppMenu.vala b/src/widgets/AppMenu.vala index 4fc38ad..51065bd 100644 --- a/src/widgets/AppMenu.vala +++ b/src/widgets/AppMenu.vala @@ -29,53 +29,11 @@ class AppMenu : Gtk.MenuButton { private AppSetting title_setting; private Gtk.Grid grid; - private uint _grade_val; - public uint grade_val { - get { - return _grade_val; - } - - set { - _grade_val = value; - grade_setting.set_value (value); - } - } - - private uint _row_val; - public uint row_val { - get { - return _row_val; - } - - set { - _row_val = value; - row_setting.set_value (value); - } - } - - private uint _column_val; - public uint column_val { - get { - return _column_val; - } - - set { - _column_val = value; - column_setting.set_value (value); - } - } - - public string title { - get { - return title_setting.get_text (); - } + public Dimensions dimensions {get; set;} + public Difficulty grade {get; set;} + public string title {get; set;} - set { - title_setting.set_text (value); - } - } - - public signal void apply (); +// public signal void apply (); construct { popover = new AppPopover (this); @@ -99,19 +57,32 @@ class AppMenu : Gtk.MenuButton { grid.row_spacing = 6; grid.column_spacing = 6; - clicked.connect_after (() => { /* Allow parent to set values first */ - store_values (); - popover.show_all (); + toggled.connect (() => { /* Allow parent to set values first */ + if (active) { + update_dimension_settings (); + update_grade_setting (); + update_title_setting (); + popover.show_all (); + } }); app_popover.apply_settings.connect (() => { - store_values (); - apply (); + update_properties (); + }); + + notify["dimensions"].connect (() => { + update_dimension_settings (); + }); + + notify["grade"].connect (() => { + update_grade_setting (); }); - app_popover.cancel.connect (() => { - restore_values (); + notify["title"].connect (() => { + update_title_setting (); }); + + } public AppMenu () { @@ -119,20 +90,27 @@ class AppMenu : Gtk.MenuButton { tooltip_text = _("Options"); } - private void store_values () { - grade_val = (uint)(grade_setting.get_value ()); - row_val = (uint)(row_setting.get_value ()); - column_val = (uint)(column_setting.get_value ()); - title = title_setting.get_text (); + private void update_dimension_settings () { + row_setting.set_value (dimensions.rows ()); + column_setting.set_value (dimensions.cols ()); + } + + private void update_grade_setting () { + grade_setting.set_value ((uint)grade); } - private void restore_values () { - grade_setting.set_value (grade_val); - row_setting.set_value (row_val); - column_setting.set_value (column_val); + private void update_title_setting () { title_setting.set_text (title); } + private void update_properties () { + var rows = (uint)(row_setting.get_value ()); + var cols = (uint)(column_setting.get_value ()); + dimensions = {cols, rows}; + grade = (Difficulty)(grade_setting.get_value ()); + title = title_setting.get_text (); + } + private void add_setting (ref int pos, AppSetting setting) { var label = setting.get_heading (); label.xalign = 1; diff --git a/src/widgets/ViewModeButton.vala b/src/widgets/ViewModeButton.vala index fc8313f..74a8312 100644 --- a/src/widgets/ViewModeButton.vala +++ b/src/widgets/ViewModeButton.vala @@ -22,35 +22,7 @@ namespace Gnonograms { /** ModeButton used by View in headbar to switch between SETTING and SOLVING modes **/ public class ViewModeButton : Granite.Widgets.ModeButton { /** PUBLIC **/ - public GameState mode { - get { - if (selected == setting_index) { - return GameState.SETTING; - } else if (selected == solving_index) { - return GameState.SOLVING; - } else if (selected == generating_index) { - return GameState.GENERATING; - } else { - return GameState.UNDEFINED; - } - } - - set { - switch (value) { - case GameState.SETTING: - set_active (setting_index); - break; - case GameState.SOLVING: - set_active (solving_index); - break; - case GameState.GENERATING: - set_active (generating_index); - break; - default: - break; - } - } - } + public GameState mode {get; set;} public Difficulty grade { set { @@ -89,6 +61,34 @@ public class ViewModeButton : Granite.Widgets.ModeButton { setting_icon.tooltip_text = _("Draw pattern"); solving_icon.tooltip_text = _("Solve puzzle"); generating_icon.tooltip_text = _("Generate new random puzzle"); + + mode_changed.connect (() => { + if (selected == setting_index) { + mode = GameState.SETTING; + } else if (selected == solving_index) { + mode = GameState.SOLVING; + } else if (selected == generating_index) { + mode = GameState.GENERATING; + } else { + mode = GameState.UNDEFINED; + } + }); + + notify["mode"].connect (() => { + switch (mode) { + case GameState.SETTING: + set_active (setting_index); + break; + case GameState.SOLVING: + set_active (solving_index); + break; + case GameState.GENERATING: + set_active (generating_index); + break; + default: + break; + } + }); } } }