nautilus/eel/eel-image-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

580 lines
15 KiB
C

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* eel-image-table.c - An image table.
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-image-table.h"
#include "eel-art-extensions.h"
#include "eel-art-gtk-extensions.h"
#include "eel-debug-drawing.h"
#include "eel-gtk-extensions.h"
#include "eel-gtk-macros.h"
#include "eel-labeled-image.h"
#include "eel-marshal.h"
#include <gtk/gtk.h>
/* Arguments */
enum
{
ARG_0,
ARG_CHILD_UNDER_POINTER
};
/* Detail member struct */
struct EelImageTableDetails
{
GtkWidget *child_under_pointer;
GtkWidget *child_being_pressed;
GdkGC *clear_gc;
};
/* Signals */
typedef enum
{
CHILD_ENTER,
CHILD_LEAVE,
CHILD_PRESSED,
CHILD_RELEASED,
CHILD_CLICKED,
LAST_SIGNAL
} ImageTableSignals;
/* Signals */
static guint image_table_signals[LAST_SIGNAL] = { 0 };
static void eel_image_table_class_init (EelImageTableClass *image_table_class);
static void eel_image_table_init (EelImageTable *image);
/* GObjectClass methods */
static void eel_image_table_finalize (GObject *object);
/* GtkWidgetClass methods */
static void eel_image_table_realize (GtkWidget *widget);
static void eel_image_table_unrealize (GtkWidget *widget);
/* GtkContainerClass methods */
static void eel_image_table_remove (GtkContainer *container,
GtkWidget *widget);
static GtkType eel_image_table_child_type (GtkContainer *container);
/* Private EelImageTable methods */
static void image_table_emit_signal (EelImageTable *image_table,
GtkWidget *child,
guint signal_index,
int x,
int y,
int button,
guint state,
GdkEvent *event);
/* Ancestor callbacks */
static int ancestor_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
gpointer event_data);
static int ancestor_leave_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
gpointer event_data);
static int ancestor_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event,
gpointer event_data);
static int ancestor_button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer event_data);
static int ancestor_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer event_data);
EEL_CLASS_BOILERPLATE (EelImageTable, eel_image_table, EEL_TYPE_WRAP_TABLE)
static void
eel_image_table_class_init (EelImageTableClass *image_table_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (image_table_class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (image_table_class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (image_table_class);
/* GObjectClass */
object_class->finalize = eel_image_table_finalize;
/* GtkWidgetClass */
widget_class->realize = eel_image_table_realize;
widget_class->unrealize = eel_image_table_unrealize;
/* GtkContainerClass */
container_class->remove = eel_image_table_remove;
container_class->child_type = eel_image_table_child_type;
/* Signals */
image_table_signals[CHILD_ENTER] = g_signal_new ("child_enter",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EelImageTableClass, child_enter),
NULL, NULL,
eel_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2,
GTK_TYPE_WIDGET,
G_TYPE_POINTER);
image_table_signals[CHILD_LEAVE] = g_signal_new ("child_leave",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EelImageTableClass, child_leave),
NULL, NULL,
eel_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2,
GTK_TYPE_WIDGET,
G_TYPE_POINTER);
image_table_signals[CHILD_PRESSED] = g_signal_new ("child_pressed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EelImageTableClass, child_pressed),
NULL, NULL,
eel_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2,
GTK_TYPE_WIDGET,
G_TYPE_POINTER);
image_table_signals[CHILD_RELEASED] = g_signal_new ("child_released",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EelImageTableClass, child_released),
NULL, NULL,
eel_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2,
GTK_TYPE_WIDGET,
G_TYPE_POINTER);
image_table_signals[CHILD_CLICKED] = g_signal_new ("child_clicked",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EelImageTableClass, child_clicked),
NULL, NULL,
eel_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2,
GTK_TYPE_WIDGET,
G_TYPE_POINTER);
}
static void
eel_image_table_init (EelImageTable *image_table)
{
GTK_WIDGET_SET_FLAGS (image_table, GTK_NO_WINDOW);
image_table->details = g_new0 (EelImageTableDetails, 1);
}
/* GObjectClass methods */
static void
eel_image_table_finalize (GObject *object)
{
EelImageTable *image_table;
image_table = EEL_IMAGE_TABLE (object);
g_free (image_table->details);
EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
static void
eel_image_table_realize (GtkWidget *widget)
{
GtkWidget *windowed_ancestor;
g_assert (EEL_IS_IMAGE_TABLE (widget));
/* Chain realize */
EEL_CALL_PARENT (GTK_WIDGET_CLASS, realize, (widget));
windowed_ancestor = eel_gtk_widget_find_windowed_ancestor (widget);
g_assert (GTK_IS_WIDGET (windowed_ancestor));
gtk_widget_add_events (windowed_ancestor,
GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_BUTTON_MOTION_MASK
| GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK
| GDK_POINTER_MOTION_MASK);
eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
"enter_notify_event",
G_CALLBACK (ancestor_enter_notify_event),
widget,
widget);
eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
"leave_notify_event",
G_CALLBACK (ancestor_leave_notify_event),
widget,
widget);
eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
"motion_notify_event",
G_CALLBACK (ancestor_motion_notify_event),
widget,
widget);
eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
"button_press_event",
G_CALLBACK (ancestor_button_press_event),
widget,
widget);
eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
"button_release_event",
G_CALLBACK (ancestor_button_release_event),
widget,
widget);
}
static void
eel_image_table_unrealize (GtkWidget *widget)
{
EelImageTable *image_table;
g_assert (EEL_IS_IMAGE_TABLE (widget));
image_table = EEL_IMAGE_TABLE (widget);
if (image_table->details->clear_gc != NULL) {
g_object_unref (image_table->details->clear_gc);
image_table->details->clear_gc = NULL;
}
/* Chain unrealize */
EEL_CALL_PARENT (GTK_WIDGET_CLASS, unrealize, (widget));
}
/* GtkContainerClass methods */
static void
eel_image_table_remove (GtkContainer *container,
GtkWidget *child)
{
EelImageTable *image_table;
g_assert (EEL_IS_IMAGE_TABLE (container));
g_assert (EEL_IS_LABELED_IMAGE (child));
image_table = EEL_IMAGE_TABLE (container);
if (child == image_table->details->child_under_pointer) {
image_table->details->child_under_pointer = NULL;
}
if (child == image_table->details->child_being_pressed) {
image_table->details->child_being_pressed = NULL;
}
EEL_CALL_PARENT (GTK_CONTAINER_CLASS, remove, (container, child));
}
static GtkType
eel_image_table_child_type (GtkContainer *container)
{
return EEL_TYPE_LABELED_IMAGE;
}
/* Private EelImageTable methods */
static void
image_table_emit_signal (EelImageTable *image_table,
GtkWidget *child,
guint signal_index,
int x,
int y,
int button,
guint state,
GdkEvent *gdk_event)
{
EelImageTableEvent event;
g_assert (EEL_IS_IMAGE_TABLE (image_table));
g_assert (GTK_IS_WIDGET (child));
g_assert (signal_index < LAST_SIGNAL);
event.x = x;
event.y = y;
event.button = button;
event.state = state;
event.event = gdk_event;
g_signal_emit (image_table,
image_table_signals[signal_index],
0,
child,
&event);
}
static void
image_table_handle_motion (EelImageTable *image_table,
int x,
int y,
GdkEvent *event)
{
GtkWidget *child;
GtkWidget *leave_emit_child = NULL;
GtkWidget *enter_emit_child = NULL;
g_assert (EEL_IS_IMAGE_TABLE (image_table));
child = eel_wrap_table_find_child_at_event_point (EEL_WRAP_TABLE (image_table), x, y);
if (child && !GTK_WIDGET_SENSITIVE (child)) {
return;
}
if (child == image_table->details->child_under_pointer) {
return;
}
if (child != NULL) {
if (image_table->details->child_under_pointer != NULL) {
leave_emit_child = image_table->details->child_under_pointer;
}
image_table->details->child_under_pointer = child;
enter_emit_child = image_table->details->child_under_pointer;
} else {
if (image_table->details->child_under_pointer != NULL) {
leave_emit_child = image_table->details->child_under_pointer;
}
image_table->details->child_under_pointer = NULL;
}
if (leave_emit_child != NULL) {
image_table_emit_signal (image_table,
leave_emit_child,
CHILD_LEAVE,
x,
y,
0,
0,
(GdkEvent *)event);
}
if (enter_emit_child != NULL) {
image_table_emit_signal (image_table,
enter_emit_child,
CHILD_ENTER,
x,
y,
0,
0,
(GdkEvent *)event);
}
}
static int
ancestor_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
gpointer event_data)
{
g_assert (GTK_IS_WIDGET (widget));
g_assert (EEL_IS_IMAGE_TABLE (event_data));
g_assert (event != NULL);
image_table_handle_motion (EEL_IMAGE_TABLE (event_data), event->x, event->y, (GdkEvent *) event);
return FALSE;
}
static int
ancestor_leave_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
gpointer event_data)
{
EelIRect bounds;
int x = -1;
int y = -1;
g_assert (GTK_IS_WIDGET (widget));
g_assert (EEL_IS_IMAGE_TABLE (event_data));
g_assert (event != NULL);
bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (event_data));
if (eel_irect_contains_point (bounds, event->x, event->y)) {
x = event->x;
y = event->y;
}
image_table_handle_motion (EEL_IMAGE_TABLE (event_data), x, y, (GdkEvent *) event);
return FALSE;
}
static int
ancestor_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event,
gpointer event_data)
{
g_assert (GTK_IS_WIDGET (widget));
g_assert (EEL_IS_IMAGE_TABLE (event_data));
g_assert (event != NULL);
image_table_handle_motion (EEL_IMAGE_TABLE (event_data), (int) event->x, (int) event->y, (GdkEvent *) event);
return FALSE;
}
static int
ancestor_button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer event_data)
{
EelImageTable *image_table;
GtkWidget *child;
g_assert (GTK_IS_WIDGET (widget));
g_assert (EEL_IS_IMAGE_TABLE (event_data));
g_assert (event != NULL);
image_table = EEL_IMAGE_TABLE (event_data);
child = eel_wrap_table_find_child_at_event_point (EEL_WRAP_TABLE (image_table), event->x, event->y);
if (child && !GTK_WIDGET_SENSITIVE (child)) {
return FALSE;
}
if (child != NULL) {
if (child == image_table->details->child_under_pointer) {
image_table->details->child_being_pressed = child;
image_table_emit_signal (image_table,
child,
CHILD_PRESSED,
event->x,
event->y,
event->button,
event->state,
(GdkEvent *)event);
}
}
return FALSE;
}
static int
ancestor_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer event_data)
{
EelImageTable *image_table;
GtkWidget *child;
GtkWidget *released_emit_child = NULL;
GtkWidget *clicked_emit_child = NULL;
g_assert (GTK_IS_WIDGET (widget));
g_assert (EEL_IS_IMAGE_TABLE (event_data));
g_assert (event != NULL);
image_table = EEL_IMAGE_TABLE (event_data);
child = eel_wrap_table_find_child_at_event_point (EEL_WRAP_TABLE (image_table), event->x, event->y);
if (child && !GTK_WIDGET_SENSITIVE (child)) {
return FALSE;
}
if (image_table->details->child_being_pressed != NULL) {
released_emit_child = image_table->details->child_being_pressed;
}
if (child != NULL) {
if (child == image_table->details->child_being_pressed) {
clicked_emit_child = child;
}
}
image_table->details->child_being_pressed = NULL;
if (released_emit_child != NULL) {
image_table_emit_signal (image_table,
released_emit_child,
CHILD_RELEASED,
event->x,
event->y,
event->button,
event->state,
(GdkEvent *)event);
}
if (clicked_emit_child != NULL) {
image_table_emit_signal (image_table,
clicked_emit_child,
CHILD_CLICKED,
event->x,
event->y,
event->button,
event->state,
(GdkEvent *)event);
}
return FALSE;
}
/**
* eel_image_table_new:
*/
GtkWidget*
eel_image_table_new (gboolean homogeneous)
{
EelImageTable *image_table;
image_table = EEL_IMAGE_TABLE (gtk_widget_new (eel_image_table_get_type (), NULL));
eel_wrap_table_set_homogeneous (EEL_WRAP_TABLE (image_table), homogeneous);
return GTK_WIDGET (image_table);
}
/**
* eel_image_table_add_empty_child:
* @image_table: A EelImageTable.
*
* Add a "empty" child to the table. Useful when you want to have
* empty space between 2 children.
*
* Returns: The empty child - A EelLabeledImage widget with no label
* or pixbuf.
*/
GtkWidget *
eel_image_table_add_empty_image (EelImageTable *image_table)
{
GtkWidget *empty;
g_return_val_if_fail (EEL_IS_IMAGE_TABLE (image_table), NULL);
empty = eel_labeled_image_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (image_table), empty);
gtk_widget_set_sensitive (empty, FALSE);
return empty;
}