[gnome-builder/wip/chergert/headerbar] omnibar: implement configuration row widget



commit dc2095d36e1dbbaa71181594064993451fee4f32
Author: Christian Hergert <chergert redhat com>
Date:   Thu Jun 23 16:45:15 2016 -0700

    omnibar: implement configuration row widget

 libide/Makefile.am                    |    2 +
 libide/resources/libide.gresource.xml |    1 +
 libide/workbench/ide-omni-bar-row.c   |  235 +++++++++++++++++++++++++++++++++
 libide/workbench/ide-omni-bar-row.h   |   39 ++++++
 libide/workbench/ide-omni-bar-row.ui  |  117 ++++++++++++++++
 libide/workbench/ide-omni-bar.c       |   88 ++++++++++---
 libide/workbench/ide-omni-bar.ui      |    1 +
 7 files changed, 465 insertions(+), 18 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index ad06fb2..3504cac 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -412,6 +412,8 @@ libide_1_0_la_SOURCES =                                   \
        workbench/ide-layout-tab-bar.h                    \
        workbench/ide-layout-tab.c                        \
        workbench/ide-layout-tab.h                        \
+       workbench/ide-omni-bar-row.c                      \
+       workbench/ide-omni-bar-row.h                      \
        workbench/ide-perspective-menu-button.c           \
        workbench/ide-perspective-menu-button.h           \
        workbench/ide-workbench-actions.c                 \
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index c74c021..dfb2536 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -62,6 +62,7 @@
     <file compressed="true" alias="ide-layout-pane.ui">../workbench/ide-layout-pane.ui</file>
     <file compressed="true" alias="ide-layout-stack.ui">../workbench/ide-layout-stack.ui</file>
     <file compressed="true" alias="ide-omni-bar.ui">../workbench/ide-omni-bar.ui</file>
+    <file compressed="true" alias="ide-omni-bar-row.ui">../workbench/ide-omni-bar-row.ui</file>
     <file compressed="true" alias="ide-omni-search-group.ui">../search/ide-omni-search-group.ui</file>
     <file compressed="true" alias="ide-omni-search-row.ui">../search/ide-omni-search-row.ui</file>
     <file compressed="true" 
alias="ide-perspective-menu-button.ui">../workbench/ide-perspective-menu-button.ui</file>
diff --git a/libide/workbench/ide-omni-bar-row.c b/libide/workbench/ide-omni-bar-row.c
new file mode 100644
index 0000000..111b82d
--- /dev/null
+++ b/libide/workbench/ide-omni-bar-row.c
@@ -0,0 +1,235 @@
+/* ide-omni-bar-row.c
+ *
+ * Copyright (C) 2016 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-omni-bar-row"
+
+#include "devices/ide-device.h"
+#include "runtimes/ide-runtime.h"
+#include "workbench/ide-omni-bar-row.h"
+
+struct _IdeOmniBarRow
+{
+  GtkListBoxRow     parent_instance;
+
+  IdeConfiguration *item;
+
+  GtkLabel         *title;
+  GtkLabel         *device_title;
+  GtkLabel         *runtime_title;
+  GtkGrid          *grid;
+  GtkImage         *checked;
+  GtkButton        *button;
+};
+
+enum {
+  PROP_0,
+  PROP_ITEM,
+  N_PROPS
+};
+
+G_DEFINE_TYPE (IdeOmniBarRow, ide_omni_bar_row, GTK_TYPE_LIST_BOX_ROW)
+
+static GParamSpec *properties [N_PROPS];
+
+/**
+ * ide_omni_bar_row_get_item:
+ *
+ * Returns: (transfer none): An #IdeConfiguration.
+ */
+IdeConfiguration *
+ide_omni_bar_row_get_item (IdeOmniBarRow *self)
+{
+  g_return_val_if_fail (IDE_IS_OMNI_BAR_ROW (self), NULL);
+
+  return self->item;
+}
+
+static void
+on_runtime_changed (IdeOmniBarRow    *self,
+                    GParamSpec       *pspec,
+                    IdeConfiguration *config)
+{
+  const gchar *display_name = NULL;
+  IdeRuntime *runtime;
+
+  g_assert (IDE_IS_OMNI_BAR_ROW (self));
+  g_assert (IDE_IS_CONFIGURATION (config));
+
+  if (NULL != (runtime = ide_configuration_get_runtime (config)))
+    display_name = ide_runtime_get_display_name (runtime);
+
+  gtk_label_set_label (self->runtime_title, display_name);
+}
+
+static void
+on_device_changed (IdeOmniBarRow    *self,
+                   GParamSpec       *pspec,
+                   IdeConfiguration *config)
+{
+  const gchar *display_name = NULL;
+  IdeDevice *device;
+
+  g_assert (IDE_IS_OMNI_BAR_ROW (self));
+  g_assert (IDE_IS_CONFIGURATION (config));
+
+  if (NULL != (device = ide_configuration_get_device (config)))
+    display_name = ide_device_get_display_name (device);
+
+  gtk_label_set_label (self->device_title, display_name);
+}
+
+static void
+ide_omni_bar_row_set_item (IdeOmniBarRow    *self,
+                           IdeConfiguration *item)
+{
+  g_return_if_fail (IDE_IS_OMNI_BAR_ROW (self));
+  g_return_if_fail (IDE_IS_CONFIGURATION (item));
+
+  if (g_set_object (&self->item, item))
+    {
+      g_object_bind_property (self->item, "display-name",
+                              self->title, "label",
+                              G_BINDING_SYNC_CREATE);
+
+      g_signal_connect_object (self->item,
+                               "notify::runtime",
+                               G_CALLBACK (on_runtime_changed),
+                               self,
+                               G_CONNECT_SWAPPED);
+
+      g_signal_connect_object (self->item,
+                               "notify::device",
+                               G_CALLBACK (on_device_changed),
+                               self,
+                               G_CONNECT_SWAPPED);
+
+      on_runtime_changed (self, NULL, item);
+      on_device_changed (self, NULL, item);
+    }
+}
+
+static void
+ide_omni_bar_row_finalize (GObject *object)
+{
+  IdeOmniBarRow *self = (IdeOmniBarRow *)object;
+
+  g_clear_object (&self->item);
+
+  G_OBJECT_CLASS (ide_omni_bar_row_parent_class)->finalize (object);
+}
+
+static void
+ide_omni_bar_row_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  IdeOmniBarRow *self = IDE_OMNI_BAR_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ITEM:
+      g_value_set_object (value, self->item);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_omni_bar_row_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  IdeOmniBarRow *self = IDE_OMNI_BAR_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ITEM:
+      ide_omni_bar_row_set_item (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_omni_bar_row_class_init (IdeOmniBarRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = ide_omni_bar_row_finalize;
+  object_class->get_property = ide_omni_bar_row_get_property;
+  object_class->set_property = ide_omni_bar_row_set_property;
+
+  properties [PROP_ITEM] =
+    g_param_spec_object ("item",
+                         "Item",
+                         "The configuration item to view",
+                         IDE_TYPE_CONFIGURATION,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 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-omni-bar-row.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, button);
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, checked);
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, grid);
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, title);
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, device_title);
+  gtk_widget_class_bind_template_child (widget_class, IdeOmniBarRow, runtime_title);
+}
+
+static void
+ide_omni_bar_row_init (IdeOmniBarRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+ide_omni_bar_row_new (IdeConfiguration *item)
+{
+  g_return_val_if_fail (IDE_IS_CONFIGURATION (item), NULL);
+
+  return g_object_new (IDE_TYPE_OMNI_BAR_ROW,
+                       "item", item,
+                       NULL);
+}
+
+/**
+ * ide_omni_bar_row_set_active:
+ *
+ * Sets this row as the currently active build configuration.
+ * Doing so will expand extra information on the row.
+ */
+void
+ide_omni_bar_row_set_active (IdeOmniBarRow *self,
+                             gboolean       active)
+{
+  g_return_if_fail (IDE_IS_OMNI_BAR_ROW (self));
+
+  active = !!active;
+
+  gtk_widget_set_visible (GTK_WIDGET (self->grid), active);
+  gtk_widget_set_visible (GTK_WIDGET (self->button), active);
+  gtk_widget_set_visible (GTK_WIDGET (self->checked), active);
+}
diff --git a/libide/workbench/ide-omni-bar-row.h b/libide/workbench/ide-omni-bar-row.h
new file mode 100644
index 0000000..89b9ab7
--- /dev/null
+++ b/libide/workbench/ide-omni-bar-row.h
@@ -0,0 +1,39 @@
+/* ide-omni-bar-row.h
+ *
+ * Copyright (C) 2016 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_OMNI_BAR_ROW_H
+#define IDE_OMNI_BAR_ROW_H
+
+#include <gtk/gtk.h>
+
+#include "buildsystem/ide-configuration.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_OMNI_BAR_ROW (ide_omni_bar_row_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeOmniBarRow, ide_omni_bar_row, IDE, OMNI_BAR_ROW, GtkListBoxRow)
+
+GtkWidget        *ide_omni_bar_row_new        (IdeConfiguration *configuration);
+IdeConfiguration *ide_omni_bar_row_get_item   (IdeOmniBarRow    *self);
+void              ide_omni_bar_row_set_active (IdeOmniBarRow    *self,
+                                               gboolean          active);
+
+G_END_DECLS
+
+#endif /* IDE_OMNI_BAR_ROW_H */
diff --git a/libide/workbench/ide-omni-bar-row.ui b/libide/workbench/ide-omni-bar-row.ui
new file mode 100644
index 0000000..ba35f71
--- /dev/null
+++ b/libide/workbench/ide-omni-bar-row.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="IdeOmniBarRow" parent="GtkListBoxRow">
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <property name="spacing">3</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkBox">
+            <property name="spacing">6</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkLabel" id="title">
+                <property name="visible">true</property>
+                <property name="xalign">0.0</property>
+                <attributes>
+                  <attribute name="scale" value="0.833333"/>
+                </attributes>
+              </object>
+            </child>
+            <child>
+              <object class="GtkImage" id="checked">
+                <property name="icon-name">object-select-symbolic</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="button">
+                <property name="halign">end</property>
+                <property name="hexpand">true</property>
+                <style>
+                  <class name="image-button"/>
+                  <class name="flat"/>
+                </style>
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">emblem-system-symbolic</property>
+                    <property name="visible">true</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid">
+            <property name="margin-start">6</property>
+            <property name="column-spacing">6</property>
+            <property name="row-spacing">3</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">true</property>
+                <property name="label" translatable="yes">Device</property>
+                <property name="xalign">1.0</property>
+                <attributes>
+                  <attribute name="scale" value=".7"/>
+                </attributes>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="top-attach">0</property>
+                <property name="left-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="device_title">
+                <property name="visible">true</property>
+                <property name="hexpand">true</property>
+                <property name="xalign">0.0</property>
+                <attributes>
+                  <attribute name="scale" value=".7"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="top-attach">0</property>
+                <property name="left-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">true</property>
+                <property name="label" translatable="yes">Runtime</property>
+                <property name="xalign">1.0</property>
+                <attributes>
+                  <attribute name="scale" value=".7"/>
+                </attributes>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="top-attach">1</property>
+                <property name="left-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="runtime_title">
+                <property name="visible">true</property>
+                <property name="hexpand">true</property>
+                <property name="xalign">0.0</property>
+                <attributes>
+                  <attribute name="scale" value=".7"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="top-attach">1</property>
+                <property name="left-attach">1</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/libide/workbench/ide-omni-bar.c b/libide/workbench/ide-omni-bar.c
index bc8a307..da97050 100644
--- a/libide/workbench/ide-omni-bar.c
+++ b/libide/workbench/ide-omni-bar.c
@@ -25,10 +25,12 @@
 
 #include "buildsystem/ide-build-result.h"
 #include "buildsystem/ide-configuration.h"
+#include "buildsystem/ide-configuration-manager.h"
 #include "projects/ide-project.h"
 #include "util/ide-gtk.h"
 #include "vcs/ide-vcs.h"
 #include "workbench/ide-omni-bar.h"
+#include "workbench/ide-omni-bar-row.h"
 
 #define LOOPER_INTERVAL_SECONDS 5
 
@@ -66,27 +68,13 @@ create_configuration_row (gpointer item,
                           gpointer user_data)
 {
   IdeConfiguration *configuration = item;
-  IdeOmniBar *self = user_data;
-  GtkListBoxRow *row;
-  GtkLabel *label;
 
   g_assert (IDE_IS_CONFIGURATION (configuration));
-  g_assert (IDE_IS_OMNI_BAR (self));
-
-  row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
-                      "visible", TRUE,
-                      NULL);
 
-  label = g_object_new (GTK_TYPE_LABEL,
-                        "xalign", 0.0f,
-                        "visible", TRUE,
-                        NULL);
-  g_object_bind_property (configuration, "display-name",
-                          label, "label",
-                          G_BINDING_SYNC_CREATE);
-  gtk_container_add (GTK_CONTAINER (row), GTK_WIDGET (label));
-
-  return GTK_WIDGET (row);
+  return g_object_new (IDE_TYPE_OMNI_BAR_ROW,
+                       "item", configuration,
+                       "visible", TRUE,
+                       NULL);
 }
 
 static void
@@ -118,6 +106,56 @@ ide_omni_bar_update (IdeOmniBar *self)
 }
 
 static void
+ide_omni_bar_select_current_config (GtkWidget *widget,
+                                    gpointer   user_data)
+{
+  IdeConfiguration *current = user_data;
+  IdeOmniBarRow *row = (IdeOmniBarRow *)widget;
+
+  g_assert (IDE_IS_OMNI_BAR_ROW (row));
+  g_assert (IDE_IS_CONFIGURATION (current));
+
+  ide_omni_bar_row_set_active (row, (current == ide_omni_bar_row_get_item (row)));
+}
+
+static void
+ide_omni_bar_current_changed (IdeOmniBar              *self,
+                              GParamSpec              *pspec,
+                              IdeConfigurationManager *config_manager)
+{
+  IdeConfiguration *current;
+
+  g_assert (IDE_IS_OMNI_BAR (self));
+  g_assert (IDE_IS_CONFIGURATION_MANAGER (config_manager));
+
+  current = ide_configuration_manager_get_current (config_manager);
+
+  gtk_container_foreach (GTK_CONTAINER (self->popover_configuration_list_box),
+                         ide_omni_bar_select_current_config,
+                         current);
+}
+
+static void
+ide_omni_bar_row_activated (IdeOmniBar    *self,
+                            IdeOmniBarRow *row,
+                            GtkListBox    *list_box)
+{
+  IdeConfiguration *config;
+  IdeConfigurationManager *config_manager;
+  IdeContext *context;
+
+  g_assert (IDE_IS_OMNI_BAR (self));
+  g_assert (IDE_IS_OMNI_BAR_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  context = ide_widget_get_context (GTK_WIDGET (self));
+  config_manager = ide_context_get_configuration_manager (context);
+  config = ide_omni_bar_row_get_item (row);
+
+  ide_configuration_manager_set_current (config_manager, config);
+}
+
+static void
 ide_omni_bar_context_set (GtkWidget  *widget,
                           IdeContext *context)
 {
@@ -167,6 +205,14 @@ ide_omni_bar_context_set (GtkWidget  *widget,
                                create_configuration_row,
                                self,
                                NULL);
+
+      g_signal_connect_object (configs,
+                               "notify::current",
+                               G_CALLBACK (ide_omni_bar_current_changed),
+                               self,
+                               G_CONNECT_SWAPPED);
+
+      ide_omni_bar_current_changed (self, NULL, configs);
     }
 
   IDE_EXIT;
@@ -418,6 +464,12 @@ ide_omni_bar_init (IdeOmniBar *self)
                                    self,
                                    G_CONNECT_SWAPPED);
 
+  g_signal_connect_object (self->popover_configuration_list_box,
+                           "row-activated",
+                           G_CALLBACK (ide_omni_bar_row_activated),
+                           self,
+                           G_CONNECT_SWAPPED);
+
   ide_widget_set_context_handler (self, ide_omni_bar_context_set);
 }
 
diff --git a/libide/workbench/ide-omni-bar.ui b/libide/workbench/ide-omni-bar.ui
index 7920731..0fdfc1a 100644
--- a/libide/workbench/ide-omni-bar.ui
+++ b/libide/workbench/ide-omni-bar.ui
@@ -210,6 +210,7 @@
                 <property name="visible">true</property>
                 <child>
                   <object class="GtkListBox" id="popover_configuration_list_box">
+                    <property name="selection-mode">none</property>
                     <property name="visible">true</property>
                   </object>
                 </child>


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