/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* E-table.c: A graphical view of a Table.
*
* Author:
* Miguel de Icaza (miguel@helixcode.com)
* Chris Lahey (clahey@helixcode.com)
*
* Copyright 1999, Helix Code, Inc
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <stdio.h>
#include <libgnomeui/gnome-canvas.h>
#include <gtk/gtksignal.h>
#include <gnome-xml/parser.h>
#include "gal/util/e-util.h"
#include "gal/widgets/e-canvas.h"
#include "gal/widgets/e-canvas-utils.h"
#include "e-entry.h"
#define MIN_ENTRY_WIDTH 150
#define INNER_BORDER 2
#define PARENT_TYPE gtk_table_get_type ()
static GtkObjectClass *parent_class;
enum {
E_ENTRY_CHANGED,
E_ENTRY_ACTIVATE,
E_ENTRY_LAST_SIGNAL
};
static guint e_entry_signals[E_ENTRY_LAST_SIGNAL] = { 0 };
/* Object argument IDs */
enum {
ARG_0,
ARG_MODEL,
ARG_EVENT_PROCESSOR,
ARG_TEXT,
ARG_FONT,
ARG_FONTSET,
ARG_FONT_GDK,
ARG_ANCHOR,
ARG_JUSTIFICATION,
ARG_X_OFFSET,
ARG_Y_OFFSET,
ARG_FILL_COLOR,
ARG_FILL_COLOR_GDK,
ARG_FILL_COLOR_RGBA,
ARG_FILL_STIPPLE,
ARG_EDITABLE,
ARG_USE_ELLIPSIS,
ARG_ELLIPSIS,
ARG_LINE_WRAP,
ARG_BREAK_CHARACTERS,
ARG_MAX_LINES,
ARG_ALLOW_NEWLINES,
ARG_DRAW_BORDERS,
ARG_DRAW_BACKGROUND,
ARG_CURSOR_POS
};
static void
canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc,
EEntry *e_entry)
{
gnome_canvas_set_scroll_region (
e_entry->canvas,
0, 0, alloc->width, alloc->height);
gtk_object_set (GTK_OBJECT (e_entry->item),
"clip_width", (double) alloc->width,
"clip_height", (double) alloc->height,
NULL);
switch (e_entry->justification) {
case GTK_JUSTIFY_RIGHT:
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), alloc->width, widget->style->klass->xthickness);
break;
case GTK_JUSTIFY_CENTER:
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), alloc->width / 2, widget->style->klass->xthickness);
break;
default:
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), 0, widget->style->klass->xthickness);
break;
}
}
static void
canvas_size_request (GtkWidget *widget, GtkRequisition *requisition,
EEntry *ee)
{
int border;
gboolean draw_borders = 0;
g_return_if_fail (widget != NULL);
g_return_if_fail (GNOME_IS_CANVAS (widget));
g_return_if_fail (requisition != NULL);
gtk_object_get (GTK_OBJECT (ee->item), "draw_borders", &draw_borders, NULL);
if (draw_borders)
border = INNER_BORDER;
else
border = 0;
requisition->width = MIN_ENTRY_WIDTH + (widget->style->klass->xthickness + border) * 2;
requisition->height = (widget->style->font->ascent +
widget->style->font->descent +
(widget->style->klass->ythickness + border) * 2);
}
static gint
canvas_focus_in_event (GtkWidget *widget, GdkEventFocus *focus, EEntry *e_entry)
{
if (e_entry->canvas->focused_item != GNOME_CANVAS_ITEM(e_entry->item))
gnome_canvas_item_grab_focus(GNOME_CANVAS_ITEM(e_entry->item));
return 0;
}
static void
e_entry_proxy_changed (EText *text, EEntry *ee)
{
gtk_signal_emit (GTK_OBJECT (ee), e_entry_signals [E_ENTRY_CHANGED]);
}
static void
e_entry_proxy_activate (EText *text, EEntry *ee)
{
gtk_signal_emit (GTK_OBJECT (ee), e_entry_signals [E_ENTRY_ACTIVATE]);
}
static void
e_entry_init (GtkObject *object)
{
EEntry *e_entry = E_ENTRY (object);
GtkTable *gtk_table = GTK_TABLE (object);
e_entry->canvas = GNOME_CANVAS(e_canvas_new());
gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "size_allocate",
GTK_SIGNAL_FUNC(canvas_size_allocate), e_entry);
gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "size_request",
GTK_SIGNAL_FUNC(canvas_size_request), e_entry);
gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "focus_in_event",
GTK_SIGNAL_FUNC(canvas_focus_in_event), e_entry);
e_entry->item = E_TEXT(gnome_canvas_item_new(gnome_canvas_root(e_entry->canvas),
e_text_get_type(),
"clip", TRUE,
"fill_clip_rectangle", TRUE,
"anchor", GTK_ANCHOR_NW,
"draw_borders", TRUE,
"draw_background", TRUE,
NULL));
e_entry->justification = GTK_JUSTIFY_LEFT;
gtk_table_attach(gtk_table, GTK_WIDGET(e_entry->canvas),
0, 1, 0, 1,
GTK_EXPAND | GTK_FILL | GTK_SHRINK,
GTK_EXPAND | GTK_FILL | GTK_SHRINK,
0, 0);
gtk_widget_show(GTK_WIDGET(e_entry->canvas));
/*
* Proxy functions: we proxy the changed and activate signals
* from the item to outselves
*/
gtk_signal_connect (GTK_OBJECT (e_entry->item), "changed",
GTK_SIGNAL_FUNC (e_entry_proxy_changed), e_entry);
gtk_signal_connect (GTK_OBJECT (e_entry->item), "activate",
GTK_SIGNAL_FUNC (e_entry_proxy_activate), e_entry);
}
/**
* e_entry_construct
*
* Constructs the given EEntry.
*
* Returns: The EEntry
**/
EEntry *
e_entry_construct (EEntry *e_entry)
{
return e_entry;
}
/**
* e_entry_new
*
* Creates a new EEntry.
*
* Returns: The new EEntry
**/
GtkWidget *
e_entry_new (void)
{
EEntry *e_entry;
e_entry = gtk_type_new (e_entry_get_type ());
e_entry = e_entry_construct (e_entry);
return GTK_WIDGET (e_entry);
}
static void
et_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
EEntry *ee = E_ENTRY (o);
GtkObject *item = GTK_OBJECT (ee->item);
switch (arg_id){
case ARG_MODEL:
gtk_object_get(item,
"model", >K_VALUE_OBJECT (*arg),
NULL);
break;
case ARG_EVENT_PROCESSOR:
gtk_object_get(item,
"event_processor", >K_VALUE_OBJECT (*arg),
NULL);
break;
case ARG_TEXT:
gtk_object_get(item,
"text", >K_VALUE_STRING (*arg),
NULL);
break;
case ARG_FONT_GDK:
gtk_object_get(item,
"font_gdk", >K_VALUE_BOXED (*arg),
NULL);
break;
case ARG_JUSTIFICATION:
gtk_object_get(item,
"justification", >K_VALUE_ENUM (*arg),
NULL);
break;
case ARG_FILL_COLOR_GDK:
gtk_object_get(item,
"fill_color_gdk", >K_VALUE_BOXED (*arg),
NULL);
break;
case ARG_FILL_COLOR_RGBA:
gtk_object_get(item,
"fill_color_rgba", >K_VALUE_UINT (*arg),
NULL);
break;
case ARG_FILL_STIPPLE:
gtk_object_get(item,
"fill_stiple", >K_VALUE_BOXED (*arg),
NULL);
break;
case ARG_EDITABLE:
gtk_object_get(item,
"editable", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_USE_ELLIPSIS:
gtk_object_get(item,
"use_ellipsis", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_ELLIPSIS:
gtk_object_get(item,
"ellipsis", >K_VALUE_STRING (*arg),
NULL);
break;
case ARG_LINE_WRAP:
gtk_object_get(item,
"line_wrap", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_BREAK_CHARACTERS:
gtk_object_get(item,
"break_characters", >K_VALUE_STRING (*arg),
NULL);
break;
case ARG_MAX_LINES:
gtk_object_get(item,
"max_lines", >K_VALUE_INT (*arg),
NULL);
break;
case ARG_ALLOW_NEWLINES:
gtk_object_get(item,
"allow_newlines", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_DRAW_BORDERS:
gtk_object_get (item,
"draw_borders", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_DRAW_BACKGROUND:
gtk_object_get (item,
"draw_background", >K_VALUE_BOOL (*arg),
NULL);
break;
case ARG_CURSOR_POS:
gtk_object_get (item,
"cursor_pos", >K_VALUE_INT (*arg),
NULL);
default:
arg->type = GTK_TYPE_INVALID;
break;
}
}
static void
et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
EEntry *ee = E_ENTRY (o);
GtkObject *item = GTK_OBJECT (ee->item);
GtkAnchorType anchor;
double width, height;
GtkWidget *canvas = GTK_WIDGET(ee->canvas);
switch (arg_id){
case ARG_MODEL:
gtk_object_set(item,
"model", GTK_VALUE_OBJECT (*arg),
NULL);
break;
case ARG_EVENT_PROCESSOR:
gtk_object_set(item,
"event_processor", GTK_VALUE_OBJECT (*arg),
NULL);
break;
case ARG_TEXT:
gtk_object_set(item,
"text", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_FONT:
gtk_object_set(item,
"font", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_FONTSET:
gtk_object_set(item,
"fontset", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_FONT_GDK:
gtk_object_set(item,
"font_gdk", GTK_VALUE_BOXED (*arg),
NULL);
break;
case ARG_JUSTIFICATION:
ee->justification = GTK_VALUE_ENUM (*arg);
gtk_object_get(item,
"clip_width", &width,
"clip_height", &height,
NULL);
switch (ee->justification) {
case GTK_JUSTIFY_CENTER:
anchor = GTK_ANCHOR_N;
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), width / 2, canvas->style->klass->xthickness);
break;
case GTK_JUSTIFY_RIGHT:
anchor = GTK_ANCHOR_NE;
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), width, canvas->style->klass->xthickness);
break;
default:
anchor = GTK_ANCHOR_NW;
e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), 0, canvas->style->klass->xthickness);
break;
}
gtk_object_set(item,
"justification", ee->justification,
"anchor", anchor,
NULL);
break;
case ARG_FILL_COLOR:
gtk_object_set(item,
"fill_color", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_FILL_COLOR_GDK:
gtk_object_set(item,
"fill_color_gdk", GTK_VALUE_BOXED (*arg),
NULL);
break;
case ARG_FILL_COLOR_RGBA:
gtk_object_set(item,
"fill_color_rgba", GTK_VALUE_UINT (*arg),
NULL);
break;
case ARG_FILL_STIPPLE:
gtk_object_set(item,
"fill_stiple", GTK_VALUE_BOXED (*arg),
NULL);
break;
case ARG_EDITABLE:
gtk_object_set(item,
"editable", GTK_VALUE_BOOL (*arg),
NULL);
break;
case ARG_USE_ELLIPSIS:
gtk_object_set(item,
"use_ellipsis", GTK_VALUE_BOOL (*arg),
NULL);
break;
case ARG_ELLIPSIS:
gtk_object_set(item,
"ellipsis", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_LINE_WRAP:
gtk_object_set(item,
"line_wrap", GTK_VALUE_BOOL (*arg),
NULL);
break;
case ARG_BREAK_CHARACTERS:
gtk_object_set(item,
"break_characters", GTK_VALUE_STRING (*arg),
NULL);
break;
case ARG_MAX_LINES:
gtk_object_set(item,
"max_lines", GTK_VALUE_INT (*arg),
NULL);
break;
case ARG_ALLOW_NEWLINES:
gtk_object_set(item,
"allow_newlines", GTK_VALUE_BOOL (*arg),
NULL);
break;
case ARG_DRAW_BORDERS: {
gboolean draw_border;
gboolean need_queue;
gtk_object_get (item, "draw_borders", &draw_border, NULL);
need_queue = (draw_border ^ GTK_VALUE_BOOL (*arg));
gtk_object_set (item, "draw_borders", GTK_VALUE_BOOL (*arg), NULL);
if (need_queue)
gtk_widget_queue_resize (GTK_WIDGET (ee));
break;
}
case ARG_CURSOR_POS:
gtk_object_set (item,
"cursor_pos", GTK_VALUE_INT (*arg), NULL);
break;
case ARG_DRAW_BACKGROUND:
gtk_object_set (item, "draw_background",
GTK_VALUE_BOOL (*arg), NULL);
break;
}
}
static void
e_entry_class_init (GtkObjectClass *object_class)
{
EEntryClass *klass = E_ENTRY_CLASS(object_class);
parent_class = gtk_type_class (PARENT_TYPE);
object_class->set_arg = et_set_arg;
object_class->get_arg = et_get_arg;
klass->changed = NULL;
klass->activate = NULL;
e_entry_signals[E_ENTRY_CHANGED] =
gtk_signal_new ("changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (EEntryClass, changed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
e_entry_signals[E_ENTRY_ACTIVATE] =
gtk_signal_new ("activate",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (EEntryClass, activate),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, e_entry_signals, E_ENTRY_LAST_SIGNAL);
gtk_object_add_arg_type ("EEntry::model",
GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_MODEL);
gtk_object_add_arg_type ("EEntry::event_processor",
GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_EVENT_PROCESSOR);
gtk_object_add_arg_type ("EEntry::text",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TEXT);
gtk_object_add_arg_type ("EEntry::font",
GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FONT);
gtk_object_add_arg_type ("EEntry::fontset",
GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FONTSET);
gtk_object_add_arg_type ("EEntry::font_gdk",
GTK_TYPE_GDK_FONT, GTK_ARG_READWRITE, ARG_FONT_GDK);
gtk_object_add_arg_type ("EEntry::justification",
GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFICATION);
gtk_object_add_arg_type ("EEntry::fill_color",
GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FILL_COLOR);
gtk_object_add_arg_type ("EEntry::fill_color_gdk",
GTK_TYPE_GDK_COLOR, GTK_ARG_READWRITE, ARG_FILL_COLOR_GDK);
gtk_object_add_arg_type ("EEntry::fill_color_rgba",
GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA);
gtk_object_add_arg_type ("EEntry::fill_stipple",
GTK_TYPE_GDK_WINDOW, GTK_ARG_READWRITE, ARG_FILL_STIPPLE);
gtk_object_add_arg_type ("EEntry::editable",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
gtk_object_add_arg_type ("EEntry::use_ellipsis",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_USE_ELLIPSIS);
gtk_object_add_arg_type ("EEntry::ellipsis",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ELLIPSIS);
gtk_object_add_arg_type ("EEntry::line_wrap",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_LINE_WRAP);
gtk_object_add_arg_type ("EEntry::break_characters",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_BREAK_CHARACTERS);
gtk_object_add_arg_type ("EEntry::max_lines",
GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MAX_LINES);
gtk_object_add_arg_type ("EEntry::allow_newlines",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_NEWLINES);
gtk_object_add_arg_type ("EEntry::draw_borders",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW_BORDERS);
gtk_object_add_arg_type ("EEntry::draw_background",
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW_BACKGROUND);
gtk_object_add_arg_type ("EEntry::cursor_pos",
GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_CURSOR_POS);
}
E_MAKE_TYPE(e_entry, "EEntry", EEntry, e_entry_class_init, e_entry_init, PARENT_TYPE);