/*
* This program 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) version 3.
*
* This program 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 the program; if not, see
*
*
* Authors:
* Chris Lahey
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include "e-util/e-util.h"
#include "e-minicard-view-widget.h"
static void e_minicard_view_widget_init (EMinicardViewWidget *widget);
static void e_minicard_view_widget_class_init
(EMinicardViewWidgetClass *class);
static void e_minicard_view_widget_set_property
(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void e_minicard_view_widget_get_property
(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void e_minicard_view_widget_dispose (GObject *object);
static void e_minicard_view_widget_reflow (ECanvas *canvas);
static void e_minicard_view_widget_size_allocate
(GtkWidget *widget,
GtkAllocation *allocation);
static void e_minicard_view_widget_style_set
(GtkWidget *widget,
GtkStyle *previous_style);
static void e_minicard_view_widget_realize (GtkWidget *widget);
static gboolean e_minicard_view_widget_real_focus_in_event
(GtkWidget *widget,
GdkEventFocus *event);
static gpointer parent_class;
/* The arguments we take */
enum {
PROP_0,
PROP_CLIENT,
PROP_QUERY,
PROP_EDITABLE,
PROP_COLUMN_WIDTH
};
enum {
CREATE_CONTACT,
CREATE_CONTACT_LIST,
SELECTION_CHANGE,
COLUMN_WIDTH_CHANGED,
RIGHT_CLICK,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = {0, };
GType
e_minicard_view_widget_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (EMinicardViewWidgetClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) e_minicard_view_widget_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (EMinicardViewWidget),
0, /* n_preallocs */
(GInstanceInitFunc) e_minicard_view_widget_init,
};
type = g_type_register_static (
E_TYPE_CANVAS, "EMinicardViewWidget", &info, 0);
}
return type;
}
static void
e_minicard_view_widget_class_init (EMinicardViewWidgetClass *class)
{
GObjectClass *object_class;
GtkWidgetClass *widget_class;
ECanvasClass *canvas_class;
parent_class = g_type_class_peek_parent (class);
object_class = G_OBJECT_CLASS (class);
object_class->set_property = e_minicard_view_widget_set_property;
object_class->get_property = e_minicard_view_widget_get_property;
object_class->dispose = e_minicard_view_widget_dispose;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->style_set = e_minicard_view_widget_style_set;
widget_class->realize = e_minicard_view_widget_realize;
widget_class->size_allocate = e_minicard_view_widget_size_allocate;
widget_class->focus_in_event = e_minicard_view_widget_real_focus_in_event;
canvas_class = E_CANVAS_CLASS (class);
canvas_class->reflow = e_minicard_view_widget_reflow;
class->selection_change = NULL;
class->column_width_changed = NULL;
class->right_click = NULL;
g_object_class_install_property (object_class, PROP_CLIENT,
g_param_spec_object ("client",
"EBookClient",
NULL,
E_TYPE_BOOK_CLIENT,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_QUERY,
g_param_spec_string ("query",
"Query",
NULL,
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_EDITABLE,
g_param_spec_boolean ("editable",
"Editable",
NULL,
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_COLUMN_WIDTH,
g_param_spec_double ("column_width",
"Column Width",
NULL,
0.0, G_MAXDOUBLE, 225.0,
G_PARAM_READWRITE));
signals[CREATE_CONTACT] =
g_signal_new ("create-contact",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[CREATE_CONTACT_LIST] =
g_signal_new ("create-contact-list",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact_list),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SELECTION_CHANGE] =
g_signal_new ("selection_change",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EMinicardViewWidgetClass, selection_change),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[COLUMN_WIDTH_CHANGED] =
g_signal_new ("column_width_changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EMinicardViewWidgetClass, column_width_changed),
NULL, NULL,
g_cclosure_marshal_VOID__DOUBLE,
G_TYPE_NONE, 1, G_TYPE_DOUBLE);
signals[RIGHT_CLICK] =
g_signal_new ("right_click",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EMinicardViewWidgetClass, right_click),
NULL, NULL,
e_marshal_INT__POINTER,
G_TYPE_INT, 1, G_TYPE_POINTER);
}
static void
e_minicard_view_widget_init (EMinicardViewWidget *view)
{
view->emv = NULL;
view->book_client = NULL;
view->query = NULL;
view->editable = FALSE;
view->column_width = 225;
}
GtkWidget *
e_minicard_view_widget_new (EAddressbookReflowAdapter *adapter)
{
EMinicardViewWidget *widget;
widget = g_object_new (E_TYPE_MINICARD_VIEW_WIDGET, NULL);
widget->adapter = g_object_ref (adapter);
return GTK_WIDGET (widget);
}
static void
e_minicard_view_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EMinicardViewWidget *emvw;
emvw = E_MINICARD_VIEW_WIDGET (object);
switch (prop_id) {
case PROP_CLIENT:
if (emvw->book_client)
g_object_unref (emvw->book_client);
if (g_value_get_object (value)) {
emvw->book_client = E_BOOK_CLIENT (g_value_get_object (value));
if (emvw->book_client)
g_object_ref (emvw->book_client);
} else
emvw->book_client = NULL;
if (emvw->emv)
g_object_set (emvw->emv,
"client", emvw->book_client,
NULL);
break;
case PROP_QUERY:
emvw->query = g_strdup (g_value_get_string (value));
if (emvw->emv)
g_object_set (emvw->emv,
"query", emvw->query,
NULL);
break;
case PROP_EDITABLE:
emvw->editable = g_value_get_boolean (value);
if (emvw->emv)
g_object_set (emvw->emv,
"editable", emvw->editable,
NULL);
break;
case PROP_COLUMN_WIDTH:
emvw->column_width = g_value_get_double (value);
if (emvw->emv) {
g_object_set (emvw->emv,
"column_width", emvw->column_width,
NULL);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
e_minicard_view_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EMinicardViewWidget *emvw;
emvw = E_MINICARD_VIEW_WIDGET (object);
switch (prop_id) {
case PROP_CLIENT:
g_value_set_object (value, emvw->book_client);
break;
case PROP_QUERY:
g_value_set_string (value, emvw->query);
break;
case PROP_EDITABLE:
g_value_set_boolean (value, emvw->editable);
break;
case PROP_COLUMN_WIDTH:
g_value_set_double (value, emvw->column_width);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
e_minicard_view_widget_dispose (GObject *object)
{
EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (object);
if (view->book_client) {
g_object_unref (view->book_client);
view->book_client = NULL;
}
if (view->query) {
g_free (view->query);
view->query = NULL;
}
if (view->adapter) {
g_object_unref (view->adapter);
view->adapter = NULL;
}
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
selection_change (ESelectionModel *esm, EMinicardViewWidget *widget)
{
g_signal_emit (widget,
signals[SELECTION_CHANGE], 0);
}
static void
selection_row_change (ESelectionModel *esm, gint row, EMinicardViewWidget *widget)
{
selection_change (esm, widget);
}
static void
column_width_changed (ESelectionModel *esm, double width, EMinicardViewWidget *widget)
{
g_signal_emit (widget,
signals[COLUMN_WIDTH_CHANGED], 0, width);
}
static void
create_contact (EMinicardView *view, EMinicardViewWidget *widget)
{
g_signal_emit (widget, signals[CREATE_CONTACT], 0);
}
static void
create_contact_list (EMinicardView *view, EMinicardViewWidget *widget)
{
g_signal_emit (widget, signals[CREATE_CONTACT_LIST], 0);
}
static guint
right_click (EMinicardView *view, GdkEvent *event, EMinicardViewWidget *widget)
{
guint ret_val;
g_signal_emit (widget,
signals[RIGHT_CLICK], 0,
event, &ret_val);
return ret_val;
}
static void
e_minicard_view_widget_style_set (GtkWidget *widget, GtkStyle *previous_style)
{
EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget);
GtkStyle *style;
style = gtk_widget_get_style (widget);
if (view->background)
gnome_canvas_item_set (
view->background, "fill_color_gdk",
&style->base[GTK_STATE_NORMAL], NULL);
if (GTK_WIDGET_CLASS (parent_class)->style_set)
GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
}
static void
e_minicard_view_widget_realize (GtkWidget *widget)
{
EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget);
GtkStyle *style = gtk_widget_get_style (widget);
view->background = gnome_canvas_item_new (
gnome_canvas_root (GNOME_CANVAS (view)),
e_canvas_background_get_type (),
"fill_color_gdk", &style->base[GTK_STATE_NORMAL],
NULL );
view->emv = gnome_canvas_item_new (
gnome_canvas_root (GNOME_CANVAS (view)),
e_minicard_view_get_type (),
"height", (double) 100,
"minimum_width", (double) 100,
"adapter", view->adapter,
"column_width", view->column_width,
NULL );
g_signal_connect (
E_REFLOW (view->emv)->selection,
"selection_changed",
G_CALLBACK (selection_change), view);
g_signal_connect (
E_REFLOW (view->emv)->selection,
"selection_row_changed",
G_CALLBACK (selection_row_change), view);
g_signal_connect (
view->emv, "column_width_changed",
G_CALLBACK (column_width_changed), view);
g_signal_connect (
view->emv, "create-contact",
G_CALLBACK (create_contact), view);
g_signal_connect (
view->emv, "create-contact-list",
G_CALLBACK (create_contact_list), view);
g_signal_connect (
view->emv, "right_click",
G_CALLBACK (right_click), view);
if (GTK_WIDGET_CLASS (parent_class)->realize)
GTK_WIDGET_CLASS (parent_class)->realize (widget);
}
static void
e_minicard_view_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
if (gtk_widget_get_realized (widget)) {
gdouble width;
EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget);
gnome_canvas_item_set (
view->emv, "height",
(gdouble) allocation->height, NULL);
gnome_canvas_item_set (
view->emv, "minimum_width",
(gdouble) allocation->width, NULL);
g_object_get (view->emv, "width", &width, NULL);
width = MAX (width, allocation->width);
gnome_canvas_set_scroll_region (
GNOME_CANVAS (view), 0, 0,
width - 1, allocation->height - 1);
}
}
static void
e_minicard_view_widget_reflow (ECanvas *canvas)
{
gdouble width;
EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (canvas);
GtkAllocation allocation;
if (E_CANVAS_CLASS (parent_class)->reflow)
E_CANVAS_CLASS (parent_class)->reflow (canvas);
g_object_get (view->emv, "width", &width, NULL);
gtk_widget_get_allocation (GTK_WIDGET (canvas), &allocation);
gnome_canvas_set_scroll_region (
GNOME_CANVAS (canvas), 0, 0,
MAX (width, allocation.width) - 1,
allocation.height - 1);
}
ESelectionModel *
e_minicard_view_widget_get_selection_model (EMinicardViewWidget *view)
{
if (view->emv)
return E_SELECTION_MODEL (E_REFLOW (view->emv)->selection);
else
return NULL;
}
EMinicardView *
e_minicard_view_widget_get_view (EMinicardViewWidget *view)
{
if (view->emv)
return E_MINICARD_VIEW (view->emv);
else
return NULL;
}
static gboolean
e_minicard_view_widget_real_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
{
GnomeCanvas *canvas;
EMinicardViewWidget *view;
canvas = GNOME_CANVAS (widget);
view = E_MINICARD_VIEW_WIDGET (widget);
if (!canvas->focused_item) {
EReflow *reflow = E_REFLOW (view->emv);
if (reflow->count) {
gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), 0);
if (unsorted != -1)
canvas->focused_item = reflow->items[unsorted];
}
}
if (GTK_WIDGET_CLASS (parent_class)->focus_in_event)
return GTK_WIDGET_CLASS (parent_class)->focus_in_event (widget, event);
return FALSE;
}