evolution-3.6.4/widgets/table/e-table-group-leaf.c

No issues found

  1 /*
  2  *
  3  * This program is free software; you can redistribute it and/or
  4  * modify it under the terms of the GNU Lesser General Public
  5  * License as published by the Free Software Foundation; either
  6  * version 2 of the License, or (at your option) version 3.
  7  *
  8  * This program is distributed in the hope that it will be useful,
  9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11  * Lesser General Public License for more details.
 12  *
 13  * You should have received a copy of the GNU Lesser General Public
 14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 15  *
 16  *
 17  * Authors:
 18  *		Chris Lahey <clahey@ximian.com>
 19  *
 20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 21  *
 22  */
 23 
 24 #ifdef HAVE_CONFIG_H
 25 #include <config.h>
 26 #endif
 27 
 28 #include <gtk/gtk.h>
 29 #include <libgnomecanvas/libgnomecanvas.h>
 30 
 31 #include <glib/gi18n.h>
 32 #include "e-util/e-util.h"
 33 #include "misc/e-canvas.h"
 34 
 35 #include "e-table-item.h"
 36 #include "e-table-group-leaf.h"
 37 #include "e-table-sorted.h"
 38 #include "e-table-sorted-variable.h"
 39 
 40 /* workaround for avoiding APi breakage */
 41 #define etgl_get_type e_table_group_leaf_get_type
 42 G_DEFINE_TYPE (ETableGroupLeaf, etgl, E_TYPE_TABLE_GROUP)
 43 
 44 enum {
 45 	PROP_0,
 46 	PROP_HEIGHT,
 47 	PROP_WIDTH,
 48 	PROP_MINIMUM_WIDTH,
 49 	PROP_FROZEN,
 50 	PROP_TABLE_ALTERNATING_ROW_COLORS,
 51 	PROP_TABLE_HORIZONTAL_DRAW_GRID,
 52 	PROP_TABLE_VERTICAL_DRAW_GRID,
 53 	PROP_TABLE_DRAW_FOCUS,
 54 	PROP_CURSOR_MODE,
 55 	PROP_LENGTH_THRESHOLD,
 56 	PROP_SELECTION_MODEL,
 57 	PROP_UNIFORM_ROW_HEIGHT
 58 };
 59 
 60 static void
 61 etgl_dispose (GObject *object)
 62 {
 63 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object);
 64 
 65 	if (etgl->ets) {
 66 		g_object_unref (etgl->ets);
 67 		etgl->ets = NULL;
 68 	}
 69 
 70 	if (etgl->item) {
 71 		if (etgl->etgl_cursor_change_id != 0)
 72 			g_signal_handler_disconnect (
 73 				etgl->item,
 74 				etgl->etgl_cursor_change_id);
 75 		if (etgl->etgl_cursor_activated_id != 0)
 76 			g_signal_handler_disconnect (
 77 				etgl->item,
 78 				etgl->etgl_cursor_activated_id);
 79 		if (etgl->etgl_double_click_id != 0)
 80 			g_signal_handler_disconnect (
 81 				etgl->item,
 82 				etgl->etgl_double_click_id);
 83 		if (etgl->etgl_right_click_id != 0)
 84 			g_signal_handler_disconnect (
 85 				etgl->item,
 86 				etgl->etgl_right_click_id);
 87 		if (etgl->etgl_click_id != 0)
 88 			g_signal_handler_disconnect (
 89 				etgl->item,
 90 				etgl->etgl_click_id);
 91 		if (etgl->etgl_key_press_id != 0)
 92 			g_signal_handler_disconnect (
 93 				etgl->item,
 94 				etgl->etgl_key_press_id);
 95 		if (etgl->etgl_start_drag_id != 0)
 96 			g_signal_handler_disconnect (
 97 				etgl->item,
 98 				etgl->etgl_start_drag_id);
 99 
100 		etgl->etgl_cursor_change_id = 0;
101 		etgl->etgl_cursor_activated_id = 0;
102 		etgl->etgl_double_click_id = 0;
103 		etgl->etgl_right_click_id = 0;
104 		etgl->etgl_click_id = 0;
105 		etgl->etgl_key_press_id = 0;
106 		etgl->etgl_start_drag_id = 0;
107 
108 		g_object_run_dispose (G_OBJECT (etgl->item));
109 		etgl->item = NULL;
110 	}
111 
112 	if (etgl->selection_model) {
113 		g_object_unref (etgl->selection_model);
114 		etgl->selection_model = NULL;
115 	}
116 
117 	/* Chain up to parent's dispose() method. */
118 	G_OBJECT_CLASS (etgl_parent_class)->dispose (object);
119 }
120 
121 static void
122 e_table_group_leaf_construct (GnomeCanvasGroup *parent,
123                               ETableGroupLeaf *etgl,
124                               ETableHeader *full_header,
125                               ETableHeader *header,
126                               ETableModel *model,
127                               ETableSortInfo *sort_info)
128 {
129 	etgl->is_grouped =
130 		(e_table_sort_info_grouping_get_count (sort_info) > 0);
131 
132 	if (etgl->is_grouped)
133 		etgl->ets = E_TABLE_SUBSET (
134 			e_table_sorted_variable_new (
135 			model, full_header, sort_info));
136 	else
137 		etgl->ets = E_TABLE_SUBSET (
138 			e_table_sorted_new (
139 			model, full_header, sort_info));
140 
141 	e_table_group_construct (
142 		parent, E_TABLE_GROUP (etgl), full_header, header, model);
143 }
144 
145 /**
146  * e_table_group_leaf_new
147  * @parent: The %GnomeCanvasGroup to create a child of.
148  * @full_header: The full header of the %ETable.
149  * @header: The current header of the %ETable.
150  * @model: The %ETableModel of the %ETable.
151  * @sort_info: The %ETableSortInfo of the %ETable.
152  *
153  * %ETableGroupLeaf is an %ETableGroup which simply contains an
154  * %ETableItem.
155  *
156  * Returns: The new %ETableGroupLeaf.
157  */
158 ETableGroup *
159 e_table_group_leaf_new (GnomeCanvasGroup *parent,
160                         ETableHeader *full_header,
161                         ETableHeader *header,
162                         ETableModel *model,
163                         ETableSortInfo *sort_info)
164 {
165 	ETableGroupLeaf *etgl;
166 
167 	g_return_val_if_fail (parent != NULL, NULL);
168 
169 	etgl = g_object_new (E_TYPE_TABLE_GROUP_LEAF, NULL);
170 
171 	e_table_group_leaf_construct (
172 		parent, etgl, full_header,
173 		header, model, sort_info);
174 
175 	return E_TABLE_GROUP (etgl);
176 }
177 
178 static void
179 etgl_cursor_change (GObject *object,
180                     gint row,
181                     ETableGroupLeaf *etgl)
182 {
183 	if (row < E_TABLE_SUBSET (etgl->ets)->n_map)
184 		e_table_group_cursor_change (
185 			E_TABLE_GROUP (etgl),
186 			E_TABLE_SUBSET (etgl->ets)->map_table[row]);
187 }
188 
189 static void
190 etgl_cursor_activated (GObject *object,
191                        gint view_row,
192                        ETableGroupLeaf *etgl)
193 {
194 	if (view_row < E_TABLE_SUBSET (etgl->ets)->n_map)
195 		e_table_group_cursor_activated (
196 			E_TABLE_GROUP (etgl),
197 			E_TABLE_SUBSET (etgl->ets)->map_table[view_row]);
198 }
199 
200 static void
201 etgl_double_click (GObject *object,
202                    gint model_row,
203                    gint model_col,
204                    GdkEvent *event,
205                    ETableGroupLeaf *etgl)
206 {
207 	e_table_group_double_click (
208 		E_TABLE_GROUP (etgl), model_row, model_col, event);
209 }
210 
211 static gboolean
212 etgl_key_press (GObject *object,
213                 gint row,
214                 gint col,
215                 GdkEvent *event,
216                 ETableGroupLeaf *etgl)
217 {
218 	if (row < E_TABLE_SUBSET (etgl->ets)->n_map && row >= 0)
219 		return e_table_group_key_press (
220 			E_TABLE_GROUP (etgl),
221 			E_TABLE_SUBSET (etgl->ets)->map_table[row],
222 			col, event);
223 	else
224 		return FALSE;
225 }
226 
227 static gboolean
228 etgl_start_drag (GObject *object,
229                  gint model_row,
230                  gint model_col,
231                  GdkEvent *event,
232                  ETableGroupLeaf *etgl)
233 {
234 	return e_table_group_start_drag (
235 		E_TABLE_GROUP (etgl), model_row, model_col, event);
236 }
237 
238 static gboolean
239 etgl_right_click (GObject *object,
240                   gint view_row,
241                   gint model_col,
242                   GdkEvent *event,
243                   ETableGroupLeaf *etgl)
244 {
245 	if (view_row < E_TABLE_SUBSET (etgl->ets)->n_map)
246 		return e_table_group_right_click (
247 			E_TABLE_GROUP (etgl),
248 			E_TABLE_SUBSET (etgl->ets)->map_table[view_row],
249 			model_col, event);
250 	else
251 		return FALSE;
252 }
253 
254 static gboolean
255 etgl_click (GObject *object,
256             gint row,
257             gint col,
258             GdkEvent *event,
259             ETableGroupLeaf *etgl)
260 {
261 	if (row < E_TABLE_SUBSET (etgl->ets)->n_map)
262 		return e_table_group_click (
263 			E_TABLE_GROUP (etgl),
264 			E_TABLE_SUBSET (etgl->ets)->map_table[row],
265 			col, event);
266 	else
267 		return FALSE;
268 }
269 
270 static void
271 etgl_reflow (GnomeCanvasItem *item,
272              gint flags)
273 {
274 	ETableGroupLeaf *leaf = E_TABLE_GROUP_LEAF (item);
275 
276 	g_object_get (leaf->item, "height", &leaf->height, NULL);
277 	g_object_get (leaf->item, "width", &leaf->width, NULL);
278 
279 	e_canvas_item_request_parent_reflow (item);
280 }
281 
282 static void
283 etgl_realize (GnomeCanvasItem *item)
284 {
285 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (item);
286 
287 	if (GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize)
288 		GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize (item);
289 
290 	etgl->item = E_TABLE_ITEM (gnome_canvas_item_new (
291 		GNOME_CANVAS_GROUP (etgl),
292 		e_table_item_get_type (),
293 		"ETableHeader", E_TABLE_GROUP (etgl)->header,
294 		"ETableModel", etgl->ets,
295 		"alternating_row_colors", etgl->alternating_row_colors,
296 		"horizontal_draw_grid", etgl->horizontal_draw_grid,
297 		"vertical_draw_grid", etgl->vertical_draw_grid,
298 		"drawfocus", etgl->draw_focus,
299 		"cursor_mode", etgl->cursor_mode,
300 		"minimum_width", etgl->minimum_width,
301 		"length_threshold", etgl->length_threshold,
302 		"selection_model", etgl->selection_model,
303 		"uniform_row_height", etgl->uniform_row_height,
304 		NULL));
305 
306 	etgl->etgl_cursor_change_id = g_signal_connect (
307 		etgl->item, "cursor_change",
308 		G_CALLBACK (etgl_cursor_change), etgl);
309 
310 	etgl->etgl_cursor_activated_id = g_signal_connect (
311 		etgl->item, "cursor_activated",
312 		G_CALLBACK (etgl_cursor_activated), etgl);
313 
314 	etgl->etgl_double_click_id = g_signal_connect (
315 		etgl->item, "double_click",
316 		G_CALLBACK (etgl_double_click), etgl);
317 
318 	etgl->etgl_right_click_id = g_signal_connect (
319 		etgl->item, "right_click",
320 		G_CALLBACK (etgl_right_click), etgl);
321 
322 	etgl->etgl_click_id = g_signal_connect (
323 		etgl->item, "click",
324 		G_CALLBACK (etgl_click), etgl);
325 
326 	etgl->etgl_key_press_id = g_signal_connect (
327 		etgl->item, "key_press",
328 		G_CALLBACK (etgl_key_press), etgl);
329 
330 	etgl->etgl_start_drag_id = g_signal_connect (
331 		etgl->item, "start_drag",
332 		G_CALLBACK (etgl_start_drag), etgl);
333 
334 	e_canvas_item_request_reflow (item);
335 }
336 
337 static void
338 etgl_add (ETableGroup *etg,
339           gint row)
340 {
341 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
342 
343 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
344 		e_table_subset_variable_add (
345 			E_TABLE_SUBSET_VARIABLE (etgl->ets), row);
346 	}
347 }
348 
349 static void
350 etgl_add_array (ETableGroup *etg,
351                 const gint *array,
352                 gint count)
353 {
354 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
355 
356 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
357 		e_table_subset_variable_add_array (
358 			E_TABLE_SUBSET_VARIABLE (etgl->ets), array, count);
359 	}
360 }
361 
362 static void
363 etgl_add_all (ETableGroup *etg)
364 {
365 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
366 
367 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
368 		e_table_subset_variable_add_all (
369 			E_TABLE_SUBSET_VARIABLE (etgl->ets));
370 	}
371 }
372 
373 static gboolean
374 etgl_remove (ETableGroup *etg,
375              gint row)
376 {
377 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
378 
379 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
380 		return e_table_subset_variable_remove (
381 			E_TABLE_SUBSET_VARIABLE (etgl->ets), row);
382 	}
383 	return FALSE;
384 }
385 
386 static void
387 etgl_increment (ETableGroup *etg,
388                 gint position,
389                 gint amount)
390 {
391 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
392 
393 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
394 		e_table_subset_variable_increment (
395 			E_TABLE_SUBSET_VARIABLE (etgl->ets),
396 			position, amount);
397 	}
398 }
399 
400 static void
401 etgl_decrement (ETableGroup *etg,
402                 gint position,
403                 gint amount)
404 {
405 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
406 
407 	if (E_IS_TABLE_SUBSET_VARIABLE (etgl->ets)) {
408 		e_table_subset_variable_decrement (
409 			E_TABLE_SUBSET_VARIABLE (etgl->ets),
410 			position, amount);
411 	}
412 }
413 
414 static gint
415 etgl_row_count (ETableGroup *etg)
416 {
417 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
418 
419 	return e_table_model_row_count (E_TABLE_MODEL (etgl->ets));
420 }
421 
422 static void
423 etgl_set_focus (ETableGroup *etg,
424                 EFocus direction,
425                 gint view_col)
426 {
427 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
428 
429 	if (direction == E_FOCUS_END) {
430 		e_table_item_set_cursor (
431 			etgl->item, view_col,
432 			e_table_model_row_count (E_TABLE_MODEL (etgl->ets)) - 1);
433 	} else {
434 		e_table_item_set_cursor (etgl->item, view_col, 0);
435 	}
436 }
437 
438 static gint
439 etgl_get_focus_column (ETableGroup *etg)
440 {
441 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
442 
443 	return e_table_item_get_focused_column (etgl->item);
444 }
445 
446 static EPrintable *
447 etgl_get_printable (ETableGroup *etg)
448 {
449 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
450 
451 	return e_table_item_get_printable (etgl->item);
452 }
453 
454 static void
455 etgl_compute_location (ETableGroup *etg,
456                        gint *x,
457                        gint *y,
458                        gint *row,
459                        gint *col)
460 {
461 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
462 
463 	e_table_item_compute_location (etgl->item, x, y, row, col);
464 }
465 
466 static void
467 etgl_get_mouse_over (ETableGroup *etg,
468                      gint *row,
469                      gint *col)
470 {
471 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
472 
473 	if (etgl->item && etgl->item->motion_row > -1 && etgl->item->motion_col > -1) {
474 		if (row)
475 			*row = etgl->item->motion_row;
476 		if (col)
477 			*col = etgl->item->motion_col;
478 	}
479 }
480 
481 static void
482 etgl_get_cell_geometry (ETableGroup *etg,
483                         gint *row,
484                         gint *col,
485                         gint *x,
486                         gint *y,
487                         gint *width,
488                         gint *height)
489 {
490 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg);
491 
492 	e_table_item_get_cell_geometry (etgl->item, row, col, x, y, width, height);
493 }
494 
495 static void
496 etgl_set_property (GObject *object,
497                    guint property_id,
498                    const GValue *value,
499                    GParamSpec *pspec)
500 {
501 	ETableGroup *etg = E_TABLE_GROUP (object);
502 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object);
503 
504 	switch (property_id) {
505 	case PROP_FROZEN:
506 		etg->frozen = g_value_get_boolean (value);
507 		break;
508 	case PROP_MINIMUM_WIDTH:
509 	case PROP_WIDTH:
510 		etgl->minimum_width = g_value_get_double (value);
511 		if (etgl->item) {
512 			gnome_canvas_item_set (
513 				GNOME_CANVAS_ITEM (etgl->item),
514 				"minimum_width", etgl->minimum_width,
515 				NULL);
516 		}
517 		break;
518 	case PROP_LENGTH_THRESHOLD:
519 		etgl->length_threshold = g_value_get_int (value);
520 		if (etgl->item) {
521 			gnome_canvas_item_set (
522 				GNOME_CANVAS_ITEM (etgl->item),
523 				"length_threshold", etgl->length_threshold,
524 				NULL);
525 		}
526 		break;
527 	case PROP_SELECTION_MODEL:
528 		if (etgl->selection_model)
529 			g_object_unref (etgl->selection_model);
530 		etgl->selection_model = E_SELECTION_MODEL (g_value_get_object (value));
531 		if (etgl->selection_model) {
532 			g_object_ref (etgl->selection_model);
533 		}
534 		if (etgl->item) {
535 			gnome_canvas_item_set (
536 				GNOME_CANVAS_ITEM (etgl->item),
537 				"selection_model", etgl->selection_model,
538 				NULL);
539 		}
540 		break;
541 
542 	case PROP_UNIFORM_ROW_HEIGHT:
543 		etgl->uniform_row_height = g_value_get_boolean (value);
544 		if (etgl->item) {
545 			gnome_canvas_item_set (
546 				GNOME_CANVAS_ITEM (etgl->item),
547 				"uniform_row_height", etgl->uniform_row_height,
548 				NULL);
549 		}
550 		break;
551 
552 	case PROP_TABLE_ALTERNATING_ROW_COLORS:
553 		etgl->alternating_row_colors = g_value_get_boolean (value);
554 		if (etgl->item) {
555 			gnome_canvas_item_set (
556 				GNOME_CANVAS_ITEM (etgl->item),
557 				"alternating_row_colors", etgl->alternating_row_colors,
558 				NULL);
559 		}
560 		break;
561 
562 	case PROP_TABLE_HORIZONTAL_DRAW_GRID:
563 		etgl->horizontal_draw_grid = g_value_get_boolean (value);
564 		if (etgl->item) {
565 			gnome_canvas_item_set (
566 				GNOME_CANVAS_ITEM (etgl->item),
567 				"horizontal_draw_grid", etgl->horizontal_draw_grid,
568 				NULL);
569 		}
570 		break;
571 
572 	case PROP_TABLE_VERTICAL_DRAW_GRID:
573 		etgl->vertical_draw_grid = g_value_get_boolean (value);
574 		if (etgl->item) {
575 			gnome_canvas_item_set (
576 				GNOME_CANVAS_ITEM (etgl->item),
577 				"vertical_draw_grid", etgl->vertical_draw_grid,
578 				NULL);
579 		}
580 		break;
581 
582 	case PROP_TABLE_DRAW_FOCUS:
583 		etgl->draw_focus = g_value_get_boolean (value);
584 		if (etgl->item) {
585 			gnome_canvas_item_set (
586 				GNOME_CANVAS_ITEM (etgl->item),
587 				"drawfocus", etgl->draw_focus,
588 				NULL);
589 		}
590 		break;
591 
592 	case PROP_CURSOR_MODE:
593 		etgl->cursor_mode = g_value_get_int (value);
594 		if (etgl->item) {
595 			gnome_canvas_item_set (
596 				GNOME_CANVAS_ITEM (etgl->item),
597 				"cursor_mode", etgl->cursor_mode,
598 				NULL);
599 		}
600 		break;
601 	default:
602 		break;
603 	}
604 }
605 
606 static void
607 etgl_get_property (GObject *object,
608                    guint property_id,
609                    GValue *value,
610                    GParamSpec *pspec)
611 {
612 	ETableGroup *etg = E_TABLE_GROUP (object);
613 	ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object);
614 
615 	switch (property_id) {
616 	case PROP_FROZEN:
617 		g_value_set_boolean (value, etg->frozen);
618 		break;
619 	case PROP_HEIGHT:
620 		g_value_set_double (value, etgl->height);
621 		break;
622 	case PROP_WIDTH:
623 		g_value_set_double (value, etgl->width);
624 		break;
625 	case PROP_MINIMUM_WIDTH:
626 		g_value_set_double (value, etgl->minimum_width);
627 		break;
628 	case PROP_UNIFORM_ROW_HEIGHT:
629 		g_value_set_boolean (value, etgl->uniform_row_height);
630 	default:
631 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
632 		break;
633 	}
634 }
635 
636 static void
637 etgl_class_init (ETableGroupLeafClass *class)
638 {
639 	GnomeCanvasItemClass *item_class = GNOME_CANVAS_ITEM_CLASS (class);
640 	ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS (class);
641 	GObjectClass *object_class = G_OBJECT_CLASS (class);
642 
643 	object_class->dispose = etgl_dispose;
644 	object_class->set_property = etgl_set_property;
645 	object_class->get_property = etgl_get_property;
646 
647 	item_class->realize = etgl_realize;
648 
649 	e_group_class->add = etgl_add;
650 	e_group_class->add_array = etgl_add_array;
651 	e_group_class->add_all = etgl_add_all;
652 	e_group_class->remove = etgl_remove;
653 	e_group_class->increment  = etgl_increment;
654 	e_group_class->decrement  = etgl_decrement;
655 	e_group_class->row_count  = etgl_row_count;
656 	e_group_class->set_focus  = etgl_set_focus;
657 	e_group_class->get_focus_column = etgl_get_focus_column;
658 	e_group_class->get_printable = etgl_get_printable;
659 	e_group_class->compute_location = etgl_compute_location;
660 	e_group_class->get_mouse_over = etgl_get_mouse_over;
661 	e_group_class->get_cell_geometry = etgl_get_cell_geometry;
662 
663 	g_object_class_install_property (
664 		object_class,
665 		PROP_TABLE_ALTERNATING_ROW_COLORS,
666 		g_param_spec_boolean (
667 			"alternating_row_colors",
668 			"Alternating Row Colors",
669 			"Alternating Row Colors",
670 			FALSE,
671 			G_PARAM_WRITABLE));
672 
673 	g_object_class_install_property (
674 		object_class,
675 		PROP_TABLE_HORIZONTAL_DRAW_GRID,
676 		g_param_spec_boolean (
677 			"horizontal_draw_grid",
678 			"Horizontal Draw Grid",
679 			"Horizontal Draw Grid",
680 			FALSE,
681 			G_PARAM_WRITABLE));
682 
683 	g_object_class_install_property (
684 		object_class,
685 		PROP_TABLE_VERTICAL_DRAW_GRID,
686 		g_param_spec_boolean (
687 			"vertical_draw_grid",
688 			"Vertical Draw Grid",
689 			"Vertical Draw Grid",
690 			FALSE,
691 			G_PARAM_WRITABLE));
692 
693 	g_object_class_install_property (
694 		object_class,
695 		PROP_TABLE_DRAW_FOCUS,
696 		g_param_spec_boolean (
697 			"drawfocus",
698 			"Draw focus",
699 			"Draw focus",
700 			FALSE,
701 			G_PARAM_WRITABLE));
702 
703 	g_object_class_install_property (
704 		object_class,
705 		PROP_CURSOR_MODE,
706 		g_param_spec_int (
707 			"cursor_mode",
708 			"Cursor mode",
709 			"Cursor mode",
710 			E_CURSOR_LINE,
711 			E_CURSOR_SPREADSHEET,
712 			E_CURSOR_LINE,
713 			G_PARAM_WRITABLE));
714 
715 	g_object_class_install_property (
716 		object_class,
717 		PROP_LENGTH_THRESHOLD,
718 		g_param_spec_int (
719 			"length_threshold",
720 			"Length Threshold",
721 			"Length Threshold",
722 			-1, G_MAXINT, 0,
723 			G_PARAM_WRITABLE));
724 
725 	g_object_class_install_property (
726 		object_class,
727 		PROP_SELECTION_MODEL,
728 		g_param_spec_object (
729 			"selection_model",
730 			"Selection model",
731 			"Selection model",
732 			E_TYPE_SELECTION_MODEL,
733 			G_PARAM_WRITABLE));
734 
735 	g_object_class_install_property (
736 		object_class,
737 		PROP_HEIGHT,
738 		g_param_spec_double (
739 			"height",
740 			"Height",
741 			"Height",
742 			0.0, G_MAXDOUBLE, 0.0,
743 			G_PARAM_READABLE));
744 
745 	g_object_class_install_property (
746 		object_class,
747 		PROP_WIDTH,
748 		g_param_spec_double (
749 			"width",
750 			"Width",
751 			"Width",
752 			0.0, G_MAXDOUBLE, 0.0,
753 			G_PARAM_READWRITE));
754 
755 	g_object_class_install_property (
756 		object_class,
757 		PROP_MINIMUM_WIDTH,
758 		g_param_spec_double (
759 			"minimum_width",
760 			"Minimum width",
761 			"Minimum Width",
762 			0.0, G_MAXDOUBLE, 0.0,
763 			G_PARAM_READWRITE));
764 
765 	g_object_class_install_property (
766 		object_class,
767 		PROP_FROZEN,
768 		g_param_spec_boolean (
769 			"frozen",
770 			"Frozen",
771 			"Frozen",
772 			FALSE,
773 			G_PARAM_READWRITE));
774 
775 	g_object_class_install_property (
776 		object_class,
777 		PROP_UNIFORM_ROW_HEIGHT,
778 		g_param_spec_boolean (
779 			"uniform_row_height",
780 			"Uniform row height",
781 			"Uniform row height",
782 			FALSE,
783 			G_PARAM_READWRITE));
784 }
785 
786 static void
787 etgl_init (ETableGroupLeaf *etgl)
788 {
789 	etgl->width = 1;
790 	etgl->height = 1;
791 	etgl->minimum_width = 0;
792 
793 	etgl->ets = NULL;
794 	etgl->item = NULL;
795 
796 	etgl->etgl_cursor_change_id = 0;
797 	etgl->etgl_cursor_activated_id = 0;
798 	etgl->etgl_double_click_id = 0;
799 	etgl->etgl_right_click_id = 0;
800 	etgl->etgl_click_id = 0;
801 	etgl->etgl_key_press_id = 0;
802 	etgl->etgl_start_drag_id = 0;
803 
804 	etgl->alternating_row_colors = 1;
805 	etgl->horizontal_draw_grid = 1;
806 	etgl->vertical_draw_grid = 1;
807 	etgl->draw_focus = 1;
808 	etgl->cursor_mode = E_CURSOR_SIMPLE;
809 	etgl->length_threshold = -1;
810 
811 	etgl->selection_model = NULL;
812 	etgl->uniform_row_height = FALSE;
813 
814 	e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (etgl), etgl_reflow);
815 }