diff options
author | nobody <nobody@localhost> | 2002-05-11 02:20:52 +0800 |
---|---|---|
committer | nobody <nobody@localhost> | 2002-05-11 02:20:52 +0800 |
commit | 1a00e2771f6baabf4e5cb513808bd5870285433f (patch) | |
tree | a43da2f62b64dd3447c4703f7283ce5baf574a41 | |
parent | bd32b80723a742023fb02183630cfccfa406e451 (diff) | |
download | gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar.gz gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar.bz2 gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar.lz gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar.xz gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.tar.zst gsoc2013-evolution-1a00e2771f6baabf4e5cb513808bd5870285433f.zip |
This commit was manufactured by cvs2svn to create branch 'gal-2'.
svn path=/branches/gal-2/; revision=16750
-rw-r--r-- | widgets/menus/gal-view-instance-save-as-dialog.c | 312 | ||||
-rw-r--r-- | widgets/table/e-cell-vbox.c | 489 | ||||
-rw-r--r-- | widgets/table/e-cell-vbox.h | 68 | ||||
-rw-r--r-- | widgets/table/e-table-memory-store.c | 436 | ||||
-rw-r--r-- | widgets/table/e-table-memory-store.h | 122 | ||||
-rw-r--r-- | widgets/table/e-table-search.c | 251 | ||||
-rw-r--r-- | widgets/table/e-table-search.h | 72 |
7 files changed, 1750 insertions, 0 deletions
diff --git a/widgets/menus/gal-view-instance-save-as-dialog.c b/widgets/menus/gal-view-instance-save-as-dialog.c new file mode 100644 index 0000000000..c00937b46f --- /dev/null +++ b/widgets/menus/gal-view-instance-save-as-dialog.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * gal-define-views-dialog.c + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> + +#include "gal-view-instance-save-as-dialog.h" + +#include <libgnomeui/gnome-dialog.h> +#include <libgnomeui/gnome-stock.h> +#include "gal-define-views-model.h" +#include "gal-view-new-dialog.h" +#include <gal/e-table/e-table-scrolled.h> +#include <gal/util/e-i18n.h> + +static GnomeDialogClass *parent_class = NULL; +#define PARENT_TYPE gnome_dialog_get_type() + +/* The arguments we take */ +enum { + ARG_0, + ARG_INSTANCE, +}; + +typedef struct { + char *title; + ETableModel *model; + GalViewInstanceSaveAsDialog *names; +} GalViewInstanceSaveAsDialogChild; + + +/* Static functions */ +static void +gal_view_instance_save_as_dialog_set_instance(GalViewInstanceSaveAsDialog *dialog, + GalViewInstance *instance) +{ + dialog->instance = instance; + if (dialog->model) { + gtk_object_set(GTK_OBJECT(dialog->model), + "collection", instance ? instance->collection : NULL, + NULL); + } +} + +static void +gvisad_setup_radio_buttons (GalViewInstanceSaveAsDialog *dialog) +{ + GtkWidget *radio_replace = glade_xml_get_widget (dialog->gui, "radiobutton-replace"); + GtkWidget *radio_create = glade_xml_get_widget (dialog->gui, "radiobutton-create" ); + GtkWidget *widget; + GtkNotebook *notebook = GTK_NOTEBOOK (glade_xml_get_widget (dialog->gui, "notebook-help")); + + widget = glade_xml_get_widget (dialog->gui, "custom-replace"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_replace))) { + gtk_widget_set_sensitive (widget, TRUE); + gtk_notebook_set_page (notebook, 0); + dialog->toggle = GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_REPLACE; + } else { + gtk_widget_set_sensitive (widget, FALSE); + } + + widget = glade_xml_get_widget (dialog->gui, "entry-create"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_create))) { + gtk_widget_set_sensitive (widget, TRUE); + gtk_notebook_set_page (notebook, 1); + dialog->toggle = GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_CREATE; + } else { + gtk_widget_set_sensitive (widget, FALSE); + } +} + +static void +gvisad_radio_toggled (GtkWidget *widget, GalViewInstanceSaveAsDialog *dialog) +{ + gvisad_setup_radio_buttons (dialog); +} + +static void +gvisad_connect_signal(GalViewInstanceSaveAsDialog *dialog, char *widget_name, char *signal, GtkSignalFunc handler) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget(dialog->gui, widget_name); + + if (widget) + gtk_signal_connect(GTK_OBJECT(widget), signal, handler, dialog); +} + +/* Method override implementations */ +static void +gal_view_instance_save_as_dialog_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GalViewInstanceSaveAsDialog *dialog; + + dialog = GAL_VIEW_INSTANCE_SAVE_AS_DIALOG (o); + + switch (arg_id){ + case ARG_INSTANCE: + if (GTK_VALUE_OBJECT(*arg)) + gal_view_instance_save_as_dialog_set_instance(dialog, GAL_VIEW_INSTANCE(GTK_VALUE_OBJECT(*arg))); + else + gal_view_instance_save_as_dialog_set_instance(dialog, NULL); + break; + + default: + return; + } +} + +static void +gal_view_instance_save_as_dialog_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GalViewInstanceSaveAsDialog *dialog; + + dialog = GAL_VIEW_INSTANCE_SAVE_AS_DIALOG (object); + + switch (arg_id) { + case ARG_INSTANCE: + if (dialog->instance) + GTK_VALUE_OBJECT(*arg) = GTK_OBJECT(dialog->instance); + else + GTK_VALUE_OBJECT(*arg) = NULL; + break; + + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gal_view_instance_save_as_dialog_destroy (GtkObject *object) +{ + GalViewInstanceSaveAsDialog *gal_view_instance_save_as_dialog = GAL_VIEW_INSTANCE_SAVE_AS_DIALOG(object); + + gtk_object_unref(GTK_OBJECT(gal_view_instance_save_as_dialog->gui)); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +/* Init functions */ +static void +gal_view_instance_save_as_dialog_class_init (GalViewInstanceSaveAsDialogClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + + parent_class = gtk_type_class (PARENT_TYPE); + + object_class->set_arg = gal_view_instance_save_as_dialog_set_arg; + object_class->get_arg = gal_view_instance_save_as_dialog_get_arg; + object_class->destroy = gal_view_instance_save_as_dialog_destroy; + + gtk_object_add_arg_type("GalViewInstanceSaveAsDialog::instance", GAL_VIEW_INSTANCE_TYPE, + GTK_ARG_READWRITE, ARG_INSTANCE); +} + +static void +gal_view_instance_save_as_dialog_init (GalViewInstanceSaveAsDialog *dialog) +{ + GladeXML *gui; + GtkWidget *widget; + GtkWidget *etable; + + dialog->instance = NULL; + + gui = glade_xml_new_with_domain (GAL_GLADEDIR "/gal-view-instance-save-as-dialog.glade", NULL, PACKAGE); + dialog->gui = gui; + + widget = glade_xml_get_widget(gui, "table-top"); + if (!widget) { + return; + } + gtk_widget_ref(widget); + gtk_widget_unparent(widget); + gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), widget, TRUE, TRUE, 0); + gtk_widget_unref(widget); + + gnome_dialog_append_buttons(GNOME_DIALOG(dialog), + GNOME_STOCK_BUTTON_OK, + GNOME_STOCK_BUTTON_CANCEL, + NULL); + + gvisad_connect_signal(dialog, "radiobutton-replace", "toggled", GTK_SIGNAL_FUNC(gvisad_radio_toggled)); + gvisad_connect_signal(dialog, "radiobutton-create", "toggled", GTK_SIGNAL_FUNC(gvisad_radio_toggled)); + + dialog->model = NULL; + etable = glade_xml_get_widget(dialog->gui, "custom-replace"); + if (etable) { + dialog->model = gtk_object_get_data(GTK_OBJECT(etable), "GalViewInstanceSaveAsDialog::model"); + gtk_object_set(GTK_OBJECT(dialog->model), + "collection", dialog->instance ? dialog->instance->collection : NULL, + NULL); + } + + gvisad_setup_radio_buttons (dialog); + gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, FALSE); +} + + +/* For use from libglade. */ +/* ETable creation */ +#define SPEC "<ETableSpecification no-header=\"true\" cursor-mode=\"line\" draw-grid=\"false\" selection-mode=\"single\" gettext-domain=\"" E_I18N_DOMAIN "\">" \ + "<ETableColumn model_col= \"0\" _title=\"Name\" expansion=\"1.0\" minimum_width=\"18\" resizable=\"true\" cell=\"string\" compare=\"string\"/>" \ + "<ETableState> <column source=\"0\"/> <grouping> </grouping> </ETableState>" \ + "</ETableSpecification>" + +GtkWidget *gal_view_instance_save_as_dialog_create_etable(char *name, char *string1, char *string2, int int1, int int2); + +GtkWidget * +gal_view_instance_save_as_dialog_create_etable(char *name, char *string1, char *string2, int int1, int int2) +{ + GtkWidget *table; + ETableModel *model; + model = gal_define_views_model_new(); + table = e_table_scrolled_new(model, NULL, SPEC, NULL); + gtk_object_set_data(GTK_OBJECT(table), "GalViewInstanceSaveAsDialog::model", model); + return table; +} + +/* External methods */ +/** + * gal_view_instance_save_as_dialog_new + * + * Returns a new dialog for defining views. + * + * Returns: The GalViewInstanceSaveAsDialog. + */ +GtkWidget* +gal_view_instance_save_as_dialog_new (GalViewInstance *instance) +{ + GtkWidget *widget = GTK_WIDGET (gtk_type_new (gal_view_instance_save_as_dialog_get_type ())); + gal_view_instance_save_as_dialog_set_instance(GAL_VIEW_INSTANCE_SAVE_AS_DIALOG (widget), instance); + return widget; +} + +GtkType +gal_view_instance_save_as_dialog_get_type (void) +{ + static GtkType type = 0; + + if (!type) { + static const GtkTypeInfo info = + { + "GalViewInstanceSaveAsDialog", + sizeof (GalViewInstanceSaveAsDialog), + sizeof (GalViewInstanceSaveAsDialogClass), + (GtkClassInitFunc) gal_view_instance_save_as_dialog_class_init, + (GtkObjectInitFunc) gal_view_instance_save_as_dialog_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +void +gal_view_instance_save_as_dialog_save (GalViewInstanceSaveAsDialog *dialog) +{ + GalView *view = gal_view_instance_get_current_view (dialog->instance); + GtkWidget *widget; + char *title; + int n; + const char *id = NULL; + switch (dialog->toggle) { + case GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_REPLACE: + widget = glade_xml_get_widget(dialog->gui, "custom-replace"); + if (widget && E_IS_TABLE_SCROLLED (widget)) { + n = e_table_get_cursor_row (e_table_scrolled_get_table (E_TABLE_SCROLLED (widget))); + id = gal_view_collection_set_nth_view (dialog->instance->collection, n, view); + gal_view_collection_save (dialog->instance->collection); + } + break; + case GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_CREATE: + widget = glade_xml_get_widget(dialog->gui, "entry-create"); + if (widget && GTK_IS_ENTRY (widget)) { + title = gtk_entry_get_text (GTK_ENTRY (widget)); + id = gal_view_collection_append_with_title (dialog->instance->collection, title, view); + gal_view_collection_save (dialog->instance->collection); + } + break; + } + + if (id) { + gal_view_instance_set_current_view_id (dialog->instance, id); + } +} diff --git a/widgets/table/e-cell-vbox.c b/widgets/table/e-cell-vbox.c new file mode 100644 index 0000000000..a854c2dae1 --- /dev/null +++ b/widgets/table/e-cell-vbox.c @@ -0,0 +1,489 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-cell-vbox.c - Vbox cell object. + * Copyright 1999, 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * Chris Lahey <clahey@ximian.com> + * + * A majority of code taken from: + * + * the ECellText renderer. + * Copyright 1999, 2000, Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> + +#include <ctype.h> +#include <math.h> +#include <stdio.h> + +#include <gdk/gdkx.h> /* for BlackPixel */ +#include <gtk/gtkenums.h> +#include <gtk/gtkentry.h> +#include <gtk/gtkwindow.h> +#include <gtk/gtkinvisible.h> +#include <gtk/gtksignal.h> +#include <gdk/gdkkeysyms.h> + +#include "gal/util/e-util.h" +#include "e-table-item.h" +#include "e-cell-vbox.h" + +#define PARENT_TYPE e_cell_get_type () + +typedef struct { + ECellView cell_view; + int subcell_view_count; + ECellView **subcell_views; + int *model_cols; +} ECellVboxView; + +static ECellClass *parent_class; + +#define INDENT_AMOUNT 16 + +/* + * ECell::new_view method + */ +static ECellView * +ecv_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view) +{ + ECellVbox *ecv = E_CELL_VBOX (ecell); + ECellVboxView *vbox_view = g_new0 (ECellVboxView, 1); + int i; + + vbox_view->cell_view.ecell = ecell; + vbox_view->cell_view.e_table_model = table_model; + vbox_view->cell_view.e_table_item_view = e_table_item_view; + + /* create our subcell view */ + vbox_view->subcell_view_count = ecv->subcell_count; + vbox_view->subcell_views = g_new (ECellView *, vbox_view->subcell_view_count); + vbox_view->model_cols = g_new (int, vbox_view->subcell_view_count); + + for (i = 0; i < vbox_view->subcell_view_count; i++) { + vbox_view->subcell_views[i] = e_cell_new_view (ecv->subcells[i], table_model, e_table_item_view /* XXX */); + vbox_view->model_cols[i] = ecv->model_cols[i]; + } + + return (ECellView *)vbox_view; +} + +/* + * ECell::kill_view method + */ +static void +ecv_kill_view (ECellView *ecv) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecv; + int i; + + /* kill our subcell view */ + for (i = 0; i < vbox_view->subcell_view_count; i++) + e_cell_kill_view (vbox_view->subcell_views[i]); + + g_free (vbox_view->model_cols); + g_free (vbox_view->subcell_views); + g_free (vbox_view); +} + +/* + * ECell::realize method + */ +static void +ecv_realize (ECellView *ecell_view) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + int i; + + /* realize our subcell view */ + for (i = 0; i < vbox_view->subcell_view_count; i++) + e_cell_realize (vbox_view->subcell_views[i]); + + if (parent_class->realize) + (* parent_class->realize) (ecell_view); +} + +/* + * ECell::unrealize method + */ +static void +ecv_unrealize (ECellView *ecv) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecv; + int i; + + /* unrealize our subcell view. */ + for (i = 0; i < vbox_view->subcell_view_count; i++) + e_cell_unrealize (vbox_view->subcell_views[i]); + + if (parent_class->unrealize) + (* parent_class->unrealize) (ecv); +} + +/* + * ECell::draw method + */ +static void +ecv_draw (ECellView *ecell_view, GdkDrawable *drawable, + int model_col, int view_col, int row, ECellFlags flags, + int x1, int y1, int x2, int y2) +{ + ECellVboxView *vbox_view = (ECellVboxView *)ecell_view; + + int subcell_offset = 0; + int i; + + for (i = 0; i < vbox_view->subcell_view_count; i++) { + /* Now cause our subcells to draw their contents, + shifted by subcell_offset pixels */ + int height = e_cell_height (vbox_view->subcell_views[i], vbox_view->model_cols[i], view_col, row); + e_cell_draw (vbox_view->subcell_views[i], drawable, + vbox_view->model_cols[i], view_col, row, flags, + x1, y1 + subcell_offset, x2, y1 + subcell_offset + height); + + subcell_offset += e_cell_height (vbox_view->subcell_views[i], vbox_view->model_cols[i], view_col, row); + } +} + +/* + * ECell::event method + */ +static gint +ecv_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row, ECellFlags flags, ECellActions *actions) +{ + ECellVboxView *vbox_view = (ECellVboxView *)ecell_view; + int y = 0; + int i; + int subcell_offset = 0; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + y = event->button.y; + break; + case GDK_MOTION_NOTIFY: + y = event->motion.y; + break; + default: + /* nada */ + break; + } + + + for (i = 0; i < vbox_view->subcell_view_count; i++) { + int height = e_cell_height (vbox_view->subcell_views[i], vbox_view->model_cols[i], view_col, row); + if (y < subcell_offset + height) + return e_cell_event(vbox_view->subcell_views[i], event, vbox_view->model_cols[i], view_col, row, flags, actions); + subcell_offset += height; + } + return 0; +} + +/* + * ECell::height method + */ +static int +ecv_height (ECellView *ecell_view, int model_col, int view_col, int row) +{ + ECellVboxView *vbox_view = (ECellVboxView *)ecell_view; + int height = 0; + int i; + + for (i = 0; i < vbox_view->subcell_view_count; i++) { + height += e_cell_height (vbox_view->subcell_views[i], vbox_view->model_cols[i], view_col, row); + } + return height; +} + +/* + * ECell::max_width method + */ +static int +ecv_max_width (ECellView *ecell_view, int model_col, int view_col) +{ + ECellVboxView *vbox_view = (ECellVboxView *)ecell_view; + int max_width = 0; + int i; + + for (i = 0; i < vbox_view->subcell_view_count; i++) { + int width = e_cell_max_width (vbox_view->subcell_views[i], vbox_view->model_cols[i], view_col); + max_width = MAX(width, max_width); + } + + return max_width; +} + +#if 0 +/* + * ECellView::show_tooltip method + */ +static void +ecv_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, + int col_width, ETableTooltip *tooltip) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + EVboxModel *vbox_model = e_cell_vbox_get_vbox_model (ecell_view->e_table_model, row); + EVboxPath node = e_cell_vbox_get_node (ecell_view->e_table_model, row); + int offset = offset_of_node (ecell_view->e_table_model, row); + GdkPixbuf *node_image; + + node_image = e_vbox_model_icon_at (vbox_model, node); + if (node_image) + offset += gdk_pixbuf_get_width (node_image); + + tooltip->x += offset; + e_cell_show_tooltip (vbox_view->subcell_view, model_col, view_col, row, col_width - offset, tooltip); +} + +/* + * ECellView::get_bg_color method + */ +static char * +ecv_get_bg_color (ECellView *ecell_view, int row) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + + return e_cell_get_bg_color (vbox_view->subcell_views[0], row); +} + +/* + * ECellView::enter_edit method + */ +static void * +ecv_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) +{ + /* just defer to our subcell's view */ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + + return e_cell_enter_edit (vbox_view->subcell_view, model_col, view_col, row); +} + +/* + * ECellView::leave_edit method + */ +static void +ecv_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) +{ + /* just defer to our subcell's view */ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + + e_cell_leave_edit (vbox_view->subcell_view, model_col, view_col, row, edit_context); +} + +static void +ecv_print (ECellView *ecell_view, GnomePrintContext *context, + int model_col, int view_col, int row, + double width, double height) +{ + ECellVboxView *vbox_view = (ECellVboxView *) ecell_view; + + if (/* XXX only if we're the active sort */ TRUE) { + EVboxModel *vbox_model = e_cell_vbox_get_vbox_model (ecell_view->e_table_model, row); + EVboxTableAdapter *vbox_table_adapter = e_cell_vbox_get_vbox_table_adapter(ecell_view->e_table_model, row); + EVboxPath node = e_cell_vbox_get_node (ecell_view->e_table_model, row); + int offset = offset_of_node (ecell_view->e_table_model, row); + int subcell_offset = offset; + gboolean expandable = e_vbox_model_node_is_expandable (vbox_model, node); + gboolean expanded = e_vbox_table_adapter_node_is_expanded (vbox_table_adapter, node); + + /* draw our lines */ + if (E_CELL_VBOX(vbox_view->cell_view.ecell)->draw_lines) { + int depth; + + if (!e_vbox_model_node_is_root (vbox_model, node) + || e_vbox_model_node_get_children (vbox_model, node, NULL) > 0) { + gnome_print_moveto (context, + offset - INDENT_AMOUNT / 2, + height / 2); + + gnome_print_lineto (context, + offset, + height / 2); + } + + if (visible_depth_of_node (ecell_view->e_table_model, row) != 0) { + gnome_print_moveto (context, + offset - INDENT_AMOUNT / 2, + height); + gnome_print_lineto (context, + offset - INDENT_AMOUNT / 2, + (e_vbox_model_node_get_next (vbox_model, node) + ? 0 + : height / 2)); + } + + /* now traverse back up to the root of the vbox, checking at + each level if the node has siblings, and drawing the + correct vertical pipe for it's configuration. */ + node = e_vbox_model_node_get_parent (vbox_model, node); + depth = visible_depth_of_node (ecell_view->e_table_model, row) - 1; + offset -= INDENT_AMOUNT; + while (node && depth != 0) { + if (e_vbox_model_node_get_next(vbox_model, node)) { + gnome_print_moveto (context, + offset - INDENT_AMOUNT / 2, + height); + gnome_print_lineto (context, + offset - INDENT_AMOUNT / 2, + 0); + } + node = e_vbox_model_node_get_parent (vbox_model, node); + depth --; + offset -= INDENT_AMOUNT; + } + } + + /* now draw our icon if we're expandable */ + if (expandable) { + double image_matrix [6] = {16, 0, 0, 16, 0, 0}; + GdkPixbuf *image = (expanded + ? E_CELL_VBOX(vbox_view->cell_view.ecell)->open_pixbuf + : E_CELL_VBOX(vbox_view->cell_view.ecell)->closed_pixbuf); + int image_width, image_height, image_rowstride; + guchar *image_pixels; + + image_width = gdk_pixbuf_get_width(image); + image_height = gdk_pixbuf_get_height(image); + image_pixels = gdk_pixbuf_get_pixels(image); + image_rowstride = gdk_pixbuf_get_rowstride(image); + + image_matrix [4] = subcell_offset - INDENT_AMOUNT / 2 - image_width / 2; + image_matrix [5] = height / 2 - image_height / 2; + + gnome_print_gsave (context); + gnome_print_concat (context, image_matrix); + + gnome_print_rgbaimage (context, image_pixels, image_width, image_height, image_rowstride); + gnome_print_grestore (context); + } + + gnome_print_stroke (context); + + if (gnome_print_translate(context, subcell_offset, 0) == -1) + /* FIXME */; + width -= subcell_offset; + } + + + e_cell_print (vbox_view->subcell_view, context, model_col, view_col, row, width, height); +} + +static gdouble +ecv_print_height (ECellView *ecell_view, GnomePrintContext *context, + int model_col, int view_col, int row, + double width) +{ + return 12; /* XXX */ +} +#endif + +/* + * GtkObject::destroy method + */ +static void +ecv_destroy (GtkObject *object) +{ + ECellVbox *ecv = E_CELL_VBOX (object); + int i; + + /* destroy our subcell */ + for (i = 0; i < ecv->subcell_count; i++) + if (ecv->subcells[i]) + gtk_object_unref (GTK_OBJECT (ecv->subcells[i])); + g_free (ecv->subcells); + ecv->subcells = NULL; + ecv->subcell_count = 0; + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +e_cell_vbox_class_init (GtkObjectClass *object_class) +{ + ECellClass *ecc = (ECellClass *) object_class; + + object_class->destroy = ecv_destroy; + + ecc->new_view = ecv_new_view; + ecc->kill_view = ecv_kill_view; + ecc->realize = ecv_realize; + ecc->unrealize = ecv_unrealize; + ecc->draw = ecv_draw; + ecc->event = ecv_event; + ecc->height = ecv_height; +#if 0 + ecc->enter_edit = ecv_enter_edit; + ecc->leave_edit = ecv_leave_edit; + ecc->print = ecv_print; + ecc->print_height = ecv_print_height; +#endif + ecc->max_width = ecv_max_width; +#if 0 + ecc->show_tooltip = ecv_show_tooltip; + ecc->get_bg_color = ecv_get_bg_color; +#endif + + parent_class = gtk_type_class (PARENT_TYPE); +} + +static void +e_cell_vbox_init (GtkObject *object) +{ + ECellVbox *ecv = E_CELL_VBOX (object); + + ecv->subcells = NULL; + ecv->subcell_count = 0; +} + +E_MAKE_TYPE(e_cell_vbox, "ECellVbox", ECellVbox, e_cell_vbox_class_init, e_cell_vbox_init, PARENT_TYPE); + +/** + * e_cell_vbox_new: + * + * Creates a new ECell renderer that can be used to render multiple + * child cells. + * + * Return value: an ECell object that can be used to render multiple + * child cells. + **/ +ECell * +e_cell_vbox_new (void) +{ + ECellVbox *ecv = gtk_type_new (e_cell_vbox_get_type ()); + + return (ECell *) ecv; +} + +void +e_cell_vbox_append (ECellVbox *vbox, ECell *subcell, int model_col) +{ + vbox->subcell_count ++; + + vbox->subcells = g_renew (ECell *, vbox->subcells, vbox->subcell_count); + vbox->model_cols = g_renew (int, vbox->model_cols, vbox->subcell_count); + + vbox->subcells[vbox->subcell_count - 1] = subcell; + vbox->model_cols[vbox->subcell_count - 1] = model_col; + + if (subcell) + gtk_object_ref (GTK_OBJECT (subcell)); +} diff --git a/widgets/table/e-cell-vbox.h b/widgets/table/e-cell-vbox.h new file mode 100644 index 0000000000..c5207561f5 --- /dev/null +++ b/widgets/table/e-cell-vbox.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-cell-vbox.h - Vbox cell object. + * Copyright 1999 - 2002, Ximian, Inc. + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * Chris Lahey <clahey@ximina.com + * + * A majority of code taken from: + * + * the ECellText renderer. + * Copyright 1999, 2000, Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _E_CELL_VBOX_H_ +#define _E_CELL_VBOX_H_ + +#include <libgnomeui/gnome-canvas.h> +#include <gal/e-table/e-cell.h> +#include <libgnome/gnome-defs.h> + +BEGIN_GNOME_DECLS + +#define E_CELL_VBOX_TYPE (e_cell_vbox_get_type ()) +#define E_CELL_VBOX(o) (GTK_CHECK_CAST ((o), E_CELL_VBOX_TYPE, ECellVbox)) +#define E_CELL_VBOX_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_VBOX_TYPE, ECellVboxClass)) +#define E_IS_CELL_VBOX(o) (GTK_CHECK_TYPE ((o), E_CELL_VBOX_TYPE)) +#define E_IS_CELL_VBOX_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_VBOX_TYPE)) + +typedef struct { + ECell parent; + + int subcell_count; + ECell **subcells; + int *model_cols; +} ECellVbox; + +typedef struct { + ECellClass parent_class; +} ECellVboxClass; + +GtkType e_cell_vbox_get_type (void); +ECell *e_cell_vbox_new (void); +void e_cell_vbox_append (ECellVbox *vbox, + ECell *subcell, + int model_col); + + +END_GNOME_DECLS + +#endif /* _E_CELL_VBOX_H_ */ + + diff --git a/widgets/table/e-table-memory-store.c b/widgets/table/e-table-memory-store.c new file mode 100644 index 0000000000..e36a0e1558 --- /dev/null +++ b/widgets/table/e-table-memory-store.c @@ -0,0 +1,436 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-memory-store.c + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <string.h> +#include "e-table-memory-store.h" + +#define PARENT_TYPE e_table_memory_get_type () + +#define STORE_LOCATOR(etms, col, row) (*((etms)->priv->store + (row) * (etms)->priv->col_count + (col))) + +struct _ETableMemoryStorePrivate { + int col_count; + ETableMemoryStoreColumnInfo *columns; + void **store; +}; + +static void * +duplicate_value (ETableMemoryStore *etms, int col, const void *val) +{ + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (val); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF: + if (val) + gdk_pixbuf_ref ((void *) val); + return (void *) val; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT: + if (val) + gtk_object_ref ((void *) val); + return (void *) val; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.duplicate_value) + return etms->priv->columns[col].custom.duplicate_value (E_TABLE_MODEL (etms), col, val, NULL); + break; + default: + break; + } + return (void *) val; +} + +static int +etms_column_count (ETableModel *etm) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return etms->priv->col_count; +} + +static void * +etms_value_at (ETableModel *etm, int col, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return STORE_LOCATOR (etms, col, row); +} + +static void +etms_set_value_at (ETableModel *etm, int col, int row, const void *val) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + e_table_model_pre_change (etm); + + STORE_LOCATOR (etms, col, row) = duplicate_value (etms, col, val); + + e_table_model_cell_changed (etm, col, row); +} + +static gboolean +etms_is_cell_editable (ETableModel *etm, int col, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return etms->priv->columns[col].editable; +} + +/* The default for etms_duplicate_value is to return the raw value. */ +static void * +etms_duplicate_value (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return duplicate_value (etms, col, value); +} + +static void +etms_free_value (ETableModel *etm, int col, void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + g_free (value); + break; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF: + if (value) + gdk_pixbuf_unref (value); + break; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT: + if (value) + gtk_object_unref (value); + break; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.free_value) + etms->priv->columns[col].custom.free_value (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } +} + +static void * +etms_initialize_value (ETableModel *etm, int col) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (""); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF: + return NULL; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT: + if (etms->priv->columns[col].custom.initialize_value) + return etms->priv->columns[col].custom.initialize_value (E_TABLE_MODEL (etms), col, NULL); + break; + default: + break; + } + return 0; +} + +static gboolean +etms_value_is_empty (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return !(value && *(char *) value); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF: + return value == NULL; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT: + if (etms->priv->columns[col].custom.value_is_empty) + return etms->priv->columns[col].custom.value_is_empty (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } + return value == 0; +} + +static char * +etms_value_to_string (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (value); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF: + return g_strdup (""); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT: + if (etms->priv->columns[col].custom.value_is_empty) + return etms->priv->columns[col].custom.value_to_string (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } + return g_strdup_printf ("%d", GPOINTER_TO_INT (value)); +} + +static void +etms_append_row (ETableModel *etm, ETableModel *source, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + void **new_data; + int i; + int row_count; + + new_data = g_new (void *, etms->priv->col_count); + + for (i = 0; i < etms->priv->col_count; i++) { + new_data[i] = e_table_model_value_at (source, i, row); + } + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + + e_table_memory_store_insert_array (etms, row_count, new_data, NULL); +} + +static void +e_table_memory_store_init (ETableMemoryStore *etms) +{ + etms->priv = g_new (ETableMemoryStorePrivate, 1); + + etms->priv->col_count = 0; + etms->priv->columns = NULL; + etms->priv->store = NULL; +} + +static void +e_table_memory_store_class_init (GtkObjectClass *object_class) +{ + ETableModelClass *model_class = (ETableModelClass *) object_class; + + model_class->column_count = etms_column_count; + model_class->value_at = etms_value_at; + model_class->set_value_at = etms_set_value_at; + model_class->is_cell_editable = etms_is_cell_editable; + model_class->duplicate_value = etms_duplicate_value; + model_class->free_value = etms_free_value; + model_class->initialize_value = etms_initialize_value; + model_class->value_is_empty = etms_value_is_empty; + model_class->value_to_string = etms_value_to_string; + model_class->append_row = etms_append_row; +} + +GtkType +e_table_memory_store_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableMemoryStore", + sizeof (ETableMemoryStore), + sizeof (ETableMemoryStoreClass), + (GtkClassInitFunc) e_table_memory_store_class_init, + (GtkObjectInitFunc) e_table_memory_store_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +/** + * e_table_memory_store_new: + * @col_count: + * @value_at: + * @set_value_at: + * @is_cell_editable: + * @duplicate_value: + * @free_value: + * @initialize_value: + * @value_is_empty: + * @value_to_string: + * @data: closure pointer. + * + * This initializes a new ETableMemoryStoreModel object. ETableMemoryStoreModel is + * an implementaiton of the abstract class ETableModel. The ETableMemoryStoreModel + * is designed to allow people to easily create ETableModels without having + * to create a new GtkType derived from ETableModel every time they need one. + * + * Instead, ETableMemoryStoreModel uses a setup based in callback functions, every + * callback function signature mimics the signature of each ETableModel method + * and passes the extra @data pointer to each one of the method to provide them + * with any context they might want to use. + * + * Returns: An ETableMemoryStoreModel object (which is also an ETableModel + * object). + */ +ETableModel * +e_table_memory_store_new (ETableMemoryStoreColumnInfo *columns) +{ + ETableMemoryStore *et; + + et = gtk_type_new (e_table_memory_store_get_type ()); + + if (e_table_memory_store_construct (et, columns)) { + return (ETableModel *) et; + } else { + gtk_object_unref (GTK_OBJECT (et)); + return NULL; + } +} + +ETableModel * +e_table_memory_store_construct (ETableMemoryStore *etms, ETableMemoryStoreColumnInfo *columns) +{ + int i; + for (i = 0; columns[i].type != E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR; i++) + /* Intentionally blank */; + etms->priv->col_count = i; + + etms->priv->columns = g_new (ETableMemoryStoreColumnInfo, etms->priv->col_count + 1); + + memcpy (etms->priv->columns, columns, (etms->priv->col_count + 1) * sizeof (ETableMemoryStoreColumnInfo)); + + return E_TABLE_MODEL (etms); +} + + +void +e_table_memory_store_adopt_value_at (ETableMemoryStore *etms, int col, int row, void *value) +{ + e_table_model_pre_change (E_TABLE_MODEL (etms)); + + STORE_LOCATOR (etms, col, row) = value; + + e_table_model_cell_changed (E_TABLE_MODEL (etms), col, row); +} + +/* The size of these arrays is the number of columns. */ +void +e_table_memory_store_insert_array (ETableMemoryStore *etms, int row, void **store, gpointer data) +{ + int row_count; + int i; + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) + 1; + if (row == -1) + row = row_count - 1; + etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); + memmove (etms->priv->store + etms->priv->col_count * (row + 1), + etms->priv->store + etms->priv->col_count * row, + etms->priv->col_count * (row_count - row - 1) * sizeof (void *)); + + for (i = 0; i < etms->priv->col_count; i++) { + STORE_LOCATOR(etms, i, row) = duplicate_value(etms, i, store[i]); + } + + e_table_memory_insert (E_TABLE_MEMORY (etms), row, data); +} + +void +e_table_memory_store_insert (ETableMemoryStore *etms, int row, gpointer data, ...) +{ + void **store; + va_list args; + int i; + + store = g_new (void *, etms->priv->col_count + 1); + + va_start (args, data); + for (i = 0; i < etms->priv->col_count; i++) { + store[i] = va_arg (args, void *); + } + va_end (args); + + e_table_memory_store_insert_array (etms, row, store, data); + + g_free (store); +} + +void +e_table_memory_store_insert_adopt_array (ETableMemoryStore *etms, int row, void **store, gpointer data) +{ + int row_count; + int i; + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) + 1; + if (row == -1) + row = row_count - 1; + etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); + memmove (etms->priv->store + etms->priv->col_count * (row + 1), + etms->priv->store + etms->priv->col_count * row, + etms->priv->col_count * (row_count - row - 1) * sizeof (void *)); + + for (i = 0; i < etms->priv->col_count; i++) { + STORE_LOCATOR(etms, i, row) = store[i]; + } + + e_table_memory_insert (E_TABLE_MEMORY (etms), row, data); +} + +void +e_table_memory_store_insert_adopt (ETableMemoryStore *etms, int row, gpointer data, ...) +{ + void **store; + va_list args; + int i; + + store = g_new (void *, etms->priv->col_count + 1); + + va_start (args, data); + for (i = 0; i < etms->priv->col_count; i++) { + store[i] = va_arg (args, void *); + } + va_end (args); + + e_table_memory_store_insert_adopt_array (etms, row, store, data); + + g_free (store); +} + +void +e_table_memory_store_remove (ETableMemoryStore *etms, int row) +{ + int row_count; + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)) - 1; + memmove (etms->priv->store + etms->priv->col_count * row, + etms->priv->store + etms->priv->col_count * (row + 1), + etms->priv->col_count * (row_count - row) * sizeof (void *)); + etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); + + e_table_memory_remove (E_TABLE_MEMORY (etms), row); +} + +void +e_table_memory_store_clear (ETableMemoryStore *etms) +{ + e_table_memory_clear (E_TABLE_MEMORY (etms)); + + g_free (etms->priv->store); + etms->priv->store = NULL; +} diff --git a/widgets/table/e-table-memory-store.h b/widgets/table/e-table-memory-store.h new file mode 100644 index 0000000000..c4d7f2bfe3 --- /dev/null +++ b/widgets/table/e-table-memory-store.h @@ -0,0 +1,122 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-memory-store.h + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _E_TABLE_MEMORY_STORE_H_ +#define _E_TABLE_MEMORY_STORE_H_ + +#include <gal/e-table/e-table-memory.h> +#include <gal/e-table/e-table-memory-callbacks.h> +#include <libgnome/gnome-defs.h> + +BEGIN_GNOME_DECLS + +#define E_TABLE_MEMORY_STORE_TYPE (e_table_memory_store_get_type ()) +#define E_TABLE_MEMORY_STORE(o) (GTK_CHECK_CAST ((o), E_TABLE_MEMORY_STORE_TYPE, ETableMemoryStore)) +#define E_TABLE_MEMORY_STORE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_MEMORY_STORE_TYPE, ETableMemoryStoreClass)) +#define E_IS_TABLE_MEMORY_STORE(o) (GTK_CHECK_TYPE ((o), E_TABLE_MEMORY_STORE_TYPE)) +#define E_IS_TABLE_MEMORY_STORE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_MEMORY_STORE_TYPE)) + +typedef enum { + E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_INTEGER, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_OBJECT, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM +} ETableMemoryStoreColumnType; + +typedef struct { + ETableMemoryCalbacksDuplicateValueFn duplicate_value; + ETableMemoryCalbacksFreeValueFn free_value; + ETableMemoryCalbacksInitializeValueFn initialize_value; + ETableMemoryCalbacksValueIsEmptyFn value_is_empty; + ETableMemoryCalbacksValueToStringFn value_to_string; +} ETableMemoryStoreCustomColumn; + +typedef struct { + ETableMemoryStoreColumnType type; + ETableMemoryStoreCustomColumn custom; + guint editable : 1; +} ETableMemoryStoreColumnInfo; + +#define E_TABLE_MEMORY_STORE_TERMINATOR { E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_INTEGER { E_TABLE_MEMORY_STORE_COLUMN_TYPE_INTEGER, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_STRING { E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_PIXBUF { E_TABLE_MEMORY_STORE_COLUMN_TYPE_PIXBUF, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_EDITABLE_STRING { E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, { NULL }, TRUE } +#define E_TABLE_MEMORY_STORE_CUSTOM(editable, duplicate, free, initialize, empty, string) \ + { E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM, \ + { (duplicate), (free), (initialize), (empty), (string) }, editable } +#define E_TABLE_MEMORY_STORE_OBJECT(editable, initialize, empty, string) \ + { E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM, \ + { NULL, NULL, (initialize), (empty), (string) }, editable } + +typedef struct _ETableMemoryStorePrivate ETableMemoryStorePrivate; + +typedef struct { + ETableMemory parent; + + ETableMemoryStorePrivate *priv; +} ETableMemoryStore; + +typedef struct { + ETableMemoryClass parent_class; +} ETableMemoryStoreClass; + +GtkType e_table_memory_store_get_type (void); + +/* Object Creation */ +ETableModel *e_table_memory_store_new (ETableMemoryStoreColumnInfo *columns); +ETableModel *e_table_memory_store_construct (ETableMemoryStore *store, + ETableMemoryStoreColumnInfo *columns); + +/* Adopt a value instead of copying it. */ +void e_table_memory_store_adopt_value_at (ETableMemoryStore *etms, + int col, + int row, + void *value); + +/* The size of these arrays is the number of columns. */ +void e_table_memory_store_insert_array (ETableMemoryStore *etms, + int row, + void **store, + gpointer data); +void e_table_memory_store_insert (ETableMemoryStore *etms, + int row, + gpointer data, + ...); +void e_table_memory_store_insert_adopt (ETableMemoryStore *etms, + int row, + gpointer data, + ...); +void e_table_memory_store_insert_adopt_array (ETableMemoryStore *etms, + int row, + void **store, + gpointer data); +void e_table_memory_store_remove (ETableMemoryStore *etms, + int row); +void e_table_memory_store_clear (ETableMemoryStore *etms); + +END_GNOME_DECLS + +#endif /* _E_TABLE_MEMORY_STORE_H_ */ diff --git a/widgets/table/e-table-search.c b/widgets/table/e-table-search.c new file mode 100644 index 0000000000..dfc08c7cf8 --- /dev/null +++ b/widgets/table/e-table-search.c @@ -0,0 +1,251 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-search.c + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-search.h" +#include "gal/util/e-util.h" + +#include <string.h> + +#define ETS_CLASS(e) ((ETableSearchClass *)((GtkObject *)e)->klass) + +#define PARENT_TYPE gtk_object_get_type () + +#define d(x) + +d(static gint depth = 0); + +struct _ETableSearchPrivate { + guint timeout_id; + + char *search_string; + gunichar last_character; +}; + +static GtkObjectClass *e_table_search_parent_class; + +enum { + SEARCH_SEARCH, + SEARCH_ACCEPT, + LAST_SIGNAL +}; + +static guint e_table_search_signals [LAST_SIGNAL] = { 0, }; + +static gboolean +e_table_search_search (ETableSearch *e_table_search, char *string, ETableSearchFlags flags) +{ + gboolean ret_val; + g_return_val_if_fail (e_table_search != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_SEARCH (e_table_search), FALSE); + + gtk_signal_emit (GTK_OBJECT (e_table_search), + e_table_search_signals [SEARCH_SEARCH], string, flags, &ret_val); + + return ret_val; +} + +static void +e_table_search_accept (ETableSearch *e_table_search) +{ + g_return_if_fail (e_table_search != NULL); + g_return_if_fail (E_IS_TABLE_SEARCH (e_table_search)); + + gtk_signal_emit (GTK_OBJECT (e_table_search), + e_table_search_signals [SEARCH_ACCEPT]); +} + +static gboolean +ets_accept (gpointer data) +{ + ETableSearch *ets = data; + e_table_search_accept (ets); + g_free (ets->priv->search_string); + + ets->priv->timeout_id = 0; + ets->priv->search_string = g_strdup (""); + ets->priv->last_character = 0; + + return FALSE; +} + +static void +drop_timeout (ETableSearch *ets) +{ + if (ets->priv->timeout_id) { + g_source_remove (ets->priv->timeout_id); + } + ets->priv->timeout_id = 0; +} + +static void +add_timeout (ETableSearch *ets) +{ + drop_timeout (ets); + ets->priv->timeout_id = g_timeout_add (1000, ets_accept, ets); +} + +static void +e_table_search_destroy (GtkObject *object) +{ + ETableSearch *ets = (ETableSearch *) object; + + /* FIXME: do we need to unregister the timeout? bad things + might happen if a timeout is still active. */ + g_free (ets->priv->search_string); + g_free (ets->priv); + + if (e_table_search_parent_class->destroy) + (*e_table_search_parent_class->destroy)(object); +} + +static void +e_table_search_class_init (GtkObjectClass *object_class) +{ + ETableSearchClass *klass = E_TABLE_SEARCH_CLASS(object_class); + e_table_search_parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = e_table_search_destroy; + + e_table_search_signals [SEARCH_SEARCH] = + gtk_signal_new ("search", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (ETableSearchClass, search), + e_marshal_BOOL__STRING_ENUM, + GTK_TYPE_BOOL, 2, GTK_TYPE_STRING, GTK_TYPE_ENUM); + + e_table_search_signals [SEARCH_ACCEPT] = + gtk_signal_new ("accept", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (ETableSearchClass, accept), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + E_OBJECT_CLASS_ADD_SIGNALS (object_class, e_table_search_signals, LAST_SIGNAL); + + klass->search = NULL; + klass->accept = NULL; +} + +static void +e_table_search_init (ETableSearch *ets) +{ + ets->priv = g_new (ETableSearchPrivate, 1); + + ets->priv->timeout_id = 0; + ets->priv->search_string = g_strdup (""); + ets->priv->last_character = 0; +} + + +guint +e_table_search_get_type (void) +{ + static guint type = 0; + + if (!type) + { + GtkTypeInfo info = + { + "ETableSearch", + sizeof (ETableSearch), + sizeof (ETableSearchClass), + (GtkClassInitFunc) e_table_search_class_init, + (GtkObjectInitFunc) e_table_search_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +ETableSearch * +e_table_search_new (void) +{ + ETableSearch *ets = gtk_type_new (e_table_search_get_type()); + + return ets; +} + +/** + * e_table_search_column_count: + * @e_table_search: The e-table-search to operate on + * + * Returns: the number of columns in the table search. + */ +void +e_table_search_input_character (ETableSearch *ets, gunichar character) +{ + char character_utf8[7]; + char *temp_string; + + g_return_if_fail (ets != NULL); + g_return_if_fail (E_IS_TABLE_SEARCH (ets)); + + character_utf8 [g_unichar_to_utf8 (character, character_utf8)] = 0; + + temp_string = g_strdup_printf ("%s%s", ets->priv->search_string, character_utf8); + if (e_table_search_search (ets, temp_string, + ets->priv->last_character != 0 ? E_TABLE_SEARCH_FLAGS_CHECK_CURSOR_FIRST : 0)) { + g_free (ets->priv->search_string); + ets->priv->search_string = temp_string; + add_timeout (ets); + ets->priv->last_character = character; + return; + } else { + g_free (temp_string); + } + + if (character == ets->priv->last_character) { + if (ets->priv->search_string && e_table_search_search (ets, ets->priv->search_string, 0)) { + add_timeout (ets); + } + } +} + +gboolean +e_table_search_backspace (ETableSearch *ets) +{ + char *end; + + g_return_val_if_fail (ets != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_SEARCH (ets), FALSE); + + if (!ets->priv->search_string || + !*ets->priv->search_string) + return FALSE; + + end = ets->priv->search_string + strlen (ets->priv->search_string); + end = g_utf8_prev_char (end); + *end = 0; + ets->priv->last_character = 0; + add_timeout (ets); + return TRUE; +} diff --git a/widgets/table/e-table-search.h b/widgets/table/e-table-search.h new file mode 100644 index 0000000000..bd614206a0 --- /dev/null +++ b/widgets/table/e-table-search.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-search.h + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _E_TABLE_SEARCH_H_ +#define _E_TABLE_SEARCH_H_ + +#include <gtk/gtkobject.h> +#include <libgnome/gnome-defs.h> +#include <gal/unicode/gunicode.h> + +BEGIN_GNOME_DECLS + +#define E_TABLE_SEARCH_TYPE (e_table_search_get_type ()) +#define E_TABLE_SEARCH(o) (GTK_CHECK_CAST ((o), E_TABLE_SEARCH_TYPE, ETableSearch)) +#define E_TABLE_SEARCH_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SEARCH_TYPE, ETableSearchClass)) +#define E_IS_TABLE_SEARCH(o) (GTK_CHECK_TYPE ((o), E_TABLE_SEARCH_TYPE)) +#define E_IS_TABLE_SEARCH_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SEARCH_TYPE)) + +typedef struct _ETableSearchPrivate ETableSearchPrivate; + +typedef enum { + E_TABLE_SEARCH_FLAGS_CHECK_CURSOR_FIRST = 1 << 0 +} ETableSearchFlags; + +typedef struct { + GtkObject base; + + ETableSearchPrivate *priv; +} ETableSearch; + +typedef struct { + GtkObjectClass parent_class; + + /* + * Signals + */ + gboolean (*search) (ETableSearch *ets, char *string /* utf8 */, ETableSearchFlags flags); + void (*accept) (ETableSearch *ets); +} ETableSearchClass; + +GtkType e_table_search_get_type (void); +ETableSearch *e_table_search_new (void); + +/**/ +void e_table_search_input_character (ETableSearch *e_table_search, + gunichar character); +gboolean e_table_search_backspace (ETableSearch *e_table_search); +void e_table_search_cancel (ETableSearch *e_table_search); + +END_GNOME_DECLS + +#endif /* _E_TABLE_SEARCH_H_ */ |