[gtk+] gtk-demo: Add window size saving example



commit 3a499d61dce4c2dbcafc7a401d17bce3de127bd9
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Feb 13 22:53:16 2016 -0500

    gtk-demo: Add window size saving example
    
    Implement the recommendations from
    https://wiki.gnome.org/HowDoI/SaveWindowState
    in the Application Class example.

 demos/gtk-demo/application.c            |  151 +++++++++++++++++++++++++++----
 demos/gtk-demo/application.ui           |   11 +--
 demos/gtk-demo/org.gtk.Demo.gschema.xml |    9 ++
 3 files changed, 148 insertions(+), 23 deletions(-)
---
diff --git a/demos/gtk-demo/application.c b/demos/gtk-demo/application.c
index 2ad143e..195eb61 100644
--- a/demos/gtk-demo/application.c
+++ b/demos/gtk-demo/application.c
@@ -23,7 +23,15 @@ typedef struct {
 
   GtkWidget *message;
   GtkWidget *infobar;
+  GtkWidget *status;
+  GtkWidget *menutool;
+  GMenuModel *toolmenu;
   GtkTextBuffer *buffer;
+
+  int width;
+  int height;
+  gboolean maximized;
+  gboolean fullscreen;
 } DemoApplicationWindow;
 typedef GtkApplicationWindowClass DemoApplicationWindowClass;
 
@@ -241,8 +249,8 @@ activate_quit (GSimpleAction *action,
 }
 
 static void
-update_statusbar (GtkTextBuffer *buffer,
-                  GtkStatusbar  *statusbar)
+update_statusbar (GtkTextBuffer         *buffer,
+                  DemoApplicationWindow *window)
 {
   gchar *msg;
   gint row, col;
@@ -250,7 +258,7 @@ update_statusbar (GtkTextBuffer *buffer,
   GtkTextIter iter;
 
   /* clear any previous message, underflow is allowed */
-  gtk_statusbar_pop (statusbar, 0);
+  gtk_statusbar_pop (GTK_STATUSBAR (window->status), 0);
 
   count = gtk_text_buffer_get_char_count (buffer);
 
@@ -264,18 +272,18 @@ update_statusbar (GtkTextBuffer *buffer,
   msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document",
                          row, col, count);
 
-  gtk_statusbar_push (statusbar, 0, msg);
+  gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, msg);
 
   g_free (msg);
 }
 
 static void
-mark_set_callback (GtkTextBuffer     *buffer,
-                   const GtkTextIter *new_location,
-                   GtkTextMark       *mark,
-                   gpointer           data)
+mark_set_callback (GtkTextBuffer         *buffer,
+                   const GtkTextIter     *new_location,
+                   GtkTextMark           *mark,
+                   DemoApplicationWindow *window)
 {
-  update_statusbar (buffer, GTK_STATUSBAR (data));
+  update_statusbar (buffer, window);
 }
 
 static void
@@ -333,9 +341,9 @@ static GActionEntry win_entries[] = {
 };
 
 static void
-clicked_cb (GtkWidget *widget, GtkWidget *info)
+clicked_cb (GtkWidget *widget, DemoApplicationWindow *window)
 {
-  gtk_widget_hide (info);
+  gtk_widget_hide (window->infobar);
 }
 
 static void
@@ -365,9 +373,13 @@ create_window (GApplication *app,
 {
   DemoApplicationWindow *window;
 
-  window = (DemoApplicationWindow *)g_object_new (demo_application_window_get_type (), NULL);
+  window = (DemoApplicationWindow *)g_object_new (demo_application_window_get_type (),
+                                                  "application", app,
+                                                  NULL);
   if (content)
     gtk_text_buffer_set_text (window->buffer, content, -1);
+
+  gtk_window_present (GTK_WINDOW (window));
 }
 
 static void
@@ -391,6 +403,8 @@ demo_application_init (DemoApplication *app)
   action = g_settings_create_action (settings, "color");
 
   g_action_map_add_action (G_ACTION_MAP (app), action);
+
+  g_object_unref (settings);
 }
 
 static void
@@ -403,23 +417,127 @@ demo_application_class_init (DemoApplicationClass *class)
 }
 
 static void
-demo_application_window_init (DemoApplicationWindow *win)
+demo_application_window_store_state (DemoApplicationWindow *win)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.Demo");
+  g_settings_set (settings, "window-size", "(ii)", win->width, win->height);
+  g_settings_set_boolean (settings, "maximized", win->maximized);
+  g_settings_set_boolean (settings, "fullscreen", win->fullscreen);
+  g_object_unref (settings);
+}
+
+static void
+demo_application_window_load_state (DemoApplicationWindow *win)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.Demo");
+  g_settings_get (settings, "window-size", "(ii)", &win->width, &win->height);
+  win->maximized = g_settings_get_boolean (settings, "maximized");
+  win->fullscreen = g_settings_get_boolean (settings, "fullscreen");
+  g_object_unref (settings);
+}
+
+static void
+demo_application_window_init (DemoApplicationWindow *window)
 {
-  gtk_widget_init_template (GTK_WIDGET (win));
-  g_action_map_add_action_entries (G_ACTION_MAP (win),
+  GtkWidget *menu;
+
+  window->width = -1;
+  window->height = -1;
+  window->maximized = FALSE;
+  window->fullscreen = FALSE;
+
+  gtk_widget_init_template (GTK_WIDGET (window));
+
+  menu = gtk_menu_new_from_model (window->toolmenu);
+  gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (window->menutool), menu);
+
+  g_action_map_add_action_entries (G_ACTION_MAP (window),
                                    win_entries, G_N_ELEMENTS (win_entries),
-                                   win);
+                                   window);
+}
+
+static void
+demo_application_window_constructed (GObject *object)
+{
+  DemoApplicationWindow *window = (DemoApplicationWindow *)object;
+
+  demo_application_window_load_state (window);
+
+  gtk_window_set_default_size (GTK_WINDOW (window), window->width, window->height);
+
+  if (window->maximized)
+    gtk_window_maximize (GTK_WINDOW (window));
+
+  if (window->fullscreen)
+    gtk_window_fullscreen (GTK_WINDOW (window));
+
+  G_OBJECT_CLASS (demo_application_window_parent_class)->constructed (object);
+}
+
+static void
+demo_application_window_size_allocate (GtkWidget     *widget,
+                                       GtkAllocation *allocation)
+{
+  DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
+
+  GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget, allocation);
+
+  if (!window->maximized && !window->fullscreen)
+    {
+      window->width = allocation->width;
+      window->height = allocation->height;
+    }
+}
+
+static gboolean
+demo_application_window_state_event (GtkWidget           *widget,
+                                     GdkEventWindowState *event)
+{
+  DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
+  gboolean res = GDK_EVENT_PROPAGATE;
+
+  if (GTK_WIDGET_CLASS (demo_application_window_parent_class)->window_state_event)
+    res = GTK_WIDGET_CLASS (demo_application_window_parent_class)->window_state_event (widget, event);
+
+  window->maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
+  window->fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
+
+  return res;
+}
+
+static void
+demo_application_window_destroy (GtkWidget *widget)
+{
+  DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
+
+  demo_application_window_store_state (window);
+
+  GTK_WIDGET_CLASS (demo_application_window_parent_class)->destroy (widget);
 }
 
 static void
 demo_application_window_class_init (DemoApplicationWindowClass *class)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
+  object_class->constructed = demo_application_window_constructed;
+
+  widget_class->size_allocate = demo_application_window_size_allocate;
+  widget_class->window_state_event = demo_application_window_state_event;
+  widget_class->destroy = demo_application_window_destroy;
+
   gtk_widget_class_set_template_from_resource (widget_class, "/application/application.ui");
   gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, message);
   gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, infobar);
+  gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, status);
   gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, buffer);
+  gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, menutool);
+  gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, toolmenu);
   gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
   gtk_widget_class_bind_template_callback (widget_class, update_statusbar);
   gtk_widget_class_bind_template_callback (widget_class, mark_set_callback);
@@ -432,6 +550,7 @@ main (int argc, char *argv[])
 
   app = GTK_APPLICATION (g_object_new (demo_application_get_type (),
                                        "application-id", "org.gtk.Demo2",
+                                       "flags", G_APPLICATION_HANDLES_OPEN,
                                        NULL));
 
   return g_application_run (G_APPLICATION (app), 0, NULL);
diff --git a/demos/gtk-demo/application.ui b/demos/gtk-demo/application.ui
index 4945b2e..871c6f8 100644
--- a/demos/gtk-demo/application.ui
+++ b/demos/gtk-demo/application.ui
@@ -1,11 +1,10 @@
 <?xml version="1.0"?>
 <interface>
-  <template class="DemoApplicationWindow" parent="GtkWindow">
+  <template class="DemoApplicationWindow" parent="GtkApplicationWindow">
     <property name="title" translatable="yes">Application Class</property>
     <property name="default-width">200</property>
     <property name="default-height">200</property>
     <property name="icon-name">document-open</property>
-    <property name="visible">1</property>
     <child>
       <object class="GtkGrid" id="grid">
         <property name="visible">1</property>
@@ -20,7 +19,6 @@
               <object class="GtkMenuToolButton" id="menutool">
                 <property name="visible">1</property>
                 <property name="icon-name">document-open</property>
-                <property name="menumodel">toolmenu</property>
               </object>
             </child>
             <child>
@@ -50,7 +48,6 @@
         </child>
         <child>
           <object class="GtkInfoBar" id="infobar">
-            <property name="visible">1</property>
             <property name="no-show-all">1</property>
             <property name="hexpand">1</property>
             <child internal-child="content_area">
@@ -71,7 +68,7 @@
                     <property name="valign">center</property>
                     <property name="label" translatable="yes">_OK</property>
                     <property name="use_underline">1</property>
-                    <signal name="clicked" handler="cliced_cb" object="infobar"/>
+                    <signal name="clicked" handler="clicked_cb"/>
                   </object>
                 </child>
               </object>
@@ -120,7 +117,7 @@
     </item>
   </menu>
   <object class="GtkTextBuffer" id="buffer">
-    <signal name="changed" handler="update_statusbar" object="status"/>
-    <signal name="mark-set" handler="mark_set_callback" object="status"/>
+    <signal name="changed" handler="update_statusbar"/>
+    <signal name="mark-set" handler="mark_set_callback"/>
   </object>
 </interface>
diff --git a/demos/gtk-demo/org.gtk.Demo.gschema.xml b/demos/gtk-demo/org.gtk.Demo.gschema.xml
index 33e12aa..93be088 100644
--- a/demos/gtk-demo/org.gtk.Demo.gschema.xml
+++ b/demos/gtk-demo/org.gtk.Demo.gschema.xml
@@ -12,6 +12,15 @@
     <key name='color' enum='org.gtk.Demo.Color'>
       <default>'red'</default>
     </key>
+    <key name='window-size' type='(ii)'>
+      <default>(-1, -1)</default>
+    </key>
+    <key name='maximized' type='b'>
+      <default>false</default>
+    </key>
+    <key name='fullscreen' type='b'>
+      <default>false</default>
+    </key>
   </schema>
 
 </schemalist>


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