113
101
value_release (cond->value[1]);
116
/**********************************************************************************/
119
filter_field_index (GnmFilterField const *field)
121
return field->parent.anchor.cell_bound.start.col -
122
field->filter->r.start.col;
126
filter_field_finalize (GObject *object)
128
GnmFilterField *field = FILTER_FIELD (object);
129
GObjectClass *parent;
131
g_return_if_fail (field != NULL);
133
if (field->cond != NULL) {
134
gnm_filter_condition_unref (field->cond);
138
parent = g_type_class_peek (SHEET_OBJECT_TYPE);
139
parent->finalize (object);
142
/* Cut and paste from gtkwindow.c */
144
do_focus_change (GtkWidget *widget, gboolean in)
146
GdkEventFocus fevent;
148
g_object_ref (widget);
151
GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
153
GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
155
fevent.type = GDK_FOCUS_CHANGE;
156
fevent.window = widget->window;
159
gtk_widget_event (widget, (GdkEvent *)&fevent);
161
g_object_notify (G_OBJECT (widget), "has-focus");
163
g_object_unref (widget);
167
filter_popup_destroy (GtkWidget *popup, GtkWidget *list)
169
do_focus_change (list, FALSE);
170
gtk_widget_destroy (popup);
174
cb_filter_key_press (GtkWidget *popup, GdkEventKey *event, GtkWidget *list)
176
if (event->keyval != GDK_Escape)
178
filter_popup_destroy (popup, list);
183
cb_filter_button_press (GtkWidget *popup, GdkEventButton *event,
186
/* A press outside the popup cancels */
187
if (event->window != popup->window) {
188
filter_popup_destroy (popup, list);
195
cb_filter_button_release (GtkWidget *popup, GdkEventButton *event,
199
GnmFilterField *field;
200
GnmFilterCondition *cond = NULL;
201
WorkbookControlGUI *wbcg;
202
GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent *) event);
205
/* A release inside list accepts */
206
if (event_widget != GTK_WIDGET (list))
209
field = g_object_get_data (G_OBJECT (list), FIELD_ID);
210
wbcg = g_object_get_data (G_OBJECT (list), WBCG_ID);
212
gtk_tree_selection_get_selected (gtk_tree_view_get_selection (list),
216
gboolean set_condition = TRUE;
218
gtk_tree_model_get (gtk_tree_view_get_model (list), &iter,
219
1, &strval, 2, &type,
222
field_num = filter_field_index (field);
225
cond = gnm_filter_condition_new_single (
227
value_new_string_nocopy (strval));
230
case 1: /* unfilter */
234
set_condition = FALSE;
235
dialog_auto_filter (wbcg, field->filter, field_num,
239
cond = gnm_filter_condition_new_single (
240
GNM_FILTER_OP_BLANKS, NULL);
243
cond = gnm_filter_condition_new_single (
244
GNM_FILTER_OP_NON_BLANKS, NULL);
246
case 10: /* Top 10 */
247
set_condition = FALSE;
248
dialog_auto_filter (wbcg, field->filter, field_num,
252
set_condition = FALSE;
253
g_warning ("Unknown type %d", type);
259
gnm_filter_set_condition (field->filter, field_num,
261
sheet_update (field->filter->sheet);
264
filter_popup_destroy (popup, GTK_WIDGET (list));
269
cb_filter_motion_notify_event (GtkWidget *widget, GdkEventMotion *event,
273
if (event->x >= 0 && event->y >= 0 &&
274
event->x < widget->allocation.width &&
275
event->y < widget->allocation.height &&
276
gtk_tree_view_get_path_at_pos (list, event->x, event->y,
277
&path, NULL, NULL, NULL)) {
278
gtk_tree_selection_select_path (gtk_tree_view_get_selection (list), path);
279
gtk_tree_path_free (path);
287
GODateConventions const *date_conv;
291
cb_collect_unique (GnmCellIter const *iter, UniqueCollection *uc)
293
if (cell_is_blank (iter->cell))
294
uc->has_blank = TRUE;
296
GOFormat const *format = cell_get_format (iter->cell);
297
GnmValue const *v = iter->cell->value;
298
char *str = format_value (format, v, NULL, -1, uc->date_conv);
299
g_hash_table_replace (uc->hash, str, iter->cell);
306
cb_hash_domain (GnmValue *key, gpointer value, gpointer accum)
308
g_ptr_array_add (accum, key);
312
order_alphabetically (void const *ptr_a, void const *ptr_b)
314
char const * const *a = ptr_a;
315
char const * const *b = ptr_b;
316
return strcmp (*a, *b);
319
static GtkListStore *
320
collect_unique_elements (GnmFilterField *field,
321
GtkTreePath **clip, GtkTreePath **select)
326
GPtrArray *sorted = g_ptr_array_new ();
328
gboolean is_custom = FALSE;
329
GnmRange r = field->filter->r;
330
GnmValue const *check = NULL;
331
Sheet *sheet = field->filter->sheet;
333
if (field->cond != NULL &&
334
field->cond->op[0] == GNM_FILTER_OP_EQUAL &&
335
field->cond->op[1] == GNM_FILTER_UNUSED) {
336
check = field->cond->value[0];
339
model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
341
gtk_list_store_append (model, &iter);
342
gtk_list_store_set (model, &iter, 0, _("(All)"), 1, NULL, 2, 1, -1);
343
if (field->cond == NULL || field->cond->op[0] == GNM_FILTER_UNUSED)
344
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
346
gtk_list_store_append (model, &iter);
347
gtk_list_store_set (model, &iter, 0, _("(Top 10...)"), 1, NULL, 2, 10,-1);
348
if (field->cond != NULL &&
349
(GNM_FILTER_OP_TYPE_MASK & field->cond->op[0]) == GNM_FILTER_OP_TOP_N)
350
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
352
/* default to this we can easily revamp later */
353
gtk_list_store_append (model, &iter);
354
gtk_list_store_set (model, &iter, 0, _("(Custom...)"), 1, NULL, 2, 2, -1);
355
if (*select == NULL) {
357
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
361
/* r.end.row = XL actually extend to the first non-empty element in the list */
362
r.end.col = r.start.col += filter_field_index (field);
363
uc.has_blank = FALSE;
364
uc.hash = g_hash_table_new_full (g_str_hash, g_str_equal,
365
(GDestroyNotify)g_free,
367
uc.date_conv = workbook_date_conv (sheet->workbook);
369
sheet_foreach_cell_in_range (sheet,
371
r.start.col, r.start.row, r.end.col, r.end.row,
372
(CellIterFunc)&cb_collect_unique, &uc);
374
g_hash_table_foreach (uc.hash, (GHFunc)cb_hash_domain, sorted);
375
qsort (&g_ptr_array_index (sorted, 0),
376
sorted->len, sizeof (char *),
377
order_alphabetically);
378
for (i = 0; i < sorted->len ; i++) {
379
char const *str = g_ptr_array_index (sorted, i);
381
gsize len = g_utf8_strlen (str, -1);
382
unsigned const max = 50;
385
label = g_strdup (str);
386
strcpy (g_utf8_offset_to_pointer (label, max), "...");
389
gtk_list_store_append (model, &iter);
390
gtk_list_store_set (model, &iter,
391
0, label ? label : str, /* Menu text */
392
1, str, /* Actual string selected on. */
397
*clip = gtk_tree_model_get_path (GTK_TREE_MODEL (model),
400
if (strcmp (value_peek_string (check), str) == 0) {
401
gtk_tree_path_free (*select);
402
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
408
gtk_list_store_append (model, &iter);
409
gtk_list_store_set (model, &iter, 0, _("(Blanks...)"), 1, NULL, 2, 3, -1);
410
if (field->cond != NULL &&
411
field->cond->op[0] == GNM_FILTER_OP_BLANKS)
412
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
414
gtk_list_store_append (model, &iter);
415
gtk_list_store_set (model, &iter, 0, _("(Non Blanks...)"), 1, NULL, 2, 4, -1);
416
if (field->cond != NULL &&
417
field->cond->op[0] == GNM_FILTER_OP_NON_BLANKS)
418
*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
419
} else if (is_custom && field->cond != NULL &&
420
(GNM_FILTER_OP_TYPE_MASK & field->cond->op[0]) == GNM_FILTER_OP_BLANKS) {
421
gtk_tree_path_free (*select);
425
g_hash_table_destroy (uc.hash);
426
g_ptr_array_free (sorted, TRUE);
432
cb_focus_changed (GtkWindow *toplevel)
435
g_warning (gtk_window_has_toplevel_focus (toplevel) ? "focus" : "no focus");
440
cb_filter_button_pressed (GtkButton *button, FooCanvasItem *view)
442
GnmPane *pane = GNM_CANVAS (view->canvas)->pane;
443
SheetControlGUI *scg = pane->gcanvas->simple.scg;
444
SheetObject *so = sheet_object_view_get_so (SHEET_OBJECT_VIEW (view));
445
GnmFilterField *field = FILTER_FIELD (so);
446
GtkWidget *frame, *popup, *list, *container;
449
GtkTreeViewColumn *column;
450
GtkTreePath *clip = NULL, *select = NULL;
453
popup = gtk_window_new (GTK_WINDOW_POPUP);
454
model = collect_unique_elements (field, &clip, &select);
455
column = gtk_tree_view_column_new_with_attributes ("ID",
456
gtk_cell_renderer_text_new (), "text", 0,
458
list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
459
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
460
gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
461
gtk_widget_size_request (GTK_WIDGET (list), &req);
462
g_object_set_data (G_OBJECT (list), FIELD_ID, field);
463
g_object_set_data (G_OBJECT (list), WBCG_ID, scg_get_wbcg (scg));
464
g_signal_connect (G_OBJECT (wbcg_toplevel (scg_get_wbcg (scg))),
465
"notify::has-toplevel-focus",
466
G_CALLBACK (cb_focus_changed), list);
468
frame = gtk_frame_new (NULL);
469
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
472
range_dump (&so->anchor.cell_bound, "");
473
fprintf (stderr, " : so = %p, view = %p\n", so, view);
477
GtkWidget *sw = gtk_scrolled_window_new (
478
gtk_tree_view_get_hadjustment (GTK_TREE_VIEW (list)),
479
gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (list)));
480
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
481
GTK_POLICY_AUTOMATIC,
483
gtk_tree_view_get_background_area (GTK_TREE_VIEW (list),
485
gtk_tree_path_free (clip);
487
gtk_widget_set_size_request (list, req.width, rect.y);
488
gtk_container_add (GTK_CONTAINER (sw), list);
493
gtk_container_add (GTK_CONTAINER (frame), container);
496
gtk_window_set_decorated (GTK_WINDOW (popup), FALSE);
497
gdk_window_get_origin (GTK_WIDGET (pane->gcanvas)->window,
499
gtk_window_move (GTK_WINDOW (popup),
500
root_x + scg_colrow_distance_get (scg, TRUE,
501
pane->gcanvas->first.col,
502
field->parent.anchor.cell_bound.start.col + 1) - req.width,
503
root_y + scg_colrow_distance_get (scg, FALSE,
504
pane->gcanvas->first.row,
505
field->filter->r.start.row + 1));
507
gtk_container_add (GTK_CONTAINER (popup), frame);
509
g_signal_connect (popup,
511
G_CALLBACK (cb_filter_key_press), list);
512
g_signal_connect (popup,
513
"button_press_event",
514
G_CALLBACK (cb_filter_button_press), list);
515
g_signal_connect (popup,
516
"button_release_event",
517
G_CALLBACK (cb_filter_button_release), list);
518
g_signal_connect (list,
519
"motion_notify_event",
520
G_CALLBACK (cb_filter_motion_notify_event), list);
522
gtk_widget_show_all (popup);
524
/* after we show the window setup the selection (showing the list
525
* clears the selection) */
526
if (select != NULL) {
527
gtk_tree_selection_select_path (
528
gtk_tree_view_get_selection (GTK_TREE_VIEW (list)),
530
gtk_tree_path_free (select);
533
gtk_widget_grab_focus (GTK_WIDGET (list));
534
do_focus_change (GTK_WIDGET (list), TRUE);
536
gtk_grab_add (popup);
537
gdk_pointer_grab (popup->window, TRUE,
538
GDK_BUTTON_PRESS_MASK |
539
GDK_BUTTON_RELEASE_MASK |
540
GDK_POINTER_MOTION_MASK,
541
NULL, NULL, GDK_CURRENT_TIME);
545
filter_field_arrow_format (GnmFilterField *field, GtkWidget *arrow)
547
gtk_arrow_set (GTK_ARROW (arrow),
548
field->cond != NULL ? GTK_ARROW_RIGHT : GTK_ARROW_DOWN,
550
gtk_widget_modify_fg (arrow, GTK_STATE_NORMAL,
551
field->cond != NULL ? &gs_yellow : &gs_black);
555
filter_view_destroy (SheetObjectView *sov)
557
gtk_object_destroy (GTK_OBJECT (sov));
560
filter_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
562
FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
566
/* clip vertically */
567
h = (coords[3] - coords[1]);
571
/* maintain squareness horzontally */
576
/* NOTE : far point is EXCLUDED so we add 1 */
577
foo_canvas_item_set (view,
580
"width", coords [2] - x,
584
foo_canvas_item_show (view);
586
foo_canvas_item_hide (view);
590
filter_foo_view_init (SheetObjectViewIface *sov_iface)
592
sov_iface->destroy = filter_view_destroy;
593
sov_iface->set_bounds = filter_view_set_bounds;
595
typedef FooCanvasWidget FilterFooView;
596
typedef FooCanvasWidgetClass FilterFooViewClass;
597
static GSF_CLASS_FULL (FilterFooView, filter_foo_view,
598
NULL, NULL, NULL, NULL,
599
NULL, FOO_TYPE_CANVAS_WIDGET, 0,
600
GSF_INTERFACE (filter_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
602
static SheetObjectView *
603
filter_field_new_view (SheetObject *so, SheetObjectViewContainer *container)
605
GnmCanvas *gcanvas = ((GnmPane *)container)->gcanvas;
606
GtkWidget *arrow, *view_widget = gtk_button_new ();
607
GnmFilterField *field = (GnmFilterField *) so;
608
FooCanvasItem *view_item = foo_canvas_item_new (gcanvas->object_views,
609
filter_foo_view_get_type (),
610
"widget", view_widget,
611
"size_pixels", FALSE,
614
GTK_WIDGET_UNSET_FLAGS (view_widget, GTK_CAN_FOCUS);
615
arrow = gtk_arrow_new (field->cond != NULL ? GTK_ARROW_RIGHT : GTK_ARROW_DOWN,
617
filter_field_arrow_format (field, arrow);
618
gtk_container_add (GTK_CONTAINER (view_widget), arrow);
620
g_object_set_data (G_OBJECT (view_widget), VIEW_ITEM_ID, view_item);
621
g_object_set_data (G_OBJECT (view_item), ARROW_ID, arrow);
622
g_signal_connect (view_widget,
624
G_CALLBACK (cb_filter_button_pressed), view_item);
625
gtk_widget_show_all (view_widget);
627
return gnm_pane_object_register (so, view_item, FALSE);
631
filter_field_init (SheetObject *so)
633
/* keep the arrows from wandering with their cells */
634
so->flags &= ~SHEET_OBJECT_MOVE_WITH_CELLS;
638
filter_field_class_init (GObjectClass *object_class)
640
SheetObjectClass *sheet_object_class = SHEET_OBJECT_CLASS (object_class);
642
/* Object class method overrides */
643
object_class->finalize = filter_field_finalize;
645
/* SheetObject class method overrides */
646
sheet_object_class->new_view = filter_field_new_view;
647
sheet_object_class->read_xml_dom = NULL;
648
sheet_object_class->write_xml_sax = NULL;
649
sheet_object_class->print = NULL;
650
sheet_object_class->copy = NULL;
653
GSF_CLASS (GnmFilterField, filter_field,
654
filter_field_class_init, filter_field_init,
657
104
/*****************************************************************************/
660
107
GnmFilterCondition const *cond;
661
108
GnmValue *val[2];
662
109
GORegexp regexp[2];
110
Sheet *target_sheet; /* not necessarilly the src */
890
colrow_set_visibility (iter->pp.sheet, FALSE, FALSE,
340
colrow_set_visibility (data->target_sheet, FALSE, FALSE,
891
341
iter->pp.eval.row, iter->pp.eval.row);
894
344
/*****************************************************************************/
897
filter_field_apply (GnmFilterField *field)
347
* gnm_filter_combo_apply :
348
* @fcombo : #GnmFilterCombo
349
* @target_sheet : @Sheet
353
gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
899
GnmFilter *filter = field->filter;
900
int const col = field->parent.anchor.cell_bound.start.col;
355
GnmFilter const *filter = fcombo->filter;
356
GnmFilterCondition const *cond = fcombo->cond;
357
int const col = sheet_object_get_range (SHEET_OBJECT (fcombo))->start.col;
901
358
int const start_row = filter->r.start.row + 1;
902
359
int const end_row = filter->r.end.row;
904
if (start_row > end_row)
907
if (field->cond == NULL ||
908
field->cond->op[0] == GNM_FILTER_UNUSED)
910
if (0x10 >= (field->cond->op[0] & GNM_FILTER_OP_TYPE_MASK)) {
360
CellIterFlags iter_flags = CELL_ITER_IGNORE_HIDDEN;
362
if (start_row > end_row ||
364
cond->op[0] == GNM_FILTER_UNUSED)
367
/* For the combo we filter a temporary sheet using the data from filter->sheet
368
* and need to include everything from the source, because it has a
369
* different set of conditions */
370
if (target_sheet != filter->sheet)
371
iter_flags = CELL_ITER_ALL;
373
if (0x10 >= (cond->op[0] & GNM_FILTER_OP_TYPE_MASK)) {
912
data.cond = field->cond;
913
filter_expr_init (&data, 0, field->cond, filter);
914
if (field->cond->op[1] != GNM_FILTER_UNUSED)
915
filter_expr_init (&data, 1, field->cond, field->filter);
376
data.target_sheet = target_sheet;
377
filter_expr_init (&data, 0, cond, filter);
378
if (cond->op[1] != GNM_FILTER_UNUSED)
379
filter_expr_init (&data, 1, cond, filter);
917
381
sheet_foreach_cell_in_range (filter->sheet,
918
CELL_ITER_IGNORE_HIDDEN,
382
(target_sheet == filter->sheet) ? CELL_ITER_IGNORE_HIDDEN : CELL_ITER_ALL,
919
383
col, start_row, col, end_row,
920
384
(CellIterFunc) cb_filter_expr, &data);
922
386
filter_expr_release (&data, 0);
923
if (field->cond->op[1] != GNM_FILTER_UNUSED)
387
if (cond->op[1] != GNM_FILTER_UNUSED)
924
388
filter_expr_release (&data, 1);
925
} else if (field->cond->op[0] == GNM_FILTER_OP_BLANKS)
926
sheet_foreach_cell_in_range (filter->sheet,
927
CELL_ITER_IGNORE_HIDDEN,
928
col, start_row, col, end_row,
929
cb_filter_blanks, NULL);
930
else if (field->cond->op[0] == GNM_FILTER_OP_NON_BLANKS)
931
sheet_foreach_cell_in_range (filter->sheet,
932
CELL_ITER_IGNORE_HIDDEN,
933
col, start_row, col, end_row,
934
cb_filter_non_blanks, NULL);
935
else if (0x30 == (field->cond->op[0] & GNM_FILTER_OP_TYPE_MASK)) {
936
if (field->cond->op[0] & 0x2) { /* relative */
389
} else if (cond->op[0] == GNM_FILTER_OP_BLANKS)
390
sheet_foreach_cell_in_range (filter->sheet,
391
CELL_ITER_IGNORE_HIDDEN,
392
col, start_row, col, end_row,
393
(CellIterFunc) cb_filter_blanks, target_sheet);
394
else if (cond->op[0] == GNM_FILTER_OP_NON_BLANKS)
395
sheet_foreach_cell_in_range (filter->sheet,
396
CELL_ITER_IGNORE_HIDDEN,
397
col, start_row, col, end_row,
398
(CellIterFunc) cb_filter_non_blanks, target_sheet);
399
else if (0x30 == (cond->op[0] & GNM_FILTER_OP_TYPE_MASK)) {
400
if (cond->op[0] & 0x2) { /* relative */
937
401
FilterPercentage data;
938
402
gnm_float offset;
940
data.find_max = (field->cond->op[0] & 0x1) ? FALSE : TRUE;
404
data.find_max = (cond->op[0] & 0x1) ? FALSE : TRUE;
941
405
data.initialized = FALSE;
942
406
sheet_foreach_cell_in_range (filter->sheet,
943
407
CELL_ITER_IGNORE_HIDDEN | CELL_ITER_IGNORE_BLANK,
944
408
col, start_row, col, end_row,
945
409
(CellIterFunc) cb_filter_find_percentage, &data);
946
offset = (data.high - data.low) * field->cond->count / 100.;
410
offset = (data.high - data.low) * cond->count / 100.;
947
411
data.high -= offset;
948
412
data.low += offset;
413
data.target_sheet = target_sheet;
949
414
sheet_foreach_cell_in_range (filter->sheet,
950
415
CELL_ITER_IGNORE_HIDDEN,
951
416
col, start_row, col, end_row,
952
417
(CellIterFunc) cb_hide_unwanted_percentage, &data);
953
418
} else { /* absolute */
954
419
FilterItems data;
955
data.find_max = (field->cond->op[0] & 0x1) ? FALSE : TRUE;
420
data.find_max = (cond->op[0] & 0x1) ? FALSE : TRUE;
956
421
data.elements = 0;
957
data.count = field->cond->count;
422
data.count = cond->count;
958
423
data.vals = g_alloca (sizeof (GnmValue *) * data.count);
959
424
sheet_foreach_cell_in_range (filter->sheet,
960
425
CELL_ITER_IGNORE_HIDDEN | CELL_ITER_IGNORE_BLANK,
961
426
col, start_row, col, end_row,
962
427
(CellIterFunc) cb_filter_find_items, &data);
428
data.target_sheet = target_sheet;
963
429
sheet_foreach_cell_in_range (filter->sheet,
964
430
CELL_ITER_IGNORE_HIDDEN,
965
431
col, start_row, col, end_row,
966
432
(CellIterFunc) cb_hide_unwanted_items, &data);
969
g_warning ("Invalid operator %d", field->cond->op[0]);
973
filter_field_set_active (GnmFilterField *field)
976
SheetObject *so = &field->parent;
978
for (ptr = so->realized_list; ptr; ptr = ptr->next)
979
filter_field_arrow_format (field,
980
g_object_get_data (ptr->data, ARROW_ID));
435
g_warning ("Invalid operator %d", cond->op[0]);
443
static guint signals [LAST_SIGNAL] = { 0 };
446
SheetObjectClass parent;
448
void (*cond_changed) (GnmFilterCombo *);
449
} GnmFilterComboClass;
452
gnm_filter_combo_finalize (GObject *object)
454
GnmFilterCombo *fcombo = GNM_FILTER_COMBO (object);
455
GObjectClass *parent;
456
if (fcombo->cond != NULL) {
457
gnm_filter_condition_unref (fcombo->cond);
460
parent = g_type_class_peek (SHEET_OBJECT_TYPE);
461
parent->finalize (object);
465
gnm_filter_combo_init (SheetObject *so)
467
/* keep the arrows from wandering with their cells */
468
so->flags &= ~SHEET_OBJECT_MOVE_WITH_CELLS;
470
static SheetObjectView *
471
gnm_filter_combo_foo_view_new (SheetObject *so, SheetObjectViewContainer *container)
473
return gnm_cell_combo_foo_view_new (so,
474
gnm_filter_combo_foo_view_get_type (), container);
477
gnm_filter_combo_class_init (GObjectClass *gobject_class)
479
SheetObjectClass *so_class = SHEET_OBJECT_CLASS (gobject_class);
481
/* Object class method overrides */
482
gobject_class->finalize = gnm_filter_combo_finalize;
484
/* SheetObject class method overrides */
485
so_class->new_view = gnm_filter_combo_foo_view_new;
486
so_class->read_xml_dom = NULL;
487
so_class->write_xml_sax = NULL;
488
so_class->print = NULL;
489
so_class->copy = NULL;
491
signals[COND_CHANGED] = g_signal_new ("cond-changed",
492
GNM_FILTER_COMBO_TYPE,
494
G_STRUCT_OFFSET (GnmFilterComboClass, cond_changed),
496
g_cclosure_marshal_VOID__VOID,
500
GSF_CLASS (GnmFilterCombo, gnm_filter_combo,
501
gnm_filter_combo_class_init, gnm_filter_combo_init,
983
504
/*************************************************************************/