[gnome-builder] util: add GbSimplePopover



commit 551e1436f2f8f86f1f46af5684d69b71f8c98062
Author: Christian Hergert <christian hergert me>
Date:   Fri Sep 18 16:09:20 2015 -0700

    util: add GbSimplePopover
    
    This class is aimed to make it quick to add simple popovers in the style
    used in other areas of Builder such as new file, rename file, etc.

 data/ui/gb-simple-popover.ui              |   55 ++++
 src/Makefile.am                           |    2 +
 src/resources/gnome-builder.gresource.xml |    1 +
 src/util/gb-simple-popover.c              |  415 +++++++++++++++++++++++++++++
 src/util/gb-simple-popover.h              |   90 +++++++
 5 files changed, 563 insertions(+), 0 deletions(-)
---
diff --git a/data/ui/gb-simple-popover.ui b/data/ui/gb-simple-popover.ui
new file mode 100644
index 0000000..689efcf
--- /dev/null
+++ b/data/ui/gb-simple-popover.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.16 -->
+  <template class="GbSimplePopover" parent="GtkPopover">
+    <child>
+      <object class="GtkBox">
+        <property name="border-width">12</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkLabel" id="title">
+            <property name="xalign">0.0</property>
+            <property name="visible">true</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">horizontal</property>
+            <property name="spacing">9</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkEntry" id="entry">
+                <property name="width-chars">20</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="button">
+                <property name="sensitive">false</property>
+                <property name="use-underline">true</property>
+                <property name="visible">true</property>
+                <style>
+                  <class name="suggested-action"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="message">
+            <property name="xalign">0.0</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 025cb73..d65c75e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -156,6 +156,8 @@ libgnome_builder_la_SOURCES = \
        util/gb-plugins.h \
        util/gb-rgba.c \
        util/gb-rgba.h \
+       util/gb-simple-popover.c \
+       util/gb-simple-popover.h \
        util/gb-string.c \
        util/gb-string.h \
        util/gb-widget.c \
diff --git a/src/resources/gnome-builder.gresource.xml b/src/resources/gnome-builder.gresource.xml
index ec089d7..18862b5 100644
--- a/src/resources/gnome-builder.gresource.xml
+++ b/src/resources/gnome-builder.gresource.xml
@@ -43,6 +43,7 @@
     <file alias="ui/gb-search-display-group.ui">../../data/ui/gb-search-display-group.ui</file>
     <file alias="ui/gb-search-display-row.ui">../../data/ui/gb-search-display-row.ui</file>
     <file alias="ui/gb-shortcuts-window.ui">../../data/ui/gb-shortcuts-window.ui</file>
+    <file alias="ui/gb-simple-popover.ui">../../data/ui/gb-simple-popover.ui</file>
     <file alias="ui/gb-view.ui">../../data/ui/gb-view.ui</file>
     <file alias="ui/gb-view-stack.ui">../../data/ui/gb-view-stack.ui</file>
     <file alias="ui/gb-workbench.ui">../../data/ui/gb-workbench.ui</file>
diff --git a/src/util/gb-simple-popover.c b/src/util/gb-simple-popover.c
new file mode 100644
index 0000000..9c034cf
--- /dev/null
+++ b/src/util/gb-simple-popover.c
@@ -0,0 +1,415 @@
+/* gb-simple-popover.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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 "gb-simple-popover.h"
+
+typedef struct
+{
+  GtkPopover parent_instance;
+
+  GtkLabel  *title;
+  GtkLabel  *message;
+  GtkEntry  *entry;
+  GtkButton *button;
+} GbSimplePopoverPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GbSimplePopover, gb_simple_popover, GTK_TYPE_POPOVER)
+
+enum {
+  PROP_0,
+  PROP_BUTTON_TEXT,
+  PROP_MESSAGE,
+  PROP_READY,
+  PROP_TEXT,
+  PROP_TITLE,
+  LAST_PROP
+};
+
+enum {
+  ACTIVATE,
+  CHANGED,
+  INSERT_TEXT,
+  LAST_SIGNAL
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+static guint gSignals [LAST_SIGNAL];
+
+const gchar *
+gb_simple_popover_get_button_text (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_val_if_fail (GB_IS_SIMPLE_POPOVER (self), NULL);
+
+  return gtk_button_get_label (priv->button);
+}
+
+void
+gb_simple_popover_set_button_text (GbSimplePopover *self,
+                                   const gchar     *button_text)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_if_fail (GB_IS_SIMPLE_POPOVER (self));
+
+  gtk_button_set_label (priv->button, button_text);
+  g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_BUTTON_TEXT]);
+}
+
+const gchar *
+gb_simple_popover_get_message (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_val_if_fail (GB_IS_SIMPLE_POPOVER (self), NULL);
+
+  return gtk_label_get_text (priv->message);
+}
+
+void
+gb_simple_popover_set_message (GbSimplePopover *self,
+                               const gchar     *message)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_if_fail (GB_IS_SIMPLE_POPOVER (self));
+
+  gtk_label_set_label (priv->message, message);
+  g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_MESSAGE]);
+}
+
+gboolean
+gb_simple_popover_get_ready (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_val_if_fail (GB_IS_SIMPLE_POPOVER (self), FALSE);
+
+  return gtk_widget_get_sensitive (GTK_WIDGET (priv->button));
+}
+
+void
+gb_simple_popover_set_ready (GbSimplePopover *self,
+                             gboolean         ready)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_if_fail (GB_IS_SIMPLE_POPOVER (self));
+
+  gtk_widget_set_sensitive (GTK_WIDGET (priv->button), ready);
+  g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_READY]);
+}
+
+const gchar *
+gb_simple_popover_get_text (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_val_if_fail (GB_IS_SIMPLE_POPOVER (self), NULL);
+
+  return gtk_entry_get_text (priv->entry);
+}
+
+void
+gb_simple_popover_set_text (GbSimplePopover *self,
+                            const gchar     *text)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_if_fail (GB_IS_SIMPLE_POPOVER (self));
+
+  gtk_entry_set_text (priv->entry, text);
+  g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_TEXT]);
+}
+
+const gchar *
+gb_simple_popover_get_title (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_val_if_fail (GB_IS_SIMPLE_POPOVER (self), NULL);
+
+  return gtk_label_get_label (priv->title);
+}
+
+void
+gb_simple_popover_set_title (GbSimplePopover *self,
+                             const gchar     *title)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_return_if_fail (GB_IS_SIMPLE_POPOVER (self));
+
+  gtk_label_set_label (priv->title, title);
+  g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_TITLE]);
+}
+
+static void
+gb_simple_popover_button_clicked (GbSimplePopover *self,
+                                  GtkButton       *button)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+  const gchar *text;
+
+  g_assert (GB_IS_SIMPLE_POPOVER (self));
+  g_assert (GTK_IS_BUTTON (button));
+
+  text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+  g_signal_emit (self, gSignals [ACTIVATE], 0, text);
+  gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static void
+gb_simple_popover_entry_activate (GbSimplePopover *self,
+                                  GtkEntry        *entry)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  g_assert (GB_IS_SIMPLE_POPOVER (self));
+  g_assert (GTK_IS_ENTRY (entry));
+
+  if (gb_simple_popover_get_ready (self))
+    gtk_widget_activate (GTK_WIDGET (priv->button));
+}
+
+static void
+gb_simple_popover_entry_changed (GbSimplePopover *self,
+                                 GtkEntry        *entry)
+{
+  g_assert (GB_IS_SIMPLE_POPOVER (self));
+  g_assert (GTK_IS_ENTRY (entry));
+
+  g_signal_emit (self, gSignals [CHANGED], 0);
+}
+
+static void
+gb_simple_popover_entry_insert_text (GbSimplePopover *self,
+                                     gchar           *new_text,
+                                     gint             new_text_length,
+                                     gint            *position,
+                                     GtkEntry        *entry)
+{
+  gboolean ret = GDK_EVENT_PROPAGATE;
+  guint pos;
+  guint n_chars;
+
+  g_assert (GB_IS_SIMPLE_POPOVER (self));
+  g_assert (new_text != NULL);
+  g_assert (position != NULL);
+
+  pos = *position;
+  n_chars = (new_text_length >= 0) ? new_text_length : g_utf8_strlen (new_text, -1);
+
+  g_signal_emit (self, gSignals [INSERT_TEXT], 0, pos, new_text, n_chars, &ret);
+
+  if (ret == GDK_EVENT_STOP)
+    g_signal_stop_emission_by_name (entry, "insert-text");
+}
+
+static void
+gb_simple_popover_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GbSimplePopover *self = GB_SIMPLE_POPOVER (object);
+
+  switch (prop_id)
+    {
+    case PROP_BUTTON_TEXT:
+      g_value_set_string (value, gb_simple_popover_get_button_text (self));
+      break;
+
+    case PROP_MESSAGE:
+      g_value_set_string (value, gb_simple_popover_get_message (self));
+      break;
+
+    case PROP_READY:
+      g_value_set_boolean (value, gb_simple_popover_get_ready (self));
+      break;
+
+    case PROP_TEXT:
+      g_value_set_string (value, gb_simple_popover_get_text (self));
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, gb_simple_popover_get_title (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_simple_popover_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GbSimplePopover *self = GB_SIMPLE_POPOVER (object);
+
+  switch (prop_id)
+    {
+    case PROP_BUTTON_TEXT:
+      gb_simple_popover_set_button_text (self, g_value_get_string (value));
+      break;
+
+    case PROP_MESSAGE:
+      gb_simple_popover_set_message (self, g_value_get_string (value));
+      break;
+
+    case PROP_READY:
+      gb_simple_popover_set_ready (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_TEXT:
+      gb_simple_popover_set_text (self, g_value_get_string (value));
+      break;
+
+    case PROP_TITLE:
+      gb_simple_popover_set_title (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_simple_popover_class_init (GbSimplePopoverClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->get_property = gb_simple_popover_get_property;
+  object_class->set_property = gb_simple_popover_set_property;
+
+  gParamSpecs [PROP_BUTTON_TEXT] =
+    g_param_spec_string ("button-text",
+                         "Button Text",
+                         "Button Text",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gParamSpecs [PROP_MESSAGE] =
+    g_param_spec_string ("message",
+                         "Message",
+                         "Message",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gParamSpecs [PROP_READY] =
+    g_param_spec_boolean ("ready",
+                          "Ready",
+                          "Ready",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gParamSpecs [PROP_TEXT] =
+    g_param_spec_string ("text",
+                         "Text",
+                         "Text",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gParamSpecs [PROP_TITLE] =
+    g_param_spec_string ("title",
+                         "Title",
+                         "Title",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+
+  gSignals [ACTIVATE] =
+    g_signal_new ("activate",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GbSimplePopoverClass, activate),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_STRING);
+
+  gSignals [CHANGED] =
+    g_signal_new ("changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GbSimplePopoverClass, insert_text),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  0);
+
+  gSignals [INSERT_TEXT] =
+    g_signal_new ("insert-text",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GbSimplePopoverClass, insert_text),
+                  NULL, NULL, NULL,
+                  G_TYPE_BOOLEAN,
+                  3,
+                  G_TYPE_UINT,
+                  G_TYPE_STRING,
+                  G_TYPE_UINT);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/gb-simple-popover.ui");
+  gtk_widget_class_bind_template_child_private (widget_class, GbSimplePopover, title);
+  gtk_widget_class_bind_template_child_private (widget_class, GbSimplePopover, message);
+  gtk_widget_class_bind_template_child_private (widget_class, GbSimplePopover, entry);
+  gtk_widget_class_bind_template_child_private (widget_class, GbSimplePopover, button);
+}
+
+static void
+gb_simple_popover_init (GbSimplePopover *self)
+{
+  GbSimplePopoverPrivate *priv = gb_simple_popover_get_instance_private (self);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (priv->button,
+                           "clicked",
+                           G_CALLBACK (gb_simple_popover_button_clicked),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->entry,
+                           "changed",
+                           G_CALLBACK (gb_simple_popover_entry_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->entry,
+                           "activate",
+                           G_CALLBACK (gb_simple_popover_entry_activate),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->entry,
+                           "insert-text",
+                           G_CALLBACK (gb_simple_popover_entry_insert_text),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+GtkWidget *
+gb_simple_popover_new (void)
+{
+  return g_object_new (GB_TYPE_SIMPLE_POPOVER, NULL);
+}
diff --git a/src/util/gb-simple-popover.h b/src/util/gb-simple-popover.h
new file mode 100644
index 0000000..a11e35e
--- /dev/null
+++ b/src/util/gb-simple-popover.h
@@ -0,0 +1,90 @@
+/* gb-simple-popover.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef GB_SIMPLE_POPOVER_H
+#define GB_SIMPLE_POPOVER_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_SIMPLE_POPOVER (gb_simple_popover_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GbSimplePopover, gb_simple_popover, GB, SIMPLE_POPOVER, GtkPopover)
+
+struct _GbSimplePopoverClass
+{
+  GtkPopoverClass parent;
+
+  /**
+   * GbSimplePopover::activate:
+   * @self: The #GbSimplePopover instance.
+   * @text: The text at the time of activation.
+   *
+   * This signal is emitted when the popover's forward button is activated.
+   * Connect to this signal to perform your forward progress.
+   */
+  void (*activate) (GbSimplePopover *self,
+                    const gchar     *text);
+
+  /**
+   * GbSimplePopover::insert-text:
+   * @self: A #GbSimplePopover.
+   * @position: the position in UTF-8 characters.
+   * @chars: the NULL terminated UTF-8 text to insert.
+   * @n_chars: the number of UTF-8 characters in chars.
+   *
+   * Use this signal to determine if text should be allowed to be inserted
+   * into the text buffer. Return GDK_EVENT_STOP to prevent the text from
+   * being inserted.
+   */
+  gboolean (*insert_text) (GbSimplePopover *self,
+                           guint            position,
+                           const gchar     *chars,
+                           guint            n_chars);
+
+  
+  /**
+   * GbSimplePopover::changed:
+   * @self: A #GbSimplePopover.
+   *
+   * This signal is emitted when the entry text changes.
+   */
+  void (*changed) (GbSimplePopover *self);
+};
+
+GtkWidget   *gb_simple_popover_new             (void);
+const gchar *gb_simple_popover_get_text        (GbSimplePopover *self);
+void         gb_simple_popover_set_text        (GbSimplePopover *self,
+                                                const gchar     *text);
+const gchar *gb_simple_popover_get_message     (GbSimplePopover *self);
+void         gb_simple_popover_set_message     (GbSimplePopover *self,
+                                                const gchar     *message);
+const gchar *gb_simple_popover_get_title       (GbSimplePopover *self);
+void         gb_simple_popover_set_title       (GbSimplePopover *self,
+                                                const gchar     *title);
+const gchar *gb_simple_popover_get_button_text (GbSimplePopover *self);
+void         gb_simple_popover_set_button_text (GbSimplePopover *self,
+                                                const gchar     *button_text);
+gboolean     gb_simple_popover_get_ready       (GbSimplePopover *self);
+void         gb_simple_popover_set_ready       (GbSimplePopover *self,
+                                                gboolean         ready);
+
+G_END_DECLS
+
+#endif /* GB_SIMPLE_POPOVER_H */


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