summaryrefslogtreecommitdiff
path: root/src/widgets/notification-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/notification-widget.c')
-rw-r--r--src/widgets/notification-widget.c821
1 files changed, 0 insertions, 821 deletions
diff --git a/src/widgets/notification-widget.c b/src/widgets/notification-widget.c
deleted file mode 100644
index 97cfc22..0000000
--- a/src/widgets/notification-widget.c
+++ /dev/null
@@ -1,821 +0,0 @@
-#include "widgets/notification-widget.h"
-
-//
-// FoobarNotificationCloseAction:
-//
-// The action invoked when the user requests to "close" the notification. The notification is either marked as
-// "dismissed" and kept around or removed from the list.
-//
-
-G_DEFINE_ENUM_TYPE(
- FoobarNotificationCloseAction,
- foobar_notification_close_action,
- G_DEFINE_ENUM_VALUE( FOOBAR_TYPE_NOTIFICATION_CLOSE_ACTION_REMOVE, "remove" ),
- G_DEFINE_ENUM_VALUE( FOOBAR_TYPE_NOTIFICATION_CLOSE_ACTION_DISMISS, "dismiss" ) )
-
-//
-// FoobarNotificationWidget:
-//
-// Shared widget for displaying a notification. The widget also manages an inset/margin -- this is done to allow the
-// "close" button to extend into the margin area.
-//
-
-struct _FoobarNotificationWidget
-{
- GtkWidget parent_instance;
- GtkWidget* container;
- GtkWidget* content;
- GtkWidget* close_button;
- FoobarNotification* notification;
- FoobarNotificationCloseAction close_action;
- gchar* time_format;
- gint min_height;
- gint close_button_inset;
- gint inset_start;
- gint inset_end;
- gint inset_top;
- gint inset_bottom;
-};
-
-enum
-{
- PROP_NOTIFICATION = 1,
- PROP_CLOSE_ACTION,
- PROP_TIME_FORMAT,
- PROP_MIN_HEIGHT,
- PROP_CLOSE_BUTTON_INSET,
- PROP_INSET_START,
- PROP_INSET_END,
- PROP_INSET_TOP,
- PROP_INSET_BOTTOM,
- N_PROPS,
-};
-
-static GParamSpec* props[N_PROPS] = { 0 };
-
-static void foobar_notification_widget_class_init ( FoobarNotificationWidgetClass* klass );
-static void foobar_notification_widget_init ( FoobarNotificationWidget* self );
-static void foobar_notification_widget_get_property ( GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec );
-static void foobar_notification_widget_set_property ( GObject* object,
- guint prop_id,
- GValue const* value,
- GParamSpec* pspec );
-static void foobar_notification_widget_dispose ( GObject* object );
-static void foobar_notification_widget_finalize ( GObject* object );
-static void foobar_notification_widget_handle_enter ( GtkEventControllerMotion* controller,
- gdouble x,
- gdouble y,
- gpointer userdata );
-static void foobar_notification_widget_handle_leave ( GtkEventControllerMotion* controller,
- gpointer userdata );
-static void foobar_notification_widget_handle_close_clicked( GtkButton* button,
- gpointer userdata );
-static gchar* foobar_notification_widget_compute_time_label ( GtkExpression* expression,
- GDateTime* time,
- gchar const* format,
- gpointer userdata );
-static gboolean foobar_notification_widget_compute_icon_visible( GtkExpression* expression,
- GIcon* icon,
- gpointer userdata );
-static gboolean foobar_notification_widget_compute_body_visible( GtkExpression* expression,
- gchar const* body,
- gpointer userdata );
-static void foobar_notification_widget_update_margins ( FoobarNotificationWidget* self );
-
-G_DEFINE_FINAL_TYPE( FoobarNotificationWidget, foobar_notification_widget, GTK_TYPE_WIDGET )
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Widget Implementation
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Static initialization for notifications.
-//
-void foobar_notification_widget_class_init( FoobarNotificationWidgetClass* klass )
-{
- GtkWidgetClass* widget_klass = GTK_WIDGET_CLASS( klass );
- gtk_widget_class_set_layout_manager_type( widget_klass, GTK_TYPE_BIN_LAYOUT );
- gtk_widget_class_set_css_name( widget_klass, "notification" );
-
- GObjectClass* object_klass = G_OBJECT_CLASS( klass );
- object_klass->get_property = foobar_notification_widget_get_property;
- object_klass->set_property = foobar_notification_widget_set_property;
- object_klass->dispose = foobar_notification_widget_dispose;
- object_klass->finalize = foobar_notification_widget_finalize;
-
- props[PROP_NOTIFICATION] = g_param_spec_object(
- "notification",
- "Notification",
- "Content to display.",
- FOOBAR_TYPE_NOTIFICATION,
- G_PARAM_READWRITE );
- props[PROP_CLOSE_ACTION] = g_param_spec_enum(
- "close-action",
- "Close Action",
- "Action to execute when the notification is closed.",
- FOOBAR_TYPE_NOTIFICATION_CLOSE_ACTION,
- 0,
- G_PARAM_READWRITE );
- props[PROP_TIME_FORMAT] = g_param_spec_string(
- "time-format",
- "Time Format",
- "Time format used to display the notification's timestamp.",
- NULL,
- G_PARAM_READWRITE );
- props[PROP_MIN_HEIGHT] = g_param_spec_int(
- "min-height",
- "Minimum Height",
- "Minimum requested height for the notification itself.",
- 0,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- props[PROP_CLOSE_BUTTON_INSET] = g_param_spec_int(
- "close-button-inset",
- "Close Button Inset",
- "Offset of the close button within the notification (may be negative, possibly increasing the actual inset).",
- INT_MIN,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- props[PROP_INSET_START] = g_param_spec_int(
- "inset-start",
- "Inset Start",
- "Inset for the start edge of the widget.",
- 0,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- props[PROP_INSET_END] = g_param_spec_int(
- "inset-end",
- "Inset End",
- "Inset for the end edge of the widget.",
- 0,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- props[PROP_INSET_TOP] = g_param_spec_int(
- "inset-top",
- "Inset Top",
- "Inset for the top edge of the widget.",
- 0,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- props[PROP_INSET_BOTTOM] = g_param_spec_int(
- "inset-bottom",
- "Inset Bottom",
- "Inset for the bottom edge of the widget.",
- 0,
- INT_MAX,
- 0,
- G_PARAM_READWRITE );
- g_object_class_install_properties( object_klass, N_PROPS, props );
-}
-
-//
-// Instance initialization for notifications.
-//
-void foobar_notification_widget_init( FoobarNotificationWidget* self )
-{
- // Set up the main notification content.
-
- GtkWidget* icon = gtk_image_new( );
- gtk_widget_add_css_class( icon, "icon" );
- gtk_widget_set_valign( icon, GTK_ALIGN_CENTER );
-
- GtkWidget* title = gtk_label_new( NULL );
- gtk_label_set_justify( GTK_LABEL( title ), GTK_JUSTIFY_LEFT );
- gtk_label_set_ellipsize( GTK_LABEL( title ), PANGO_ELLIPSIZE_END );
- gtk_label_set_wrap( GTK_LABEL( title ), FALSE );
- gtk_label_set_xalign( GTK_LABEL( title ), 0 );
- gtk_widget_add_css_class( title, "title" );
- gtk_widget_set_valign( title, GTK_ALIGN_BASELINE_CENTER );
- gtk_widget_set_hexpand( title, TRUE );
-
- GtkWidget* time = gtk_label_new( NULL );
- gtk_label_set_wrap( GTK_LABEL( time ), FALSE );
- gtk_widget_add_css_class( time, "time" );
- gtk_widget_set_valign( time, GTK_ALIGN_BASELINE_CENTER );
-
- GtkWidget* body = gtk_label_new( NULL );
- gtk_label_set_use_markup( GTK_LABEL( body ), TRUE );
- gtk_label_set_justify( GTK_LABEL( body ), GTK_JUSTIFY_LEFT );
- gtk_label_set_ellipsize( GTK_LABEL( body ), PANGO_ELLIPSIZE_END );
- gtk_label_set_wrap( GTK_LABEL( body ), TRUE );
- gtk_label_set_wrap_mode( GTK_LABEL( body ), PANGO_WRAP_WORD_CHAR );
- // XXX: Increase once layout is fixed in GTK (https://gitlab.gnome.org/GNOME/gtk/-/issues/5885)
- gtk_label_set_lines( GTK_LABEL( body ), 1 );
- gtk_label_set_xalign( GTK_LABEL( body ), 0 );
- gtk_widget_add_css_class( body, "body" );
-
- GtkWidget* header = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
- gtk_box_append( GTK_BOX( header ), title );
- gtk_box_append( GTK_BOX( header ), time );
-
- GtkWidget* row = gtk_box_new( GTK_ORIENTATION_VERTICAL, 0 );
- gtk_box_append( GTK_BOX( row ), header );
- gtk_box_append( GTK_BOX( row ), body );
- gtk_widget_set_hexpand( row, TRUE );
- gtk_widget_set_valign( row, GTK_ALIGN_CENTER );
-
- self->content = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
- gtk_box_append( GTK_BOX( self->content ), icon );
- gtk_box_append( GTK_BOX( self->content ), row );
- gtk_widget_add_css_class( self->content, "content" );
-
- // Set up the overlay for the close button.
-
- GtkWidget* close_icon = gtk_image_new_from_icon_name( "fluent-dismiss-symbolic" );
- gtk_image_set_pixel_size( GTK_IMAGE( close_icon ), 12 );
-
- self->close_button = gtk_button_new( );
- gtk_button_set_child( GTK_BUTTON( self->close_button ), close_icon );
- gtk_widget_add_css_class( self->close_button, "close-button" );
- gtk_widget_set_visible( self->close_button, FALSE );
- gtk_widget_set_halign( self->close_button, GTK_ALIGN_END );
- gtk_widget_set_valign( self->close_button, GTK_ALIGN_START );
- g_signal_connect( self->close_button, "clicked", G_CALLBACK( foobar_notification_widget_handle_close_clicked ), self );
-
- GtkEventController* hover_controller = gtk_event_controller_motion_new( );
- g_signal_connect( hover_controller, "enter", G_CALLBACK( foobar_notification_widget_handle_enter ), self );
- g_signal_connect( hover_controller, "leave", G_CALLBACK( foobar_notification_widget_handle_leave ), self );
-
- self->container = gtk_overlay_new( );
- gtk_overlay_set_child( GTK_OVERLAY( self->container ), self->content );
- gtk_overlay_add_overlay( GTK_OVERLAY( self->container ), self->close_button );
- gtk_widget_add_controller( self->container, hover_controller );
- gtk_widget_set_parent( self->container, GTK_WIDGET( self ) );
-
- // Set up bindings.
-
- {
- GtkExpression* notification_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL, "notification" );
- GtkExpression* image_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION, notification_expr, "image" );
- gtk_expression_bind( gtk_expression_ref( image_expr ), icon, "gicon", self );
- GtkExpression* visible_params[] = { image_expr };
- GtkExpression* visible_expr = gtk_cclosure_expression_new(
- G_TYPE_BOOLEAN,
- NULL,
- G_N_ELEMENTS( visible_params ),
- visible_params,
- G_CALLBACK( foobar_notification_widget_compute_icon_visible ),
- NULL,
- NULL );
- gtk_expression_bind( visible_expr, icon, "visible", self );
- }
-
- {
- GtkExpression* notification_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL, "notification" );
- GtkExpression* summary_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION, notification_expr, "summary" );
- gtk_expression_bind( summary_expr, title, "label", self );
- }
-
- {
- GtkExpression* notification_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL, "notification" );
- GtkExpression* body_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION, notification_expr, "body" );
- gtk_expression_bind( gtk_expression_ref( body_expr ), body, "label", self );
- GtkExpression* visible_params[] = { body_expr };
- GtkExpression* visible_expr = gtk_cclosure_expression_new(
- G_TYPE_BOOLEAN,
- NULL,
- G_N_ELEMENTS( visible_params ),
- visible_params,
- G_CALLBACK( foobar_notification_widget_compute_body_visible ),
- NULL,
- NULL );
- gtk_expression_bind( visible_expr, body, "visible", self );
- }
-
- {
- GtkExpression* notification_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL, "notification" );
- GtkExpression* time_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION, notification_expr, "time" );
- GtkExpression* format_expr = gtk_property_expression_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL, "time-format" );
- GtkExpression* str_params[] = { time_expr, format_expr };
- GtkExpression* str_expr = gtk_cclosure_expression_new(
- G_TYPE_STRING,
- NULL,
- G_N_ELEMENTS( str_params ),
- str_params,
- G_CALLBACK( foobar_notification_widget_compute_time_label ),
- self,
- NULL );
- gtk_expression_bind( str_expr, time, "label", self );
- }
-}
-
-//
-// Property getter implementation, mapping a property id to a method.
-//
-void foobar_notification_widget_get_property(
- GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec )
-{
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)object;
-
- switch ( prop_id )
- {
- case PROP_NOTIFICATION:
- g_value_set_object( value, foobar_notification_widget_get_notification( self ) );
- break;
- case PROP_CLOSE_ACTION:
- g_value_set_enum( value, foobar_notification_widget_get_close_action( self ) );
- break;
- case PROP_TIME_FORMAT:
- g_value_set_string( value, foobar_notification_widget_get_time_format( self ) );
- break;
- case PROP_MIN_HEIGHT:
- g_value_set_int( value, foobar_notification_widget_get_min_height( self ) );
- break;
- case PROP_CLOSE_BUTTON_INSET:
- g_value_set_int( value, foobar_notification_widget_get_close_button_inset( self ) );
- break;
- case PROP_INSET_START:
- g_value_set_int( value, foobar_notification_widget_get_inset_start( self ) );
- break;
- case PROP_INSET_END:
- g_value_set_int( value, foobar_notification_widget_get_inset_end( self ) );
- break;
- case PROP_INSET_TOP:
- g_value_set_int( value, foobar_notification_widget_get_inset_top( self ) );
- break;
- case PROP_INSET_BOTTOM:
- g_value_set_int( value, foobar_notification_widget_get_inset_bottom( self ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Property setter implementation, mapping a property id to a method.
-//
-void foobar_notification_widget_set_property(
- GObject* object,
- guint prop_id,
- GValue const* value,
- GParamSpec* pspec )
-{
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)object;
-
- switch ( prop_id )
- {
- case PROP_NOTIFICATION:
- foobar_notification_widget_set_notification( self, g_value_get_object( value ) );
- break;
- case PROP_CLOSE_ACTION:
- foobar_notification_widget_set_close_action( self, g_value_get_enum( value ) );
- break;
- case PROP_TIME_FORMAT:
- foobar_notification_widget_set_time_format( self, g_value_get_string( value ) );
- break;
- case PROP_MIN_HEIGHT:
- foobar_notification_widget_set_min_height( self, g_value_get_int( value ) );
- break;
- case PROP_CLOSE_BUTTON_INSET:
- foobar_notification_widget_set_close_button_inset( self, g_value_get_int( value ) );
- break;
- case PROP_INSET_START:
- foobar_notification_widget_set_inset_start( self, g_value_get_int( value ) );
- break;
- case PROP_INSET_END:
- foobar_notification_widget_set_inset_end( self, g_value_get_int( value ) );
- break;
- case PROP_INSET_TOP:
- foobar_notification_widget_set_inset_top( self, g_value_get_int( value ) );
- break;
- case PROP_INSET_BOTTOM:
- foobar_notification_widget_set_inset_bottom( self, g_value_get_int( value ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Instance de-initialization for notifications.
-//
-void foobar_notification_widget_dispose( GObject* object )
-{
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)object;
-
- GtkWidget* child;
- while ( ( child = gtk_widget_get_first_child( GTK_WIDGET( self ) ) ) )
- {
- gtk_widget_unparent( child );
- }
-
- G_OBJECT_CLASS( foobar_notification_widget_parent_class )->dispose( object );
-}
-
-//
-// Instance cleanup for notifications.
-//
-void foobar_notification_widget_finalize( GObject* object )
-{
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)object;
-
- g_clear_object( &self->notification );
- g_clear_pointer( &self->time_format, g_free );
-
- G_OBJECT_CLASS( foobar_notification_widget_parent_class )->finalize( object );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Public API
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Create a new notification widget instance.
-//
-GtkWidget* foobar_notification_widget_new( void )
-{
- return g_object_new( FOOBAR_TYPE_NOTIFICATION_WIDGET, NULL );
-}
-
-//
-// Get the notification model currently displayed.
-//
-FoobarNotification* foobar_notification_widget_get_notification( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), NULL );
- return self->notification;
-}
-
-//
-// Get the action invoked when the user wants to "close" a notification.
-//
-FoobarNotificationCloseAction foobar_notification_widget_get_close_action( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->close_action;
-}
-
-//
-// Get the time format string used to display the notification's timestamp.
-//
-gchar const* foobar_notification_widget_get_time_format( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), NULL );
- return self->time_format;
-}
-
-//
-// Get the minimum height of the notification (excluding the inset).
-//
-gint foobar_notification_widget_get_min_height( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->min_height;
-}
-
-//
-// Get the offset of the close button within the notification (may be negative, possibly increasing the actual inset).
-//
-gint foobar_notification_widget_get_close_button_inset( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->close_button_inset;
-}
-
-//
-// Get the margin for the start edge of the notification.
-//
-gint foobar_notification_widget_get_inset_start( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->inset_start;
-}
-
-//
-// Get the margin for the end edge of the notification.
-//
-gint foobar_notification_widget_get_inset_end( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->inset_end;
-}
-
-//
-// Get the margin for the top edge of the notification.
-//
-gint foobar_notification_widget_get_inset_top( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->inset_top;
-}
-
-//
-// Get the margin for the bottom edge of the notification.
-//
-gint foobar_notification_widget_get_inset_bottom( FoobarNotificationWidget* self )
-{
- g_return_val_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ), 0 );
- return self->inset_bottom;
-}
-
-//
-// Update the notification model currently displayed.
-//
-void foobar_notification_widget_set_notification(
- FoobarNotificationWidget* self,
- FoobarNotification* value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- if ( self->notification != value )
- {
- g_clear_object( &self->notification );
- if ( value ) { self->notification = g_object_ref( value ); }
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_NOTIFICATION] );
- }
-}
-
-//
-// Update the action invoked when the user wants to "close" a notification.
-//
-void foobar_notification_widget_set_close_action(
- FoobarNotificationWidget* self,
- FoobarNotificationCloseAction value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- if ( self->close_action != value )
- {
- self->close_action = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_CLOSE_ACTION] );
- }
-}
-
-//
-// Update the time format string used to display the notification's timestamp.
-//
-void foobar_notification_widget_set_time_format(
- FoobarNotificationWidget* self,
- gchar const* value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- if ( g_strcmp0( self->time_format, value ) )
- {
- g_clear_pointer( &self->time_format, g_free );
- self->time_format = g_strdup( value );
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_TIME_FORMAT] );
- }
-}
-
-//
-// Update the minimum height of the notification (excluding the inset).
-//
-void foobar_notification_widget_set_min_height(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- value = MAX( value, 0 );
- if ( self->min_height != value )
- {
- self->min_height = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_MIN_HEIGHT] );
- gtk_widget_set_size_request( self->content, -1, self->min_height );
- }
-}
-
-//
-// Update the offset of the close button within the notification (may be negative, possibly increasing the actual inset).
-//
-void foobar_notification_widget_set_close_button_inset(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- if ( self->close_button_inset != value )
- {
- self->close_button_inset = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_CLOSE_BUTTON_INSET] );
- foobar_notification_widget_update_margins( self );
- }
-}
-
-//
-// Update the margin for the start edge of the notification.
-//
-void foobar_notification_widget_set_inset_start(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- value = MAX( value, 0 );
- if ( self->inset_start != value )
- {
- self->inset_start = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_START] );
- foobar_notification_widget_update_margins( self );
- }
-}
-
-//
-// Update the margin for the end edge of the notification.
-//
-void foobar_notification_widget_set_inset_end(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- value = MAX( value, 0 );
- if ( self->inset_end != value )
- {
- self->inset_end = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_END] );
- foobar_notification_widget_update_margins( self );
- }
-}
-
-//
-// Update the margin for the top edge of the notification.
-//
-void foobar_notification_widget_set_inset_top(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- value = MAX( value, 0 );
- if ( self->inset_top != value )
- {
- self->inset_top = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_TOP] );
- foobar_notification_widget_update_margins( self );
- }
-}
-
-//
-// Update the margin for the bottom edge of the notification.
-//
-void foobar_notification_widget_set_inset_bottom(
- FoobarNotificationWidget* self,
- gint value )
-{
- g_return_if_fail( FOOBAR_IS_NOTIFICATION_WIDGET( self ) );
-
- value = MAX( value, 0 );
- if ( self->inset_bottom != value )
- {
- self->inset_bottom = value;
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_BOTTOM] );
- foobar_notification_widget_update_margins( self );
- }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Signal Handlers
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Called when the mouse cursor enters the notification.
-//
-// We will temporarily block the dismissal timeout for the notification and show the close button.
-//
-void foobar_notification_widget_handle_enter(
- GtkEventControllerMotion* controller,
- gdouble x,
- gdouble y,
- gpointer userdata )
-{
- (void)controller;
- (void)x;
- (void)y;
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)userdata;
-
- gtk_widget_set_visible( self->close_button, TRUE );
- if ( self->notification ) { foobar_notification_block_timeout( self->notification ); }
-}
-
-//
-// Called when the mouse cursor leaves the notification.
-//
-// We will unblock the dismissal timeout for the notification and hide the close button.
-//
-void foobar_notification_widget_handle_leave(
- GtkEventControllerMotion* controller,
- gpointer userdata )
-{
- (void)controller;
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)userdata;
-
- gtk_widget_set_visible( self->close_button, FALSE );
- if ( self->notification ) { foobar_notification_resume_timeout( self->notification ); }
-}
-
-//
-// Called when the user has clicked the "close" button.
-//
-// This either marks the notification as dismissed or removes it.
-//
-void foobar_notification_widget_handle_close_clicked(
- GtkButton* button,
- gpointer userdata )
-{
- (void)button;
- FoobarNotificationWidget* self = (FoobarNotificationWidget*)userdata;
-
- if ( self->notification )
- {
- switch ( self->close_action )
- {
- case FOOBAR_TYPE_NOTIFICATION_CLOSE_ACTION_REMOVE:
- foobar_notification_close( self->notification );
- break;
- case FOOBAR_TYPE_NOTIFICATION_CLOSE_ACTION_DISMISS:
- foobar_notification_dismiss( self->notification );
- break;
- default:
- g_warn_if_reached( );
- break;
- }
- }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Value Converters
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Derive the timestamp label value from the notification's timestamp and the selected time format.
-//
-gchar* foobar_notification_widget_compute_time_label(
- GtkExpression* expression,
- GDateTime* time,
- gchar const* format,
- gpointer userdata )
-{
- (void)expression;
- (void)userdata;
-
- return format != NULL ? g_date_time_format( time, format ) : NULL;
-}
-
-//
-// Derive the visibility of the notification icon from its value.
-//
-gboolean foobar_notification_widget_compute_icon_visible(
- GtkExpression* expression,
- GIcon* icon,
- gpointer userdata )
-{
- (void)expression;
- (void)userdata;
-
- return icon != NULL;
-}
-
-//
-// Derive the visibility of the notification body label from its value.
-//
-gboolean foobar_notification_widget_compute_body_visible(
- GtkExpression* expression,
- gchar const* body,
- gpointer userdata )
-{
- (void)expression;
- (void)userdata;
-
- return body != NULL && g_strcmp0( body, "" );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Helper Methods
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Update the margins of the content widget and close button to the current inset values.
-//
-void foobar_notification_widget_update_margins( FoobarNotificationWidget* self )
-{
- gint inset = MAX( self->close_button_inset, 0 );
- gint overrun = MAX( -self->close_button_inset, 0 );
- gint actual_inset_end = MAX( self->inset_end, overrun );
- gint actual_inset_top = MAX( self->inset_top, overrun );
-
- gtk_widget_set_margin_start( self->container, self->inset_start );
- gtk_widget_set_margin_end( self->container, actual_inset_end - overrun );
- gtk_widget_set_margin_top( self->container, actual_inset_top - overrun );
- gtk_widget_set_margin_bottom( self->container, self->inset_bottom );
-
- gtk_widget_set_margin_end( self->content, overrun );
- gtk_widget_set_margin_top( self->content, overrun );
-
- gtk_widget_set_margin_end( self->close_button, inset );
- gtk_widget_set_margin_top( self->close_button, inset );
-}