[gtk+/overlay: 1/34] overlay: add initial version of gtkoverlay
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/overlay: 1/34] overlay: add initial version of gtkoverlay
- Date: Sat, 11 Jun 2011 00:58:44 +0000 (UTC)
commit aea302af51723c46a04c4f4a2d57ade5d1e40f75
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Thu May 19 18:53:05 2011 +0200
overlay: add initial version of gtkoverlay
gtk/Makefile.am | 4 +
gtk/gtkoverlay.c | 529 +++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkoverlay.h | 81 ++++++++
gtk/gtkoverlaychild.c | 307 ++++++++++++++++++++++++++++
gtk/gtkoverlaychild.h | 70 +++++++
5 files changed, 991 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 4111938..ee600de 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -256,6 +256,8 @@ gtk_public_h_sources = \
gtknumerableicon.h \
gtkoffscreenwindow.h \
gtkorientable.h \
+ gtkoverlay.h \
+ gtkoverlaychild.h \
gtkpagesetup.h \
gtkpaned.h \
gtkpapersize.h \
@@ -587,6 +589,8 @@ gtk_base_c_sources = \
gtknumerableicon.c \
gtkoffscreenwindow.c \
gtkorientable.c \
+ gtkoverlay.c \
+ gtkoverlaychild.c \
gtkpagesetup.c \
gtkpaned.c \
gtkpango.c \
diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c
new file mode 100644
index 0000000..68221df
--- /dev/null
+++ b/gtk/gtkoverlay.c
@@ -0,0 +1,529 @@
+/*
+ * gtkoverlay.c
+ * This file is part of gtk
+ *
+ * Copyright (C) 2011 - Ignacio Casal Quinteiro, Mike Krüger
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gtkoverlay.h"
+
+typedef struct
+{
+ GtkWidget *child;
+ GtkWidget *original;
+} ChildContainer;
+
+struct _GtkOverlayPrivate
+{
+ GtkWidget *main_widget;
+ GtkWidget *relative_widget;
+ GSList *children;
+};
+
+enum
+{
+ PROP_0,
+ PROP_MAIN_WIDGET,
+ PROP_RELATIVE_WIDGET
+};
+
+G_DEFINE_TYPE (GtkOverlay, gtk_overlay, GTK_TYPE_CONTAINER)
+
+static ChildContainer *
+child_container_new (GtkWidget *child,
+ GtkWidget *original)
+{
+ ChildContainer *ret;
+
+ ret = g_slice_new (ChildContainer);
+ ret->child = child;
+ ret->original = original;
+
+ return ret;
+}
+
+static void
+child_container_free (ChildContainer *container)
+{
+ g_slice_free (ChildContainer, container);
+}
+
+static GtkWidget *
+child_container_get_child (ChildContainer *container)
+{
+ GtkWidget *child;
+
+ if (container->child != NULL)
+ child = container->child;
+ else
+ child = container->original;
+
+ return child;
+}
+
+static void
+add_toplevel_widget (GtkOverlay *overlay,
+ GtkWidget *child,
+ GtkWidget *original)
+{
+ ChildContainer *container;
+
+ if (child != NULL)
+ gtk_widget_set_parent (child, GTK_WIDGET (overlay));
+ else
+ gtk_widget_set_parent (original, GTK_WIDGET (overlay));
+
+ container = child_container_new (child, original);
+
+ overlay->priv->children = g_slist_append (overlay->priv->children,
+ container);
+}
+
+static void
+gtk_overlay_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_overlay_parent_class)->dispose (object);
+}
+
+static void
+gtk_overlay_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkOverlay *overlay = GTK_OVERLAY (object);
+ GtkOverlayPrivate *priv = overlay->priv;
+
+ switch (prop_id)
+ {
+ case PROP_MAIN_WIDGET:
+ g_value_set_object (value, priv->main_widget);
+ break;
+
+ case PROP_RELATIVE_WIDGET:
+ g_value_set_object (value, priv->relative_widget);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GtkWidget *
+wrap_child_if_needed (GtkWidget *widget)
+{
+ GtkWidget *child;
+
+ if (GTK_IS_OVERLAY_CHILD (widget))
+ return widget;
+
+ child = GTK_WIDGET (gtk_overlay_child_new (widget));
+ gtk_widget_show (child);
+
+ g_signal_connect_swapped (widget,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroy),
+ child);
+
+ return child;
+}
+
+static void
+gtk_overlay_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkOverlay *overlay = GTK_OVERLAY (object);
+ GtkOverlayPrivate *priv = overlay->priv;
+
+ switch (prop_id)
+ {
+ case PROP_MAIN_WIDGET:
+ priv->main_widget = g_value_get_object (value);
+
+ add_toplevel_widget (overlay,
+ NULL,
+ priv->main_widget);
+ break;
+
+ case PROP_RELATIVE_WIDGET:
+ priv->relative_widget = g_value_get_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_overlay_realize (GtkWidget *widget)
+{
+ GtkAllocation allocation;
+ GdkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GtkStyleContext *context;
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gtk_widget_set_window (widget, window);
+ gdk_window_set_user_data (window, widget);
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
+ gtk_style_context_set_background (context, window);
+}
+
+static void
+gtk_overlay_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkOverlayPrivate *priv = GTK_OVERLAY (widget)->priv;
+
+ *minimum = 0;
+ *natural = 0;
+
+ if (priv->main_widget)
+ gtk_widget_get_preferred_width (priv->main_widget, minimum, natural);
+}
+
+static void
+gtk_overlay_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkOverlayPrivate *priv = GTK_OVERLAY (widget)->priv;
+
+ *minimum = 0;
+ *natural = 0;
+
+ if (priv->main_widget)
+ gtk_widget_get_preferred_height (priv->main_widget, minimum, natural);
+}
+
+static void
+gtk_overlay_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkOverlay *overlay = GTK_OVERLAY (widget);
+ GtkOverlayPrivate *priv = overlay->priv;
+ GtkAllocation main_alloc;
+ GSList *l;
+
+ GTK_WIDGET_CLASS (gtk_overlay_parent_class)->size_allocate (widget, allocation);
+
+ /* main widget allocation */
+ main_alloc.x = 0;
+ main_alloc.y = 0;
+ main_alloc.width = allocation->width;
+ main_alloc.height = allocation->height;
+
+ gtk_widget_size_allocate (overlay->priv->main_widget, &main_alloc);
+
+ /* if a relative widget exists place the floating widgets in relation to it */
+ if (priv->relative_widget)
+ gtk_widget_get_allocation (priv->relative_widget, &main_alloc);
+
+ for (l = priv->children; l != NULL; l = g_slist_next (l))
+ {
+ ChildContainer *container = l->data;
+ GtkWidget *child;
+ GtkRequisition req;
+ GtkAllocation alloc;
+ guint offset;
+ GtkAlign halign, valign;
+
+ child = child_container_get_child (container);
+
+ if (child == priv->main_widget)
+ continue;
+
+ gtk_widget_get_preferred_size (child, NULL, &req);
+ offset = gtk_overlay_child_get_offset (GTK_OVERLAY_CHILD (child));
+ halign = gtk_widget_get_halign (child);
+ valign = gtk_widget_get_valign (child);
+
+ /* FIXME: Add all the positions here */
+ switch (halign)
+ {
+ /* The gravity is treated as position and not as a gravity */
+ case GTK_ALIGN_END:
+ switch (valign)
+ {
+ case GTK_ALIGN_START:
+ alloc.x = MAX (main_alloc.x, main_alloc.width - req.width - (gint) offset);
+ alloc.y = 0;
+ break;
+
+ case GTK_ALIGN_END:
+ alloc.x = MAX (main_alloc.x, main_alloc.width - req.width - (gint) offset);
+ alloc.y = MAX (main_alloc.y, main_alloc.height - req.height);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case GTK_ALIGN_START:
+ switch (valign)
+ {
+ case GTK_ALIGN_START:
+ alloc.x = offset;
+ alloc.y = 0;
+ break;
+
+ case GTK_ALIGN_END:
+ alloc.x = offset;
+ alloc.y = MAX (main_alloc.y, main_alloc.height - req.height);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ alloc.x = 0;
+ alloc.y = 0;
+ }
+
+ alloc.width = MIN (main_alloc.width, req.width);
+ alloc.height = MIN (main_alloc.height, req.height);
+
+ gtk_widget_size_allocate (child, &alloc);
+ }
+}
+
+static GtkOverlayChild *
+get_overlay_child (GtkOverlay *overlay,
+ GtkWidget *widget)
+{
+ GSList *l;
+
+ for (l = overlay->priv->children; l != NULL; l = g_slist_next (l))
+ {
+ ChildContainer *container = l->data;
+
+ if (container->original == widget &&
+ GTK_IS_OVERLAY_CHILD (container->child))
+ {
+ return GTK_OVERLAY_CHILD (container->child);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+overlay_add (GtkContainer *overlay,
+ GtkWidget *widget)
+{
+ GtkOverlayChild *child;
+
+ /* check that the widget is not added yet */
+ child = get_overlay_child (GTK_OVERLAY (overlay), widget);
+
+ if (child == NULL)
+ add_toplevel_widget (GTK_OVERLAY (overlay),
+ wrap_child_if_needed (widget),
+ widget);
+}
+
+static void
+gtk_overlay_remove (GtkContainer *overlay,
+ GtkWidget *widget)
+{
+ GtkOverlayPrivate *priv = GTK_OVERLAY (overlay)->priv;
+ GSList *l;
+
+ for (l = priv->children; l != NULL; l = g_slist_next (l))
+ {
+ ChildContainer *container = l->data;
+ GtkWidget *original = container->original;
+
+ if (original == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ if (container->child != NULL &&
+ original != container->child)
+ {
+ g_signal_handlers_disconnect_by_func (original,
+ gtk_widget_destroy,
+ container->child);
+
+ gtk_widget_destroy (container->child);
+ }
+
+ child_container_free (container);
+ priv->children = g_slist_delete_link (priv->children,
+ l);
+
+ break;
+ }
+ }
+}
+
+static void
+gtk_overlay_forall (GtkContainer *overlay,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkOverlayPrivate *priv = GTK_OVERLAY (overlay)->priv;
+ GSList *children;
+
+ children = priv->children;
+
+ while (children)
+ {
+ ChildContainer *container = children->data;
+ children = children->next;
+ GtkWidget *child;
+
+ child = child_container_get_child (container);
+
+ (* callback) (child, callback_data);
+ }
+}
+
+static GType
+gtk_overlay_child_type (GtkContainer *overlay)
+{
+ return GTK_TYPE_WIDGET;
+}
+
+static void
+gtk_overlay_class_init (GtkOverlayClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ object_class->dispose = gtk_overlay_dispose;
+ object_class->get_property = gtk_overlay_get_property;
+ object_class->set_property = gtk_overlay_set_property;
+
+ widget_class->realize = gtk_overlay_realize;
+ widget_class->get_preferred_width = gtk_overlay_get_preferred_width;
+ widget_class->get_preferred_height = gtk_overlay_get_preferred_height;
+ widget_class->size_allocate = gtk_overlay_size_allocate;
+
+ container_class->add = overlay_add;
+ container_class->remove = gtk_overlay_remove;
+ container_class->forall = gtk_overlay_forall;
+ container_class->child_type = gtk_overlay_child_type;
+
+ g_object_class_install_property (object_class, PROP_MAIN_WIDGET,
+ g_param_spec_object ("main-widget",
+ "Main Widget",
+ "The Main Widget",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_RELATIVE_WIDGET,
+ g_param_spec_object ("relative-widget",
+ "Relative Widget",
+ "Widget on which the floating widgets are placed",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (object_class, sizeof (GtkOverlayPrivate));
+}
+
+static void
+gtk_overlay_init (GtkOverlay *overlay)
+{
+ overlay->priv = G_TYPE_INSTANCE_GET_PRIVATE (overlay, GTK_TYPE_OVERLAY, GtkOverlayPrivate);
+
+ gtk_widget_set_app_paintable (GTK_WIDGET (overlay), TRUE);
+}
+
+/**
+ * gtk_overlay_new:
+ * @main_widget: a #GtkWidget
+ * @relative_widget: (allow-none): a #Gtkwidget
+ *
+ * Creates a new #GtkOverlay. If @relative_widget is not %NULL the floating
+ * widgets will be placed in relation to it, if not @main_widget will be use
+ * for this purpose.
+ *
+ * Returns: a new #GtkOverlay object.
+ */
+GtkWidget *
+gtk_overlay_new (GtkWidget *main_widget,
+ GtkWidget *relative_widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (main_widget), NULL);
+
+ return GTK_WIDGET (g_object_new (GTK_TYPE_OVERLAY,
+ "main-widget", main_widget,
+ "relative-widget", relative_widget,
+ NULL));
+}
+
+/**
+ * gtk_overlay_add:
+ * @overlay: a #GtkOverlay
+ * @widget: a #GtkWidget to be added to the container
+ * @offset: offset for @widget
+ *
+ * Adds @widget to @overlay in a specific position.
+ */
+void
+gtk_overlay_add (GtkOverlay *overlay,
+ GtkWidget *widget,
+ guint offset)
+{
+ GtkOverlayChild *child;
+
+ g_return_if_fail (GTK_IS_OVERLAY (overlay));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_container_add (GTK_CONTAINER (overlay), widget);
+
+ /* NOTE: can we improve this without exposing overlay child? */
+ child = get_overlay_child (overlay, widget);
+ g_assert (child != NULL);
+
+ gtk_overlay_child_set_offset (child, offset);
+}
diff --git a/gtk/gtkoverlay.h b/gtk/gtkoverlay.h
new file mode 100644
index 0000000..ead6cd7
--- /dev/null
+++ b/gtk/gtkoverlay.h
@@ -0,0 +1,81 @@
+/*
+ * gtkoverlay.h
+ * This file is part of gtk
+ *
+ * Copyright (C) 2011 - Ignacio Casal Quinteiro
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_OVERLAY_H__
+#define __GTK_OVERLAY_H__
+
+#include <gtk/gtkcontainer.h>
+#include "gtkoverlaychild.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_OVERLAY (gtk_overlay_get_type ())
+#define GTK_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OVERLAY, GtkOverlay))
+#define GTK_OVERLAY_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OVERLAY, GtkOverlay const))
+#define GTK_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_OVERLAY, GtkOverlayClass))
+#define GTK_IS_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_OVERLAY))
+#define GTK_IS_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_OVERLAY))
+#define GTK_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_OVERLAY, GtkOverlayClass))
+
+typedef struct _GtkOverlay GtkOverlay;
+typedef struct _GtkOverlayClass GtkOverlayClass;
+typedef struct _GtkOverlayPrivate GtkOverlayPrivate;
+
+struct _GtkOverlay
+{
+ GtkContainer parent;
+
+ GtkOverlayPrivate *priv;
+};
+
+struct _GtkOverlayClass
+{
+ GtkContainerClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+ void (*_gtk_reserved5) (void);
+ void (*_gtk_reserved6) (void);
+ void (*_gtk_reserved7) (void);
+ void (*_gtk_reserved8) (void);
+ void (*_gtk_reserved9) (void);
+};
+
+GType gtk_overlay_get_type (void) G_GNUC_CONST;
+
+GtkWidget *gtk_overlay_new (GtkWidget *main_widget,
+ GtkWidget *relative_widget);
+
+void gtk_overlay_add (GtkOverlay *overlay,
+ GtkWidget *widget,
+ guint offset);
+
+G_END_DECLS
+
+#endif /* __GTK_OVERLAY_H__ */
diff --git a/gtk/gtkoverlaychild.c b/gtk/gtkoverlaychild.c
new file mode 100644
index 0000000..1b8c71d
--- /dev/null
+++ b/gtk/gtkoverlaychild.c
@@ -0,0 +1,307 @@
+/*
+ * gtk-overlay-child.c
+ * This file is part of gtk
+ *
+ * Copyright (C) 2011 - Ignacio Casal Quinteiro
+ *
+ * gtk 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.1 of the License, or (at your option) any later version.
+ *
+ * gtk 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtkoverlaychild.h"
+
+struct _GtkOverlayChildPrivate
+{
+ GBinding *binding;
+ guint offset;
+};
+
+enum
+{
+ PROP_0,
+ PROP_WIDGET,
+ PROP_OFFSET
+};
+
+G_DEFINE_TYPE (GtkOverlayChild, gtk_overlay_child, GTK_TYPE_BIN)
+
+static void
+gtk_overlay_child_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkOverlayChild *child = GTK_OVERLAY_CHILD (object);
+
+ switch (prop_id)
+ {
+ case PROP_WIDGET:
+ g_value_set_object (value, gtk_bin_get_child (GTK_BIN (child)));
+ break;
+ case PROP_OFFSET:
+ g_value_set_uint (value, child->priv->offset);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_overlay_child_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkOverlayChild *child = GTK_OVERLAY_CHILD (object);
+
+ switch (prop_id)
+ {
+ case PROP_WIDGET:
+ gtk_container_add (GTK_CONTAINER (child),
+ g_value_get_object (value));
+ break;
+ case PROP_OFFSET:
+ child->priv->offset = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_overlay_child_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ GdkWindow *parent_window;
+ GdkWindow *window;
+ GtkStyleContext *context;
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ parent_window = gtk_widget_get_parent_window (widget);
+ context = gtk_widget_get_style_context (widget);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.event_mask = GDK_EXPOSURE_MASK;
+ attributes.width = 0;
+ attributes.height = 0;
+
+ window = gdk_window_new (parent_window, &attributes, 0);
+ gdk_window_set_user_data (window, widget);
+ gtk_widget_set_window (widget, window);
+ gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
+ gtk_style_context_set_background (context, window);
+}
+
+static void
+gtk_overlay_child_get_size (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint *minimum,
+ gint *natural)
+{
+ GtkOverlayChild *overlay_child = GTK_OVERLAY_CHILD (widget);
+ GtkWidget *child;
+ gint child_min = 0, child_nat = 0;
+
+ child = gtk_bin_get_child (GTK_BIN (overlay_child));
+
+ if (child != NULL)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_widget_get_preferred_width (child,
+ &child_min, &child_nat);
+ }
+ else
+ {
+ gtk_widget_get_preferred_height (child,
+ &child_min, &child_nat);
+ }
+ }
+
+ *minimum = child_min;
+ *natural = child_nat;
+}
+
+static void
+gtk_overlay_child_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_overlay_child_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum, natural);
+}
+
+static void
+gtk_overlay_child_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_overlay_child_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum, natural);
+}
+
+static void
+gtk_overlay_child_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkOverlayChild *overlay_child = GTK_OVERLAY_CHILD (widget);
+ GtkWidget *child;
+ GtkAllocation tmp;
+
+ tmp.width = allocation->width;
+ tmp.height = allocation->height;
+ tmp.x = tmp.y = 0;
+
+ GTK_WIDGET_CLASS (gtk_overlay_child_parent_class)->size_allocate (widget, allocation);
+
+ child = gtk_bin_get_child (GTK_BIN (overlay_child));
+
+ if (child != NULL)
+ {
+ gtk_widget_size_allocate (child, &tmp);
+ }
+}
+
+static void
+gtk_overlay_child_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkOverlayChild *overlay_child = GTK_OVERLAY_CHILD (container);
+
+ overlay_child->priv->binding = g_object_bind_property (G_OBJECT (widget), "visible",
+ G_OBJECT (container), "visible",
+ G_BINDING_BIDIRECTIONAL);
+
+ GTK_CONTAINER_CLASS (gtk_overlay_child_parent_class)->add (container, widget);
+}
+
+static void
+gtk_overlay_child_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkOverlayChild *child = GTK_OVERLAY_CHILD (container);
+
+ g_object_unref (child->priv->binding);
+
+ GTK_CONTAINER_CLASS (gtk_overlay_child_parent_class)->remove (container, widget);
+}
+
+static void
+gtk_overlay_child_class_init (GtkOverlayChildClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ object_class->get_property = gtk_overlay_child_get_property;
+ object_class->set_property = gtk_overlay_child_set_property;
+
+ widget_class->realize = gtk_overlay_child_realize;
+ widget_class->get_preferred_width = gtk_overlay_child_get_preferred_width;
+ widget_class->get_preferred_height = gtk_overlay_child_get_preferred_height;
+ widget_class->size_allocate = gtk_overlay_child_size_allocate;
+
+ container_class->add = gtk_overlay_child_add;
+ container_class->remove = gtk_overlay_child_remove;
+
+ g_object_class_install_property (object_class, PROP_WIDGET,
+ g_param_spec_object ("widget",
+ "Widget",
+ "The Widget",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_OFFSET,
+ g_param_spec_uint ("offset",
+ "Offset",
+ "The Widget Offset",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (object_class, sizeof (GtkOverlayChildPrivate));
+}
+
+static void
+gtk_overlay_child_init (GtkOverlayChild *child)
+{
+ child->priv = G_TYPE_INSTANCE_GET_PRIVATE (child,
+ GTK_TYPE_OVERLAY_CHILD,
+ GtkOverlayChildPrivate);
+
+ gtk_widget_set_has_window (GTK_WIDGET (child), TRUE);
+}
+
+/**
+ * gtk_overlay_child_new:
+ * @widget: a #GtkWidget
+ *
+ * Creates a new #GtkOverlayChild object
+ *
+ * Returns: a new #GtkOverlayChild object
+ */
+GtkOverlayChild *
+gtk_overlay_child_new (GtkWidget *widget)
+{
+ return g_object_new (GTK_TYPE_OVERLAY_CHILD,
+ "widget", widget,
+ NULL);
+}
+
+/**
+ * gtk_overlay_child_get_offset:
+ * @child: a #GtkOverlayChild
+ *
+ * Gets the offset for @child. The offset is usually used by #GtkOverlay
+ * to not place the widget directly in the border of the container
+ *
+ * Returns: the offset for @child
+ */
+guint
+gtk_overlay_child_get_offset (GtkOverlayChild *child)
+{
+ g_return_val_if_fail (GTK_IS_OVERLAY_CHILD (child), 0);
+
+ return child->priv->offset;
+}
+
+/**
+ * gtk_overlay_child_set_offset:
+ * @child: a #GtkOverlayChild
+ * @offset: the offset for @child
+ *
+ * Sets the new offset for @child
+ */
+void
+gtk_overlay_child_set_offset (GtkOverlayChild *child,
+ guint offset)
+{
+ g_return_if_fail (GTK_IS_OVERLAY_CHILD (child));
+
+ if (child->priv->offset != offset)
+ {
+ child->priv->offset = offset;
+
+ g_object_notify (G_OBJECT (child), "offset");
+ }
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gtk/gtkoverlaychild.h b/gtk/gtkoverlaychild.h
new file mode 100644
index 0000000..9894ec8
--- /dev/null
+++ b/gtk/gtkoverlaychild.h
@@ -0,0 +1,70 @@
+/*
+ * gtk-overlay-child.h
+ * This file is part of gtk
+ *
+ * Copyright (C) 2011 - Ignacio Casal Quinteiro
+ *
+ * gtk 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.1 of the License, or (at your option) any later version.
+ *
+ * gtk 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_OVERLAY_CHILD_H__
+#define __GTK_OVERLAY_CHILD_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_OVERLAY_CHILD (gtk_overlay_child_get_type ())
+#define GTK_OVERLAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OVERLAY_CHILD, GtkOverlayChild))
+#define GTK_OVERLAY_CHILD_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OVERLAY_CHILD, GtkOverlayChild const))
+#define GTK_OVERLAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_OVERLAY_CHILD, GtkOverlayChildClass))
+#define GTK_IS_OVERLAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_OVERLAY_CHILD))
+#define GTK_IS_OVERLAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_OVERLAY_CHILD))
+#define GTK_OVERLAY_CHILD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_OVERLAY_CHILD, GtkOverlayChildClass))
+
+typedef struct _GtkOverlayChild GtkOverlayChild;
+typedef struct _GtkOverlayChildClass GtkOverlayChildClass;
+typedef struct _GtkOverlayChildPrivate GtkOverlayChildPrivate;
+
+struct _GtkOverlayChild
+{
+ GtkBin parent;
+
+ GtkOverlayChildPrivate *priv;
+};
+
+struct _GtkOverlayChildClass
+{
+ GtkBinClass parent_class;
+};
+
+GType gtk_overlay_child_get_type (void) G_GNUC_CONST;
+
+GtkOverlayChild *gtk_overlay_child_new (GtkWidget *widget);
+
+guint gtk_overlay_child_get_offset (GtkOverlayChild *child);
+
+void gtk_overlay_child_set_offset (GtkOverlayChild *child,
+ guint offset);
+
+gboolean gtk_overlay_child_get_fixed (GtkOverlayChild *child);
+
+void gtk_overlay_child_set_fixed (GtkOverlayChild *child,
+ gboolean fixed);
+
+G_END_DECLS
+
+#endif /* __GTK_OVERLAY_CHILD_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]