diff options
Diffstat (limited to 'src/widgets/inset-container.c')
| -rw-r--r-- | src/widgets/inset-container.c | 363 |
1 files changed, 0 insertions, 363 deletions
diff --git a/src/widgets/inset-container.c b/src/widgets/inset-container.c deleted file mode 100644 index 052f872..0000000 --- a/src/widgets/inset-container.c +++ /dev/null @@ -1,363 +0,0 @@ -#include "widgets/inset-container.h" - -// -// FoobarInsetContainer: -// -// A custom widget which renders a child with an inset/padding. -// -// Notably, it also supports negative inset values which is useful in order to provide uniform spacing between widgets. -// - -struct _FoobarInsetContainer -{ - GtkWidget parent_instance; - GtkWidget* child; - gint inset_horizontal; - gint inset_vertical; -}; - -enum -{ - PROP_CHILD = 1, - PROP_INSET_HORIZONTAL, - PROP_INSET_VERTICAL, - N_PROPS, -}; - -static GParamSpec* props[N_PROPS] = { 0 }; - -static void foobar_inset_container_class_init ( FoobarInsetContainerClass* klass ); -static void foobar_inset_container_init ( FoobarInsetContainer* self ); -static void foobar_inset_container_get_property ( GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ); -static void foobar_inset_container_set_property ( GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ); -static void foobar_inset_container_dispose ( GObject* object ); -static GtkSizeRequestMode foobar_inset_container_get_request_mode( GtkWidget* widget ); -static void foobar_inset_container_measure ( GtkWidget* widget, - GtkOrientation orientation, - int for_size, - int* minimum, - int* natural, - int* minimum_baseline, - int* natural_baseline ); -static void foobar_inset_container_size_allocate ( GtkWidget* widget, - int width, - int height, - int baseline ); - -G_DEFINE_FINAL_TYPE( FoobarInsetContainer, foobar_inset_container, GTK_TYPE_WIDGET ) - -// --------------------------------------------------------------------------------------------------------------------- -// Widget Implementation -// --------------------------------------------------------------------------------------------------------------------- - -// -// Static initialization for inset containers. -// -void foobar_inset_container_class_init( FoobarInsetContainerClass* klass ) -{ - GtkWidgetClass* widget_klass = GTK_WIDGET_CLASS( klass ); - widget_klass->get_request_mode = foobar_inset_container_get_request_mode; - widget_klass->measure = foobar_inset_container_measure; - widget_klass->size_allocate = foobar_inset_container_size_allocate; - gtk_widget_class_set_css_name( widget_klass, "inset-container" ); - - GObjectClass* object_klass = G_OBJECT_CLASS( klass ); - object_klass->get_property = foobar_inset_container_get_property; - object_klass->set_property = foobar_inset_container_set_property; - object_klass->dispose = foobar_inset_container_dispose; - - props[PROP_CHILD] = g_param_spec_object( - "child", - "Child", - "Child widget for the panel item.", - GTK_TYPE_WIDGET, - G_PARAM_READWRITE ); - props[PROP_INSET_HORIZONTAL] = g_param_spec_int( - "inset-horizontal", - "Inset Horizontal", - "The horizontal offset (may be negative).", - INT_MIN, - INT_MAX, - 0, - G_PARAM_READWRITE ); - props[PROP_INSET_VERTICAL] = g_param_spec_int( - "inset-vertical", - "Inset Vertical", - "The vertical offset (may be negative).", - INT_MIN, - INT_MAX, - 0, - G_PARAM_READWRITE ); - g_object_class_install_properties( object_klass, N_PROPS, props ); -} - -// -// Instance initialization for inset containers. -// -void foobar_inset_container_init( FoobarInsetContainer* self ) -{ - (void)self; -} - -// -// Property getter implementation, mapping a property id to a method. -// -void foobar_inset_container_get_property( - GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)object; - - switch ( prop_id ) - { - case PROP_CHILD: - g_value_set_object( value, foobar_inset_container_get_child( self ) ); - break; - case PROP_INSET_HORIZONTAL: - g_value_set_int( value, foobar_inset_container_get_inset_horizontal( self ) ); - break; - case PROP_INSET_VERTICAL: - g_value_set_int( value, foobar_inset_container_get_inset_vertical( 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_inset_container_set_property( - GObject* object, - guint prop_id, - GValue const* value, - GParamSpec* pspec ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)object; - - switch ( prop_id ) - { - case PROP_CHILD: - foobar_inset_container_set_child( self, g_value_get_object( value ) ); - break; - case PROP_INSET_HORIZONTAL: - foobar_inset_container_set_inset_horizontal( self, g_value_get_int( value ) ); - break; - case PROP_INSET_VERTICAL: - foobar_inset_container_set_inset_vertical( self, g_value_get_int( value ) ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); - break; - } -} - -// -// Instance de-initialization for inset containers. -// -void foobar_inset_container_dispose( GObject* object ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)object; - - g_clear_pointer( &self->child, gtk_widget_unparent ); - - G_OBJECT_CLASS( foobar_inset_container_parent_class )->dispose( object ); -} - -// -// Determine the size request mode used to measure the widget. -// -// This implementation just forwards the request mode from the child widget. -// -GtkSizeRequestMode foobar_inset_container_get_request_mode( GtkWidget* widget ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)widget; - if ( !self->child ) { return GTK_SIZE_REQUEST_CONSTANT_SIZE; } - - return gtk_widget_get_request_mode( self->child ); -} - -// -// Compute the requested size of the widget. -// -// This implementation uses the size requested by the child widget and then adds the inset to it. -// -void foobar_inset_container_measure( - GtkWidget* widget, - GtkOrientation orientation, - int for_size, - int* minimum, - int* natural, - int* minimum_baseline, - int* natural_baseline ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)widget; - if ( !self->child ) - { - *minimum = 0; - *natural = 0; - *minimum_baseline = 0; - *natural_baseline = 0; - return; - } - - // Get the inset for the given orientation and the other one. - - gint inset; - gint other_inset; - switch ( orientation ) - { - case GTK_ORIENTATION_HORIZONTAL: - inset = self->inset_horizontal; - other_inset = self->inset_vertical; - break; - case GTK_ORIENTATION_VERTICAL: - inset = self->inset_vertical; - other_inset = self->inset_horizontal; - break; - default: - g_warn_if_reached( ); - return; - } - - // Compute the new size, taking into consideration that the inset might have already been added to measure the other - // side and needs to be subtracted before passing it to the child widget's measure function. - - for_size = MAX( 0, for_size - ( 2 * other_inset ) ); - gtk_widget_measure( self->child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline ); - *minimum = MAX( 0, *minimum + ( 2 * inset ) ); - *natural = MAX( 0, *natural + ( 2 * inset ) ); - if ( orientation == GTK_ORIENTATION_VERTICAL ) - { - *minimum_baseline = MAX( 0, *minimum_baseline + inset ); - *natural_baseline = MAX( 0, *natural_baseline + inset ); - } -} - -// -// Arrange the child widget. -// -void foobar_inset_container_size_allocate( - GtkWidget* widget, - int width, - int height, - int baseline ) -{ - FoobarInsetContainer* self = (FoobarInsetContainer*)widget; - if ( !self->child ) { return; } - - GtkAllocation allocation = - { - .width = MAX( 0, width - 2 * self->inset_horizontal ), - .height = MAX( 0, height - 2 * self->inset_vertical ), - .x = self->inset_horizontal, - .y = self->inset_vertical, - }; - gtk_widget_size_allocate( self->child, &allocation, MAX( 0, baseline + self->inset_vertical ) ); -} - -// --------------------------------------------------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------------------------------------------------- - -// -// Create a new inset container instance. -// -GtkWidget* foobar_inset_container_new( void ) -{ - return g_object_new( FOOBAR_TYPE_INSET_CONTAINER, NULL ); -} - -// -// Get the container's child widget. -// -GtkWidget* foobar_inset_container_get_child( FoobarInsetContainer* self ) -{ - g_return_val_if_fail( FOOBAR_IS_INSET_CONTAINER( self ), NULL ); - return self->child; -} - -// -// Get the inset applied to the left and right side of the widget. -// -gint foobar_inset_container_get_inset_horizontal( FoobarInsetContainer* self ) -{ - g_return_val_if_fail( FOOBAR_IS_INSET_CONTAINER( self ), 0 ); - return self->inset_horizontal; -} - -// -// Get the inset applied to the top and bottom side of the widget. -// -gint foobar_inset_container_get_inset_vertical( FoobarInsetContainer* self ) -{ - g_return_val_if_fail( FOOBAR_IS_INSET_CONTAINER( self ), 0 ); - return self->inset_vertical; -} - -// -// Update the container's child widget. -// -void foobar_inset_container_set_child( - FoobarInsetContainer* self, - GtkWidget* child ) -{ - g_return_if_fail( FOOBAR_IS_INSET_CONTAINER( self ) ); - g_return_if_fail( child == NULL || self->child == child || gtk_widget_get_parent( child ) == NULL ); - - if ( self->child != child ) - { - g_clear_pointer( &self->child, gtk_widget_unparent ); - - if ( child ) - { - self->child = child; - gtk_widget_set_parent( child, GTK_WIDGET( self ) ); - } - - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_CHILD] ); - } -} - -// -// Update the inset applied to the left and right side of the widget. -// -void foobar_inset_container_set_inset_horizontal( - FoobarInsetContainer* self, - gint value ) -{ - g_return_if_fail( FOOBAR_IS_INSET_CONTAINER( self ) ); - - if ( self->inset_horizontal != value ) - { - self->inset_horizontal = value; - gtk_widget_queue_resize( GTK_WIDGET( self ) ); - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_HORIZONTAL] ); - } -} - -// -// Update the inset applied to the top and bottom side of the widget. -// -void foobar_inset_container_set_inset_vertical( - FoobarInsetContainer* self, - gint value ) -{ - g_return_if_fail( FOOBAR_IS_INSET_CONTAINER( self ) ); - - if ( self->inset_vertical != value ) - { - self->inset_vertical = value; - gtk_widget_queue_resize( GTK_WIDGET( self ) ); - g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_INSET_VERTICAL] ); - } -} |
