[gnome-panel] clock: redo clock button



commit 386032ce65be9095de8c9186b965c066672ed7a2
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat May 1 17:32:51 2021 +0300

    clock: redo clock button
    
    https://gitlab.gnome.org/GNOME/gnome-panel/-/issues/31

 modules/clock/Makefile.am    |   2 +
 modules/clock/clock-applet.c | 288 +++++++--------------------------
 modules/clock/clock-button.c | 377 +++++++++++++++++++++++++++++++++++++++++++
 modules/clock/clock-button.h |  50 ++++++
 4 files changed, 489 insertions(+), 228 deletions(-)
---
diff --git a/modules/clock/Makefile.am b/modules/clock/Makefile.am
index 78aa036ef..351f9b439 100644
--- a/modules/clock/Makefile.am
+++ b/modules/clock/Makefile.am
@@ -20,6 +20,8 @@ org_gnome_gnome_panel_clock_la_SOURCES = \
        calendar-window.h \
        clock-applet.c \
        clock-applet.h \
+       clock-button.c \
+       clock-button.h \
        clock-face.c \
        clock-face.h \
        clock-location.c \
diff --git a/modules/clock/clock-applet.c b/modules/clock/clock-applet.c
index 340fc948f..bfa8d596c 100644
--- a/modules/clock/clock-applet.c
+++ b/modules/clock/clock-applet.c
@@ -48,11 +48,10 @@
 #include <gdk/gdkx.h>
 
 #include <libgnome-desktop/gnome-wall-clock.h>
-
-#include <libgnome-panel/gp-utils.h>
 #include <libgweather/gweather.h>
 
 #include "clock-applet.h"
+#include "clock-button.h"
 
 #include "calendar-window.h"
 #include "clock-location.h"
@@ -74,14 +73,6 @@ struct _ClockApplet
        /* widgets */
         GtkWidget *panel_button;       /* main toggle button for the whole clock */
 
-       GtkWidget *main_obox;           /* orientable box inside panel_button */
-        GtkWidget *weather_obox;        /* orientable box for the weather widgets */
-
-       GtkWidget *clockw;              /* main label for the date/time display */
-
-        GtkWidget *panel_weather_icon;
-        GtkWidget *panel_temperature_label;
-
        GtkWidget *calendar_popup;
 
         GtkWidget *clock_vbox;
@@ -119,7 +110,6 @@ struct _ClockApplet
 
        /* runtime data */
         GnomeWallClock    *wall_clock;
-       GtkAllocation      old_allocation;
 };
 
 G_DEFINE_TYPE (ClockApplet, clock_applet, GP_TYPE_APPLET)
@@ -127,8 +117,6 @@ G_DEFINE_TYPE (ClockApplet, clock_applet, GP_TYPE_APPLET)
 static void display_properties_dialog (ClockApplet       *applet,
                                        gboolean           start_in_locations_page);
 
-static void update_orient             (ClockApplet       *applet);
-
 static inline GtkWidget *
 _clock_get_widget (ClockApplet *cd,
                    const gchar *name)
@@ -136,35 +124,6 @@ _clock_get_widget (ClockApplet *cd,
        return GTK_WIDGET (gtk_builder_get_object (cd->builder, name));
 }
 
-static int
-calculate_minimum_width (GtkWidget   *widget,
-                        const gchar *text)
-{
-       PangoContext *pango_context;
-       PangoLayout  *layout;
-       int           width, height;
-       GtkStyleContext *style_context;
-       GtkStateFlags    state;
-       GtkBorder        padding;
-
-       pango_context = gtk_widget_get_pango_context (widget);
-
-       layout = pango_layout_new (pango_context);
-       pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
-       pango_layout_set_text (layout, text, -1);
-       pango_layout_get_pixel_size (layout, &width, &height);
-       g_object_unref (G_OBJECT (layout));
-       layout = NULL;
-
-       state = gtk_widget_get_state_flags (widget);
-       style_context = gtk_widget_get_style_context (widget);
-       gtk_style_context_get_padding (style_context, state, &padding);
-
-       width += padding.left + padding.right;
-
-       return width;
-}
-
 /* sets accessible name and description for the widget */
 static void
 set_atk_name_description (GtkWidget  *widget,
@@ -242,10 +201,7 @@ update_clock (GnomeWallClock *wall_clock, GParamSpec *pspec, ClockApplet *cd)
         const char *clock;
 
         clock = gnome_wall_clock_get_clock (cd->wall_clock);
-        gtk_label_set_text (GTK_LABEL (cd->clockw), clock);
-
-        update_orient (cd);
-        gtk_widget_queue_resize (cd->panel_button);
+        clock_button_set_clock (CLOCK_BUTTON (cd->panel_button), clock);
 
         update_tooltip (cd);
         update_location_tiles (cd);
@@ -686,57 +642,6 @@ toggle_calendar (GtkWidget *button,
        update_calendar_popup (cd);
 }
 
-static gboolean
-do_not_eat_button_press (GtkWidget      *widget,
-                         GdkEventButton *event)
-{
-       if (event->button != 1)
-               g_signal_stop_emission_by_name (widget, "button_press_event");
-
-       return FALSE;
-}
-
-static void
-clock_update_text_gravity (GtkWidget *label)
-{
-       PangoLayout  *layout;
-       PangoContext *context;
-
-       layout = gtk_label_get_layout (GTK_LABEL (label));
-       context = pango_layout_get_context (layout);
-       pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO);
-}
-
-static GtkWidget *
-create_main_clock_button (void)
-{
-        GtkWidget *button;
-
-        button = gtk_toggle_button_new ();
-       gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
-
-        gtk_widget_set_name (button, "clock-applet-button");
-
-        return button;
-}
-
-static GtkWidget *
-create_main_clock_label (ClockApplet *cd)
-{
-        GtkWidget *label;
-
-        label = gtk_label_new (NULL);
-       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
-       clock_update_text_gravity (label);
-       g_signal_connect (label, "screen-changed",
-                         G_CALLBACK (clock_update_text_gravity),
-                         NULL);
-
-        gp_add_text_color_class (label);
-
-        return label;
-}
-
 static gboolean
 weather_tooltip (GtkWidget   *widget,
                  gint         x,
@@ -768,69 +673,52 @@ weather_tooltip (GtkWidget   *widget,
 }
 
 static void
-update_panel_weather (ClockApplet *cd)
+panel_icon_size_cb (GpApplet    *applet,
+                    GParamSpec  *pspec,
+                    ClockApplet *self)
 {
-        gboolean show_weather, show_temperature;
-
-        show_weather = g_settings_get_boolean (cd->applet_settings, "show-weather");
-        show_temperature = g_settings_get_boolean (cd->applet_settings, "show-temperature");
-
-        if ((show_weather || show_temperature) &&
-            g_list_length (cd->locations) > 0)
-                gtk_widget_show (cd->weather_obox);
-        else
-                gtk_widget_hide (cd->weather_obox);
-
-        gtk_widget_queue_resize (GTK_WIDGET (cd));
+        clock_button_set_icon_size (CLOCK_BUTTON (self->panel_button),
+                                    gp_applet_get_panel_icon_size (applet));
 }
 
 static void
 create_clock_widget (ClockApplet *cd)
 {
-        GtkOrientation orientation;
-
-        orientation = gp_applet_get_orientation (GP_APPLET (cd));
+        GtkWidget *weather_box;
 
         g_signal_connect (cd->wall_clock, "notify::clock",
                           G_CALLBACK (update_clock), cd);
 
         /* Main toggle button */
-        cd->panel_button = create_main_clock_button ();
-       g_signal_connect (cd->panel_button, "button_press_event",
-                         G_CALLBACK (do_not_eat_button_press), NULL);
-       g_signal_connect (cd->panel_button, "toggled",
-                         G_CALLBACK (toggle_calendar), cd);
-        gtk_widget_show (cd->panel_button);
-
-        /* Main orientable box */
-        cd->main_obox = gtk_box_new (orientation, 12);
-        gtk_container_add (GTK_CONTAINER (cd->panel_button), cd->main_obox);
-        gtk_widget_show (cd->main_obox);
+        cd->panel_button = clock_button_new ();
+
+        clock_button_set_orientation (CLOCK_BUTTON (cd->panel_button),
+                                      gp_applet_get_orientation (GP_APPLET (cd)));
+
+        clock_button_set_position (CLOCK_BUTTON (cd->panel_button),
+                                   gp_applet_get_position (GP_APPLET (cd)));
+
+        clock_button_set_icon_size (CLOCK_BUTTON (cd->panel_button),
+                                    gp_applet_get_panel_icon_size (GP_APPLET (cd)));
+
+        g_signal_connect (GP_APPLET (cd),
+                          "notify::panel-icon-size",
+                          G_CALLBACK (panel_icon_size_cb),
+                          cd);
+
+        g_signal_connect (cd->panel_button,
+                          "toggled",
+                          G_CALLBACK (toggle_calendar),
+                          cd);
 
         /* Weather orientable box */
-        cd->weather_obox = gtk_box_new (orientation, 2);
-        gtk_box_pack_start (GTK_BOX (cd->main_obox), cd->weather_obox, FALSE, FALSE, 0);
-        gtk_widget_set_has_tooltip (cd->weather_obox, TRUE);
-        g_signal_connect (cd->weather_obox, "query-tooltip",
-                          G_CALLBACK (weather_tooltip), cd);
-
-        /* Weather widgets */
-        cd->panel_weather_icon = gtk_image_new ();
-        gtk_box_pack_start (GTK_BOX (cd->weather_obox), cd->panel_weather_icon, FALSE, FALSE, 0);
-        g_settings_bind (cd->applet_settings, "show-weather", cd->panel_weather_icon, "visible",
-                         G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY);
-
-        cd->panel_temperature_label = gtk_label_new (NULL);
-        gtk_box_pack_start (GTK_BOX (cd->weather_obox), cd->panel_temperature_label, FALSE, FALSE, 0);
-        g_settings_bind (cd->applet_settings, "show-temperature", cd->panel_temperature_label, "visible",
-                         G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY);
-
-        gp_add_text_color_class (cd->panel_temperature_label);
-
-        /* Main label for time display */
-       cd->clockw = create_main_clock_label (cd);
-        gtk_box_pack_start (GTK_BOX (cd->main_obox), cd->clockw, FALSE, FALSE, 0);
-       gtk_widget_show (cd->clockw);
+        weather_box = clock_button_get_weather_box (CLOCK_BUTTON (cd->panel_button));
+        gtk_widget_set_has_tooltip (weather_box, TRUE);
+
+        g_signal_connect (weather_box,
+                          "query-tooltip",
+                          G_CALLBACK (weather_tooltip),
+                          cd);
 
         /* Done! */
 
@@ -838,57 +726,12 @@ create_clock_widget (ClockApplet *cd)
 
        gtk_container_add (GTK_CONTAINER (cd), cd->panel_button);
        gtk_container_set_border_width (GTK_CONTAINER (cd), 0);
-
-       update_panel_weather (cd);
+       gtk_widget_show (cd->panel_button);
 
        /* Refresh the clock so that it paints its first state */
         update_clock (NULL, NULL, cd);
 }
 
-static void
-update_orient (ClockApplet *cd)
-{
-       const gchar   *text;
-       int            min_width;
-       GtkAllocation  allocation;
-       gdouble        new_angle;
-       gdouble        angle;
-
-       text = gtk_label_get_text (GTK_LABEL (cd->clockw));
-       min_width = calculate_minimum_width (cd->panel_button, text);
-       gtk_widget_get_allocation (cd->panel_button, &allocation);
-
-       if (gp_applet_get_position (GP_APPLET (cd)) == GTK_POS_RIGHT &&
-           min_width > allocation.width)
-               new_angle = 270;
-       else if (gp_applet_get_position (GP_APPLET (cd)) == GTK_POS_LEFT &&
-                min_width > allocation.width)
-               new_angle = 90;
-       else
-               new_angle = 0;
-
-       angle = gtk_label_get_angle (GTK_LABEL (cd->clockw));
-       if (angle != new_angle) {
-               gtk_label_set_angle (GTK_LABEL (cd->clockw), new_angle);
-                gtk_label_set_angle (GTK_LABEL (cd->panel_temperature_label), new_angle);
-       }
-}
-
-/* this is when the panel size changes */
-static void
-panel_button_change_pixel_size (GtkWidget     *widget,
-                                GtkAllocation *allocation,
-                                ClockApplet   *cd)
-{
-       if (cd->old_allocation.width  == allocation->width &&
-           cd->old_allocation.height == allocation->height)
-               return;
-
-       cd->old_allocation = *allocation;
-
-       update_clock (NULL, NULL, cd);
-}
-
 static void
 verb_display_properties_dialog (GSimpleAction *action,
                                 GVariant      *parameter,
@@ -1012,8 +855,6 @@ location_weather_updated_cb (ClockLocation  *location,
        ClockApplet *cd = data;
        const gchar *icon_name;
        const gchar *temp;
-       GtkIconTheme *theme;
-       GdkPixbuf *pixbuf;
 
        if (!info || !gweather_info_is_valid (info))
                return;
@@ -1021,16 +862,22 @@ location_weather_updated_cb (ClockLocation  *location,
        if (!clock_location_is_current (location))
                return;
 
-       icon_name = gweather_info_get_icon_name (info);
-       /* FIXME: mmh, screen please? Also, don't hardcode to 16 */
-       theme = gtk_icon_theme_get_default ();
-       pixbuf = gtk_icon_theme_load_icon (theme, icon_name, 16,
-                                          GTK_ICON_LOOKUP_GENERIC_FALLBACK, NULL);
+       icon_name = NULL;
+       if (g_settings_get_boolean (cd->applet_settings, "show-weather")) {
+               if (gp_applet_get_prefer_symbolic_icons (GP_APPLET (cd)))
+                       icon_name = gweather_info_get_symbolic_icon_name (info);
+               else
+                       icon_name = gweather_info_get_icon_name (info);
+       }
 
-       temp = gweather_info_get_temp_summary (info);
+       temp = NULL;
+       if (g_settings_get_boolean (cd->applet_settings, "show-temperature")) {
+               temp = gweather_info_get_temp_summary (info);
+       }
 
-       gtk_image_set_from_pixbuf (GTK_IMAGE (cd->panel_weather_icon), pixbuf);
-       gtk_label_set_text (GTK_LABEL (cd->panel_temperature_label), temp);
+       clock_button_set_weather (CLOCK_BUTTON (cd->panel_button),
+                                 icon_name,
+                                 temp);
 }
 
 static void
@@ -1058,17 +905,11 @@ locations_changed (GSettings   *settings,
        glong id;
 
        if (!cd->locations) {
-               if (cd->weather_obox)
-                       gtk_widget_hide (cd->weather_obox);
-               if (cd->panel_weather_icon)
-                       gtk_image_set_from_pixbuf (GTK_IMAGE (cd->panel_weather_icon),
-                                                  NULL);
-               if (cd->panel_temperature_label)
-                       gtk_label_set_text (GTK_LABEL (cd->panel_temperature_label),
-                                           "");
-       } else {
-               if (cd->weather_obox)
-                       gtk_widget_show (cd->weather_obox);
+               if (cd->panel_button) {
+                       clock_button_set_weather (CLOCK_BUTTON (cd->panel_button),
+                                                 NULL,
+                                                 NULL);
+               }
        }
 
        for (l = cd->locations; l; l = l->next) {
@@ -1160,11 +1001,6 @@ fill_clock_applet (ClockApplet *cd)
 
        create_clock_widget (cd);
 
-       g_signal_connect (G_OBJECT (cd->panel_button),
-                         "size_allocate",
-                         G_CALLBACK (panel_button_change_pixel_size),
-                         cd);
-
        gp_applet_setup_menu_from_resource (applet,
                                            CLOCK_RESOURCE_PATH "clock-menu.ui",
                                            clock_menu_actions);
@@ -2002,18 +1838,14 @@ clock_applet_placement_changed (GpApplet        *applet,
                                 GtkOrientation   orientation,
                                 GtkPositionType  position)
 {
-        ClockApplet *cd;
-
-        cd = CLOCK_APPLET (applet);
+        ClockApplet *self;
 
-        if (cd->main_obox == NULL)
-                return;
+        self = CLOCK_APPLET (applet);
 
-        gtk_orientable_set_orientation (GTK_ORIENTABLE (cd->main_obox), orientation);
-        gtk_orientable_set_orientation (GTK_ORIENTABLE (cd->weather_obox), orientation);
+        clock_button_set_orientation (CLOCK_BUTTON (self->panel_button), orientation);
+        clock_button_set_position (CLOCK_BUTTON (self->panel_button), position);
 
-        update_clock (NULL, NULL, cd);
-        update_calendar_popup (cd);
+        update_calendar_popup (self);
 }
 
 static void
diff --git a/modules/clock/clock-button.c b/modules/clock/clock-button.c
new file mode 100644
index 000000000..28668465b
--- /dev/null
+++ b/modules/clock/clock-button.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2021 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "clock-button.h"
+
+#include <libgnome-panel/gp-utils.h>
+
+struct _ClockButton
+{
+  GtkToggleButton  parent;
+
+  GtkOrientation   orientation;
+  GtkPositionType  position;
+  guint            icon_size;
+
+  double           angle;
+
+  GtkWidget       *main_box;
+
+  GtkWidget       *clock_label;
+
+  GtkWidget       *weather_box;
+  GtkWidget       *weather_image;
+  GtkWidget       *temperature_label;
+
+  char            *weather_icon;
+
+  guint            update_angle_id;
+};
+
+G_DEFINE_TYPE (ClockButton, clock_button, GTK_TYPE_TOGGLE_BUTTON)
+
+static void
+update_weather_visibility (ClockButton *self)
+{
+  gboolean has_icon;
+  gboolean has_temperature;
+
+  has_icon = gtk_widget_get_visible (self->weather_image);
+  has_temperature = gtk_widget_get_visible (self->temperature_label);
+
+  gtk_widget_set_visible (self->weather_box, has_icon || has_temperature);
+}
+
+static void
+update_weather_icon (ClockButton *self)
+{
+  if (self->weather_icon == NULL || *self->weather_icon == '\0')
+    {
+      gtk_image_clear (GTK_IMAGE (self->weather_image));
+      gtk_widget_hide (self->weather_image);
+    }
+  else
+    {
+      gtk_image_set_from_icon_name (GTK_IMAGE (self->weather_image),
+                                    self->weather_icon,
+                                    GTK_ICON_SIZE_MENU);
+
+      gtk_image_set_pixel_size (GTK_IMAGE (self->weather_image),
+                                self->icon_size);
+
+      gtk_widget_show (self->weather_image);
+    }
+
+  update_weather_visibility (self);
+}
+
+static void
+set_weather_text (ClockButton *self,
+                  const char  *temperature)
+{
+  if (temperature == NULL)
+    temperature = "";
+
+  gtk_label_set_text (GTK_LABEL (self->temperature_label), temperature);
+  gtk_widget_set_visible (self->temperature_label, *temperature != '\0');
+
+  update_weather_visibility (self);
+}
+
+static void
+set_text_gravity_to_auto (GtkWidget *widget)
+{
+  PangoLayout *layout;
+  PangoContext *context;
+
+  layout = gtk_label_get_layout (GTK_LABEL (widget));
+  context = pango_layout_get_context (layout);
+
+  pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO);
+}
+
+static int
+get_clock_width (ClockButton *self)
+{
+  GtkWidget *label;
+  int width;
+
+  label = gtk_label_new (gtk_label_get_text (GTK_LABEL (self->clock_label)));
+  set_text_gravity_to_auto (label);
+  gp_add_text_color_class (label);
+  gtk_widget_show (label);
+
+  gtk_widget_get_preferred_width (label, &width, NULL);
+
+  g_object_ref_sink (label);
+  gtk_widget_destroy (label);
+
+  return width;
+}
+
+static void
+update_angle (ClockButton *self)
+{
+  double new_angle;
+
+  new_angle = 0.0;
+
+  if (self->orientation == GTK_ORIENTATION_VERTICAL)
+    {
+      GtkAllocation allocation;
+      GtkStyleContext *context;
+      GtkStateFlags state;
+      GtkBorder padding;
+
+      gtk_widget_get_allocation (GTK_WIDGET (self), &allocation);
+
+      context = gtk_widget_get_style_context (GTK_WIDGET (self));
+      state = gtk_style_context_get_state (context);
+
+      gtk_style_context_get_padding (context, state, &padding);
+
+      allocation.width -= padding.left + padding.right;
+
+      if (allocation.width < get_clock_width (self))
+        {
+          if (self->position == GTK_POS_RIGHT)
+            new_angle = 270.0;
+          else if (self->position == GTK_POS_LEFT)
+            new_angle = 90.0;
+        }
+    }
+
+  if (self->angle == new_angle)
+    return;
+
+  gtk_label_set_angle (GTK_LABEL (self->clock_label), new_angle);
+  gtk_label_set_angle (GTK_LABEL (self->temperature_label), new_angle);
+
+  self->angle = new_angle;
+}
+
+static gboolean
+update_angle_cb (gpointer user_data)
+{
+  ClockButton *self;
+
+  self = CLOCK_BUTTON (user_data);
+
+  update_angle (self);
+  self->update_angle_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+clock_button_dispose (GObject *object)
+{
+  ClockButton *self;
+
+  self = CLOCK_BUTTON (object);
+
+  if (self->update_angle_id != 0)
+    {
+      g_source_remove (self->update_angle_id);
+      self->update_angle_id = 0;
+    }
+
+  G_OBJECT_CLASS (clock_button_parent_class)->dispose (object);
+}
+
+static void
+clock_button_finalize (GObject *object)
+{
+  ClockButton *self;
+
+  self = CLOCK_BUTTON (object);
+
+  g_clear_pointer (&self->weather_icon, g_free);
+
+  G_OBJECT_CLASS (clock_button_parent_class)->finalize (object);
+}
+
+static void
+clock_button_size_allocate (GtkWidget     *widget,
+                            GtkAllocation *allocation)
+{
+  ClockButton *self;
+  GtkAllocation old_allocation;
+
+  self = CLOCK_BUTTON (widget);
+
+  gtk_widget_get_allocation (widget, &old_allocation);
+  GTK_WIDGET_CLASS (clock_button_parent_class)->size_allocate (widget,
+                                                               allocation);
+
+  if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
+    return;
+
+  if (old_allocation.width != allocation->width &&
+      self->update_angle_id == 0)
+    {
+      self->update_angle_id = g_idle_add (update_angle_cb, self);
+      g_source_set_name_by_id (self->update_angle_id,
+                               "[clock] update_angle_cb");
+    }
+}
+
+static void
+clock_button_class_init (ClockButtonClass *self_class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = G_OBJECT_CLASS (self_class);
+  widget_class = GTK_WIDGET_CLASS (self_class);
+
+  object_class->dispose = clock_button_dispose;
+  object_class->finalize = clock_button_finalize;
+
+  widget_class->size_allocate = clock_button_size_allocate;
+}
+
+static void
+clock_button_init (ClockButton *self)
+{
+  gtk_widget_set_name (GTK_WIDGET (self), "clock-applet-button");
+  gtk_button_set_relief (GTK_BUTTON (self), GTK_RELIEF_NONE);
+
+  self->orientation = GTK_ORIENTATION_HORIZONTAL;
+  self->position = GTK_POS_TOP;
+  self->icon_size = 16;
+
+  self->angle = 0.0;
+
+  self->main_box = gtk_box_new (self->orientation, 12);
+  gtk_container_add (GTK_CONTAINER (self), self->main_box);
+
+  self->weather_box = gtk_box_new (self->orientation, 6);
+  gtk_box_pack_start (GTK_BOX (self->main_box),
+                      self->weather_box,
+                      TRUE,
+                      TRUE,
+                      0);
+
+  self->clock_label = gtk_label_new (NULL);
+  gtk_box_pack_start (GTK_BOX (self->main_box),
+                      self->clock_label,
+                      TRUE,
+                      TRUE,
+                      0);
+
+  self->weather_image = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (self->weather_box),
+                      self->weather_image,
+                      FALSE,
+                      FALSE,
+                      0);
+
+  self->temperature_label = gtk_label_new (NULL);
+  gtk_box_pack_start (GTK_BOX (self->weather_box),
+                      self->temperature_label,
+                      FALSE,
+                      FALSE,
+                      0);
+
+  set_text_gravity_to_auto (self->clock_label);
+  set_text_gravity_to_auto (self->temperature_label);
+
+  gp_add_text_color_class (self->clock_label);
+  gp_add_text_color_class (self->weather_image);
+  gp_add_text_color_class (self->temperature_label);
+
+  gtk_widget_show (self->main_box);
+  gtk_widget_show (self->clock_label);
+}
+
+GtkWidget *
+clock_button_new (void)
+{
+  return g_object_new (CLOCK_TYPE_BUTTON, NULL);
+}
+
+GtkWidget *
+clock_button_get_weather_box (ClockButton *self)
+{
+  return self->weather_box;
+}
+
+void
+clock_button_set_orientation (ClockButton    *self,
+                              GtkOrientation  orientation)
+{
+  if (self->orientation == orientation)
+    return;
+
+  self->orientation = orientation;
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (self->main_box),
+                                  self->orientation);
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (self->weather_box),
+                                  self->orientation);
+}
+
+void
+clock_button_set_position (ClockButton     *self,
+                           GtkPositionType  position)
+{
+  if (self->position == position)
+    return;
+
+  self->position = position;
+
+  update_angle (self);
+}
+
+void
+clock_button_set_icon_size (ClockButton *self,
+                            guint        icon_size)
+{
+  if (self->icon_size == icon_size)
+    return;
+
+  self->icon_size = icon_size;
+
+  update_weather_icon (self);
+}
+
+void
+clock_button_set_clock (ClockButton *self,
+                        const char  *clock)
+{
+  gtk_label_set_text (GTK_LABEL (self->clock_label), clock);
+  update_angle (self);
+}
+
+void
+clock_button_set_weather (ClockButton *self,
+                          const char  *icon_name,
+                          const char  *temperature)
+{
+  if (g_strcmp0 (self->weather_icon, icon_name) != 0)
+    {
+      g_free (self->weather_icon);
+      self->weather_icon = g_strdup (icon_name);
+
+      update_weather_icon (self);
+    }
+
+  set_weather_text (self, temperature);
+}
diff --git a/modules/clock/clock-button.h b/modules/clock/clock-button.h
new file mode 100644
index 000000000..2042ca5f3
--- /dev/null
+++ b/modules/clock/clock-button.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CLOCK_BUTTON_H
+#define CLOCK_BUTTON_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CLOCK_TYPE_BUTTON (clock_button_get_type ())
+G_DECLARE_FINAL_TYPE (ClockButton, clock_button, CLOCK, BUTTON, GtkToggleButton)
+
+GtkWidget *clock_button_new             (void);
+
+GtkWidget *clock_button_get_weather_box (ClockButton     *self);
+
+void       clock_button_set_orientation (ClockButton     *self,
+                                         GtkOrientation   orientation);
+
+void       clock_button_set_position    (ClockButton     *self,
+                                         GtkPositionType  position);
+
+void       clock_button_set_icon_size   (ClockButton     *self,
+                                         guint            icon_size);
+
+void       clock_button_set_clock       (ClockButton     *self,
+                                         const char      *clock);
+
+void       clock_button_set_weather     (ClockButton     *self,
+                                         const char      *icon_name,
+                                         const char      *temperature);
+
+G_END_DECLS
+
+#endif


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