00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "config.h"
00037
00038 #include <gnome.h>
00039 #include <string.h>
00040
00041 #include "QuickFill.h"
00042 #include "combocell.h"
00043 #include "gnc-gconf-utils.h"
00044 #include "gnucash-item-edit.h"
00045 #include "gnucash-item-list.h"
00046 #include "gnucash-sheet.h"
00047 #include "table-allgui.h"
00048
00049 #define KEY_AUTO_RAISE_LISTS "auto_raise_lists"
00050
00051 typedef struct _PopBox
00052 {
00053 GnucashSheet *sheet;
00054 GncItemEdit *item_edit;
00055 GncItemList *item_list;
00056 GtkListStore *tmp_store;
00057
00058 gboolean signals_connected;
00059
00060 gboolean list_popped;
00061
00062 gboolean autosize;
00063
00064 QuickFill *qf;
00065 gboolean use_quickfill_cache;
00066
00067 gboolean in_list_select;
00068
00069 gboolean strict;
00070
00071 gunichar complete_char;
00072
00073 GList *ignore_strings;
00074 } PopBox;
00075
00076
00077 static void gnc_combo_cell_gui_realize (BasicCell *bcell, gpointer w);
00078 static void gnc_combo_cell_gui_move (BasicCell *bcell);
00079 static void gnc_combo_cell_gui_destroy (BasicCell *bcell);
00080 static gboolean gnc_combo_cell_enter (BasicCell *bcell,
00081 int *cursor_position,
00082 int *start_selection,
00083 int *end_selection);
00084 static void gnc_combo_cell_leave (BasicCell *bcell);
00085 static void gnc_combo_cell_destroy (BasicCell *bcell);
00086
00087 static GOnce auto_pop_init_once = G_ONCE_INIT;
00088 static gboolean auto_pop_combos = FALSE;
00089
00090
00091 static void
00092 gnc_combo_cell_set_autopop (GConfEntry *entry, gpointer user_data)
00093 {
00094 GConfValue *value;
00095
00096 value = gconf_entry_get_value(entry);
00097 auto_pop_combos = gconf_value_get_bool(value);
00098 }
00099
00100 static gpointer
00101 gnc_combo_cell_autopop_init (gpointer unused)
00102 {
00103 auto_pop_combos = gnc_gconf_get_bool (GCONF_GENERAL_REGISTER,
00104 KEY_AUTO_RAISE_LISTS,
00105 NULL);
00106
00107 gnc_gconf_general_register_cb(KEY_AUTO_RAISE_LISTS,
00108 gnc_combo_cell_set_autopop,
00109 NULL);
00110 return NULL;
00111 }
00112
00113 BasicCell *
00114 gnc_combo_cell_new (void)
00115 {
00116 ComboCell * cell;
00117
00118 g_once(&auto_pop_init_once, gnc_combo_cell_autopop_init, NULL);
00119
00120 cell = g_new0 (ComboCell, 1);
00121
00122 gnc_combo_cell_init (cell);
00123
00124 return &cell->cell;
00125 }
00126
00127 void
00128 gnc_combo_cell_init (ComboCell *cell)
00129 {
00130 PopBox *box;
00131
00132 gnc_basic_cell_init (&(cell->cell));
00133
00134 cell->cell.is_popup = TRUE;
00135
00136 cell->cell.destroy = gnc_combo_cell_destroy;
00137
00138 cell->cell.gui_realize = gnc_combo_cell_gui_realize;
00139 cell->cell.gui_destroy = gnc_combo_cell_gui_destroy;
00140
00141 box = g_new0 (PopBox, 1);
00142
00143 box->sheet = NULL;
00144 box->item_edit = NULL;
00145 box->item_list = NULL;
00146 box->tmp_store = gtk_list_store_new (1, G_TYPE_STRING);
00147 box->signals_connected = FALSE;
00148 box->list_popped = FALSE;
00149 box->autosize = FALSE;
00150
00151 cell->cell.gui_private = box;
00152
00153 box->qf = gnc_quickfill_new ();
00154 box->use_quickfill_cache = FALSE;
00155
00156 box->in_list_select = FALSE;
00157
00158 box->strict = TRUE;
00159
00160 box->complete_char = '\0';
00161
00162 box->ignore_strings = NULL;
00163 }
00164
00165 static void
00166 select_item_cb (GncItemList *item_list, char *item_string, gpointer data)
00167 {
00168 ComboCell *cell = data;
00169 PopBox *box = cell->cell.gui_private;
00170
00171 box->in_list_select = TRUE;
00172 gnucash_sheet_modify_current_cell (box->sheet, item_string);
00173 box->in_list_select = FALSE;
00174
00175 gnc_item_edit_hide_popup (box->item_edit);
00176 box->list_popped = FALSE;
00177 }
00178
00179 static void
00180 change_item_cb (GncItemList *item_list, char *item_string, gpointer data)
00181 {
00182 ComboCell *cell = data;
00183 PopBox *box = cell->cell.gui_private;
00184
00185 box->in_list_select = TRUE;
00186 gnucash_sheet_modify_current_cell (box->sheet, item_string);
00187 box->in_list_select = FALSE;
00188 }
00189
00190 static void
00191 activate_item_cb (GncItemList *item_list, char *item_string, gpointer data)
00192 {
00193 ComboCell *cell = data;
00194 PopBox *box = cell->cell.gui_private;
00195
00196 gnc_item_edit_hide_popup (box->item_edit);
00197 box->list_popped = FALSE;
00198 }
00199
00200 static void
00201 key_press_item_cb (GncItemList *item_list, GdkEventKey *event, gpointer data)
00202 {
00203 ComboCell *cell = data;
00204 PopBox *box = cell->cell.gui_private;
00205
00206 switch (event->keyval)
00207 {
00208 case GDK_Escape:
00209 gnc_item_edit_hide_popup (box->item_edit);
00210 box->list_popped = FALSE;
00211 break;
00212
00213 default:
00214 gtk_widget_event (GTK_WIDGET(box->sheet),
00215 (GdkEvent *) event);
00216 break;
00217 }
00218 }
00219
00220 static void
00221 combo_disconnect_signals (ComboCell *cell)
00222 {
00223 PopBox *box = cell->cell.gui_private;
00224
00225 if (!box->signals_connected)
00226 return;
00227
00228 g_signal_handlers_disconnect_matched (G_OBJECT (box->item_list), G_SIGNAL_MATCH_DATA,
00229 0, 0, NULL, NULL, cell);
00230
00231 box->signals_connected = FALSE;
00232 }
00233
00234 static void
00235 combo_connect_signals (ComboCell *cell)
00236 {
00237 PopBox *box = cell->cell.gui_private;
00238
00239 if (box->signals_connected)
00240 return;
00241
00242 g_signal_connect (G_OBJECT (box->item_list), "select_item",
00243 G_CALLBACK (select_item_cb), cell);
00244
00245 g_signal_connect (G_OBJECT (box->item_list), "change_item",
00246 G_CALLBACK (change_item_cb), cell);
00247
00248 g_signal_connect (G_OBJECT (box->item_list), "activate_item",
00249 G_CALLBACK (activate_item_cb), cell);
00250
00251 g_signal_connect (G_OBJECT (box->item_list), "key_press_event",
00252 G_CALLBACK (key_press_item_cb), cell);
00253
00254 box->signals_connected = TRUE;
00255 }
00256
00257 static void
00258 block_list_signals (ComboCell *cell)
00259 {
00260 PopBox *box = cell->cell.gui_private;
00261
00262 if (!box->signals_connected)
00263 return;
00264
00265 g_signal_handlers_block_matched (G_OBJECT (box->item_list), G_SIGNAL_MATCH_DATA,
00266 0, 0, NULL, NULL, cell);
00267 }
00268
00269 static void
00270 unblock_list_signals (ComboCell *cell)
00271 {
00272 PopBox *box = cell->cell.gui_private;
00273
00274 if (!box->signals_connected)
00275 return;
00276
00277 g_signal_handlers_unblock_matched (G_OBJECT (box->item_list), G_SIGNAL_MATCH_DATA,
00278 0, 0, NULL, NULL, cell);
00279 }
00280
00281 static void
00282 gnc_combo_cell_gui_destroy (BasicCell *bcell)
00283 {
00284 PopBox *box = bcell->gui_private;
00285 ComboCell *cell = (ComboCell *) bcell;
00286
00287 if (cell->cell.gui_realize == NULL)
00288 {
00289 if (box != NULL && box->item_list != NULL)
00290 {
00291 combo_disconnect_signals(cell);
00292 g_object_unref (box->item_list);
00293 box->item_list = NULL;
00294 }
00295
00296
00297 cell->cell.gui_realize = gnc_combo_cell_gui_realize;
00298 cell->cell.gui_move = NULL;
00299 cell->cell.enter_cell = NULL;
00300 cell->cell.leave_cell = NULL;
00301 cell->cell.gui_destroy = NULL;
00302 }
00303 }
00304
00305 static void
00306 gnc_combo_cell_destroy (BasicCell *bcell)
00307 {
00308 ComboCell *cell = (ComboCell *) bcell;
00309 PopBox *box = cell->cell.gui_private;
00310
00311 gnc_combo_cell_gui_destroy (&(cell->cell));
00312
00313 if (box != NULL)
00314 {
00315 GList *node;
00316
00317
00318 if (FALSE == box->use_quickfill_cache)
00319 {
00320 gnc_quickfill_destroy (box->qf);
00321 box->qf = NULL;
00322 }
00323
00324 for (node = box->ignore_strings; node; node = node->next)
00325 {
00326 g_free (node->data);
00327 node->data = NULL;
00328 }
00329
00330 g_list_free (box->ignore_strings);
00331 box->ignore_strings = NULL;
00332
00333 g_free (box);
00334 cell->cell.gui_private = NULL;
00335 }
00336
00337 cell->cell.gui_private = NULL;
00338 cell->cell.gui_realize = NULL;
00339 }
00340
00341 void
00342 gnc_combo_cell_set_sort_enabled (ComboCell *cell, gboolean enabled)
00343 {
00344 PopBox *box;
00345
00346 if (cell == NULL)
00347 return;
00348
00349 box = cell->cell.gui_private;
00350 if (box->item_list == NULL)
00351 return;
00352
00353 block_list_signals (cell);
00354 gnc_item_list_set_sort_enabled(box->item_list, enabled);
00355 unblock_list_signals (cell);
00356 }
00357
00358 void
00359 gnc_combo_cell_clear_menu (ComboCell * cell)
00360 {
00361 PopBox *box;
00362
00363 if (cell == NULL)
00364 return;
00365
00366 box = cell->cell.gui_private;
00367 if (box == NULL)
00368 return;
00369
00370
00371 if (FALSE == box->use_quickfill_cache)
00372 {
00373 gnc_quickfill_destroy (box->qf);
00374 box->qf = gnc_quickfill_new ();
00375 }
00376
00377 if (box->item_list != NULL)
00378 {
00379 block_list_signals (cell);
00380
00381 gnc_item_list_clear (box->item_list);
00382
00383 unblock_list_signals (cell);
00384 }
00385 }
00386
00387 void
00388 gnc_combo_cell_use_quickfill_cache (ComboCell * cell, QuickFill *shared_qf)
00389 {
00390 PopBox *box;
00391
00392 if (cell == NULL) return;
00393
00394 box = cell->cell.gui_private;
00395 if (NULL == box) return;
00396
00397 if (FALSE == box->use_quickfill_cache)
00398 {
00399 box->use_quickfill_cache = TRUE;
00400 gnc_quickfill_destroy (box->qf);
00401 }
00402 box->qf = shared_qf;
00403 }
00404
00405 void
00406 gnc_combo_cell_use_list_store_cache (ComboCell * cell, gpointer data)
00407 {
00408 if (cell == NULL) return;
00409
00410 cell->shared_store = data;
00411 }
00412
00413 void
00414 gnc_combo_cell_add_menu_item (ComboCell *cell, const char * menustr)
00415 {
00416 PopBox *box;
00417
00418 if (cell == NULL)
00419 return;
00420 if (menustr == NULL)
00421 return;
00422
00423 box = cell->cell.gui_private;
00424
00425 if (box->item_list != NULL)
00426 {
00427 block_list_signals (cell);
00428
00429 gnc_item_list_append (box->item_list, menustr);
00430 if (cell->cell.value &&
00431 (strcmp (menustr, cell->cell.value) == 0))
00432 gnc_item_list_select (box->item_list, menustr);
00433
00434 unblock_list_signals (cell);
00435 }
00436 else
00437 {
00438 GtkTreeIter iter;
00439
00440 gtk_list_store_append(box->tmp_store, &iter);
00441 gtk_list_store_set(box->tmp_store, &iter, 0, menustr, -1);
00442 }
00443
00444
00445
00446 if (FALSE == box->use_quickfill_cache)
00447 {
00448 gnc_quickfill_insert (box->qf, menustr, QUICKFILL_ALPHA);
00449 }
00450 }
00451
00452 void
00453 gnc_combo_cell_add_account_menu_item (ComboCell *cell, char * menustr)
00454 {
00455 PopBox *box;
00456 gchar *menu_copy, *value_copy;
00457
00458 if (cell == NULL)
00459 return;
00460 if (menustr == NULL)
00461 return;
00462
00463 box = cell->cell.gui_private;
00464
00465 if (box->item_list != NULL)
00466 {
00467 block_list_signals (cell);
00468
00469 gnc_item_list_append (box->item_list, menustr);
00470 if (cell->cell.value)
00471 {
00472 menu_copy = g_strdelimit(g_strdup(menustr), "-:/\\.", ' ');
00473 value_copy =
00474 g_strdelimit(g_strdup(cell->cell.value), "-:/\\.", ' ');
00475 if (strcmp (menu_copy, value_copy) == 0)
00476 {
00477 gnc_combo_cell_set_value (cell, menustr);
00478 gnc_item_list_select (box->item_list, menustr);
00479 }
00480 g_free(value_copy);
00481 g_free(menu_copy);
00482 }
00483 unblock_list_signals (cell);
00484 }
00485
00486
00487
00488 if (FALSE == box->use_quickfill_cache)
00489 {
00490 gnc_quickfill_insert (box->qf, menustr, QUICKFILL_ALPHA);
00491 }
00492 }
00493
00494 void
00495 gnc_combo_cell_set_value (ComboCell *cell, const char *str)
00496 {
00497 gnc_basic_cell_set_value (&cell->cell, str);
00498 }
00499
00500 static void
00501 gnc_combo_cell_modify_verify (BasicCell *_cell,
00502 const char *change,
00503 int change_len,
00504 const char *newval,
00505 int newval_len,
00506 int *cursor_position,
00507 int *start_selection,
00508 int *end_selection)
00509 {
00510 ComboCell *cell = (ComboCell *) _cell;
00511 PopBox *box = cell->cell.gui_private;
00512 const char *match_str;
00513 QuickFill *match;
00514 gboolean pop_list;
00515 glong newval_chars;
00516 glong change_chars;
00517
00518 newval_chars = g_utf8_strlen (newval, newval_len);
00519 change_chars = g_utf8_strlen (change, change_len);
00520
00521 if (box->in_list_select)
00522 {
00523 gnc_basic_cell_set_value_internal (_cell, newval);
00524
00525 *cursor_position = -1;
00526 *start_selection = 0;
00527 *end_selection = -1;
00528
00529 return;
00530 }
00531
00532
00533 if (change == NULL)
00534 {
00535 gnc_basic_cell_set_value_internal (_cell, newval);
00536 return;
00537 }
00538
00539
00540 if (*cursor_position < _cell->value_chars)
00541 {
00542 gnc_basic_cell_set_value_internal (_cell, newval);
00543 return;
00544 }
00545
00546 match = gnc_quickfill_get_string_match (box->qf, newval);
00547
00548 match_str = gnc_quickfill_string (match);
00549
00550 if ((match == NULL) || (match_str == NULL))
00551 {
00552 gnc_basic_cell_set_value_internal (_cell, newval);
00553
00554 block_list_signals (cell);
00555 gnc_item_list_select (box->item_list, NULL);
00556 unblock_list_signals (cell);
00557
00558 return;
00559 }
00560
00561 *start_selection = newval_chars;
00562 *end_selection = -1;
00563 *cursor_position += change_chars;
00564
00565 if (!box->list_popped)
00566 pop_list = auto_pop_combos;
00567 else
00568 pop_list = FALSE;
00569
00570 if (pop_list)
00571 {
00572 gnc_item_edit_show_popup (box->item_edit);
00573 box->list_popped = TRUE;
00574 }
00575
00576 block_list_signals (cell);
00577 gnc_item_list_select (box->item_list, match_str);
00578 unblock_list_signals (cell);
00579
00580 gnc_basic_cell_set_value_internal (_cell, match_str);
00581 }
00582
00583 static gboolean
00584 gnc_combo_cell_direct_update (BasicCell *bcell,
00585 int *cursor_position,
00586 int *start_selection,
00587 int *end_selection,
00588 void *gui_data)
00589 {
00590 ComboCell *cell = (ComboCell *) bcell;
00591 PopBox *box = cell->cell.gui_private;
00592 GdkEventKey *event = gui_data;
00593 gboolean keep_on_going = FALSE;
00594 gboolean extra_colon;
00595 gunichar unicode_value;
00596 QuickFill *match;
00597 const char *match_str;
00598 int prefix_len;
00599 int find_pos;
00600 int new_pos;
00601
00602 if (event->type != GDK_KEY_PRESS)
00603 return FALSE;
00604
00605 unicode_value = gdk_keyval_to_unicode(event->keyval);
00606 switch (event->keyval)
00607 {
00608 case GDK_slash:
00609 if (!(event->state & GDK_MOD1_MASK))
00610 {
00611 if (unicode_value == box->complete_char)
00612 break;
00613
00614 return FALSE;
00615 }
00616 keep_on_going = TRUE;
00617
00618 case GDK_Tab:
00619 case GDK_ISO_Left_Tab:
00620 if (!(event->state & GDK_CONTROL_MASK) &&
00621 !keep_on_going)
00622 return FALSE;
00623
00624 match = gnc_quickfill_get_string_len_match
00625 (box->qf, bcell->value, *cursor_position);
00626 if (match == NULL)
00627 return TRUE;
00628
00629 match = gnc_quickfill_get_unique_len_match
00630 (match, &prefix_len);
00631 if (match == NULL)
00632 return TRUE;
00633
00634 match_str = gnc_quickfill_string (match);
00635
00636 if ((match_str != NULL) &&
00637 (strncmp (match_str, bcell->value,
00638 strlen (bcell->value)) == 0) &&
00639 (strcmp (match_str, bcell->value) != 0))
00640 {
00641 gnc_basic_cell_set_value_internal (bcell,
00642 match_str);
00643
00644 block_list_signals (cell);
00645 gnc_item_list_select (box->item_list,
00646 match_str);
00647 unblock_list_signals (cell);
00648 }
00649
00650 *cursor_position += prefix_len;
00651 *start_selection = *cursor_position;
00652 *end_selection = -1;
00653
00654 return TRUE;
00655 }
00656
00657 if (box->complete_char == 0)
00658 return FALSE;
00659
00660 if (unicode_value != box->complete_char)
00661 return FALSE;
00662
00663 if (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))
00664 return FALSE;
00665
00666 if ((*cursor_position < bcell->value_chars) &&
00667 ((*end_selection < bcell->value_chars) ||
00668 (*cursor_position < *start_selection)))
00669 return FALSE;
00670
00671 if ((*cursor_position == bcell->value_chars) &&
00672 (*start_selection != *end_selection) &&
00673 (*end_selection < bcell->value_chars))
00674 return FALSE;
00675
00676 find_pos = -1;
00677 if (*start_selection < bcell->value_chars)
00678 {
00679 int i = *start_selection;
00680 const char *c;
00681 gunichar uc;
00682
00683 c = g_utf8_offset_to_pointer (bcell->value, i);
00684 while (*c)
00685 {
00686 uc = g_utf8_get_char (c);
00687 if (uc == box->complete_char)
00688 {
00689 find_pos = (i + 1);
00690 break;
00691 }
00692 c = g_utf8_next_char (c);
00693 i++;
00694 }
00695 }
00696
00697 new_pos = *cursor_position;
00698
00699 if (find_pos >= 0)
00700 {
00701 new_pos = find_pos;
00702 extra_colon = FALSE;
00703 }
00704 else
00705 {
00706 new_pos = bcell->value_chars;
00707 extra_colon = TRUE;
00708 }
00709
00710 match = gnc_quickfill_get_string_len_match (box->qf,
00711 bcell->value, new_pos);
00712 if (match == NULL)
00713 return FALSE;
00714
00715 if (extra_colon)
00716 {
00717 match = gnc_quickfill_get_char_match (match,
00718 box->complete_char);
00719 if (match == NULL)
00720 return FALSE;
00721
00722 new_pos++;
00723 }
00724
00725 match_str = gnc_quickfill_string (match);
00726
00727 if ((match_str != NULL) &&
00728 (strncmp (match_str, bcell->value, strlen (bcell->value)) == 0) &&
00729 (strcmp (match_str, bcell->value) != 0))
00730 {
00731 gnc_basic_cell_set_value_internal (bcell, match_str);
00732
00733 block_list_signals (cell);
00734 gnc_item_list_select (box->item_list, match_str);
00735 unblock_list_signals (cell);
00736 }
00737
00738 *cursor_position = new_pos;
00739 *start_selection = new_pos;
00740 *end_selection = -1;
00741
00742 return TRUE;
00743 }
00744
00745 static void
00746 gnc_combo_cell_gui_realize (BasicCell *bcell, gpointer data)
00747 {
00748 GnucashSheet *sheet = data;
00749 GnomeCanvasItem *item = sheet->item_editor;
00750 GncItemEdit *item_edit = GNC_ITEM_EDIT (item);
00751 ComboCell *cell = (ComboCell *) bcell;
00752 PopBox *box = cell->cell.gui_private;
00753
00754
00755 box->sheet = sheet;
00756 box->item_edit = item_edit;
00757 if (cell->shared_store)
00758 box->item_list = gnc_item_edit_new_list(box->item_edit, cell->shared_store);
00759 else
00760 box->item_list = gnc_item_edit_new_list(box->item_edit, box->tmp_store);
00761 g_object_ref_sink(box->item_list);
00762
00763
00764 cell->cell.gui_realize = NULL;
00765 cell->cell.gui_move = gnc_combo_cell_gui_move;
00766 cell->cell.enter_cell = gnc_combo_cell_enter;
00767 cell->cell.leave_cell = gnc_combo_cell_leave;
00768 cell->cell.gui_destroy = gnc_combo_cell_gui_destroy;
00769 cell->cell.modify_verify = gnc_combo_cell_modify_verify;
00770 cell->cell.direct_update = gnc_combo_cell_direct_update;
00771 }
00772
00773 static void
00774 gnc_combo_cell_gui_move (BasicCell *bcell)
00775 {
00776 PopBox *box = bcell->gui_private;
00777
00778 combo_disconnect_signals ((ComboCell *) bcell);
00779
00780 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
00781 NULL, NULL, NULL, NULL, NULL);
00782
00783 box->list_popped = FALSE;
00784 }
00785
00786 static int
00787 get_popup_height (GnomeCanvasItem *item,
00788 int space_available,
00789 int row_height,
00790 gpointer user_data)
00791 {
00792 PopBox *box = user_data;
00793 int count, pad = 4;
00794
00795 count = gnc_item_list_num_entries(box->item_list);
00796 return MIN(space_available, (count * (row_height + pad)) + pad);
00797 }
00798
00799 static int
00800 popup_autosize (GnomeCanvasItem *item,
00801 int max_width,
00802 gpointer user_data)
00803 {
00804 PopBox *box = user_data;
00805
00806 if (!box || !box->autosize)
00807 return max_width;
00808
00809 return gnc_item_list_autosize (GNC_ITEM_LIST (item)) + 20;
00810 }
00811
00812 static void
00813 popup_set_focus (GnomeCanvasItem *item,
00814 gpointer user_data)
00815 {
00816 gtk_widget_grab_focus (GTK_WIDGET (GNC_ITEM_LIST (item)->tree_view));
00817 }
00818
00819 static void
00820 popup_post_show (GnomeCanvasItem *item,
00821 gpointer user_data)
00822 {
00823
00824
00825
00826
00827
00828 gtk_widget_size_request (GNC_ITEM_LIST (item)->frame, NULL);
00829
00830 gnc_item_list_autosize (GNC_ITEM_LIST (item));
00831 gnc_item_list_show_selected (GNC_ITEM_LIST (item));
00832 }
00833
00834 static int
00835 popup_get_width (GnomeCanvasItem *item,
00836 gpointer user_data)
00837 {
00838 return GTK_WIDGET (GNC_ITEM_LIST (item)->tree_view)->allocation.width;
00839 }
00840
00841 static gboolean
00842 gnc_combo_cell_enter (BasicCell *bcell,
00843 int *cursor_position,
00844 int *start_selection,
00845 int *end_selection)
00846 {
00847 ComboCell *cell = (ComboCell *) bcell;
00848 PopBox *box = bcell->gui_private;
00849 GList *find = NULL;
00850
00851 if (bcell->value)
00852 find = g_list_find_custom (box->ignore_strings,
00853 bcell->value,
00854 (GCompareFunc) strcmp);
00855 if (find)
00856 return FALSE;
00857
00858 gnc_item_edit_set_popup (box->item_edit,
00859 GNOME_CANVAS_ITEM (box->item_list),
00860 get_popup_height, popup_autosize,
00861 popup_set_focus, popup_post_show,
00862 popup_get_width, box);
00863
00864 block_list_signals (cell);
00865 gnc_item_list_select (box->item_list, bcell->value);
00866 unblock_list_signals (cell);
00867
00868 combo_connect_signals (cell);
00869
00870 *cursor_position = -1;
00871 *start_selection = 0;
00872 *end_selection = -1;
00873
00874 return TRUE;
00875 }
00876
00877 static void
00878 gnc_combo_cell_leave (BasicCell *bcell)
00879 {
00880 PopBox *box = bcell->gui_private;
00881
00882 combo_disconnect_signals ((ComboCell *) bcell);
00883
00884 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
00885 NULL, NULL, NULL, NULL, NULL);
00886
00887 box->list_popped = FALSE;
00888
00889 if (box->strict)
00890 {
00891 if (bcell->value)
00892 {
00893 if (gnc_item_in_list (box->item_list, bcell->value))
00894 return;
00895
00896 if (g_list_find_custom (box->ignore_strings,
00897 bcell->value,
00898 (GCompareFunc) strcmp))
00899 return;
00900 }
00901 gnc_basic_cell_set_value_internal (bcell, "");
00902 }
00903 }
00904
00905 void
00906 gnc_combo_cell_set_strict (ComboCell *cell, gboolean strict)
00907 {
00908 PopBox *box;
00909
00910 if (cell == NULL)
00911 return;
00912
00913 box = cell->cell.gui_private;
00914
00915 box->strict = strict;
00916 }
00917
00918 void
00919 gnc_combo_cell_set_complete_char (ComboCell *cell, gunichar complete_char)
00920 {
00921 PopBox *box;
00922
00923 if (cell == NULL)
00924 return;
00925
00926 box = cell->cell.gui_private;
00927
00928 box->complete_char = complete_char;
00929 }
00930
00931 void
00932 gnc_combo_cell_add_ignore_string (ComboCell *cell,
00933 const char *ignore_string)
00934 {
00935 PopBox *box;
00936
00937 if (cell == NULL)
00938 return;
00939
00940 if (!ignore_string)
00941 return;
00942
00943 box = cell->cell.gui_private;
00944
00945 box->ignore_strings = g_list_prepend (box->ignore_strings,
00946 g_strdup (ignore_string));
00947 }
00948
00949 void
00950 gnc_combo_cell_set_autosize (ComboCell *cell, gboolean autosize)
00951 {
00952 PopBox *box;
00953
00954 if (!cell)
00955 return;
00956
00957 box = cell->cell.gui_private;
00958 if (!box)
00959 return;
00960
00961 box->autosize = autosize;
00962 }
00963
00964
00965
00966
00967
00968