[recipes] Add a compound timer widget



commit 3d338019916a262a55328ad3e4e6768b708adab2
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Feb 3 07:15:29 2017 +0100

    Add a compound timer widget
    
    This is closer to the mockups, although not quite the same.

 src/Makefile.am              |    2 +
 src/gr-time-widget.c         |  234 ++++++++++++++++++++++++++++++++++++++++++
 src/gr-time-widget.h         |   33 ++++++
 src/gr-time-widget.ui        |  102 ++++++++++++++++++
 src/main.c                   |    2 +
 src/recipes-ui.gresource.xml |    1 +
 src/recipes.css              |   48 +++++++++
 7 files changed, 422 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 1714099..feaa315 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -104,6 +104,8 @@ recipes_SOURCES = \
        gr-shopping-page.c      \
        gr-timer.h              \
        gr-timer.c              \
+       gr-time-widget.h        \
+       gr-time-widget.c        \
        gr-timer-widget.h       \
        gr-timer-widget.c       \
        gr-toggle-button.h      \
diff --git a/src/gr-time-widget.c b/src/gr-time-widget.c
new file mode 100644
index 0000000..bfe02ca
--- /dev/null
+++ b/src/gr-time-widget.c
@@ -0,0 +1,234 @@
+/* gr-time-widget.c:
+ *
+ * Copyright (C) 2017 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * 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 3 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 <math.h>
+#include "gr-timer.h"
+#include "gr-time-widget.h"
+#include "gr-timer-widget.h"
+
+struct _GrTimeWidget
+{
+        GtkOverlay parent_instance;
+
+        int size;
+        GrTimer *timer;
+        gulong handler;
+
+        GrTimerWidget *timer_widget;
+        GtkWidget *time_remaining;
+        GtkWidget *timer_button_stack;
+        GtkWidget *pause_stack;
+};
+
+G_DEFINE_TYPE (GrTimeWidget, gr_time_widget, GTK_TYPE_OVERLAY)
+
+enum {
+        PROP_0,
+        PROP_TIMER,
+        PROP_SIZE,
+        N_PROPS
+};
+
+GrTimeWidget *
+gr_time_widget_new (void)
+{
+        return g_object_new (GR_TYPE_TIME_WIDGET, NULL);
+}
+
+static void
+remaining_changed (GrTimeWidget *self)
+{
+        guint64 remaining;
+        int seconds;
+        int minutes;
+        int hours;
+        g_autofree char *str = NULL;
+
+        remaining = gr_timer_get_remaining (self->timer);
+        seconds = (int)(remaining / G_TIME_SPAN_SECOND);
+        minutes = seconds / 60;
+        seconds = seconds - 60 * minutes;
+        hours = minutes / 60;
+        minutes = minutes - 60 * hours;
+
+        str = g_strdup_printf ("%02d∶%02d∶%02d", hours, minutes, seconds);
+        gtk_label_set_label (GTK_LABEL (self->time_remaining), str);
+        gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+set_timer (GrTimeWidget *self,
+           GrTimer      *timer)
+{
+        GrTimer *old = self->timer;
+
+        if (g_set_object (&self->timer, timer)) {
+                if (self->handler) {
+                        g_signal_handler_disconnect (old, self->handler);
+                        self->handler = 0;
+                }
+                if (timer) {
+                        self->handler = g_signal_connect_swapped (timer, "notify::remaining", G_CALLBACK 
(remaining_changed), self);
+                        remaining_changed (self);
+                }
+                g_object_set (self->timer_widget, "timer", timer, NULL);
+                g_object_notify (G_OBJECT (self), "timer");
+        }
+}
+
+static void
+set_size (GrTimeWidget *self,
+          int           size)
+{
+        self->size = size;
+
+        g_object_set (self->timer_widget, "size", size, NULL);
+        g_object_notify (G_OBJECT (self), "size");
+}
+
+static void
+timer_start (GrTimeWidget *self)
+{
+        gr_timer_start (self->timer);
+        gtk_stack_set_visible_child_name (GTK_STACK (self->timer_button_stack), "active");
+        gtk_stack_set_visible_child_name (GTK_STACK (self->pause_stack), "pause");
+}
+
+static void
+timer_pause (GrTimeWidget *self)
+{
+        if (gr_timer_get_active (self->timer)) {
+                gr_timer_stop (self->timer);
+                gtk_stack_set_visible_child_name (GTK_STACK (self->pause_stack), "resume");
+        }
+        else {
+                gr_timer_continue (self->timer);
+                gtk_stack_set_visible_child_name (GTK_STACK (self->pause_stack), "pause");
+        }
+}
+
+static void
+timer_reset (GrTimeWidget *self)
+{
+        gr_timer_reset (self->timer);
+        gtk_stack_set_visible_child_name (GTK_STACK (self->timer_button_stack), "start");
+}
+
+static void
+gr_time_widget_finalize (GObject *object)
+{
+        GrTimeWidget *self = GR_TIME_WIDGET (object);
+
+        if (self->handler)
+                g_signal_handler_disconnect (self->timer, self->handler);
+        g_clear_object (&self->timer);
+
+        G_OBJECT_CLASS (gr_time_widget_parent_class)->finalize (object);
+}
+
+static void
+gr_time_widget_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+        GrTimeWidget *self = GR_TIME_WIDGET (object);
+
+        switch (prop_id)
+          {
+          case PROP_TIMER:
+                  g_value_set_object (value, self->timer);
+                  break;
+
+          case PROP_SIZE:
+                  g_value_set_int (value, self->size);
+                  break;
+
+          default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+          }
+}
+
+static void
+gr_time_widget_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+        GrTimeWidget *self = GR_TIME_WIDGET (object);
+
+        switch (prop_id)
+          {
+          case PROP_TIMER:
+                  set_timer (self, g_value_get_object (value));
+                  break;
+
+          case PROP_SIZE:
+                  set_size (self, g_value_get_int (value));
+                  break;
+
+          default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+          }
+}
+
+static void
+gr_time_widget_class_init (GrTimeWidgetClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+        object_class->finalize = gr_time_widget_finalize;
+        object_class->get_property = gr_time_widget_get_property;
+        object_class->set_property = gr_time_widget_set_property;
+
+        g_object_class_install_property (object_class,
+                                         PROP_TIMER,
+                                         g_param_spec_object ("timer", NULL, NULL,
+                                                              GR_TYPE_TIMER,
+                                                              G_PARAM_READWRITE));
+
+        g_object_class_install_property (object_class,
+                                         PROP_SIZE,
+                                         g_param_spec_int ("size", NULL, NULL,
+                                                           1, G_MAXINT, 32,
+                                                           G_PARAM_READWRITE));
+
+        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Recipes/gr-time-widget.ui");
+        gtk_widget_class_bind_template_child (widget_class, GrTimeWidget, timer_widget);
+        gtk_widget_class_bind_template_child (widget_class, GrTimeWidget, time_remaining);
+        gtk_widget_class_bind_template_child (widget_class, GrTimeWidget, timer_button_stack);
+        gtk_widget_class_bind_template_child (widget_class, GrTimeWidget, pause_stack);
+
+        gtk_widget_class_bind_template_callback (widget_class, timer_start);
+        gtk_widget_class_bind_template_callback (widget_class, timer_pause);
+        gtk_widget_class_bind_template_callback (widget_class, timer_reset);
+}
+
+static void
+gr_time_widget_init (GrTimeWidget *self)
+{
+        gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+        gtk_widget_init_template (GTK_WIDGET (self));
+
+        self->size = 32;
+}
diff --git a/src/gr-time-widget.h b/src/gr-time-widget.h
new file mode 100644
index 0000000..7a9f838
--- /dev/null
+++ b/src/gr-time-widget.h
@@ -0,0 +1,33 @@
+/* gr-time-widget.h:
+ *
+ * Copyright (C) 2017 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * 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 3 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GR_TYPE_TIME_WIDGET (gr_time_widget_get_type())
+
+G_DECLARE_FINAL_TYPE (GrTimeWidget, gr_time_widget, GR, TIME_WIDGET, GtkOverlay)
+
+GrTimeWidget * gr_time_widget_new (void);
+
+G_END_DECLS
diff --git a/src/gr-time-widget.ui b/src/gr-time-widget.ui
new file mode 100644
index 0000000..d7dd856
--- /dev/null
+++ b/src/gr-time-widget.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="recipes">
+  <!-- interface-requires gtk+ 3.10 -->
+  <template class="GrTimeWidget" parent="GtkOverlay">
+    <property name="visible">True</property>
+    <child>
+      <object class="GrTimerWidget" id="timer_widget">
+        <property name="visible">1</property>
+      </object>
+    </child>
+    <child type="overlay">
+      <object class="GtkBox" id="timer_grid">
+        <property name="visible">1</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">20</property>
+        <child>
+          <object class="GtkLabel" id="time_remaining">
+            <property name="visible">1</property>
+            <style>
+              <class name="timer-label"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="timer_button_stack">
+            <property name="visible">1</property>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">1</property>
+                <property name="label" translatable="yes">Start</property>
+                <signal name="clicked" handler="timer_start" swapped="yes"/>
+                <style>
+                  <class name="suggested-action"/>
+                </style>
+              </object>
+              <packing>
+                <property name="name">start</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">1</property>
+                <property name="homogeneous">1</property>
+                <property name="spacing">20</property>
+                <child>
+                  <object class="GtkButton">
+                    <property name="visible">1</property>
+                    <property name="halign">fill</property>
+                    <signal name="clicked" handler="timer_pause" swapped="yes"/>
+                    <style>
+                      <class name="text-button"/>
+                      <class name="pause-button"/>
+                    </style>
+                    <child>
+                      <object class="GtkStack" id="pause_stack">
+                        <property name="visible">1</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">1</property>
+                            <property name="label" translatable="yes">Pause</property>
+                          </object>
+                          <packing>
+                            <property name="name">pause</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">1</property>
+                            <property name="label" translatable="yes">Continue</property>
+                          </object>
+                          <packing>
+                            <property name="name">resume</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkButton">
+                    <property name="visible">1</property>
+                    <property name="halign">fill</property>
+                    <property name="label">Reset</property>
+                    <signal name="clicked" handler="timer_reset" swapped="yes"/>
+                    <style>
+                      <class name="destructive-action"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">active</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/main.c b/src/main.c
index 27d636d..c5315cd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,6 +35,7 @@
 #include "gr-search-page.h"
 #include "gr-shopping-page.h"
 #include "gr-timer-widget.h"
+#include "gr-time-widget.h"
 #include "gr-toggle-button.h"
 #include "gr-image-viewer.h"
 #include "gr-image-page.h"
@@ -58,6 +59,7 @@ main (int argc, char *argv[])
         g_type_ensure (GR_TYPE_SEARCH_PAGE);
         g_type_ensure (GR_TYPE_SHOPPING_PAGE);
         g_type_ensure (GR_TYPE_TIMER_WIDGET);
+        g_type_ensure (GR_TYPE_TIME_WIDGET);
         g_type_ensure (GR_TYPE_TOGGLE_BUTTON);
 
         setlocale (LC_ALL, "");
diff --git a/src/recipes-ui.gresource.xml b/src/recipes-ui.gresource.xml
index ed92828..1d4d00b 100644
--- a/src/recipes-ui.gresource.xml
+++ b/src/recipes-ui.gresource.xml
@@ -20,6 +20,7 @@
     <file preprocess="xml-stripblanks">gr-recipe-tile.ui</file>
     <file preprocess="xml-stripblanks">gr-search-page.ui</file>
     <file preprocess="xml-stripblanks">gr-shopping-page.ui</file>
+    <file preprocess="xml-stripblanks">gr-time-widget.ui</file>
     <file preprocess="xml-stripblanks">gr-query-editor.ui</file>
     <file preprocess="xml-stripblanks">gr-window.ui</file>
     <file preprocess="xml-stripblanks">chef-conflict-dialog.ui</file>
diff --git a/src/recipes.css b/src/recipes.css
index 25ff3f1..bc5ffd9 100644
--- a/src/recipes.css
+++ b/src/recipes.css
@@ -290,3 +290,51 @@ flowbox flowboxchild {
 .note.content:backdrop {
   background: #cbd6e1;
 }
+
+button.osd {
+        padding: 10px;
+}
+
+.cooking {
+        background: black;
+}
+
+.cooking.overlay {
+        background: gray;
+        padding: 40px;
+        border-radius: 20px;
+}
+
+.cooking .heading {
+        font-size: 30px;
+}
+
+.cooking-image {
+        color: #ddd;
+        background: #aaa;
+        min-width: 400px;
+        min-height: 400px;
+}
+
+.timer-label,
+.cooking-label {
+        font-size: 30px;
+        color: #ddd;
+}
+
+.cooking-heading {
+        font-size: 20px;
+        color: #ddd;
+}
+
+.timer-frame border {
+        border: none;
+}
+
+.pause-button {
+        color: #ccc;
+        border-color: #ccc;
+        border-width: 1px;
+        box-shadow: none;
+        background: #444;
+}


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