[gnome-sudoku] Responsive layout based on HdySqueezer



commit 84c166dd04f78e545556f8588e5d4e7b471f3fb3
Author: lajonss <l3n1 dupaw eu>
Date:   Thu Nov 19 02:43:47 2020 +0100

    Responsive layout based on HdySqueezer

 data/gnome-sudoku.ui  | 192 +++++++++++++++++++++++++++-----------------------
 meson.build           |   1 +
 src/gnome-sudoku.vala |  87 +++++++++++++++--------
 src/meson.build       |   2 +-
 4 files changed, 163 insertions(+), 119 deletions(-)
---
diff --git a/data/gnome-sudoku.ui b/data/gnome-sudoku.ui
index f42dd387..04589406 100644
--- a/data/gnome-sudoku.ui
+++ b/data/gnome-sudoku.ui
@@ -235,116 +235,130 @@
               </packing>
             </child>
             <child>
-              <object class="GtkAspectFrame" id="frame">
+              <object class="HdySqueezer" id="squeezer">
                 <property name="visible">True</property>
-                <property name="shadow-type">GTK_SHADOW_NONE</property>
-                <property name="obey-child">False</property>
-                <property name="ratio">1.4</property>
+                <property name="transition-type">crossfade</property>
                 <child>
-                  <object class="GtkBox" id="game_box">
+                  <object class="GtkAspectFrame" id="frame_h">
                     <property name="visible">True</property>
-                    <property name="spacing">25</property>
+                    <property name="shadow-type">GTK_SHADOW_NONE</property>
+                    <property name="obey-child">False</property>
+                    <property name="ratio">1.4</property>
                     <child>
-                      <object class="GtkButtonBox" id="controls_box">
+                      <object class="GtkBox" id="game_box">
                         <property name="visible">True</property>
-                        <property name="halign">end</property>
-                        <property name="valign">end</property>
-                        <property name="can-focus">False</property>
-                        <property name="orientation">vertical</property>
-                        <property name="spacing">6</property>
+                        <property name="spacing">25</property>
                         <child>
-                          <object class="GtkButton" id="play_pause_button">
+                          <object class="GtkButtonBox" id="controls_box">
                             <property name="visible">True</property>
-                            <property name="can-focus">True</property>
-                            <property name="receives-default">True</property>
-                            <property name="action-name">app.pause</property>
-                            <property name="use-underline">True</property>
-                            <property name="width-request">120</property>
-                            <property name="height-request">60</property>
+                            <property name="halign">end</property>
+                            <property name="valign">end</property>
+                            <property name="can-focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">6</property>
                             <child>
-                              <object class="GtkLabel" id="play_pause_label">
+                              <object class="GtkButton" id="play_pause_button">
                                 <property name="visible">True</property>
-                                <property name="can-focus">False</property>
-                                <property name="margin">12</property>
-                                <property name="label" translatable="yes">_Pause</property>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">True</property>
+                                <property name="action-name">app.pause</property>
                                 <property name="use-underline">True</property>
+                                <property name="width-request">120</property>
+                                <property name="height-request">60</property>
+                                <child>
+                                  <object class="GtkLabel" id="play_pause_label">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">False</property>
+                                    <property name="margin">12</property>
+                                    <property name="label" translatable="yes">_Pause</property>
+                                    <property name="use-underline">True</property>
+                                  </object>
+                                </child>
                               </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="pack-type">end</property>
+                                <property name="position">0</property>
+                              </packing>
                             </child>
-                          </object>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="visible">True</property>
+                                <property name="use-underline">True</property>
+                                <property name="label" translatable="yes">_Clear Board</property>
+                                <property name="halign">fill</property>
+                                <property name="valign">center</property>
+                                <property name="action-name">app.reset</property>
+                                <property name="tooltip-text" translatable="yes">Reset the board to its 
original state</property>
+                                <property name="width-request">120</property>
+                                <property name="height-request">60</property>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="visible">True</property>
+                                <property name="use-underline">True</property>
+                                <property name="label" translatable="yes">_New Puzzle</property>
+                                <property name="halign">fill</property>
+                                <property name="valign">center</property>
+                                <property name="action-name">app.new-game</property>
+                                <property name="tooltip-text" translatable="yes">Start a new 
puzzle</property>
+                                <property name="width-request">120</property>
+                                <property name="height-request">60</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="play_custom_game_button">
+                                <property name="visible">False</property>
+                                <property name="use-underline">True</property>
+                                <property name="label" translatable="yes">_Start Playing</property>
+                                <property name="halign">fill</property>
+                                <property name="valign">center</property>
+                                <property name="action-name">app.play-custom-game</property>
+                                <property name="tooltip-text" translatable="yes">Start playing the custom 
puzzle you have created</property>
+                                <property name="width-request">120</property>
+                                <property name="height-request">60</property>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                          </object>  <!-- End of controls_box -->
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">True</property>
                             <property name="pack-type">end</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton">
-                            <property name="visible">True</property>
-                            <property name="use-underline">True</property>
-                            <property name="label" translatable="yes">_Clear Board</property>
-                            <property name="halign">fill</property>
-                            <property name="valign">center</property>
-                            <property name="action-name">app.reset</property>
-                            <property name="tooltip-text" translatable="yes">Reset the board to its original 
state</property>
-                            <property name="width-request">120</property>
-                            <property name="height-request">60</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton">
-                            <property name="visible">True</property>
-                            <property name="use-underline">True</property>
-                            <property name="label" translatable="yes">_New Puzzle</property>
-                            <property name="halign">fill</property>
-                            <property name="valign">center</property>
-                            <property name="action-name">app.new-game</property>
-                            <property name="tooltip-text" translatable="yes">Start a new puzzle</property>
-                            <property name="width-request">120</property>
-                            <property name="height-request">60</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
+                            <property name="padding">0</property>
                           </packing>
                         </child>
-                        <child>
-                          <object class="GtkButton" id="play_custom_game_button">
-                            <property name="visible">False</property>
-                            <property name="use-underline">True</property>
-                            <property name="label" translatable="yes">_Start Playing</property>
-                            <property name="halign">fill</property>
-                            <property name="valign">center</property>
-                            <property name="action-name">app.play-custom-game</property>
-                            <property name="tooltip-text" translatable="yes">Start playing the custom puzzle 
you have created</property>
-                            <property name="width-request">120</property>
-                            <property name="height-request">60</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                      </object>  <!-- End of controls_box -->
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="pack-type">end</property>
-                        <property name="padding">0</property>
-                      </packing>
+                      </object> <!-- End of game_box -->
                     </child>
-                  </object> <!-- End of game_box -->
+                  </object> <!-- End of frame_h -->
+                </child>
+                <child>
+                  <object class="GtkAspectFrame" id="frame_v">
+                    <property name="visible">True</property>
+                    <property name="shadow-type">GTK_SHADOW_NONE</property>
+                    <property name="obey-child">False</property>
+                    <property name="ratio">0.9</property>
+                  </object> <!-- End of frame_v -->
                 </child>
-              </object> <!-- End of frame -->
+              </object> <!-- End of squeezer -->
               <packing>
-                <property name="name">frame</property>
+                <property name="name">squeezer</property>
               </packing>
             </child>
           </object> <!-- End of main_stack -->
diff --git a/meson.build b/meson.build
index c4e5c9c3..d188fd2b 100644
--- a/meson.build
+++ b/meson.build
@@ -36,6 +36,7 @@ gtk = dependency('gtk+-3.0', version: '>= 3.24.0')
 json_glib = dependency('json-glib-1.0')
 qqwing = dependency('qqwing', version: '>= 1.3.4')
 threads = dependency('threads')
+libhandy = dependency('libhandy-1')
 
 config_include_dir = include_directories('.')
 
diff --git a/src/gnome-sudoku.vala b/src/gnome-sudoku.vala
index 08e0c9d3..8f75839a 100644
--- a/src/gnome-sudoku.vala
+++ b/src/gnome-sudoku.vala
@@ -42,8 +42,10 @@ public class Sudoku : Gtk.Application
 
     private HeaderBar headerbar;
     private Stack main_stack;
+    private Hdy.Squeezer squeezer;
+    private AspectFrame frame_v;
+    private AspectFrame frame_h;
     private Box game_box; // Holds the view
-    private AspectFrame frame;
     private ButtonBox controls_box;
 
     private Box undo_redo_box;
@@ -51,6 +53,8 @@ public class Sudoku : Gtk.Application
 
     private SudokuSaver saver;
 
+    private Orientation current_layout = Orientation.HORIZONTAL;
+
     private SimpleAction undo_action;
     private SimpleAction redo_action;
     private SimpleAction clear_action;
@@ -60,11 +64,11 @@ public class Sudoku : Gtk.Application
     private SimpleAction play_custom_game_action;
     private SimpleAction new_game_action;
 
-    private Orientation current_layout;
-
     private bool show_possibilities = false;
     private GameMode current_game_mode = GameMode.PLAY;
 
+    private const int board_size = 360;
+
     private const GLib.ActionEntry action_entries[] =
     {
         {"new-game", new_game_cb                                    },
@@ -162,7 +166,6 @@ public class Sudoku : Gtk.Application
         window.size_allocate.connect (size_allocate_cb);
         window.window_state_event.connect (window_state_event_cb);
         window.set_default_size (settings.get_int ("window-width"), settings.get_int ("window-height"));
-        window.configure_event.connect (configure_event_cb);
         if (settings.get_boolean ("window-is-maximized"))
             window.maximize ();
 
@@ -170,10 +173,14 @@ public class Sudoku : Gtk.Application
 
         headerbar = (HeaderBar) builder.get_object ("headerbar");
         main_stack = (Stack) builder.get_object ("main_stack");
+
+        squeezer = (Hdy.Squeezer) builder.get_object ("squeezer");
+        squeezer.draw.connect (draw_cb);
+
+        frame_h = (AspectFrame) builder.get_object ("frame_h");
+        frame_v = (AspectFrame) builder.get_object ("frame_v");
         game_box = (Box) builder.get_object ("game_box");
-        frame = (AspectFrame) builder.get_object ("frame");
         controls_box = (ButtonBox) builder.get_object ("controls_box");
-
         undo_redo_box = (Box) builder.get_object ("undo_redo_box");
         back_button = (Button) builder.get_object ("back_button");
         clock_label = (Label) builder.get_object ("clock_label");
@@ -192,6 +199,7 @@ public class Sudoku : Gtk.Application
         play_custom_game_action = (SimpleAction) lookup_action ("play-custom-game");
 
         window.set_titlebar (headerbar);
+        prepare_layout ();
 
         saver = new SudokuSaver ();
         var savegame = saver.get_savedgame ();
@@ -369,7 +377,6 @@ public class Sudoku : Gtk.Application
         if (view != null)
             game_box.remove (view);
 
-        check_initial_layout_ratio ();
         show_game_view ();
         game = new SudokuGame (board);
         game.mode = current_game_mode;
@@ -385,7 +392,7 @@ public class Sudoku : Gtk.Application
         game.start_clock ();
 
         view = new SudokuView (game);
-        view.set_size_request (480, 480);
+        view.set_size_request (board_size, board_size);
 
         view.show_possibilities = show_possibilities;
         if (current_game_mode == GameMode.CREATE)
@@ -518,7 +525,7 @@ public class Sudoku : Gtk.Application
 
     private void show_game_view ()
     {
-        main_stack.set_visible_child_name ("frame");
+        main_stack.set_visible_child_name ("squeezer");
         back_button.visible = false;
         undo_redo_box.visible = true;
         print_action.set_enabled (true);
@@ -558,7 +565,7 @@ public class Sudoku : Gtk.Application
 
     private void undo_cb ()
     {
-        if (main_stack.get_visible_child_name () != "frame")
+        if (main_stack.get_visible_child_name () != "squeezer")
             return;
         game.undo ();
         undo_action.set_enabled (!game.is_undostack_null ());
@@ -568,7 +575,7 @@ public class Sudoku : Gtk.Application
 
     private void redo_cb ()
     {
-        if (main_stack.get_visible_child_name () != "frame")
+        if (main_stack.get_visible_child_name () != "squeezer")
             return;
         game.redo ();
         redo_action.set_enabled (!game.is_redostack_null ());
@@ -578,7 +585,7 @@ public class Sudoku : Gtk.Application
 
     private void print_cb ()
     {
-        if (main_stack.get_visible_child_name () != "frame")
+        if (main_stack.get_visible_child_name () != "squeezer")
             return;
         print_action.set_enabled (false);
         print_multiple_action.set_enabled (false);
@@ -598,7 +605,7 @@ public class Sudoku : Gtk.Application
         print_multiple_action.set_enabled (false);
         var print_dialog = new PrintDialog (saver, window);
         print_dialog.destroy.connect (() => {
-            this.print_action.set_enabled (main_stack.get_visible_child_name () == "frame");
+            this.print_action.set_enabled (main_stack.get_visible_child_name () == "squeezer");
             this.print_multiple_action.set_enabled (true);
         });
         print_dialog.run ();
@@ -642,41 +649,63 @@ public class Sudoku : Gtk.Application
                                );
     }
 
-    private void check_initial_layout_ratio ()
+    private void prepare_layout ()
+    {
+        var main_stack_m = main_stack.margin;
+        var game_box_s = game_box.spacing;
+        var controls_box_s = controls_box.spacing;
+        var button_w = play_pause_button.width_request;
+        var button_h = play_pause_button.height_request;
+
+        var complementary_size = (int) (board_size + 2 * game_box_s + 2 * main_stack_m);
+        var board_and_spacing = board_size + 3 * game_box_s + 2 * controls_box_s + 2 * main_stack_m;
+
+        frame_h.width_request = (int) (board_and_spacing + button_w);
+        frame_h.height_request = complementary_size;
+
+        frame_v.width_request = complementary_size;
+        frame_v.height_request =  (int) (board_and_spacing + button_h);
+    }
+
+    private bool draw_cb ()
     {
-        apply_layout_ratio (get_window_orientation ());
+        return check_layout_change ();
     }
 
-    private bool configure_event_cb ()
+    private bool check_layout_change ()
     {
         var layout = get_window_orientation ();
-        if (layout == current_layout)
-            return false;
-
-        apply_layout_ratio (layout);
-        return false;
+        var changed = layout != current_layout;
+        if (changed)
+            set_layout (layout);
+        return changed;
     }
 
     private Orientation get_window_orientation ()
     {
-        int width, height;
-        window.get_size(out width, out height);
-        return width > height ? Orientation.HORIZONTAL : Orientation.VERTICAL;
+        var is_vertical = squeezer.visible_child == frame_v;
+        return is_vertical ? Orientation.VERTICAL : Orientation.HORIZONTAL;
     }
 
-    private void apply_layout_ratio (Orientation layout)
+    private void set_layout (Orientation layout)
     {
-        if(layout == Orientation.HORIZONTAL) {
-            frame.ratio = 1.4f;
+        current_layout = layout;
+        AspectFrame previous;
+        AspectFrame next;
+        if (layout == Orientation.HORIZONTAL) {
+            next = frame_h;
+            previous = frame_v;
             controls_box.halign = Align.END;
             controls_box.orientation = Orientation.VERTICAL;
         } else {
-            frame.ratio = 0.8f;
+            next = frame_v;
+            previous = frame_h;
             controls_box.halign = Align.CENTER;
             controls_box.orientation = Orientation.HORIZONTAL;
         }
         game_box.orientation = layout;
-        current_layout = layout;
+        previous.remove (game_box);
+        next.add (game_box);
     }
 
     public static int main (string[] args)
diff --git a/src/meson.build b/src/meson.build
index 4b17c75c..a81994e7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -14,7 +14,7 @@ gnome_sudoku_sources = [
   resources
 ]
 
-gnome_sudoku_dependencies = [gtk, libsudoku_dep]
+gnome_sudoku_dependencies = [gtk, libhandy, libsudoku_dep]
 
 gnome_sudoku = executable(meson.project_name(), gnome_sudoku_sources,
   vala_args: gnome_sudoku_vala_args,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]