From 35858dad6fee8827135e00756860a9385eaf278e Mon Sep 17 00:00:00 2001 From: Nicola Fontana Date: Sat, 8 Jan 2011 17:34:31 +0100 Subject: [PATCH] [AdgGtkLayout] First implementation An widget that adds scrolling capabilities to the AdgGtkArea class. --- demo/adg-demo.ui.in | 12 +- src/adg-gtk.h | 1 + src/adg-gtk/Makefile.am | 5 +- .../adg-gtk-layout-private.h} | 23 +- src/adg-gtk/adg-gtk-layout.c | 486 +++++++++++++++++++++ src/adg-gtk/adg-gtk-layout.h | 72 +++ src/adg-gtk/tests/.gitignore | 1 + src/adg-gtk/tests/Makefile.am | 3 + src/adg-gtk/tests/test-gtk-layout.c | 151 +++++++ src/adg.xml | 3 + 10 files changed, 747 insertions(+), 10 deletions(-) copy src/{adg-gtk.h => adg-gtk/adg-gtk-layout-private.h} (71%) create mode 100644 src/adg-gtk/adg-gtk-layout.c create mode 100644 src/adg-gtk/adg-gtk-layout.h create mode 100644 src/adg-gtk/tests/test-gtk-layout.c diff --git a/demo/adg-demo.ui.in b/demo/adg-demo.ui.in index 62a99469..2222cbc7 100644 --- a/demo/adg-demo.ui.in +++ b/demo/adg-demo.ui.in @@ -12,9 +12,17 @@ True - + True - True + automatic + automatic + 800 + 400 + + + True + + 0 diff --git a/src/adg-gtk.h b/src/adg-gtk.h index c94df786..8db01c4c 100644 --- a/src/adg-gtk.h +++ b/src/adg-gtk.h @@ -26,5 +26,6 @@ #include "adg-gtk/adg-gtk-utils.h" #include "adg-gtk/adg-gtk-area.h" +#include "adg-gtk/adg-gtk-layout.h" #endif /* __ADG_GTK_H__ */ diff --git a/src/adg-gtk/Makefile.am b/src/adg-gtk/Makefile.am index 69896720..5a7ee07c 100644 --- a/src/adg-gtk/Makefile.am +++ b/src/adg-gtk/Makefile.am @@ -5,12 +5,15 @@ SUBDIRS= tests # file groups h_sources= adg-gtk-area.h \ + adg-gtk-layout.h \ adg-gtk-utils.h built_h_sources= private_h_sources= adg-gtk-area-private.h \ - adg-gtk-internal.h + adg-gtk-internal.h \ + adg-gtk-layout-private.h built_private_h_sources= adg-gtk-marshal.h c_sources= adg-gtk-area.c \ + adg-gtk-layout.c \ adg-gtk-utils.c built_c_sources= adg-gtk-marshal.c template_sources= adg-gtk-marshal.genmarshal diff --git a/src/adg-gtk.h b/src/adg-gtk/adg-gtk-layout-private.h similarity index 71% copy from src/adg-gtk.h copy to src/adg-gtk/adg-gtk-layout-private.h index c94df786..9f304275 100644 --- a/src/adg-gtk.h +++ b/src/adg-gtk/adg-gtk-layout-private.h @@ -18,13 +18,22 @@ */ -#ifndef __ADG_GTK_H__ -#define __ADG_GTK_H__ +#ifndef __ADG_GTK_LAYOUT_PRIVATE_H__ +#define __ADG_GTK_LAYOUT_PRIVATE_H__ -#include -#include -#include "adg-gtk/adg-gtk-utils.h" -#include "adg-gtk/adg-gtk-area.h" +G_BEGIN_DECLS -#endif /* __ADG_GTK_H__ */ +typedef struct _AdgGtkLayoutPrivate AdgGtkLayoutPrivate; + +struct _AdgGtkLayoutPrivate { + GtkAdjustment *hadjustment; + GtkAdjustment *vadjustment; + + CpmlExtents viewport; +}; + +G_END_DECLS + + +#endif /* __ADG_GTK_LAYOUT_PRIVATE_H__ */ diff --git a/src/adg-gtk/adg-gtk-layout.c b/src/adg-gtk/adg-gtk-layout.c new file mode 100644 index 00000000..0b1be77d --- /dev/null +++ b/src/adg-gtk/adg-gtk-layout.c @@ -0,0 +1,486 @@ +/* ADG - Automatic Drawing Generation + * Copyright (C) 2007,2008,2009,2010 Nicola Fontana + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +/** + * SECTION:adg-gtk-layout + * @short_description: A #GtkWidget specifically designed to contain + * an #AdgCanvas entity + * + * This is an #AdgGtkArea derived object with scrolling capabilities. + **/ + +/** + * AdgGtkLayout: + * + * All fields are private and should not be used directly. + * Use its public methods instead. + **/ + + +#include "adg-gtk-internal.h" +#include "adg-gtk-area.h" +#include "adg-gtk-layout.h" +#include "adg-gtk-layout-private.h" +#include "adg-gtk-marshal.h" + +#define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_gtk_layout_parent_class) +#define _ADG_OLD_WIDGET_CLASS ((GtkWidgetClass *) adg_gtk_layout_parent_class) +#define _ADG_OLD_AREA_CLASS ((AdgGtkAreaClass *) adg_gtk_layout_parent_class) + + +G_DEFINE_TYPE(AdgGtkLayout, adg_gtk_layout, ADG_GTK_TYPE_AREA); + +enum { + PROP_0, + PROP_HADJUSTMENT, + PROP_VADJUSTMENT +}; + + +static void _adg_dispose (GObject *object); +static void _adg_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void _adg_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void _adg_set_scroll_adjustments (GtkWidget *widget, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +static void _adg_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void _adg_canvas_changed (AdgGtkArea *area, + AdgCanvas *old_canvas); +static void _adg_extents_changed (AdgGtkArea *area, + const CpmlExtents *old_extents); +static void _adg_set_adjustment (AdgGtkLayout *layout, + GtkAdjustment **dst, + GtkAdjustment *src); +static void _adg_update_adjustments (AdgGtkLayout *layout); +static void _adg_value_changed (AdgGtkLayout *layout); + + +static void +adg_gtk_layout_class_init(AdgGtkLayoutClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + AdgGtkAreaClass *area_class; + GParamSpec *param; + GClosure *closure; + GType param_types[2]; + + gobject_class = (GObjectClass *) klass; + widget_class = (GtkWidgetClass *) klass; + area_class = (AdgGtkAreaClass *) klass; + + g_type_class_add_private(klass, sizeof(AdgGtkLayoutPrivate)); + + gobject_class->dispose = _adg_dispose; + gobject_class->get_property = _adg_get_property; + gobject_class->set_property = _adg_set_property; + + widget_class->size_allocate = _adg_size_allocate; + + area_class->canvas_changed = _adg_canvas_changed; + area_class->extents_changed = _adg_extents_changed; + + param = g_param_spec_object("hadjustment", + P_("Horizontal adjustment"), + P_("The GtkAdjustment that determines the values of the horizontal position for this viewport"), + GTK_TYPE_ADJUSTMENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(gobject_class, PROP_HADJUSTMENT, param); + + param = g_param_spec_object("vadjustment", + P_("Vertical adjustment"), + P_("The GtkAdjustment that determines the values of the vertical position for this viewport"), + GTK_TYPE_ADJUSTMENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(gobject_class, PROP_VADJUSTMENT, param); + + /** + * AdgGtkLayout::set-scroll-adjustments: + * @layout: an #AdgGtkLayout + * @old_canvas: the old #AdgCanvas object + * + * Emitted when the #AdgGtkLayout scroll adjustments have been set. + **/ + closure = g_cclosure_new(G_CALLBACK(_adg_set_scroll_adjustments), NULL, NULL); + param_types[0] = GTK_TYPE_ADJUSTMENT; + param_types[1] = GTK_TYPE_ADJUSTMENT; + widget_class->set_scroll_adjustments_signal = + g_signal_newv("set-scroll-adjustments", ADG_GTK_TYPE_LAYOUT, + G_SIGNAL_RUN_LAST, closure, NULL, NULL, + adg_gtk_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, param_types); +} + +static void +adg_gtk_layout_init(AdgGtkLayout *layout) +{ + AdgGtkLayoutPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(layout, + ADG_GTK_TYPE_LAYOUT, + AdgGtkLayoutPrivate); + + data->hadjustment = NULL; + data->vadjustment = NULL; + data->viewport.is_defined = FALSE; + + layout->data = data; +} + +static void +_adg_dispose(GObject *object) +{ + AdgGtkLayoutPrivate *data = ((AdgGtkLayout *) object)->data; + + if (data->hadjustment != NULL) { + g_object_unref(data->hadjustment); + data->hadjustment = NULL; + } + + if (data->vadjustment != NULL) { + g_object_unref(data->vadjustment); + data->vadjustment = NULL; + } + + if (_ADG_OLD_OBJECT_CLASS->dispose != NULL) + _ADG_OLD_OBJECT_CLASS->dispose(object); +} + +static void +_adg_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + AdgGtkLayoutPrivate *data = ((AdgGtkLayout *) object)->data; + + switch (prop_id) { + case PROP_HADJUSTMENT: + g_value_set_object(value, data->hadjustment); + break; + case PROP_VADJUSTMENT: + g_value_set_object(value, data->vadjustment); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +_adg_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + AdgGtkLayout *layout; + AdgGtkLayoutPrivate *data; + GtkAdjustment *adjustment; + + layout = (AdgGtkLayout *) object; + data = layout->data; + + switch (prop_id) { + case PROP_HADJUSTMENT: + adjustment = g_value_get_object(value); + if (adjustment == NULL) + adjustment = (GtkAdjustment *) gtk_adjustment_new(0, 0, 0, 0, 0, 0); + + _adg_set_adjustment(layout, &data->hadjustment, adjustment); + break; + case PROP_VADJUSTMENT: + adjustment = g_value_get_object(value); + if (adjustment == NULL) + adjustment = (GtkAdjustment *) gtk_adjustment_new(0, 0, 0, 0, 0, 0); + + _adg_set_adjustment(layout, &data->vadjustment, adjustment); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +/** + * adg_gtk_layout_new: + * + * Creates a new empty #AdgGtkLayout. The widget is useful only after + * an #AdgCanvas has been added either using the #AdgGtkLayout:canvas + * property or with adg_gtk_layout_set_canvas(). + * + * Returns: the newly created widget + **/ +GtkWidget * +adg_gtk_layout_new(void) +{ + return g_object_new(ADG_GTK_TYPE_LAYOUT, NULL); +} + +/** + * adg_gtk_layout_new_with_canvas: + * @canvas: the #AdgCanvas shown by this widget + * + * Creates a new #AdgGtkLayout and sets the #AdgGtkLayout:canvas property + * to @canvas. + * + * Returns: the newly created widget + **/ +GtkWidget * +adg_gtk_layout_new_with_canvas(AdgCanvas *canvas) +{ + g_return_val_if_fail(ADG_IS_CANVAS(canvas), NULL); + + return g_object_new(ADG_GTK_TYPE_LAYOUT, "canvas", canvas, NULL); +} + +/** + * adg_gtk_layout_set_hadjustment: + * @layout: an #AdgGtkLayout + * @hadjustment: the new adjustment + * + * Sets the new horizontal adjustment for @layout to @hadjustment. + * The old adjustment, if present, is unreferenced. + * + * This is basically the same as manually setting the + * #AdgGtkLayout:hadjustment property with g_object_set(). + **/ +void +adg_gtk_layout_set_hadjustment(AdgGtkLayout *layout, + GtkAdjustment *hadjustment) +{ + g_return_if_fail(ADG_GTK_IS_LAYOUT(layout)); + g_object_set(layout, "hadjustment", hadjustment, NULL); +} + +/** + * adg_gtk_layout_get_hadjustment: + * @layout: an #AdgGtkLayout + * + * Retrieves the current horizontal adjustment of @layout. + **/ +GtkAdjustment * +adg_gtk_layout_get_hadjustment(AdgGtkLayout *layout) +{ + AdgGtkLayoutPrivate *data; + + g_return_val_if_fail(ADG_GTK_IS_LAYOUT(layout), NULL); + + data = layout->data; + + return data->hadjustment; +} + +/** + * adg_gtk_layout_set_vadjustment: + * @layout: an #AdgGtkLayout + * @vadjustment: the new adjustment + * + * Sets the new vertical adjustment for @layout to @vadjustment. + * The old adjustment, if present, is unreferenced. + * + * This is basically the same as manually setting the + * #AdgGtkLayout:vadjustment property with g_object_set(). + **/ +void +adg_gtk_layout_set_vadjustment(AdgGtkLayout *layout, + GtkAdjustment *vadjustment) +{ + g_return_if_fail(ADG_GTK_IS_LAYOUT(layout)); + g_object_set(layout, "vadjustment", vadjustment, NULL); +} + +/** + * adg_gtk_layout_get_vadjustment: + * @layout: an #AdgGtkLayout + * + * Retrieves the current vertical adjustment of @layout. + **/ +GtkAdjustment * +adg_gtk_layout_get_vadjustment(AdgGtkLayout *layout) +{ + AdgGtkLayoutPrivate *data; + + g_return_val_if_fail(ADG_GTK_IS_LAYOUT(layout), NULL); + + data = layout->data; + + return data->vadjustment; +} + + +static void +_adg_set_scroll_adjustments(GtkWidget *widget, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + g_object_set(widget, + "hadjustment", hadjustment, + "vadjustment", vadjustment, + NULL); +} + +static void +_adg_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + AdgGtkLayout *layout; + AdgGtkLayoutPrivate *data; + + layout = (AdgGtkLayout *) widget; + data = layout->data; + + if (_ADG_OLD_WIDGET_CLASS->size_allocate) + _ADG_OLD_WIDGET_CLASS->size_allocate(widget, allocation); + + + /* Resize the viewport on a new allocation. + * TODO: plan other policies instead of forcibly set only the + * size field on the viewport struct, such as modifying the + * org to keep the sheet centered in the allocation space. */ + data->viewport.size.x = allocation->width; + data->viewport.size.y = allocation->height; + data->viewport.is_defined = TRUE; + + _adg_update_adjustments(layout); +} + +static void +_adg_canvas_changed(AdgGtkArea *area, AdgCanvas *old_canvas) +{ + AdgGtkLayoutPrivate *data = ((AdgGtkLayout *) area)->data; + + if (_ADG_OLD_AREA_CLASS->canvas_changed != NULL) + _ADG_OLD_AREA_CLASS->canvas_changed(area, old_canvas); + + /* By convention, expect the origin of a new canvas to be + * on the top/left corner of the allocation area */ + data->viewport.org.x = 0; + data->viewport.org.y = 0; +} + +static void +_adg_extents_changed(AdgGtkArea *area, const CpmlExtents *old_extents) +{ + if (_ADG_OLD_AREA_CLASS->extents_changed != NULL) + _ADG_OLD_AREA_CLASS->extents_changed(area, old_extents); + + _adg_update_adjustments((AdgGtkLayout *) area); +} + +static void +_adg_set_adjustment(AdgGtkLayout *layout, + GtkAdjustment **dst, GtkAdjustment *src) +{ + GCallback value_changed; + + if (*dst == src) + return; + + value_changed = G_CALLBACK(_adg_value_changed); + + if (*dst != NULL) { + /* Release the old adjustment */ + g_signal_handlers_disconnect_by_func(*dst, value_changed, layout); + g_object_unref(*dst); + } + + g_signal_connect_swapped(src, "value-changed", value_changed, layout); + g_object_ref_sink(src); + + *dst = src; +} + +/** + * _adg_update_adjustments: + * @layout: an #AdgGtkLayout + * + * Updates the scrollbars according to the new extents of the canvas + * of @area and to the current viewport. + * + * The algorithm uses three local #CpmlExtents variables: the + * viewport (what physically shown by the graphic device), + * the sheet (the extents of the drawing, margins + * included) and surface (a helper variable that is the + * union of the previous two extents). + **/ +static void +_adg_update_adjustments(AdgGtkLayout *layout) +{ + AdgGtkArea *area; + AdgCanvas *canvas; + const CpmlExtents *sheet, *viewport; + AdgGtkLayoutPrivate *data; + GtkAdjustment *hadj, *vadj; + CpmlExtents surface; + + area = (AdgGtkArea *) layout; + canvas = adg_gtk_area_get_canvas(area); + if (canvas == NULL) + return; + + sheet = adg_gtk_area_get_extents(area); + if (sheet == NULL || !sheet->is_defined) + return; + + data = layout->data; + hadj = data->hadjustment; + vadj = data->vadjustment; + viewport = &data->viewport; + surface = *sheet; + cpml_extents_add(&surface, viewport); + + g_object_set(hadj, + "lower", surface.org.x, + "upper", surface.org.x + surface.size.x, + "page-size", viewport->size.x, + "value", viewport->org.x, + NULL); + g_object_set(vadj, + "lower", surface.org.y, + "upper", surface.org.y + surface.size.y, + "page-size", viewport->size.y, + "value", viewport->org.y, + NULL); +} + +static void +_adg_value_changed(AdgGtkLayout *layout) +{ + AdgGtkArea *area; + AdgGtkLayoutPrivate *data; + AdgPair org; + AdgMatrix map; + + if (!GTK_WIDGET_REALIZED(layout)) + return; + + area = (AdgGtkArea *) layout; + data = layout->data; + org.x = gtk_adjustment_get_value(data->hadjustment); + org.y = gtk_adjustment_get_value(data->vadjustment); + + cairo_matrix_init_translate(&map, data->viewport.org.x - org.x, + data->viewport.org.y - org.y); + adg_gtk_area_transform_render_map(area, &map, ADG_TRANSFORM_BEFORE); + + gtk_widget_queue_draw((GtkWidget *) layout); + _adg_update_adjustments(layout); +} diff --git a/src/adg-gtk/adg-gtk-layout.h b/src/adg-gtk/adg-gtk-layout.h new file mode 100644 index 00000000..182a7fab --- /dev/null +++ b/src/adg-gtk/adg-gtk-layout.h @@ -0,0 +1,72 @@ +/* ADG - Automatic Drawing Generation + * Copyright (C) 2007,2008,2009,2010 Nicola Fontana + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#if !defined(__ADG_GTK_H__) +#error "Only can be included directly." +#endif + + +#ifndef __ADG_GTK_LAYOUT_H__ +#define __ADG_GTK_LAYOUT_H__ + + +G_BEGIN_DECLS + +#define ADG_GTK_TYPE_LAYOUT (adg_gtk_layout_get_type()) +#define ADG_GTK_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), ADG_GTK_TYPE_LAYOUT, AdgGtkLayout)) +#define ADG_GTK_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ADG_GTK_TYPE_LAYOUT, AdgGtkLayoutClass)) +#define ADG_GTK_IS_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), ADG_GTK_TYPE_LAYOUT)) +#define ADG_GTK_IS_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ADG_GTK_TYPE_LAYOUT)) +#define ADG_GTK_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), ADG_GTK_TYPE_LAYOUT, AdgGtkLayoutClass)) + +typedef struct _AdgGtkLayout AdgGtkLayout; +typedef struct _AdgGtkLayoutClass AdgGtkLayoutClass; + +struct _AdgGtkLayout { + /*< private >*/ + AdgGtkArea parent; + gpointer data; +}; + +struct _AdgGtkLayoutClass { + /*< private >*/ + AdgGtkAreaClass parent_class; + /*< public >*/ + /* Virtual Table */ + void (*canvas_changed) (AdgGtkLayout *layout); +}; + + +GType adg_gtk_layout_get_type (void) G_GNUC_CONST; + +GtkWidget * adg_gtk_layout_new (void); +GtkWidget * adg_gtk_layout_new_with_canvas (AdgCanvas *canvas); +void adg_gtk_layout_set_hadjustment (AdgGtkLayout *layout, + GtkAdjustment *hadjustment); +GtkAdjustment * adg_gtk_layout_get_hadjustment (AdgGtkLayout *layout); +void adg_gtk_layout_set_vadjustment (AdgGtkLayout *layout, + GtkAdjustment *vadjustment); +GtkAdjustment * adg_gtk_layout_get_vadjustment (AdgGtkLayout *layout); + + +G_END_DECLS + + +#endif /* __ADG_GTK_LAYOUT_H__ */ diff --git a/src/adg-gtk/tests/.gitignore b/src/adg-gtk/tests/.gitignore index 37d4ec28..cd01ab42 100644 --- a/src/adg-gtk/tests/.gitignore +++ b/src/adg-gtk/tests/.gitignore @@ -1 +1,2 @@ /test-gtk-area +/test-gtk-layout diff --git a/src/adg-gtk/tests/Makefile.am b/src/adg-gtk/tests/Makefile.am index 5aaf5456..6e9aea6f 100644 --- a/src/adg-gtk/tests/Makefile.am +++ b/src/adg-gtk/tests/Makefile.am @@ -14,6 +14,9 @@ if HAVE_TEST_FRAMEWORK TEST_PROGS+= test-gtk-area$(EXEEXT) test_gtk_area_SOURCES= test-gtk-area.c +TEST_PROGS+= test-gtk-layout$(EXEEXT) +test_gtk_layout_SOURCES= test-gtk-layout.c + endif diff --git a/src/adg-gtk/tests/test-gtk-layout.c b/src/adg-gtk/tests/test-gtk-layout.c new file mode 100644 index 00000000..c47ef9b2 --- /dev/null +++ b/src/adg-gtk/tests/test-gtk-layout.c @@ -0,0 +1,151 @@ +/* ADG - Automatic Drawing Generation + * Copyright (C) 2010 Nicola Fontana + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include +#include + + +static void +_adg_test_hadjustment(void) +{ + AdgGtkLayout *layout; + GtkAdjustment *valid_adjustment, *invalid_adjustment, *hadjustment; + + layout = ADG_GTK_LAYOUT(adg_gtk_layout_new()); + valid_adjustment = (GtkAdjustment *) gtk_adjustment_new(0, 0, 0, 0, 0, 0); + invalid_adjustment = adg_test_invalid_pointer(); + + g_object_ref(valid_adjustment); + + /* Using the public APIs */ + g_test_message("The implementation must provide a fallback adjustment"); + hadjustment = adg_gtk_layout_get_hadjustment(layout); + g_assert(GTK_IS_ADJUSTMENT(hadjustment)); + + adg_gtk_layout_set_hadjustment(layout, NULL); + hadjustment = adg_gtk_layout_get_hadjustment(layout); + g_assert(GTK_IS_ADJUSTMENT(hadjustment)); + + adg_gtk_layout_set_hadjustment(layout, valid_adjustment); + hadjustment = adg_gtk_layout_get_hadjustment(layout); + g_assert(hadjustment == valid_adjustment); + + adg_gtk_layout_set_hadjustment(layout, invalid_adjustment); + hadjustment = adg_gtk_layout_get_hadjustment(layout); + g_assert(hadjustment == valid_adjustment); + + adg_gtk_layout_set_hadjustment(layout, NULL); + hadjustment = adg_gtk_layout_get_hadjustment(layout); + g_assert(hadjustment != valid_adjustment && GTK_IS_ADJUSTMENT(hadjustment)); + + /* Using GObject property methods */ + g_object_set(layout, "hadjustment", NULL, NULL); + g_object_get(layout, "hadjustment", &hadjustment, NULL); + g_assert(GTK_IS_ADJUSTMENT(hadjustment)); + g_object_unref(hadjustment); + + g_object_set(layout, "hadjustment", valid_adjustment, NULL); + g_object_get(layout, "hadjustment", &hadjustment, NULL); + g_assert(hadjustment == valid_adjustment); + g_object_unref(hadjustment); + + g_object_set(layout, "hadjustment", invalid_adjustment, NULL); + g_object_get(layout, "hadjustment", &hadjustment, NULL); + g_assert(hadjustment == valid_adjustment); + g_object_unref(hadjustment); + + g_object_set(layout, "hadjustment", NULL, NULL); + g_object_get(layout, "hadjustment", &hadjustment, NULL); + g_assert(hadjustment != valid_adjustment && GTK_IS_ADJUSTMENT(hadjustment)); + g_object_unref(hadjustment); + + g_object_unref(layout); + g_object_unref(valid_adjustment); +} + +static void +_adg_test_vadjustment(void) +{ + AdgGtkLayout *layout; + GtkAdjustment *valid_adjustment, *invalid_adjustment, *vadjustment; + + layout = ADG_GTK_LAYOUT(adg_gtk_layout_new()); + valid_adjustment = (GtkAdjustment *) gtk_adjustment_new(0, 0, 0, 0, 0, 0); + invalid_adjustment = adg_test_invalid_pointer(); + + g_object_ref(valid_adjustment); + + /* Using the public APIs */ + g_test_message("The implementation must provide a fallback adjustment"); + vadjustment = adg_gtk_layout_get_vadjustment(layout); + g_assert(GTK_IS_ADJUSTMENT(vadjustment)); + + adg_gtk_layout_set_vadjustment(layout, NULL); + vadjustment = adg_gtk_layout_get_vadjustment(layout); + g_assert(GTK_IS_ADJUSTMENT(vadjustment)); + + adg_gtk_layout_set_vadjustment(layout, valid_adjustment); + vadjustment = adg_gtk_layout_get_vadjustment(layout); + g_assert(vadjustment == valid_adjustment); + + adg_gtk_layout_set_vadjustment(layout, invalid_adjustment); + vadjustment = adg_gtk_layout_get_vadjustment(layout); + g_assert(vadjustment == valid_adjustment); + + adg_gtk_layout_set_vadjustment(layout, NULL); + vadjustment = adg_gtk_layout_get_vadjustment(layout); + g_assert(vadjustment != valid_adjustment && GTK_IS_ADJUSTMENT(vadjustment)); + + /* Using GObject property methods */ + g_object_set(layout, "vadjustment", NULL, NULL); + g_object_get(layout, "vadjustment", &vadjustment, NULL); + g_assert(GTK_IS_ADJUSTMENT(vadjustment)); + g_object_unref(vadjustment); + + g_object_set(layout, "vadjustment", valid_adjustment, NULL); + g_object_get(layout, "vadjustment", &vadjustment, NULL); + g_assert(vadjustment == valid_adjustment); + g_object_unref(vadjustment); + + g_object_set(layout, "vadjustment", invalid_adjustment, NULL); + g_object_get(layout, "vadjustment", &vadjustment, NULL); + g_assert(vadjustment == valid_adjustment); + g_object_unref(vadjustment); + + g_object_set(layout, "vadjustment", NULL, NULL); + g_object_get(layout, "vadjustment", &vadjustment, NULL); + g_assert(vadjustment != valid_adjustment && GTK_IS_ADJUSTMENT(vadjustment)); + g_object_unref(vadjustment); + + g_object_unref(layout); + g_object_unref(valid_adjustment); +} + + +int +main(int argc, char *argv[]) +{ + adg_test_init(&argc, &argv); + + adg_test_add_func("/adg/gtk/layout/hadjustment", _adg_test_hadjustment); + adg_test_add_func("/adg/gtk/layout/vadjustment", _adg_test_vadjustment); + + return g_test_run(); +} diff --git a/src/adg.xml b/src/adg.xml index 58735e90..5f9e3799 100644 --- a/src/adg.xml +++ b/src/adg.xml @@ -5,11 +5,14 @@ + + -- 2.11.4.GIT