diff options
Diffstat (limited to 'widgets')
78 files changed, 4169 insertions, 4371 deletions
diff --git a/widgets/e-minicard/e-minicard-label.c b/widgets/e-minicard/e-minicard-label.c index 43603f2d6d..5b528d6190 100644 --- a/widgets/e-minicard/e-minicard-label.c +++ b/widgets/e-minicard/e-minicard-label.c @@ -24,6 +24,7 @@ #include "e-minicard-label.h" #include "e-text.h" #include "e-canvas.h" +#include "e-util.h" static void e_minicard_label_init (EMinicardLabel *card); static void e_minicard_label_class_init (EMinicardLabelClass *klass); static void e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -32,8 +33,8 @@ static gboolean e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event); static void e_minicard_label_realize (GnomeCanvasItem *item); static void e_minicard_label_unrealize (GnomeCanvasItem *item); -static void _update_label( EMinicardLabel *minicard_label ); -static void _resize( GtkObject *object, gpointer data ); +static void update_label( EMinicardLabel *minicard_label ); +static void resize( GtkObject *object, gpointer data ); static GnomeCanvasGroupClass *parent_class = NULL; @@ -148,11 +149,11 @@ e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) switch (arg_id){ case ARG_WIDTH: e_minicard_label->width = GTK_VALUE_DOUBLE (*arg); - _update_label( e_minicard_label ); + update_label( e_minicard_label ); gnome_canvas_item_request_update (item); break; case ARG_HAS_FOCUS: - if (e_minicard_label->field && GTK_VALUE_BOOL(*arg)) + if (e_minicard_label->field && (GTK_VALUE_ENUM(*arg) != E_FOCUS_NONE)) e_canvas_item_grab_focus(e_minicard_label->field); break; case ARG_FIELD: @@ -186,7 +187,7 @@ e_minicard_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_DOUBLE (*arg) = e_minicard_label->height; break; case ARG_HAS_FOCUS: - GTK_VALUE_BOOL (*arg) = e_minicard_label->has_focus; + GTK_VALUE_ENUM (*arg) = e_minicard_label->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE; break; case ARG_FIELD: if ( e_minicard_label->field ) { @@ -213,6 +214,11 @@ e_minicard_label_realize (GnomeCanvasItem *item) { EMinicardLabel *e_minicard_label; GnomeCanvasGroup *group; + static GdkFont *font = NULL; + + if ( font == NULL ) { + font = gdk_font_load("lucidasans-10"); + } e_minicard_label = E_MINICARD_LABEL (item); group = GNOME_CANVAS_GROUP( item ); @@ -239,7 +245,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) "clip_height", (double) 1, "clip", TRUE, "use_ellipsis", TRUE, - "font", "lucidasans-10", + "font_gdk", font, "fill_color", "black", NULL ); if ( e_minicard_label->fieldname_text ) @@ -251,7 +257,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) } gtk_signal_connect(GTK_OBJECT(e_minicard_label->fieldname), "resize", - GTK_SIGNAL_FUNC(_resize), + GTK_SIGNAL_FUNC(resize), (gpointer) e_minicard_label); e_minicard_label->field = @@ -264,7 +270,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) "clip_height", (double) 1, "clip", TRUE, "use_ellipsis", TRUE, - "font", "lucidasans-10", + "font_gdk", font, "fill_color", "black", "editable", TRUE, NULL ); @@ -278,10 +284,10 @@ e_minicard_label_realize (GnomeCanvasItem *item) gtk_signal_connect(GTK_OBJECT(e_minicard_label->field), "resize", - GTK_SIGNAL_FUNC(_resize), + GTK_SIGNAL_FUNC(resize), (gpointer) e_minicard_label); - _update_label (e_minicard_label); + update_label (e_minicard_label); if (!item->canvas->aa) { @@ -400,7 +406,7 @@ e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event) } static void -_update_label( EMinicardLabel *e_minicard_label ) +update_label( EMinicardLabel *e_minicard_label ) { if ( GTK_OBJECT_FLAGS( e_minicard_label ) & GNOME_CANVAS_ITEM_REALIZED ) { @@ -450,7 +456,7 @@ _update_label( EMinicardLabel *e_minicard_label ) static void -_resize( GtkObject *object, gpointer data ) +resize( GtkObject *object, gpointer data ) { - _update_label(E_MINICARD_LABEL(data)); + update_label(E_MINICARD_LABEL(data)); } diff --git a/widgets/e-minicard/e-minicard.c b/widgets/e-minicard/e-minicard.c index b667f1ac21..805c4e78ff 100644 --- a/widgets/e-minicard/e-minicard.c +++ b/widgets/e-minicard/e-minicard.c @@ -25,6 +25,7 @@ #include "e-minicard-label.h" #include "e-text.h" #include "e-canvas.h" +#include "e-util.h" static void e_minicard_init (EMinicard *card); static void e_minicard_class_init (EMinicardClass *klass); static void e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -105,7 +106,7 @@ e_minicard_class_init (EMinicardClass *klass) GTK_ARG_READWRITE, ARG_WIDTH); gtk_object_add_arg_type ("EMinicard::height", GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_HEIGHT); - gtk_object_add_arg_type ("EMinicard::has_focus", GTK_TYPE_BOOL, + gtk_object_add_arg_type ("EMinicard::has_focus", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_HAS_FOCUS); gtk_object_add_arg_type ("EMinicard::card", GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_CARD); @@ -149,10 +150,18 @@ e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) } break; case ARG_HAS_FOCUS: - if (e_minicard->fields) - gnome_canvas_item_set(GNOME_CANVAS_ITEM(e_minicard->fields->data), - "has_focus", GTK_VALUE_BOOL(*arg), - NULL); + if (e_minicard->fields) { + if ( GTK_VALUE_ENUM(*arg) == E_FOCUS_START || + GTK_VALUE_ENUM(*arg) == E_FOCUS_CURRENT) { + gnome_canvas_item_set(GNOME_CANVAS_ITEM(e_minicard->fields->data), + "has_focus", GTK_VALUE_ENUM(*arg), + NULL); + } else if ( GTK_VALUE_ENUM(*arg) == E_FOCUS_END ) { + gnome_canvas_item_set(GNOME_CANVAS_ITEM(g_list_last(e_minicard->fields)->data), + "has_focus", GTK_VALUE_ENUM(*arg), + NULL); + } + } else e_canvas_item_grab_focus(GNOME_CANVAS_ITEM(e_minicard)); break; @@ -179,7 +188,7 @@ e_minicard_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_DOUBLE (*arg) = e_minicard->height; break; case ARG_HAS_FOCUS: - GTK_VALUE_BOOL (*arg) = e_minicard->has_focus; + GTK_VALUE_ENUM (*arg) = e_minicard->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE; break; case ARG_CARD: /* GTK_VALUE_POINTER (*arg) = e_minicard->card; */ @@ -364,11 +373,11 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) GList *list; for (list = e_minicard->fields; list; list = list->next) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (list->data); - gboolean has_focus; + EFocus has_focus; gtk_object_get(GTK_OBJECT(item), "has_focus", &has_focus, NULL); - if (has_focus) { + if (has_focus != E_FOCUS_NONE) { if (event->key.state & GDK_SHIFT_MASK) list = list->prev; else @@ -376,7 +385,7 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) if (list) { item = GNOME_CANVAS_ITEM (list->data); gnome_canvas_item_set(item, - "has_focus", TRUE, + "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, NULL); return 1; } else { diff --git a/widgets/e-minicard/e-reflow.c b/widgets/e-minicard/e-reflow.c index c1022f8f78..984e972f0c 100644 --- a/widgets/e-minicard/e-reflow.c +++ b/widgets/e-minicard/e-reflow.c @@ -24,6 +24,7 @@ #include <math.h> #include "e-reflow.h" #include "e-canvas-utils.h" +#include "e-util.h" static void e_reflow_init (EReflow *card); static void e_reflow_class_init (EReflowClass *klass); static void e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -278,7 +279,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) GList *list; for (list = e_reflow->items; list; list = list->next) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (list->data); - gboolean has_focus; + EFocus has_focus; gtk_object_get(GTK_OBJECT(item), "has_focus", &has_focus, NULL); @@ -290,7 +291,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) if (list) { item = GNOME_CANVAS_ITEM(list->data); gnome_canvas_item_set(item, - "has_focus", TRUE, + "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, NULL); return 1; } else { @@ -625,7 +626,6 @@ e_reflow_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { - EReflow *e_reflow = E_REFLOW(item); double distance = 1; if (GNOME_CANVAS_ITEM_CLASS(parent_class)->point) diff --git a/widgets/e-minicard/test-minicard-label.c b/widgets/e-minicard/test-minicard-label.c index 67c17a0ace..8da34e6f22 100644 --- a/widgets/e-minicard/test-minicard-label.c +++ b/widgets/e-minicard/test-minicard-label.c @@ -44,6 +44,7 @@ static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpoi NULL ); } +#if 0 static void about_callback( GtkWidget *widget, gpointer data ) { @@ -61,6 +62,7 @@ static void about_callback( GtkWidget *widget, gpointer data ) NULL); gtk_widget_show (about); } +#endif static void button_press_callback( GtkWidget *widget, gpointer data ) { diff --git a/widgets/e-minicard/test-minicard.c b/widgets/e-minicard/test-minicard.c index 79077c4b2d..1ad066b3fe 100644 --- a/widgets/e-minicard/test-minicard.c +++ b/widgets/e-minicard/test-minicard.c @@ -43,6 +43,7 @@ static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpoi NULL ); } +#if 0 static void about_callback( GtkWidget *widget, gpointer data ) { @@ -60,6 +61,7 @@ static void about_callback( GtkWidget *widget, gpointer data ) NULL); gtk_widget_show (about); } +#endif int main( int argc, char *argv[] ) { diff --git a/widgets/e-minicard/test-reflow.c b/widgets/e-minicard/test-reflow.c index 4533e0249d..319a3f5626 100644 --- a/widgets/e-minicard/test-reflow.c +++ b/widgets/e-minicard/test-reflow.c @@ -69,6 +69,7 @@ static void resize(GnomeCanvasItem *item, gpointer data) NULL ); } +#if 0 static void about_callback( GtkWidget *widget, gpointer data ) { @@ -86,6 +87,7 @@ static void about_callback( GtkWidget *widget, gpointer data ) NULL); gtk_widget_show (about); } +#endif int main( int argc, char *argv[] ) { diff --git a/widgets/e-reflow/e-reflow.c b/widgets/e-reflow/e-reflow.c index c1022f8f78..984e972f0c 100644 --- a/widgets/e-reflow/e-reflow.c +++ b/widgets/e-reflow/e-reflow.c @@ -24,6 +24,7 @@ #include <math.h> #include "e-reflow.h" #include "e-canvas-utils.h" +#include "e-util.h" static void e_reflow_init (EReflow *card); static void e_reflow_class_init (EReflowClass *klass); static void e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -278,7 +279,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) GList *list; for (list = e_reflow->items; list; list = list->next) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (list->data); - gboolean has_focus; + EFocus has_focus; gtk_object_get(GTK_OBJECT(item), "has_focus", &has_focus, NULL); @@ -290,7 +291,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) if (list) { item = GNOME_CANVAS_ITEM(list->data); gnome_canvas_item_set(item, - "has_focus", TRUE, + "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, NULL); return 1; } else { @@ -625,7 +626,6 @@ e_reflow_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { - EReflow *e_reflow = E_REFLOW(item); double distance = 1; if (GNOME_CANVAS_ITEM_CLASS(parent_class)->point) diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index 88ad00e78a..5ed89f05ef 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,73 @@ +2000-02-24 Christopher James Lahey <clahey@helixcode.com> + + * e-table-subset-variable.c, e-table-subset-variable.h: A new + model which is a subset, but you can add and remove rows. + + * test-table.c: Added a thaw method for use with the + e-table-subset (emits model_changed.) Adapted to the changes to + e_table_item. Properly parse headers. Adapted to the changes to + e_table, including creating example xml spec data. + + * test-cols.c, test-check.c: Added a thaw method for use with the + e-table-subset (emits model_changed.) Adapted to the changes to + e_table_item. + + * e-table.c, e-table.h: Reworked e-table to use the ETable + grouping system. The only difference for the interface is that + instead of passing in a column_spec and a grouping_spec, you pass + in a single string that is an xml format that includes both pieces + of information. + + * e-table-subset.h: Added rules for emacs to do correct + indentation. + + * e-table-subset.c: Implemented freezing. No signals are emitted + while frozen and "model_changed" is emitted when thawed. + + * e-table-sorted.h: ETableSortedClass has ETableSubset as its + parent object instead of ETableSubsetClass. Fixed this. + + * e-table-simple.c, e-table-simple.h: Implemented the thaw method. + Use of simple now requires an extra argument (the thaw method.) + + * e-table-model.h, e-table-model.c: Added e_table_model_freeze and + e_table_model_thaw. + + * e-table-item.h, e-table-item.c: Reworked this a bit to make it + provide some things the new group system needed and to make + inter-item keyboard focus work. Changed the external interface + only in the list of arguments it recognizes and signals it emits. + Instead of "x" and "y", you have to use + e_canvas_item_move_absolute and instead of emitting a + "height_changed" signal, it emits a "resize" signal. There's new + "has_focus", "width", and "height" arguments and a function to get + the currently focused column. + + * e-table-header-item.c: Got rid of some warnings here. Changed + the + + * e-table-group-leaf.h, e-table-group-leaf.c, + e-table-group-container.h, e-table-group-container.c: New types to + make e_table_group work properly. + + * e-table-group.h, e-table-group.c: Completely reworked e-table + grouping. e-table-group now uses a hierarchical structure. + + * e-cell.h: Added e_cell_print. This doesn't work yet. + + * e-cell.c: Made e_cell_realize exist. (It was improperly named + e_cell_view_realize in the .c.) + + * e-cell-text.c: Made the blinking cursor disappear properly. + + * check-filled.xpm, check-empty.xpm: Made these const char *[] + instead of char *[] to avoid compiler warnings. + + * Makefile.am: Added e-table-group-container.c, + e-table-group-container.h, e-table-group-leaf.c, + e-table-group-leaf.h, e-table-subset-variable.c, + e-table-subset-variable.h. + 2000-02-18 Miguel de Icaza <miguel@nuclecu.unam.mx> * e-table-header.c: Include <string.h> diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index 556a77bad8..0780ae7c57 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -23,6 +23,10 @@ libetable_a_SOURCES = \ e-table-col.h \ e-table-group.c \ e-table-group.h \ + e-table-group-container.c \ + e-table-group-container.h \ + e-table-group-leaf.c \ + e-table-group-leaf.h \ e-table-header.c \ e-table-header.h \ e-table-header-item.c \ @@ -36,7 +40,9 @@ libetable_a_SOURCES = \ e-table-sorted.c \ e-table-sorted.h \ e-table-subset.c \ - e-table-subset.h + e-table-subset.h \ + e-table-subset-variable.c \ + e-table-subset-variable.h noinst_PROGRAMS = \ table-test diff --git a/widgets/e-table/check-empty.xpm b/widgets/e-table/check-empty.xpm index 2dd873e137..746b20234e 100644 --- a/widgets/e-table/check-empty.xpm +++ b/widgets/e-table/check-empty.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_empty_xpm[] = { +static const char * check_empty_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/e-table/check-filled.xpm b/widgets/e-table/check-filled.xpm index 689d7a7967..c0468fc25b 100644 --- a/widgets/e-table/check-filled.xpm +++ b/widgets/e-table/check-filled.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_filled_xpm[] = { +static const char * check_filled_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index 8131d16384..fb33f10537 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -120,7 +120,6 @@ typedef struct { } ECellTextView; typedef struct _CurrentCell{ - ECellTextView *text_view; int width; gchar *text; @@ -233,6 +232,10 @@ static void ect_stop_editing (ECellTextView *text_view) { CellEdit *edit = text_view->edit; + int row, view_col; + + row = edit->cell.row; + view_col = edit->cell.view_col; g_free (edit->old_text); edit->old_text = NULL; @@ -246,12 +249,24 @@ ect_stop_editing (ECellTextView *text_view) g_free(edit->primary_selection); if (edit->clipboard_selection) g_free(edit->clipboard_selection); + if ( ! edit->default_cursor_shown ) { + gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); + edit->default_cursor_shown = TRUE; + } + if (edit->timeout_id) { + g_source_remove(edit->timeout_id); + edit->timeout_id = 0; + } + if (edit->timer) { + g_timer_stop(edit->timer); + g_timer_destroy(edit->timer); + edit->timer = NULL; + } g_free (edit); text_view->edit = NULL; - - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); + ect_queue_redraw (text_view, view_col, row); } /* @@ -260,7 +275,6 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->cell.view_col, text_view->edit->cell.row); ect_stop_editing (text_view); } @@ -379,9 +393,11 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (edit){ - if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) + if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) { edit_display = TRUE; - fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + } else + fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } else { fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } @@ -776,6 +792,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, break; case GDK_BUTTON_PRESS: /* Fall Through */ case GDK_BUTTON_RELEASE: + event->button.x -= 4; + event->button.y -= 1; if ((!edit_display) && ect->editable && event->type == GDK_BUTTON_RELEASE @@ -828,6 +846,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, } break; case GDK_MOTION_NOTIFY: + event->motion.x -= 4; + event->motion.y -= 1; if (edit_display) { GdkEventMotion motion = event->motion; e_tep_event.motion.time = motion.time; @@ -928,15 +948,6 @@ ect_height (ECellView *ecell_view, int model_col, int view_col, int row) } /* - * Callback: invoked when the user pressed "enter" on the GtkEntry - */ -static void -ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) -{ - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); -} - -/* * ECellView::enter_edit method */ static void * @@ -1011,19 +1022,6 @@ ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, voi CellEdit *edit = text_view->edit; if (edit){ - if ( ! edit->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); - edit->default_cursor_shown = TRUE; - } - if (edit->timeout_id) { - g_source_remove(edit->timeout_id); - edit->timeout_id = 0; - } - if (edit->timer) { - g_timer_stop(edit->timer); - g_timer_destroy(edit->timer); - edit->timer = NULL; - } ect_accept_edits (text_view); ect_stop_editing (text_view); } else { @@ -1508,9 +1506,6 @@ e_cell_text_view_command(ETextEventProcessor *tep, ETextEventProcessorCommand *c break; case E_TEP_ACTIVATE: e_table_item_leave_edit (text_view->cell_view.e_table_item_view); - if (edit->timer) { - g_timer_reset(edit->timer); - } break; case E_TEP_SET_SELECT_BY_WORD: edit->select_by_word = command->value; @@ -1842,7 +1837,9 @@ calc_line_widths (CurrentCell *cell) } if (ect->use_ellipsis && - ! text_view->edit && + (!(text_view->edit && + cell->row == text_view->edit->cell.row && + cell->view_col == text_view->edit->cell.view_col)) && lines->width > cell->width) { if (font) { lines->ellipsis_length = 0; diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index f1345e8c6b..1d87019007 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -129,7 +129,7 @@ e_cell_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view } void -e_cell_view_realize (ECellView *ecell_view) +e_cell_realize (ECellView *ecell_view) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->realize (ecell_view); } diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index 3c258689e4..b21653d6d1 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include <gdk/gdktypes.h> +#include <libgnomeprint/gnome-print.h> #include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) @@ -62,6 +63,9 @@ void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2); +void e_cell_print (ECellView *ecell_view, GnomePrintContext *context, + int model_col, int view_col, int row, + double width, double height); void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); diff --git a/widgets/e-table/e-table-group-container.c b/widgets/e-table/e-table-group-container.c new file mode 100644 index 0000000000..a9f494db04 --- /dev/null +++ b/widgets/e-table/e-table-group-container.c @@ -0,0 +1,804 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-container.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" +#include "e-util/e-canvas-utils.h" +#include "widgets/e-text/e-text.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define BUTTON_HEIGHT 10 +#define BUTTON_PADDING 2 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgc_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static int etgc_event (GnomeCanvasItem *item, GdkEvent *event); +static void etgc_realize (GnomeCanvasItem *item); +static void etgc_unrealize (GnomeCanvasItem *item); + +static void etgc_add (ETableGroup *etg, gint row); +static gboolean etgc_remove (ETableGroup *etg, gint row); +static void etgc_increment (ETableGroup *etg, gint position, gint amount); +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col); + +static void etgc_child_resize (GtkObject *object, gpointer data); + +static void etgc_queue_reposition (ETableGroupContainer *etgc); + +typedef struct { + ETableGroup *child; + void *key; + GnomeCanvasItem *text; + GnomeCanvasItem *rect; + gint count; +} ETableGroupContainerChildNode; + +static void +etgc_destroy (GtkObject *object) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (object); + + gdk_font_unref(etgc->font); + + GTK_OBJECT_CLASS (etgc_parent_class)->destroy (object); +} +#if 0 +void +e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etg != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etg->children = g_list_append (etg->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etg->transparent ? 0 : TITLE_HEIGHT; + int x = etg->transparent ? 0 : GROUP_INDENT; + + for (l = etg->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etg_relayout), etg); + } + } +} + +static void +etg_realize (GnomeCanvasItem *item) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); + + if (!etg->transparent){ + int current_width, current_height; + + etg_dim (etg, ¤t_width, ¤t_height); + + if ((current_height != etg->height) || (current_width != etg->width)){ + etg->width = current_width; + etg->height = current_height; + + gnome_canvas_item_set ( + etg->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etg->width, + "y2", (double) etg->height, + NULL); + } + } +} +#endif + +void +e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model); + etgc->ecol = ecol; + etgc->child_rules = child_rules; + + etgc->font = gdk_font_load ("lucidasans-10"); +#if 0 + etgc->open = open; + etgc->transparent = transparent; + + etgc_dim (etgc, &etgc->width, &etgc->height); + + if (!etgc->transparent) + etgc->rect = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (etgc), + gnome_canvas_rect_get_type (), + "fill_color", "gray", + "outline_color", "gray20", + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); +#endif + +#if 0 + /* + * Reparent the child into our space. + */ + gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etgc)); + + gnome_canvas_item_set ( + child, + "x", (double) GROUP_INDENT, + "y", (double) TITLE_HEIGHT, + NULL); + + /* + * Force dimension computation + */ + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update ( + GNOME_CANVAS_ITEM (etgc), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); +#endif +} + +ETableGroup * +e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + ETableGroupContainer *etgc; + + g_return_val_if_fail (parent != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); + + etgc = gtk_type_new (e_table_group_container_get_type ()); + + e_table_group_container_construct (parent, etgc, full_header, header, + model, ecol, child_rules); + return E_TABLE_GROUP (etgc); +} + +#if 0 +static void +etgc_relayout (GnomeCanvasItem *eti, ETableGroupContainer *etgc) +{ + GList *l; + int height = etgc->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + if (child == eti) + move = TRUE; + + if (move){ + printf ("Moving item %p\n", child); + gnome_canvas_item_set ( child, + "y", (double) height, + NULL); + } + } + if (height != etgc->height){ + etgc->height = height; + gtk_signal_emit (GTK_OBJECT (etgc), etgc_signals [RESIZE]); + } +} + +void +e_table_group_container_add (ETableGroupContainer *etgc, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etgc != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etgc)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etgc->children = g_list_append (etgc->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etgc)->klass)->bounds (etgc, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etgc)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etgc->transparent ? 0 : TITLE_HEIGHT; + int x = etgc->transparent ? 0 : GROUP_INDENT; + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etgc_relayout), etgc); + } + } +} + +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->realize (item); + + for (l = etgc->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etgc_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update (item, affine, clip_path, flags); + + if ( etgc->need_resize ) { + + if (!etgc->transparent){ + int current_width, current_height; + + etgc_dim (etgc, ¤t_width, ¤t_height); + + if ((current_height != etgc->height) || (current_width != etgc->width)){ + etgc->width = current_width; + etgc->height = current_height; + + gnome_canvas_item_set ( + etgc->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); + } + } + etgc->need_resize = FALSE; + } +} +#endif + +static int +etgc_event (GnomeCanvasItem *item, GdkEvent *event) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(item); + gboolean return_val = TRUE; + gboolean change_focus = FALSE; + gboolean use_col = FALSE; + gint start_col = 0; + gint old_col; + EFocus direction = E_FOCUS_START; + + switch (event->type) { + case GDK_KEY_PRESS: + if (event->key.keyval == GDK_Tab || + event->key.keyval == GDK_KP_Tab || + event->key.keyval == GDK_ISO_Left_Tab) { + change_focus = TRUE; + use_col = TRUE; + start_col = (event->key.state & GDK_SHIFT_MASK) ? -1 : 0; + direction = (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START; + } else if (event->key.keyval == GDK_Left || + event->key.keyval == GDK_KP_Left) { + change_focus = TRUE; + use_col = TRUE; + start_col = -1; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Right || + event->key.keyval == GDK_KP_Right) { + change_focus = TRUE; + use_col = TRUE; + start_col = 0; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Down || + event->key.keyval == GDK_KP_Down) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Up || + event->key.keyval == GDK_KP_Up) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Return || + event->key.keyval == GDK_KP_Enter) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } + if ( change_focus ) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + old_col = e_table_group_get_focus_column(child); + + if (direction == E_FOCUS_END) + list = list->prev; + else + list = list->next; + + if (list) { + child_node = (ETableGroupContainerChildNode *)list->data; + child = child_node->child; + if (use_col) + e_table_group_set_focus(child, direction, start_col); + else { + e_table_group_set_focus(child, direction, old_col); + } + return 1; + } else { + return 0; + } + } + } + } + return_val = FALSE; + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event(item, event); + } + return return_val; + +} + +/* Realize handler for the text item */ +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) (item); + + etgc = E_TABLE_GROUP_CONTAINER (item); +} + +/* Unrealize handler for the etgc item */ +static void +etgc_unrealize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + etgc = E_TABLE_GROUP_CONTAINER (item); + + etgc->font = NULL; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) (item); +} + +static void +compute_text (ETableGroupContainer *etgc, ETableGroupContainerChildNode *child_node) +{ + /* FIXME : What a hack, eh? */ + gchar *text = g_strdup_printf("%s : %s (%d items)", etgc->ecol->text, (gchar *)child_node->key, (gint) child_node->count); + gnome_canvas_item_set(child_node->text, + "text", text, + NULL); + g_free(text); +} + +static void etgc_add (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + void *val = e_table_model_value_at (etg->model, etgc->ecol->col_idx, row); + GCompareFunc comp = etgc->ecol->compare; + GList *list = etgc->children; + ETableGroup *child; + ETableGroupContainerChildNode *child_node; + for ( ; list; list = g_list_next(list) ) { + child_node = (ETableGroupContainerChildNode *)(list->data); + if ( (*comp)(child_node->key, val) ) { + child = child_node->child; + child_node->count ++; + e_table_group_add(child, row); + compute_text(etgc, child_node); + return; + } + } + child_node = g_new(ETableGroupContainerChildNode, 1); + child_node->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + gnome_canvas_rect_get_type (), + "fill_color", "grey70", + "outline_color", "grey50", + NULL); + child_node->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + e_text_get_type(), + "font_gdk", etgc->font, + "anchor", GTK_ANCHOR_SW, + "x", (double) 0, + "y", (double) 0, + "fill_color", "black", + NULL); + child = e_table_group_new(GNOME_CANVAS_GROUP(etgc), etg->full_header, etg->header, etg->model, etgc->child_rules); + child_node->child = child; + child_node->key = val; + + gtk_signal_connect(GTK_OBJECT(child), "resize", + etgc_child_resize, etgc); + child_node->count = 1; + e_table_group_add(child, row); + etgc->children = g_list_append(etgc->children, child_node); + compute_text(etgc, child_node); + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gboolean etgc_remove (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + if ( e_table_group_remove(child, row) ) { + child_node->count --; + if ( child_node->count == 0 ) { + gtk_object_unref(GTK_OBJECT(child_node->text)); + gtk_object_unref(GTK_OBJECT(child)); + etgc->children = g_list_remove(etgc->children, child_node); + g_free(child_node); + } else { + compute_text(etgc, child_node); + } + return TRUE; + } + } + return FALSE; + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + e_table_group_increment(((ETableGroupContainerChildNode *)list->data)->child, position, amount); + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + if (direction == E_FOCUS_END) { + e_table_group_set_focus(((ETableGroupContainerChildNode *)g_list_last(etgc->children)->data)->child, direction, view_col); + } else { + e_table_group_set_focus(((ETableGroupContainerChildNode *)etgc->children->data)->child, direction, view_col); + } + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gint +etgc_get_focus_column (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + return e_table_group_get_focus_column(child); + } + } + } + return 0; +} + +static void etgc_thaw (ETableGroup *etg) +{ + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void +etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etgc_thaw(etg); + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void etgc_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + GList *list = etgc->children; + etgc->width = width; + + for ( ; list; list = g_list_next(list) ) { + gdouble child_width = width - GROUP_INDENT; + gtk_object_set(GTK_OBJECT(((ETableGroupContainerChildNode *)list->data)->child), + "width", child_width, + NULL); + } + + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gdouble etgc_get_width (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->width; +} + +static gdouble etgc_get_height (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->height; +} + +static void +etgc_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgc_destroy; + object_class->set_arg = etgc_set_arg; + object_class->get_arg = etgc_get_arg; + + item_class->event = etgc_event; + item_class->realize = etgc_realize; + item_class->unrealize = etgc_unrealize; + + etgc_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgc_add; + e_group_class->remove = etgc_remove; + e_group_class->increment = etgc_increment; + e_group_class->set_focus = etgc_set_focus; + e_group_class->get_focus_column = etgc_get_focus_column; + e_group_class->thaw = etgc_thaw; + + e_group_class->get_width = etgc_get_width; + e_group_class->set_width = etgc_set_width; + e_group_class->get_height = etgc_get_height; + + gtk_object_add_arg_type ("ETableGroupContainer::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupContainer::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupContainer::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgc_init (GtkObject *object) +{ + ETableGroupContainer *container = E_TABLE_GROUP_CONTAINER(object); + container->children = FALSE; +} + +static gboolean +etgc_update_positioning (ETableGroupContainer *etgc, gpointer data) +{ + gboolean frozen; + gtk_object_get(GTK_OBJECT(etgc), + "frozen", &frozen, + NULL); + if ( frozen ) { + etgc->idle = 0; + return FALSE; + } + if ( GTK_OBJECT_FLAGS( etgc ) & GNOME_CANVAS_ITEM_REALIZED ) { + gdouble old_height; + + old_height = etgc->height; + if ( etgc->children == NULL ) { + } else { + GList *list; + gdouble extra_height; + gdouble running_height; + gdouble item_height = 0; + + extra_height = 0; + if (etgc->font) + extra_height += etgc->font->ascent + etgc->font->descent + BUTTON_PADDING * 2; + + extra_height = MAX(extra_height, BUTTON_HEIGHT + BUTTON_PADDING * 2); + + running_height = extra_height; + + list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + gtk_object_get( GTK_OBJECT(child), + "height", &item_height, + NULL ); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child_node->text), + GROUP_INDENT, + running_height - BUTTON_PADDING); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child), + GROUP_INDENT, + running_height); + + gnome_canvas_item_set(GNOME_CANVAS_ITEM(child_node->rect), + "x1", (double) 0, + "x2", (double) etgc->width, + "y1", (double) running_height - extra_height, + "y2", (double) running_height + item_height, + NULL); + + running_height += item_height + extra_height; + } + running_height -= extra_height; + if ( running_height != old_height) { + etgc->height = running_height; + gtk_signal_emit_by_name (GTK_OBJECT (etgc), "resize"); + } + } + } + etgc->idle = 0; + return FALSE; +} + +static void +etgc_queue_reposition (ETableGroupContainer *etgc) +{ + if (etgc->idle == 0) + etgc->idle = g_idle_add((GSourceFunc)etgc_update_positioning, etgc); +} + +static void +etgc_child_resize (GtkObject *object, gpointer data) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(data); + etgc_queue_reposition (etgc); +} + +E_MAKE_TYPE (e_table_group_container, "ETableGroupContainer", ETableGroupContainer, etgc_class_init, etgc_init, PARENT_TYPE); + diff --git a/widgets/e-table/e-table-group-container.h b/widgets/e-table/e-table-group-container.h new file mode 100644 index 0000000000..4942f9e695 --- /dev/null +++ b/widgets/e-table/e-table-group-container.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_CONTAINER_H_ +#define _E_TABLE_GROUP_CONTAINER_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-model.h" +#include "e-table-header.h" +#include "e-table-group.h" + +#define E_TABLE_GROUP_CONTAINER_TYPE (e_table_group_container_get_type ()) +#define E_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainer)) +#define E_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainerClass)) +#define E_IS_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_CONTAINER_TYPE)) +#define E_IS_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_CONTAINER_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * The ETableCol used to group this set + */ + ETableCol *ecol; + + /* + * List of ETableGroups we stack + */ + GList *children; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + GdkFont *font; + + gdouble width, height; + + void *child_rules; + + gint idle; + + /* + * Update booleans: + */ + guint need_resize : 1; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; +} ETableGroupContainer; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupContainerClass; + +ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); +void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); + +GtkType e_table_group_container_get_type (void); + +#endif /* _E_TABLE_GROUP_CONTAINER_H_ */ diff --git a/widgets/e-table/e-table-group-leaf.c b/widgets/e-table/e-table-group-leaf.c new file mode 100644 index 0000000000..ba73ad9886 --- /dev/null +++ b/widgets/e-table/e-table-group-leaf.c @@ -0,0 +1,288 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-leaf.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgl_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static void +etgl_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object); +} + +static void +e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model); + etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_subset_variable_new(model)); +} + +ETableGroup * +e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + ETableGroupLeaf *etgl; + + g_return_val_if_fail (parent != NULL, NULL); + + etgl = gtk_type_new (e_table_group_leaf_get_type ()); + + e_table_group_leaf_construct (parent, etgl, full_header, + header, model); + return E_TABLE_GROUP (etgl); +} + +static void +etgl_resize (GtkObject *object, gpointer data) +{ + e_table_group_resize (E_TABLE_GROUP(data)); +} + +static void +etgl_realize (GnomeCanvasItem *item) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF(item); + gdouble height; + + if ( GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize ) + GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize (item); + + etgl->item = E_TABLE_ITEM(gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgl), + e_table_item_get_type (), + "ETableHeader", E_TABLE_GROUP(etgl)->header, + "ETableModel", etgl->subset, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + "width", etgl->width, + NULL)); + gtk_signal_connect(GTK_OBJECT(etgl->item), + "resize", etgl_resize, etgl); + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + if ( height != 1 ) + e_table_group_resize(E_TABLE_GROUP(etgl)); +} + +static int +etgl_event (GnomeCanvasItem *item, GdkEvent *event) +{ + gboolean return_val = TRUE; + + switch (event->type) { + + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event(item, event); + } + return return_val; + +} + +static void +etgl_add (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_add(etgl->subset, row); +} + +static gboolean +etgl_remove (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_subset_variable_remove(etgl->subset, row); +} + +static void +etgl_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_increment(etgl->subset, position, amount); +} + +static void +etgl_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + if (direction == E_FOCUS_END) { + e_table_item_focus(etgl->item, view_col, e_table_model_row_count(E_TABLE_MODEL(etgl->subset)) - 1); + } else { + e_table_item_focus(etgl->item, view_col, 0); + } +} + +static gint +etgl_get_focus_column (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_item_get_focused_column(etgl->item); +} + +static void +etgl_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + etgl->width = width; +#if 0 + if ( etgl->item ) { + gnome_canvas_item_set(GNOME_CANVAS_ITEM(etgl->item), + "width", width, + NULL); + } +#endif +} + +static gdouble +etgl_get_width (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gtk_object_get(GTK_OBJECT(etgl->item), + "width", &etgl->width, + NULL); + return etgl->width; +} + +static gdouble +etgl_get_height (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gdouble height; + if ( etgl->item ) + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + else + height = 1; + return height; +} + +static void +etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +etgl_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgl_destroy; + object_class->set_arg = etgl_set_arg; + object_class->get_arg = etgl_get_arg; + + item_class->realize = etgl_realize; + item_class->event = etgl_event; + + etgl_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgl_add; + e_group_class->remove = etgl_remove; + e_group_class->increment = etgl_increment; + e_group_class->set_focus = etgl_set_focus; + e_group_class->get_focus_column = etgl_get_focus_column; + + e_group_class->get_width = etgl_get_width; + e_group_class->set_width = etgl_set_width; + e_group_class->get_height = etgl_get_height; + + gtk_object_add_arg_type ("ETableGroupLeaf::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupLeaf::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupLeaf::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgl_init (GtkObject *object) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object); + + etgl->width = 1; + etgl->subset = NULL; + etgl->item = NULL; +} + +E_MAKE_TYPE (e_table_group_leaf, "ETableGroupLeaf", ETableGroupLeaf, etgl_class_init, etgl_init, PARENT_TYPE); diff --git a/widgets/e-table/e-table-group-leaf.h b/widgets/e-table/e-table-group-leaf.h new file mode 100644 index 0000000000..372bf4cc70 --- /dev/null +++ b/widgets/e-table/e-table-group-leaf.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_LEAF_H_ +#define _E_TABLE_GROUP_LEAF_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-group.h" +#include "e-table-subset-variable.h" +#include "e-table-item.h" + +#define E_TABLE_GROUP_LEAF_TYPE (e_table_group_leaf_get_type ()) +#define E_TABLE_GROUP_LEAF(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeaf)) +#define E_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeafClass)) +#define E_IS_TABLE_GROUP_LEAF(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_LEAF_TYPE)) +#define E_IS_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_LEAF_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * Item. + */ + ETableItem *item; + + gdouble width; + + ETableSubsetVariable *subset; +} ETableGroupLeaf; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupLeafClass; + +ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); +GtkType e_table_group_leaf_get_type (void); + +#endif /* _E_TABLE_GROUP_LEAF_H_ */ diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c index 5652d2623f..68bc3e7abf 100644 --- a/widgets/e-table/e-table-group.c +++ b/widgets/e-table/e-table-group.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-Table-Group.c: Implements the grouping objects for elements on a table * @@ -10,8 +11,11 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-group-container.h" +#include "e-table-group-leaf.h" #include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" #define TITLE_HEIGHT 16 @@ -19,88 +23,30 @@ #define PARENT_TYPE gnome_canvas_group_get_type () +#define ETG_CLASS(e) (E_TABLE_GROUP_CLASS(GTK_OBJECT(e)->klass)) + static GnomeCanvasGroupClass *etg_parent_class; enum { - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; static gint etg_signals [LAST_SIGNAL] = { 0, }; -static void -etg_destroy (GtkObject *object) -{ - ETableGroup *etg = E_TABLE_GROUP (object); - - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); -} - -static void -etg_dim (ETableGroup *etg, int *width, int *height) -{ - GSList *l; - - *width = *height = 0; - - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; - - *height += child->y2 - child->y1; - *width += child->x2 - child->x1; - } - - if (!etg->transparent){ - *height += TITLE_HEIGHT; - *width += GROUP_INDENT; - } -} +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; -void -e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, - gboolean transparent) -{ - gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - - etg->ecol = ecol; - etg->open = open; - etg->transparent = transparent; - - etg_dim (etg, &etg->width, &etg->height); - - if (!etg->transparent) - etg->rect = gnome_canvas_item_new ( - GNOME_CANVAS_GROUP (etg), - gnome_canvas_rect_get_type (), - "fill_color", "gray", - "outline_color", "gray20", - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); +static void etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static gboolean etg_get_focus (ETableGroup *etg); #if 0 - /* - * Reparent the child into our space. - */ - gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etg)); - - gnome_canvas_item_set ( - child, - "x", (double) GROUP_INDENT, - "y", (double) TITLE_HEIGHT, - NULL); - - /* - * Force dimension computation - */ - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update ( - GNOME_CANVAS_ITEM (etg), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); -#endif -} - GnomeCanvasItem * e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, gboolean open, gboolean transparent) @@ -116,158 +62,275 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, return GNOME_CANVAS_ITEM (etg); } +#endif -static void -etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +ETableGroup * +e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules) { - GSList *l; - int height = etg->transparent ? 0 : GROUP_INDENT; - gboolean move = FALSE; + g_return_val_if_fail (model != NULL, NULL); - printf ("Relaying out\n"); - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; + if(rules && !xmlStrcmp(rules->name, "group")) { + gint col_idx = atoi(xmlGetProp(rules, "column")); + ETableCol *col; + if ( col_idx > e_table_header_count(full_header) ) + return e_table_group_leaf_new(parent, full_header, header, model); + col = e_table_header_get_columns(full_header)[col_idx]; + return e_table_group_container_new(parent, full_header, header, model, col, rules->childs); + } else { + return e_table_group_leaf_new(parent, full_header, header, model); + } + return NULL; +} + +void +e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); + etg->full_header = full_header; + etg->header = header; + etg->model = model; +} + +void +e_table_group_add (ETableGroup *etg, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); - height += child->y2 - child->y1; + if ( ETG_CLASS (etg)->add ) + ETG_CLASS (etg)->add (etg, row); +} - if (child == eti) - move = TRUE; +gboolean +e_table_group_remove (ETableGroup *etg, + gint row) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); - if (move){ - printf ("Moving item %p\n", child); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); - } - } - if (height != etg->height){ - etg->height = height; - gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); - } + if ( ETG_CLASS (etg)->remove ) + return ETG_CLASS (etg)->remove (etg, row); + else + return FALSE; +} + +gint +e_table_group_get_count (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), 0); + + if ( ETG_CLASS (etg)->get_count ) + return ETG_CLASS (etg)->get_count (etg); + else + return 0; } void -e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +e_table_group_increment (ETableGroup *etg, + gint position, + gint amount) { - double x1, y1, x2, y2; - g_return_if_fail (etg != NULL); - g_return_if_fail (item != NULL); g_return_if_fail (E_IS_TABLE_GROUP (etg)); - g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); - - etg->children = g_slist_append (etg->children, item); - - GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); - - if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ - GSList *l; - int height = etg->transparent ? 0 : TITLE_HEIGHT; - int x = etg->transparent ? 0 : GROUP_INDENT; - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; - - height += child->y2 - child->y1; - - printf ("Height\n"); - if (E_IS_TABLE_ITEM (item)){ - printf (" Item: "); - } else { - printf (" Group: "); - } - printf ("%d\n", child->y2-child->y1); - } - gnome_canvas_item_set ( - item, - "y", (double) height, - "x", (double) x, - NULL); - - - if (E_IS_TABLE_ITEM (item)){ - - printf ("Table item! ---------\n"); - gtk_signal_connect (GTK_OBJECT (item), "height_changed", - GTK_SIGNAL_FUNC (etg_relayout), etg); - } - } + if ( ETG_CLASS (etg)->increment ) + ETG_CLASS (etg)->increment (etg, position, amount); } -static void -etg_realize (GnomeCanvasItem *item) +void +e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->set_focus ) + ETG_CLASS (etg)->set_focus (etg, direction, row); +} + +gboolean +e_table_group_get_focus (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus ) + return ETG_CLASS (etg)->get_focus (etg); + else + return FALSE; +} + +gboolean +e_table_group_get_focus_column (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus_column ) + return ETG_CLASS (etg)->get_focus_column (etg); + else + return FALSE; +} + +ETableCol * +e_table_group_get_ecol (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), NULL); + + if ( ETG_CLASS (etg)->get_ecol ) + return ETG_CLASS (etg)->get_ecol (etg); + else + return NULL; +} + +void +e_table_group_resize (ETableGroup *e_table_group) +{ + g_return_if_fail (e_table_group != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (e_table_group)); + + gtk_signal_emit (GTK_OBJECT (e_table_group), + etg_signals [RESIZE]); +} + +static int +etg_event (GnomeCanvasItem *item, GdkEvent *event) { ETableGroup *etg = E_TABLE_GROUP (item); - GSList *l; - int height = 0; - - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + gboolean return_val = TRUE; - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; + switch (event->type) { - printf ("During realization for child %p -> %d\n", child, height); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); + case GDK_FOCUS_CHANGE: + etg->has_focus = event->focus_change.in; + return_val = FALSE; - height += child->y2 - child->y1; + default: + return_val = FALSE; } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event(item, event); + } + return return_val; + } static void -etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +etg_thaw(ETableGroup *etg) { - ETableGroup *etg = E_TABLE_GROUP (item); + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->thaw ) + ETG_CLASS (etg)->thaw (etg); +} + +static void +etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); - - if (!etg->transparent){ - int current_width, current_height; - - etg_dim (etg, ¤t_width, ¤t_height); - - if ((current_height != etg->height) || (current_width != etg->width)){ - etg->width = current_width; - etg->height = current_height; - - gnome_canvas_item_set ( - etg->rect, - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etg_thaw(etg); } + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->set_width ) + ETG_CLASS(etg)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; } } static void +etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( ETG_CLASS(etg)->get_height ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->get_width ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean +etg_get_focus (ETableGroup *etg) +{ + return etg->has_focus; +} + +static void etg_class_init (GtkObjectClass *object_class) { GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *klass = (ETableGroupClass *) object_class; + + object_class->set_arg = etg_set_arg; + object_class->get_arg = etg_get_arg; - object_class->destroy = etg_destroy; + item_class->event = etg_event; - item_class->realize = etg_realize; - item_class->update = etg_update; + klass->resize = NULL; + + klass->add = NULL; + klass->remove = NULL; + klass->get_count = NULL; + klass->increment = NULL; + klass->set_focus = NULL; + klass->get_focus = etg_get_focus; + klass->get_ecol = NULL; + + klass->thaw = NULL; + klass->get_height = NULL; + klass->get_width = NULL; + klass->set_width = NULL; etg_parent_class = gtk_type_class (PARENT_TYPE); - etg_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + etg_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + GTK_SIGNAL_OFFSET (ETableGroupClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, etg_signals, LAST_SIGNAL); - } E_MAKE_TYPE (e_table_group, "ETableGroup", ETableGroup, etg_class_init, NULL, PARENT_TYPE); diff --git a/widgets/e-table/e-table-group.h b/widgets/e-table/e-table-group.h index 468d5dd794..1b3f346290 100644 --- a/widgets/e-table/e-table-group.h +++ b/widgets/e-table/e-table-group.h @@ -1,9 +1,12 @@ -#ifndef _E_TABLE_TREE_H_ -#define _E_TABLE_TREE_H_ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_H_ +#define _E_TABLE_GROUP_H_ #include <libgnomeui/gnome-canvas.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-util/e-util.h" #define E_TABLE_GROUP_TYPE (e_table_group_get_type ()) #define E_TABLE_GROUP(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_TYPE, ETableGroup)) @@ -15,49 +18,75 @@ typedef struct { GnomeCanvasGroup group; /* - * The ETableCol used to group this set + * The full header. */ - ETableCol *ecol; - - /* - * The canvas rectangle that contains the children - */ - GnomeCanvasItem *rect; - - /* - * Dimensions of the ETableGroup - */ - int width, height; - + ETableHeader *full_header; + ETableHeader *header; + /* - * State: the ETableGroup is open or closed + * The model we pull data from. */ - guint open:1; + ETableModel *model; /* * Whether we should add indentation and open/close markers, * or if we just act as containers of subtables. */ - guint transparent:1; + guint transparent : 1; - /* - * List of GnomeCanvasItems we stack - */ - GSList *children; + guint has_focus : 1; + + guint frozen : 1; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; - void (*height_changed) (ETableGroup *etg); + void (*resize) (ETableGroup *etg); + + void (*add) (ETableGroup *etg, gint row); + gboolean (*remove) (ETableGroup *etg, gint row); + gint (*get_count) (ETableGroup *etg); + void (*increment) (ETableGroup *etg, gint position, gint amount); + void (*set_focus) (ETableGroup *etg, EFocus direction, gint view_col); + gboolean (*get_focus) (ETableGroup *etg); + gint (*get_focus_column) (ETableGroup *etg); + ETableCol *(*get_ecol) (ETableGroup *etg); + + void (*thaw) (ETableGroup *etg); + gdouble (*get_height) (ETableGroup *etg); + gdouble (*get_width) (ETableGroup *etg); + void (*set_width) (ETableGroup *etg, gdouble width); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, - gboolean open, gboolean transparent); -void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, gboolean transparent); +void e_table_group_add (ETableGroup *etg, + gint row); +gboolean e_table_group_remove (ETableGroup *etg, + gint row); +gint e_table_group_get_count (ETableGroup *etg); +void e_table_group_increment (ETableGroup *etg, + gint position, + gint amount); +void e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint view_col); +gboolean e_table_group_get_focus (ETableGroup *etg); +gint e_table_group_get_focus_column (ETableGroup *etg); +ETableCol *e_table_group_get_ecol (ETableGroup *etg); + +ETableGroup *e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules); +void e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); -void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); +/* For emitting the signal */ +void e_table_group_resize (ETableGroup *etg); GtkType e_table_group_get_type (void); -#endif /* _E_TABLE_TREE_H_ */ +#endif /* _E_TABLE_GROUP_H_ */ diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index b025664385..6b6146c938 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -317,7 +317,7 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, { /* Check if it's the correct ethi */ if (ethi->drag_col == -1) - return; + return FALSE; gdk_drag_status (context, 0, time); if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { @@ -372,7 +372,7 @@ ethi_drag_drop (GtkWidget *canvas, gboolean successful = FALSE; if (ethi->drag_col == -1) - return; + return FALSE; if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && @@ -486,7 +486,6 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, { GdkRectangle clip; int xtra; - int arrowx; gdk_draw_rectangle ( drawable, gc, TRUE, @@ -541,7 +540,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, gtk_paint_arrow (gtk_widget_get_style(GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas)), drawable, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, + GTK_SHADOW_IN, &clip, GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas), "header", diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index 130c51a85c..d8ecdf1404 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel. * @@ -26,7 +27,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; @@ -36,12 +37,14 @@ enum { ARG_0, ARG_TABLE_HEADER, ARG_TABLE_MODEL, - ARG_TABLE_X, - ARG_TABLE_Y, ARG_TABLE_DRAW_GRID, ARG_TABLE_DRAW_FOCUS, ARG_MODE_SPREADSHEET, - ARG_LENGHT_THRESHOLD + ARG_LENGHT_THRESHOLD, + + ARG_WIDTH, + ARG_HEIGHT, + ARG_HAS_FOCUS }; static gboolean @@ -67,7 +70,7 @@ eti_realize_cell_views (ETableItem *eti) int i; for (i = 0; i < eti->n_cells; i++) - e_cell_view_realize (eti->cell_views [i], eti); + e_cell_realize (eti->cell_views [i]); eti->cell_views_realized = 1; } @@ -287,13 +290,13 @@ eti_compute_height (ETableItem *eti) int new_height = eti_get_height (eti); if (new_height != eti->height){ - double x1, y1, x2, y2; + /* double x1, y1, x2, y2;*/ printf ("Emitting!\n"); eti->height = new_height; eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); - gtk_signal_emit (GTK_OBJECT (eti), eti_signals [HEIGHT_CHANGED]); + gtk_signal_emit (GTK_OBJECT (eti), eti_signals [RESIZE]); } } @@ -537,14 +540,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) eti_add_table_model (eti, GTK_VALUE_POINTER (*arg)); break; - case ARG_TABLE_X: - eti->x1 = GTK_VALUE_DOUBLE (*arg); - break; - - case ARG_TABLE_Y: - eti->y1 = GTK_VALUE_DOUBLE (*arg); - break; - case ARG_LENGHT_THRESHOLD: eti->length_threshold = GTK_VALUE_INT (*arg); break; @@ -565,6 +560,27 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) } static void +eti_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableItem *eti; + + item = GNOME_CANVAS_ITEM (o); + eti = E_TABLE_ITEM (o); + + switch (arg_id){ + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = eti->width; + break; + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = eti->height; + break; + default: + arg->type = GTK_TYPE_INVALID; + } +} + +static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); @@ -576,7 +592,7 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - eti->renderers_can_change_size = 0; + eti->renderers_can_change_size = 1; eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -878,31 +894,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub } static void -eti_cursor_move_left (ETableItem *eti) +eti_cursor_move (ETableItem *eti, gint row, gint column) { e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); + e_table_item_focus (eti, column, row); +} + +static void +eti_cursor_move_left (ETableItem *eti) +{ + eti_cursor_move(eti, eti->focused_row, eti->focused_col - 1); } static void eti_cursor_move_right (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); + eti_cursor_move(eti, eti->focused_row, eti->focused_col + 1); } static void eti_cursor_move_up (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); + eti_cursor_move(eti, eti->focused_row - 1, eti->focused_col); } static void eti_cursor_move_down (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); + eti_cursor_move(eti, eti->focused_row + 1, eti->focused_col); } static int @@ -911,6 +930,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; ETableCol *ecol; + gint return_val = TRUE; switch (e->type){ case GDK_BUTTON_PRESS: @@ -982,66 +1002,66 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti->focused_col > 0) eti_cursor_move_left (eti); - - return TRUE; - + break; + case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - return TRUE; - + break; + case GDK_Up: if (eti->focused_row > 0) eti_cursor_move_up (eti); - return TRUE; + else + return_val = FALSE; + break; case GDK_Down: if ((eti->focused_row + 1) < eti->rows) eti_cursor_move_down (eti); - - return TRUE; + else + return_val = FALSE; + break; case GDK_Tab: + case GDK_KP_Tab: + case GDK_ISO_Left_Tab: if ((e->key.state & GDK_SHIFT_MASK) != 0){ /* shift tab */ if (eti->focused_col > 0) eti_cursor_move_left (eti); - else if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->cols - 1, eti->focused_row - 1); - } else { - /* FIXME: request focus leave backward */ - } + else if (eti->focused_row > 0) + eti_cursor_move(eti, eti->focused_row - 1, eti->cols - 1); + else + return_val = FALSE; } else { - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - else if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, 0, eti->rows - 1); - } else { - /* FIXME: request focus leave forward */ - } + else if (eti->focused_row < eti->rows - 1) + eti_cursor_move(eti, eti->focused_row + 1, 0); + else + return_val = FALSE; } break; default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) - return 0; + return_val = FALSE; if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff)) - return 0; + return_val = FALSE; } - } - ecol = e_table_header_get_column (eti->header, eti->focused_col); - ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + ecol = e_table_header_get_column (eti->header, eti->focused_col); + ecell_view = eti->cell_views [eti->focused_col]; + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + } break; - + case GDK_KEY_RELEASE: if (eti->focused_col == -1) return FALSE; @@ -1053,8 +1073,15 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } break; + case GDK_FOCUS_CHANGE: + if (e->focus_change.in) { + } else { + e_table_item_leave_edit (eti); + e_table_item_unfocus (eti); + } + default: - return FALSE; + return_val = FALSE; } return TRUE; } @@ -1084,6 +1111,7 @@ eti_class_init (GtkObjectClass *object_class) object_class->destroy = eti_destroy; object_class->set_arg = eti_set_arg; + object_class->get_arg = eti_get_arg; item_class->update = eti_update; item_class->realize = eti_realize; @@ -1099,10 +1127,6 @@ eti_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_HEADER); gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_TABLE_MODEL); - gtk_object_add_arg_type ("ETableItem::x", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_X); - gtk_object_add_arg_type ("ETableItem::y", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID); gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL, @@ -1110,6 +1134,13 @@ eti_class_init (GtkObjectClass *object_class) gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET); + gtk_object_add_arg_type ("ETableItem::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableItem::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableItem::has_focus", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_HAS_FOCUS); + eti_signals [ROW_SELECTION] = gtk_signal_new ("row_selection", GTK_RUN_LAST, @@ -1118,11 +1149,11 @@ eti_class_init (GtkObjectClass *object_class) gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); - eti_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + eti_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + GTK_SIGNAL_OFFSET (ETableItemClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); @@ -1192,6 +1223,16 @@ e_table_item_unfocus (ETableItem *eti) eti->focused_row = -1; } +gint +e_table_item_get_focused_column (ETableItem *eti) +{ + g_return_val_if_fail (eti != NULL, -1); + g_return_val_if_fail (E_IS_TABLE_ITEM (eti), -1); + + return eti->focused_col; +} + + const GSList * e_table_item_get_selection (ETableItem *eti) { diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index f19819f2fc..635dc76922 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -68,7 +68,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); - void (*height_changed) (ETableItem *eti); + void (*resize) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); @@ -79,6 +79,8 @@ GtkType e_table_item_get_type (void); void e_table_item_focus (ETableItem *eti, int col, int row); void e_table_item_unfocus (ETableItem *eti); +gint e_table_item_get_focused_column (ETableItem *eti); + /* * Selection */ diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index 9e397710ef..e84e6da4d3 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a Table Model * @@ -173,4 +174,23 @@ e_table_model_cell_changed (ETableModel *e_table_model, int col, int row) e_table_model_signals [MODEL_CELL_CHANGED], col, row); } +void +e_table_model_freeze (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = TRUE; + return ETM_CLASS (e_table_model)->thaw (e_table_model); +} +void +e_table_model_thaw (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = FALSE; + if (ETM_CLASS(e_table_model)->thaw) + ETM_CLASS (e_table_model)->thaw (e_table_model); +} diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h index 2d08f3744e..9f2dbbf87c 100644 --- a/widgets/e-table/e-table-model.h +++ b/widgets/e-table/e-table-model.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_MODEL_H_ #define _E_TABLE_MODEL_H_ @@ -11,6 +12,8 @@ typedef struct { GtkObject base; + + guint frozen : 1; } ETableModel; typedef struct { @@ -24,7 +27,7 @@ typedef struct { void *(*value_at) (ETableModel *etm, int col, int row); void (*set_value_at) (ETableModel *etm, int col, int row, const void *value); gboolean (*is_cell_editable) (ETableModel *etm, int col, int row); - + void (*thaw) (ETableModel *etm); /* * Signals */ @@ -48,6 +51,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_freeze (ETableModel *e_table_model); +void e_table_model_thaw (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c index 38e1dd8eb0..1f64d08f39 100644 --- a/widgets/e-table/e-table-simple.c +++ b/widgets/e-table/e-table-simple.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a simple table model implementation that uses function * pointers to simplify the creation of new, exotic and colorful tables in @@ -55,6 +56,14 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) } static void +simple_thaw (ETableModel *etm) +{ + ETableSimple *simple = (ETableSimple *)etm; + + simple->thaw (etm, simple->data); +} + +static void e_table_simple_class_init (GtkObjectClass *object_class) { ETableModelClass *model_class = (ETableModelClass *) object_class; @@ -64,6 +73,7 @@ e_table_simple_class_init (GtkObjectClass *object_class) model_class->value_at = simple_value_at; model_class->set_value_at = simple_set_value_at; model_class->is_cell_editable = simple_is_cell_editable; + model_class->thaw = simple_thaw; } GtkType @@ -95,6 +105,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data) { ETableSimple *et; @@ -106,6 +117,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->value_at = value_at; et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; + et->thaw = thaw; et->data = data; return (ETableModel *) et; diff --git a/widgets/e-table/e-table-simple.h b/widgets/e-table/e-table-simple.h index d890245386..a3164eefc0 100644 --- a/widgets/e-table/e-table-simple.h +++ b/widgets/e-table/e-table-simple.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SIMPLE_H_ #define _E_TABLE_SIMPLE_H_ @@ -8,6 +9,7 @@ typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *dat typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data); typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef void (*ETableSimpleThawFn) (ETableModel *etm, void *data); typedef struct { ETableModel parent; @@ -17,6 +19,7 @@ typedef struct { ETableSimpleValueAtFn value_at; ETableSimpleSetValueAtFn set_value_at; ETableSimpleIsCellEditableFn is_cell_editable; + ETableSimpleThawFn thaw; void *data; } ETableSimple; @@ -31,6 +34,7 @@ ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data); #endif /* _E_TABLE_SIMPLE_H_ */ diff --git a/widgets/e-table/e-table-sorted.h b/widgets/e-table/e-table-sorted.h index 2ec52df2e7..92bd8d1522 100644 --- a/widgets/e-table/e-table-sorted.h +++ b/widgets/e-table/e-table-sorted.h @@ -19,7 +19,7 @@ typedef struct { } ETableSorted; typedef struct { - ETableSubset parent_class; + ETableSubsetClass parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); diff --git a/widgets/e-table/e-table-subset-variable.c b/widgets/e-table/e-table-subset-variable.c new file mode 100644 index 0000000000..76da03c44f --- /dev/null +++ b/widgets/e-table/e-table-subset-variable.c @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-table-subset.c: Implements a table that contains a subset of another table. + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 Helix Code, Inc. + */ +#include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> +#include <string.h> +#include "e-util/e-util.h" +#include "e-table-subset-variable.h" + +#define PARENT_TYPE E_TABLE_SUBSET_TYPE + +#define INCREMENT_AMOUNT 10 + +static ETableModelClass *etssv_parent_class; + +static void +etssv_class_init (GtkObjectClass *klass) +{ + etssv_parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_table_subset_variable, "ETableSubsetVariable", ETableSubsetVariable, etssv_class_init, NULL, PARENT_TYPE); + +ETableModel * +e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source) +{ + if ( e_table_subset_construct(E_TABLE_SUBSET(etssv), source, 1) == NULL ) + return NULL; + E_TABLE_SUBSET(etssv)->n_map = 0; + + return E_TABLE_MODEL (etssv); +} + +ETableModel * +e_table_subset_variable_new (ETableModel *source) +{ + ETableSubsetVariable *etssv = gtk_type_new (E_TABLE_SUBSET_VARIABLE_TYPE); + + if (e_table_subset_variable_construct (etssv, source) == NULL){ + gtk_object_destroy (GTK_OBJECT (etssv)); + return NULL; + } + + return (ETableModel *) etssv; +} + +void +e_table_subset_variable_add (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + + if ( etss->n_map + 1 > etssv->n_vals_allocated ) + etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int)); + etss->map_table[etss->n_map++] = row; + if ( !etm->frozen ) + e_table_model_changed(etm); +} + +gboolean +e_table_subset_variable_remove (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + int i; + + for ( i = 0; i < etss->n_map; i++ ) { + if (etss->map_table[i] == row) { + memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int)); + etss->n_map --; + if ( !etm->frozen ) + e_table_model_changed(etm); + return TRUE; + } + } + return FALSE; +} + +void +e_table_subset_variable_increment (ETableSubsetVariable *etssv, + gint position, + gint amount) +{ + int i; + ETableSubset *etss = E_TABLE_SUBSET(etssv); + for ( i = 0; i < etss->n_map; i++ ) { + if ( etss->map_table[i] > position ) + etss->map_table[i] += amount; + } +} + +void +e_table_subset_variable_set_allocation (ETableSubsetVariable *etssv, + gint total) +{ + ETableSubset *etss = E_TABLE_SUBSET(etssv); + if ( total <= 0 ) + total = 1; + if ( total > etss->n_map ) { + etss->map_table = g_realloc(etss->map_table, total * sizeof(int)); + } +} diff --git a/widgets/e-table/e-table-subset-variable.h b/widgets/e-table/e-table-subset-variable.h new file mode 100644 index 0000000000..9755fb2477 --- /dev/null +++ b/widgets/e-table/e-table-subset-variable.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_SUBSET_VARIABLE_H_ +#define _E_TABLE_SUBSET_VARIABLE_H_ + +#include <gtk/gtkobject.h> +#include "e-table-subset.h" + +#define E_TABLE_SUBSET_VARIABLE_TYPE (e_table_subset_variable_get_type ()) +#define E_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariable)) +#define E_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariableClass)) +#define E_IS_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_SUBSET_VARIABLE_TYPE)) +#define E_IS_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SUBSET_VARIABLE_TYPE)) + +typedef struct { + ETableSubset base; + + int n_vals_allocated; +} ETableSubsetVariable; + +typedef struct { + ETableSubsetClass parent_class; +} ETableSubsetVariableClass; + +GtkType e_table_subset_variable_get_type (void); +ETableModel *e_table_subset_variable_new (ETableModel *etm); +ETableModel *e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source); +void e_table_subset_variable_add (ETableSubsetVariable *ets, + gint row); +gboolean e_table_subset_variable_remove (ETableSubsetVariable *ets, + gint row); +void e_table_subset_variable_increment (ETableSubsetVariable *ets, + gint position, + gint amount); +void e_table_subset_variable_set_allocation (ETableSubsetVariable *ets, + gint total); +#endif /* _E_TABLE_SUBSET_VARIABLE_H_ */ + diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c index a9e4a5c5a4..a09d221980 100644 --- a/widgets/e-table/e-table-subset.c +++ b/widgets/e-table/e-table-subset.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-subset.c: Implements a table that contains a subset of another table. * @@ -71,6 +72,12 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) } static void +etss_thaw (ETableModel *etm) +{ + e_table_model_changed (etm); +} + +static void etss_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; @@ -84,6 +91,7 @@ etss_class_init (GtkObjectClass *klass) table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; + table_class->thaw = etss_thaw; } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); @@ -91,20 +99,23 @@ E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, static void etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) { - e_table_model_changed (E_TABLE_MODEL (etss)); + if ( !E_TABLE_MODEL(etss)->frozen ) + e_table_model_changed (E_TABLE_MODEL (etss)); } static void etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_row_changed (E_TABLE_MODEL (etss), i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } } } } @@ -112,14 +123,16 @@ etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) static void etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } } } } @@ -130,7 +143,7 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + buffer = (unsigned int *) g_malloc (sizeof (unsigned int) * nvals); if (buffer == NULL) return NULL; etss->map_table = buffer; diff --git a/widgets/e-table/e-table-subset.h b/widgets/e-table/e-table-subset.h index 314f28aea6..d8af1696f5 100644 --- a/widgets/e-table/e-table-subset.h +++ b/widgets/e-table/e-table-subset.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SUBSET_H_ #define _E_TABLE_SUBSET_H_ diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 46531113e4..551ef52227 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -1,5 +1,6 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * E-table-view.c: A graphical view of a Table. + * E-table.c: A graphical view of a Table. * * Author: * Miguel de Icaza (miguel@gnu.org) @@ -16,7 +17,9 @@ #include <stdio.h> #include <libgnomeui/gnome-canvas.h> #include <gtk/gtksignal.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" +#include "e-util/e-xml-utils.h" #include "e-table.h" #include "e-table-header-item.h" #include "e-table-subset.h" @@ -40,8 +43,6 @@ et_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); - g_free (et->group_spec); - (*e_table_parent_class->destroy)(object); } @@ -56,19 +57,16 @@ e_table_init (GtkObject *object) } static ETableHeader * -e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +e_table_make_header (ETable *e_table, ETableHeader *full_header, xmlNode *xmlColumns) { ETableHeader *nh; - char *copy = alloca (strlen (cols) + 1); - char *p, *state; + xmlNode *column; const int max_cols = e_table_header_count (full_header); nh = e_table_header_new (); - strcpy (copy, cols); - while ((p = strtok_r (copy, ",", &state)) != NULL){ - int col = atoi (p); + for (column = xmlColumns->childs; column; column = column->next) { + int col = atoi (column->childs->content); - copy = NULL; if (col >= max_cols) continue; @@ -113,6 +111,7 @@ e_table_setup_header (ETable *e_table) } +#if 0 typedef struct { void *value; GArray *array; @@ -201,7 +200,7 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } - +#endif typedef struct _Node Node; struct _Node { @@ -212,7 +211,7 @@ struct _Node { guint is_leaf:1; }; - +#if 0 static Node * leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) { @@ -335,8 +334,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - - group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "columns", ecol, TRUE, parent == NULL); group = node_new (group_item, model, parent); for (i = 0; tables [i] != NULL; i++){ @@ -347,8 +347,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, GnomeCanvasItem *item_leaf_header; Node *leaf_header; + /* FIXME *//* item_leaf_header = e_table_group_new ( - GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE); + GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE);*/ leaf_header = node_new (item_leaf_header, tables [i], group); e_table_create_leaf (e_table, tables [i], leaf_header); @@ -424,6 +425,14 @@ static GnomeCanvasClass *e_table_canvas_parent_class; static void e_table_canvas_realize (GtkWidget *widget) { +#if 0 + GnomeCanvasItem *group_item; + + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "header", E_TABLE, TRUE, parent == NULL); + + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; int *groups; @@ -433,6 +442,8 @@ e_table_canvas_realize (GtkWidget *widget) groups = group_spec_to_desc (e_table->group_spec); + + leaf = e_table_create_nodes ( e_table, e_table->model, e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, groups); @@ -440,6 +451,7 @@ e_table_canvas_realize (GtkWidget *widget) if (groups) g_free (groups); +#endif } static void @@ -496,33 +508,75 @@ e_table_canvas_new (ETable *e_table) return GNOME_CANVAS (e_table_canvas); } +#endif static void -table_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) +table_canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) { + gdouble height; + gdouble width; + gtk_object_get(GTK_OBJECT(e_table->group), + "height", &height, + NULL); gnome_canvas_set_scroll_region ( GNOME_CANVAS (e_table->table_canvas), - 0, 0, alloc->width, alloc->height); + 0, 0, alloc->width, MAX(height, alloc->height)); + width = alloc->width; + gtk_object_set(GTK_OBJECT(e_table->group), + "width", width, + NULL); } static void -e_table_setup_table (ETable *e_table) +e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, ETableModel *model, xmlNode *xml_grouping) { - e_table->table_canvas = e_table_canvas_new (e_table); + e_table->table_canvas = GNOME_CANVAS(gnome_canvas_new ()); gtk_signal_connect ( GTK_OBJECT (e_table->table_canvas), "size_allocate", - GTK_SIGNAL_FUNC (table_canvas_size_alocate), e_table); + GTK_SIGNAL_FUNC (table_canvas_size_allocate), e_table); gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); gtk_table_attach ( GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + + e_table->group = e_table_group_new(GNOME_CANVAS_GROUP(e_table->table_canvas->root), + full_header, + header, + model, + xml_grouping->childs); + +} + +static void +e_table_fill_table (ETable *e_table, ETableModel *model) +{ + int count; + int i; + count = e_table_model_row_count(model); + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", TRUE, + NULL); + for ( i = 0; i < count; i++ ) { + e_table_group_add(e_table->group, i); + } + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", FALSE, + NULL); } void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec) + const char *spec) { + xmlDoc *xmlSpec; + xmlNode *xmlRoot; + xmlNode *xmlColumns; + xmlNode *xmlGrouping; + + char *copy; + copy = g_strdup(spec); + GTK_TABLE (e_table)->homogeneous = FALSE; gtk_table_resize (GTK_TABLE (e_table), 1, 2); @@ -532,24 +586,29 @@ e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, e_table->model = etm; gtk_object_ref (GTK_OBJECT (etm)); + + xmlSpec = xmlParseMemory(copy, strlen(copy) + 1); + e_table->specification = xmlSpec; - e_table->header = e_table_make_header (e_table, full_header, cols_spec); + xmlRoot = xmlDocGetRootElement(xmlSpec); + xmlColumns = e_xml_get_child_by_name(xmlRoot, "columns-shown"); + xmlGrouping = e_xml_get_child_by_name(xmlRoot, "grouping"); + + e_table->header = e_table_make_header (e_table, full_header, xmlColumns); e_table_setup_header (e_table); - e_table_setup_table (e_table); - - e_table->group_spec = g_strdup (group_spec); - + e_table_setup_table (e_table, full_header, e_table->header, etm, xmlGrouping); + e_table_fill_table (e_table, etm); } GtkWidget * -e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *spec) { ETable *e_table; e_table = gtk_type_new (e_table_get_type ()); - e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + e_table_construct (e_table, full_header, etm, spec); return (GtkWidget *) e_table; } diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index 63c131324f..a372d8042c 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -1,10 +1,13 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ #include <libgnomeui/gnome-canvas.h> #include <gtk/gtktable.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-table-group.h" BEGIN_GNOME_DECLS @@ -21,15 +24,17 @@ typedef struct { ETableHeader *full_header, *header; + ETableGroup *group; + GnomeCanvas *header_canvas, *table_canvas; GnomeCanvasItem *header_item, *root; + + xmlDoc *specification; guint draw_grid:1; guint draw_focus:1; guint spreadsheet:1; - - char *group_spec; } ETable; typedef struct { @@ -38,9 +43,9 @@ typedef struct { GtkType e_table_get_type (void); void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); END_GNOME_DECLS diff --git a/widgets/e-table/test-check.c b/widgets/e-table/test-check.c index 380da8048e..a6a59788ad 100644 --- a/widgets/e-table/test-check.c +++ b/widgets/e-table/test-check.c @@ -13,6 +13,7 @@ #include "e-table-header-item.h" #include "e-table-item.h" #include "e-util/e-cursors.h" +#include "e-util/e-canvas-utils.h" #include "e-cell-text.h" #include "e-cell-checkbox.h" @@ -79,6 +80,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -93,13 +100,14 @@ check_test (void) ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; GdkPixbuf *pixbuf; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -137,21 +145,15 @@ check_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 0, 30); } - - - - diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c index 3fe17ae555..adc9ed6c20 100644 --- a/widgets/e-table/test-cols.c +++ b/widgets/e-table/test-cols.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <string.h> #include <gnome.h> +#include "e-util/e-canvas-utils.h" #include "e-util/e-cursors.h" #include "e-table-simple.h" #include "e-table-header.h" @@ -84,6 +85,12 @@ set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); } +static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + void multi_cols_test (void) { @@ -92,13 +99,14 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -157,17 +165,17 @@ multi_cols_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); + + e_canvas_item_move_absolute(item, 0, 30); gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), @@ -176,18 +184,16 @@ multi_cols_test (void) "x", 300, "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header_multiple, "ETableModel", e_table_model, - "x", (double) 300, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 300, 30); } diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c index 27e1ac59f1..1bd50e1479 100644 --- a/widgets/e-table/test-table.c +++ b/widgets/e-table/test-table.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Test code for the ETable package * @@ -55,6 +56,8 @@ parse_headers () p = buffer; for (i = 0; (s = strtok (p, " \t")) != NULL; i++){ column_labels [i] = g_strdup (s); + if ( strchr(column_labels [i], '\n') ) + *strchr(column_labels [i], '\n') = 0; p = NULL; } @@ -174,6 +177,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -196,7 +205,7 @@ table_browser_test (void) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -244,8 +253,6 @@ table_browser_test (void) e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 0, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, @@ -253,7 +260,7 @@ table_browser_test (void) } static void -do_e_table_demo (const char *col_spec, const char *group_spec) +do_e_table_demo (const char *spec) { GtkWidget *e_table, *window, *frame; ETableModel *e_table_model; @@ -266,7 +273,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); full_header = e_table_header_new (); cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT, TRUE); @@ -283,7 +290,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); frame = gtk_frame_new (NULL); - e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + e_table = e_table_new (full_header, e_table_model, spec); gtk_container_add (GTK_CONTAINER (frame), e_table); gtk_container_add (GTK_CONTAINER (window), frame); @@ -298,9 +305,10 @@ e_table_test (void) { load_data (); - if (getenv ("DO")){ - do_e_table_demo ("0,1,2,3,4", NULL); - do_e_table_demo ("0,1,2,3,4", "3,4"); + if (1){/*getenv ("DO")){*/ + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf/> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <group column=\"4\"> <leaf/> </group> </group> </grouping> </ETableSpecification>"); } - do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\"> <leaf/> </group> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <leaf/> </group> </grouping> </ETableSpecification>"); } diff --git a/widgets/e-text-event-processor-emacs-like.c b/widgets/e-text-event-processor-emacs-like.c deleted file mode 100644 index 41bcd0c31d..0000000000 --- a/widgets/e-text-event-processor-emacs-like.c +++ /dev/null @@ -1,357 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-text-event-processor.c - * Copyright (C) 2000 Helix Code, Inc. - * Author: Chris Lahey <clahey@helixcode.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <gnome.h> -#include "e-text-event-processor-emacs-like.h" -static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card); -static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass); -static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event); - -static ETextEventProcessorClass *parent_class = NULL; - -/* The arguments we take */ -enum { - ARG_0 -}; - -static const ETextEventProcessorCommand control_keys[26] = -{ - { E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */ - { E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */ - { E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */ - { E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */ - { E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */ - { E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */ - { E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */ - { E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */ - { E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */ - { E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */ - { E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */ - { E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */ - { E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */ - { E_TEP_SELECTION, E_TEP_DELETE, 0, "" }, /* x */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */ -}; - -static const ETextEventProcessorCommand alt_keys[26] = -{ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */ - { E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */ - { E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */ - { E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */ - { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */ - -}; - -GtkType -e_text_event_processor_emacs_like_get_type (void) -{ - static GtkType text_event_processor_emacs_like_type = 0; - - if (!text_event_processor_emacs_like_type) - { - static const GtkTypeInfo text_event_processor_emacs_like_info = - { - "ETextEventProcessorEmacsLike", - sizeof (ETextEventProcessorEmacsLike), - sizeof (ETextEventProcessorEmacsLikeClass), - (GtkClassInitFunc) e_text_event_processor_emacs_like_class_init, - (GtkObjectInitFunc) e_text_event_processor_emacs_like_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info); - } - - return text_event_processor_emacs_like_type; -} - -static void -e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass) -{ - GtkObjectClass *object_class; - ETextEventProcessorClass *processor_class; - - object_class = (GtkObjectClass*) klass; - processor_class = (ETextEventProcessorClass*) klass; - - parent_class = gtk_type_class (e_text_event_processor_get_type ()); - - processor_class->event = e_text_event_processor_emacs_like_event; -} - -static void -e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep) -{ -} - -static gint -e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event) -{ - ETextEventProcessorCommand command; - ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep); - command.action = E_TEP_NOP; - switch (event->type) { - case GDK_BUTTON_PRESS: - if (event->button.button == 1) { - command.action = E_TEP_GRAB; - command.time = event->button.time; - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - if (event->button.state & GDK_SHIFT_MASK) - command.action = E_TEP_SELECT; - else - command.action = E_TEP_MOVE; - command.position = E_TEP_VALUE; - command.value = event->button.position; - command.time = event->button.time; - tep_el->mouse_down = TRUE; - } - break; - case GDK_BUTTON_RELEASE: - if (event->button.button == 1) { - command.action = E_TEP_UNGRAB; - command.time = event->button.time; - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - command.time = event->button.time; - tep_el->mouse_down = FALSE; - } else if (event->button.button == 2) { - command.action = E_TEP_MOVE; - command.position = E_TEP_VALUE; - command.value = event->button.position; - command.time = event->button.time; - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - - command.action = E_TEP_GET_SELECTION; - command.position = E_TEP_SELECTION; - command.value = 0; - command.time = event->button.time; - } - break; - case GDK_MOTION_NOTIFY: - if (tep_el->mouse_down) { - command.action = E_TEP_SELECT; - command.position = E_TEP_VALUE; - command.time = event->motion.time; - command.value = event->motion.position; - } - break; - case GDK_KEY_PRESS: - { - ETextEventProcessorEventKey key = event->key; - command.time = event->key.time; - if (key.state & GDK_SHIFT_MASK) - command.action = E_TEP_SELECT; - else - command.action = E_TEP_MOVE; - switch(key.keyval) { - case GDK_Home: - if (key.state & GDK_CONTROL_MASK) - command.position = E_TEP_START_OF_BUFFER; - else - command.position = E_TEP_START_OF_LINE; - break; - case GDK_End: - if (key.state & GDK_CONTROL_MASK) - command.position = E_TEP_END_OF_BUFFER; - else - command.position = E_TEP_END_OF_LINE; - break; - case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break; - case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break; - /* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */ - case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break; - case GDK_Down: command.position = E_TEP_FORWARD_LINE; break; - case GDK_Left: - if (key.state & GDK_CONTROL_MASK) - command.position = E_TEP_BACKWARD_WORD; - else - command.position = E_TEP_BACKWARD_CHARACTER; - break; - case GDK_Right: - if (key.state & GDK_CONTROL_MASK) - command.position = E_TEP_FORWARD_WORD; - else - command.position = E_TEP_FORWARD_CHARACTER; - break; - - case GDK_BackSpace: - command.action = E_TEP_DELETE; - if (key.state & GDK_CONTROL_MASK) - command.position = E_TEP_BACKWARD_WORD; - else - command.position = E_TEP_BACKWARD_CHARACTER; - break; - case GDK_Clear: - command.action = E_TEP_DELETE; - command.position = E_TEP_END_OF_LINE; - break; - case GDK_Insert: - if (key.state & GDK_SHIFT_MASK) { - command.action = E_TEP_PASTE; - command.position = E_TEP_SELECTION; - } else if (key.state & GDK_CONTROL_MASK) { - command.action = E_TEP_COPY; - command.position = E_TEP_SELECTION; - } else { - /* gtk_toggle_insert(text) -- IMPLEMENT */ - } - break; - case GDK_Delete: - if (key.state & GDK_CONTROL_MASK){ - command.action = E_TEP_DELETE; - command.position = E_TEP_FORWARD_WORD; - } else if (key.state & GDK_SHIFT_MASK) { - command.action = E_TEP_COPY; - command.position = E_TEP_SELECTION; - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - - command.action = E_TEP_DELETE; - command.position = E_TEP_SELECTION; - } else { - command.action = E_TEP_DELETE; - command.position = E_TEP_FORWARD_CHARACTER; - } - break; - case GDK_Tab: - /* Don't insert literally */ - command.action = E_TEP_NOP; - command.position = E_TEP_SELECTION; - break; - case GDK_Return: - if (key.state & GDK_CONTROL_MASK) { - command.action = E_TEP_ACTIVATE; - command.position = E_TEP_SELECTION; - } else { - command.action = E_TEP_INSERT; - command.position = E_TEP_SELECTION; - command.value = 1; - command.string = "\n"; - } - break; - case GDK_Escape: - /* Don't insert literally */ - command.action = E_TEP_NOP; - command.position = E_TEP_SELECTION; - break; - - default: - if (key.state & GDK_CONTROL_MASK) { - if ((key.keyval >= 'A') && (key.keyval <= 'Z')) - key.keyval -= 'A' - 'a'; - - if ((key.keyval >= 'a') && (key.keyval <= 'z')) { - command.position = control_keys[(int) (key.keyval - 'a')].position; - if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE) - command.action = control_keys[(int) (key.keyval - 'a')].action; - command.value = control_keys[(int) (key.keyval - 'a')].value; - command.string = control_keys[(int) (key.keyval - 'a')].string; - } - - if (key.keyval == 'x') { - command.action = E_TEP_COPY; - command.position = E_TEP_SELECTION; - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - - command.action = E_TEP_DELETE; - command.position = E_TEP_SELECTION; - } - - break; - } else if (key.state & GDK_MOD1_MASK) { - if ((key.keyval >= 'A') && (key.keyval <= 'Z')) - key.keyval -= 'A' - 'a'; - - if ((key.keyval >= 'a') && (key.keyval <= 'z')) { - command.position = alt_keys[(int) (key.keyval - 'a')].position; - if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE) - command.action = alt_keys[(int) (key.keyval - 'a')].action; - command.value = alt_keys[(int) (key.keyval - 'a')].value; - command.string = alt_keys[(int) (key.keyval - 'a')].string; - } - } else if (key.length > 0) { - command.action = E_TEP_INSERT; - command.position = E_TEP_SELECTION; - command.value = strlen(key.string); - command.string = key.string; - - } else { - command.action = E_TEP_NOP; - } - } - break; - case GDK_KEY_RELEASE: - command.time = event->key.time; - command.action = E_TEP_NOP; - break; - default: - command.action = E_TEP_NOP; - break; - } - } - if (command.action != E_TEP_NOP) { - gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command); - return 1; - } - else - return 0; -} - -ETextEventProcessor * -e_text_event_processor_emacs_like_new (void) -{ - ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ()); - return E_TEXT_EVENT_PROCESSOR (retval); -} - diff --git a/widgets/e-text-event-processor-emacs-like.h b/widgets/e-text-event-processor-emacs-like.h deleted file mode 100644 index 651bb552b3..0000000000 --- a/widgets/e-text-event-processor-emacs-like.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-text-event-processor-emacs-like.h - * Copyright (C) 2000 Helix Code, Inc. - * Author: Chris Lahey <clahey@helixcode.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ -#define __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ - -#include <gnome.h> -#include "e-text-event-processor.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* ETextEventProcessorEmacsLike - Turns events on a text widget into commands. Uses an emacs-ish interface. - * - */ - -#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE (e_text_event_processor_emacs_like_get_type ()) -#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLike)) -#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLikeClass)) -#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE)) -#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE)) - - -typedef struct _ETextEventProcessorEmacsLike ETextEventProcessorEmacsLike; -typedef struct _ETextEventProcessorEmacsLikeClass ETextEventProcessorEmacsLikeClass; - -struct _ETextEventProcessorEmacsLike -{ - ETextEventProcessor parent; - - /* object specific fields */ - gboolean mouse_down; -}; - -struct _ETextEventProcessorEmacsLikeClass -{ - ETextEventProcessorClass parent_class; -}; - - -GtkType e_text_event_processor_emacs_like_get_type (void); -ETextEventProcessor *e_text_event_processor_emacs_like_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ */ diff --git a/widgets/e-text-event-processor-types.h b/widgets/e-text-event-processor-types.h deleted file mode 100644 index 32a39bf0c0..0000000000 --- a/widgets/e-text-event-processor-types.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-text-event-processor.h - * Copyright (C) 2000 Helix Code, Inc. - * Author: Chris Lahey <clahey@helixcode.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef __E_TEXT_EVENT_PROCESSOR_TYPES_H__ -#define __E_TEXT_EVENT_PROCESSOR_TYPES_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <gdk/gdktypes.h> - -typedef enum _ETextEventProcessorCommandPosition ETextEventProcessorCommandPosition; -typedef enum _ETextEventProcessorCommandAction ETextEventProcessorCommandAction; -typedef struct _ETextEventProcessorCommand ETextEventProcessorCommand; - -typedef union _ETextEventProcessorEvent ETextEventProcessorEvent; -typedef struct _ETextEventProcessorEventButton ETextEventProcessorEventButton; -typedef struct _ETextEventProcessorEventKey ETextEventProcessorEventKey; -typedef struct _ETextEventProcessorEventMotion ETextEventProcessorEventMotion; - -enum _ETextEventProcessorCommandPosition { - E_TEP_VALUE, - E_TEP_SELECTION, - - E_TEP_START_OF_BUFFER, - E_TEP_END_OF_BUFFER, - - E_TEP_START_OF_LINE, - E_TEP_END_OF_LINE, - - E_TEP_FORWARD_CHARACTER, - E_TEP_BACKWARD_CHARACTER, - - E_TEP_FORWARD_WORD, - E_TEP_BACKWARD_WORD, - - E_TEP_FORWARD_LINE, - E_TEP_BACKWARD_LINE, - - E_TEP_FORWARD_PARAGRAPH, - E_TEP_BACKWARD_PARAGRAPH, - - E_TEP_FORWARD_PAGE, - E_TEP_BACKWARD_PAGE -}; - -enum _ETextEventProcessorCommandAction { - E_TEP_MOVE, - E_TEP_SELECT, - E_TEP_DELETE, - E_TEP_INSERT, - - E_TEP_COPY, - E_TEP_PASTE, - E_TEP_GET_SELECTION, - E_TEP_SET_SELECT_BY_WORD, - E_TEP_ACTIVATE, - - E_TEP_GRAB, - E_TEP_UNGRAB, - - E_TEP_NOP -}; - -struct _ETextEventProcessorCommand { - ETextEventProcessorCommandPosition position; - ETextEventProcessorCommandAction action; - int value; - char *string; - guint32 time; -}; - -struct _ETextEventProcessorEventButton { - GdkEventType type; - guint32 time; - guint state; - guint button; - gint position; -}; - -struct _ETextEventProcessorEventKey { - GdkEventType type; - guint32 time; - guint state; - guint keyval; - gint length; - gchar *string; -}; - -struct _ETextEventProcessorEventMotion { - GdkEventType type; - guint32 time; - guint state; - gint position; -}; - -union _ETextEventProcessorEvent { - GdkEventType type; - ETextEventProcessorEventButton button; - ETextEventProcessorEventKey key; - ETextEventProcessorEventMotion motion; -}; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __E_TEXT_EVENT_PROCESSOR_TYPES_H__ */ diff --git a/widgets/e-text-event-processor.c b/widgets/e-text-event-processor.c deleted file mode 100644 index 47f028ca62..0000000000 --- a/widgets/e-text-event-processor.c +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-text-event-processor.c - * Copyright (C) 2000 Helix Code, Inc. - * Author: Chris Lahey <clahey@helixcode.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <gnome.h> -#include "e-text-event-processor.h" -static void e_text_event_processor_init (ETextEventProcessor *card); -static void e_text_event_processor_class_init (ETextEventProcessorClass *klass); - -static GtkObjectClass *parent_class = NULL; - -/* The arguments we take */ -enum { - ARG_0 -}; - -enum { - E_TEP_EVENT, - E_TEP_LAST_SIGNAL -}; - -static guint e_tep_signals[E_TEP_LAST_SIGNAL] = { 0 }; - -GtkType -e_text_event_processor_get_type (void) -{ - static GtkType text_event_processor_type = 0; - - if (!text_event_processor_type) - { - static const GtkTypeInfo text_event_processor_info = - { - "ETextEventProcessor", - sizeof (ETextEventProcessor), - sizeof (ETextEventProcessorClass), - (GtkClassInitFunc) e_text_event_processor_class_init, - (GtkObjectInitFunc) e_text_event_processor_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - text_event_processor_type = gtk_type_unique (gtk_object_get_type (), &text_event_processor_info); - } - - return text_event_processor_type; -} - -static void -e_text_event_processor_class_init (ETextEventProcessorClass *klass) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass*) klass; - - parent_class = gtk_type_class (gtk_object_get_type ()); - - e_tep_signals[E_TEP_EVENT] = - gtk_signal_new ("command", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ETextEventProcessorClass, command), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, e_tep_signals, E_TEP_LAST_SIGNAL); - - klass->event = NULL; - klass->command = NULL; -} - -static void -e_text_event_processor_init (ETextEventProcessor *tep) -{ -} - -gint -e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event) -{ - if (E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event) { - return E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event(tep, event); - } else { - return 0; - } -} diff --git a/widgets/e-text-event-processor.h b/widgets/e-text-event-processor.h deleted file mode 100644 index 1fc79f3f70..0000000000 --- a/widgets/e-text-event-processor.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-text-event-processor.h - * Copyright (C) 2000 Helix Code, Inc. - * Author: Chris Lahey <clahey@helixcode.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_TEXT_EVENT_PROCESSOR_H__ -#define __E_TEXT_EVENT_PROCESSOR_H__ - -#include <gnome.h> -#include "e-text-event-processor-types.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* ETextEventProcessor - Turns events on a text widget into commands. - * - */ - -#define E_TEXT_EVENT_PROCESSOR_TYPE (e_text_event_processor_get_type ()) -#define E_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessor)) -#define E_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessorClass)) -#define E_IS_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE)) -#define E_IS_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE)) - - -typedef struct _ETextEventProcessor ETextEventProcessor; -typedef struct _ETextEventProcessorClass ETextEventProcessorClass; - -struct _ETextEventProcessor -{ - GtkObject parent; - - /* object specific fields */ - -}; - -struct _ETextEventProcessorClass -{ - GtkObjectClass parent_class; - - /* signals */ - void (* command) (ETextEventProcessor *tep, ETextEventProcessorCommand *command); - - /* virtual functions */ - gint (* event) (ETextEventProcessor *tep, ETextEventProcessorEvent *event); -}; - - -GtkType e_text_event_processor_get_type (void); -gint e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __E_TEXT_EVENT_PROCESSOR_H__ */ diff --git a/widgets/e-text.c b/widgets/e-text.c deleted file mode 100644 index b33e99194d..0000000000 --- a/widgets/e-text.c +++ /dev/null @@ -1,2526 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* EText - Text item for evolution. - * Copyright (C) 2000 Helix Code, Inc. - * - * Author: Chris Lahey <clahey@umich.edu> - * - * A majority of code taken from: - * - * Text item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent - * canvas widget. Tk is copyrighted by the Regents of the University - * of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998 The Free Software Foundation - * - * Author: Federico Mena <federico@nuclecu.unam.mx> */ - -#include <config.h> -#include <math.h> -#include <ctype.h> -#include "e-text.h" -#include <gdk/gdkx.h> /* for BlackPixel */ -#include <libart_lgpl/art_affine.h> -#include <libart_lgpl/art_rgb.h> -#include <libart_lgpl/art_rgb_bitmap_affine.h> -#include <gtk/gtkinvisible.h> - -#include "e-text-event-processor-emacs-like.h" - -enum { - E_TEXT_RESIZE, - E_TEXT_CHANGE, - E_TEXT_LAST_SIGNAL -}; - -static guint e_text_signals[E_TEXT_LAST_SIGNAL] = { 0 }; - - - -/* This defines a line of text */ -struct line { - char *text; /* Line's text, it is a pointer into the text->text string */ - int length; /* Line's length in characters */ - int width; /* Line's width in pixels */ - int ellipsis_length; /* Length before adding ellipsis */ -}; - - - -/* Object argument IDs */ -enum { - ARG_0, - ARG_TEXT, - ARG_X, - ARG_Y, - ARG_FONT, - ARG_FONTSET, - ARG_FONT_GDK, - ARG_ANCHOR, - ARG_JUSTIFICATION, - ARG_CLIP_WIDTH, - ARG_CLIP_HEIGHT, - ARG_CLIP, - ARG_X_OFFSET, - ARG_Y_OFFSET, - ARG_FILL_COLOR, - ARG_FILL_COLOR_GDK, - ARG_FILL_COLOR_RGBA, - ARG_FILL_STIPPLE, - ARG_TEXT_WIDTH, - ARG_TEXT_HEIGHT, - ARG_EDITABLE, - ARG_USE_ELLIPSIS, - ARG_ELLIPSIS, - ARG_LINE_WRAP, - ARG_MAX_LINES -}; - - -enum { - E_SELECTION_PRIMARY, - E_SELECTION_CLIPBOARD -}; -enum { - TARGET_STRING, - TARGET_TEXT, - TARGET_COMPOUND_TEXT -}; - -static void e_text_class_init (ETextClass *class); -static void e_text_init (EText *text); -static void e_text_destroy (GtkObject *object); -static void e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); - -static void e_text_update (GnomeCanvasItem *item, double *affine, - ArtSVP *clip_path, int flags); -static void e_text_realize (GnomeCanvasItem *item); -static void e_text_unrealize (GnomeCanvasItem *item); -static void e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - int x, int y, int width, int height); -static double e_text_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, - GnomeCanvasItem **actual_item); -static void e_text_bounds (GnomeCanvasItem *item, - double *x1, double *y1, double *x2, double *y2); -static void e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf); -static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event); - -static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data); - -static guint32 e_text_get_event_time (EText *text); - -static void e_text_get_selection(EText *text, GdkAtom selection, guint32 time); -static void e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length); - -static GtkWidget *e_text_get_invisible(EText *text); -static void _selection_clear_event (GtkInvisible *invisible, - GdkEventSelection *event, - EText *text); -static void _selection_get (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EText *text); -static void _selection_received (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint time, - EText *text); - -static ETextSuckFont *e_suck_font (GdkFont *font); -static void e_suck_font_free (ETextSuckFont *suckfont); - - -static GnomeCanvasItemClass *parent_class; -static GdkAtom clipboard_atom = GDK_NONE; - - - -/** - * e_text_get_type: - * @void: - * - * Registers the &EText class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &EText class. - **/ -GtkType -e_text_get_type (void) -{ - static GtkType text_type = 0; - - if (!text_type) { - GtkTypeInfo text_info = { - "EText", - sizeof (EText), - sizeof (ETextClass), - (GtkClassInitFunc) e_text_class_init, - (GtkObjectInitFunc) e_text_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - text_type = gtk_type_unique (gnome_canvas_item_get_type (), &text_info); - } - - return text_type; -} - -/* Class initialization function for the text item */ -static void -e_text_class_init (ETextClass *klass) -{ - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - object_class = (GtkObjectClass *) klass; - item_class = (GnomeCanvasItemClass *) klass; - - parent_class = gtk_type_class (gnome_canvas_item_get_type ()); - - e_text_signals[E_TEXT_RESIZE] = - gtk_signal_new ("resize", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ETextClass, resize), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - - e_text_signals[E_TEXT_CHANGE] = - gtk_signal_new ("change", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (ETextClass, change), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - - gtk_object_class_add_signals (object_class, e_text_signals, E_TEXT_LAST_SIGNAL); - - gtk_object_add_arg_type ("EText::text", - GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TEXT); - gtk_object_add_arg_type ("EText::x", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X); - gtk_object_add_arg_type ("EText::y", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y); - gtk_object_add_arg_type ("EText::font", - GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FONT); - gtk_object_add_arg_type ("EText::fontset", - GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FONTSET); - gtk_object_add_arg_type ("EText::font_gdk", - GTK_TYPE_GDK_FONT, GTK_ARG_READWRITE, ARG_FONT_GDK); - gtk_object_add_arg_type ("EText::anchor", - GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR); - gtk_object_add_arg_type ("EText::justification", - GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFICATION); - gtk_object_add_arg_type ("EText::clip_width", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_CLIP_WIDTH); - gtk_object_add_arg_type ("EText::clip_height", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_CLIP_HEIGHT); - gtk_object_add_arg_type ("EText::clip", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CLIP); - gtk_object_add_arg_type ("EText::x_offset", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X_OFFSET); - gtk_object_add_arg_type ("EText::y_offset", - GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y_OFFSET); - gtk_object_add_arg_type ("EText::fill_color", - GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_FILL_COLOR); - gtk_object_add_arg_type ("EText::fill_color_gdk", - GTK_TYPE_GDK_COLOR, GTK_ARG_READWRITE, ARG_FILL_COLOR_GDK); - gtk_object_add_arg_type ("EText::fill_color_rgba", - GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA); - gtk_object_add_arg_type ("EText::fill_stipple", - GTK_TYPE_GDK_WINDOW, GTK_ARG_READWRITE, ARG_FILL_STIPPLE); - gtk_object_add_arg_type ("EText::text_width", - GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_WIDTH); - gtk_object_add_arg_type ("EText::text_height", - GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_HEIGHT); - gtk_object_add_arg_type ("EText::editable", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE); - gtk_object_add_arg_type ("EText::use_ellipsis", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_USE_ELLIPSIS); - gtk_object_add_arg_type ("EText::ellipsis", - GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ELLIPSIS); - gtk_object_add_arg_type ("EText::line_wrap", - GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_LINE_WRAP); - gtk_object_add_arg_type ("EText::max_lines", - GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MAX_LINES); - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); - - - - klass->resize = NULL; - klass->change = NULL; - - object_class->destroy = e_text_destroy; - object_class->set_arg = e_text_set_arg; - object_class->get_arg = e_text_get_arg; - - item_class->update = e_text_update; - item_class->realize = e_text_realize; - item_class->unrealize = e_text_unrealize; - item_class->draw = e_text_draw; - item_class->point = e_text_point; - item_class->bounds = e_text_bounds; - item_class->render = e_text_render; - item_class->event = e_text_event; -} - -/* Object initialization function for the text item */ -static void -e_text_init (EText *text) -{ - text->x = 0.0; - text->y = 0.0; - text->anchor = GTK_ANCHOR_CENTER; - text->justification = GTK_JUSTIFY_LEFT; - text->clip_width = 0.0; - text->clip_height = 0.0; - text->xofs = 0.0; - text->yofs = 0.0; - - text->ellipsis = NULL; - text->use_ellipsis = FALSE; - text->ellipsis_width = 0; - - text->editable = FALSE; - text->editing = FALSE; - text->xofs_edit = 0; - - text->selection_start = 0; - text->selection_end = 0; - text->select_by_word = FALSE; - - text->timeout_id = 0; - text->timer = NULL; - - text->lastx = 0; - text->lasty = 0; - text->last_state = 0; - - text->scroll_start = 0; - text->show_cursor = TRUE; - text->button_down = FALSE; - - text->tep = NULL; - - text->has_selection = FALSE; - - text->invisible = NULL; - text->primary_selection = NULL; - text->primary_length = 0; - text->clipboard_selection = NULL; - text->clipboard_length = 0; - - text->pointer_in = FALSE; - text->default_cursor_shown = TRUE; - - text->line_wrap = FALSE; - text->max_lines = -1; -} - -/* Destroy handler for the text item */ -static void -e_text_destroy (GtkObject *object) -{ - EText *text; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNOME_IS_CANVAS_TEXT (object)); - - text = E_TEXT (object); - - if (text->text) - g_free (text->text); - - if (text->tep) - gtk_object_unref (GTK_OBJECT(text->tep)); - - if (text->invisible) - gtk_object_unref (GTK_OBJECT(text->invisible)); - - if (text->lines) - g_free (text->lines); - - if (text->font) - gdk_font_unref (text->font); - - if (text->suckfont) - e_suck_font_free (text->suckfont); - - if (text->stipple) - gdk_bitmap_unref (text->stipple); - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - -static void -get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, double *py2) -{ - GnomeCanvasItem *item; - double x, y; - double clip_x, clip_y; - int old_height; - - item = GNOME_CANVAS_ITEM (text); - - x = text->x; - y = text->y; - - clip_x = x; - clip_y = y; - - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; - else - text->height = 0; - - if (old_height != text->height) - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); - - /* Anchor text */ - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - x -= text->max_width / 2; - clip_x -= text->clip_width / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - x -= text->max_width; - clip_x -= text->clip_width; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - y -= text->height / 2; - clip_y -= text->clip_height / 2; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - y -= text->height; - clip_y -= text->clip_height; - break; - } - - /* Bounds */ - - if (text->clip) { - /* maybe do bbox intersection here? */ - *px1 = clip_x; - *py1 = clip_y; - *px2 = clip_x + text->clip_width; - *py2 = clip_y + text->clip_height; - } else { - *px1 = x; - *py1 = y; - *px2 = x + text->max_width; - *py2 = y + text->height; - } -} - -static void -get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) -{ - GnomeCanvasItem *item; - double wx, wy; - int old_height; - - item = GNOME_CANVAS_ITEM (text); - - /* Get canvas pixel coordinates for text position */ - - wx = text->x; - wy = text->y; - gnome_canvas_item_i2w (item, &wx, &wy); - gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy); - - /* Get canvas pixel coordinates for clip rectangle position */ - - gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); - text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit; - text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; - - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; - else - text->height = 0; - - if (old_height != text->height) - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); - - /* Anchor text */ - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - text->cx -= text->max_width / 2; - text->clip_cx -= text->clip_cwidth / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - text->cx -= text->max_width; - text->clip_cx -= text->clip_cwidth; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - text->cy -= text->height / 2; - text->clip_cy -= text->clip_cheight / 2; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - text->cy -= text->height; - text->clip_cy -= text->clip_cheight; - break; - } - - /* Bounds */ - - if (text->clip) { - *px1 = text->clip_cx; - *py1 = text->clip_cy; - *px2 = text->clip_cx + text->clip_cwidth; - *py2 = text->clip_cy + text->clip_cheight; - } else { - *px1 = text->cx; - *py1 = text->cy; - *px2 = text->cx + text->max_width; - *py2 = text->cy + text->height; - } -} - -/* Recalculates the bounding box of the text item. The bounding box is defined - * by the text's extents if the clip rectangle is disabled. If it is enabled, - * the bounding box is defined by the clip rectangle itself. - */ -static void -recalc_bounds (EText *text) -{ - GnomeCanvasItem *item; - - item = GNOME_CANVAS_ITEM (text); - - get_bounds (text, &item->x1, &item->y1, &item->x2, &item->y2); - - gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); -} - -static void -calc_ellipsis (EText *text) -{ - if (text->font) - text->ellipsis_width = - gdk_text_width (text->font, - text->ellipsis ? text->ellipsis : "...", - text->ellipsis ? strlen (text->ellipsis) : 3); -} - -/* Calculates the line widths (in pixels) of the text's splitted lines */ -static void -calc_line_widths (EText *text) -{ - struct line *lines; - int i; - int j; - - lines = text->lines; - text->max_width = 0; - - if (!lines) - return; - - for (i = 0; i < text->num_lines; i++) { - if (lines->length != 0) { - if (text->font) { - lines->width = gdk_text_width (text->font, - lines->text, lines->length); - lines->ellipsis_length = 0; - } else { - lines->width = 0; - } - - if (text->clip && - text->use_ellipsis && - ! text->editing && - lines->width > text->clip_width) { - if (text->font) { - lines->ellipsis_length = 0; - for (j = 0; j < lines->length; j++ ) { - if (gdk_text_width (text->font, lines->text, j) + text->ellipsis_width <= text->clip_width) - lines->ellipsis_length = j; - else - break; - } - } - else - lines->ellipsis_length = 0; - lines->width = gdk_text_width (text->font, lines->text, lines->ellipsis_length) + - text->ellipsis_width; - } - else - lines->ellipsis_length = lines->length; - - if (lines->width > text->max_width) - text->max_width = lines->width; - } - - lines++; - } -} - -/* Splits the text of the text item into lines */ -static void -split_into_lines (EText *text) -{ - char *p; - struct line *lines; - int len; - int line_num; - char *laststart; - char *lastend; - char *linestart; - - /* Free old array of lines */ - - if (text->lines) - g_free (text->lines); - - text->lines = NULL; - text->num_lines = 0; - - if (!text->text) - return; - - /* First, count the number of lines */ - - lastend = text->text; - laststart = text->text; - linestart = text->text; - - for (p = text->text; *p; p++) { - if (text->line_wrap && (*p == ' ' || *p == '\n')) { - if ( laststart != lastend - && gdk_text_width(text->font, - linestart, - p - linestart) - > text->clip_width ) { - text->num_lines ++; - linestart = laststart; - laststart = p + 1; - lastend = p; - } else if (*p == ' ') { - laststart = p + 1; - lastend = p; - } - } - if (*p == '\n') { - text->num_lines ++; - lastend = p + 1; - laststart = p + 1; - linestart = p + 1; - } - } - - if (text->line_wrap) { - if ( laststart != lastend - && gdk_text_width(text->font, - linestart, - p - linestart) - > text->clip_width ) { - text->num_lines ++; - } - } - - text->num_lines++; - - if ( (!text->editing) && text->max_lines != -1 && text->num_lines > text->max_lines ) { - text->num_lines = text->max_lines; - } - - /* Allocate array of lines and calculate split positions */ - - text->lines = lines = g_new0 (struct line, text->num_lines); - len = 0; - line_num = 1; - lastend = text->text; - laststart = text->text; - - for (p = text->text; line_num < text->num_lines && *p; p++) { - gboolean handled = FALSE; - if (len == 0) - lines->text = p; - if (text->line_wrap && (*p == ' ' || *p == '\n')) { - if ( gdk_text_width(text->font, - lines->text, - p - lines->text) - > text->clip_width - && laststart != lastend ) { - lines->length = lastend - lines->text; - lines++; - line_num ++; - len = p - laststart; - lines->text = laststart; - laststart = p + 1; - lastend = p; - } else if (*p == ' ') { - laststart = p + 1; - lastend = p; - len ++; - } - handled = TRUE; - } - if ( line_num >= text->num_lines ) - break; - if (*p == '\n') { - lines->length = p - lines->text; - lines++; - line_num ++; - len = 0; - lastend = p + 1; - laststart = p + 1; - handled = TRUE; - } - if (!handled) - len++; - } - - if ( line_num < text->num_lines && text->line_wrap ) { - if ( gdk_text_width(text->font, - lines->text, - p - lines->text) - > text->clip_width - && laststart != lastend ) { - lines->length = lastend - lines->text; - lines++; - line_num ++; - len = p - laststart; - lines->text = laststart; - laststart = p + 1; - lastend = p; - } - } - - if (len == 0) - lines->text = p; - lines->length = strlen(lines->text); - - calc_line_widths (text); -} - -/* Convenience function to set the text's GC's foreground color */ -static void -set_text_gc_foreground (EText *text) -{ - GdkColor c; - - if (!text->gc) - return; - - c.pixel = text->pixel; - gdk_gc_set_foreground (text->gc, &c); -} - -/* Sets the stipple pattern for the text */ -static void -set_stipple (EText *text, GdkBitmap *stipple, int reconfigure) -{ - if (text->stipple && !reconfigure) - gdk_bitmap_unref (text->stipple); - - text->stipple = stipple; - if (stipple && !reconfigure) - gdk_bitmap_ref (stipple); - - if (text->gc) { - if (stipple) { - gdk_gc_set_stipple (text->gc, stipple); - gdk_gc_set_fill (text->gc, GDK_STIPPLED); - } else - gdk_gc_set_fill (text->gc, GDK_SOLID); - } -} - -/* Set_arg handler for the text item */ -static void -e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - GnomeCanvasItem *item; - EText *text; - GdkColor color = { 0, 0, 0, 0, }; - GdkColor *pcolor; - gboolean color_changed; - int have_pixel; - - item = GNOME_CANVAS_ITEM (object); - text = E_TEXT (object); - - color_changed = FALSE; - have_pixel = FALSE; - - switch (arg_id) { - case ARG_TEXT: - if (text->text) - g_free (text->text); - - text->text = g_strdup (GTK_VALUE_STRING (*arg)); - split_into_lines (text); - recalc_bounds (text); - break; - - case ARG_X: - text->x = GTK_VALUE_DOUBLE (*arg); - recalc_bounds (text); - break; - - case ARG_Y: - text->y = GTK_VALUE_DOUBLE (*arg); - recalc_bounds (text); - break; - - case ARG_FONT: - if (text->font) - gdk_font_unref (text->font); - - text->font = gdk_font_load (GTK_VALUE_STRING (*arg)); - - if (item->canvas->aa) { - if (text->suckfont) - e_suck_font_free (text->suckfont); - - text->suckfont = e_suck_font (text->font); - } - - calc_ellipsis (text); - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_FONTSET: - if (text->font) - gdk_font_unref (text->font); - - text->font = gdk_fontset_load (GTK_VALUE_STRING (*arg)); - - if (item->canvas->aa) { - if (text->suckfont) - e_suck_font_free (text->suckfont); - - text->suckfont = e_suck_font (text->font); - } - - calc_ellipsis (text); - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_FONT_GDK: - if (text->font) - gdk_font_unref (text->font); - - text->font = GTK_VALUE_BOXED (*arg); - gdk_font_ref (text->font); - - if (item->canvas->aa) { - if (text->suckfont) - e_suck_font_free (text->suckfont); - - text->suckfont = e_suck_font (text->font); - } - calc_ellipsis (text); - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_ANCHOR: - text->anchor = GTK_VALUE_ENUM (*arg); - recalc_bounds (text); - break; - - case ARG_JUSTIFICATION: - text->justification = GTK_VALUE_ENUM (*arg); - break; - - case ARG_CLIP_WIDTH: - text->clip_width = fabs (GTK_VALUE_DOUBLE (*arg)); - calc_ellipsis (text); - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_CLIP_HEIGHT: - text->clip_height = fabs (GTK_VALUE_DOUBLE (*arg)); - recalc_bounds (text); - break; - - case ARG_CLIP: - text->clip = GTK_VALUE_BOOL (*arg); - calc_ellipsis (text); - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_X_OFFSET: - text->xofs = GTK_VALUE_DOUBLE (*arg); - recalc_bounds (text); - break; - - case ARG_Y_OFFSET: - text->yofs = GTK_VALUE_DOUBLE (*arg); - recalc_bounds (text); - break; - - case ARG_FILL_COLOR: - if (GTK_VALUE_STRING (*arg)) - gdk_color_parse (GTK_VALUE_STRING (*arg), &color); - - text->rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case ARG_FILL_COLOR_GDK: - pcolor = GTK_VALUE_BOXED (*arg); - if (pcolor) { - color = *pcolor; - gdk_color_context_query_color (item->canvas->cc, &color); - have_pixel = TRUE; - } - - text->rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case ARG_FILL_COLOR_RGBA: - text->rgba = GTK_VALUE_UINT (*arg); - color_changed = TRUE; - break; - - case ARG_FILL_STIPPLE: - set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE); - break; - - case ARG_EDITABLE: - text->editable = GTK_VALUE_BOOL (*arg); - break; - - case ARG_USE_ELLIPSIS: - text->use_ellipsis = GTK_VALUE_BOOL (*arg); - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_ELLIPSIS: - if (text->ellipsis) - g_free (text->ellipsis); - - text->ellipsis = g_strdup (GTK_VALUE_STRING (*arg)); - calc_ellipsis (text); - calc_line_widths (text); - recalc_bounds (text); - break; - - case ARG_LINE_WRAP: - text->line_wrap = GTK_VALUE_BOOL (*arg); - split_into_lines (text); - recalc_bounds (text); - break; - - case ARG_MAX_LINES: - text->max_lines = GTK_VALUE_INT (*arg); - split_into_lines (text); - recalc_bounds (text); - break; - - default: - break; - } - - if (color_changed) { - if (have_pixel) - text->pixel = color.pixel; - else - text->pixel = gnome_canvas_get_color_pixel (item->canvas, text->rgba); - - if (!item->canvas->aa) - set_text_gc_foreground (text); - - gnome_canvas_item_request_update (item); - } -} - -/* Get_arg handler for the text item */ -static void -e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EText *text; - GdkColor *color; - - text = E_TEXT (object); - - switch (arg_id) { - case ARG_TEXT: - GTK_VALUE_STRING (*arg) = g_strdup (text->text); - break; - - case ARG_X: - GTK_VALUE_DOUBLE (*arg) = text->x; - break; - - case ARG_Y: - GTK_VALUE_DOUBLE (*arg) = text->y; - break; - - case ARG_FONT_GDK: - GTK_VALUE_BOXED (*arg) = text->font; - break; - - case ARG_ANCHOR: - GTK_VALUE_ENUM (*arg) = text->anchor; - break; - - case ARG_JUSTIFICATION: - GTK_VALUE_ENUM (*arg) = text->justification; - break; - - case ARG_CLIP_WIDTH: - GTK_VALUE_DOUBLE (*arg) = text->clip_width; - break; - - case ARG_CLIP_HEIGHT: - GTK_VALUE_DOUBLE (*arg) = text->clip_height; - break; - - case ARG_CLIP: - GTK_VALUE_BOOL (*arg) = text->clip; - break; - - case ARG_X_OFFSET: - GTK_VALUE_DOUBLE (*arg) = text->xofs; - break; - - case ARG_Y_OFFSET: - GTK_VALUE_DOUBLE (*arg) = text->yofs; - break; - - case ARG_FILL_COLOR_GDK: - color = g_new (GdkColor, 1); - color->pixel = text->pixel; - gdk_color_context_query_color (text->item.canvas->cc, color); - GTK_VALUE_BOXED (*arg) = color; - break; - - case ARG_FILL_COLOR_RGBA: - GTK_VALUE_UINT (*arg) = text->rgba; - break; - - case ARG_FILL_STIPPLE: - GTK_VALUE_BOXED (*arg) = text->stipple; - break; - - case ARG_TEXT_WIDTH: - GTK_VALUE_DOUBLE (*arg) = text->max_width / text->item.canvas->pixels_per_unit; - break; - - case ARG_TEXT_HEIGHT: - GTK_VALUE_DOUBLE (*arg) = text->height / text->item.canvas->pixels_per_unit; - break; - - case ARG_EDITABLE: - GTK_VALUE_BOOL (*arg) = text->editable; - break; - - case ARG_USE_ELLIPSIS: - GTK_VALUE_BOOL (*arg) = text->use_ellipsis; - break; - - case ARG_ELLIPSIS: - GTK_VALUE_STRING (*arg) = g_strdup (text->ellipsis); - break; - - case ARG_LINE_WRAP: - GTK_VALUE_BOOL (*arg) = text->line_wrap; - break; - - case ARG_MAX_LINES: - GTK_VALUE_INT (*arg) = text->max_lines; - break; - - default: - arg->type = GTK_TYPE_INVALID; - break; - } -} - -/* Update handler for the text item */ -static void -e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) -{ - EText *text; - double x1, y1, x2, y2; - ArtDRect i_bbox, c_bbox; - int i; - - text = E_TEXT (item); - - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - - if (!item->canvas->aa) { - set_text_gc_foreground (text); - set_stipple (text, text->stipple, TRUE); - get_bounds (text, &x1, &y1, &x2, &y2); - - gnome_canvas_update_bbox (item, x1, y1, x2, y2); - } else { - /* aa rendering */ - for (i = 0; i < 6; i++) - text->affine[i] = affine[i]; - get_bounds_item_relative (text, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); - art_drect_affine_transform (&c_bbox, &i_bbox, affine); - gnome_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1); - - } -} - -/* Realize handler for the text item */ -static void -e_text_realize (GnomeCanvasItem *item) -{ - EText *text; - - text = E_TEXT (item); - - if (parent_class->realize) - (* parent_class->realize) (item); - - text->gc = gdk_gc_new (item->canvas->layout.bin_window); - - text->i_cursor = gdk_cursor_new (GDK_XTERM); - text->default_cursor = gdk_cursor_new (GDK_LEFT_PTR); -} - -/* Unrealize handler for the text item */ -static void -e_text_unrealize (GnomeCanvasItem *item) -{ - EText *text; - - text = E_TEXT (item); - - gdk_gc_unref (text->gc); - text->gc = NULL; - - gdk_cursor_destroy (text->i_cursor); - gdk_cursor_destroy (text->default_cursor); - - if (parent_class->unrealize) - (* parent_class->unrealize) (item); -} - -/* Calculates the x position of the specified line of text, based on the text's justification */ -static double -get_line_xpos_item_relative (EText *text, struct line *line) -{ - double x; - - x = text->x; - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - x -= text->max_width / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - x -= text->max_width; - break; - } - - switch (text->justification) { - case GTK_JUSTIFY_RIGHT: - x += text->max_width - line->width; - break; - - case GTK_JUSTIFY_CENTER: - x += (text->max_width - line->width) * 0.5; - break; - - default: - /* For GTK_JUSTIFY_LEFT, we don't have to do anything. We do not support - * GTK_JUSTIFY_FILL, yet. - */ - break; - } - - return x; -} - -/* Calculates the y position of the first line of text. */ -static double -get_line_ypos_item_relative (EText *text) -{ - double y; - - y = text->y; - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - y -= text->height / 2; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - y -= text->height; - break; - } - - return y; -} - -/* Calculates the x position of the specified line of text, based on the text's justification */ -static int -get_line_xpos (EText *text, struct line *line) -{ - int x; - - x = text->cx; - - switch (text->justification) { - case GTK_JUSTIFY_RIGHT: - x += text->max_width - line->width; - break; - - case GTK_JUSTIFY_CENTER: - x += (text->max_width - line->width) / 2; - break; - - default: - /* For GTK_JUSTIFY_LEFT, we don't have to do anything. We do not support - * GTK_JUSTIFY_FILL, yet. - */ - break; - } - - return x; -} - -static void -_get_tep(EText *text) -{ - if (!text->tep) { - text->tep = e_text_event_processor_emacs_like_new(); - gtk_object_ref (GTK_OBJECT (text->tep)); - gtk_object_sink (GTK_OBJECT (text->tep)); - gtk_signal_connect(GTK_OBJECT(text->tep), - "command", - GTK_SIGNAL_FUNC(e_text_command), - (gpointer) text); - } -} - -/* Draw handler for the text item */ -static void -e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - int x, int y, int width, int height) -{ - EText *text; - GdkRectangle rect, *clip_rect; - struct line *lines; - int i; - int xpos, ypos; - int start_char, end_char; - int sel_start, sel_end; - GdkRectangle sel_rect; - GdkGC *fg_gc; - GnomeCanvas *canvas; - - text = E_TEXT (item); - canvas = GNOME_CANVAS_ITEM(text)->canvas; - - fg_gc = GTK_WIDGET(canvas)->style->fg_gc[text->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; - - if (!text->text || !text->font) - return; - - clip_rect = NULL; - if (text->clip) { - rect.x = text->clip_cx - x; - rect.y = text->clip_cy - y; - rect.width = text->clip_cwidth; - rect.height = text->clip_cheight; - - gdk_gc_set_clip_rectangle (text->gc, &rect); - gdk_gc_set_clip_rectangle (fg_gc, &rect); - clip_rect = ▭ - } - lines = text->lines; - ypos = text->cy + text->font->ascent; - - if (text->stipple) - gnome_canvas_set_stipple_origin (item->canvas, text->gc); - - for (i = 0; i < text->num_lines; i++) { - xpos = get_line_xpos (text, lines); - if (text->editing) { - xpos -= text->xofs_edit; - start_char = lines->text - text->text; - end_char = start_char + lines->length; - sel_start = text->selection_start; - sel_end = text->selection_end; - if (sel_start > sel_end ) { - sel_start ^= sel_end; - sel_end ^= sel_start; - sel_start ^= sel_end; - } - if ( sel_start < start_char ) - sel_start = start_char; - if ( sel_end > end_char ) - sel_end = end_char; - if ( sel_start < sel_end ) { - sel_rect.x = xpos - x + gdk_text_width (text->font, - lines->text, - sel_start - start_char); - sel_rect.y = ypos - y - text->font->ascent; - sel_rect.width = gdk_text_width (text->font, - lines->text + sel_start - start_char, - sel_end - sel_start); - sel_rect.height = text->font->ascent + text->font->descent; - gtk_paint_flat_box(GTK_WIDGET(item->canvas)->style, - drawable, - text->has_selection ? - GTK_STATE_SELECTED : - GTK_STATE_ACTIVE, - GTK_SHADOW_NONE, - clip_rect, - GTK_WIDGET(item->canvas), - "text", - sel_rect.x, - sel_rect.y, - sel_rect.width, - sel_rect.height); - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x, - ypos - y, - lines->text, - sel_start - start_char); - gdk_draw_text (drawable, - text->font, - fg_gc, - xpos - x + gdk_text_width (text->font, - lines->text, - sel_start - start_char), - ypos - y, - lines->text + sel_start - start_char, - sel_end - sel_start); - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x + gdk_text_width (text->font, - lines->text, - sel_end - start_char), - ypos - y, - lines->text + sel_end - start_char, - end_char - sel_end); - } else { - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x, - ypos - y, - lines->text, - lines->length); - } - if (text->selection_start == text->selection_end && - text->selection_start >= start_char && - text->selection_start <= end_char && - text->show_cursor) { - gdk_draw_rectangle (drawable, - text->gc, - TRUE, - xpos - x + gdk_text_width (text->font, - lines->text, - sel_start - start_char), - ypos - y - text->font->ascent, - 1, - text->font->ascent + text->font->descent); - } - } else { - if ( text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) { - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x, - ypos - y, - lines->text, - lines->ellipsis_length); - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x + - lines->width - text->ellipsis_width, - ypos - y, - text->ellipsis ? text->ellipsis : "...", - text->ellipsis ? strlen (text->ellipsis) : 3); - } else - - gdk_draw_text (drawable, - text->font, - text->gc, - xpos - x, - ypos - y, - lines->text, - lines->length); - } - - ypos += text->font->ascent + text->font->descent; - lines++; - } - - if (text->clip) { - gdk_gc_set_clip_rectangle (text->gc, NULL); - gdk_gc_set_clip_rectangle (fg_gc, NULL); - } -} - -/* Render handler for the text item */ -static void -e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) -{ - EText *text; - guint32 fg_color; - double xpos, ypos; - struct line *lines; - int i, j; - double affine[6]; - ETextSuckFont *suckfont; - int dx, dy; - ArtPoint start_i, start_c; - - text = E_TEXT (item); - - if (!text->text || !text->font || !text->suckfont) - return; - - suckfont = text->suckfont; - - fg_color = text->rgba; - - gnome_canvas_buf_ensure_buf (buf); - - lines = text->lines; - start_i.y = get_line_ypos_item_relative (text); - - art_affine_scale (affine, item->canvas->pixels_per_unit, item->canvas->pixels_per_unit); - for (i = 0; i < 6; i++) - affine[i] = text->affine[i]; - - for (i = 0; i < text->num_lines; i++) { - if (lines->length != 0) { - start_i.x = get_line_xpos_item_relative (text, lines); - art_affine_point (&start_c, &start_i, text->affine); - xpos = start_c.x; - ypos = start_c.y; - - for (j = 0; j < lines->length; j++) { - ETextSuckChar *ch; - - ch = &suckfont->chars[(unsigned char)((lines->text)[j])]; - - affine[4] = xpos; - affine[5] = ypos; - art_rgb_bitmap_affine ( - buf->buf, - buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1, - buf->buf_rowstride, - suckfont->bitmap + (ch->bitmap_offset >> 3), - ch->width, - suckfont->bitmap_height, - suckfont->bitmap_width >> 3, - fg_color, - affine, - ART_FILTER_NEAREST, NULL); - - dx = ch->left_sb + ch->width + ch->right_sb; - xpos += dx * affine[0]; - ypos += dx * affine[1]; - } - } - - dy = text->font->ascent + text->font->descent; - start_i.y += dy; - lines++; - } - - buf->is_bg = 0; -} - -/* Point handler for the text item */ -static double -e_text_point (GnomeCanvasItem *item, double x, double y, - int cx, int cy, GnomeCanvasItem **actual_item) -{ - EText *text; - int i; - struct line *lines; - int x1, y1, x2, y2; - int font_height; - int dx, dy; - double dist, best; - - text = E_TEXT (item); - - *actual_item = item; - - /* The idea is to build bounding rectangles for each of the lines of - * text (clipped by the clipping rectangle, if it is activated) and see - * whether the point is inside any of these. If it is, we are done. - * Otherwise, calculate the distance to the nearest rectangle. - */ - - if (text->font) - font_height = text->font->ascent + text->font->descent; - else - font_height = 0; - - best = 1.0e36; - - lines = text->lines; - - for (i = 0; i < text->num_lines; i++) { - /* Compute the coordinates of rectangle for the current line, - * clipping if appropriate. - */ - - x1 = get_line_xpos (text, lines); - y1 = text->cy + i * font_height; - x2 = x1 + lines->width; - y2 = y1 + font_height; - - if (text->clip) { - if (x1 < text->clip_cx) - x1 = text->clip_cx; - - if (y1 < text->clip_cy) - y1 = text->clip_cy; - - if (x2 > (text->clip_cx + text->clip_width)) - x2 = text->clip_cx + text->clip_width; - - if (y2 > (text->clip_cy + text->clip_height)) - y2 = text->clip_cy + text->clip_height; - - if ((x1 >= x2) || (y1 >= y2)) - continue; - } - - /* Calculate distance from point to rectangle */ - - if (cx < x1) - dx = x1 - cx; - else if (cx >= x2) - dx = cx - x2 + 1; - else - dx = 0; - - if (cy < y1) - dy = y1 - cy; - else if (cy >= y2) - dy = cy - y2 + 1; - else - dy = 0; - - if ((dx == 0) && (dy == 0)) - return 0.0; - - dist = sqrt (dx * dx + dy * dy); - if (dist < best) - best = dist; - - /* Next! */ - - lines++; - } - - return best / item->canvas->pixels_per_unit; -} - -/* Bounds handler for the text item */ -static void -e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) -{ - EText *text; - double width, height; - - text = E_TEXT (item); - - *x1 = text->x; - *y1 = text->y; - - if (text->clip) { - width = text->clip_width; - height = text->clip_height; - } else { - width = text->max_width / item->canvas->pixels_per_unit; - height = text->height / item->canvas->pixels_per_unit; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - *x1 -= width / 2.0; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - *x1 -= width; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - *y1 -= height / 2.0; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - *y1 -= height; - break; - } - - *x2 = *x1 + width; - *y2 = *y1 + height; -} - -static void -_get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) -{ - if (xp || yp) { - struct line *lines; - int x, y; - int j; - x = get_line_xpos (text, lines); - y = text->cy; - for (j = 0, lines = text->lines; j < text->num_lines; lines++, j++) { - if (lines->text > text->text + position) - break; - y += text->font->ascent + text->font->descent; - } - lines --; - y -= text->font->descent; - - x += gdk_text_width (text->font, - lines->text, - position - (lines->text - text->text)); - x -= text->xofs_edit; - if (xp) - *xp = x; - if (yp) - *yp = y; - } -} - -static gint -_get_position_from_xy (EText *text, gint x, gint y) -{ - int i, j; - int ypos = text->cy; - int xpos; - struct line *lines; - j = 0; - while (y > ypos) { - ypos += text->font->ascent + text->font->descent; - j ++; - } - j--; - if (j >= text->num_lines) - j = text->num_lines - 1; - if (j < 0) - j = 0; - i = 0; - lines = text->lines; - lines += j; - x += text->xofs_edit; - xpos = get_line_xpos (text, lines); - for(i = 0; i < lines->length; i++) { - int charwidth = gdk_text_width(text->font, - lines->text + i, - 1); - xpos += charwidth / 2; - if (xpos > x) { - break; - } - xpos += (charwidth + 1) / 2; - } - return lines->text + i - text->text; -} - -#define SCROLL_WAIT_TIME 30000 - -static gboolean -_blink_scroll_timeout (gpointer data) -{ - EText *text = E_TEXT(data); - gulong current_time; - gboolean scroll = FALSE; - gboolean redraw = FALSE; - - g_timer_elapsed(text->timer, ¤t_time); - - if (text->scroll_start + SCROLL_WAIT_TIME > 1000000) { - if (current_time > text->scroll_start - (1000000 - SCROLL_WAIT_TIME) && - current_time < text->scroll_start) - scroll = TRUE; - } else { - if (current_time > text->scroll_start + SCROLL_WAIT_TIME || - current_time < text->scroll_start) - scroll = TRUE; - } - if (scroll && text->button_down) { - if (text->lastx - text->clip_cx > text->clip_cwidth && - text->xofs_edit < text->max_width - text->clip_cwidth) { - text->xofs_edit += 4; - if (text->xofs_edit > text->max_width - text->clip_cwidth + 1) - text->xofs_edit = text->max_width - text->clip_cwidth + 1; - redraw = TRUE; - } - if (text->lastx - text->clip_cx < 0 && - text->xofs_edit > 0) { - text->xofs_edit -= 4; - if (text->xofs_edit < 0) - text->xofs_edit = 0; - redraw = TRUE; - } - if (redraw) { - ETextEventProcessorEvent e_tep_event; - e_tep_event.type = GDK_MOTION_NOTIFY; - e_tep_event.motion.state = text->last_state; - e_tep_event.motion.time = 0; - e_tep_event.motion.position = _get_position_from_xy(text, text->lastx, text->lasty); - _get_tep(text); - e_text_event_processor_handle_event (text->tep, - &e_tep_event); - text->scroll_start = current_time; - } - } - - if (!((current_time / 500000) % 2)) { - if (!text->show_cursor) - redraw = TRUE; - text->show_cursor = TRUE; - } else { - if (text->show_cursor) - redraw = TRUE; - text->show_cursor = FALSE; - } - if (redraw) - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); - return TRUE; -} - -static gint -e_text_event (GnomeCanvasItem *item, GdkEvent *event) -{ - EText *text = E_TEXT(item); - ETextEventProcessorEvent e_tep_event; - - gint return_val = 0; - - e_tep_event.type = event->type; - switch (event->type) { - case GDK_FOCUS_CHANGE: - if (text->editable) { - GdkEventFocus *focus_event; - focus_event = (GdkEventFocus *) event; - if (focus_event->in) { - if(!text->editing) { - text->editing = TRUE; - if ( text->pointer_in ) { - if ( text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->i_cursor); - text->default_cursor_shown = FALSE; - } - } - text->selection_start = 0; - text->selection_end = 0; - text->select_by_word = FALSE; - text->xofs_edit = 0; - if (text->timeout_id == 0) - text->timeout_id = g_timeout_add(10, _blink_scroll_timeout, text); - text->timer = g_timer_new(); - g_timer_elapsed(text->timer, &(text->scroll_start)); - g_timer_start(text->timer); - } - } else { - text->editing = FALSE; - if ( ! text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->default_cursor); - text->default_cursor_shown = TRUE; - } - if (text->timeout_id) { - g_source_remove(text->timeout_id); - text->timeout_id = 0; - } - if (text->timer) { - g_timer_stop(text->timer); - g_timer_destroy(text->timer); - text->timer = NULL; - } - } - if ( text->line_wrap ) - split_into_lines (text); - else - calc_line_widths (text); - recalc_bounds (text); - } - return_val = 0; - break; - case GDK_KEY_PRESS: /* Fall Through */ - case GDK_KEY_RELEASE: - if (text->editing) { - GdkEventKey key = event->key; - e_tep_event.key.time = key.time; - e_tep_event.key.state = key.state; - e_tep_event.key.keyval = key.keyval; - e_tep_event.key.length = key.length; - e_tep_event.key.string = key.string; - _get_tep(text); - return e_text_event_processor_handle_event (text->tep, - &e_tep_event); - } - else - return 0; - break; - case GDK_BUTTON_PRESS: /* Fall Through */ - case GDK_BUTTON_RELEASE: - if (text->editing) { - GdkEventButton button = event->button; - e_tep_event.button.time = button.time; - e_tep_event.button.state = button.state; - e_tep_event.button.button = button.button; - e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y); - _get_tep(text); - return_val = e_text_event_processor_handle_event (text->tep, - &e_tep_event); - if (event->button.button == 1) { - if (event->type == GDK_BUTTON_PRESS) - text->button_down = TRUE; - else - text->button_down = FALSE; - } - text->lastx = button.x; - text->lasty = button.y; - text->last_state = button.state; - } else if (text->editable && event->type == GDK_BUTTON_RELEASE && event->button.button == 1) { - gnome_canvas_item_grab_focus (item); - return 1; - } - break; - case GDK_MOTION_NOTIFY: - if (text->editing) { - GdkEventMotion motion = event->motion; - e_tep_event.motion.time = motion.time; - e_tep_event.motion.state = motion.state; - e_tep_event.motion.position = _get_position_from_xy(text, motion.x, motion.y); - _get_tep(text); - return_val = e_text_event_processor_handle_event (text->tep, - &e_tep_event); - text->lastx = motion.x; - text->lasty = motion.y; - text->last_state = motion.state; - } - break; - case GDK_ENTER_NOTIFY: - text->pointer_in = TRUE; - if (text->editing) { - if ( text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->i_cursor); - text->default_cursor_shown = FALSE; - } - } - break; - case GDK_LEAVE_NOTIFY: - text->pointer_in = FALSE; - if (text->editing) { - if ( ! text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->default_cursor); - text->default_cursor_shown = TRUE; - } - } - break; - default: - break; - } - if (return_val) - return return_val; - if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event) - return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event); - else - return 0; -} - -static int -_get_position(EText *text, ETextEventProcessorCommand *command) -{ - int i; - int length; - int x, y; - - switch (command->position) { - - case E_TEP_VALUE: - return command->value; - - case E_TEP_SELECTION: - return text->selection_end; - - case E_TEP_START_OF_BUFFER: - return 0; - case E_TEP_END_OF_BUFFER: - return strlen(text->text); - - case E_TEP_START_OF_LINE: - for (i = text->selection_end - 2; i > 0; i--) - if (text->text[i] == '\n') { - i++; - break; - } - return i; - case E_TEP_END_OF_LINE: - length = strlen(text->text); - for (i = text->selection_end + 1; i < length; i++) - if (text->text[i] == '\n') { - break; - } - if (i > length) - i = length; - return i; - - case E_TEP_FORWARD_CHARACTER: - length = strlen(text->text); - i = text->selection_end + 1; - if (i > length) - i = length; - return i; - case E_TEP_BACKWARD_CHARACTER: - i = text->selection_end - 1; - if (i < 0) - i = 0; - return i; - - case E_TEP_FORWARD_WORD: - length = strlen(text->text); - for (i = text->selection_end + 1; i < length; i++) - if (isspace(text->text[i])) { - break; - } - if (i > length) - i = length; - return i; - case E_TEP_BACKWARD_WORD: - for (i = text->selection_end - 2; i > 0; i--) - if (isspace(text->text[i])) { - i++; - break; - } - if (i < 0) - i = 0; - return i; - - case E_TEP_FORWARD_LINE: - _get_xy_from_position(text, text->selection_end, &x, &y); - y += text->font->ascent + text->font->descent; - return _get_position_from_xy(text, x, y); - case E_TEP_BACKWARD_LINE: - _get_xy_from_position(text, text->selection_end, &x, &y); - y -= text->font->ascent + text->font->descent; - return _get_position_from_xy(text, x, y); - - case E_TEP_FORWARD_PARAGRAPH: - case E_TEP_BACKWARD_PARAGRAPH: - - case E_TEP_FORWARD_PAGE: - case E_TEP_BACKWARD_PAGE: - return text->selection_end; - default: - return text->selection_end; - } -} - -static void -_delete_selection(EText *text) -{ - gint length = strlen(text->text); - if (text->selection_end == text->selection_start) - return; - if (text->selection_end < text->selection_start) { - text->selection_end ^= text->selection_start; - text->selection_start ^= text->selection_end; - text->selection_end ^= text->selection_start; - } - memmove( text->text + text->selection_start, - text->text + text->selection_end, - length - text->selection_end + 1 ); - length -= text->selection_end - text->selection_start; - text->selection_end = text->selection_start; -} - -static void -_insert(EText *text, char *string, int value) -{ - if (value > 0) { - char *temp; - gint length = strlen(text->text); - temp = g_new(gchar, length + value + 1); - strncpy(temp, text->text, text->selection_start); - strncpy(temp + text->selection_start, string, value); - strcpy(temp + text->selection_start + value, text->text + text->selection_start); - g_free(text->text); - text->text = temp; - text->selection_start += value; - text->selection_end = text->selection_start; - } -} - -static void -e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data) -{ - EText *text = E_TEXT(data); - int sel_start, sel_end; - switch (command->action) { - case E_TEP_MOVE: - text->selection_start = _get_position(text, command); - text->selection_end = text->selection_start; - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_SELECT: - text->selection_end = _get_position(text, command); - sel_start = MIN(text->selection_start, text->selection_end); - sel_end = MAX(text->selection_start, text->selection_end); - if (sel_start != sel_end) { - e_text_supply_selection (text, command->time, GDK_SELECTION_PRIMARY, text->text + sel_start, sel_end - sel_start); - } else if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_DELETE: - if (text->selection_end == text->selection_start) { - text->selection_end = _get_position(text, command); - } - _delete_selection(text); - split_into_lines (text); - recalc_bounds (text); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - - case E_TEP_INSERT: - if (text->selection_end != text->selection_start) { - _delete_selection(text); - } - _insert(text, command->string, command->value); - split_into_lines (text); - recalc_bounds (text); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_COPY: - sel_start = MIN(text->selection_start, text->selection_end); - sel_end = MAX(text->selection_start, text->selection_end); - if (sel_start != sel_end) { - e_text_supply_selection (text, command->time, clipboard_atom, text->text + sel_start, sel_end - sel_start); - } - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_PASTE: - e_text_get_selection (text, clipboard_atom, command->time); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_GET_SELECTION: - e_text_get_selection (text, GDK_SELECTION_PRIMARY, command->time); - break; - case E_TEP_ACTIVATE: - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_SET_SELECT_BY_WORD: - text->select_by_word = command->value; - break; - case E_TEP_GRAB: - gnome_canvas_item_grab (GNOME_CANVAS_ITEM(text), - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, - text->i_cursor, - command->time); - break; - case E_TEP_UNGRAB: - gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM(text), command->time); - break; - case E_TEP_NOP: - break; - } - - if (!text->button_down) { - int x; - int i; - struct line *lines = text->lines; - for (lines = text->lines, i = 0; i < text->num_lines ; i++, lines ++) { - if (lines->text - text->text > text->selection_end) { - break; - } - } - lines --; - x = gdk_text_width(text->font, - lines->text, - text->selection_end - (lines->text - text->text)); - - - if (x < text->xofs_edit) { - text->xofs_edit = x; - } - - if (2 + x - text->clip_width > text->xofs_edit) { - text->xofs_edit = 2 + x - text->clip_width; - } - } - - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); -} - -static void _invisible_destroy (GtkInvisible *invisible, - EText *text) -{ - text->invisible = NULL; -} - -static GtkWidget *e_text_get_invisible(EText *text) -{ - GtkWidget *invisible; - if (text->invisible) { - invisible = text->invisible; - } else { - invisible = gtk_invisible_new(); - text->invisible = invisible; - - gtk_selection_add_target (invisible, - GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, - E_SELECTION_PRIMARY); - gtk_selection_add_target (invisible, - clipboard_atom, - GDK_SELECTION_TYPE_STRING, - E_SELECTION_CLIPBOARD); - - gtk_signal_connect (GTK_OBJECT(invisible), "selection_get", - GTK_SIGNAL_FUNC (_selection_get), - text); - gtk_signal_connect (GTK_OBJECT(invisible), "selection_clear_event", - GTK_SIGNAL_FUNC (_selection_clear_event), - text); - gtk_signal_connect (GTK_OBJECT(invisible), "selection_received", - GTK_SIGNAL_FUNC (_selection_received), - text); - - gtk_signal_connect (GTK_OBJECT(invisible), "destroy", - GTK_SIGNAL_FUNC (_invisible_destroy), - text); - } - return invisible; -} - -static void -_selection_clear_event (GtkInvisible *invisible, - GdkEventSelection *event, - EText *text) -{ - if (event->selection == GDK_SELECTION_PRIMARY) { - g_free (text->primary_selection); - text->primary_selection = NULL; - text->primary_length = 0; - - text->has_selection = FALSE; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); - - } else if (event->selection == clipboard_atom) { - g_free (text->clipboard_selection); - text->clipboard_selection = NULL; - text->clipboard_length = 0; - } -} - -static void -_selection_get (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EText *text) -{ - switch (info) { - case E_SELECTION_PRIMARY: - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, text->primary_selection, text->primary_length); - break; - case E_SELECTION_CLIPBOARD: - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, text->clipboard_selection, text->clipboard_length); - break; - } -} - -static void -_selection_received (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint time, - EText *text) -{ - if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { - return; - } else { - ETextEventProcessorCommand command; - command.action = E_TEP_INSERT; - command.position = E_TEP_SELECTION; - command.string = selection_data->data; - command.value = selection_data->length; - command.time = time; - e_text_command(text->tep, &command, text); - } -} - -static void e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length) -{ - gboolean successful; - GtkWidget *invisible; - - invisible = e_text_get_invisible(text); - - if (selection == GDK_SELECTION_PRIMARY ) { - if (text->primary_selection) { - g_free (text->primary_selection); - } - text->primary_selection = g_strndup(data, length); - text->primary_length = length; - } else if (selection == clipboard_atom) { - if (text->clipboard_selection) { - g_free (text->clipboard_selection); - } - text->clipboard_selection = g_strndup(data, length); - text->clipboard_length = length; - } - - successful = gtk_selection_owner_set (invisible, - selection, - time); - - if (selection == GDK_SELECTION_PRIMARY) - text->has_selection = successful; -} - -static void -e_text_get_selection(EText *text, GdkAtom selection, guint32 time) -{ - GtkWidget *invisible; - invisible = e_text_get_invisible(text); - gtk_selection_convert(invisible, - selection, - GDK_SELECTION_TYPE_STRING, - time); -} - -#if 0 -static void -e_text_real_copy_clipboard (EText *text) -{ - guint32 time; - gint selection_start_pos; - gint selection_end_pos; - - g_return_if_fail (text != NULL); - g_return_if_fail (E_IS_TEXT (text)); - - time = gtk_text_get_event_time (text); - selection_start_pos = MIN (text->selection_start, text->selection_end); - selection_end_pos = MAX (text->selection_start, text->selection_end); - - if (selection_start_pos != selection_end_pos) - { - if (gtk_selection_owner_set (GTK_WIDGET (text->canvas), - clipboard_atom, - time)) - text->clipboard_text = ""; - } -} - -static void -e_text_real_paste_clipboard (EText *text) -{ - guint32 time; - - g_return_if_fail (text != NULL); - g_return_if_fail (E_IS_TEXT (text)); - - time = e_text_get_event_time (text); - if (text->editable) - gtk_selection_convert (GTK_WIDGET(text->widget), - clipboard_atom, - gdk_atom_intern ("COMPOUND_TEXT", FALSE), time); -} -#endif - -/* Get the timestamp of the current event. Actually, the only thing - * we really care about below is the key event - */ -static guint32 -e_text_get_event_time (EText *text) -{ - GdkEvent *event; - guint32 tm = GDK_CURRENT_TIME; - - event = gtk_get_current_event(); - - if (event) - switch (event->type) - { - case GDK_MOTION_NOTIFY: - tm = event->motion.time; break; - case GDK_BUTTON_PRESS: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - tm = event->button.time; break; - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - tm = event->key.time; break; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - tm = event->crossing.time; break; - case GDK_PROPERTY_NOTIFY: - tm = event->property.time; break; - case GDK_SELECTION_CLEAR: - case GDK_SELECTION_REQUEST: - case GDK_SELECTION_NOTIFY: - tm = event->selection.time; break; - case GDK_PROXIMITY_IN: - case GDK_PROXIMITY_OUT: - tm = event->proximity.time; break; - default: /* use current time */ - break; - } - gdk_event_free(event); - - return tm; -} - - - -/* Routines for sucking fonts from the X server */ - -static ETextSuckFont * -e_suck_font (GdkFont *font) -{ - ETextSuckFont *suckfont; - int i; - int x, y; - char text[1]; - int lbearing, rbearing, ch_width, ascent, descent; - GdkPixmap *pixmap; - GdkColor black, white; - GdkImage *image; - GdkGC *gc; - guchar *line; - int width, height; - int black_pixel, pixel; - - if (!font) - return NULL; - - suckfont = g_new (ETextSuckFont, 1); - - height = font->ascent + font->descent; - x = 0; - for (i = 0; i < 256; i++) { - text[0] = i; - gdk_text_extents (font, text, 1, - &lbearing, &rbearing, &ch_width, &ascent, &descent); - suckfont->chars[i].left_sb = lbearing; - suckfont->chars[i].right_sb = ch_width - rbearing; - suckfont->chars[i].width = rbearing - lbearing; - suckfont->chars[i].ascent = ascent; - suckfont->chars[i].descent = descent; - suckfont->chars[i].bitmap_offset = x; - x += (ch_width + 31) & -32; - } - - width = x; - - suckfont->bitmap_width = width; - suckfont->bitmap_height = height; - suckfont->ascent = font->ascent; - - pixmap = gdk_pixmap_new (NULL, suckfont->bitmap_width, - suckfont->bitmap_height, 1); - gc = gdk_gc_new (pixmap); - gdk_gc_set_font (gc, font); - - black_pixel = BlackPixel (gdk_display, DefaultScreen (gdk_display)); - black.pixel = black_pixel; - white.pixel = WhitePixel (gdk_display, DefaultScreen (gdk_display)); - gdk_gc_set_foreground (gc, &white); - gdk_draw_rectangle (pixmap, gc, 1, 0, 0, width, height); - - gdk_gc_set_foreground (gc, &black); - for (i = 0; i < 256; i++) { - text[0] = i; - gdk_draw_text (pixmap, font, gc, - suckfont->chars[i].bitmap_offset - suckfont->chars[i].left_sb, - font->ascent, - text, 1); - } - - /* The handling of the image leaves me with distinct unease. But this - * is more or less copied out of gimp/app/text_tool.c, so it _ought_ to - * work. -RLL - */ - - image = gdk_image_get (pixmap, 0, 0, width, height); - suckfont->bitmap = g_malloc0 ((width >> 3) * height); - - line = suckfont->bitmap; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - pixel = gdk_image_get_pixel (image, x, y); - if (pixel == black_pixel) - line[x >> 3] |= 128 >> (x & 7); - } - line += width >> 3; - } - - gdk_image_destroy (image); - - /* free the pixmap */ - gdk_pixmap_unref (pixmap); - - /* free the gc */ - gdk_gc_destroy (gc); - - return suckfont; -} - -static void -e_suck_font_free (ETextSuckFont *suckfont) -{ - g_free (suckfont->bitmap); - g_free (suckfont); -} diff --git a/widgets/e-text.h b/widgets/e-text.h deleted file mode 100644 index ef8da442d6..0000000000 --- a/widgets/e-text.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* EText - Text item for evolution. - * Copyright (C) 2000 Helix Code, Inc. - * - * Author: Chris Lahey <clahey@umich.edu> - * - * A majority of code taken from: - * - * Text item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent - * canvas widget. Tk is copyrighted by the Regents of the University - * of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998 The Free Software Foundation - * - * Author: Federico Mena <federico@nuclecu.unam.mx> */ - -#ifndef E_TEXT_H -#define E_TEXT_H - -#include <gnome.h> -#include "e-text-event-processor.h" - - -BEGIN_GNOME_DECLS - - -/* Text item for the canvas. Text items are positioned by an anchor point and an anchor direction. - * - * A clipping rectangle may be specified for the text. The rectangle is anchored at the text's anchor - * point, and is specified by clipping width and height parameters. If the clipping rectangle is - * enabled, it will clip the text. - * - * In addition, x and y offset values may be specified. These specify an offset from the anchor - * position. If used in conjunction with the clipping rectangle, these could be used to implement - * simple scrolling of the text within the clipping rectangle. - * - * The following object arguments are available: - * - * name type read/write description - * ------------------------------------------------------------------------------------------ - * text string RW The string of the text label - * x double RW X coordinate of anchor point - * y double RW Y coordinate of anchor point - * font string W X logical font descriptor - * fontset string W X logical fontset descriptor - * font_gdk GdkFont* RW Pointer to a GdkFont - * anchor GtkAnchorType RW Anchor side for the text - * justification GtkJustification RW Justification for multiline text - * fill_color string W X color specification for text - * fill_color_gdk GdkColor* RW Pointer to an allocated GdkColor - * fill_stipple GdkBitmap* RW Stipple pattern for filling the text - * clip_width double RW Width of clip rectangle - * clip_height double RW Height of clip rectangle - * clip boolean RW Use clipping rectangle? - * x_offset double RW Horizontal offset distance from anchor position - * y_offset double RW Vertical offset distance from anchor position - * text_width double R Used to query the width of the rendered text - * text_height double R Used to query the rendered height of the text - * - * These are currently ignored in the AA version: - * editable boolean RW Can this item be edited - * use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false. - * ellipsis string RW The characters to use as ellipsis. NULL = "...". - * line_wrap boolean RW Line wrap when not editing. - * max_line_wrap int RW Number of lines possible when doing line wrap. - * - * These are not implemented yet: - * background boolean RW Draw a background rectangle. - * background_on_edit boolean RW Draw a background when editing. - */ - -#define E_TYPE_TEXT (e_text_get_type ()) -#define E_TEXT(obj) (GTK_CHECK_CAST ((obj), E_TYPE_TEXT, EText)) -#define E_TEXT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_TEXT, ETextClass)) -#define E_IS_TEXT(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_TEXT)) -#define E_IS_TEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_TEXT)) - - -typedef struct _EText EText; -typedef struct _ETextClass ETextClass; -typedef struct _ETextSuckFont ETextSuckFont; -typedef struct _ETextSuckChar ETextSuckChar; - -struct _ETextSuckChar { - int left_sb; - int right_sb; - int width; - int ascent; - int descent; - int bitmap_offset; /* in pixels */ -}; - -struct _ETextSuckFont { - guchar *bitmap; - gint bitmap_width; - gint bitmap_height; - gint ascent; - ETextSuckChar chars[256]; -}; - -struct _EText { - GnomeCanvasItem item; - - char *text; /* Text to display */ - gpointer lines; /* Text split into lines (private field) */ - int num_lines; /* Number of lines of text */ - - double x, y; /* Position at anchor */ - GdkFont *font; /* Font for text */ - GtkAnchorType anchor; /* Anchor side for text */ - GtkJustification justification; /* Justification for text */ - - double clip_width; /* Width of optional clip rectangle */ - double clip_height; /* Height of optional clip rectangle */ - - double xofs, yofs; /* Text offset distance from anchor position */ - - gulong pixel; /* Fill color */ - GdkBitmap *stipple; /* Stipple for text */ - GdkGC *gc; /* GC for drawing text */ - - int cx, cy; /* Top-left canvas coordinates for text */ - int clip_cx, clip_cy; /* Top-left canvas coordinates for clip rectangle */ - int clip_cwidth, clip_cheight; /* Size of clip rectangle in pixels */ - int max_width; /* Maximum width of text lines */ - int height; /* Rendered text height in pixels */ - - guint clip : 1; /* Use clip rectangle? */ - - /* Antialiased specific stuff follows */ - ETextSuckFont *suckfont; /* Sucked font */ - guint32 rgba; /* RGBA color for text */ - double affine[6]; /* The item -> canvas affine */ - - char *ellipsis; /* The ellipsis characters. NULL = "...". */ - double ellipsis_width; /* The width of the ellipsis. */ - gboolean use_ellipsis; /* Whether to use the ellipsis. */ - - gboolean editable; /* Item is editable */ - gboolean editing; /* Item is currently being edited */ - - int xofs_edit; /* Offset because of editing */ - - /* This needs to be reworked a bit once we get line wrapping. */ - int selection_start; /* Start of selection */ - int selection_end; /* End of selection */ - gboolean select_by_word; /* Current selection is by word */ - - /* This section is for drag scrolling and blinking cursor. */ - gint timeout_id; /* Current timeout id for scrolling */ - GTimer *timer; /* Timer for blinking cursor and scrolling */ - - gint lastx, lasty; /* Last x and y motion events */ - gint last_state; /* Last state */ - gulong scroll_start; /* Starting time for scroll (microseconds) */ - - gint show_cursor; /* Is cursor currently shown */ - gboolean button_down; /* Is mouse button 1 down */ - - ETextEventProcessor *tep; /* Text Event Processor */ - - GtkWidget *invisible; /* For selection handling */ - gboolean has_selection; /* TRUE if we have the selection */ - gchar *primary_selection; /* Primary selection text */ - gint primary_length; /* Primary selection text length */ - gchar *clipboard_selection; /* Clipboard selection text */ - gint clipboard_length; /* Clipboard selection text length*/ - - guint pointer_in : 1; /* Is the pointer currently over us? */ - guint default_cursor_shown : 1; /* Is the default cursor currently shown? */ - - guint line_wrap : 1; /* Do line wrap */ - - gint max_lines; /* Max number of lines (-1 = infinite) */ - - GdkCursor *default_cursor; /* Default cursor (arrow) */ - GdkCursor *i_cursor; /* I beam cursor */ -}; - -struct _ETextClass { - GnomeCanvasItemClass parent_class; - - void (* resize) (EText *text); - void (* change) (EText *text); -}; - - -/* Standard Gtk function */ -GtkType e_text_get_type (void); - - -END_GNOME_DECLS - -#endif diff --git a/widgets/e-text/e-text.c b/widgets/e-text/e-text.c index 2e3e7c158a..6647531eee 100644 --- a/widgets/e-text/e-text.c +++ b/widgets/e-text/e-text.c @@ -109,8 +109,6 @@ static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event); static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data); -static guint32 e_text_get_event_time (EText *text); - static void e_text_get_selection(EText *text, GdkAtom selection, guint32 time); static void e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length); @@ -1701,7 +1699,7 @@ static void _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) { if (xp || yp) { - struct line *lines; + struct line *lines = NULL; int x, y; int j; x = get_line_xpos (text, lines); @@ -1993,7 +1991,9 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_ENTER_NOTIFY: - text->tooltip_timeout = gtk_timeout_add (3000, _do_tooltip, text); + if ( text->tooltip_count == 0 ) + text->tooltip_timeout = gtk_timeout_add (1000, _do_tooltip, text); + text->tooltip_count ++; text->pointer_in = TRUE; if (text->editing) { if ( text->default_cursor_shown ) { @@ -2003,10 +2003,13 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_LEAVE_NOTIFY: - gtk_timeout_remove (text->tooltip_timeout); - if (text->tooltip_window) { - gtk_widget_destroy (text->tooltip_window); - text->tooltip_window = NULL; + text->tooltip_count --; + if ( text->tooltip_count == 0 ) { + gtk_timeout_remove (text->tooltip_timeout); + if (text->tooltip_window) { + gtk_widget_destroy (text->tooltip_window); + text->tooltip_window = NULL; + } } text->pointer_in = FALSE; @@ -2443,50 +2446,6 @@ e_text_real_paste_clipboard (EText *text) } #endif -/* Get the timestamp of the current event. Actually, the only thing - * we really care about below is the key event - */ -static guint32 -e_text_get_event_time (EText *text) -{ - GdkEvent *event; - guint32 tm = GDK_CURRENT_TIME; - - event = gtk_get_current_event(); - - if (event) - switch (event->type) - { - case GDK_MOTION_NOTIFY: - tm = event->motion.time; break; - case GDK_BUTTON_PRESS: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - tm = event->button.time; break; - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - tm = event->key.time; break; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - tm = event->crossing.time; break; - case GDK_PROPERTY_NOTIFY: - tm = event->property.time; break; - case GDK_SELECTION_CLEAR: - case GDK_SELECTION_REQUEST: - case GDK_SELECTION_NOTIFY: - tm = event->selection.time; break; - case GDK_PROXIMITY_IN: - case GDK_PROXIMITY_OUT: - tm = event->proximity.time; break; - default: /* use current time */ - break; - } - gdk_event_free(event); - - return tm; -} - /* Routines for sucking fonts from the X server */ diff --git a/widgets/e-text/e-text.h b/widgets/e-text/e-text.h index c44589d3ae..2f29fb189b 100644 --- a/widgets/e-text/e-text.h +++ b/widgets/e-text/e-text.h @@ -176,6 +176,7 @@ struct _EText { gint tooltip_timeout; /* Timeout for the tooltip */ GtkWidget *tooltip_window; /* GtkWindow for displaying the tooltip */ + gint tooltip_count; /* GDK_ENTER_NOTIFY count. */ }; struct _ETextClass { diff --git a/widgets/misc/e-canvas-utils.h b/widgets/misc/e-canvas-utils.h index 13ec43117c..9580f64f96 100644 --- a/widgets/misc/e-canvas-utils.h +++ b/widgets/misc/e-canvas-utils.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * e-canvas-utils.c + * e-canvas-utils.h * Copyright (C) 2000 Helix Code, Inc. * Author: Chris Lahey <clahey@helixcode.com> * @@ -20,5 +20,10 @@ * Boston, MA 02111-1307, USA. */ +#ifndef __E_CANVAS_UTILS__ +#define __E_CANVAS_UTILS__ + #include <gnome.h> void e_canvas_item_move_absolute (GnomeCanvasItem *item, double dx, double dy); + +#endif /* __E_CANVAS_UTILS__ */ diff --git a/widgets/misc/e-reflow.c b/widgets/misc/e-reflow.c index c1022f8f78..984e972f0c 100644 --- a/widgets/misc/e-reflow.c +++ b/widgets/misc/e-reflow.c @@ -24,6 +24,7 @@ #include <math.h> #include "e-reflow.h" #include "e-canvas-utils.h" +#include "e-util.h" static void e_reflow_init (EReflow *card); static void e_reflow_class_init (EReflowClass *klass); static void e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -278,7 +279,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) GList *list; for (list = e_reflow->items; list; list = list->next) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (list->data); - gboolean has_focus; + EFocus has_focus; gtk_object_get(GTK_OBJECT(item), "has_focus", &has_focus, NULL); @@ -290,7 +291,7 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event) if (list) { item = GNOME_CANVAS_ITEM(list->data); gnome_canvas_item_set(item, - "has_focus", TRUE, + "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, NULL); return 1; } else { @@ -625,7 +626,6 @@ e_reflow_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { - EReflow *e_reflow = E_REFLOW(item); double distance = 1; if (GNOME_CANVAS_ITEM_CLASS(parent_class)->point) diff --git a/widgets/table/check-empty.xpm b/widgets/table/check-empty.xpm index 2dd873e137..746b20234e 100644 --- a/widgets/table/check-empty.xpm +++ b/widgets/table/check-empty.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_empty_xpm[] = { +static const char * check_empty_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/table/check-filled.xpm b/widgets/table/check-filled.xpm index 689d7a7967..c0468fc25b 100644 --- a/widgets/table/check-filled.xpm +++ b/widgets/table/check-filled.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_filled_xpm[] = { +static const char * check_filled_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index 8131d16384..fb33f10537 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -120,7 +120,6 @@ typedef struct { } ECellTextView; typedef struct _CurrentCell{ - ECellTextView *text_view; int width; gchar *text; @@ -233,6 +232,10 @@ static void ect_stop_editing (ECellTextView *text_view) { CellEdit *edit = text_view->edit; + int row, view_col; + + row = edit->cell.row; + view_col = edit->cell.view_col; g_free (edit->old_text); edit->old_text = NULL; @@ -246,12 +249,24 @@ ect_stop_editing (ECellTextView *text_view) g_free(edit->primary_selection); if (edit->clipboard_selection) g_free(edit->clipboard_selection); + if ( ! edit->default_cursor_shown ) { + gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); + edit->default_cursor_shown = TRUE; + } + if (edit->timeout_id) { + g_source_remove(edit->timeout_id); + edit->timeout_id = 0; + } + if (edit->timer) { + g_timer_stop(edit->timer); + g_timer_destroy(edit->timer); + edit->timer = NULL; + } g_free (edit); text_view->edit = NULL; - - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); + ect_queue_redraw (text_view, view_col, row); } /* @@ -260,7 +275,6 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->cell.view_col, text_view->edit->cell.row); ect_stop_editing (text_view); } @@ -379,9 +393,11 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (edit){ - if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) + if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) { edit_display = TRUE; - fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + } else + fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } else { fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } @@ -776,6 +792,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, break; case GDK_BUTTON_PRESS: /* Fall Through */ case GDK_BUTTON_RELEASE: + event->button.x -= 4; + event->button.y -= 1; if ((!edit_display) && ect->editable && event->type == GDK_BUTTON_RELEASE @@ -828,6 +846,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, } break; case GDK_MOTION_NOTIFY: + event->motion.x -= 4; + event->motion.y -= 1; if (edit_display) { GdkEventMotion motion = event->motion; e_tep_event.motion.time = motion.time; @@ -928,15 +948,6 @@ ect_height (ECellView *ecell_view, int model_col, int view_col, int row) } /* - * Callback: invoked when the user pressed "enter" on the GtkEntry - */ -static void -ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) -{ - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); -} - -/* * ECellView::enter_edit method */ static void * @@ -1011,19 +1022,6 @@ ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, voi CellEdit *edit = text_view->edit; if (edit){ - if ( ! edit->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); - edit->default_cursor_shown = TRUE; - } - if (edit->timeout_id) { - g_source_remove(edit->timeout_id); - edit->timeout_id = 0; - } - if (edit->timer) { - g_timer_stop(edit->timer); - g_timer_destroy(edit->timer); - edit->timer = NULL; - } ect_accept_edits (text_view); ect_stop_editing (text_view); } else { @@ -1508,9 +1506,6 @@ e_cell_text_view_command(ETextEventProcessor *tep, ETextEventProcessorCommand *c break; case E_TEP_ACTIVATE: e_table_item_leave_edit (text_view->cell_view.e_table_item_view); - if (edit->timer) { - g_timer_reset(edit->timer); - } break; case E_TEP_SET_SELECT_BY_WORD: edit->select_by_word = command->value; @@ -1842,7 +1837,9 @@ calc_line_widths (CurrentCell *cell) } if (ect->use_ellipsis && - ! text_view->edit && + (!(text_view->edit && + cell->row == text_view->edit->cell.row && + cell->view_col == text_view->edit->cell.view_col)) && lines->width > cell->width) { if (font) { lines->ellipsis_length = 0; diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c index f1345e8c6b..1d87019007 100644 --- a/widgets/table/e-cell.c +++ b/widgets/table/e-cell.c @@ -129,7 +129,7 @@ e_cell_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view } void -e_cell_view_realize (ECellView *ecell_view) +e_cell_realize (ECellView *ecell_view) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->realize (ecell_view); } diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index 3c258689e4..b21653d6d1 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include <gdk/gdktypes.h> +#include <libgnomeprint/gnome-print.h> #include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) @@ -62,6 +63,9 @@ void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2); +void e_cell_print (ECellView *ecell_view, GnomePrintContext *context, + int model_col, int view_col, int row, + double width, double height); void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); diff --git a/widgets/table/e-table-group-container.c b/widgets/table/e-table-group-container.c new file mode 100644 index 0000000000..a9f494db04 --- /dev/null +++ b/widgets/table/e-table-group-container.c @@ -0,0 +1,804 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-container.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" +#include "e-util/e-canvas-utils.h" +#include "widgets/e-text/e-text.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define BUTTON_HEIGHT 10 +#define BUTTON_PADDING 2 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgc_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static int etgc_event (GnomeCanvasItem *item, GdkEvent *event); +static void etgc_realize (GnomeCanvasItem *item); +static void etgc_unrealize (GnomeCanvasItem *item); + +static void etgc_add (ETableGroup *etg, gint row); +static gboolean etgc_remove (ETableGroup *etg, gint row); +static void etgc_increment (ETableGroup *etg, gint position, gint amount); +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col); + +static void etgc_child_resize (GtkObject *object, gpointer data); + +static void etgc_queue_reposition (ETableGroupContainer *etgc); + +typedef struct { + ETableGroup *child; + void *key; + GnomeCanvasItem *text; + GnomeCanvasItem *rect; + gint count; +} ETableGroupContainerChildNode; + +static void +etgc_destroy (GtkObject *object) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (object); + + gdk_font_unref(etgc->font); + + GTK_OBJECT_CLASS (etgc_parent_class)->destroy (object); +} +#if 0 +void +e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etg != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etg->children = g_list_append (etg->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etg->transparent ? 0 : TITLE_HEIGHT; + int x = etg->transparent ? 0 : GROUP_INDENT; + + for (l = etg->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etg_relayout), etg); + } + } +} + +static void +etg_realize (GnomeCanvasItem *item) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); + + if (!etg->transparent){ + int current_width, current_height; + + etg_dim (etg, ¤t_width, ¤t_height); + + if ((current_height != etg->height) || (current_width != etg->width)){ + etg->width = current_width; + etg->height = current_height; + + gnome_canvas_item_set ( + etg->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etg->width, + "y2", (double) etg->height, + NULL); + } + } +} +#endif + +void +e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model); + etgc->ecol = ecol; + etgc->child_rules = child_rules; + + etgc->font = gdk_font_load ("lucidasans-10"); +#if 0 + etgc->open = open; + etgc->transparent = transparent; + + etgc_dim (etgc, &etgc->width, &etgc->height); + + if (!etgc->transparent) + etgc->rect = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (etgc), + gnome_canvas_rect_get_type (), + "fill_color", "gray", + "outline_color", "gray20", + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); +#endif + +#if 0 + /* + * Reparent the child into our space. + */ + gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etgc)); + + gnome_canvas_item_set ( + child, + "x", (double) GROUP_INDENT, + "y", (double) TITLE_HEIGHT, + NULL); + + /* + * Force dimension computation + */ + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update ( + GNOME_CANVAS_ITEM (etgc), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); +#endif +} + +ETableGroup * +e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + ETableGroupContainer *etgc; + + g_return_val_if_fail (parent != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); + + etgc = gtk_type_new (e_table_group_container_get_type ()); + + e_table_group_container_construct (parent, etgc, full_header, header, + model, ecol, child_rules); + return E_TABLE_GROUP (etgc); +} + +#if 0 +static void +etgc_relayout (GnomeCanvasItem *eti, ETableGroupContainer *etgc) +{ + GList *l; + int height = etgc->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + if (child == eti) + move = TRUE; + + if (move){ + printf ("Moving item %p\n", child); + gnome_canvas_item_set ( child, + "y", (double) height, + NULL); + } + } + if (height != etgc->height){ + etgc->height = height; + gtk_signal_emit (GTK_OBJECT (etgc), etgc_signals [RESIZE]); + } +} + +void +e_table_group_container_add (ETableGroupContainer *etgc, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etgc != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etgc)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etgc->children = g_list_append (etgc->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etgc)->klass)->bounds (etgc, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etgc)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etgc->transparent ? 0 : TITLE_HEIGHT; + int x = etgc->transparent ? 0 : GROUP_INDENT; + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etgc_relayout), etgc); + } + } +} + +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->realize (item); + + for (l = etgc->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etgc_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update (item, affine, clip_path, flags); + + if ( etgc->need_resize ) { + + if (!etgc->transparent){ + int current_width, current_height; + + etgc_dim (etgc, ¤t_width, ¤t_height); + + if ((current_height != etgc->height) || (current_width != etgc->width)){ + etgc->width = current_width; + etgc->height = current_height; + + gnome_canvas_item_set ( + etgc->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); + } + } + etgc->need_resize = FALSE; + } +} +#endif + +static int +etgc_event (GnomeCanvasItem *item, GdkEvent *event) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(item); + gboolean return_val = TRUE; + gboolean change_focus = FALSE; + gboolean use_col = FALSE; + gint start_col = 0; + gint old_col; + EFocus direction = E_FOCUS_START; + + switch (event->type) { + case GDK_KEY_PRESS: + if (event->key.keyval == GDK_Tab || + event->key.keyval == GDK_KP_Tab || + event->key.keyval == GDK_ISO_Left_Tab) { + change_focus = TRUE; + use_col = TRUE; + start_col = (event->key.state & GDK_SHIFT_MASK) ? -1 : 0; + direction = (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START; + } else if (event->key.keyval == GDK_Left || + event->key.keyval == GDK_KP_Left) { + change_focus = TRUE; + use_col = TRUE; + start_col = -1; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Right || + event->key.keyval == GDK_KP_Right) { + change_focus = TRUE; + use_col = TRUE; + start_col = 0; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Down || + event->key.keyval == GDK_KP_Down) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Up || + event->key.keyval == GDK_KP_Up) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Return || + event->key.keyval == GDK_KP_Enter) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } + if ( change_focus ) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + old_col = e_table_group_get_focus_column(child); + + if (direction == E_FOCUS_END) + list = list->prev; + else + list = list->next; + + if (list) { + child_node = (ETableGroupContainerChildNode *)list->data; + child = child_node->child; + if (use_col) + e_table_group_set_focus(child, direction, start_col); + else { + e_table_group_set_focus(child, direction, old_col); + } + return 1; + } else { + return 0; + } + } + } + } + return_val = FALSE; + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event(item, event); + } + return return_val; + +} + +/* Realize handler for the text item */ +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) (item); + + etgc = E_TABLE_GROUP_CONTAINER (item); +} + +/* Unrealize handler for the etgc item */ +static void +etgc_unrealize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + etgc = E_TABLE_GROUP_CONTAINER (item); + + etgc->font = NULL; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) (item); +} + +static void +compute_text (ETableGroupContainer *etgc, ETableGroupContainerChildNode *child_node) +{ + /* FIXME : What a hack, eh? */ + gchar *text = g_strdup_printf("%s : %s (%d items)", etgc->ecol->text, (gchar *)child_node->key, (gint) child_node->count); + gnome_canvas_item_set(child_node->text, + "text", text, + NULL); + g_free(text); +} + +static void etgc_add (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + void *val = e_table_model_value_at (etg->model, etgc->ecol->col_idx, row); + GCompareFunc comp = etgc->ecol->compare; + GList *list = etgc->children; + ETableGroup *child; + ETableGroupContainerChildNode *child_node; + for ( ; list; list = g_list_next(list) ) { + child_node = (ETableGroupContainerChildNode *)(list->data); + if ( (*comp)(child_node->key, val) ) { + child = child_node->child; + child_node->count ++; + e_table_group_add(child, row); + compute_text(etgc, child_node); + return; + } + } + child_node = g_new(ETableGroupContainerChildNode, 1); + child_node->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + gnome_canvas_rect_get_type (), + "fill_color", "grey70", + "outline_color", "grey50", + NULL); + child_node->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + e_text_get_type(), + "font_gdk", etgc->font, + "anchor", GTK_ANCHOR_SW, + "x", (double) 0, + "y", (double) 0, + "fill_color", "black", + NULL); + child = e_table_group_new(GNOME_CANVAS_GROUP(etgc), etg->full_header, etg->header, etg->model, etgc->child_rules); + child_node->child = child; + child_node->key = val; + + gtk_signal_connect(GTK_OBJECT(child), "resize", + etgc_child_resize, etgc); + child_node->count = 1; + e_table_group_add(child, row); + etgc->children = g_list_append(etgc->children, child_node); + compute_text(etgc, child_node); + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gboolean etgc_remove (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + if ( e_table_group_remove(child, row) ) { + child_node->count --; + if ( child_node->count == 0 ) { + gtk_object_unref(GTK_OBJECT(child_node->text)); + gtk_object_unref(GTK_OBJECT(child)); + etgc->children = g_list_remove(etgc->children, child_node); + g_free(child_node); + } else { + compute_text(etgc, child_node); + } + return TRUE; + } + } + return FALSE; + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + e_table_group_increment(((ETableGroupContainerChildNode *)list->data)->child, position, amount); + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + if (direction == E_FOCUS_END) { + e_table_group_set_focus(((ETableGroupContainerChildNode *)g_list_last(etgc->children)->data)->child, direction, view_col); + } else { + e_table_group_set_focus(((ETableGroupContainerChildNode *)etgc->children->data)->child, direction, view_col); + } + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gint +etgc_get_focus_column (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + return e_table_group_get_focus_column(child); + } + } + } + return 0; +} + +static void etgc_thaw (ETableGroup *etg) +{ + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void +etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etgc_thaw(etg); + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void etgc_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + GList *list = etgc->children; + etgc->width = width; + + for ( ; list; list = g_list_next(list) ) { + gdouble child_width = width - GROUP_INDENT; + gtk_object_set(GTK_OBJECT(((ETableGroupContainerChildNode *)list->data)->child), + "width", child_width, + NULL); + } + + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gdouble etgc_get_width (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->width; +} + +static gdouble etgc_get_height (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->height; +} + +static void +etgc_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgc_destroy; + object_class->set_arg = etgc_set_arg; + object_class->get_arg = etgc_get_arg; + + item_class->event = etgc_event; + item_class->realize = etgc_realize; + item_class->unrealize = etgc_unrealize; + + etgc_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgc_add; + e_group_class->remove = etgc_remove; + e_group_class->increment = etgc_increment; + e_group_class->set_focus = etgc_set_focus; + e_group_class->get_focus_column = etgc_get_focus_column; + e_group_class->thaw = etgc_thaw; + + e_group_class->get_width = etgc_get_width; + e_group_class->set_width = etgc_set_width; + e_group_class->get_height = etgc_get_height; + + gtk_object_add_arg_type ("ETableGroupContainer::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupContainer::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupContainer::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgc_init (GtkObject *object) +{ + ETableGroupContainer *container = E_TABLE_GROUP_CONTAINER(object); + container->children = FALSE; +} + +static gboolean +etgc_update_positioning (ETableGroupContainer *etgc, gpointer data) +{ + gboolean frozen; + gtk_object_get(GTK_OBJECT(etgc), + "frozen", &frozen, + NULL); + if ( frozen ) { + etgc->idle = 0; + return FALSE; + } + if ( GTK_OBJECT_FLAGS( etgc ) & GNOME_CANVAS_ITEM_REALIZED ) { + gdouble old_height; + + old_height = etgc->height; + if ( etgc->children == NULL ) { + } else { + GList *list; + gdouble extra_height; + gdouble running_height; + gdouble item_height = 0; + + extra_height = 0; + if (etgc->font) + extra_height += etgc->font->ascent + etgc->font->descent + BUTTON_PADDING * 2; + + extra_height = MAX(extra_height, BUTTON_HEIGHT + BUTTON_PADDING * 2); + + running_height = extra_height; + + list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + gtk_object_get( GTK_OBJECT(child), + "height", &item_height, + NULL ); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child_node->text), + GROUP_INDENT, + running_height - BUTTON_PADDING); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child), + GROUP_INDENT, + running_height); + + gnome_canvas_item_set(GNOME_CANVAS_ITEM(child_node->rect), + "x1", (double) 0, + "x2", (double) etgc->width, + "y1", (double) running_height - extra_height, + "y2", (double) running_height + item_height, + NULL); + + running_height += item_height + extra_height; + } + running_height -= extra_height; + if ( running_height != old_height) { + etgc->height = running_height; + gtk_signal_emit_by_name (GTK_OBJECT (etgc), "resize"); + } + } + } + etgc->idle = 0; + return FALSE; +} + +static void +etgc_queue_reposition (ETableGroupContainer *etgc) +{ + if (etgc->idle == 0) + etgc->idle = g_idle_add((GSourceFunc)etgc_update_positioning, etgc); +} + +static void +etgc_child_resize (GtkObject *object, gpointer data) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(data); + etgc_queue_reposition (etgc); +} + +E_MAKE_TYPE (e_table_group_container, "ETableGroupContainer", ETableGroupContainer, etgc_class_init, etgc_init, PARENT_TYPE); + diff --git a/widgets/table/e-table-group-container.h b/widgets/table/e-table-group-container.h new file mode 100644 index 0000000000..4942f9e695 --- /dev/null +++ b/widgets/table/e-table-group-container.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_CONTAINER_H_ +#define _E_TABLE_GROUP_CONTAINER_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-model.h" +#include "e-table-header.h" +#include "e-table-group.h" + +#define E_TABLE_GROUP_CONTAINER_TYPE (e_table_group_container_get_type ()) +#define E_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainer)) +#define E_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainerClass)) +#define E_IS_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_CONTAINER_TYPE)) +#define E_IS_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_CONTAINER_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * The ETableCol used to group this set + */ + ETableCol *ecol; + + /* + * List of ETableGroups we stack + */ + GList *children; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + GdkFont *font; + + gdouble width, height; + + void *child_rules; + + gint idle; + + /* + * Update booleans: + */ + guint need_resize : 1; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; +} ETableGroupContainer; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupContainerClass; + +ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); +void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); + +GtkType e_table_group_container_get_type (void); + +#endif /* _E_TABLE_GROUP_CONTAINER_H_ */ diff --git a/widgets/table/e-table-group-leaf.c b/widgets/table/e-table-group-leaf.c new file mode 100644 index 0000000000..ba73ad9886 --- /dev/null +++ b/widgets/table/e-table-group-leaf.c @@ -0,0 +1,288 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-leaf.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgl_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static void +etgl_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object); +} + +static void +e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model); + etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_subset_variable_new(model)); +} + +ETableGroup * +e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + ETableGroupLeaf *etgl; + + g_return_val_if_fail (parent != NULL, NULL); + + etgl = gtk_type_new (e_table_group_leaf_get_type ()); + + e_table_group_leaf_construct (parent, etgl, full_header, + header, model); + return E_TABLE_GROUP (etgl); +} + +static void +etgl_resize (GtkObject *object, gpointer data) +{ + e_table_group_resize (E_TABLE_GROUP(data)); +} + +static void +etgl_realize (GnomeCanvasItem *item) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF(item); + gdouble height; + + if ( GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize ) + GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize (item); + + etgl->item = E_TABLE_ITEM(gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgl), + e_table_item_get_type (), + "ETableHeader", E_TABLE_GROUP(etgl)->header, + "ETableModel", etgl->subset, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + "width", etgl->width, + NULL)); + gtk_signal_connect(GTK_OBJECT(etgl->item), + "resize", etgl_resize, etgl); + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + if ( height != 1 ) + e_table_group_resize(E_TABLE_GROUP(etgl)); +} + +static int +etgl_event (GnomeCanvasItem *item, GdkEvent *event) +{ + gboolean return_val = TRUE; + + switch (event->type) { + + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event(item, event); + } + return return_val; + +} + +static void +etgl_add (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_add(etgl->subset, row); +} + +static gboolean +etgl_remove (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_subset_variable_remove(etgl->subset, row); +} + +static void +etgl_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_increment(etgl->subset, position, amount); +} + +static void +etgl_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + if (direction == E_FOCUS_END) { + e_table_item_focus(etgl->item, view_col, e_table_model_row_count(E_TABLE_MODEL(etgl->subset)) - 1); + } else { + e_table_item_focus(etgl->item, view_col, 0); + } +} + +static gint +etgl_get_focus_column (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_item_get_focused_column(etgl->item); +} + +static void +etgl_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + etgl->width = width; +#if 0 + if ( etgl->item ) { + gnome_canvas_item_set(GNOME_CANVAS_ITEM(etgl->item), + "width", width, + NULL); + } +#endif +} + +static gdouble +etgl_get_width (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gtk_object_get(GTK_OBJECT(etgl->item), + "width", &etgl->width, + NULL); + return etgl->width; +} + +static gdouble +etgl_get_height (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gdouble height; + if ( etgl->item ) + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + else + height = 1; + return height; +} + +static void +etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +etgl_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgl_destroy; + object_class->set_arg = etgl_set_arg; + object_class->get_arg = etgl_get_arg; + + item_class->realize = etgl_realize; + item_class->event = etgl_event; + + etgl_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgl_add; + e_group_class->remove = etgl_remove; + e_group_class->increment = etgl_increment; + e_group_class->set_focus = etgl_set_focus; + e_group_class->get_focus_column = etgl_get_focus_column; + + e_group_class->get_width = etgl_get_width; + e_group_class->set_width = etgl_set_width; + e_group_class->get_height = etgl_get_height; + + gtk_object_add_arg_type ("ETableGroupLeaf::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupLeaf::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupLeaf::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgl_init (GtkObject *object) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object); + + etgl->width = 1; + etgl->subset = NULL; + etgl->item = NULL; +} + +E_MAKE_TYPE (e_table_group_leaf, "ETableGroupLeaf", ETableGroupLeaf, etgl_class_init, etgl_init, PARENT_TYPE); diff --git a/widgets/table/e-table-group-leaf.h b/widgets/table/e-table-group-leaf.h new file mode 100644 index 0000000000..372bf4cc70 --- /dev/null +++ b/widgets/table/e-table-group-leaf.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_LEAF_H_ +#define _E_TABLE_GROUP_LEAF_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-group.h" +#include "e-table-subset-variable.h" +#include "e-table-item.h" + +#define E_TABLE_GROUP_LEAF_TYPE (e_table_group_leaf_get_type ()) +#define E_TABLE_GROUP_LEAF(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeaf)) +#define E_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeafClass)) +#define E_IS_TABLE_GROUP_LEAF(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_LEAF_TYPE)) +#define E_IS_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_LEAF_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * Item. + */ + ETableItem *item; + + gdouble width; + + ETableSubsetVariable *subset; +} ETableGroupLeaf; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupLeafClass; + +ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); +GtkType e_table_group_leaf_get_type (void); + +#endif /* _E_TABLE_GROUP_LEAF_H_ */ diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c index 5652d2623f..68bc3e7abf 100644 --- a/widgets/table/e-table-group.c +++ b/widgets/table/e-table-group.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-Table-Group.c: Implements the grouping objects for elements on a table * @@ -10,8 +11,11 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-group-container.h" +#include "e-table-group-leaf.h" #include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" #define TITLE_HEIGHT 16 @@ -19,88 +23,30 @@ #define PARENT_TYPE gnome_canvas_group_get_type () +#define ETG_CLASS(e) (E_TABLE_GROUP_CLASS(GTK_OBJECT(e)->klass)) + static GnomeCanvasGroupClass *etg_parent_class; enum { - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; static gint etg_signals [LAST_SIGNAL] = { 0, }; -static void -etg_destroy (GtkObject *object) -{ - ETableGroup *etg = E_TABLE_GROUP (object); - - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); -} - -static void -etg_dim (ETableGroup *etg, int *width, int *height) -{ - GSList *l; - - *width = *height = 0; - - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; - - *height += child->y2 - child->y1; - *width += child->x2 - child->x1; - } - - if (!etg->transparent){ - *height += TITLE_HEIGHT; - *width += GROUP_INDENT; - } -} +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; -void -e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, - gboolean transparent) -{ - gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - - etg->ecol = ecol; - etg->open = open; - etg->transparent = transparent; - - etg_dim (etg, &etg->width, &etg->height); - - if (!etg->transparent) - etg->rect = gnome_canvas_item_new ( - GNOME_CANVAS_GROUP (etg), - gnome_canvas_rect_get_type (), - "fill_color", "gray", - "outline_color", "gray20", - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); +static void etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static gboolean etg_get_focus (ETableGroup *etg); #if 0 - /* - * Reparent the child into our space. - */ - gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etg)); - - gnome_canvas_item_set ( - child, - "x", (double) GROUP_INDENT, - "y", (double) TITLE_HEIGHT, - NULL); - - /* - * Force dimension computation - */ - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update ( - GNOME_CANVAS_ITEM (etg), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); -#endif -} - GnomeCanvasItem * e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, gboolean open, gboolean transparent) @@ -116,158 +62,275 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, return GNOME_CANVAS_ITEM (etg); } +#endif -static void -etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +ETableGroup * +e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules) { - GSList *l; - int height = etg->transparent ? 0 : GROUP_INDENT; - gboolean move = FALSE; + g_return_val_if_fail (model != NULL, NULL); - printf ("Relaying out\n"); - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; + if(rules && !xmlStrcmp(rules->name, "group")) { + gint col_idx = atoi(xmlGetProp(rules, "column")); + ETableCol *col; + if ( col_idx > e_table_header_count(full_header) ) + return e_table_group_leaf_new(parent, full_header, header, model); + col = e_table_header_get_columns(full_header)[col_idx]; + return e_table_group_container_new(parent, full_header, header, model, col, rules->childs); + } else { + return e_table_group_leaf_new(parent, full_header, header, model); + } + return NULL; +} + +void +e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); + etg->full_header = full_header; + etg->header = header; + etg->model = model; +} + +void +e_table_group_add (ETableGroup *etg, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); - height += child->y2 - child->y1; + if ( ETG_CLASS (etg)->add ) + ETG_CLASS (etg)->add (etg, row); +} - if (child == eti) - move = TRUE; +gboolean +e_table_group_remove (ETableGroup *etg, + gint row) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); - if (move){ - printf ("Moving item %p\n", child); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); - } - } - if (height != etg->height){ - etg->height = height; - gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); - } + if ( ETG_CLASS (etg)->remove ) + return ETG_CLASS (etg)->remove (etg, row); + else + return FALSE; +} + +gint +e_table_group_get_count (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), 0); + + if ( ETG_CLASS (etg)->get_count ) + return ETG_CLASS (etg)->get_count (etg); + else + return 0; } void -e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +e_table_group_increment (ETableGroup *etg, + gint position, + gint amount) { - double x1, y1, x2, y2; - g_return_if_fail (etg != NULL); - g_return_if_fail (item != NULL); g_return_if_fail (E_IS_TABLE_GROUP (etg)); - g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); - - etg->children = g_slist_append (etg->children, item); - - GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); - - if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ - GSList *l; - int height = etg->transparent ? 0 : TITLE_HEIGHT; - int x = etg->transparent ? 0 : GROUP_INDENT; - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; - - height += child->y2 - child->y1; - - printf ("Height\n"); - if (E_IS_TABLE_ITEM (item)){ - printf (" Item: "); - } else { - printf (" Group: "); - } - printf ("%d\n", child->y2-child->y1); - } - gnome_canvas_item_set ( - item, - "y", (double) height, - "x", (double) x, - NULL); - - - if (E_IS_TABLE_ITEM (item)){ - - printf ("Table item! ---------\n"); - gtk_signal_connect (GTK_OBJECT (item), "height_changed", - GTK_SIGNAL_FUNC (etg_relayout), etg); - } - } + if ( ETG_CLASS (etg)->increment ) + ETG_CLASS (etg)->increment (etg, position, amount); } -static void -etg_realize (GnomeCanvasItem *item) +void +e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->set_focus ) + ETG_CLASS (etg)->set_focus (etg, direction, row); +} + +gboolean +e_table_group_get_focus (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus ) + return ETG_CLASS (etg)->get_focus (etg); + else + return FALSE; +} + +gboolean +e_table_group_get_focus_column (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus_column ) + return ETG_CLASS (etg)->get_focus_column (etg); + else + return FALSE; +} + +ETableCol * +e_table_group_get_ecol (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), NULL); + + if ( ETG_CLASS (etg)->get_ecol ) + return ETG_CLASS (etg)->get_ecol (etg); + else + return NULL; +} + +void +e_table_group_resize (ETableGroup *e_table_group) +{ + g_return_if_fail (e_table_group != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (e_table_group)); + + gtk_signal_emit (GTK_OBJECT (e_table_group), + etg_signals [RESIZE]); +} + +static int +etg_event (GnomeCanvasItem *item, GdkEvent *event) { ETableGroup *etg = E_TABLE_GROUP (item); - GSList *l; - int height = 0; - - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + gboolean return_val = TRUE; - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; + switch (event->type) { - printf ("During realization for child %p -> %d\n", child, height); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); + case GDK_FOCUS_CHANGE: + etg->has_focus = event->focus_change.in; + return_val = FALSE; - height += child->y2 - child->y1; + default: + return_val = FALSE; } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event(item, event); + } + return return_val; + } static void -etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +etg_thaw(ETableGroup *etg) { - ETableGroup *etg = E_TABLE_GROUP (item); + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->thaw ) + ETG_CLASS (etg)->thaw (etg); +} + +static void +etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); - - if (!etg->transparent){ - int current_width, current_height; - - etg_dim (etg, ¤t_width, ¤t_height); - - if ((current_height != etg->height) || (current_width != etg->width)){ - etg->width = current_width; - etg->height = current_height; - - gnome_canvas_item_set ( - etg->rect, - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etg_thaw(etg); } + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->set_width ) + ETG_CLASS(etg)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; } } static void +etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( ETG_CLASS(etg)->get_height ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->get_width ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean +etg_get_focus (ETableGroup *etg) +{ + return etg->has_focus; +} + +static void etg_class_init (GtkObjectClass *object_class) { GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *klass = (ETableGroupClass *) object_class; + + object_class->set_arg = etg_set_arg; + object_class->get_arg = etg_get_arg; - object_class->destroy = etg_destroy; + item_class->event = etg_event; - item_class->realize = etg_realize; - item_class->update = etg_update; + klass->resize = NULL; + + klass->add = NULL; + klass->remove = NULL; + klass->get_count = NULL; + klass->increment = NULL; + klass->set_focus = NULL; + klass->get_focus = etg_get_focus; + klass->get_ecol = NULL; + + klass->thaw = NULL; + klass->get_height = NULL; + klass->get_width = NULL; + klass->set_width = NULL; etg_parent_class = gtk_type_class (PARENT_TYPE); - etg_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + etg_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + GTK_SIGNAL_OFFSET (ETableGroupClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, etg_signals, LAST_SIGNAL); - } E_MAKE_TYPE (e_table_group, "ETableGroup", ETableGroup, etg_class_init, NULL, PARENT_TYPE); diff --git a/widgets/table/e-table-group.h b/widgets/table/e-table-group.h index 468d5dd794..1b3f346290 100644 --- a/widgets/table/e-table-group.h +++ b/widgets/table/e-table-group.h @@ -1,9 +1,12 @@ -#ifndef _E_TABLE_TREE_H_ -#define _E_TABLE_TREE_H_ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_H_ +#define _E_TABLE_GROUP_H_ #include <libgnomeui/gnome-canvas.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-util/e-util.h" #define E_TABLE_GROUP_TYPE (e_table_group_get_type ()) #define E_TABLE_GROUP(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_TYPE, ETableGroup)) @@ -15,49 +18,75 @@ typedef struct { GnomeCanvasGroup group; /* - * The ETableCol used to group this set + * The full header. */ - ETableCol *ecol; - - /* - * The canvas rectangle that contains the children - */ - GnomeCanvasItem *rect; - - /* - * Dimensions of the ETableGroup - */ - int width, height; - + ETableHeader *full_header; + ETableHeader *header; + /* - * State: the ETableGroup is open or closed + * The model we pull data from. */ - guint open:1; + ETableModel *model; /* * Whether we should add indentation and open/close markers, * or if we just act as containers of subtables. */ - guint transparent:1; + guint transparent : 1; - /* - * List of GnomeCanvasItems we stack - */ - GSList *children; + guint has_focus : 1; + + guint frozen : 1; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; - void (*height_changed) (ETableGroup *etg); + void (*resize) (ETableGroup *etg); + + void (*add) (ETableGroup *etg, gint row); + gboolean (*remove) (ETableGroup *etg, gint row); + gint (*get_count) (ETableGroup *etg); + void (*increment) (ETableGroup *etg, gint position, gint amount); + void (*set_focus) (ETableGroup *etg, EFocus direction, gint view_col); + gboolean (*get_focus) (ETableGroup *etg); + gint (*get_focus_column) (ETableGroup *etg); + ETableCol *(*get_ecol) (ETableGroup *etg); + + void (*thaw) (ETableGroup *etg); + gdouble (*get_height) (ETableGroup *etg); + gdouble (*get_width) (ETableGroup *etg); + void (*set_width) (ETableGroup *etg, gdouble width); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, - gboolean open, gboolean transparent); -void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, gboolean transparent); +void e_table_group_add (ETableGroup *etg, + gint row); +gboolean e_table_group_remove (ETableGroup *etg, + gint row); +gint e_table_group_get_count (ETableGroup *etg); +void e_table_group_increment (ETableGroup *etg, + gint position, + gint amount); +void e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint view_col); +gboolean e_table_group_get_focus (ETableGroup *etg); +gint e_table_group_get_focus_column (ETableGroup *etg); +ETableCol *e_table_group_get_ecol (ETableGroup *etg); + +ETableGroup *e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules); +void e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); -void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); +/* For emitting the signal */ +void e_table_group_resize (ETableGroup *etg); GtkType e_table_group_get_type (void); -#endif /* _E_TABLE_TREE_H_ */ +#endif /* _E_TABLE_GROUP_H_ */ diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index b025664385..6b6146c938 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -317,7 +317,7 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, { /* Check if it's the correct ethi */ if (ethi->drag_col == -1) - return; + return FALSE; gdk_drag_status (context, 0, time); if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { @@ -372,7 +372,7 @@ ethi_drag_drop (GtkWidget *canvas, gboolean successful = FALSE; if (ethi->drag_col == -1) - return; + return FALSE; if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && @@ -486,7 +486,6 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, { GdkRectangle clip; int xtra; - int arrowx; gdk_draw_rectangle ( drawable, gc, TRUE, @@ -541,7 +540,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, gtk_paint_arrow (gtk_widget_get_style(GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas)), drawable, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, + GTK_SHADOW_IN, &clip, GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas), "header", diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index 130c51a85c..d8ecdf1404 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel. * @@ -26,7 +27,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; @@ -36,12 +37,14 @@ enum { ARG_0, ARG_TABLE_HEADER, ARG_TABLE_MODEL, - ARG_TABLE_X, - ARG_TABLE_Y, ARG_TABLE_DRAW_GRID, ARG_TABLE_DRAW_FOCUS, ARG_MODE_SPREADSHEET, - ARG_LENGHT_THRESHOLD + ARG_LENGHT_THRESHOLD, + + ARG_WIDTH, + ARG_HEIGHT, + ARG_HAS_FOCUS }; static gboolean @@ -67,7 +70,7 @@ eti_realize_cell_views (ETableItem *eti) int i; for (i = 0; i < eti->n_cells; i++) - e_cell_view_realize (eti->cell_views [i], eti); + e_cell_realize (eti->cell_views [i]); eti->cell_views_realized = 1; } @@ -287,13 +290,13 @@ eti_compute_height (ETableItem *eti) int new_height = eti_get_height (eti); if (new_height != eti->height){ - double x1, y1, x2, y2; + /* double x1, y1, x2, y2;*/ printf ("Emitting!\n"); eti->height = new_height; eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); - gtk_signal_emit (GTK_OBJECT (eti), eti_signals [HEIGHT_CHANGED]); + gtk_signal_emit (GTK_OBJECT (eti), eti_signals [RESIZE]); } } @@ -537,14 +540,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) eti_add_table_model (eti, GTK_VALUE_POINTER (*arg)); break; - case ARG_TABLE_X: - eti->x1 = GTK_VALUE_DOUBLE (*arg); - break; - - case ARG_TABLE_Y: - eti->y1 = GTK_VALUE_DOUBLE (*arg); - break; - case ARG_LENGHT_THRESHOLD: eti->length_threshold = GTK_VALUE_INT (*arg); break; @@ -565,6 +560,27 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) } static void +eti_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableItem *eti; + + item = GNOME_CANVAS_ITEM (o); + eti = E_TABLE_ITEM (o); + + switch (arg_id){ + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = eti->width; + break; + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = eti->height; + break; + default: + arg->type = GTK_TYPE_INVALID; + } +} + +static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); @@ -576,7 +592,7 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - eti->renderers_can_change_size = 0; + eti->renderers_can_change_size = 1; eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -878,31 +894,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub } static void -eti_cursor_move_left (ETableItem *eti) +eti_cursor_move (ETableItem *eti, gint row, gint column) { e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); + e_table_item_focus (eti, column, row); +} + +static void +eti_cursor_move_left (ETableItem *eti) +{ + eti_cursor_move(eti, eti->focused_row, eti->focused_col - 1); } static void eti_cursor_move_right (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); + eti_cursor_move(eti, eti->focused_row, eti->focused_col + 1); } static void eti_cursor_move_up (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); + eti_cursor_move(eti, eti->focused_row - 1, eti->focused_col); } static void eti_cursor_move_down (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); + eti_cursor_move(eti, eti->focused_row + 1, eti->focused_col); } static int @@ -911,6 +930,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; ETableCol *ecol; + gint return_val = TRUE; switch (e->type){ case GDK_BUTTON_PRESS: @@ -982,66 +1002,66 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti->focused_col > 0) eti_cursor_move_left (eti); - - return TRUE; - + break; + case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - return TRUE; - + break; + case GDK_Up: if (eti->focused_row > 0) eti_cursor_move_up (eti); - return TRUE; + else + return_val = FALSE; + break; case GDK_Down: if ((eti->focused_row + 1) < eti->rows) eti_cursor_move_down (eti); - - return TRUE; + else + return_val = FALSE; + break; case GDK_Tab: + case GDK_KP_Tab: + case GDK_ISO_Left_Tab: if ((e->key.state & GDK_SHIFT_MASK) != 0){ /* shift tab */ if (eti->focused_col > 0) eti_cursor_move_left (eti); - else if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->cols - 1, eti->focused_row - 1); - } else { - /* FIXME: request focus leave backward */ - } + else if (eti->focused_row > 0) + eti_cursor_move(eti, eti->focused_row - 1, eti->cols - 1); + else + return_val = FALSE; } else { - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - else if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, 0, eti->rows - 1); - } else { - /* FIXME: request focus leave forward */ - } + else if (eti->focused_row < eti->rows - 1) + eti_cursor_move(eti, eti->focused_row + 1, 0); + else + return_val = FALSE; } break; default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) - return 0; + return_val = FALSE; if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff)) - return 0; + return_val = FALSE; } - } - ecol = e_table_header_get_column (eti->header, eti->focused_col); - ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + ecol = e_table_header_get_column (eti->header, eti->focused_col); + ecell_view = eti->cell_views [eti->focused_col]; + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + } break; - + case GDK_KEY_RELEASE: if (eti->focused_col == -1) return FALSE; @@ -1053,8 +1073,15 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } break; + case GDK_FOCUS_CHANGE: + if (e->focus_change.in) { + } else { + e_table_item_leave_edit (eti); + e_table_item_unfocus (eti); + } + default: - return FALSE; + return_val = FALSE; } return TRUE; } @@ -1084,6 +1111,7 @@ eti_class_init (GtkObjectClass *object_class) object_class->destroy = eti_destroy; object_class->set_arg = eti_set_arg; + object_class->get_arg = eti_get_arg; item_class->update = eti_update; item_class->realize = eti_realize; @@ -1099,10 +1127,6 @@ eti_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_HEADER); gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_TABLE_MODEL); - gtk_object_add_arg_type ("ETableItem::x", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_X); - gtk_object_add_arg_type ("ETableItem::y", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID); gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL, @@ -1110,6 +1134,13 @@ eti_class_init (GtkObjectClass *object_class) gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET); + gtk_object_add_arg_type ("ETableItem::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableItem::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableItem::has_focus", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_HAS_FOCUS); + eti_signals [ROW_SELECTION] = gtk_signal_new ("row_selection", GTK_RUN_LAST, @@ -1118,11 +1149,11 @@ eti_class_init (GtkObjectClass *object_class) gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); - eti_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + eti_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + GTK_SIGNAL_OFFSET (ETableItemClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); @@ -1192,6 +1223,16 @@ e_table_item_unfocus (ETableItem *eti) eti->focused_row = -1; } +gint +e_table_item_get_focused_column (ETableItem *eti) +{ + g_return_val_if_fail (eti != NULL, -1); + g_return_val_if_fail (E_IS_TABLE_ITEM (eti), -1); + + return eti->focused_col; +} + + const GSList * e_table_item_get_selection (ETableItem *eti) { diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index f19819f2fc..635dc76922 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -68,7 +68,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); - void (*height_changed) (ETableItem *eti); + void (*resize) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); @@ -79,6 +79,8 @@ GtkType e_table_item_get_type (void); void e_table_item_focus (ETableItem *eti, int col, int row); void e_table_item_unfocus (ETableItem *eti); +gint e_table_item_get_focused_column (ETableItem *eti); + /* * Selection */ diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c index 9e397710ef..e84e6da4d3 100644 --- a/widgets/table/e-table-model.c +++ b/widgets/table/e-table-model.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a Table Model * @@ -173,4 +174,23 @@ e_table_model_cell_changed (ETableModel *e_table_model, int col, int row) e_table_model_signals [MODEL_CELL_CHANGED], col, row); } +void +e_table_model_freeze (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = TRUE; + return ETM_CLASS (e_table_model)->thaw (e_table_model); +} +void +e_table_model_thaw (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = FALSE; + if (ETM_CLASS(e_table_model)->thaw) + ETM_CLASS (e_table_model)->thaw (e_table_model); +} diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h index 2d08f3744e..9f2dbbf87c 100644 --- a/widgets/table/e-table-model.h +++ b/widgets/table/e-table-model.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_MODEL_H_ #define _E_TABLE_MODEL_H_ @@ -11,6 +12,8 @@ typedef struct { GtkObject base; + + guint frozen : 1; } ETableModel; typedef struct { @@ -24,7 +27,7 @@ typedef struct { void *(*value_at) (ETableModel *etm, int col, int row); void (*set_value_at) (ETableModel *etm, int col, int row, const void *value); gboolean (*is_cell_editable) (ETableModel *etm, int col, int row); - + void (*thaw) (ETableModel *etm); /* * Signals */ @@ -48,6 +51,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_freeze (ETableModel *e_table_model); +void e_table_model_thaw (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c index 38e1dd8eb0..1f64d08f39 100644 --- a/widgets/table/e-table-simple.c +++ b/widgets/table/e-table-simple.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a simple table model implementation that uses function * pointers to simplify the creation of new, exotic and colorful tables in @@ -55,6 +56,14 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) } static void +simple_thaw (ETableModel *etm) +{ + ETableSimple *simple = (ETableSimple *)etm; + + simple->thaw (etm, simple->data); +} + +static void e_table_simple_class_init (GtkObjectClass *object_class) { ETableModelClass *model_class = (ETableModelClass *) object_class; @@ -64,6 +73,7 @@ e_table_simple_class_init (GtkObjectClass *object_class) model_class->value_at = simple_value_at; model_class->set_value_at = simple_set_value_at; model_class->is_cell_editable = simple_is_cell_editable; + model_class->thaw = simple_thaw; } GtkType @@ -95,6 +105,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data) { ETableSimple *et; @@ -106,6 +117,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->value_at = value_at; et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; + et->thaw = thaw; et->data = data; return (ETableModel *) et; diff --git a/widgets/table/e-table-simple.h b/widgets/table/e-table-simple.h index d890245386..a3164eefc0 100644 --- a/widgets/table/e-table-simple.h +++ b/widgets/table/e-table-simple.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SIMPLE_H_ #define _E_TABLE_SIMPLE_H_ @@ -8,6 +9,7 @@ typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *dat typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data); typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef void (*ETableSimpleThawFn) (ETableModel *etm, void *data); typedef struct { ETableModel parent; @@ -17,6 +19,7 @@ typedef struct { ETableSimpleValueAtFn value_at; ETableSimpleSetValueAtFn set_value_at; ETableSimpleIsCellEditableFn is_cell_editable; + ETableSimpleThawFn thaw; void *data; } ETableSimple; @@ -31,6 +34,7 @@ ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data); #endif /* _E_TABLE_SIMPLE_H_ */ diff --git a/widgets/table/e-table-sorted.h b/widgets/table/e-table-sorted.h index 2ec52df2e7..92bd8d1522 100644 --- a/widgets/table/e-table-sorted.h +++ b/widgets/table/e-table-sorted.h @@ -19,7 +19,7 @@ typedef struct { } ETableSorted; typedef struct { - ETableSubset parent_class; + ETableSubsetClass parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); diff --git a/widgets/table/e-table-subset-variable.c b/widgets/table/e-table-subset-variable.c new file mode 100644 index 0000000000..76da03c44f --- /dev/null +++ b/widgets/table/e-table-subset-variable.c @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-table-subset.c: Implements a table that contains a subset of another table. + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 Helix Code, Inc. + */ +#include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> +#include <string.h> +#include "e-util/e-util.h" +#include "e-table-subset-variable.h" + +#define PARENT_TYPE E_TABLE_SUBSET_TYPE + +#define INCREMENT_AMOUNT 10 + +static ETableModelClass *etssv_parent_class; + +static void +etssv_class_init (GtkObjectClass *klass) +{ + etssv_parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_table_subset_variable, "ETableSubsetVariable", ETableSubsetVariable, etssv_class_init, NULL, PARENT_TYPE); + +ETableModel * +e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source) +{ + if ( e_table_subset_construct(E_TABLE_SUBSET(etssv), source, 1) == NULL ) + return NULL; + E_TABLE_SUBSET(etssv)->n_map = 0; + + return E_TABLE_MODEL (etssv); +} + +ETableModel * +e_table_subset_variable_new (ETableModel *source) +{ + ETableSubsetVariable *etssv = gtk_type_new (E_TABLE_SUBSET_VARIABLE_TYPE); + + if (e_table_subset_variable_construct (etssv, source) == NULL){ + gtk_object_destroy (GTK_OBJECT (etssv)); + return NULL; + } + + return (ETableModel *) etssv; +} + +void +e_table_subset_variable_add (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + + if ( etss->n_map + 1 > etssv->n_vals_allocated ) + etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int)); + etss->map_table[etss->n_map++] = row; + if ( !etm->frozen ) + e_table_model_changed(etm); +} + +gboolean +e_table_subset_variable_remove (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + int i; + + for ( i = 0; i < etss->n_map; i++ ) { + if (etss->map_table[i] == row) { + memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int)); + etss->n_map --; + if ( !etm->frozen ) + e_table_model_changed(etm); + return TRUE; + } + } + return FALSE; +} + +void +e_table_subset_variable_increment (ETableSubsetVariable *etssv, + gint position, + gint amount) +{ + int i; + ETableSubset *etss = E_TABLE_SUBSET(etssv); + for ( i = 0; i < etss->n_map; i++ ) { + if ( etss->map_table[i] > position ) + etss->map_table[i] += amount; + } +} + +void +e_table_subset_variable_set_allocation (ETableSubsetVariable *etssv, + gint total) +{ + ETableSubset *etss = E_TABLE_SUBSET(etssv); + if ( total <= 0 ) + total = 1; + if ( total > etss->n_map ) { + etss->map_table = g_realloc(etss->map_table, total * sizeof(int)); + } +} diff --git a/widgets/table/e-table-subset-variable.h b/widgets/table/e-table-subset-variable.h new file mode 100644 index 0000000000..9755fb2477 --- /dev/null +++ b/widgets/table/e-table-subset-variable.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_SUBSET_VARIABLE_H_ +#define _E_TABLE_SUBSET_VARIABLE_H_ + +#include <gtk/gtkobject.h> +#include "e-table-subset.h" + +#define E_TABLE_SUBSET_VARIABLE_TYPE (e_table_subset_variable_get_type ()) +#define E_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariable)) +#define E_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariableClass)) +#define E_IS_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_SUBSET_VARIABLE_TYPE)) +#define E_IS_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SUBSET_VARIABLE_TYPE)) + +typedef struct { + ETableSubset base; + + int n_vals_allocated; +} ETableSubsetVariable; + +typedef struct { + ETableSubsetClass parent_class; +} ETableSubsetVariableClass; + +GtkType e_table_subset_variable_get_type (void); +ETableModel *e_table_subset_variable_new (ETableModel *etm); +ETableModel *e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source); +void e_table_subset_variable_add (ETableSubsetVariable *ets, + gint row); +gboolean e_table_subset_variable_remove (ETableSubsetVariable *ets, + gint row); +void e_table_subset_variable_increment (ETableSubsetVariable *ets, + gint position, + gint amount); +void e_table_subset_variable_set_allocation (ETableSubsetVariable *ets, + gint total); +#endif /* _E_TABLE_SUBSET_VARIABLE_H_ */ + diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c index a9e4a5c5a4..a09d221980 100644 --- a/widgets/table/e-table-subset.c +++ b/widgets/table/e-table-subset.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-subset.c: Implements a table that contains a subset of another table. * @@ -71,6 +72,12 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) } static void +etss_thaw (ETableModel *etm) +{ + e_table_model_changed (etm); +} + +static void etss_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; @@ -84,6 +91,7 @@ etss_class_init (GtkObjectClass *klass) table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; + table_class->thaw = etss_thaw; } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); @@ -91,20 +99,23 @@ E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, static void etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) { - e_table_model_changed (E_TABLE_MODEL (etss)); + if ( !E_TABLE_MODEL(etss)->frozen ) + e_table_model_changed (E_TABLE_MODEL (etss)); } static void etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_row_changed (E_TABLE_MODEL (etss), i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } } } } @@ -112,14 +123,16 @@ etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) static void etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } } } } @@ -130,7 +143,7 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + buffer = (unsigned int *) g_malloc (sizeof (unsigned int) * nvals); if (buffer == NULL) return NULL; etss->map_table = buffer; diff --git a/widgets/table/e-table-subset.h b/widgets/table/e-table-subset.h index 314f28aea6..d8af1696f5 100644 --- a/widgets/table/e-table-subset.h +++ b/widgets/table/e-table-subset.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SUBSET_H_ #define _E_TABLE_SUBSET_H_ diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 46531113e4..551ef52227 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -1,5 +1,6 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * E-table-view.c: A graphical view of a Table. + * E-table.c: A graphical view of a Table. * * Author: * Miguel de Icaza (miguel@gnu.org) @@ -16,7 +17,9 @@ #include <stdio.h> #include <libgnomeui/gnome-canvas.h> #include <gtk/gtksignal.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" +#include "e-util/e-xml-utils.h" #include "e-table.h" #include "e-table-header-item.h" #include "e-table-subset.h" @@ -40,8 +43,6 @@ et_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); - g_free (et->group_spec); - (*e_table_parent_class->destroy)(object); } @@ -56,19 +57,16 @@ e_table_init (GtkObject *object) } static ETableHeader * -e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +e_table_make_header (ETable *e_table, ETableHeader *full_header, xmlNode *xmlColumns) { ETableHeader *nh; - char *copy = alloca (strlen (cols) + 1); - char *p, *state; + xmlNode *column; const int max_cols = e_table_header_count (full_header); nh = e_table_header_new (); - strcpy (copy, cols); - while ((p = strtok_r (copy, ",", &state)) != NULL){ - int col = atoi (p); + for (column = xmlColumns->childs; column; column = column->next) { + int col = atoi (column->childs->content); - copy = NULL; if (col >= max_cols) continue; @@ -113,6 +111,7 @@ e_table_setup_header (ETable *e_table) } +#if 0 typedef struct { void *value; GArray *array; @@ -201,7 +200,7 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } - +#endif typedef struct _Node Node; struct _Node { @@ -212,7 +211,7 @@ struct _Node { guint is_leaf:1; }; - +#if 0 static Node * leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) { @@ -335,8 +334,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - - group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "columns", ecol, TRUE, parent == NULL); group = node_new (group_item, model, parent); for (i = 0; tables [i] != NULL; i++){ @@ -347,8 +347,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, GnomeCanvasItem *item_leaf_header; Node *leaf_header; + /* FIXME *//* item_leaf_header = e_table_group_new ( - GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE); + GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE);*/ leaf_header = node_new (item_leaf_header, tables [i], group); e_table_create_leaf (e_table, tables [i], leaf_header); @@ -424,6 +425,14 @@ static GnomeCanvasClass *e_table_canvas_parent_class; static void e_table_canvas_realize (GtkWidget *widget) { +#if 0 + GnomeCanvasItem *group_item; + + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "header", E_TABLE, TRUE, parent == NULL); + + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; int *groups; @@ -433,6 +442,8 @@ e_table_canvas_realize (GtkWidget *widget) groups = group_spec_to_desc (e_table->group_spec); + + leaf = e_table_create_nodes ( e_table, e_table->model, e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, groups); @@ -440,6 +451,7 @@ e_table_canvas_realize (GtkWidget *widget) if (groups) g_free (groups); +#endif } static void @@ -496,33 +508,75 @@ e_table_canvas_new (ETable *e_table) return GNOME_CANVAS (e_table_canvas); } +#endif static void -table_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) +table_canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) { + gdouble height; + gdouble width; + gtk_object_get(GTK_OBJECT(e_table->group), + "height", &height, + NULL); gnome_canvas_set_scroll_region ( GNOME_CANVAS (e_table->table_canvas), - 0, 0, alloc->width, alloc->height); + 0, 0, alloc->width, MAX(height, alloc->height)); + width = alloc->width; + gtk_object_set(GTK_OBJECT(e_table->group), + "width", width, + NULL); } static void -e_table_setup_table (ETable *e_table) +e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, ETableModel *model, xmlNode *xml_grouping) { - e_table->table_canvas = e_table_canvas_new (e_table); + e_table->table_canvas = GNOME_CANVAS(gnome_canvas_new ()); gtk_signal_connect ( GTK_OBJECT (e_table->table_canvas), "size_allocate", - GTK_SIGNAL_FUNC (table_canvas_size_alocate), e_table); + GTK_SIGNAL_FUNC (table_canvas_size_allocate), e_table); gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); gtk_table_attach ( GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + + e_table->group = e_table_group_new(GNOME_CANVAS_GROUP(e_table->table_canvas->root), + full_header, + header, + model, + xml_grouping->childs); + +} + +static void +e_table_fill_table (ETable *e_table, ETableModel *model) +{ + int count; + int i; + count = e_table_model_row_count(model); + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", TRUE, + NULL); + for ( i = 0; i < count; i++ ) { + e_table_group_add(e_table->group, i); + } + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", FALSE, + NULL); } void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec) + const char *spec) { + xmlDoc *xmlSpec; + xmlNode *xmlRoot; + xmlNode *xmlColumns; + xmlNode *xmlGrouping; + + char *copy; + copy = g_strdup(spec); + GTK_TABLE (e_table)->homogeneous = FALSE; gtk_table_resize (GTK_TABLE (e_table), 1, 2); @@ -532,24 +586,29 @@ e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, e_table->model = etm; gtk_object_ref (GTK_OBJECT (etm)); + + xmlSpec = xmlParseMemory(copy, strlen(copy) + 1); + e_table->specification = xmlSpec; - e_table->header = e_table_make_header (e_table, full_header, cols_spec); + xmlRoot = xmlDocGetRootElement(xmlSpec); + xmlColumns = e_xml_get_child_by_name(xmlRoot, "columns-shown"); + xmlGrouping = e_xml_get_child_by_name(xmlRoot, "grouping"); + + e_table->header = e_table_make_header (e_table, full_header, xmlColumns); e_table_setup_header (e_table); - e_table_setup_table (e_table); - - e_table->group_spec = g_strdup (group_spec); - + e_table_setup_table (e_table, full_header, e_table->header, etm, xmlGrouping); + e_table_fill_table (e_table, etm); } GtkWidget * -e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *spec) { ETable *e_table; e_table = gtk_type_new (e_table_get_type ()); - e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + e_table_construct (e_table, full_header, etm, spec); return (GtkWidget *) e_table; } diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index 63c131324f..a372d8042c 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -1,10 +1,13 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ #include <libgnomeui/gnome-canvas.h> #include <gtk/gtktable.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-table-group.h" BEGIN_GNOME_DECLS @@ -21,15 +24,17 @@ typedef struct { ETableHeader *full_header, *header; + ETableGroup *group; + GnomeCanvas *header_canvas, *table_canvas; GnomeCanvasItem *header_item, *root; + + xmlDoc *specification; guint draw_grid:1; guint draw_focus:1; guint spreadsheet:1; - - char *group_spec; } ETable; typedef struct { @@ -38,9 +43,9 @@ typedef struct { GtkType e_table_get_type (void); void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); END_GNOME_DECLS diff --git a/widgets/table/test-check.c b/widgets/table/test-check.c index 380da8048e..a6a59788ad 100644 --- a/widgets/table/test-check.c +++ b/widgets/table/test-check.c @@ -13,6 +13,7 @@ #include "e-table-header-item.h" #include "e-table-item.h" #include "e-util/e-cursors.h" +#include "e-util/e-canvas-utils.h" #include "e-cell-text.h" #include "e-cell-checkbox.h" @@ -79,6 +80,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -93,13 +100,14 @@ check_test (void) ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; GdkPixbuf *pixbuf; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -137,21 +145,15 @@ check_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 0, 30); } - - - - diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c index 3fe17ae555..adc9ed6c20 100644 --- a/widgets/table/test-cols.c +++ b/widgets/table/test-cols.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <string.h> #include <gnome.h> +#include "e-util/e-canvas-utils.h" #include "e-util/e-cursors.h" #include "e-table-simple.h" #include "e-table-header.h" @@ -84,6 +85,12 @@ set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); } +static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + void multi_cols_test (void) { @@ -92,13 +99,14 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -157,17 +165,17 @@ multi_cols_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); + + e_canvas_item_move_absolute(item, 0, 30); gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), @@ -176,18 +184,16 @@ multi_cols_test (void) "x", 300, "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header_multiple, "ETableModel", e_table_model, - "x", (double) 300, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 300, 30); } diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c index 27e1ac59f1..1bd50e1479 100644 --- a/widgets/table/test-table.c +++ b/widgets/table/test-table.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Test code for the ETable package * @@ -55,6 +56,8 @@ parse_headers () p = buffer; for (i = 0; (s = strtok (p, " \t")) != NULL; i++){ column_labels [i] = g_strdup (s); + if ( strchr(column_labels [i], '\n') ) + *strchr(column_labels [i], '\n') = 0; p = NULL; } @@ -174,6 +177,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -196,7 +205,7 @@ table_browser_test (void) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -244,8 +253,6 @@ table_browser_test (void) e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 0, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, @@ -253,7 +260,7 @@ table_browser_test (void) } static void -do_e_table_demo (const char *col_spec, const char *group_spec) +do_e_table_demo (const char *spec) { GtkWidget *e_table, *window, *frame; ETableModel *e_table_model; @@ -266,7 +273,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); full_header = e_table_header_new (); cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT, TRUE); @@ -283,7 +290,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); frame = gtk_frame_new (NULL); - e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + e_table = e_table_new (full_header, e_table_model, spec); gtk_container_add (GTK_CONTAINER (frame), e_table); gtk_container_add (GTK_CONTAINER (window), frame); @@ -298,9 +305,10 @@ e_table_test (void) { load_data (); - if (getenv ("DO")){ - do_e_table_demo ("0,1,2,3,4", NULL); - do_e_table_demo ("0,1,2,3,4", "3,4"); + if (1){/*getenv ("DO")){*/ + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf/> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <group column=\"4\"> <leaf/> </group> </group> </grouping> </ETableSpecification>"); } - do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\"> <leaf/> </group> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <leaf/> </group> </grouping> </ETableSpecification>"); } diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index 2e3e7c158a..6647531eee 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -109,8 +109,6 @@ static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event); static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data); -static guint32 e_text_get_event_time (EText *text); - static void e_text_get_selection(EText *text, GdkAtom selection, guint32 time); static void e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length); @@ -1701,7 +1699,7 @@ static void _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) { if (xp || yp) { - struct line *lines; + struct line *lines = NULL; int x, y; int j; x = get_line_xpos (text, lines); @@ -1993,7 +1991,9 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_ENTER_NOTIFY: - text->tooltip_timeout = gtk_timeout_add (3000, _do_tooltip, text); + if ( text->tooltip_count == 0 ) + text->tooltip_timeout = gtk_timeout_add (1000, _do_tooltip, text); + text->tooltip_count ++; text->pointer_in = TRUE; if (text->editing) { if ( text->default_cursor_shown ) { @@ -2003,10 +2003,13 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_LEAVE_NOTIFY: - gtk_timeout_remove (text->tooltip_timeout); - if (text->tooltip_window) { - gtk_widget_destroy (text->tooltip_window); - text->tooltip_window = NULL; + text->tooltip_count --; + if ( text->tooltip_count == 0 ) { + gtk_timeout_remove (text->tooltip_timeout); + if (text->tooltip_window) { + gtk_widget_destroy (text->tooltip_window); + text->tooltip_window = NULL; + } } text->pointer_in = FALSE; @@ -2443,50 +2446,6 @@ e_text_real_paste_clipboard (EText *text) } #endif -/* Get the timestamp of the current event. Actually, the only thing - * we really care about below is the key event - */ -static guint32 -e_text_get_event_time (EText *text) -{ - GdkEvent *event; - guint32 tm = GDK_CURRENT_TIME; - - event = gtk_get_current_event(); - - if (event) - switch (event->type) - { - case GDK_MOTION_NOTIFY: - tm = event->motion.time; break; - case GDK_BUTTON_PRESS: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - tm = event->button.time; break; - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - tm = event->key.time; break; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - tm = event->crossing.time; break; - case GDK_PROPERTY_NOTIFY: - tm = event->property.time; break; - case GDK_SELECTION_CLEAR: - case GDK_SELECTION_REQUEST: - case GDK_SELECTION_NOTIFY: - tm = event->selection.time; break; - case GDK_PROXIMITY_IN: - case GDK_PROXIMITY_OUT: - tm = event->proximity.time; break; - default: /* use current time */ - break; - } - gdk_event_free(event); - - return tm; -} - /* Routines for sucking fonts from the X server */ diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index c44589d3ae..2f29fb189b 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -176,6 +176,7 @@ struct _EText { gint tooltip_timeout; /* Timeout for the tooltip */ GtkWidget *tooltip_window; /* GtkWindow for displaying the tooltip */ + gint tooltip_count; /* GDK_ENTER_NOTIFY count. */ }; struct _ETextClass { |