[gnome-builder] terminal: add a runtime selection popover



commit dcb4c10fb7e292695e5f5f5bc5ce86fa74672703
Author: Christian Hergert <chergert redhat com>
Date:   Wed May 1 11:51:18 2019 -0700

    terminal: add a runtime selection popover
    
    This will be the basis for container selection for terminals.

 src/libide/terminal/ide-terminal-popover-row.c    | 110 +++++++++++
 src/libide/terminal/ide-terminal-popover-row.h    |  38 ++++
 src/libide/terminal/ide-terminal-popover-row.ui   |  28 +++
 src/libide/terminal/ide-terminal-popover.c        | 213 ++++++++++++++++++++++
 src/libide/terminal/ide-terminal-popover.h        |  33 ++++
 src/libide/terminal/ide-terminal-popover.ui       |  35 ++++
 src/libide/terminal/libide-terminal.gresource.xml |   2 +
 src/libide/terminal/meson.build                   |   4 +
 8 files changed, 463 insertions(+)
---
diff --git a/src/libide/terminal/ide-terminal-popover-row.c b/src/libide/terminal/ide-terminal-popover-row.c
new file mode 100644
index 000000000..5929d80e0
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover-row.c
@@ -0,0 +1,110 @@
+/* ide-terminal-popover-row.c
+ *
+ * Copyright 2019 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-terminal-popover-row"
+
+#include "config.h"
+
+#include "ide-terminal-popover-row.h"
+
+struct _IdeTerminalPopoverRow
+{
+  GtkListBoxRow  parent_instance;
+
+  IdeRuntime    *runtime;
+
+  GtkLabel      *label;
+  GtkImage      *check;
+};
+
+G_DEFINE_TYPE (IdeTerminalPopoverRow, ide_terminal_popover_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+ide_terminal_popover_row_finalize (GObject *object)
+{
+  IdeTerminalPopoverRow *self = (IdeTerminalPopoverRow *)object;
+
+  g_clear_object (&self->runtime);
+
+  G_OBJECT_CLASS (ide_terminal_popover_row_parent_class)->finalize (object);
+}
+
+static void
+ide_terminal_popover_row_class_init (IdeTerminalPopoverRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = ide_terminal_popover_row_finalize;
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-terminal/ui/ide-terminal-popover-row.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeTerminalPopoverRow, label);
+  gtk_widget_class_bind_template_child (widget_class, IdeTerminalPopoverRow, check);
+}
+
+static void
+ide_terminal_popover_row_init (IdeTerminalPopoverRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+ide_terminal_popover_row_new (IdeRuntime *runtime)
+{
+  IdeTerminalPopoverRow *self;
+
+  g_return_val_if_fail (IDE_IS_RUNTIME (runtime), NULL);
+
+  self = g_object_new (IDE_TYPE_TERMINAL_POPOVER_ROW,
+                       "visible", TRUE,
+                       NULL);
+  self->runtime = g_object_ref (runtime);
+  gtk_label_set_label (self->label, ide_runtime_get_display_name (runtime));
+
+  return GTK_WIDGET (g_steal_pointer (&self));
+}
+
+void
+ide_terminal_popover_row_set_selected (IdeTerminalPopoverRow *self,
+                                       gboolean               selected)
+{
+  g_return_if_fail (IDE_IS_TERMINAL_POPOVER_ROW (self));
+
+  /* Always keep image visible */
+  g_object_set (self->check,
+                "icon-name", selected ? "object-select-symbolic" : NULL,
+                NULL);
+}
+
+/**
+ * ide_terminal_popover_row_get_runtime:
+ * @self: a #IdeTerminalPopoverRow
+ *
+ * Gets the runtime for a row.
+ *
+ * Returns: (transfer none): an #IdeRuntime, or %NULL
+ */
+IdeRuntime *
+ide_terminal_popover_row_get_runtime (IdeTerminalPopoverRow *self)
+{
+  g_return_val_if_fail (IDE_IS_TERMINAL_POPOVER_ROW (self), NULL);
+
+  return self->runtime;
+}
diff --git a/src/libide/terminal/ide-terminal-popover-row.h b/src/libide/terminal/ide-terminal-popover-row.h
new file mode 100644
index 000000000..f44e6bd89
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover-row.h
@@ -0,0 +1,38 @@
+/* ide-terminal-popover-row.h
+ *
+ * Copyright 2019 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_TERMINAL_POPOVER_ROW (ide_terminal_popover_row_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeTerminalPopoverRow, ide_terminal_popover_row, IDE, TERMINAL_POPOVER_ROW, 
GtkListBoxRow)
+
+GtkWidget  *ide_terminal_popover_row_new          (IdeRuntime            *runtime);
+IdeRuntime *ide_terminal_popover_row_get_runtime  (IdeTerminalPopoverRow *self);
+void        ide_terminal_popover_row_set_selected (IdeTerminalPopoverRow *self,
+                                                   gboolean               selected);
+
+G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-popover-row.ui b/src/libide/terminal/ide-terminal-popover-row.ui
new file mode 100644
index 000000000..f89d8c524
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover-row.ui
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="IdeTerminalPopoverRow" parent="GtkListBoxRow">
+    <child>
+      <object class="GtkBox">
+        <property name="margin">6</property>
+        <property name="spacing">6</property>
+        <property name="orientation">horizontal</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="ellipsize">end</property>
+            <property name="visible">true</property>
+            <property name="use-markup">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage" id="check">
+            <property name="visible">true</property>
+            <property name="pixel-size">16</property>
+            <property name="height-request">16</property>
+            <property name="width-request">16</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/libide/terminal/ide-terminal-popover.c b/src/libide/terminal/ide-terminal-popover.c
new file mode 100644
index 000000000..885edac38
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover.c
@@ -0,0 +1,213 @@
+/* ide-terminal-popover.c
+ *
+ * Copyright 2019 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-terminal-popover"
+
+#include "config.h"
+
+#include <dazzle.h>
+#include <libide-foundry.h>
+#include <libide-gui.h>
+
+#include "ide-terminal-popover.h"
+#include "ide-terminal-popover-row.h"
+
+struct _IdeTerminalPopover
+{
+  GtkPopover          parent_instance;
+
+  DzlListModelFilter *filter;
+  gchar              *selected;
+
+  /* Template widgets */
+  GtkSearchEntry     *search_entry;
+  GtkListBox         *list_box;
+};
+
+G_DEFINE_TYPE (IdeTerminalPopover, ide_terminal_popover, GTK_TYPE_POPOVER)
+
+static void
+ide_terminal_popover_update_selected_cb (GtkWidget *widget,
+                                         gpointer   user_data)
+{
+  IdeTerminalPopoverRow *row = (IdeTerminalPopoverRow *)widget;
+  IdeRuntime *runtime = user_data;
+  gboolean selected;
+
+  g_assert (IDE_IS_TERMINAL_POPOVER_ROW (row));
+  g_assert (IDE_IS_RUNTIME (runtime));
+
+  selected = runtime == ide_terminal_popover_row_get_runtime (row);
+  ide_terminal_popover_row_set_selected (row, selected);
+}
+
+static void
+ide_terminal_popover_row_activated_cb (IdeTerminalPopover    *self,
+                                       IdeTerminalPopoverRow *row,
+                                       GtkListBox            *list_box)
+{
+  IdeRuntime *runtime;
+
+  g_assert (IDE_IS_TERMINAL_POPOVER (self));
+  g_assert (IDE_IS_TERMINAL_POPOVER_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  runtime = ide_terminal_popover_row_get_runtime (row);
+
+  g_free (self->selected);
+  self->selected = g_strdup (ide_runtime_get_id (runtime));
+
+  gtk_container_foreach (GTK_CONTAINER (self->list_box),
+                         ide_terminal_popover_update_selected_cb,
+                         runtime);
+}
+
+static GtkWidget *
+ide_terminal_popover_create_row_cb (gpointer item,
+                                    gpointer user_data)
+{
+  IdeRuntime *runtime = item;
+  IdeTerminalPopover *self = user_data;
+  GtkWidget *row = ide_terminal_popover_row_new (runtime);
+
+  if (ide_str_equal0 (ide_runtime_get_id (runtime), self->selected))
+    ide_terminal_popover_row_set_selected (IDE_TERMINAL_POPOVER_ROW (row), TRUE);
+  else
+    ide_terminal_popover_row_set_selected (IDE_TERMINAL_POPOVER_ROW (row), FALSE);
+
+  return row;
+}
+
+static gboolean
+ide_terminal_popover_filter_func (GObject  *item,
+                                  gpointer  user_data)
+{
+  DzlPatternSpec *spec = user_data;
+  IdeRuntime *runtime = IDE_RUNTIME (item);
+  const gchar *str;
+
+  str = ide_runtime_get_id (runtime);
+  if (dzl_pattern_spec_match (spec, str))
+    return TRUE;
+
+  str = ide_runtime_get_category (runtime);
+  if (dzl_pattern_spec_match (spec, str))
+    return TRUE;
+
+  str = ide_runtime_get_display_name (runtime);
+  if (dzl_pattern_spec_match (spec, str))
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+ide_terminal_popover_search_changed_cb (IdeTerminalPopover *self,
+                                        GtkSearchEntry     *entry)
+{
+  const gchar *text;
+
+  g_assert (IDE_IS_TERMINAL_POPOVER (self));
+  g_assert (GTK_IS_SEARCH_ENTRY (entry));
+
+  if (self->filter == NULL)
+    return;
+
+  text = gtk_entry_get_text (GTK_ENTRY (entry));
+  if (ide_str_empty0 (text))
+    text = NULL;
+
+  dzl_list_model_filter_set_filter_func (self->filter,
+                                         ide_terminal_popover_filter_func,
+                                         dzl_pattern_spec_new (text),
+                                         (GDestroyNotify) dzl_pattern_spec_unref);
+}
+
+static void
+ide_terminal_popover_context_set_cb (GtkWidget  *widget,
+                                     IdeContext *context)
+{
+  IdeTerminalPopover *self = (IdeTerminalPopover *)widget;
+  IdeRuntimeManager *runtime_manager;
+  IdeConfigManager *config_manager;
+  IdeConfig *config;
+
+  g_assert (IDE_IS_TERMINAL_POPOVER (self));
+  g_assert (!context || IDE_IS_CONTEXT (context));
+
+  if (context == NULL)
+    return;
+
+  config_manager = ide_config_manager_from_context (context);
+  config = ide_config_manager_get_current (config_manager);
+  runtime_manager = ide_runtime_manager_from_context (context);
+
+  if (config != NULL)
+    {
+      g_free (self->selected);
+      self->selected = g_strdup (ide_config_get_runtime_id (config));
+    }
+
+  g_clear_object (&self->filter);
+  self->filter = dzl_list_model_filter_new (G_LIST_MODEL (runtime_manager));
+
+  gtk_list_box_bind_model (self->list_box,
+                           G_LIST_MODEL (self->filter),
+                           ide_terminal_popover_create_row_cb,
+                           self, NULL);
+}
+
+static void
+ide_terminal_popover_class_init (IdeTerminalPopoverClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-terminal/ui/ide-terminal-popover.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeTerminalPopover, list_box);
+  gtk_widget_class_bind_template_child (widget_class, IdeTerminalPopover, search_entry);
+}
+
+static void
+ide_terminal_popover_init (IdeTerminalPopover *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  self->selected = g_strdup ("host");
+
+  ide_widget_set_context_handler (self, ide_terminal_popover_context_set_cb);
+
+  g_signal_connect_object (self->search_entry,
+                           "changed",
+                           G_CALLBACK (ide_terminal_popover_search_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->list_box,
+                           "row-activated",
+                           G_CALLBACK (ide_terminal_popover_row_activated_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+GtkWidget *
+ide_terminal_popover_new (void)
+{
+  return g_object_new (IDE_TYPE_TERMINAL_POPOVER, NULL);
+}
diff --git a/src/libide/terminal/ide-terminal-popover.h b/src/libide/terminal/ide-terminal-popover.h
new file mode 100644
index 000000000..168c84282
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover.h
@@ -0,0 +1,33 @@
+/* ide-terminal-popover.h
+ *
+ * Copyright 2019 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_TERMINAL_POPOVER (ide_terminal_popover_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeTerminalPopover, ide_terminal_popover, IDE, TERMINAL_POPOVER, GtkPopover)
+
+GtkWidget *ide_terminal_popover_new (void);
+
+G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-popover.ui b/src/libide/terminal/ide-terminal-popover.ui
new file mode 100644
index 000000000..b6e19e64b
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-popover.ui
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="IdeTerminalPopover" parent="GtkPopover">
+    <child>
+      <object class="GtkBox">
+        <property name="margin">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkSearchEntry" id="search_entry">
+            <property name="placeholder-text" translatable="yes">Search runtimes</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="propagate-natural-width">true</property>
+            <property name="propagate-natural-height">true</property>
+            <property name="max-content-height">350</property>
+            <property name="max-content-width">400</property>
+            <property name="min-content-width">400</property>
+            <property name="shadow-type">in</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkListBox" id="list_box">
+                <property name="visible">true</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/libide/terminal/libide-terminal.gresource.xml 
b/src/libide/terminal/libide-terminal.gresource.xml
index a8623ac95..25622585b 100644
--- a/src/libide/terminal/libide-terminal.gresource.xml
+++ b/src/libide/terminal/libide-terminal.gresource.xml
@@ -5,6 +5,8 @@
   </gresource>
   <gresource prefix="/org/gnome/libide-terminal/ui">
     <file preprocess="xml-stripblanks">ide-terminal-page.ui</file>
+    <file preprocess="xml-stripblanks">ide-terminal-popover.ui</file>
+    <file preprocess="xml-stripblanks">ide-terminal-popover-row.ui</file>
     <file preprocess="xml-stripblanks">ide-terminal-search.ui</file>
     <file preprocess="xml-stripblanks">ide-terminal-surface.ui</file>
     <file preprocess="xml-stripblanks">ide-terminal-workspace.ui</file>
diff --git a/src/libide/terminal/meson.build b/src/libide/terminal/meson.build
index 2de76e0bd..5f2bd6b66 100644
--- a/src/libide/terminal/meson.build
+++ b/src/libide/terminal/meson.build
@@ -27,6 +27,8 @@ install_headers(libide_terminal_public_headers, subdir: libide_terminal_header_s
 libide_terminal_private_headers = [
   'ide-terminal-page-actions.h',
   'ide-terminal-page-private.h',
+  'ide-terminal-popover.h',
+  'ide-terminal-popover-row.h',
   'ide-terminal-private.h',
   'ide-terminal-search-private.h',
 ]
@@ -43,6 +45,8 @@ libide_terminal_public_sources = [
 
 libide_terminal_private_sources = [
   'ide-terminal-page-actions.c',
+  'ide-terminal-popover.c',
+  'ide-terminal-popover-row.c',
 ]
 
 #


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