nautilus/eel/eel-wrap-table.c
Alexander Larsson 7e668edf20 eel/ Import eel into nautilus.
2008-12-15  Alexander Larsson  <alexl@redhat.com>

        * Makefile.am:
        * acconfig.h:
        * configure.in:
	* eel/
        * libnautilus-private/Makefile.am:
	Import eel into nautilus.


svn path=/trunk/; revision=14815
2008-12-15 15:56:41 +00:00

1054 lines
28 KiB
C

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* eel-wrap-box.c - A table that can wrap its contents as needed.
Copyright (C) 2000 Eazel, Inc.
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Gnome 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the Gnome Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Authors: Ramiro Estrugo <ramiro@eazel.com>
*/
#include <config.h>
#include "eel-wrap-table.h"
#include "eel-art-extensions.h"
#include "eel-art-gtk-extensions.h"
#include "eel-gtk-extensions.h"
#include "eel-gtk-macros.h"
#include "eel-types.h"
#include <gtk/gtk.h>
/* Arguments */
enum
{
PROP_0,
PROP_X_SPACING,
PROP_Y_SPACING,
PROP_X_JUSTIFICATION,
PROP_Y_JUSTIFICATION,
PROP_HOMOGENEOUS
};
/* Detail member struct */
struct EelWrapTableDetails
{
guint x_spacing;
guint y_spacing;
EelJustification x_justification;
EelJustification y_justification;
gboolean homogeneous;
GList *children;
guint is_scrolled : 1;
guint cols;
};
static void eel_wrap_table_class_init (EelWrapTableClass *wrap_table_class);
static void eel_wrap_table_init (EelWrapTable *wrap);
/* GObjectClass methods */
static void eel_wrap_table_finalize (GObject *object);
static void eel_wrap_table_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void eel_wrap_table_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
/* GtkWidgetClass methods */
static void eel_wrap_table_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static int eel_wrap_table_expose_event (GtkWidget *widget,
GdkEventExpose *event);
static void eel_wrap_table_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void eel_wrap_table_map (GtkWidget *widget);
static void eel_wrap_table_unmap (GtkWidget *widget);
static void eel_wrap_table_realize (GtkWidget *widget);
/* GtkContainerClass methods */
static void eel_wrap_table_add (GtkContainer *container,
GtkWidget *widget);
static void eel_wrap_table_remove (GtkContainer *container,
GtkWidget *widget);
static void eel_wrap_table_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data);
static GtkType eel_wrap_table_child_type (GtkContainer *container);
/* Private EelWrapTable methods */
static EelDimensions wrap_table_irect_max_dimensions (const EelDimensions *one,
const EelDimensions *two);
static EelDimensions wrap_table_get_max_child_dimensions (const EelWrapTable *wrap_table);
static EelDimensions wrap_table_get_content_dimensions (const EelWrapTable *wrap_table);
static EelIRect wrap_table_get_content_bounds (const EelWrapTable *wrap_table);
static gboolean wrap_table_child_focus_in (GtkWidget *widget,
GdkEventFocus *event,
gpointer data);
static void wrap_table_layout (EelWrapTable *wrap_table);
EEL_CLASS_BOILERPLATE (EelWrapTable, eel_wrap_table, GTK_TYPE_CONTAINER)
/* Class init methods */
static void
eel_wrap_table_class_init (EelWrapTableClass *wrap_table_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (wrap_table_class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (wrap_table_class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (wrap_table_class);
/* GObjectClass */
gobject_class->finalize = eel_wrap_table_finalize;
gobject_class->set_property = eel_wrap_table_set_property;
gobject_class->get_property = eel_wrap_table_get_property;
/* GtkWidgetClass */
widget_class->size_request = eel_wrap_table_size_request;
widget_class->size_allocate = eel_wrap_table_size_allocate;
widget_class->expose_event = eel_wrap_table_expose_event;
widget_class->map = eel_wrap_table_map;
widget_class->unmap = eel_wrap_table_unmap;
widget_class->realize = eel_wrap_table_realize;
/* GtkContainerClass */
container_class->add = eel_wrap_table_add;
container_class->remove = eel_wrap_table_remove;
container_class->forall = eel_wrap_table_forall;
container_class->child_type = eel_wrap_table_child_type;
/* Register some the enum types we need */
eel_type_init ();
/* Arguments */
g_object_class_install_property
(gobject_class,
PROP_X_SPACING,
g_param_spec_uint ("x_spacing", NULL, NULL,
0, G_MAXINT, 0, G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_Y_SPACING,
g_param_spec_uint ("y_spacing", NULL, NULL,
0, G_MAXINT, 0, G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_X_JUSTIFICATION,
g_param_spec_enum ("x_justification", NULL, NULL,
EEL_TYPE_JUSTIFICATION,
EEL_JUSTIFICATION_BEGINNING,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_Y_JUSTIFICATION,
g_param_spec_enum ("y_justification", NULL, NULL,
EEL_TYPE_JUSTIFICATION,
EEL_JUSTIFICATION_BEGINNING,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_HOMOGENEOUS,
g_param_spec_boolean ("homogenous", NULL, NULL,
FALSE, G_PARAM_READWRITE));
}
static void
eel_wrap_table_init (EelWrapTable *wrap_table)
{
GTK_WIDGET_SET_FLAGS (wrap_table, GTK_NO_WINDOW);
wrap_table->details = g_new0 (EelWrapTableDetails, 1);
wrap_table->details->x_justification = EEL_JUSTIFICATION_BEGINNING;
wrap_table->details->y_justification = EEL_JUSTIFICATION_END;
wrap_table->details->cols = 1;
}
static void
eel_wrap_table_finalize (GObject *object)
{
EelWrapTable *wrap_table;
wrap_table = EEL_WRAP_TABLE (object);
g_list_free (wrap_table->details->children);
g_free (wrap_table->details);
EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
/* GObjectClass methods */
static void
eel_wrap_table_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
EelWrapTable *wrap_table;
g_assert (EEL_IS_WRAP_TABLE (object));
wrap_table = EEL_WRAP_TABLE (object);
switch (property_id)
{
case PROP_X_SPACING:
eel_wrap_table_set_x_spacing (wrap_table, g_value_get_uint (value));
break;
case PROP_Y_SPACING:
eel_wrap_table_set_y_spacing (wrap_table, g_value_get_uint (value));
break;
case PROP_X_JUSTIFICATION:
eel_wrap_table_set_x_justification (wrap_table, g_value_get_enum (value));
break;
case PROP_Y_JUSTIFICATION:
eel_wrap_table_set_y_justification (wrap_table, g_value_get_enum (value));
break;
case PROP_HOMOGENEOUS:
eel_wrap_table_set_homogeneous (wrap_table, g_value_get_boolean (value));
break;
default:
g_assert_not_reached ();
}
}
static void
eel_wrap_table_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
EelWrapTable *wrap_table;
g_assert (EEL_IS_WRAP_TABLE (object));
wrap_table = EEL_WRAP_TABLE (object);
switch (property_id)
{
case PROP_X_SPACING:
g_value_set_uint (value, eel_wrap_table_get_x_spacing (wrap_table));
break;
case PROP_Y_SPACING:
g_value_set_uint (value, eel_wrap_table_get_y_spacing (wrap_table));
break;
case PROP_X_JUSTIFICATION:
g_value_set_enum (value, eel_wrap_table_get_x_justification (wrap_table));
break;
case PROP_Y_JUSTIFICATION:
g_value_set_enum (value, eel_wrap_table_get_y_justification (wrap_table));
break;
case PROP_HOMOGENEOUS:
g_value_set_boolean (value, eel_wrap_table_get_homogeneous (wrap_table));
break;
default:
g_assert_not_reached ();
}
}
/* GtkWidgetClass methods */
static void
eel_wrap_table_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
EelWrapTable *wrap_table;
EelDimensions content_dimensions;
g_assert (EEL_IS_WRAP_TABLE (widget));
g_assert (requisition != NULL);
wrap_table = EEL_WRAP_TABLE (widget);
content_dimensions = wrap_table_get_content_dimensions (wrap_table);
/* The -1 tells Satan to use as much space as is available */
requisition->width = -1;
requisition->height = content_dimensions.height + GTK_CONTAINER (widget)->border_width * 2;
}
static void
eel_wrap_table_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
EelWrapTable *wrap_table;
g_assert (EEL_IS_WRAP_TABLE (widget));
g_assert (allocation != NULL);
wrap_table = EEL_WRAP_TABLE (widget);
widget->allocation = *allocation;
wrap_table_layout (wrap_table);
}
static int
eel_wrap_table_expose_event (GtkWidget *widget,
GdkEventExpose *event)
{
EelWrapTable *wrap_table;
GList *iterator;
g_assert (EEL_IS_WRAP_TABLE (widget));
g_assert (GTK_WIDGET_REALIZED (widget));
g_assert (event != NULL);
wrap_table = EEL_WRAP_TABLE (widget);
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
g_assert (GTK_IS_WIDGET (iterator->data));
gtk_container_propagate_expose (GTK_CONTAINER (widget),
GTK_WIDGET (iterator->data),
event);
}
return FALSE;
}
static void
eel_wrap_table_map (GtkWidget *widget)
{
EelWrapTable *wrap_table;
GList *iterator;
g_assert (EEL_IS_WRAP_TABLE (widget));
wrap_table = EEL_WRAP_TABLE (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
GtkWidget *item;
item = iterator->data;
if (GTK_WIDGET_VISIBLE (item) && !GTK_WIDGET_MAPPED (item)) {
gtk_widget_map (item);
}
}
}
static void
eel_wrap_table_unmap (GtkWidget *widget)
{
EelWrapTable *wrap_table;
GList *iterator;
g_assert (EEL_IS_WRAP_TABLE (widget));
wrap_table = EEL_WRAP_TABLE (widget);
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
GtkWidget *item;
item = iterator->data;
if (GTK_WIDGET_VISIBLE (item) && GTK_WIDGET_MAPPED (item)) {
gtk_widget_unmap (item);
}
}
}
static void
eel_wrap_table_realize (GtkWidget *widget)
{
g_assert (EEL_IS_WRAP_TABLE (widget));
GTK_WIDGET_CLASS (parent_class)->realize (widget);
gtk_widget_queue_resize (widget);
}
/* GtkContainerClass methods */
static void
eel_wrap_table_add (GtkContainer *container,
GtkWidget *child)
{
EelWrapTable *wrap_table;
g_assert (container != NULL);
g_assert (EEL_IS_WRAP_TABLE (container));
g_assert (GTK_IS_WIDGET (child));
wrap_table = EEL_WRAP_TABLE (container);
gtk_widget_set_parent (child, GTK_WIDGET (container));
wrap_table->details->children = g_list_append (wrap_table->details->children, child);
if (GTK_WIDGET_REALIZED (container)) {
gtk_widget_realize (child);
}
if (GTK_WIDGET_VISIBLE (container) && GTK_WIDGET_VISIBLE (child)) {
if (GTK_WIDGET_MAPPED (container)) {
gtk_widget_map (child);
}
gtk_widget_queue_resize (child);
}
if (wrap_table->details->is_scrolled) {
g_signal_connect (child, "focus_in_event",
G_CALLBACK (wrap_table_child_focus_in),
wrap_table);
}
}
static void
eel_wrap_table_remove (GtkContainer *container,
GtkWidget *child)
{
EelWrapTable *wrap_table;
gboolean child_was_visible;
g_assert (EEL_IS_WRAP_TABLE (container));
g_assert (GTK_IS_WIDGET (child));
wrap_table = EEL_WRAP_TABLE (container);;
child_was_visible = GTK_WIDGET_VISIBLE (child);
gtk_widget_unparent (child);
wrap_table->details->children = g_list_remove (wrap_table->details->children, child);
if (child_was_visible) {
gtk_widget_queue_resize (GTK_WIDGET (container));
}
if (wrap_table->details->is_scrolled) {
g_signal_handlers_disconnect_by_func (
child,
G_CALLBACK (wrap_table_child_focus_in),
wrap_table);
}
}
static void
eel_wrap_table_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data)
{
EelWrapTable *wrap_table;
GList *node;
GList *next;
g_assert (EEL_IS_WRAP_TABLE (container));
g_assert (callback != NULL);
wrap_table = EEL_WRAP_TABLE (container);;
for (node = wrap_table->details->children; node != NULL; node = next) {
g_assert (GTK_IS_WIDGET (node->data));
next = node->next;
(* callback) (GTK_WIDGET (node->data), callback_data);
}
}
static GtkType
eel_wrap_table_child_type (GtkContainer *container)
{
return GTK_TYPE_WIDGET;
}
/* Private EelWrapTable methods */
static int
wrap_table_get_num_fitting (int available,
int spacing,
int max_child_size)
{
int num;
g_assert (max_child_size > 0);
g_assert (spacing >= 0);
available = MAX (available, 0);
num = (available + spacing) / (max_child_size + spacing);
num = MAX (num, 1);
return num;
}
static void
wrap_table_layout (EelWrapTable *wrap_table)
{
GList *iterator;
EelIPoint pos;
EelDimensions max_child_dimensions;
EelIRect content_bounds;
guint num_cols;
g_assert (EEL_IS_WRAP_TABLE (wrap_table));
max_child_dimensions = wrap_table_get_max_child_dimensions (wrap_table);
content_bounds = wrap_table_get_content_bounds (wrap_table);
pos.x = content_bounds.x0;
pos.y = content_bounds.y0;
num_cols = wrap_table_get_num_fitting (GTK_WIDGET (wrap_table)->allocation.width -
GTK_CONTAINER (wrap_table)->border_width * 2,
wrap_table->details->x_spacing,
max_child_dimensions.width);
if (num_cols != wrap_table->details->cols) {
wrap_table->details->cols = num_cols;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
return;
}
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
GtkWidget *item;
item = iterator->data;
if (GTK_WIDGET_VISIBLE (item)) {
GtkAllocation item_allocation;
if (wrap_table->details->homogeneous) {
item_allocation.x = pos.x;
item_allocation.y = pos.y;
item_allocation.width = max_child_dimensions.width;
item_allocation.height = max_child_dimensions.height;
if ((pos.x + max_child_dimensions.width) > content_bounds.x1) {
pos.x = content_bounds.x0 + wrap_table->details->x_spacing + max_child_dimensions.width;
pos.y += (max_child_dimensions.height + wrap_table->details->y_spacing);
item_allocation.x = content_bounds.x0;
item_allocation.y = pos.y;
} else {
pos.x += (wrap_table->details->x_spacing + max_child_dimensions.width);
}
} else {
GtkRequisition item_requisition;
gtk_widget_size_request (item, &item_requisition);
item_allocation.x = pos.x;
item_allocation.y = pos.y;
item_allocation.width = item_requisition.width;
item_allocation.height = item_requisition.height;
g_assert (item_allocation.width <= max_child_dimensions.width);
g_assert (item_allocation.height <= max_child_dimensions.height);
if ((pos.x + max_child_dimensions.width) > content_bounds.x1) {
pos.x = content_bounds.x0 + wrap_table->details->x_spacing + max_child_dimensions.width;
pos.y += (max_child_dimensions.height + wrap_table->details->y_spacing);
item_allocation.x = content_bounds.x0;
item_allocation.y = pos.y;
} else {
pos.x += (wrap_table->details->x_spacing + max_child_dimensions.width);
}
switch (wrap_table->details->x_justification) {
case EEL_JUSTIFICATION_MIDDLE:
item_allocation.x += (max_child_dimensions.width - (int) item_allocation.width) / 2;
break;
case EEL_JUSTIFICATION_END:
item_allocation.x += (max_child_dimensions.width - (int) item_allocation.width);
break;
default:
break;
}
switch (wrap_table->details->y_justification) {
case EEL_JUSTIFICATION_MIDDLE:
item_allocation.y += (max_child_dimensions.height - (int) item_allocation.height) / 2;
break;
case EEL_JUSTIFICATION_END:
item_allocation.y += (max_child_dimensions.height - (int) item_allocation.height);
break;
default:
break;
}
}
gtk_widget_size_allocate (item, &item_allocation);
}
}
}
static EelDimensions
wrap_table_irect_max_dimensions (const EelDimensions *one,
const EelDimensions *two)
{
EelDimensions max_dimensions;
g_assert (one != NULL);
g_assert (two != NULL);
max_dimensions.width = MAX (one->width, two->width);
max_dimensions.height = MAX (one->height, two->height);
return max_dimensions;
}
static EelDimensions
wrap_table_get_max_child_dimensions (const EelWrapTable *wrap_table)
{
EelDimensions max_dimensions;
GList *iterator;
g_assert (EEL_IS_WRAP_TABLE (wrap_table));
max_dimensions = eel_dimensions_empty;
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
GtkWidget *child;
child = iterator->data;
if (GTK_WIDGET_VISIBLE (child)) {
GtkRequisition child_requisition;
EelDimensions child_dimensions;
gtk_widget_size_request (child, &child_requisition);
child_dimensions.width = (int) child_requisition.width;
child_dimensions.height = (int) child_requisition.height;
max_dimensions = wrap_table_irect_max_dimensions (&child_dimensions, &max_dimensions);
}
}
return max_dimensions;
}
static EelDimensions
wrap_table_get_content_dimensions (const EelWrapTable *wrap_table)
{
EelDimensions content_dimensions;
guint num_children;
g_assert (EEL_IS_WRAP_TABLE (wrap_table));
content_dimensions = eel_dimensions_empty;
num_children = g_list_length (wrap_table->details->children);
if (num_children > 0) {
EelDimensions max_child_dimensions;
EelDimensions dimensions;
int num_cols;
int num_rows;
dimensions = eel_gtk_widget_get_dimensions (GTK_WIDGET (wrap_table));
max_child_dimensions = wrap_table_get_max_child_dimensions (wrap_table);
max_child_dimensions.width = MAX (max_child_dimensions.width, 1);
max_child_dimensions.height = MAX (max_child_dimensions.height, 1);
num_cols = wrap_table_get_num_fitting (dimensions.width -
GTK_CONTAINER (wrap_table)->border_width * 2,
wrap_table->details->x_spacing,
max_child_dimensions.width);
num_rows = num_children / num_cols;
num_rows = MAX (num_rows, 1);
if ((num_children % num_rows) > 0) {
num_rows++;
}
content_dimensions.width = dimensions.width;
content_dimensions.height = num_rows * max_child_dimensions.height;
content_dimensions.width += (num_cols - 1) * wrap_table->details->x_spacing;
content_dimensions.height += (num_rows - 1) * wrap_table->details->y_spacing;
}
return content_dimensions;
}
static EelIRect
wrap_table_get_content_bounds (const EelWrapTable *wrap_table)
{
EelIRect content_bounds;
g_assert (EEL_IS_WRAP_TABLE (wrap_table));
content_bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (wrap_table));
content_bounds.x0 += GTK_CONTAINER (wrap_table)->border_width;
content_bounds.y0 += GTK_CONTAINER (wrap_table)->border_width;
content_bounds.x1 -= GTK_CONTAINER (wrap_table)->border_width;
content_bounds.y1 -= GTK_CONTAINER (wrap_table)->border_width;
return content_bounds;
}
static gboolean
wrap_table_child_focus_in (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
g_assert (widget->parent && widget->parent->parent);
g_assert (GTK_IS_VIEWPORT (widget->parent->parent));
eel_gtk_viewport_scroll_to_rect (GTK_VIEWPORT (widget->parent->parent),
&widget->allocation);
return FALSE;
}
/**
* eel_wrap_table_new:
*
*/
GtkWidget*
eel_wrap_table_new (gboolean homogeneous)
{
EelWrapTable *wrap_table;
wrap_table = EEL_WRAP_TABLE (gtk_widget_new (eel_wrap_table_get_type (), NULL));
eel_wrap_table_set_homogeneous (wrap_table, homogeneous);
return GTK_WIDGET (wrap_table);
}
/**
* eel_wrap_table_set_x_spacing:
* @wrap_table: A EelWrapTable.
* @x_spacing: The new horizontal spacing between wraps.
*
*/
void
eel_wrap_table_set_x_spacing (EelWrapTable *wrap_table,
guint x_spacing)
{
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
if (wrap_table->details->x_spacing == x_spacing) {
return;
}
wrap_table->details->x_spacing = x_spacing;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_item_spacing:
* @wrap_table: A EelWrapTable.
*
* Returns: The horizontal spacing between wraps.
*/
guint
eel_wrap_table_get_x_spacing (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), 0);
return wrap_table->details->x_spacing;
}
/**
* eel_wrap_table_set_y_spacing:
* @wrap_table: A EelWrapTable.
* @y_spacing: The new horizontal spacing between wraps.
*
*/
void
eel_wrap_table_set_y_spacing (EelWrapTable *wrap_table,
guint y_spacing)
{
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
if (wrap_table->details->y_spacing == y_spacing) {
return;
}
wrap_table->details->y_spacing = y_spacing;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_item_spacing:
* @wrap_table: A EelWrapTable.
*
* Returns: The horizontal spacing between wraps.
*/
guint
eel_wrap_table_get_y_spacing (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), 0);
return wrap_table->details->y_spacing;
}
/**
* eel_wrap_table_find_child_at_event_point:
* @wrap_table: A EelWrapTable.
* @x: Event x;
* @y: Event y;
*
* Returns: Child found at given coordinates or NULL of no child is found.
*/
GtkWidget *
eel_wrap_table_find_child_at_event_point (const EelWrapTable *wrap_table,
int x,
int y)
{
GList *iterator;
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), NULL);
for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
GtkWidget *child;
child = iterator->data;
if (GTK_WIDGET_VISIBLE (child)) {
EelIRect child_bounds;
child_bounds = eel_gtk_widget_get_bounds (child);
if (eel_irect_contains_point (child_bounds, x, y)) {
return child;
}
}
}
return NULL;
}
/**
* eel_wrap_table_set_x_justification:
* @wrap_table: A EelWrapTable.
* @x_justification: The new horizontal justification between wraps.
*
*/
void
eel_wrap_table_set_x_justification (EelWrapTable *wrap_table,
EelJustification x_justification)
{
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
g_return_if_fail (x_justification >= EEL_JUSTIFICATION_BEGINNING);
g_return_if_fail (x_justification <= EEL_JUSTIFICATION_END);
if (wrap_table->details->x_justification == x_justification) {
return;
}
wrap_table->details->x_justification = x_justification;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_item_justification:
* @wrap_table: A EelWrapTable.
*
* Returns: The horizontal justification between wraps.
*/
EelJustification
eel_wrap_table_get_x_justification (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), 0);
return wrap_table->details->x_justification;
}
/**
* eel_wrap_table_set_y_justification:
* @wrap_table: A EelWrapTable.
* @y_justification: The new horizontal justification between wraps.
*
*/
void
eel_wrap_table_set_y_justification (EelWrapTable *wrap_table,
EelJustification y_justification)
{
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
g_return_if_fail (y_justification >= EEL_JUSTIFICATION_BEGINNING);
g_return_if_fail (y_justification <= EEL_JUSTIFICATION_END);
if (wrap_table->details->y_justification == y_justification) {
return;
}
wrap_table->details->y_justification = y_justification;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_item_justification:
* @wrap_table: A EelWrapTable.
*
* Returns: The horizontal justification between wraps.
*/
EelJustification
eel_wrap_table_get_y_justification (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), 0);
return wrap_table->details->y_justification;
}
/**
* eel_wrap_table_set_homogeneous:
* @wrap_table: A EelWrapTable.
* @homogeneous: The new horizontal spacing between wraps.
*
*/
void
eel_wrap_table_set_homogeneous (EelWrapTable *wrap_table,
gboolean homogeneous)
{
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
if (wrap_table->details->homogeneous == homogeneous) {
return;
}
wrap_table->details->homogeneous = homogeneous;
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_item_spacing:
* @wrap_table: A EelWrapTable.
*
* Returns: The horizontal spacing between wraps.
*/
gboolean
eel_wrap_table_get_homogeneous (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), FALSE);
return wrap_table->details->homogeneous;
}
/**
* eel_wrap_table_reorder_child:
* @wrap_table: A EelWrapTable.
* @child: Child to reorder.
* @position: New position to put child at.
*
* Reorder the given chilren into the given position.
*
* Position is interpreted as follows:
*
* 0 - Place child at start of table.
* -1 - Place child at end of table.
* n - Place child at nth position. Count starts at 0.
*/
void
eel_wrap_table_reorder_child (EelWrapTable *wrap_table,
GtkWidget *child,
int position)
{
GList *node;
gboolean found_child = FALSE;
g_return_if_fail (EEL_IS_WRAP_TABLE (wrap_table));
g_return_if_fail (g_list_length (wrap_table->details->children) > 0);
if (position == -1) {
position = g_list_length (wrap_table->details->children) - 1;
}
g_return_if_fail (position >= 0);
g_return_if_fail ((guint) position < g_list_length (wrap_table->details->children));
for (node = wrap_table->details->children; node != NULL; node = node->next) {
GtkWidget *next_child;
next_child = node->data;
if (next_child == child) {
g_assert (found_child == FALSE);
found_child = TRUE;
}
}
g_return_if_fail (found_child);
wrap_table->details->children = g_list_remove (wrap_table->details->children, child);
wrap_table->details->children = g_list_insert (wrap_table->details->children, child, position);
gtk_widget_queue_resize (GTK_WIDGET (wrap_table));
}
/**
* eel_wrap_table_get_num_children:
* @wrap_table: A EelWrapTable.
*
* Returns: The number of children being managed by the wrap table.
*/
guint
eel_wrap_table_get_num_children (const EelWrapTable *wrap_table)
{
g_return_val_if_fail (EEL_IS_WRAP_TABLE (wrap_table), 0);
return g_list_length (wrap_table->details->children);
}
GtkWidget *
eel_scrolled_wrap_table_new (gboolean homogenous,
GtkWidget **wrap_table_out)
{
GtkWidget *scrolled_window;
GtkWidget *wrap_table;
GtkWidget *viewport;
g_return_val_if_fail (wrap_table_out != NULL, NULL);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)),
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport),
GTK_SHADOW_NONE);
gtk_container_add (GTK_CONTAINER (scrolled_window),
viewport);
wrap_table = eel_wrap_table_new (homogenous);
gtk_container_add (GTK_CONTAINER (viewport),
wrap_table);
gtk_widget_show (wrap_table);
gtk_widget_show (viewport);
EEL_WRAP_TABLE (wrap_table)->details->is_scrolled = 1;
*wrap_table_out = wrap_table;
return scrolled_window;
}