diff --git a/gtk/gtk.h b/gtk/gtk.h index 8ee2ba1b0b..e0c9d2fa48 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -174,6 +174,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkpopoverholder.c b/gtk/gtkpopoverholder.c new file mode 100644 index 0000000000..7a7cb5f3a4 --- /dev/null +++ b/gtk/gtkpopoverholder.c @@ -0,0 +1,172 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2020 Red Hat, Inc. + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library. If not, see . + */ + +#include "config.h" +#include "gtkwidgetprivate.h" +#include "gtkpopoverholder.h" +#include "gtknative.h" + + +struct _GtkPopoverHolder +{ + GtkWidget parent_instance; + GtkWidget *child; + GtkPopover *popover; +}; + +struct _GtkPopoverHolderClass +{ + GtkWidgetClass parent_class; +}; + +G_DEFINE_TYPE (GtkPopoverHolder, gtk_popover_holder, GTK_TYPE_WIDGET) + +static void +gtk_popover_holder_size_allocate (GtkWidget *widget, + int width, + int height, + int baseline) +{ + GtkPopoverHolder *self = GTK_POPOVER_HOLDER (widget); + + if (self->child && _gtk_widget_get_visible (self->child)) + gtk_widget_size_allocate (self->child, + &(GtkAllocation) { + 0, 0, + width, height + }, baseline); + + if (self->popover) + gtk_native_check_resize (GTK_NATIVE (self->popover)); +} + +static void +gtk_popover_holder_measure (GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline) +{ + GtkPopoverHolder *self = GTK_POPOVER_HOLDER (widget); + + if (self->child != NULL && _gtk_widget_get_visible (self->child)) + gtk_widget_measure (self->child, + orientation, + for_size, + minimum, natural, + minimum_baseline, natural_baseline); + else + { + *minimum = 0; + *natural = 0; + } +} + +static void +gtk_popover_holder_dispose (GObject *object) +{ + GtkPopoverHolder *self = GTK_POPOVER_HOLDER (object); + + g_clear_pointer (&self->child, gtk_widget_unparent); + if (self->popover) + { + gtk_popover_set_relative_to (self->popover, NULL); + self->popover = NULL; + } + + G_OBJECT_CLASS (gtk_popover_holder_parent_class)->dispose (object); +} + +static void +gtk_popover_holder_class_init (GtkPopoverHolderClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + + object_class->dispose = gtk_popover_holder_dispose; + + widget_class->measure = gtk_popover_holder_measure; + widget_class->size_allocate = gtk_popover_holder_size_allocate; +} + +static void +gtk_popover_holder_init (GtkPopoverHolder *self) +{ +} + +GtkWidget * +gtk_popover_holder_new (void) +{ + return g_object_new (GTK_TYPE_POPOVER_HOLDER, NULL); +} + +GtkWidget * +gtk_popover_holder_get_child (GtkPopoverHolder *self) +{ + g_return_val_if_fail (GTK_IS_POPOVER_HOLDER (self), NULL); + + return self->child; +} + +void +gtk_popover_holder_set_child (GtkPopoverHolder *self, + GtkWidget *child) +{ + g_return_if_fail (GTK_IS_POPOVER_HOLDER (self)); + g_return_if_fail (GTK_IS_WIDGET (child)); + + if (self->child) + gtk_widget_unparent (self->child); + + self->child = child; + + if (self->child) + gtk_widget_set_parent (self->child, GTK_WIDGET (self)); +} + +GtkPopover * +gtk_popover_holder_get_popover (GtkPopoverHolder *self) +{ + g_return_val_if_fail (GTK_IS_POPOVER_HOLDER (self), NULL); + + return self->popover; +} + +void +gtk_popover_holder_set_popover (GtkPopoverHolder *self, + GtkPopover *popover) +{ + g_return_if_fail (GTK_IS_POPOVER_HOLDER (self)); + g_return_if_fail (GTK_IS_POPOVER (popover)); + + if (self->popover) + { + if (gtk_widget_get_visible (GTK_WIDGET (self->popover))) + gtk_widget_hide (GTK_WIDGET (self->popover)); + + gtk_popover_set_relative_to (self->popover, NULL); + } + + self->popover = popover; + + if (self->popover) + { + gtk_popover_set_relative_to (self->popover, GTK_WIDGET (self)); + } +} diff --git a/gtk/gtkpopoverholder.h b/gtk/gtkpopoverholder.h new file mode 100644 index 0000000000..62e4f943c5 --- /dev/null +++ b/gtk/gtkpopoverholder.h @@ -0,0 +1,67 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2020 Red Hat, Inc. + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library. If not, see . + */ + +#ifndef __GTK_POPOVER_HOLDER_H__ +#define __GTK_POPOVER_HOLDER_H__ + + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_POPOVER_HOLDER (gtk_popover_holder_get_type ()) +#define GTK_POPOVER_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_HOLDER, GtkPopoverHolder)) +#define GTK_POPOVER_HOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_POPOVER_HOLDER, GtkPopoverHolderClass)) +#define GTK_IS_POPOVER_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_HOLDER)) +#define GTK_IS_POPOVER_HOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_POPOVER_HOLDER)) +#define GTK_POPOVER_HOLDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_POPOVER_HOLDER, GtkPopoverHolderClass)) + + +typedef struct _GtkPopoverHolder GtkPopoverHolder; +typedef struct _GtkPopoverHolderClass GtkPopoverHolderClass; + + +GDK_AVAILABLE_IN_ALL +GType gtk_popover_holder_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_popover_holder_new (void); + +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_popover_holder_get_child (GtkPopoverHolder *self); + +GDK_AVAILABLE_IN_ALL +void gtk_popover_holder_set_child (GtkPopoverHolder *self, + GtkWidget *widget); + +GDK_AVAILABLE_IN_ALL +GtkPopover * gtk_popover_holder_get_popover (GtkPopoverHolder *self); + +GDK_AVAILABLE_IN_ALL +void gtk_popover_holder_set_popover (GtkPopoverHolder *self, + GtkPopover *popover); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPopoverHolder, g_object_unref) + +G_END_DECLS + +#endif /* __GTK_POPOVER_HOLDER_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index ca72c02101..ee6647328e 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -298,6 +298,7 @@ gtk_public_sources = files([ 'gtkpasswordentry.c', 'gtkpicture.c', 'gtkpopover.c', + 'gtkpopoverholder.c', 'gtkpopovermenu.c', 'gtkpopovermenubar.c', 'gtkprintcontext.c',