[gnome-builder/wip/chergert/sysprof: 14/18] header-bar: add IdeRunButton to the headerbar



commit 48682022d6ff0d01f682aa7ccac7b177804c4594
Author: Christian Hergert <chergert redhat com>
Date:   Mon Aug 22 18:40:38 2016 -0700

    header-bar: add IdeRunButton to the headerbar
    
    This tracks the various ways we can run the project, and ensures they can
    be selected from the headerbar.

 data/theme/shared.css                        |    5 +
 libide/Makefile.am                           |    2 +
 libide/resources/libide.gresource.xml        |    1 +
 libide/runner/ide-run-button.c               |  259 ++++++++++++++++++++++++++
 libide/runner/ide-run-button.h               |   34 ++++
 libide/runner/ide-run-button.ui              |   70 +++++++
 libide/workbench/ide-workbench-header-bar.ui |    9 +
 libide/workbench/ide-workbench.c             |    6 +
 8 files changed, 386 insertions(+), 0 deletions(-)
---
diff --git a/data/theme/shared.css b/data/theme/shared.css
index 705dcb7..92d723e 100644
--- a/data/theme/shared.css
+++ b/data/theme/shared.css
@@ -231,3 +231,8 @@ textview border.left {
 treeview.dim-label {
   color: alpha(currentColor, 0.5);
 }
+
+
+button.run-arrow-button {
+  min-width: 12px;
+}
diff --git a/libide/Makefile.am b/libide/Makefile.am
index ae65160..94e709c 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -89,6 +89,7 @@ libide_1_0_la_public_headers =                            \
        projects/ide-project-miner.h                      \
        projects/ide-project.h                            \
        projects/ide-recent-projects.h                    \
+       runner/ide-run-button.h                           \
        runner/ide-run-manager.h                          \
        runner/ide-runner.h                               \
        runner/ide-runner-addin.h                         \
@@ -240,6 +241,7 @@ libide_1_0_la_public_sources =                            \
        projects/ide-project-miner.c                      \
        projects/ide-project.c                            \
        projects/ide-recent-projects.c                    \
+       runner/ide-run-button.c                           \
        runner/ide-run-manager.c                          \
        runner/ide-runner.c                               \
        runner/ide-runner-addin.c                         \
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index 63254ca..ecf67b7 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -75,6 +75,7 @@
     <file compressed="true" 
alias="ide-preferences-perspective.ui">../preferences/ide-preferences-perspective.ui</file>
     <file compressed="true" 
alias="ide-preferences-spin-button.ui">../preferences/ide-preferences-spin-button.ui</file>
     <file compressed="true" alias="ide-preferences-switch.ui">../preferences/ide-preferences-switch.ui</file>
+    <file compressed="true" alias="ide-run-button.ui">../runner/ide-run-button.ui</file>
     <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>
diff --git a/libide/runner/ide-run-button.c b/libide/runner/ide-run-button.c
new file mode 100644
index 0000000..d16f043
--- /dev/null
+++ b/libide/runner/ide-run-button.c
@@ -0,0 +1,259 @@
+/* ide-run-button.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-run-button"
+
+#include <glib/gi18n.h>
+
+#include "ide-context.h"
+#include "ide-debug.h"
+
+#include "runner/ide-run-button.h"
+#include "runner/ide-run-manager.h"
+#include "runner/ide-run-manager-private.h"
+#include "util/ide-gtk.h"
+
+struct _IdeRunButton
+{
+  GtkBox         parent_instance;
+
+  GtkSizeGroup  *accel_size_group;
+  GtkButton     *button;
+  GtkImage      *button_image;
+  GtkListBox    *list_box;
+  GtkMenuButton *menu_button;
+  GtkPopover    *popover;
+  GtkButton     *stop_button;
+};
+
+G_DEFINE_TYPE (IdeRunButton, ide_run_button, GTK_TYPE_BOX)
+
+static GtkWidget *
+create_row (const IdeRunHandlerInfo *info,
+            IdeRunButton            *self)
+{
+  GtkListBoxRow *row;
+  GtkLabel *label;
+  GtkImage *image;
+  GtkBox *box;
+
+  g_assert (info != NULL);
+  g_assert (IDE_IS_RUN_BUTTON (self));
+
+  row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+                      "can-focus", FALSE,
+                      "selectable", FALSE,
+                      "visible", TRUE,
+                      NULL);
+
+  g_object_set_data_full (G_OBJECT (row), "IDE_RUN_HANDLER_ID", g_strdup (info->id), g_free);
+
+  box = g_object_new (GTK_TYPE_BOX,
+                      "visible", TRUE,
+                      NULL);
+  gtk_container_add (GTK_CONTAINER (row), GTK_WIDGET (box));
+
+  image = g_object_new (GTK_TYPE_IMAGE,
+                        "hexpand", FALSE,
+                        "icon-name", info->icon_name,
+                        "visible", TRUE,
+                        NULL);
+  gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (image));
+
+  label = g_object_new (GTK_TYPE_LABEL,
+                        "label", info->title,
+                        "hexpand", TRUE,
+                        "xalign", 0.0f,
+                        "visible", TRUE,
+                        NULL);
+  gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (label));
+
+  if (info->accel != NULL)
+    {
+      g_autofree gchar *xaccel = NULL;
+      guint accel_key = 0;
+      GdkModifierType accel_mod = 0;
+
+      gtk_accelerator_parse (info->accel, &accel_key, &accel_mod);
+      xaccel = gtk_accelerator_get_label (accel_key, accel_mod);
+      label = g_object_new (GTK_TYPE_LABEL,
+                            "label", xaccel,
+                            "margin-start", 20,
+                            "visible", TRUE,
+                            "xalign", 0.0f,
+                            NULL);
+      ide_widget_add_style_class (GTK_WIDGET (label), "dim-label");
+      gtk_container_add_with_properties (GTK_CONTAINER (box), GTK_WIDGET (label),
+                                         "pack-type", GTK_PACK_END,
+                                         NULL);
+      gtk_size_group_add_widget (self->accel_size_group, GTK_WIDGET (label));
+    }
+
+  return GTK_WIDGET (row);
+}
+
+static void
+ide_run_button_clear (IdeRunButton *self)
+{
+  g_assert (IDE_IS_RUN_BUTTON (self));
+
+  gtk_container_foreach (GTK_CONTAINER (self->list_box), (GtkCallback)gtk_widget_destroy, NULL);
+}
+
+static void
+ide_run_button_handler_set (IdeRunButton  *self,
+                            GParamSpec    *pspec,
+                            IdeRunManager *run_manager)
+{
+  const GList *list;
+  const GList *iter;
+  const gchar *handler;
+
+  g_assert (IDE_IS_RUN_BUTTON (self));
+  g_assert (IDE_IS_RUN_MANAGER (run_manager));
+
+  handler = ide_run_manager_get_handler (run_manager);
+  list = _ide_run_manager_get_handlers (run_manager);
+
+  for (iter = list; iter; iter = iter->next)
+    {
+      const IdeRunHandlerInfo *info = iter->data;
+
+      if (g_strcmp0 (info->id, handler) == 0)
+        {
+          g_object_set (self->button_image,
+                        "icon-name", info->icon_name,
+                        NULL);
+          g_object_set (self->button,
+                        "tooltip-text", info->title,
+                        NULL);
+          break;
+        }
+    }
+}
+
+static void
+ide_run_button_load (IdeRunButton *self,
+                     IdeContext   *context)
+{
+  IdeRunManager *run_manager;
+  const GList *list;
+  const GList *iter;
+
+  g_assert (IDE_IS_RUN_BUTTON (self));
+  g_assert (IDE_IS_CONTEXT (context));
+
+  run_manager = ide_context_get_run_manager (context);
+  list = _ide_run_manager_get_handlers (run_manager);
+
+  for (iter = list; iter; iter = iter->next)
+    {
+      const IdeRunHandlerInfo *info = iter->data;
+      GtkWidget *row;
+
+      row = create_row (info, self);
+
+      gtk_container_add (GTK_CONTAINER (self->list_box), row);
+    }
+
+  g_object_bind_property (run_manager, "busy", self->button, "visible",
+                          G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+  g_object_bind_property (run_manager, "busy", self->stop_button, "visible",
+                          G_BINDING_SYNC_CREATE);
+
+  g_signal_connect_object (run_manager,
+                           "notify::handler",
+                           G_CALLBACK (ide_run_button_handler_set),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  ide_run_button_handler_set (self, NULL, run_manager);
+}
+
+static void
+ide_run_button_row_activated (IdeRunButton  *self,
+                              GtkListBoxRow *row,
+                              GtkListBox    *list_box)
+{
+  IdeContext *context;
+  const gchar *id;
+
+  g_assert (IDE_IS_RUN_BUTTON (self));
+  g_assert (GTK_IS_LIST_BOX_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  context = ide_widget_get_context (GTK_WIDGET (self));
+  id = g_object_get_data (G_OBJECT (row), "IDE_RUN_HANDLER_ID");
+
+  if (id != NULL && context != NULL)
+    {
+      IdeRunManager *run_manager;
+
+      /* First change the run action to the selected handler. */
+      run_manager = ide_context_get_run_manager (context);
+      ide_run_manager_set_handler (run_manager, id);
+      gtk_widget_hide (GTK_WIDGET (self->popover));
+
+      /* Now run the action */
+      ide_widget_action (GTK_WIDGET (self), "run-manager", "run-with-handler", g_variant_new_string (id));
+    }
+}
+
+static void
+ide_run_button_context_set (GtkWidget  *widget,
+                            IdeContext *context)
+{
+  IdeRunButton *self = (IdeRunButton *)widget;
+
+  g_assert (IDE_IS_RUN_BUTTON (self));
+  g_assert (!context || IDE_IS_CONTEXT (context));
+
+  ide_run_button_clear (self);
+
+  if (context != NULL)
+    ide_run_button_load (self, context);
+}
+
+static void
+ide_run_button_class_init (IdeRunButtonClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-run-button.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, accel_size_group);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, button);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, button_image);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, list_box);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, menu_button);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, popover);
+  gtk_widget_class_bind_template_child (widget_class, IdeRunButton, stop_button);
+}
+
+static void
+ide_run_button_init (IdeRunButton *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (self->list_box,
+                           "row-activated",
+                           G_CALLBACK (ide_run_button_row_activated),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  ide_widget_set_context_handler (self, ide_run_button_context_set);
+}
diff --git a/libide/runner/ide-run-button.h b/libide/runner/ide-run-button.h
new file mode 100644
index 0000000..94f99cd
--- /dev/null
+++ b/libide/runner/ide-run-button.h
@@ -0,0 +1,34 @@
+/* ide-run-button.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_RUN_BUTTON_H
+#define IDE_RUN_BUTTON_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_RUN_BUTTON (ide_run_button_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeRunButton, ide_run_button, IDE, RUN_BUTTON, GtkBox)
+
+GtkWidget *ide_run_button_new (void);
+
+G_END_DECLS
+
+#endif /* IDE_RUN_BUTTON_H */
diff --git a/libide/runner/ide-run-button.ui b/libide/runner/ide-run-button.ui
new file mode 100644
index 0000000..e1c287d
--- /dev/null
+++ b/libide/runner/ide-run-button.ui
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <object class="GtkPopover" id="popover">
+    <style>
+      <class name="popover-selector"/>
+    </style>
+    <child>
+      <object class="GtkListBox" id="list_box">
+        <property name="visible">true</property>
+      </object>
+    </child>
+  </object>
+  <template class="IdeRunButton" parent="GtkBox">
+    <property name="orientation">horizontal</property>
+    <style>
+      <class name="linked"/>
+    </style>
+    <child>
+      <object class="GtkButton" id="button">
+        <property name="action-name">run-manager.run</property>
+        <property name="focus-on-click">false</property>
+        <property name="visible">true</property>
+        <style>
+          <class name="image-button"/>
+        </style>
+        <child>
+          <object class="GtkImage" id="button_image">
+            <property name="icon-name">media-playback-start-symbolic</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkButton" id="stop_button">
+        <property name="action-name">run-manager.stop</property>
+        <property name="focus-on-click">false</property>
+        <style>
+          <class name="image-button"/>
+        </style>
+        <child>
+          <object class="GtkImage">
+            <property name="icon-name">media-playback-stop-symbolic</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuButton" id="menu_button">
+        <property name="focus-on-click">false</property>
+        <property name="popover">popover</property>
+        <property name="visible">true</property>
+        <style>
+          <class name="image-button"/>
+          <class name="run-arrow-button"/>
+        </style>
+        <child>
+          <object class="GtkImage" id="menu_button_image">
+            <property name="icon-name">pan-down-symbolic</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+  <object class="GtkSizeGroup" id="accel_size_group">
+    <property name="mode">horizontal</property>
+  </object>
+</interface>
diff --git a/libide/workbench/ide-workbench-header-bar.ui b/libide/workbench/ide-workbench-header-bar.ui
index 87ac0eb..4d4b0e4 100644
--- a/libide/workbench/ide-workbench-header-bar.ui
+++ b/libide/workbench/ide-workbench-header-bar.ui
@@ -25,6 +25,15 @@
         <property name="spacing">30</property>
         <property name="visible">true</property>
         <child>
+          <object class="IdeRunButton">
+            <property name="visible">true</property>
+          </object>
+          <packing>
+            <property name="priority">0</property>
+            <property name="pack-type">start</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkMenuButton" id="menu_button">
             <property name="tooltip-text" translatable="yes">Show workbench menu</property>
             <property name="focus-on-click">false</property>
diff --git a/libide/workbench/ide-workbench.c b/libide/workbench/ide-workbench.c
index 3b1419e..189b685 100644
--- a/libide/workbench/ide-workbench.c
+++ b/libide/workbench/ide-workbench.c
@@ -568,6 +568,7 @@ ide_workbench_set_context (IdeWorkbench *self,
 {
   g_autoptr(GSettings) settings = NULL;
   IdeBuildManager *build_manager;
+  IdeRunManager *run_manager;
   IdeProject *project;
   guint delay_msec;
 
@@ -592,6 +593,11 @@ ide_workbench_set_context (IdeWorkbench *self,
                                   "build-manager",
                                   G_ACTION_GROUP (build_manager));
 
+  run_manager = ide_context_get_run_manager (context);
+  gtk_widget_insert_action_group (GTK_WIDGET (self),
+                                  "run-manager",
+                                  G_ACTION_GROUP (run_manager));
+
   self->addins = peas_extension_set_new (peas_engine_get_default (),
                                          IDE_TYPE_WORKBENCH_ADDIN,
                                          NULL);


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