[gnome-flashback] desktop: calculate grid size



commit 50fcd59ac29920d779e66b377cd863f5f454fd80
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Mon Nov 4 20:05:02 2019 +0200

    desktop: calculate grid size

 gnome-flashback/libdesktop/gf-monitor-view.c | 290 +++++++++++++++++++++++++--
 1 file changed, 277 insertions(+), 13 deletions(-)
---
diff --git a/gnome-flashback/libdesktop/gf-monitor-view.c b/gnome-flashback/libdesktop/gf-monitor-view.c
index 4a89f6c..4b74a91 100644
--- a/gnome-flashback/libdesktop/gf-monitor-view.c
+++ b/gnome-flashback/libdesktop/gf-monitor-view.c
@@ -18,19 +18,37 @@
 #include "config.h"
 #include "gf-monitor-view.h"
 
+#include "gf-icon.h"
+#include "gf-utils.h"
+
 struct _GfMonitorView
 {
   GtkFixed    parent;
 
   GdkMonitor *monitor;
 
+  gboolean    grid_points;
+
   guint       icon_size;
   guint       extra_text_width;
   guint       column_spacing;
   guint       row_spacing;
 
-  int         width;
-  int         height;
+  guint       grid_size_id;
+
+  GtkWidget  *dummy_icon;
+
+  int         view_width;
+  int         view_height;
+
+  int         columns;
+  int         rows;
+
+  int         spacing_x;
+  int         spacing_y;
+
+  int         offset_x;
+  int         offset_y;
 };
 
 enum
@@ -39,6 +57,8 @@ enum
 
   PROP_MONITOR,
 
+  PROP_GRID_POINTS,
+
   PROP_ICON_SIZE,
   PROP_EXTRA_TEXT_WIDTH,
   PROP_COLUMN_SPACING,
@@ -51,6 +71,171 @@ static GParamSpec *view_properties[LAST_PROP] = { NULL };
 
 G_DEFINE_TYPE (GfMonitorView, gf_monitor_view, GTK_TYPE_FIXED)
 
+static void
+icon_destroy_cb (GtkWidget *widget,
+                 GFile     *file)
+{
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+static GtkWidget *
+create_dummy_icon (GfMonitorView *self)
+{
+  GFileIOStream *iostream;
+  GError *error;
+  GFile *file;
+  char *attributes;
+  GFileInfo *info;
+  GIcon *icon;
+  const char *name;
+  GtkWidget *widget;
+
+  iostream = NULL;
+  error = NULL;
+
+  file = g_file_new_tmp ("dummy-desktop-file-XXXXXX", &iostream, &error);
+
+  if (error != NULL)
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+  attributes = gf_build_attributes_list (G_FILE_ATTRIBUTE_STANDARD_NAME,
+                                         G_FILE_ATTRIBUTE_STANDARD_ICON,
+                                         NULL);
+
+  info = g_file_io_stream_query_info (iostream, attributes, NULL, &error);
+  g_object_unref (iostream);
+  g_free (attributes);
+
+  if (error != NULL)
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+  icon = g_icon_new_for_string ("text-x-generic", NULL);
+  g_file_info_set_icon (info, icon);
+  g_object_unref (icon);
+
+  name = "Lorem Ipsum is simply dummy text of the printing and typesetting "
+         "industry. Lorem Ipsum has been the industry's standard dummy text "
+         "ever since the 1500s, when an unknown printer took a galley of "
+         "type and scrambled it to make a type specimen book.";
+
+  g_file_info_set_name (info, name);
+
+  widget = gf_icon_new (file, info);
+  g_object_unref (info);
+
+  g_object_bind_property (self, "icon-size",
+                          widget, "icon-size",
+                          G_BINDING_DEFAULT |
+                          G_BINDING_SYNC_CREATE);
+
+  g_object_bind_property (self, "extra-text-width",
+                          widget, "extra-text-width",
+                          G_BINDING_DEFAULT |
+                          G_BINDING_SYNC_CREATE);
+
+  g_signal_connect (widget, "destroy",
+                    G_CALLBACK (icon_destroy_cb),
+                    g_object_ref (file));
+
+  g_object_unref (file);
+
+  return widget;
+}
+
+static void
+calculate_grid_size (GfMonitorView *self)
+{
+  GtkRequisition icon_size;
+  int columns;
+  int rows;
+
+  if (self->dummy_icon == NULL)
+    {
+      self->dummy_icon = create_dummy_icon (self);
+      gtk_widget_show (self->dummy_icon);
+    }
+
+  if (self->dummy_icon == NULL)
+    return;
+
+  gtk_widget_get_preferred_size (self->dummy_icon, &icon_size, NULL);
+
+  columns = self->view_width / icon_size.width;
+  rows = self->view_height / icon_size.height;
+
+  while (TRUE)
+    {
+      int spacing;
+
+      spacing = (columns - 1) * self->column_spacing;
+      if (spacing + columns * icon_size.width <= self->view_width ||
+          columns == 1)
+        break;
+
+      columns--;
+    }
+
+  while (TRUE)
+    {
+      int spacing;
+
+      spacing = (rows - 1) * self->row_spacing;
+      if (spacing + rows * icon_size.height <= self->view_height ||
+          rows == 1)
+        break;
+
+      rows--;
+    }
+
+  self->columns = columns;
+  self->rows = rows;
+
+  self->spacing_x = icon_size.width + self->column_spacing;
+  self->spacing_y = icon_size.height + self->row_spacing;
+
+  self->offset_x = (self->view_width - columns * icon_size.width -
+                    (columns - 1) * self->column_spacing) / 2;
+  self->offset_y = (self->view_height - rows * icon_size.height -
+                    (rows - 1) * self->row_spacing) / 2;
+
+  if (self->grid_points)
+    gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static gboolean
+recalculate_grid_size_cb (gpointer user_data)
+{
+  GfMonitorView *self;
+
+  self = GF_MONITOR_VIEW (user_data);
+
+  calculate_grid_size (self);
+  self->grid_size_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+recalculate_grid_size (GfMonitorView *self)
+{
+  if (self->grid_size_id != 0)
+    return;
+
+  self->grid_size_id = g_idle_add (recalculate_grid_size_cb, self);
+
+  g_source_set_name_by_id (self->grid_size_id,
+                           "[gnome-flashback] recalculate_grid_size_cb");
+}
+
 static void
 set_icon_size (GfMonitorView *self,
                guint          icon_size)
@@ -60,7 +245,7 @@ set_icon_size (GfMonitorView *self,
 
   self->icon_size = icon_size;
 
-  gtk_widget_queue_resize (GTK_WIDGET (self));
+  recalculate_grid_size (self);
 }
 
 static void
@@ -72,7 +257,7 @@ set_extra_text_width (GfMonitorView *self,
 
   self->extra_text_width = extra_text_width;
 
-  gtk_widget_queue_resize (GTK_WIDGET (self));
+  recalculate_grid_size (self);
 }
 
 static void
@@ -84,7 +269,7 @@ set_column_spacing (GfMonitorView *self,
 
   self->column_spacing = column_spacing;
 
-  gtk_widget_queue_resize (GTK_WIDGET (self));
+  recalculate_grid_size (self);
 }
 
 static void
@@ -96,7 +281,7 @@ set_row_spacing (GfMonitorView *self,
 
   self->row_spacing = row_spacing;
 
-  gtk_widget_queue_resize (GTK_WIDGET (self));
+  recalculate_grid_size (self);
 }
 
 static void
@@ -108,10 +293,10 @@ workarea_cb (GdkMonitor    *monitor,
 
   gdk_monitor_get_workarea (monitor, &workarea);
 
-  self->width = workarea.width;
-  self->height = workarea.height;
+  self->view_width = workarea.width;
+  self->view_height = workarea.height;
 
-  gtk_widget_queue_resize (GTK_WIDGET (self));
+  recalculate_grid_size (self);
 }
 
 static void
@@ -142,6 +327,66 @@ gf_monitor_view_dispose (GObject *object)
   G_OBJECT_CLASS (gf_monitor_view_parent_class)->dispose (object);
 }
 
+static void
+gf_monitor_view_finalize (GObject *object)
+{
+  GfMonitorView *self;
+
+  self = GF_MONITOR_VIEW (object);
+
+  g_clear_pointer (&self->dummy_icon, gtk_widget_destroy);
+
+  if (self->grid_size_id != 0)
+    {
+      g_source_remove (self->grid_size_id);
+      self->grid_size_id = 0;
+    }
+
+  G_OBJECT_CLASS (gf_monitor_view_parent_class)->finalize (object);
+}
+
+static gboolean
+gf_monitor_view_draw (GtkWidget *widget,
+                      cairo_t   *cr)
+{
+  GfMonitorView *self;
+
+  self = GF_MONITOR_VIEW (widget);
+
+  if (self->grid_points)
+    {
+      int c;
+
+      cairo_save (cr);
+      cairo_set_line_width (cr, 1);
+
+      for (c = 0; c < self->columns; c++)
+        {
+          int r;
+
+          for (r = 0; r < self->rows; r++)
+            {
+              int x;
+              int y;
+
+              x = self->offset_x + c * self->spacing_x + self->spacing_x / 2;
+              y = self->offset_y + r * self->spacing_y + self->spacing_y / 2;
+
+              cairo_move_to (cr, x - 3, y);
+              cairo_line_to (cr, x + 3, y);
+
+              cairo_move_to (cr, x, y - 3);
+              cairo_line_to (cr, x, y + 3);
+            }
+        }
+
+      cairo_stroke (cr);
+      cairo_restore (cr);
+    }
+
+  return GTK_WIDGET_CLASS (gf_monitor_view_parent_class)->draw (widget, cr);
+}
+
 static void
 gf_monitor_view_get_property (GObject    *object,
                               guint       property_id,
@@ -154,6 +399,10 @@ gf_monitor_view_get_property (GObject    *object,
 
   switch (property_id)
     {
+      case PROP_GRID_POINTS:
+        g_value_set_boolean (value, self->grid_points);
+        break;
+
       case PROP_ICON_SIZE:
         g_value_set_uint (value, self->icon_size);
         break;
@@ -185,6 +434,11 @@ gf_monitor_view_set_property (GObject      *object,
         self->monitor = g_value_dup_object (value);
         break;
 
+      case PROP_GRID_POINTS:
+        self->grid_points = g_value_get_boolean (value);
+        gtk_widget_queue_draw (GTK_WIDGET (self));
+        break;
+
       case PROP_ICON_SIZE:
         set_icon_size (self, g_value_get_uint (value));
         break;
@@ -216,8 +470,8 @@ gf_monitor_view_get_preferred_height (GtkWidget *widget,
 
   self = GF_MONITOR_VIEW (widget);
 
-  *minimum_height = self->height;
-  *natural_height = self->height;
+  *minimum_height = self->view_height;
+  *natural_height = self->view_height;
 }
 
 static void
@@ -229,8 +483,8 @@ gf_monitor_view_get_preferred_width (GtkWidget *widget,
 
   self = GF_MONITOR_VIEW (widget);
 
-  *minimum_width = self->width;
-  *natural_width = self->width;
+  *minimum_width = self->view_width;
+  *natural_width = self->view_width;
 }
 
 static GtkSizeRequestMode
@@ -251,6 +505,14 @@ install_properties (GObjectClass *object_class)
                          G_PARAM_WRITABLE |
                          G_PARAM_STATIC_STRINGS);
 
+  view_properties[PROP_GRID_POINTS] =
+    g_param_spec_boolean ("grid-points",
+                          "grid-points",
+                          "grid-points",
+                          FALSE,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS);
+
   view_properties[PROP_ICON_SIZE] =
     g_param_spec_uint ("icon-size",
                        "icon-size",
@@ -301,9 +563,11 @@ gf_monitor_view_class_init (GfMonitorViewClass *self_class)
 
   object_class->constructed = gf_monitor_view_constructed;
   object_class->dispose = gf_monitor_view_dispose;
+  object_class->finalize = gf_monitor_view_finalize;
   object_class->get_property = gf_monitor_view_get_property;
   object_class->set_property = gf_monitor_view_set_property;
 
+  widget_class->draw = gf_monitor_view_draw;
   widget_class->get_preferred_height = gf_monitor_view_get_preferred_height;
   widget_class->get_preferred_width = gf_monitor_view_get_preferred_width;
   widget_class->get_request_mode = gf_monitor_view_get_request_mode;


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