[gnome-builder] messages: add IdeWorkbenchMessage



commit 75e1e5468a899c61f42dc13163b944a2468ea45d
Author: Christian Hergert <chergert redhat com>
Date:   Fri Mar 10 00:30:02 2017 -0800

    messages: add IdeWorkbenchMessage
    
    This is a new widget that can be pushed onto a workbench so that toplevel
    messages are visible to the user. You might use this to show a warning
    that a package needs to be installed, such as flatpak-builder.

 libide/Makefile.am                        |    2 +
 libide/ide.h                              |    1 +
 libide/resources/libide.gresource.xml     |    1 +
 libide/workbench/ide-workbench-message.c  |  222 +++++++++++++++++++++++++++++
 libide/workbench/ide-workbench-message.h  |   46 ++++++
 libide/workbench/ide-workbench-message.ui |   43 ++++++
 libide/workbench/ide-workbench-private.h  |    1 +
 libide/workbench/ide-workbench.c          |   74 ++++++++++
 libide/workbench/ide-workbench.h          |    5 +
 libide/workbench/ide-workbench.ui         |   26 +++-
 10 files changed, 416 insertions(+), 5 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index c25561d..ca1d0ca 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -191,6 +191,7 @@ libide_1_0_la_public_headers =                                              \
        workbench/ide-omni-bar.h                                            \
        workbench/ide-perspective.h                                         \
        workbench/ide-workbench-addin.h                                     \
+       workbench/ide-workbench-message.h                                   \
        workbench/ide-workbench-header-bar.h                                \
        workbench/ide-workbench.h                                           \
        workers/ide-worker.h                                                \
@@ -370,6 +371,7 @@ libide_1_0_la_public_sources =                                              \
        workbench/ide-perspective.c                                         \
        workbench/ide-workbench-addin.c                                     \
        workbench/ide-workbench-header-bar.c                                \
+       workbench/ide-workbench-message.c                                   \
        workbench/ide-workbench-open.c                                      \
        workbench/ide-workbench.c                                           \
        workers/ide-worker.c                                                \
diff --git a/libide/ide.h b/libide/ide.h
index 38b2c9f..587201b 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -172,6 +172,7 @@ G_BEGIN_DECLS
 #include "workbench/ide-layout.h"
 #include "workbench/ide-perspective.h"
 #include "workbench/ide-workbench-addin.h"
+#include "workbench/ide-workbench-message.h"
 #include "workbench/ide-workbench-header-bar.h"
 #include "workbench/ide-workbench.h"
 
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index 775f112..c6dd809 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -83,6 +83,7 @@
     <file compressed="true" alias="ide-shortcuts-window.ui">../keybindings/ide-shortcuts-window.ui</file>
     <file compressed="true" 
alias="ide-workbench-header-bar.ui">../workbench/ide-workbench-header-bar.ui</file>
     <file compressed="true" alias="ide-workbench.ui">../workbench/ide-workbench.ui</file>
+    <file compressed="true" alias="ide-workbench-message.ui">../workbench/ide-workbench-message.ui</file>
   </gresource>
 
   <gresource prefix="/org/gnome/builder/plugins/buildconfig">
diff --git a/libide/workbench/ide-workbench-message.c b/libide/workbench/ide-workbench-message.c
new file mode 100644
index 0000000..fb319c8
--- /dev/null
+++ b/libide/workbench/ide-workbench-message.c
@@ -0,0 +1,222 @@
+/* ide-workbench-message.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat 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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-workbench-message"
+
+#include "ide-workbench-message.h"
+
+struct _IdeWorkbenchMessage
+{
+  GtkInfoBar parent_instance;
+
+  gchar *id;
+
+  GtkLabel *title;
+  GtkLabel *subtitle;
+};
+
+enum {
+  PROP_0,
+  PROP_ID,
+  PROP_TITLE,
+  PROP_SUBTITLE,
+  N_PROPS
+};
+
+G_DEFINE_TYPE (IdeWorkbenchMessage, ide_workbench_message, GTK_TYPE_INFO_BAR)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_workbench_message_finalize (GObject *object)
+{
+  IdeWorkbenchMessage *self = (IdeWorkbenchMessage *)object;
+
+  g_clear_pointer (&self->id, g_free);
+
+  G_OBJECT_CLASS (ide_workbench_message_parent_class)->finalize (object);
+}
+
+static void
+ide_workbench_message_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  IdeWorkbenchMessage *self = IDE_WORKBENCH_MESSAGE (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      g_value_set_string (value, ide_workbench_message_get_id (self));
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, ide_workbench_message_get_title (self));
+      break;
+
+    case PROP_SUBTITLE:
+      g_value_set_string (value, ide_workbench_message_get_subtitle (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_workbench_message_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  IdeWorkbenchMessage *self = IDE_WORKBENCH_MESSAGE (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      ide_workbench_message_set_id (self, g_value_get_string (value));
+      break;
+
+    case PROP_TITLE:
+      ide_workbench_message_set_title (self, g_value_get_string (value));
+      break;
+
+    case PROP_SUBTITLE:
+      ide_workbench_message_set_subtitle (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_workbench_message_class_init (IdeWorkbenchMessageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = ide_workbench_message_finalize;
+  object_class->get_property = ide_workbench_message_get_property;
+  object_class->set_property = ide_workbench_message_set_property;
+
+  properties [PROP_ID] =
+    g_param_spec_string ("id", NULL, NULL, NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_TITLE] =
+    g_param_spec_string ("title", NULL, NULL, NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_SUBTITLE] =
+    g_param_spec_string ("subtitle", NULL, NULL, NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-workbench-message.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, IdeWorkbenchMessage, title);
+  gtk_widget_class_bind_template_child (widget_class, IdeWorkbenchMessage, subtitle);
+}
+
+static void
+ide_workbench_message_init (IdeWorkbenchMessage *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+const gchar *
+ide_workbench_message_get_id (IdeWorkbenchMessage *self)
+{
+  g_return_val_if_fail (IDE_IS_WORKBENCH_MESSAGE (self), NULL);
+
+  return self->id;
+}
+
+void
+ide_workbench_message_set_id (IdeWorkbenchMessage *self,
+                              const gchar         *id)
+{
+  g_return_if_fail (IDE_IS_WORKBENCH_MESSAGE (self));
+
+  if (g_strcmp0 (id, self->id) != 0)
+    {
+      g_free (self->id);
+      self->id = g_strdup (id);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
+    }
+}
+
+const gchar *
+ide_workbench_message_get_title (IdeWorkbenchMessage *self)
+{
+  g_return_val_if_fail (IDE_IS_WORKBENCH_MESSAGE (self), NULL);
+
+  return gtk_label_get_label (self->title);
+}
+
+void
+ide_workbench_message_set_title (IdeWorkbenchMessage *self,
+                                 const gchar         *title)
+{
+  g_return_if_fail (IDE_IS_WORKBENCH_MESSAGE (self));
+
+  gtk_label_set_label (self->title, title);
+  gtk_widget_set_visible (GTK_WIDGET (self->title), title || *title);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
+}
+
+const gchar *
+ide_workbench_message_get_subtitle (IdeWorkbenchMessage *self)
+{
+  g_return_val_if_fail (IDE_IS_WORKBENCH_MESSAGE (self), NULL);
+
+  return gtk_label_get_label (self->subtitle);
+}
+
+void
+ide_workbench_message_set_subtitle (IdeWorkbenchMessage *self,
+                                    const gchar         *subtitle)
+{
+  g_return_if_fail (IDE_IS_WORKBENCH_MESSAGE (self));
+
+  gtk_label_set_label (self->subtitle, subtitle);
+  gtk_widget_set_visible (GTK_WIDGET (self->subtitle), subtitle || *subtitle);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SUBTITLE]);
+}
+
+void
+ide_workbench_message_add_action (IdeWorkbenchMessage *self,
+                                  const gchar         *title,
+                                  const gchar         *action_name)
+{
+  GtkWidget *button;
+
+  g_return_if_fail (IDE_IS_WORKBENCH_MESSAGE (self));
+  g_return_if_fail (title);
+
+  button = g_object_new (GTK_TYPE_BUTTON,
+                         "action-name", action_name,
+                         "label", title,
+                         "visible", TRUE,
+                         NULL);
+
+  gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_action_area (GTK_INFO_BAR (self))), button);
+}
diff --git a/libide/workbench/ide-workbench-message.h b/libide/workbench/ide-workbench-message.h
new file mode 100644
index 0000000..10069a3
--- /dev/null
+++ b/libide/workbench/ide-workbench-message.h
@@ -0,0 +1,46 @@
+/* ide-workbench-message.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat 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/>.
+ */
+
+#ifndef IDE_WORKBENCH_MESSAGE_H
+#define IDE_WORKBENCH_MESSAGE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_WORKBENCH_MESSAGE (ide_workbench_message_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeWorkbenchMessage, ide_workbench_message, IDE, WORKBENCH_MESSAGE, GtkInfoBar)
+
+GtkWidget   *ide_workbench_message_new          (void);
+const gchar *ide_workbench_message_get_id       (IdeWorkbenchMessage *self);
+void         ide_workbench_message_set_id       (IdeWorkbenchMessage *self,
+                                                 const gchar         *id);
+const gchar *ide_workbench_message_get_title    (IdeWorkbenchMessage *self);
+void         ide_workbench_message_set_title    (IdeWorkbenchMessage *self,
+                                                 const gchar         *title);
+const gchar *ide_workbench_message_get_subtitle (IdeWorkbenchMessage *self);
+void         ide_workbench_message_set_subtitle (IdeWorkbenchMessage *self,
+                                                 const gchar         *subtitle);
+void         ide_workbench_message_add_action   (IdeWorkbenchMessage *self,
+                                                 const gchar         *label,
+                                                 const gchar         *action_name);
+
+G_END_DECLS
+
+#endif /* IDE_WORKBENCH_MESSAGE_H */
diff --git a/libide/workbench/ide-workbench-message.ui b/libide/workbench/ide-workbench-message.ui
new file mode 100644
index 0000000..f9e9ac1
--- /dev/null
+++ b/libide/workbench/ide-workbench-message.ui
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.22 -->
+  <template class="IdeWorkbenchMessage" parent="GtkInfoBar">
+    <property name="show-close-button">true</property>
+    <child internal-child="content_area">
+      <object class="GtkBox" id="hbox">
+        <property name="orientation">horizontal</property>
+        <property name="hexpand">true</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkLabel" id="title">
+                <property name="visible">true</property>
+                <property name="xalign">0.0</property>
+                <property name="wrap">true</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="subtitle">
+                <property name="visible">true</property>
+                <property name="xalign">0.0</property>
+                <property name="wrap">true</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+                <attributes>
+                  <attribute name="scale" value="0.833333"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/libide/workbench/ide-workbench-private.h b/libide/workbench/ide-workbench-private.h
index 4f738e6..f761168 100644
--- a/libide/workbench/ide-workbench-private.h
+++ b/libide/workbench/ide-workbench-private.h
@@ -51,6 +51,7 @@ struct _IdeWorkbench
   IdePerspectiveMenuButton  *perspective_menu_button;
   GtkStack                  *perspectives_stack;
   GtkSizeGroup              *header_size_group;
+  GtkBox                    *message_box;
 
   GObject                   *selection_owner;
 };
diff --git a/libide/workbench/ide-workbench.c b/libide/workbench/ide-workbench.c
index 3f49f4b..dc92319 100644
--- a/libide/workbench/ide-workbench.c
+++ b/libide/workbench/ide-workbench.c
@@ -409,6 +409,7 @@ ide_workbench_class_init (IdeWorkbenchClass *klass)
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, header_bar);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, header_size_group);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, header_stack);
+  gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, message_box);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspective_menu_button);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspectives_stack);
 }
@@ -979,3 +980,76 @@ ide_workbench_get_headerbar (IdeWorkbench *self)
 
   return self->header_bar;
 }
+
+static void
+ide_workbench_message_response (IdeWorkbench        *self,
+                                gint                 response_id,
+                                IdeWorkbenchMessage *message)
+{
+  g_assert (IDE_IS_WORKBENCH (self));
+  g_assert (IDE_IS_WORKBENCH_MESSAGE (message));
+
+  if (response_id == GTK_RESPONSE_CLOSE)
+    gtk_widget_hide (GTK_WIDGET (message));
+}
+
+void
+ide_workbench_push_message (IdeWorkbench        *self,
+                            IdeWorkbenchMessage *message)
+{
+  g_return_if_fail (IDE_IS_WORKBENCH (self));
+  g_return_if_fail (IDE_IS_WORKBENCH_MESSAGE (message));
+
+  g_signal_connect_object (message,
+                           "response",
+                           G_CALLBACK (ide_workbench_message_response),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  gtk_container_add (GTK_CONTAINER (self->message_box), GTK_WIDGET (message));
+}
+
+static void
+locate_widget_for_message_id (GtkWidget *widget,
+                              gpointer user_data)
+{
+  struct {
+    const gchar *id;
+    GtkWidget   *widget;
+  } *lookup = user_data;
+
+  if (IDE_IS_WORKBENCH_MESSAGE (widget))
+    {
+      const gchar *id;
+
+      id = ide_workbench_message_get_id (IDE_WORKBENCH_MESSAGE (widget));
+
+      if (g_strcmp0 (id, lookup->id) == 0)
+        lookup->widget = widget;
+    }
+}
+
+gboolean
+ide_workbench_pop_message (IdeWorkbench *self,
+                           const gchar  *message_id)
+{
+  struct {
+    const gchar *id;
+    GtkWidget   *widget;
+  } lookup = { message_id };
+
+  g_return_val_if_fail (IDE_IS_WORKBENCH (self), FALSE);
+  g_return_val_if_fail (message_id != NULL, FALSE);
+
+  gtk_container_foreach (GTK_CONTAINER (self->message_box),
+                         locate_widget_for_message_id,
+                         &lookup);
+
+  if (lookup.widget)
+    {
+      gtk_widget_destroy (lookup.widget);
+      return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/libide/workbench/ide-workbench.h b/libide/workbench/ide-workbench.h
index b1493c7..dbf5515 100644
--- a/libide/workbench/ide-workbench.h
+++ b/libide/workbench/ide-workbench.h
@@ -26,6 +26,7 @@
 #include "util/ide-uri.h"
 #include "workbench/ide-perspective.h"
 #include "workbench/ide-workbench-header-bar.h"
+#include "workbench/ide-workbench-message.h"
 
 G_BEGIN_DECLS
 
@@ -98,6 +99,10 @@ void                   ide_workbench_views_foreach                (IdeWorkbench
                                                                    GtkCallback             callback,
                                                                    gpointer                user_data);
 IdeWorkbenchHeaderBar *ide_workbench_get_headerbar                (IdeWorkbench           *self);
+void                   ide_workbench_push_message                 (IdeWorkbench           *self,
+                                                                   IdeWorkbenchMessage    *message);
+gboolean               ide_workbench_pop_message                  (IdeWorkbench           *self,
+                                                                   const gchar            *message_id);
 
 G_END_DECLS
 
diff --git a/libide/workbench/ide-workbench.ui b/libide/workbench/ide-workbench.ui
index b7ec8e5..876e80d 100644
--- a/libide/workbench/ide-workbench.ui
+++ b/libide/workbench/ide-workbench.ui
@@ -33,12 +33,28 @@
       <object class="GtkOverlay">
         <property name="visible">true</property>
         <child>
-          <object class="GtkStack" id="perspectives_stack">
-            <property name="hexpand">true</property>
-            <property name="homogeneous">false</property>
-            <property name="transition-type">crossfade</property>
-            <property name="transition-duration">333</property>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
             <property name="visible">true</property>
+            <child>
+              <object class="GtkBox" id="message_box">
+                <property name="orientation">vertical</property>
+                <property name="hexpand">false</property>
+                <property name="visible">true</property>
+                <style>
+                  <class name="message-box"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStack" id="perspectives_stack">
+                <property name="hexpand">true</property>
+                <property name="homogeneous">false</property>
+                <property name="transition-type">crossfade</property>
+                <property name="transition-duration">333</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
           </object>
         </child>
       </object>


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