adg: corrected bug in while changing cell values
[adg.git] / src / adg / adg-table-cell.c
blobe07e74ce4e3db8be9b164e3e9eb20c33429b12ee
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-table-cell
23 * @Section_Id:AdgTableCell
24 * @title: AdgTableCell
25 * @short_description: A single cell of an #AdgTable
27 * The #AdgTableCell is a boxed type, the basic component of an
28 * #AdgTable entity. It must be added to an #AdgTableRow that,
29 * in cascade, will be added to an #AdgTable entity.
31 * Any cell can be filled with a title and a value: the font to be
32 * used will be picked up from the #AdgTableStyle got by resolving
33 * the #AdgTable:table-dress property.
35 * The default title is placed at the upper left corner of the cell
36 * while the value is centered up to the bottom edge of the cell.
37 * Anyway the text positioning can be customized by using the
38 * adg_table_cell_set_value_pos() method.
40 * Some convenient functions to easily create title and value entities
41 * with plain text are provided: adg_table_cell_new_full(),
42 * adg_table_cell_set_text_title() and adg_table_cell_set_text_value().
43 * When using these methods keep in mind the underlying #AdgToyText
44 * entities will be displaced accordingly to the
45 * #AdgTableStyle:cell-padding value, not used when setting the
46 * entities throught other APIs.
48 * Since: 1.0
49 **/
51 /**
52 * AdgTableCell:
54 * An opaque structure referring to the cell of an #AdgTableRow.
55 * Any row can have an unlimited number of cells.
57 * Since: 1.0
58 **/
61 #include "adg-internal.h"
62 #include "adg-text-internal.h"
64 #include "adg-container.h"
65 #include "adg-alignment.h"
66 #include "adg-textual.h"
67 #include "adg-style.h"
68 #include "adg-table-style.h"
70 #include "adg-table.h"
71 #include "adg-table-row.h"
72 #include "adg-table-cell.h"
75 struct _AdgTableCell {
76 AdgTableRow *row;
77 gdouble width;
78 gboolean has_frame;
79 AdgEntity *title;
80 AdgEntity *value;
81 AdgPair value_factor;
82 CpmlExtents extents;
86 static AdgTableCell * _adg_cell_new (void);
87 static void _adg_cell_invalidate (AdgTableCell *table_cell);
88 static gboolean _adg_cell_set_title (AdgTableCell *table_cell,
89 AdgEntity *title);
90 static gboolean _adg_cell_set_value (AdgTableCell *table_cell,
91 AdgEntity *value);
92 static void _adg_cell_set_value_pos (AdgTableCell *table_cell,
93 const AdgPair *from_factor,
94 const AdgPair *to_factor);
97 GType
98 adg_table_cell_get_type(void)
100 static GType cell_type = 0;
102 if (G_UNLIKELY(cell_type == 0))
103 cell_type = g_boxed_type_register_static("AdgTableCell",
104 (GBoxedCopyFunc) adg_table_cell_dup,
105 (GBoxedFreeFunc) adg_table_cell_free);
107 return cell_type;
112 * adg_table_cell_dup:
113 * @table_cell: an #AdgTableCell structure
115 * Duplicates @table_cell. The returned duplicate should be freed
116 * with adg_table_cell_free() when no longer needed.
118 * Returns: (transfer full): a duplicate of @table_cell.
120 * Since: 1.0
122 AdgTableCell *
123 adg_table_cell_dup(const AdgTableCell *table_cell)
125 return g_memdup(table_cell, sizeof(AdgTableCell));
129 * adg_table_cell_new:
130 * @table_row: a valid #AdgTableRow
132 * Creates a new empty cell without a frame and appends it at the
133 * end of the cells yet present in @table_row. You can add content
134 * to the cell by using adg_table_cell_set_title() and
135 * adg_table_cell_set_value() or enable the frame with
136 * adg_table_cell_switch_frame().
138 * Returns: (transfer full): the newly created cell or %NULL on errors.
140 * Since: 1.0
142 AdgTableCell *
143 adg_table_cell_new(AdgTableRow *table_row)
145 AdgTableCell *table_cell;
147 g_return_val_if_fail(table_row != NULL, NULL);
149 table_cell = _adg_cell_new();
150 table_cell->row = table_row;
152 adg_table_row_insert(table_row, table_cell, NULL);
153 _adg_cell_invalidate(table_cell);
155 return table_cell;
159 * adg_table_cell_new_before:
160 * @before_cell: a valid #AdgTableCell
162 * Creates a new cell and inserts it rigthly before the @table_cell cell.
164 * Returns: (transfer full): the newly created cell or %NULL on errors.
166 * Since: 1.0
168 AdgTableCell *
169 adg_table_cell_new_before(AdgTableCell *before_cell)
171 AdgTableRow *table_row;
172 AdgTableCell *table_cell;
174 g_return_val_if_fail(before_cell != NULL, NULL);
176 table_row = before_cell->row;
177 g_return_val_if_fail(table_row != NULL, NULL);
179 table_cell = _adg_cell_new();
180 table_cell->row = table_row;
182 adg_table_row_insert(table_row, table_cell, NULL);
183 _adg_cell_invalidate(table_cell);
185 return table_cell;
189 * adg_table_cell_new_with_width:
190 * @table_row: a valid #AdgTableRow
191 * @width: the cell width
193 * A convenient wrapper to adg_table_cell_new() that allows to
194 * specify the @width of @table_row all at once.
196 * Returns: (transfer full): the newly created cell or %NULL on errors.
198 * Since: 1.0
200 AdgTableCell *
201 adg_table_cell_new_with_width(AdgTableRow *table_row, gdouble width)
203 AdgTableCell *table_cell = adg_table_cell_new(table_row);
205 if (table_cell != NULL)
206 adg_table_cell_set_width(table_cell, width);
208 return table_cell;
212 * adg_table_cell_new_full:
213 * @table_row: a valid #AdgTableRow
214 * @width: the cell width
215 * @name: (allow-none): the name to bound to this cell
216 * @title: (allow-none): the title text
217 * @has_frame: whether to draw or not the frame
219 * A convenient function to add a cell and specifies some common
220 * used properties at once.
222 * If @name is %NULL, the created cell will not be a named cell.
223 * Check adg_table_set_cell() for further details on what a named
224 * cell is supposed to be..
226 * @title can be %NULL, in which case no title entity will be created.
228 * Returns: (transfer full): the newly created cell or %NULL on errors.
230 * Since: 1.0
232 AdgTableCell *
233 adg_table_cell_new_full(AdgTableRow *table_row, gdouble width,
234 const gchar *name, const gchar *title,
235 gboolean has_frame)
237 AdgTableCell *table_cell = adg_table_cell_new(table_row);
239 if (table_cell == NULL)
240 return NULL;
242 adg_table_cell_set_width(table_cell, width);
243 adg_table_cell_switch_frame(table_cell, has_frame);
245 if (title) {
246 adg_table_cell_set_text_title(table_cell, title);
248 if (name) {
249 AdgTable *table = adg_table_row_get_table(table_row);
250 adg_table_set_cell(table, name, table_cell);
253 return table_cell;
257 * adg_table_cell_dispose:
258 * @table_cell: a valid #AdgTableCell struct
260 * Disposes @table_cell.
262 * Since: 1.0
264 void
265 adg_table_cell_dispose(AdgTableCell *table_cell)
267 _adg_cell_set_title(table_cell, NULL);
268 _adg_cell_set_value(table_cell, NULL);
272 * adg_table_cell_free:
273 * @table_cell: an #AdgTableCell structure
275 * Releases all the memory allocated by @table_cell, itself included.
277 * Since: 1.0
279 void
280 adg_table_cell_free(AdgTableCell *table_cell)
282 AdgTableRow *table_row = table_cell->row;
284 if (table_cell->row != NULL) {
285 AdgTable *table = adg_table_row_get_table(table_row);
286 adg_table_row_remove(table_row, table_cell);
287 if (table)
288 adg_table_set_cell(table, NULL, table_cell);
291 adg_table_cell_dispose(table_cell);
292 g_free(table_cell);
296 * adg_table_cell_get_row:
297 * @table_cell: a valid #AdgTableCell
299 * Gets the row container of @table_cell. The returned #AdgTableRow
300 * is owned by @table_cell and must not be modified or freed.
302 * Returns: (transfer none): the container row.
304 * Since: 1.0
306 AdgTableRow *
307 adg_table_cell_get_row(AdgTableCell *table_cell)
309 g_return_val_if_fail(table_cell != NULL, NULL);
310 return table_cell->row;
314 * adg_table_cell_get_table:
315 * @table_cell: a valid #AdgTableCell
317 * A convenient function that gets the table that contains
318 * @table_cell. The returned #AdgTable is owned by @table_cell
319 * and must not be modified or freed.
321 * Returns: (transfer none): the container table.
323 * Since: 1.0
325 AdgTable *
326 adg_table_cell_get_table(AdgTableCell *table_cell)
328 AdgTableRow *table_row = adg_table_cell_get_row(table_cell);
329 if (table_row == NULL)
330 return NULL;
332 return adg_table_row_get_table(table_row);
336 * adg_table_cell_set_title:
337 * @table_cell: a valid #AdgTableCell
338 * @title: the new title entity
340 * Sets @title as the new title entity of @table_cell. The top left
341 * corner of the bounding box of @title will be cohincident to
342 * the top left corner of the cell extents, taking into accounts
343 * eventual padding spaces specified by the table style.
345 * The old internal entity is unrefenrenced while the @title (if
346 * not %NULL) is refenenced with g_object_ref_sink().
348 * @title can be %NULL, in which case the old entity is removed.
350 * Since: 1.0
352 void
353 adg_table_cell_set_title(AdgTableCell *table_cell, AdgEntity *title)
355 g_return_if_fail(table_cell != NULL);
356 g_return_if_fail(title == NULL || ADG_IS_ENTITY(title));
358 if (_adg_cell_set_title(table_cell, title))
359 _adg_cell_invalidate(table_cell);
363 * adg_table_cell_set_text_title:
364 * @table_cell: a valid #AdgTableCell
365 * @title: a text string
367 * Convenient function to set a the title of a cell using an #AdgToyText
368 * entity with the font dress picked from #AdgTable:table-dress with
369 * a call to adg_table_style_get_title_dress().
371 * Since: 1.0
373 void
374 adg_table_cell_set_text_title(AdgTableCell *table_cell, const gchar *title)
376 AdgTable *table;
377 AdgEntity *entity;
378 AdgTableStyle *table_style;
379 const AdgPair *padding;
380 AdgDress table_dress, font_dress;
381 AdgMatrix map;
383 g_return_if_fail(table_cell != NULL);
385 if (title == NULL)
386 adg_table_cell_set_title(table_cell, NULL);
388 if (table_cell->title) {
389 gchar *old_title;
390 gboolean unchanged;
392 if (ADG_IS_TEXTUAL(table_cell->title))
393 old_title = adg_textual_dup_text((AdgTextual *) table_cell->title);
394 else
395 old_title = NULL;
397 unchanged = g_strcmp0(title, old_title) == 0;
398 g_free(old_title);
400 if (unchanged)
401 return;
404 table = adg_table_cell_get_table(table_cell);
405 table_dress = adg_table_get_table_dress(table);
406 table_style = (AdgTableStyle *) adg_entity_style((AdgEntity *) table,
407 table_dress);
408 padding = adg_table_style_get_cell_padding(table_style);
409 font_dress = adg_table_style_get_title_dress(table_style);
410 entity = g_object_new(ADG_TYPE_BEST_TEXT, "text", title,
411 "font-dress", font_dress, NULL);
413 cairo_matrix_init_translate(&map, padding->x, padding->y);
414 adg_entity_set_global_map(entity, &map);
416 adg_table_cell_set_title(table_cell, entity);
420 * adg_table_cell_title:
421 * @table_cell: a valid #AdgTableCell
423 * Gets the current title of @table_cell. The returned string is owned
424 * by @table_cell and must not be modified or freed.
426 * Returns: (transfer none): the title entity or %NULL for undefined title.
428 * Since: 1.0
430 AdgEntity *
431 adg_table_cell_title(AdgTableCell *table_cell)
433 g_return_val_if_fail(table_cell != NULL, NULL);
435 return table_cell->title;
439 * adg_table_cell_set_value:
440 * @table_cell: a valid #AdgTableCell
441 * @value: the new value entity
443 * Sets @value as the new value entity of @table_cell. The bottom middle
444 * point of the bounding box of @value will be cohincident to the
445 * bottom middle point of the cell extents, taking into accounts
446 * eventual padding spaces specified by the table style.
448 * The old internal entity is unrefenrenced while the @value (if
449 * not %NULL) is refenenced with g_object_ref_sink().
451 * @value can be %NULL, in which case the old entity is removed.
453 * Since: 1.0
455 void
456 adg_table_cell_set_value(AdgTableCell *table_cell, AdgEntity *value)
458 g_return_if_fail(table_cell != NULL);
459 g_return_if_fail(value == NULL || ADG_IS_ENTITY(value));
461 if (_adg_cell_set_value(table_cell, value))
462 _adg_cell_invalidate(table_cell);
466 * adg_table_cell_set_text_value:
467 * @table_cell: a valid #AdgTableCell
468 * @value: a text string
470 * Convenient function to set a the value of a cell using an #AdgToyText
471 * entity with a value font dress picked from #AdgTable:table-dress with
472 * a call to adg_table_style_get_value_dress().
474 * Since: 1.0
476 void
477 adg_table_cell_set_text_value(AdgTableCell *table_cell, const gchar *value)
479 AdgTable *table;
480 AdgEntity *entity;
481 AdgTableStyle *table_style;
482 const AdgPair *padding;
483 AdgDress table_dress, font_dress;
484 AdgMatrix map;
486 g_return_if_fail(table_cell != NULL);
488 if (value == NULL)
489 adg_table_cell_set_value(table_cell, NULL);
491 if (table_cell->value) {
492 gchar *old_value;
493 gboolean unchanged;
495 if (ADG_IS_TEXTUAL(table_cell->value))
496 old_value = adg_textual_dup_text((AdgTextual *) table_cell->value);
497 else
498 old_value = NULL;
500 unchanged = g_strcmp0(value, old_value) == 0;
501 g_free(old_value);
502 if (unchanged)
503 return;
506 table = adg_table_cell_get_table(table_cell);
507 table_dress = adg_table_get_table_dress(table);
508 table_style = (AdgTableStyle *) adg_entity_style((AdgEntity *) table,
509 table_dress);
510 padding = adg_table_style_get_cell_padding(table_style);
511 font_dress = adg_table_style_get_value_dress(table_style);
512 entity = g_object_new(ADG_TYPE_BEST_TEXT, "text", value,
513 "font-dress", font_dress, NULL);
515 cairo_matrix_init_translate(&map, 0, -padding->y);
516 adg_entity_set_global_map(entity, &map);
518 adg_table_cell_set_value(table_cell, entity);
522 * adg_table_cell_value:
523 * @table_cell: a valid #AdgTableCell
525 * Gets the current value of @table_cell. The returned string is owned
526 * by @table_cell and must not be modified or freed.
528 * Returns: (transfer none): the value entity or %NULL for undefined value.
530 * Since: 1.0
532 AdgEntity *
533 adg_table_cell_value(AdgTableCell *table_cell)
535 g_return_val_if_fail(table_cell != NULL, NULL);
537 return table_cell->value;
541 * adg_table_cell_set_value_pos:
542 * @table_cell: a valid #AdgTableCell
543 * @from_factor: the alignment factor on the value entity
544 * @to_factor: the alignment factor on the cell
546 * Sets a new custom position for the value entity of @table_cell. The
547 * @from_factor specifies the source point (as a fraction of the
548 * value extents) while the @to_factor is the destination point
549 * (specified as a fraction of the cell extents) the source point
550 * must be moved to.
552 * Since: 1.0
554 void
555 adg_table_cell_set_value_pos(AdgTableCell *table_cell,
556 const AdgPair *from_factor,
557 const AdgPair *to_factor)
559 g_return_if_fail(table_cell != NULL);
560 _adg_cell_set_value_pos(table_cell, from_factor, to_factor);
564 * adg_table_cell_set_value_pos_explicit:
565 * @table_cell: a valid #AdgTableCell
566 * @from_x: the x alignment factor on the entity
567 * @from_y: the y alignment factor on the entity
568 * @to_x: the x alignment factor on the cell
569 * @to_y: the y alignment factor on the cell
571 * A convenient wrapper around adg_table_cell_set_value_pos()
572 * that uses explicit factors instead of #AdgPair.
574 * Since: 1.0
576 void
577 adg_table_cell_set_value_pos_explicit(AdgTableCell *table_cell,
578 gdouble from_x, gdouble from_y,
579 gdouble to_x, gdouble to_y)
581 AdgPair from, to;
583 from.x = from_x;
584 from.y = from_y;
585 to.x = to_x;
586 to.y = to_y;
588 adg_table_cell_set_value_pos(table_cell, &from, &to);
592 * adg_table_cell_set_width:
593 * @table_cell: a valid #AdgTableCell
594 * @width: the new width
596 * Sets a new width on @table_cell. The extents on the whole table
597 * will be invalidated, so will be recomputed in the next
598 * arrange() phase.
600 * A positive @width value specifies the width of this cell in global
601 * space: if the width of its content (that is, either the title or the
602 * value entity) will be greater than @width, it will be rendered
603 * outside the cell boundary box, luckely overwriting the adiacent
604 * cells.
606 * Using %0 as @width means the width of the cell will be automatically
607 * adjusted to the maximum width of its content.
609 * Negative width values are not allowed: this condition will raise
610 * a warning without any further processing.
612 * Since: 1.0
614 void
615 adg_table_cell_set_width(AdgTableCell *table_cell, gdouble width)
617 g_return_if_fail(table_cell != NULL);
618 g_return_if_fail(width >= 0);
620 if (table_cell->width != width) {
621 table_cell->width = width;
622 _adg_cell_invalidate(table_cell);
627 * adg_table_cell_get_width:
628 * @table_cell: a valid #AdgTableCell
630 * Gets the width of @table_cell.
632 * Returns: the requested width or %0 on errors
634 * Since: 1.0
636 gdouble
637 adg_table_cell_get_width(AdgTableCell *table_cell)
639 g_return_val_if_fail(table_cell != NULL, 0.);
641 return table_cell->width;
645 * adg_table_cell_switch_frame:
646 * @table_cell: a valid #AdgTableCell
647 * @has_frame: whether to draw or not the frame
649 * Sets the frame flag of @table_cell: if @has_frame is %TRUE, a frame around
650 * @table_cell will be rendered using the #AdgTableStyle:cell-dress dress
651 * of the table style.
653 * Since: 1.0
655 void
656 adg_table_cell_switch_frame(AdgTableCell *table_cell, gboolean has_frame)
658 g_return_if_fail(table_cell != NULL);
660 if (table_cell->has_frame != has_frame) {
661 AdgTable *table = adg_table_cell_get_table(table_cell);
662 table_cell->has_frame = has_frame;
663 adg_table_invalidate_grid(table);
668 * adg_table_cell_has_frame:
669 * @table_cell: a valid #AdgTableCell
671 * Gets the frame flag of @table_cell.
673 * Returns: the frame flag.
675 * Since: 1.0
677 gboolean
678 adg_table_cell_has_frame(AdgTableCell *table_cell)
680 g_return_val_if_fail(table_cell != NULL, FALSE);
682 return table_cell->has_frame;
686 * adg_table_cell_get_extents:
687 * @table_cell: a valid #AdgTableCell
689 * Gets the extents of @table_cell. This function is useful only after the
690 * arrange() phase as in the other situation the extents will likely
691 * be not up to date.
693 * Returns: the extents of @table_cell or %NULL on errors
695 * Since: 1.0
697 const CpmlExtents *
698 adg_table_cell_get_extents(AdgTableCell *table_cell)
700 g_return_val_if_fail(table_cell != NULL, NULL);
702 return &table_cell->extents;
706 * adg_table_cell_size_request:
707 * @table_cell: a valid #AdgTableCell
708 * @row_extents: the extents of the container #AdgTableRow
710 * Computes the minimum space needed to properly render @table_cell
711 * and updates the size component of the internal #CpmlExtents struct,
712 * returning it to the caller. The returned #AdgPair is owned by
713 * @table_cell and should not be modified or freed.
715 * Returns: (transfer none): the minimum size required.
717 * Since: 1.0
719 const AdgPair *
720 adg_table_cell_size_request(AdgTableCell *table_cell,
721 const CpmlExtents *row_extents)
723 CpmlVector *size;
724 AdgAlignment *title_alignment;
725 AdgAlignment *value_alignment;
726 AdgTable *table;
728 size = &table_cell->extents.size;
730 if (table_cell->title) {
731 title_alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->title);
732 adg_entity_arrange((AdgEntity *) title_alignment);
733 } else {
734 title_alignment = NULL;
737 if (table_cell->value) {
738 value_alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->value);
739 adg_entity_arrange((AdgEntity *) value_alignment);
740 } else {
741 value_alignment = NULL;
744 table = adg_table_cell_get_table(table_cell);
745 size->y = row_extents->size.y;
747 if (table_cell->width == 0) {
748 AdgTableStyle *table_style = (AdgTableStyle *) adg_table_get_table_style(table);
749 const CpmlExtents *extents;
751 /* The width depends on the cell content (default = 0) */
752 size->x = 0;
754 if (title_alignment) {
755 extents = adg_entity_get_extents((AdgEntity *) title_alignment);
756 size->x = extents->size.x;
759 if (value_alignment) {
760 extents = adg_entity_get_extents((AdgEntity *) value_alignment);
761 if (extents->size.x > size->x)
762 size->x = extents->size.x;
765 size->x += adg_table_style_get_cell_spacing(table_style)->x * 2;
766 } else {
767 size->x = table_cell->width;
770 return size;
774 * adg_table_cell_arrange:
775 * @table_cell: an #AdgTableCell
776 * @layout: the new extents to use
778 * Rearranges the underlying #AdgTableCell owned by @table_cell using
779 * the new extents provided in @layout. If the x or y size component
780 * of @layout is negative, the value holded by the internal extents
781 * struct is not overriden.
783 * <note><para>
784 * table_cell->extents must be up to date if @layout->size.x or
785 * @layout->size.y is negative in order to have a valid size.
786 * </para></note>
788 * Returns: the extents of @table_cell or %NULL on errors
790 * Since: 1.0
792 const CpmlExtents *
793 adg_table_cell_arrange(AdgTableCell *table_cell, const CpmlExtents *layout)
795 CpmlExtents *extents;
796 AdgAlignment *alignment;
797 AdgMatrix map;
799 /* Set the new extents */
800 extents = &table_cell->extents;
801 extents->org = layout->org;
802 if (layout->size.x > 0)
803 extents->size.x = layout->size.x;
804 if (layout->size.y > 0)
805 extents->size.y = layout->size.y;
806 extents->is_defined = TRUE;
808 if (table_cell->title) {
809 alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->title);
811 cairo_matrix_init_translate(&map, extents->org.x, extents->org.y);
812 adg_entity_set_global_map((AdgEntity *) alignment, &map);
815 if (table_cell->value) {
816 AdgPair to;
818 alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->value);
819 to.x = extents->size.x * table_cell->value_factor.x + extents->org.x;
820 to.y = extents->size.y * table_cell->value_factor.y + extents->org.y;
822 cairo_matrix_init_translate(&map, to.x, to.y);
823 adg_entity_set_global_map((AdgEntity *) alignment, &map);
826 return extents;
830 static AdgTableCell *
831 _adg_cell_new(void)
833 AdgTableCell *table_cell;
835 table_cell = g_new(AdgTableCell, 1);
836 table_cell->row = NULL;
837 table_cell->width = 0.;
838 table_cell->has_frame = FALSE;
839 table_cell->title = NULL;
840 table_cell->value = NULL;
841 table_cell->extents.is_defined = FALSE;
842 table_cell->value_factor.x = 0.5;
843 table_cell->value_factor.y = 1;
845 return table_cell;
848 static void
849 _adg_cell_invalidate(AdgTableCell *table_cell)
851 AdgTable *table = adg_table_cell_get_table(table_cell);
853 if (table)
854 adg_entity_invalidate((AdgEntity *) table);
857 static gboolean
858 _adg_cell_set_title(AdgTableCell *table_cell, AdgEntity *title)
860 AdgEntity *alignment;
862 if (table_cell->title == title)
863 return FALSE;
865 if (table_cell->title) {
866 alignment = adg_entity_get_parent(table_cell->title);
867 g_object_unref(alignment);
870 table_cell->title = title;
872 if (title) {
873 AdgEntity *table = (AdgEntity *) adg_table_cell_get_table(table_cell);
874 alignment = (AdgEntity *) adg_alignment_new_explicit(0, -1);
875 g_object_ref_sink(alignment);
876 adg_entity_set_parent(alignment, table);
877 adg_container_add((AdgContainer *) alignment, title);
880 return TRUE;
883 static gboolean
884 _adg_cell_set_value(AdgTableCell *table_cell, AdgEntity *value)
886 AdgEntity *alignment;
888 if (table_cell->value == value)
889 return FALSE;
891 if (value) {
892 AdgEntity *table = (AdgEntity *) adg_table_cell_get_table(table_cell);
893 alignment = (AdgEntity *) adg_alignment_new_explicit(0.5, 0);
894 g_object_ref_sink(alignment);
895 adg_entity_set_parent(alignment, table);
896 adg_container_add((AdgContainer *) alignment, value);
899 if (table_cell->value) {
900 alignment = adg_entity_get_parent(table_cell->value);
901 adg_container_remove((AdgContainer *) alignment, table_cell->value);
902 g_object_unref(alignment);
905 table_cell->value = value;
906 return TRUE;
909 static void
910 _adg_cell_set_value_pos(AdgTableCell *table_cell,
911 const AdgPair *from_factor, const AdgPair *to_factor)
913 AdgAlignment *alignment;
915 if (table_cell->value == NULL)
916 return;
918 alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->value);
920 if (from_factor)
921 adg_alignment_set_factor(alignment, from_factor);
923 if (to_factor)
924 table_cell->value_factor = *to_factor;