[gnome-builder] libide/gtk: add IdeInstallButton
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide/gtk: add IdeInstallButton
- Date: Tue, 23 Aug 2022 01:06:02 +0000 (UTC)
commit 36c3b37dc0e836c6af154000fbe74fe69ea0adca
Author: Christian Hergert <chergert redhat com>
Date: Mon Aug 22 17:56:32 2022 -0700
libide/gtk: add IdeInstallButton
This is meant to be similar to the install button we had in previous
versions of Builder. Just a stack w/ two buttons and progress shown
at the bottom.
Surely we can do nicer things, but this will get us by for now.
src/libide/gtk/ide-gtk-init.c | 2 +
src/libide/gtk/ide-install-button.c | 291 ++++++++++++++++++++++++++++++++
src/libide/gtk/ide-install-button.h | 44 +++++
src/libide/gtk/ide-install-button.ui | 43 +++++
src/libide/gtk/libide-gtk.gresource.xml | 2 +
src/libide/gtk/libide-gtk.h | 1 +
src/libide/gtk/meson.build | 2 +
src/libide/gtk/style.css | 10 ++
src/libide/gui/ide-application.c | 1 +
9 files changed, 396 insertions(+)
---
diff --git a/src/libide/gtk/ide-gtk-init.c b/src/libide/gtk/ide-gtk-init.c
index ef758fec2..d6a798939 100644
--- a/src/libide/gtk/ide-gtk-init.c
+++ b/src/libide/gtk/ide-gtk-init.c
@@ -29,6 +29,7 @@
#include "ide-file-chooser-entry.h"
#include "ide-gtk-private.h"
#include "ide-enum-object.h"
+#include "ide-install-button.h"
#include "ide-progress-icon.h"
#include "ide-radio-box.h"
#include "ide-scrubber-revealer.h"
@@ -44,6 +45,7 @@ _ide_gtk_init (void)
g_type_ensure (IDE_TYPE_ENUM_OBJECT);
g_type_ensure (IDE_TYPE_ENTRY_POPOVER);
g_type_ensure (IDE_TYPE_FILE_CHOOSER_ENTRY);
+ g_type_ensure (IDE_TYPE_INSTALL_BUTTON);
g_type_ensure (IDE_TYPE_PROGRESS_ICON);
g_type_ensure (IDE_TYPE_RADIO_BOX);
g_type_ensure (IDE_TYPE_SCRUBBER_REVEALER);
diff --git a/src/libide/gtk/ide-install-button.c b/src/libide/gtk/ide-install-button.c
new file mode 100644
index 000000000..a3fda105a
--- /dev/null
+++ b/src/libide/gtk/ide-install-button.c
@@ -0,0 +1,291 @@
+/* ide-install-button.c
+ *
+ * Copyright 2022 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-install-button"
+
+#include "config.h"
+
+#include "ide-install-button.h"
+
+struct _IdeInstallButton
+{
+ GtkWidget parent_instance;
+
+ GCancellable *cancellable;
+ IdeNotification *notification;
+
+ GtkStack *stack;
+ GtkButton *install;
+ GtkButton *cancel;
+ GtkCssProvider *css;
+
+ guint disposed : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ N_PROPS
+};
+
+enum {
+ CANCEL,
+ INSTALL,
+ N_SIGNALS
+};
+
+G_DEFINE_FINAL_TYPE (IdeInstallButton, ide_install_button, GTK_TYPE_WIDGET)
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+progress_changed_cb (IdeInstallButton *self,
+ GParamSpec *pspec,
+ IdeNotification *notif)
+{
+ g_autofree gchar *css = NULL;
+ double progress;
+ guint percentage;
+
+ g_assert (IDE_IS_INSTALL_BUTTON (self));
+ g_assert (IDE_IS_NOTIFICATION (notif));
+
+ progress = ide_notification_get_progress (notif);
+ percentage = CLAMP (progress * 100., .0, 100.);
+
+ if (percentage == 0)
+ css = g_strdup (".install-progress { background-size: 0; }");
+ else if (percentage == 100)
+ css = g_strdup (".install-progress { background-size: 100%; }");
+ else
+ css = g_strdup_printf (".install-progress { background-size: %u%%; }", percentage);
+
+ gtk_css_provider_load_from_data (self->css, css, -1);
+
+ if (progress >= 1.)
+ {
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->notification);
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->install));
+ }
+}
+
+static void
+install_clicked_cb (IdeInstallButton *self,
+ GtkButton *button)
+{
+ g_assert (IDE_IS_INSTALL_BUTTON (self));
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->notification);
+
+ self->cancellable = g_cancellable_new ();
+ self->notification = ide_notification_new ();
+
+ g_signal_connect_object (self->notification,
+ "notify::progress",
+ G_CALLBACK (progress_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_emit (self, signals [INSTALL], 0, self->notification, self->cancellable);
+
+ if (self->notification != NULL)
+ progress_changed_cb (self, NULL, self->notification);
+}
+
+static void
+cancel_clicked_cb (IdeInstallButton *self,
+ GtkButton *button)
+{
+ g_assert (IDE_IS_INSTALL_BUTTON (self));
+
+ g_signal_emit (self, signals [CANCEL], 0, self->notification, self->cancellable);
+}
+
+static void
+real_install (IdeInstallButton *self,
+ IdeNotification *notification,
+ GCancellable *cancellable)
+{
+ g_assert (IDE_IS_INSTALL_BUTTON (self));
+ g_assert (IDE_IS_NOTIFICATION (notification));
+ g_assert (G_IS_CANCELLABLE (cancellable));
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->cancel));
+}
+
+static void
+real_cancel (IdeInstallButton *self,
+ IdeNotification *notification,
+ GCancellable *cancellable)
+{
+ g_assert (IDE_IS_INSTALL_BUTTON (self));
+ g_assert (IDE_IS_NOTIFICATION (notification));
+ g_assert (G_IS_CANCELLABLE (cancellable));
+
+ g_cancellable_cancel (cancellable);
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->notification);
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->install));
+}
+
+static void
+ide_install_button_dispose (GObject *object)
+{
+ IdeInstallButton *self = (IdeInstallButton *)object;
+ GtkWidget *child;
+
+ self->disposed = TRUE;
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->notification);
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
+ gtk_widget_unparent (child);
+
+ G_OBJECT_CLASS (ide_install_button_parent_class)->dispose (object);
+}
+
+static void
+ide_install_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeInstallButton *self = IDE_INSTALL_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ g_value_set_string (value, ide_install_button_get_label (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_install_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeInstallButton *self = IDE_INSTALL_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ ide_install_button_set_label (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_install_button_class_init (IdeInstallButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ide_install_button_dispose;
+ object_class->get_property = ide_install_button_get_property;
+ object_class->set_property = ide_install_button_set_property;
+
+ properties [PROP_LABEL] =
+ g_param_spec_string ("label", NULL, NULL,
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ signals [INSTALL] =
+ g_signal_new_class_handler ("install",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK (real_install),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 2, IDE_TYPE_NOTIFICATION, G_TYPE_CANCELLABLE);
+
+ signals [CANCEL] =
+ g_signal_new_class_handler ("cancel",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK (real_cancel),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 2, IDE_TYPE_NOTIFICATION, G_TYPE_CANCELLABLE);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/libide-gtk/ide-install-button.ui");
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+ gtk_widget_class_bind_template_child (widget_class, IdeInstallButton, cancel);
+ gtk_widget_class_bind_template_child (widget_class, IdeInstallButton, css);
+ gtk_widget_class_bind_template_child (widget_class, IdeInstallButton, install);
+ gtk_widget_class_bind_template_child (widget_class, IdeInstallButton, stack);
+ gtk_widget_class_bind_template_callback (widget_class, install_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cancel_clicked_cb);
+}
+
+static void
+ide_install_button_init (IdeInstallButton *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (self->cancel)),
+ GTK_STYLE_PROVIDER (self->css),
+ G_MAXINT);
+}
+
+const char *
+ide_install_button_get_label (IdeInstallButton *self)
+{
+ g_return_val_if_fail (IDE_IS_INSTALL_BUTTON (self), NULL);
+
+ return gtk_button_get_label (self->install);
+}
+
+void
+ide_install_button_set_label (IdeInstallButton *self,
+ const char *label)
+{
+ g_return_if_fail (IDE_IS_INSTALL_BUTTON (self));
+
+ gtk_button_set_label (self->install, label);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LABEL]);
+}
+
+void
+ide_install_button_cancel (IdeInstallButton *self)
+{
+ g_return_if_fail (IDE_IS_INSTALL_BUTTON (self));
+
+ if (self->disposed)
+ return;
+
+ if (gtk_stack_get_visible_child (self->stack) == GTK_WIDGET (self->cancel))
+ gtk_widget_activate (GTK_WIDGET (self->cancel));
+}
diff --git a/src/libide/gtk/ide-install-button.h b/src/libide/gtk/ide-install-button.h
new file mode 100644
index 000000000..52bc31f95
--- /dev/null
+++ b/src/libide/gtk/ide-install-button.h
@@ -0,0 +1,44 @@
+/* ide-install-button.h
+ *
+ * Copyright 2022 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-core.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_INSTALL_BUTTON (ide_install_button_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdeInstallButton, ide_install_button, IDE, INSTALL_BUTTON, GtkWidget)
+
+IDE_AVAILABLE_IN_ALL
+GtkWidget *ide_install_button_new (void);
+IDE_AVAILABLE_IN_ALL
+void ide_install_button_cancel (IdeInstallButton *self);
+IDE_AVAILABLE_IN_ALL
+const char *ide_install_button_get_label (IdeInstallButton *self);
+IDE_AVAILABLE_IN_ALL
+void ide_install_button_set_label (IdeInstallButton *self,
+ const char *label);
+
+G_END_DECLS
diff --git a/src/libide/gtk/ide-install-button.ui b/src/libide/gtk/ide-install-button.ui
new file mode 100644
index 000000000..433525989
--- /dev/null
+++ b/src/libide/gtk/ide-install-button.ui
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="IdeInstallButton" parent="GtkWidget">
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hhomogeneous">true</property>
+ <property name="vhomogeneous">true</property>
+ <property name="transition-type">crossfade</property>
+ <child>
+ <object class="GtkStackPage" id="install_page">
+ <property name="child">
+ <object class="GtkButton" id="install">
+ <style>
+ <class name="text-button"/>
+ </style>
+ <property name="label" translatable="yes">_Install</property>
+ <property name="use-underline">true</property>
+ <signal name="clicked" handler="install_clicked_cb" swapped="true"
object="IdeInstallButton"/>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage" id="cancel_page">
+ <property name="child">
+ <object class="GtkButton" id="cancel">
+ <style>
+ <class name="text-button"/>
+ <class name="install-progress"/>
+ </style>
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use-underline">true</property>
+ <signal name="clicked" handler="cancel_clicked_cb" swapped="true" object="IdeInstallButton"/>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkCssProvider" id="css">
+ </object>
+</interface>
diff --git a/src/libide/gtk/libide-gtk.gresource.xml b/src/libide/gtk/libide-gtk.gresource.xml
index 167fa8a18..fad9cc4f3 100644
--- a/src/libide/gtk/libide-gtk.gresource.xml
+++ b/src/libide/gtk/libide-gtk.gresource.xml
@@ -2,8 +2,10 @@
<gresources>
<gresource prefix="/org/gnome/libide-gtk">
<file preprocess="xml-stripblanks">ide-entry-popover.ui</file>
+ <file preprocess="xml-stripblanks">ide-install-button.ui</file>
<file preprocess="xml-stripblanks">ide-search-entry.ui</file>
<file preprocess="xml-stripblanks">ide-shortcut-accel-dialog.ui</file>
<file preprocess="xml-stripblanks">icons/enter-keyboard-shortcut.svg</file>
+ <file>style.css</file>
</gresource>
</gresources>
diff --git a/src/libide/gtk/libide-gtk.h b/src/libide/gtk/libide-gtk.h
index 21e326545..598bff738 100644
--- a/src/libide/gtk/libide-gtk.h
+++ b/src/libide/gtk/libide-gtk.h
@@ -29,6 +29,7 @@
# include "ide-font-description.h"
# include "ide-gtk.h"
# include "ide-gtk-enums.h"
+# include "ide-install-button.h"
# include "ide-joined-menu.h"
# include "ide-menu-manager.h"
# include "ide-progress-icon.h"
diff --git a/src/libide/gtk/meson.build b/src/libide/gtk/meson.build
index 037aebca8..d850c89a9 100644
--- a/src/libide/gtk/meson.build
+++ b/src/libide/gtk/meson.build
@@ -14,6 +14,7 @@ libide_gtk_public_headers = [
'ide-file-manager.h',
'ide-font-description.h',
'ide-gtk.h',
+ 'ide-install-button.h',
'ide-joined-menu.h',
'ide-menu-manager.h',
'ide-progress-icon.h',
@@ -45,6 +46,7 @@ libide_gtk_public_sources = [
'ide-file-manager.c',
'ide-font-description.c',
'ide-gtk.c',
+ 'ide-install-button.c',
'ide-joined-menu.c',
'ide-menu-manager.c',
'ide-progress-icon.c',
diff --git a/src/libide/gtk/style.css b/src/libide/gtk/style.css
new file mode 100644
index 000000000..d2e4e67c3
--- /dev/null
+++ b/src/libide/gtk/style.css
@@ -0,0 +1,10 @@
+.install-progress {
+ background-image: linear-gradient(to top, @accent_bg_color 2px, alpha(@accent_bg_color, 0) 2px);
+ background-repeat: no-repeat;
+ background-position: 0 bottom;
+ transition: none;
+ background-size: 0;
+}
+.install-progress:dir(rtl) {
+ background-position: 100% bottom;
+}
diff --git a/src/libide/gui/ide-application.c b/src/libide/gui/ide-application.c
index 76f24d725..9242c90bf 100644
--- a/src/libide/gui/ide-application.c
+++ b/src/libide/gui/ide-application.c
@@ -567,6 +567,7 @@ ide_application_init (IdeApplication *self)
ide_application_load_typelibs (self);
/* Ensure our core data is loaded early. */
+ _ide_application_add_resources (self, "resource:///org/gnome/libide-gtk/");
_ide_application_add_resources (self, "resource:///org/gnome/libide-tweaks/");
_ide_application_add_resources (self, "resource:///org/gnome/libide-sourceview/");
_ide_application_add_resources (self, "resource:///org/gnome/libide-gui/");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]