[gnome-todo] Introduce GtdOmniArea



commit 5a556c637c7b540c3d492160b9e759fda650148a
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Apr 30 19:14:54 2020 -0300

    Introduce GtdOmniArea
    
    GtdOmniArea is the headerbar widget that will do... stuff. Right
    now it's just a fancy status area, but eventually we might want
    to add more, like actions.

 src/gnome-todo.h          |   2 +
 src/gtd-omni-area-addin.c |  69 +++++++++++++
 src/gtd-omni-area-addin.h |  49 +++++++++
 src/gtd-omni-area.c       | 256 ++++++++++++++++++++++++++++++++++++++++++++++
 src/gtd-omni-area.h       |  39 +++++++
 src/gtd-omni-area.ui      |  73 +++++++++++++
 src/gtd-types.h           |   1 +
 src/meson.build           |   8 ++
 src/theme/Adwaita.css     |  16 +++
 src/todo.gresource.xml    |   1 +
 10 files changed, 514 insertions(+)
---
diff --git a/src/gnome-todo.h b/src/gnome-todo.h
index e34ba43..ed49e9b 100644
--- a/src/gnome-todo.h
+++ b/src/gnome-todo.h
@@ -28,6 +28,8 @@
 #include "gtd-menu-button.h"
 #include "gtd-notification.h"
 #include "gtd-object.h"
+#include "gtd-omni-area.h"
+#include "gtd-omni-area-addin.h"
 #include "gtd-panel.h"
 #include "gtd-provider.h"
 #include "gtd-provider-popover.h"
diff --git a/src/gtd-omni-area-addin.c b/src/gtd-omni-area-addin.c
new file mode 100644
index 0000000..3ceec50
--- /dev/null
+++ b/src/gtd-omni-area-addin.c
@@ -0,0 +1,69 @@
+/* gtd-omni-area-addin.c
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "gtd-omni-area-addin.h"
+
+#include "gtd-omni-area.h"
+
+G_DEFINE_INTERFACE (GtdOmniAreaAddin, gtd_omni_area_addin, G_TYPE_OBJECT)
+
+static void
+gtd_omni_area_addin_default_init (GtdOmniAreaAddinInterface *iface)
+{
+}
+
+/**
+ * gtd_omni_area_addin_load:
+ * @self: an #GtdOmniAreaAddin
+ * @omni_bar: an #GtdOmniArea
+ *
+ * Requests that the #GtdOmniAreaAddin initialize, possibly modifying
+ * @omni_bar as necessary.
+ */
+void
+gtd_omni_area_addin_load (GtdOmniAreaAddin *self,
+                          GtdOmniArea      *omni_bar)
+{
+  g_return_if_fail (GTD_IS_OMNI_AREA_ADDIN (self));
+  g_return_if_fail (GTD_IS_OMNI_AREA (omni_bar));
+
+  if (GTD_OMNI_AREA_ADDIN_GET_IFACE (self)->load)
+    GTD_OMNI_AREA_ADDIN_GET_IFACE (self)->load (self, omni_bar);
+}
+
+/**
+ * gtd_omni_area_addin_unload:
+ * @self: an #GtdOmniAreaAddin
+ * @omni_bar: an #GtdOmniArea
+ *
+ * Requests that the #GtdOmniAreaAddin shutdown, possibly modifying
+ * @omni_bar as necessary to return it to the original state before
+ * the addin was loaded.
+ */
+void
+gtd_omni_area_addin_unload (GtdOmniAreaAddin *self,
+                            GtdOmniArea      *omni_bar)
+{
+  g_return_if_fail (GTD_IS_OMNI_AREA_ADDIN (self));
+  g_return_if_fail (GTD_IS_OMNI_AREA (omni_bar));
+
+  if (GTD_OMNI_AREA_ADDIN_GET_IFACE (self)->unload)
+    GTD_OMNI_AREA_ADDIN_GET_IFACE (self)->unload (self, omni_bar);
+}
diff --git a/src/gtd-omni-area-addin.h b/src/gtd-omni-area-addin.h
new file mode 100644
index 0000000..7a6bc97
--- /dev/null
+++ b/src/gtd-omni-area-addin.h
@@ -0,0 +1,49 @@
+/* gtd-omni-area-addin.h
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "gtd-types.h"
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_OMNI_AREA_ADDIN (gtd_omni_area_addin_get_type ())
+G_DECLARE_INTERFACE (GtdOmniAreaAddin, gtd_omni_area_addin, GTD, OMNI_AREA_ADDIN, GObject)
+
+struct _GtdOmniAreaAddinInterface
+{
+  GTypeInterface parent;
+
+  void               (*load)                                     (GtdOmniAreaAddin   *self,
+                                                                  GtdOmniArea        *omni_area);
+
+  void               (*unload)                                   (GtdOmniAreaAddin   *self,
+                                                                  GtdOmniArea        *omni_area);
+};
+
+void                 gtd_omni_area_addin_load                    (GtdOmniAreaAddin   *self,
+                                                                  GtdOmniArea        *omni_bar);
+
+void                 gtd_omni_area_addin_unload                  (GtdOmniAreaAddin   *self,
+                                                                  GtdOmniArea        *omni_bar);
+
+G_END_DECLS
diff --git a/src/gtd-omni-area.c b/src/gtd-omni-area.c
new file mode 100644
index 0000000..a461e95
--- /dev/null
+++ b/src/gtd-omni-area.c
@@ -0,0 +1,256 @@
+/* gtd-omni-area.c
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "GtdOmniArea"
+
+#include "gtd-omni-area.h"
+
+#include "gtd-debug.h"
+#include "gtd-omni-area-addin.h"
+
+#include <libpeas/peas.h>
+
+struct _GtdOmniArea
+{
+  GtkBin              parent;
+
+  GtkStack           *main_stack;
+  GtkStack           *status_stack;
+
+  PeasExtensionSet   *addins;
+
+  GQueue             *messages;
+  guint               current;
+
+  guint               switch_messages_timeout_id;
+};
+
+G_DEFINE_TYPE (GtdOmniArea, gtd_omni_area, GTK_TYPE_BIN)
+
+
+/*
+ * Auxiliary methods
+ */
+
+static void
+show_message (GtdOmniArea *self,
+              guint        message_index)
+{
+  const gchar *message_id;
+
+  message_id = g_queue_peek_nth (self->messages, message_index);
+
+  gtk_stack_set_visible_child_name (self->status_stack, message_id);
+  self->current = message_index;
+}
+
+
+
+/*
+ * Callbacks
+ */
+
+static gboolean
+switch_message_cb (gpointer user_data)
+{
+  GtdOmniArea *self = GTD_OMNI_AREA (user_data);
+  gint next_message_index;
+  guint n_messages;
+
+  n_messages = g_queue_get_length (self->messages);
+  gtk_stack_set_visible_child_name (self->main_stack, n_messages > 0 ? "messages" : "placeholder");
+
+  next_message_index = (self->current + 1) % n_messages;
+  show_message (self, next_message_index);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+on_omni_area_addin_added_cb (PeasExtensionSet *extension_set,
+                             PeasPluginInfo   *plugin_info,
+                             GtdOmniAreaAddin *addin,
+                             GtdOmniArea      *self)
+{
+  gtd_omni_area_addin_load (addin, self);
+}
+
+static void
+on_omni_area_addin_removed_cb (PeasExtensionSet *extension_set,
+                               PeasPluginInfo   *plugin_info,
+                               GtdOmniAreaAddin *addin,
+                               GtdOmniArea      *self)
+{
+  gtd_omni_area_addin_unload (addin, self);
+}
+
+
+/*
+ * GtkWidget overrides
+ */
+
+static void
+gtd_omni_area_destroy (GtkWidget *widget)
+{
+  GtdOmniArea *self = GTD_OMNI_AREA (widget);
+
+  g_clear_object (&self->addins);
+
+  GTK_WIDGET_CLASS (gtd_omni_area_parent_class)->destroy (widget);
+}
+
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_omni_area_finalize (GObject *object)
+{
+  GtdOmniArea *self = (GtdOmniArea *)object;
+
+  g_clear_handle_id (&self->switch_messages_timeout_id, g_source_remove);
+  g_queue_free_full (self->messages, g_free);
+
+  G_OBJECT_CLASS (gtd_omni_area_parent_class)->finalize (object);
+}
+
+static void
+gtd_omni_area_class_init (GtdOmniAreaClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtd_omni_area_finalize;
+
+  widget_class->destroy = gtd_omni_area_destroy;
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/gtd-omni-area.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdOmniArea, main_stack);
+  gtk_widget_class_bind_template_child (widget_class, GtdOmniArea, status_stack);
+
+  gtk_widget_class_set_css_name (widget_class, "omniarea");
+}
+
+static void
+gtd_omni_area_init (GtdOmniArea *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  self->messages = g_queue_new ();
+  self->addins = peas_extension_set_new (peas_engine_get_default (),
+                                         GTD_TYPE_OMNI_AREA_ADDIN,
+                                         NULL);
+
+  peas_extension_set_foreach (self->addins,
+                              (PeasExtensionSetForeachFunc) on_omni_area_addin_added_cb,
+                              self);
+
+  g_signal_connect (self->addins, "extension-added", G_CALLBACK (on_omni_area_addin_added_cb), self);
+  g_signal_connect (self->addins, "extension-removed", G_CALLBACK (on_omni_area_addin_removed_cb), self);
+}
+
+/**
+ * gtd_omni_area_push_message:
+ * @self: a #GtdOmniArea
+ * @id: an identifier for this notification
+ * @text: user visible text of the notification
+ * @icon: (nullable): a #GIcon
+ *
+ * Pushes a new message to @self.
+ *
+ */
+void
+gtd_omni_area_push_message (GtdOmniArea *self,
+                            const gchar *id,
+                            const gchar *text,
+                            GIcon       *icon)
+{
+  GtkWidget *label;
+  GtkWidget *box;
+
+  g_return_if_fail (GTD_IS_OMNI_AREA (self));
+  g_return_if_fail (id != NULL);
+  g_return_if_fail (text != NULL);
+
+  GTD_ENTRY;
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
+
+  label = gtk_label_new (text);
+  gtk_label_set_width_chars (GTK_LABEL (label), 35);
+  gtk_label_set_max_width_chars (GTK_LABEL (label), 35);
+  gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_container_add (GTK_CONTAINER (box), label);
+
+  if (icon)
+    gtk_container_add (GTK_CONTAINER (box), gtk_image_new_from_gicon (icon));
+
+  gtk_stack_add_named (self->status_stack, box, id);
+
+  g_debug ("Adding message '%s' to Omni Area", id);
+
+  g_queue_push_tail (self->messages, g_strdup (id));
+  show_message (self, g_queue_get_length (self->messages) - 1);
+
+  g_clear_handle_id (&self->switch_messages_timeout_id, g_source_remove);
+  self->switch_messages_timeout_id = g_timeout_add (7500, switch_message_cb, self);
+
+  GTD_EXIT;
+}
+
+/**
+ * gtd_omni_area_withdraw_message:
+ * @self: a #GtdOmniArea
+ * @id: an identifier for this notification
+ *
+ * Withdraws a message from @self. If a message with @id doesn't
+ * exist, nothing happens.
+ */
+void
+gtd_omni_area_withdraw_message (GtdOmniArea *self,
+                                const gchar *id)
+{
+  GtkWidget *widget;
+  GList *l;
+
+  g_return_if_fail (GTD_IS_OMNI_AREA (self));
+  g_return_if_fail (id != NULL);
+
+  GTD_ENTRY;
+
+  widget = gtk_stack_get_child_by_name (self->status_stack, id);
+  if (!widget)
+    return;
+
+  g_debug ("Removing message '%s' from Omni Area", id);
+
+  gtk_widget_destroy (widget);
+
+  l = g_queue_find_custom (self->messages, id, (GCompareFunc) g_strcmp0);
+  g_queue_delete_link (self->messages, l);
+
+  if (g_queue_get_length (self->messages) == 0)
+    gtk_stack_set_visible_child_name (self->main_stack, "placeholder");
+
+  GTD_EXIT;
+}
diff --git a/src/gtd-omni-area.h b/src/gtd-omni-area.h
new file mode 100644
index 0000000..a49ffd8
--- /dev/null
+++ b/src/gtd-omni-area.h
@@ -0,0 +1,39 @@
+/* gtd-omni-area.h
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_OMNI_AREA (gtd_omni_area_get_type())
+G_DECLARE_FINAL_TYPE (GtdOmniArea, gtd_omni_area, GTD, OMNI_AREA, GtkBin)
+
+void                 gtd_omni_area_push_message                  (GtdOmniArea        *self,
+                                                                  const gchar        *id,
+                                                                  const gchar        *text,
+                                                                  GIcon              *icon);
+
+void                 gtd_omni_area_withdraw_message              (GtdOmniArea        *self,
+                                                                  const gchar        *id);
+
+G_END_DECLS
diff --git a/src/gtd-omni-area.ui b/src/gtd-omni-area.ui
new file mode 100644
index 0000000..9d10da7
--- /dev/null
+++ b/src/gtd-omni-area.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtdOmniArea" parent="GtkBin">
+
+    <child>
+      <object class="GtkCenterBox">
+
+        <child type="start">
+          <object class="GtkBox" id="start_box">
+            <property name="margin-end">12</property>
+          </object>
+        </child>
+
+        <child type="center">
+          <object class="GtkBox">
+            <property name="css-name">entry</property>
+
+
+            <child>
+              <object class="GtkStack" id="main_stack">
+                <property name="margin-start">6</property>
+                <property name="margin-end">6</property>
+                <property name="hhomogeneous">true</property>
+                <property name="transition-type">slide-up-down</property>
+                <property name="transition-duration">500</property>
+
+                <child>
+                  <object class="GtkStackPage">
+                    <property name="name">placeholder</property>
+                    <property name="child">
+                      <object class="GtkLabel">
+                        <property name="label" translatable="yes">To Do</property>
+                        <property name="xalign">0.0</property>
+                        <property name="width-chars">35</property>
+                        <property name="max-width-chars">35</property>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+
+                <child>
+                  <object class="GtkStackPage">
+                    <property name="name">messages</property>
+                    <property name="child">
+                      <object class="GtkStack" id="status_stack">
+                        <property name="margin-start">6</property>
+                        <property name="margin-end">6</property>
+                        <property name="hhomogeneous">true</property>
+                        <property name="transition-type">slide-up-down</property>
+                        <property name="transition-duration">500</property>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+
+              </object>
+            </child>
+
+
+          </object>
+        </child>
+
+        <child type="end">
+          <object class="GtkBox" id="end_box">
+            <property name="margin-start">12</property>
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+  </template>
+</interface>
diff --git a/src/gtd-types.h b/src/gtd-types.h
index 47f441f..d1a8c7d 100644
--- a/src/gtd-types.h
+++ b/src/gtd-types.h
@@ -36,6 +36,7 @@ typedef struct _GtdMarkdownRenderer     GtdMarkdownRenderer;
 typedef struct _GtdNotification         GtdNotification;
 typedef struct _GtdNotificationWidget   GtdNotificationWidget;
 typedef struct _GtdObject               GtdObject;
+typedef struct _GtdOmniArea             GtdOmniArea;
 typedef struct _GtdPanel                GtdPanel;
 typedef struct _GtdPluginManager        GtdPluginManager;
 typedef struct _GtdProvider             GtdProvider;
diff --git a/src/meson.build b/src/meson.build
index 61993f8..0ede9ff 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,6 +28,8 @@ headers = enum_headers + files(
   'widgets/gtd-menu-button.h',
   'gtd-clock.h',
   'gtd-object.h',
+  'gtd-omni-area.h',
+  'gtd-omni-area-addin.h',
   'gtd-task.h',
   'gtd-task-list.h',
   'gtd-types.h',
@@ -75,6 +77,8 @@ sources = files(
   'gtd-initial-setup-window.c',
   'gtd-clock.c',
   'gtd-object.c',
+  'gtd-omni-area.c',
+  'gtd-omni-area-addin.c',
   'gtd-plugin-dialog.c',
   'gtd-plugin-dialog-row.c',
   'gtd-rows-common.c',
@@ -251,6 +255,10 @@ if get_option('introspection')
     'gtd-clock.h',
     'gtd-object.c',
     'gtd-object.h',
+    'gtd-omni-area.c',
+    'gtd-omni-area.h',
+    'gtd-omni-area-addin.c',
+    'gtd-omni-area-addin.h',
     'gtd-task.c',
     'gtd-task.h',
     'gtd-task-list.c',
diff --git a/src/theme/Adwaita.css b/src/theme/Adwaita.css
index e2bd944..2f98c07 100644
--- a/src/theme/Adwaita.css
+++ b/src/theme/Adwaita.css
@@ -146,3 +146,19 @@ colorbutton.dark image {
 colorbutton.light image {
     color: black;
 }
+
+/* Omni Area */
+
+omniarea entry {
+  background-color: mix(@theme_bg_color, @content_view_bg, 0.25);
+  color: @theme_fg_color;
+}
+omniarea:hover entry,
+omniarea:active entry {
+  background-color: @content_view_bg;
+  color: @theme_fg_color;
+}
+
+omniarea:backdrop entry {
+  background-color: @theme_bg_color;
+}
diff --git a/src/todo.gresource.xml b/src/todo.gresource.xml
index acb9f72..07f4381 100644
--- a/src/todo.gresource.xml
+++ b/src/todo.gresource.xml
@@ -13,6 +13,7 @@
     <file compressed="true" preprocess="xml-stripblanks">task-list-view/gtd-task-row.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">widgets/gtd-empty-list-widget.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">gtd-initial-setup-window.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">gtd-omni-area.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">gtd-plugin-dialog.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">gtd-plugin-dialog-row.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">gtd-window.ui</file>


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