diff --git a/src/gui/gcal-gizmo.c b/src/gui/gcal-gizmo.c new file mode 100644 index 00000000..9320f473 --- /dev/null +++ b/src/gui/gcal-gizmo.c @@ -0,0 +1,257 @@ +/* gcal-gizmo.c + * + * Copyright (C) 2020 Purism SPC + * Copyright 2025 Hari Rana + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This file 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see . + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "config.h" + +#include "gcal-gizmo.h" + +/** + * GcalGizmo: + * + * A very basic widget for setting virtual functions affecting layout. + * + * This is only meant to be used for custom widgets that need child widgets with custom + * functions that contribute to layout. + */ + +struct _GcalGizmo +{ + GtkWidget parent_instance; + + GcalGizmoMeasureFunc measure_func; + gpointer measure_user_data; + + GcalGizmoSizeAllocateFunc size_allocate_func; + gpointer size_allocate_user_data; + + GcalGizmoSnapshotFunc snapshot_func; + gpointer snapshot_user_data; + + GcalGizmoFocusFunc focus_func; + gpointer focus_user_data; +}; + +G_DEFINE_FINAL_TYPE (GcalGizmo, gcal_gizmo, GTK_TYPE_WIDGET) + + +/* + * GtkWidget overrides + */ + +static void +gcal_gizmo_real_measure (GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline) +{ + GcalGizmo *self = (GcalGizmo *) widget; + + g_assert (GCAL_IS_GIZMO (self)); + + if (self->measure_func) + { + self->measure_func (self, + orientation, + for_size, + minimum, natural, + minimum_baseline, natural_baseline, + self->measure_user_data); + } +} + +static void +gcal_gizmo_real_size_allocate (GtkWidget *widget, + int width, + int height, + int baseline) +{ + GcalGizmo *self = (GcalGizmo *) widget; + + g_assert (GCAL_IS_GIZMO (self)); + + if (self->size_allocate_func) + self->size_allocate_func (self, width, height, baseline, self->size_allocate_user_data); +} + +static void +gcal_gizmo_real_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) +{ + GcalGizmo *self = (GcalGizmo *) widget; + + g_assert (GCAL_IS_GIZMO (self)); + + if (self->snapshot_func) + self->snapshot_func (self, snapshot, self->snapshot_user_data); + else + GTK_WIDGET_CLASS (gcal_gizmo_parent_class)->snapshot (widget, snapshot); +} + +static gboolean +gcal_gizmo_real_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GcalGizmo *self = (GcalGizmo *) widget; + + g_assert (GCAL_IS_GIZMO (self)); + + if (self->focus_func) + return self->focus_func (self, direction, self->focus_user_data); + + return FALSE; +} + + +/* + * GObject overrides + */ + +static void +gcal_gizmo_dispose (GObject *object) +{ + GtkWidget *widget = GTK_WIDGET (object); + GtkWidget *child; + + while ((child = gtk_widget_get_first_child (widget))) + gtk_widget_unparent (child); + + G_OBJECT_CLASS (gcal_gizmo_parent_class)->dispose (object); +} + + +/* + * Initialization + */ + +static void +gcal_gizmo_class_init (GcalGizmoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = gcal_gizmo_dispose; + + widget_class->measure = gcal_gizmo_real_measure; + widget_class->size_allocate = gcal_gizmo_real_size_allocate; + widget_class->snapshot = gcal_gizmo_real_snapshot; + widget_class->focus = gcal_gizmo_real_focus; +} + +static void +gcal_gizmo_init (GcalGizmo *self) +{ +} + + +/** + * gcal_gizmo_new: + * + * Create a new #GcalGizmo. + * + * Returns: (transfer full): a newly created #GcalGizmo + */ +GcalGizmo * +gcal_gizmo_new (void) +{ + return g_object_new (GCAL_TYPE_GIZMO, NULL); +} + +/** + * gcal_gizmo_set_measure_func: + * @self: a #GcalGizmo + * @measure_func: (scope call): the function to set + * + * Set the function overriding [vfunc@Gtk.Widget.measure]. + */ +void +gcal_gizmo_set_measure_func (GcalGizmo *self, + GcalGizmoMeasureFunc measure_func, + gpointer user_data) +{ + g_assert (GCAL_IS_GIZMO (self)); + + self->measure_func = measure_func; + self->measure_user_data = user_data; + + gtk_widget_queue_resize (GTK_WIDGET (self)); +} + +/** + * gcal_gizmo_set_size_allocate_func: + * @self: a #GcalGizmo + * @size_allocate_func: (scope call): the function to set + * + * Set the function overriding [vfunc@Gtk.Widget.size_allocate]. + */ +void +gcal_gizmo_set_size_allocate_func (GcalGizmo *self, + GcalGizmoSizeAllocateFunc size_allocate_func, + gpointer user_data) +{ + g_assert (GCAL_IS_GIZMO (self)); + + self->size_allocate_func = size_allocate_func; + self->size_allocate_user_data = user_data; + + gtk_widget_queue_allocate (GTK_WIDGET (self)); +} + +/** + * gcal_gizmo_set_snapshot_func: + * @self: a #GcalGizmo + * @snapshot_func: (scope call): the function to set + * + * Set the function overriding [vfunc@Gtk.Widget.snapshot]. + */ +void +gcal_gizmo_set_snapshot_func (GcalGizmo *self, + GcalGizmoSnapshotFunc snapshot_func, + gpointer user_data) +{ + g_assert (GCAL_IS_GIZMO (self)); + + self->snapshot_func = snapshot_func; + self->snapshot_user_data = user_data; + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} + +/** + * gcal_gizmo_set_focus_func: + * @self: a #GcalGizmo + * @focus_func: (scope call): the function to set + * + * Set the function overriding [vfunc@Gtk.Widget.focus]. + */ +void +gcal_gizmo_set_focus_func (GcalGizmo *self, + GcalGizmoFocusFunc focus_func, + gpointer user_data) +{ + g_assert (GCAL_IS_GIZMO (self)); + + self->focus_func = focus_func; + self->focus_user_data = user_data; +} + diff --git a/src/gui/gcal-gizmo.h b/src/gui/gcal-gizmo.h new file mode 100644 index 00000000..ff4ed8ab --- /dev/null +++ b/src/gui/gcal-gizmo.h @@ -0,0 +1,111 @@ +/* gcal-gizmo.h + * + * Copyright (C) 2020 Purism SPC + * Copyright 2025 Hari Rana + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This file 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see . + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define GCAL_TYPE_GIZMO (gcal_gizmo_get_type ()) + +G_DECLARE_FINAL_TYPE (GcalGizmo, gcal_gizmo, GCAL, GIZMO, GtkWidget) + +/** + * GcalGizmoMeasureFunc: + * @self: a #GcalGizmo + * @orientation: the orientation to measure + * @for_size: size for the opposite of @orientation, or -1 if unknown + * @minimum: (out) (optional): location to store the minimum size + * @natural: (out) (optional): location to store the natural size + * @minimum_baseline: (out) (optional): + * location to store the baseline position for the minimum size, or -1 to report no baseline + * @natural_baseline: (out) (optional): + * location to store the baseline position for the natural size, or -1 to report no baseline + * @user_data: (nullable): user data + * + * Function wrapper for overriding [vfunc@Gtk.Widget.measure]. + */ +typedef void (*GcalGizmoMeasureFunc) (GcalGizmo *self, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline, + gpointer user_data); + +/** + * GcalGizmoSizeAllocateFunc: + * @self: a #GcalGizmo + * @width: the width + * @height: the height + * @baseline: the baseline, or -1 + * @user_data: (nullable): user data + * + * Function wrapper for overriding [vfunc@Gtk.Widget.size_allocate]. + */ +typedef void (*GcalGizmoSizeAllocateFunc) (GcalGizmo *self, + int width, + int height, + int baseline, + gpointer user_data); + +/** + * GcalGizmoFocusFunc: + * @self: a #GcalGizmo + * @direction: the direction + * @user_data: (nullable): user data + * + * Function wrapper for overriding [vfunc@Gtk.Widget.focus]. + */ +typedef gboolean (*GcalGizmoFocusFunc) (GcalGizmo *self, + GtkDirectionType direction, + gpointer user_data); + +/** + * GcalGizmoSnapshotFunc: + * @self: a #GcalGizmo + * @snapshot: the snapshot + * @user_data: (nullable): user data + * + * Function wrapper for overriding [vfunc@Gtk.Widget.snapshot]. + */ +typedef void (*GcalGizmoSnapshotFunc) (GcalGizmo *self, + GtkSnapshot *snapshot, + gpointer user_data); + +GcalGizmo *gcal_gizmo_new (void); +void gcal_gizmo_set_measure_func (GcalGizmo *self, + GcalGizmoMeasureFunc measure_func, + gpointer user_data); +void gcal_gizmo_set_size_allocate_func (GcalGizmo *self, + GcalGizmoSizeAllocateFunc size_allocate_func, + gpointer user_data); +void gcal_gizmo_set_snapshot_func (GcalGizmo *self, + GcalGizmoSnapshotFunc snapshot_func, + gpointer user_data); +void gcal_gizmo_set_focus_func (GcalGizmo *self, + GcalGizmoFocusFunc focus_func, + gpointer user_data); + +G_END_DECLS + diff --git a/src/gui/meson.build b/src/gui/meson.build index 182b1e0e..12b05de0 100644 --- a/src/gui/meson.build +++ b/src/gui/meson.build @@ -49,6 +49,7 @@ sources += files( 'gcal-event-widget.c', 'gcal-event-widget-pool.c', 'gcal-fading-label.c', + 'gcal-gizmo.c', 'gcal-meeting-row.c', 'gcal-overflow-bin.c', 'gcal-overflow-bin-layout.c',