gem-graph-client/libide/gui/ide-notification-view.c

291 lines
9.0 KiB
C

/* ide-notification-view.c
*
* Copyright 2018-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-notification-view"
#include "config.h"
#include <dazzle.h>
#include "ide-notification-view-private.h"
struct _IdeNotificationView
{
GtkBin parent_instance;
IdeNotification *notification;
DzlBindingGroup *bindings;
GtkLabel *label;
GtkBox *buttons;
GtkButton *default_button;
GtkImage *default_button_image;
};
G_DEFINE_FINAL_TYPE (IdeNotificationView, ide_notification_view, GTK_TYPE_BIN)
enum {
PROP_0,
PROP_NOTIFICATION,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
static void
ide_notification_view_notify_icon (IdeNotificationView *self,
GParamSpec *pspec,
IdeNotification *notif)
{
g_autoptr(GIcon) icon = NULL;
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_NOTIFICATION_VIEW (self));
g_assert (IDE_IS_NOTIFICATION (notif));
icon = ide_notification_ref_icon (notif);
gtk_image_set_from_gicon (self->default_button_image, icon, GTK_ICON_SIZE_MENU);
gtk_widget_set_visible (GTK_WIDGET (self->default_button), icon != NULL);
}
static void
connect_notification (IdeNotificationView *self,
IdeNotification *notification)
{
g_autofree gchar *action_name = NULL;
g_autoptr(GVariant) target_value = NULL;
guint n_buttons;
g_assert (IDE_IS_NOTIFICATION_VIEW (self));
g_assert (!notification || IDE_IS_NOTIFICATION (notification));
gtk_container_foreach (GTK_CONTAINER (self->buttons), (GtkCallback)gtk_widget_destroy, NULL);
if (notification == NULL)
{
gtk_widget_hide (GTK_WIDGET (self->label));
gtk_widget_hide (GTK_WIDGET (self->default_button));
gtk_widget_hide (GTK_WIDGET (self->buttons));
return;
}
g_signal_connect_object (notification,
"notify::icon",
G_CALLBACK (ide_notification_view_notify_icon),
self,
G_CONNECT_SWAPPED);
ide_notification_view_notify_icon (self, NULL, notification);
/*
* Setup the default action button (which is shown right after the label
* containing notification title).
*/
if (ide_notification_get_default_action (notification, &action_name, &target_value))
{
gtk_actionable_set_action_name (GTK_ACTIONABLE (self->default_button), action_name);
gtk_actionable_set_action_target_value (GTK_ACTIONABLE (self->default_button), target_value);
}
/*
* Now add all of the buttons requested by the notification.
*/
ide_object_lock (IDE_OBJECT (notification));
n_buttons = ide_notification_get_n_buttons (notification);
for (guint i = 0; i < n_buttons; i++)
{
g_autofree gchar *action = NULL;
g_autofree gchar *label = NULL;
g_autoptr(GIcon) button_icon = NULL;
g_autoptr(GVariant) target = NULL;
if (ide_notification_get_button (notification, i, &label, &button_icon, &action, &target) &&
button_icon != NULL &&
action_name != NULL)
{
GtkButton *button;
button = g_object_new (GTK_TYPE_BUTTON,
"child", g_object_new (GTK_TYPE_IMAGE,
"gicon", button_icon,
"visible", TRUE,
NULL),
"action-name", action,
"action-target", target,
"has-tooltip", TRUE,
"tooltip-text", label,
"visible", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (self->buttons), GTK_WIDGET (button));
}
}
ide_object_unlock (IDE_OBJECT (notification));
}
static void
ide_notification_view_finalize (GObject *object)
{
IdeNotificationView *self = (IdeNotificationView *)object;
g_assert (IDE_IS_MAIN_THREAD ());
g_clear_object (&self->bindings);
g_clear_object (&self->notification);
G_OBJECT_CLASS (ide_notification_view_parent_class)->finalize (object);
}
static void
ide_notification_view_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
IdeNotificationView *self = IDE_NOTIFICATION_VIEW (object);
switch (prop_id)
{
case PROP_NOTIFICATION:
g_value_set_object (value, ide_notification_view_get_notification (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_notification_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
IdeNotificationView *self = IDE_NOTIFICATION_VIEW (object);
switch (prop_id)
{
case PROP_NOTIFICATION:
ide_notification_view_set_notification (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_notification_view_class_init (IdeNotificationViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = ide_notification_view_finalize;
object_class->get_property = ide_notification_view_get_property;
object_class->set_property = ide_notification_view_set_property;
/**
* IdeNotificationView:notification:
*
* The "notification" property is the #IdeNotification to be displayed.
*
* Since: 3.32
*/
properties [PROP_NOTIFICATION] =
g_param_spec_object ("notification",
"Notification",
"The IdeNotification to be viewed",
IDE_TYPE_NOTIFICATION,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | 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/libide-gui/ui/ide-notification-view.ui");
gtk_widget_class_set_css_name (widget_class, "notification");
gtk_widget_class_bind_template_child (widget_class, IdeNotificationView, label);
gtk_widget_class_bind_template_child (widget_class, IdeNotificationView, buttons);
gtk_widget_class_bind_template_child (widget_class, IdeNotificationView, default_button);
gtk_widget_class_bind_template_child (widget_class, IdeNotificationView, default_button_image);
}
static void
ide_notification_view_init (IdeNotificationView *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->bindings = dzl_binding_group_new ();
dzl_binding_group_bind (self->bindings, "title", self->label, "label", G_BINDING_SYNC_CREATE);
}
/**
* ide_notification_view_new:
*
* Create a new #IdeNotificationView to visualize a notification within
* the #IdeOmniBar.
*
* Returns: (transfer full): a newly created #IdeNotificationView
*
* Since: 3.32
*/
GtkWidget *
ide_notification_view_new (void)
{
return g_object_new (IDE_TYPE_NOTIFICATION_VIEW, NULL);
}
/**
* ide_notification_view_get_notification:
* @self: an #IdeNotificationView
*
* Gets the #IdeNotification that is being viewed.
*
* Returns: (transfer none) (nullable): an #IdeNotification or %NULL
*
* Since: 3.32
*/
IdeNotification *
ide_notification_view_get_notification (IdeNotificationView *self)
{
g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
g_return_val_if_fail (IDE_IS_NOTIFICATION_VIEW (self), NULL);
return self->notification;
}
void
ide_notification_view_set_notification (IdeNotificationView *self,
IdeNotification *notification)
{
g_return_if_fail (IDE_IS_MAIN_THREAD ());
g_return_if_fail (IDE_IS_NOTIFICATION_VIEW (self));
g_return_if_fail (!notification || IDE_IS_NOTIFICATION (notification));
if (g_set_object (&self->notification, notification))
{
dzl_binding_group_set_source (self->bindings, notification);
connect_notification (self, notification);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_NOTIFICATION]);
}
}