Logo Search packages:      
Sourcecode: nautilus version File versions  Download package

eel-wrap-table.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 */
00047 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 GType         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_has_window (GTK_WIDGET (wrap_table), FALSE);

      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_get_border_width (GTK_CONTAINER (widget)) * 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);
      
      gtk_widget_set_allocation (widget, 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_get_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_mapped (widget, TRUE);
      
      for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
            GtkWidget *item;

            item = iterator->data;

            if (gtk_widget_get_visible (item) && !gtk_widget_get_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_set_mapped (widget, FALSE);

      for (iterator = wrap_table->details->children; iterator; iterator = iterator->next) {
            GtkWidget *item;

            item = iterator->data;

            if (gtk_widget_get_visible (item) && gtk_widget_get_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;
      GtkWidget *widget;

      g_assert (container != NULL);
      g_assert (EEL_IS_WRAP_TABLE (container));
      g_assert (GTK_IS_WIDGET (child));

      widget = GTK_WIDGET (container);
      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_get_realized (widget)) {
            gtk_widget_realize (child);
      }

      if (gtk_widget_get_visible (widget) && gtk_widget_get_visible (child)) {
            if (gtk_widget_get_mapped (widget)) {
                  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_get_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 GType
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;
      GtkAllocation allocation;

      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;

      gtk_widget_get_allocation (GTK_WIDGET (wrap_table), &allocation);
      num_cols = wrap_table_get_num_fitting (allocation.width -
                                     gtk_container_get_border_width (GTK_CONTAINER (wrap_table)) * 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_get_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_get_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_get_border_width (GTK_CONTAINER (wrap_table)) * 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;
      guint border;

      g_assert (EEL_IS_WRAP_TABLE (wrap_table));

      content_bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (wrap_table));

      border = gtk_container_get_border_width (GTK_CONTAINER (wrap_table));
      content_bounds.x0 += border;
      content_bounds.y0 += border;
      content_bounds.x1 -= border;
      content_bounds.y1 -= border;

      return content_bounds;
}

static gboolean
wrap_table_child_focus_in (GtkWidget *widget, 
                     GdkEventFocus *event, 
                     gpointer data)
{
      GtkWidget *parent, *pparent;
      GtkAllocation allocation;

      parent = gtk_widget_get_parent (widget);
      if (parent)
            pparent = gtk_widget_get_parent (parent);
      g_assert (parent && pparent);
      g_assert (GTK_IS_VIEWPORT (pparent));

      gtk_widget_get_allocation (widget, &allocation);
      eel_gtk_viewport_scroll_to_rect (GTK_VIEWPORT (pparent),
                               &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_get_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,
                       GtkShadowType shadow_type,
                       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),
                              shadow_type);
      
      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;
}

Generated by  Doxygen 1.6.0   Back to index