/* Fo * fo-area-normal.c: Normal block-area object * * Copyright (C) 2001 Sun Microsystems * Copyright (C) 2007 Menteith Consulting Ltd * * See COPYING for the status of this software. */ #include "fo-utils.h" #include "fo-area.h" #include "fo-area-area.h" #include "fo-area-area-private.h" #include "fo-area-normal.h" struct _FoAreaNormal { FoAreaArea parent_instance; }; struct _FoAreaNormalClass { FoAreaAreaClass parent_class; }; static void fo_area_normal_class_init (FoAreaNormalClass *klass); static void fo_area_normal_finalize (GObject *object); static void fo_area_normal_debug_dump_properties (FoArea *area, gint depth); static FoArea* fo_area_normal_size_request (FoArea *child); static gpointer parent_class; GType fo_area_normal_get_type (void) { static GType object_type = 0; if (!object_type) { static const GTypeInfo object_info = { sizeof (FoAreaNormalClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) fo_area_normal_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (FoAreaNormal), 0, /* n_preallocs */ NULL, /* instance_init */ NULL /* value_table */ }; object_type = g_type_register_static (FO_TYPE_AREA_AREA, "FoAreaNormal", &object_info, 0); } return object_type; } static void fo_area_normal_class_init (FoAreaNormalClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = fo_area_normal_finalize; FO_AREA_CLASS (klass)->debug_dump_properties = fo_area_normal_debug_dump_properties; FO_AREA_CLASS (klass)->size_request = fo_area_normal_size_request; } static void fo_area_normal_finalize (GObject *object) { FoAreaNormal *fo_area_normal; fo_area_normal = FO_AREA_NORMAL (object); G_OBJECT_CLASS (parent_class)->finalize (object); } /** * fo_area_normal_new: * * Creates a new #FoAreaNormal initialized to default value. * * Return value: the new #FoAreaNormal **/ FoArea* fo_area_normal_new (void) { return FO_AREA (g_object_new (fo_area_normal_get_type (), NULL)); } void fo_area_normal_debug_dump_properties (FoArea *area, gint depth) { FoAreaNormal *normal; gchar *indent = g_strnfill (depth * 2, ' '); g_return_if_fail (area != NULL); g_return_if_fail (FO_IS_AREA_NORMAL (area)); normal = FO_AREA_NORMAL (area); g_free (indent); FO_AREA_CLASS (parent_class)->debug_dump_properties (area, depth + 1); } FoArea* fo_area_normal_add_child (FoArea *parent, FoArea *child) { g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (FO_IS_AREA_NORMAL (parent), NULL); g_return_val_if_fail (child != NULL, NULL); return fo_area_real_add_child (parent, child); } /** * fo_area_normal_size_request: * @child: Child area * * Check that the parent area of @child has sufficient space for * @child. If not enough space, request that the parent has * sufficient space allocated for it, then adjust @child and its * siblings as necessary to fit into the resized parent area. * * Return value: Pointer to the last area generated from @child after * any reallocation and resizing **/ FoArea* fo_area_normal_size_request (FoArea *child) { FoArea *use_child_area; FoArea *parent; gfloat total_child_height = 0; gfloat normal_child_available_bpdim; gfloat child_height; gfloat child_space_before, child_space_after; g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (FO_IS_AREA_AREA (child), NULL); g_return_val_if_fail (!FO_AREA_IS_ROOT (child), NULL); g_return_val_if_fail (FO_IS_AREA_AREA (fo_area_parent (child)), NULL); child_height = fo_area_area_get_height (child); child_space_before = fo_area_area_get_space_before (child); child_space_after = fo_area_area_get_space_after (child); parent = fo_area_parent (child); normal_child_available_bpdim = fo_area_get_child_available_bpdim (parent); #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: parent: %s; generated by: %s; available_height: %f", child, fo_object_debug_sprintf (parent), fo_object_debug_sprintf (parent->generated_by), normal_child_available_bpdim); g_message ("normal_size_request (%p):: child: %s; generated by: %s; height: %f; space_before: %f; space_after: %f", child, fo_object_debug_sprintf (child), fo_object_debug_sprintf (child->generated_by), child_height, child_space_before, child_space_after); #endif fo_area_children_foreach (parent, G_TRAVERSE_ALL, &fo_area_accumulate_height, &total_child_height); #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: child total: %f", child, total_child_height); #endif fo_area_area_set_height (parent, total_child_height + fo_area_area_get_border_before (parent) + fo_area_area_get_padding_before (parent) + fo_area_area_get_padding_after (parent) + fo_area_area_get_border_after (parent)); /* Don't bother doing a size_request if still fit within available height */ if (normal_child_available_bpdim < fo_area_area_get_height (parent)) { parent = fo_area_size_request (parent); normal_child_available_bpdim = MAX (fo_area_get_available_height (parent) - fo_area_area_get_border_before (parent) - fo_area_area_get_padding_before (parent) - fo_area_area_get_padding_after (parent) - fo_area_area_get_border_after (parent), 0); fo_area_set_child_available_bpdim (parent, normal_child_available_bpdim); #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: new parent: %s; generated by: %s; available_height: %f", child, fo_object_debug_sprintf (parent), fo_object_debug_sprintf (parent->generated_by), normal_child_available_bpdim); #endif } total_child_height = 0; fo_area_children_foreach (parent, G_TRAVERSE_ALL, &fo_area_accumulate_height, &total_child_height); #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: new child total: %f", child, total_child_height); #endif fo_area_set_next_x (parent, fo_area_area_get_border_start (parent) + fo_area_area_get_padding_start (parent)); fo_area_set_next_y (parent, - (fo_area_area_get_border_before (parent) + fo_area_area_get_padding_before (parent))); if (total_child_height <= normal_child_available_bpdim) { use_child_area = fo_area_first_child (parent); while (use_child_area) { fo_area_area_set_x (use_child_area, fo_area_get_next_x (parent) + fo_area_area_get_start_indent (use_child_area) - fo_area_area_get_x (parent)); fo_area_area_set_y (use_child_area, fo_area_get_next_y (parent)); fo_area_set_next_x (parent, 0); fo_area_set_next_y (parent, fo_area_get_next_y (parent) - fo_area_area_get_height (use_child_area)); fo_area_set_available_height (child, fo_area_area_get_height (use_child_area)); fo_area_set_available_width (child, fo_area_get_child_available_ipdim (parent)); use_child_area = fo_area_next_sibling (use_child_area); } #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: return:: parent->last: %s; generated by: %s", child, fo_object_debug_sprintf (fo_area_last_child (parent)), fo_object_debug_sprintf (fo_area_last_child (parent->generated_by))); #endif return fo_area_last_child (parent); } else { use_child_area = fo_area_first_child (parent); while (use_child_area) { if (normal_child_available_bpdim >= fo_area_area_get_height (use_child_area)) { fo_area_area_set_x (use_child_area, fo_area_get_next_x (parent) + fo_area_area_get_start_indent (use_child_area)); fo_area_area_set_y (use_child_area, fo_area_get_next_y (parent)); fo_area_set_next_x (parent, 0); fo_area_set_next_y (parent, fo_area_get_next_y (parent) - fo_area_area_get_height (use_child_area)); fo_area_set_available_height (child, fo_area_area_get_height (use_child_area)); fo_area_set_available_width (child, fo_area_get_child_available_ipdim (parent)); use_child_area = fo_area_next_sibling (use_child_area); } else { #if defined(LIBFO_DEBUG) && 1 g_message ("normal_size_request:: splitting:: child: %s; generated by: %s", fo_object_debug_sprintf (use_child_area), fo_object_debug_sprintf (use_child_area->generated_by)); #endif use_child_area = fo_area_split_before_height (use_child_area, normal_child_available_bpdim - fo_area_area_get_height (parent)); parent = fo_area_parent (use_child_area); normal_child_available_bpdim = fo_area_get_child_available_bpdim (parent); } } #if defined(LIBFO_DEBUG) && 0 g_message ("normal_size_request (%p):: total > available:: return:: parent->last: %s; generated by: %s", child, fo_object_debug_sprintf (fo_area_last_child (parent)), fo_object_debug_sprintf (fo_area_last_child (parent->generated_by))); #endif return fo_area_last_child (parent); } }