diff options
Diffstat (limited to 'widgets/text/e-entry.c')
-rw-r--r-- | widgets/text/e-entry.c | 621 |
1 files changed, 529 insertions, 92 deletions
diff --git a/widgets/text/e-entry.c b/widgets/text/e-entry.c index cac7759f58..e9ff4bedf5 100644 --- a/widgets/text/e-entry.c +++ b/widgets/text/e-entry.c @@ -1,17 +1,39 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * EEntry: An EText-based entry widget + * + * Authors: + * Miguel de Icaza <miguel@helixcode.com> + * Chris Lahey <clahey@helixcode.com> + * Jon Trowbridge <trow@ximian.com> + * + * Copyright (C) 1999, 2000, 2001 Ximian Inc. + */ + /* - * E-table.c: A graphical view of a Table. + * This program 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. * - * Author: - * Miguel de Icaza (miguel@helixcode.com) - * Chris Lahey (clahey@helixcode.com) + * 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. * - * Copyright 1999, Helix Code, Inc + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ + #include <config.h> +#include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <ctype.h> #ifdef HAVE_ALLOCA_H #include <alloca.h> #endif @@ -22,6 +44,8 @@ #include "gal/util/e-util.h" #include "gal/widgets/e-canvas.h" #include "gal/widgets/e-canvas-utils.h" +#include "e-completion-view.h" +#include "e-text.h" #include "e-entry.h" #define MIN_ENTRY_WIDTH 150 @@ -68,21 +92,54 @@ enum { ARG_CURSOR_POS }; +typedef struct _EEntryPrivate EEntryPrivate; +struct _EEntryPrivate { + GnomeCanvas *canvas; + EText *item; + GtkJustification justification; + + guint changed_proxy_tag; + guint activate_proxy_tag; + + /* Data related to completions */ + ECompletion *completion; + EEntryCompletionHandler handler; + GtkWidget *completion_view; + guint nonempty_signal_id; + guint added_signal_id; + guint full_signal_id; + guint browse_signal_id; + guint unbrowse_signal_id; + guint activate_signal_id; + GtkWidget *completion_view_popup; + gboolean popup_is_visible; + gchar *pre_browse_text; + gint completion_delay; + guint completion_delay_tag; + + guint draw_borders : 1; +}; + +static gboolean e_entry_is_empty (EEntry *entry); +static void e_entry_show_popup (EEntry *entry, gboolean x); +static void e_entry_start_completion (EEntry *entry); +static void e_entry_start_delayed_completion (EEntry *entry, gint delay); +static void e_entry_cancel_delayed_completion (EEntry *entry); + static void canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, - EEntry *e_entry) + EEntry *entry) { gint xthick; gint ythick; - gnome_canvas_set_scroll_region ( - e_entry->canvas, - 0, 0, alloc->width, alloc->height); - gtk_object_set (GTK_OBJECT (e_entry->item), + gnome_canvas_set_scroll_region (entry->priv->canvas, + 0, 0, alloc->width, alloc->height); + gtk_object_set (GTK_OBJECT (entry->priv->item), "clip_width", (double) (alloc->width), "clip_height", (double) (alloc->height), NULL); - if (e_entry->draw_borders) { + if (entry->priv->draw_borders) { xthick = 0; ythick = 0; } else { @@ -90,22 +147,25 @@ canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ythick = widget->style->klass->ythickness; } - switch (e_entry->justification) { + switch (entry->priv->justification) { case GTK_JUSTIFY_RIGHT: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), alloc->width - xthick, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), + alloc->width - xthick, ythick); break; case GTK_JUSTIFY_CENTER: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), alloc->width / 2, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), + alloc->width / 2, ythick); break; default: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(e_entry->item), xthick, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), + xthick, ythick); break; } } static void canvas_size_request (GtkWidget *widget, GtkRequisition *requisition, - EEntry *ee) + EEntry *entry) { int border; @@ -113,7 +173,7 @@ canvas_size_request (GtkWidget *widget, GtkRequisition *requisition, g_return_if_fail (GNOME_IS_CANVAS (widget)); g_return_if_fail (requisition != NULL); - if (ee->draw_borders) + if (entry->priv->draw_borders) border = INNER_BORDER; else border = 0; @@ -125,65 +185,94 @@ canvas_size_request (GtkWidget *widget, GtkRequisition *requisition, } static gint -canvas_focus_in_event (GtkWidget *widget, GdkEventFocus *focus, EEntry *e_entry) +canvas_focus_in_event (GtkWidget *widget, GdkEventFocus *focus, EEntry *entry) { - if (e_entry->canvas->focused_item != GNOME_CANVAS_ITEM(e_entry->item)) - gnome_canvas_item_grab_focus(GNOME_CANVAS_ITEM(e_entry->item)); + if (entry->priv->canvas->focused_item != GNOME_CANVAS_ITEM(entry->priv->item)) + gnome_canvas_item_grab_focus(GNOME_CANVAS_ITEM(entry->priv->item)); return 0; } static void -e_entry_proxy_changed (EText *text, EEntry *ee) +e_entry_proxy_changed (EText *text, EEntry *entry) { - gtk_signal_emit (GTK_OBJECT (ee), e_entry_signals [E_ENTRY_CHANGED]); + if (e_entry_is_empty (entry)) { + e_entry_cancel_delayed_completion (entry); + e_entry_show_popup (entry, FALSE); + } else if (entry->priv->popup_is_visible) + e_entry_start_completion (entry); + else if (entry->priv->completion && entry->priv->completion_delay >= 0) + e_entry_start_delayed_completion (entry, entry->priv->completion_delay); + + gtk_signal_emit (GTK_OBJECT (entry), e_entry_signals [E_ENTRY_CHANGED]); } static void -e_entry_proxy_activate (EText *text, EEntry *ee) +e_entry_proxy_activate (EText *text, EEntry *entry) { - gtk_signal_emit (GTK_OBJECT (ee), e_entry_signals [E_ENTRY_ACTIVATE]); + gtk_signal_emit (GTK_OBJECT (entry), e_entry_signals [E_ENTRY_ACTIVATE]); } static void e_entry_init (GtkObject *object) { - EEntry *e_entry = E_ENTRY (object); + EEntry *entry = E_ENTRY (object); GtkTable *gtk_table = GTK_TABLE (object); + + entry->priv = g_new0 (EEntryPrivate, 1); - e_entry->canvas = GNOME_CANVAS(e_canvas_new()); - gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "size_allocate", - GTK_SIGNAL_FUNC(canvas_size_allocate), e_entry); - gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "size_request", - GTK_SIGNAL_FUNC(canvas_size_request), e_entry); - gtk_signal_connect(GTK_OBJECT(e_entry->canvas), "focus_in_event", - GTK_SIGNAL_FUNC(canvas_focus_in_event), e_entry); - e_entry->draw_borders = TRUE; - e_entry->item = E_TEXT(gnome_canvas_item_new(gnome_canvas_root(e_entry->canvas), - e_text_get_type(), - "clip", TRUE, - "fill_clip_rectangle", TRUE, - "anchor", GTK_ANCHOR_NW, - "draw_borders", TRUE, - "draw_background", TRUE, - NULL)); - e_entry->justification = GTK_JUSTIFY_LEFT; - gtk_table_attach(gtk_table, GTK_WIDGET(e_entry->canvas), - 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL | GTK_SHRINK, - GTK_EXPAND | GTK_FILL | GTK_SHRINK, - 0, 0); - gtk_widget_show(GTK_WIDGET(e_entry->canvas)); + entry->priv->canvas = GNOME_CANVAS (e_canvas_new ()); + + gtk_signal_connect (GTK_OBJECT (entry->priv->canvas), + "size_allocate", + GTK_SIGNAL_FUNC (canvas_size_allocate), + entry); + + gtk_signal_connect (GTK_OBJECT (entry->priv->canvas), + "size_request", + GTK_SIGNAL_FUNC (canvas_size_request), + entry); + + gtk_signal_connect(GTK_OBJECT (entry->priv->canvas), + "focus_in_event", + GTK_SIGNAL_FUNC(canvas_focus_in_event), + entry); + + entry->priv->draw_borders = TRUE; + + entry->priv->item = E_TEXT(gnome_canvas_item_new(gnome_canvas_root (entry->priv->canvas), + e_text_get_type(), + "clip", TRUE, + "fill_clip_rectangle", TRUE, + "anchor", GTK_ANCHOR_NW, + "draw_borders", TRUE, + "draw_background", TRUE, + "max_lines", 1, + "editable", TRUE, + NULL)); + + entry->priv->justification = GTK_JUSTIFY_LEFT; + gtk_table_attach (gtk_table, GTK_WIDGET (entry->priv->canvas), + 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL | GTK_SHRINK, + GTK_EXPAND | GTK_FILL | GTK_SHRINK, + 0, 0); + gtk_widget_show (GTK_WIDGET (entry->priv->canvas)); /* * Proxy functions: we proxy the changed and activate signals * from the item to outselves */ - gtk_signal_connect (GTK_OBJECT (e_entry->item), "changed", - GTK_SIGNAL_FUNC (e_entry_proxy_changed), e_entry); - gtk_signal_connect (GTK_OBJECT (e_entry->item), "activate", - GTK_SIGNAL_FUNC (e_entry_proxy_activate), e_entry); - + entry->priv->changed_proxy_tag = gtk_signal_connect (GTK_OBJECT (entry->priv->item), + "changed", + GTK_SIGNAL_FUNC (e_entry_proxy_changed), + entry); + entry->priv->activate_proxy_tag = gtk_signal_connect (GTK_OBJECT (entry->priv->item), + "activate", + GTK_SIGNAL_FUNC (e_entry_proxy_activate), + entry); + + entry->priv->completion_delay = -1; } /** @@ -191,12 +280,11 @@ e_entry_init (GtkObject *object) * * Constructs the given EEntry. * - * Returns: The EEntry **/ -EEntry * -e_entry_construct (EEntry *e_entry) +void +e_entry_construct (EEntry *entry) { - return e_entry; + /* Do nothing */ } @@ -210,18 +298,349 @@ e_entry_construct (EEntry *e_entry) GtkWidget * e_entry_new (void) { - EEntry *e_entry; - e_entry = gtk_type_new (e_entry_get_type ()); - e_entry = e_entry_construct (e_entry); + EEntry *entry; + entry = gtk_type_new (e_entry_get_type ()); + e_entry_construct (entry); + + return GTK_WIDGET (entry); +} + +const gchar * +e_entry_get_text (EEntry *entry) +{ + g_return_val_if_fail (entry != NULL && E_IS_ENTRY (entry), NULL); + + return e_text_model_get_text (entry->priv->item->model); +} + +void +e_entry_set_text (EEntry *entry, const gchar *txt) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + + e_text_model_set_text (entry->priv->item->model, txt); +} + +static void +e_entry_set_text_quiet (EEntry *entry, const gchar *txt) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + + gtk_signal_handler_block (GTK_OBJECT (entry->priv->item), entry->priv->changed_proxy_tag); + e_entry_set_text (entry, txt); + gtk_signal_handler_unblock (GTK_OBJECT (entry->priv->item), entry->priv->changed_proxy_tag); +} + + +void +e_entry_set_editable (EEntry *entry, gboolean am_i_editable) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + + gtk_object_set (GTK_OBJECT (entry->priv->item), "editable", am_i_editable, NULL); +} + +gint +e_entry_get_position (EEntry *entry) +{ + g_return_val_if_fail (entry != NULL && E_IS_ENTRY (entry), -1); + + return entry->priv->item->selection_start; +} + +void +e_entry_set_position (EEntry *entry, gint pos) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + if (pos < 0) + pos = 0; + else if (pos > e_text_model_get_text_length (entry->priv->item->model)) + pos = e_text_model_get_text_length (entry->priv->item->model); + + entry->priv->item->selection_start = pos; +} + +void +e_entry_select_region (EEntry *entry, gint pos1, gint pos2) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + + e_entry_set_position (entry, MAX (pos1, pos2)); + entry->priv->item->selection_end = entry->priv->item->selection_start; + e_entry_set_position (entry, MIN (pos1, pos2)); +} + +/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ + +/*** Completion-related code ***/ + +static gboolean +e_entry_is_empty (EEntry *entry) +{ + const gchar *txt = e_entry_get_text (entry); + + if (txt == NULL) + return TRUE; + + while (*txt) { + if (!isspace ((gint) *txt)) + return FALSE; + ++txt; + } + + return TRUE; +} + +static void +e_entry_show_popup (EEntry *entry, gboolean visible) +{ + GtkWidget *pop = entry->priv->completion_view_popup; + + if (pop == NULL) + return; + + if (visible) { + GtkAllocation *dim = &(GTK_WIDGET (entry)->allocation); + gint x, y; + + /* Figure out where to put our popup. */ + gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y); + x += dim->x; + y += dim->height + dim->y; + + gtk_widget_set_uposition (pop, x, y); + e_completion_view_set_width (E_COMPLETION_VIEW (entry->priv->completion_view), dim->width); + + gtk_widget_show (pop); + + } else { + + gtk_widget_hide (pop); + + } + + e_completion_view_set_editable (E_COMPLETION_VIEW (entry->priv->completion_view), visible); + entry->priv->popup_is_visible = visible; +} + +static void +e_entry_refresh_popup (EEntry *entry) +{ + if (entry->priv->popup_is_visible) + e_entry_show_popup (entry, TRUE); +} + +static void +e_entry_start_completion (EEntry *entry) +{ + if (entry->priv->completion == NULL) + return; + + e_entry_cancel_delayed_completion (entry); + + if (e_entry_is_empty (entry)) + return; + + if (entry->priv->completion) + e_completion_begin_search (entry->priv->completion, + e_entry_get_text (entry), + e_entry_get_position (entry), + 0); /* No limit. Probably a bad idea. */ +} + +static gboolean +start_delayed_cb (gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + entry->priv->completion_delay_tag = 0; + e_entry_start_completion (entry); + return FALSE; +} + +static void +e_entry_start_delayed_completion (EEntry *entry, gint delay) +{ + if (delay < 0) + return; + + e_entry_cancel_delayed_completion (entry); + + if (delay == 0) + e_entry_start_completion (entry); + else + entry->priv->completion_delay_tag = gtk_timeout_add (delay, start_delayed_cb, entry); +} + +static void +e_entry_cancel_delayed_completion (EEntry *entry) +{ + if (entry->priv->completion == NULL) + return; + + e_completion_cancel_search (entry->priv->completion); /* just to be sure... */ + if (entry->priv->completion_delay_tag) { + gtk_timeout_remove (entry->priv->completion_delay_tag); + entry->priv->completion_delay_tag = 0; + } +} + +static void +nonempty_cb (ECompletionView *view, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + + e_entry_show_popup (entry, TRUE); +} + +static void +added_cb (ECompletionView *view, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + e_entry_refresh_popup (entry); +} + +static void +full_cb (ECompletionView *view, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + + e_entry_show_popup (entry, view->choice_count > 0); +} + +static void +browse_cb (ECompletionView *view, const gchar *txt, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + + if (txt == NULL) { + /* Requesting a completion. */ + e_entry_start_completion (entry); + return; + } + + if (entry->priv->pre_browse_text == NULL) + entry->priv->pre_browse_text = g_strdup (e_entry_get_text (entry)); + + /* If there is no other handler in place, echo the selected completion in + the entry. */ + if (entry->priv->handler == NULL) + e_entry_set_text_quiet (entry, txt); +} + +static void +unbrowse_cb (ECompletionView *view, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + + if (entry->priv->pre_browse_text) { + + if (entry->priv->handler == NULL) + e_entry_set_text_quiet (entry, entry->priv->pre_browse_text); + + g_free (entry->priv->pre_browse_text); + entry->priv->pre_browse_text = NULL; + } + + e_entry_show_popup (entry, FALSE); +} + +static void +activate_cb (ECompletionView *view, const gchar *txt, gpointer extra_data, gpointer user_data) +{ + EEntry *entry = E_ENTRY (user_data); + + e_entry_cancel_delayed_completion (entry); + + g_free (entry->priv->pre_browse_text); + entry->priv->pre_browse_text = NULL; + e_entry_show_popup (entry, FALSE); + + if (entry->priv->handler) + entry->priv->handler (entry, txt, extra_data); + else + e_entry_set_text (entry, txt); + + e_entry_cancel_delayed_completion (entry); +} + +void +e_entry_enable_completion (EEntry *entry, ECompletion *completion) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + g_return_if_fail (completion != NULL && E_IS_COMPLETION (completion)); + + e_entry_enable_completion_full (entry, completion, -1, NULL); +} + +void +e_entry_enable_completion_full (EEntry *entry, ECompletion *completion, gint delay, EEntryCompletionHandler handler) +{ + g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); + g_return_if_fail (completion != NULL && E_IS_COMPLETION (completion)); + + /* For now, completion can't be changed mid-stream. */ + g_return_if_fail (entry->priv->completion == NULL); - return GTK_WIDGET (e_entry); + entry->priv->completion = completion; + gtk_object_ref (GTK_OBJECT (completion)); + gtk_object_sink (GTK_OBJECT (completion)); + + entry->priv->completion_delay = delay; + entry->priv->handler = handler; + + entry->priv->completion_view = e_completion_view_new (completion); + /* Make the up and down keys enable and disable completions. */ + e_completion_view_set_complete_key (E_COMPLETION_VIEW (entry->priv->completion_view), GDK_Down); + e_completion_view_set_uncomplete_key (E_COMPLETION_VIEW (entry->priv->completion_view), GDK_Up); + + entry->priv->nonempty_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "nonempty", + GTK_SIGNAL_FUNC (nonempty_cb), + entry); + + entry->priv->added_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "added", + GTK_SIGNAL_FUNC (added_cb), + entry); + + entry->priv->full_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "full", + GTK_SIGNAL_FUNC (full_cb), + entry); + + entry->priv->browse_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "browse", + GTK_SIGNAL_FUNC (browse_cb), + entry); + + entry->priv->unbrowse_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "unbrowse", + GTK_SIGNAL_FUNC (unbrowse_cb), + entry); + + entry->priv->activate_signal_id = gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + entry); + + entry->priv->completion_view_popup = gtk_window_new (GTK_WINDOW_POPUP); + gtk_object_ref (GTK_OBJECT (entry->priv->completion_view_popup)); + gtk_object_sink (GTK_OBJECT (entry->priv->completion_view_popup)); + gtk_window_set_policy (GTK_WINDOW (entry->priv->completion_view_popup), FALSE, TRUE, FALSE); + gtk_container_add (GTK_CONTAINER (entry->priv->completion_view_popup), entry->priv->completion_view); + gtk_widget_show (entry->priv->completion_view); + + e_completion_view_connect_keys (E_COMPLETION_VIEW (entry->priv->completion_view), GTK_WIDGET (entry->priv->canvas)); } + +/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ + static void et_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) { - EEntry *ee = E_ENTRY (o); - GtkObject *item = GTK_OBJECT (ee->item); + EEntry *entry = E_ENTRY (o); + GtkObject *item = GTK_OBJECT (entry->priv->item); switch (arg_id){ case ARG_MODEL: @@ -314,7 +733,7 @@ et_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) break; case ARG_DRAW_BORDERS: - GTK_VALUE_BOOL (*arg) = ee->draw_borders; + GTK_VALUE_BOOL (*arg) = entry->priv->draw_borders; break; case ARG_DRAW_BACKGROUND: @@ -337,13 +756,13 @@ et_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) static void et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) { - EEntry *ee = E_ENTRY (o); - GtkObject *item = GTK_OBJECT (ee->item); + EEntry *entry = E_ENTRY (o); + GtkObject *item = GTK_OBJECT (entry->priv->item); GtkAnchorType anchor; double width, height; gint xthick; gint ythick; - GtkWidget *widget = GTK_WIDGET(ee->canvas); + GtkWidget *widget = GTK_WIDGET(entry->priv->canvas); switch (arg_id){ case ARG_MODEL: @@ -384,13 +803,13 @@ et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) break; case ARG_JUSTIFICATION: - ee->justification = GTK_VALUE_ENUM (*arg); + entry->priv->justification = GTK_VALUE_ENUM (*arg); gtk_object_get(item, "clip_width", &width, "clip_height", &height, NULL); - if (ee->draw_borders) { + if (entry->priv->draw_borders) { xthick = 0; ythick = 0; } else { @@ -398,22 +817,22 @@ et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) ythick = widget->style->klass->ythickness; } - switch (ee->justification) { + switch (entry->priv->justification) { case GTK_JUSTIFY_CENTER: anchor = GTK_ANCHOR_N; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), width / 2, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), width / 2, ythick); break; case GTK_JUSTIFY_RIGHT: anchor = GTK_ANCHOR_NE; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), width - xthick, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), width - xthick, ythick); break; default: anchor = GTK_ANCHOR_NW; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(ee->item), xthick, ythick); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->priv->item), xthick, ythick); break; } gtk_object_set(item, - "justification", ee->justification, + "justification", entry->priv->justification, "anchor", anchor, NULL); break; @@ -487,11 +906,11 @@ et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) case ARG_DRAW_BORDERS: { gboolean need_queue; - need_queue = (ee->draw_borders ^ GTK_VALUE_BOOL (*arg)); + need_queue = (entry->priv->draw_borders ^ GTK_VALUE_BOOL (*arg)); gtk_object_set (item, "draw_borders", GTK_VALUE_BOOL (*arg), NULL); - ee->draw_borders = GTK_VALUE_BOOL (*arg); + entry->priv->draw_borders = GTK_VALUE_BOOL (*arg); if (need_queue) - gtk_widget_queue_resize (GTK_WIDGET (ee)); + gtk_widget_queue_resize (GTK_WIDGET (entry)); break; } @@ -508,32 +927,50 @@ et_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) } static void +e_entry_destroy (GtkObject *object) +{ + EEntry *entry = E_ENTRY (object); + + if (entry->priv->completion_delay_tag) + gtk_timeout_remove (entry->priv->completion_delay_tag); + + if (entry->priv->completion) + gtk_object_unref (GTK_OBJECT (entry->priv->completion)); + if (entry->priv->completion_view_popup) + gtk_widget_destroy (entry->priv->completion_view_popup); + g_free (entry->priv->pre_browse_text); + + g_free (entry->priv); + entry->priv = NULL; +} + +static void e_entry_class_init (GtkObjectClass *object_class) { EEntryClass *klass = E_ENTRY_CLASS(object_class); + parent_class = gtk_type_class (PARENT_TYPE); object_class->set_arg = et_set_arg; object_class->get_arg = et_get_arg; + object_class->destroy = e_entry_destroy; klass->changed = NULL; klass->activate = NULL; - e_entry_signals[E_ENTRY_CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EEntryClass, changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - e_entry_signals[E_ENTRY_ACTIVATE] = - gtk_signal_new ("activate", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EEntryClass, activate), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); + e_entry_signals[E_ENTRY_CHANGED] = gtk_signal_new ("changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EEntryClass, changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + e_entry_signals[E_ENTRY_ACTIVATE] = gtk_signal_new ("activate", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EEntryClass, activate), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, e_entry_signals, E_ENTRY_LAST_SIGNAL); |