From 9306a73dfd5f061326a584a6c11971361fa7095a Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Wed, 21 Apr 2010 01:32:55 -0400 Subject: Added documentation, implemented gtk_extended_layout_is_height_for_width() where needed. --- gtk/gtkbin.c | 32 ++++++++++++++------- gtk/gtkbox.c | 11 +++++++- gtk/gtkextendedlayout.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++-- gtk/gtklabel.c | 45 ++++++++++++++++++------------ 4 files changed, 132 insertions(+), 30 deletions(-) diff --git a/gtk/gtkbin.c b/gtk/gtkbin.c index 691fb89b6..ed2796a89 100644 --- a/gtk/gtkbin.c +++ b/gtk/gtkbin.c @@ -41,16 +41,16 @@ static void gtk_bin_forall (GtkContainer *container, static GType gtk_bin_child_type (GtkContainer *container); -static void gtk_bin_extended_layout_init (GtkExtendedLayoutIface *iface); -static void gtk_bin_get_width_for_height (GtkExtendedLayout *layout, - gint height, - gint *minimum_width, - gint *natural_width); -static void gtk_bin_get_height_for_width (GtkExtendedLayout *layout, - gint width, - gint *minimum_height, - gint *natural_height); - +static void gtk_bin_extended_layout_init (GtkExtendedLayoutIface *iface); +static gboolean gtk_bin_is_height_for_width (GtkExtendedLayout *layout); +static void gtk_bin_get_width_for_height (GtkExtendedLayout *layout, + gint height, + gint *minimum_width, + gint *natural_width); +static void gtk_bin_get_height_for_width (GtkExtendedLayout *layout, + gint width, + gint *minimum_height, + gint *natural_height); static GtkExtendedLayoutIface *parent_extended_layout_iface; @@ -159,10 +159,22 @@ gtk_bin_extended_layout_init (GtkExtendedLayoutIface *iface) { parent_extended_layout_iface = g_type_interface_peek_parent (iface); + iface->is_height_for_width = gtk_bin_is_height_for_width; iface->get_width_for_height = gtk_bin_get_width_for_height; iface->get_height_for_width = gtk_bin_get_height_for_width; } +static gboolean +gtk_bin_is_height_for_width (GtkExtendedLayout *layout) +{ + GtkBin *bin = GTK_BIN (layout); + + if (bin->child) + return gtk_extended_layout_is_height_for_width (GTK_EXTENDED_LAYOUT (bin->child)); + + return TRUE; +} + static void get_child_padding_delta (GtkBin *bin, gint *delta_h, diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c index 6d470352d..96009696b 100644 --- a/gtk/gtkbox.c +++ b/gtk/gtkbox.c @@ -110,6 +110,7 @@ static GType gtk_box_child_type (GtkContainer *container); static void gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface); +static gboolean gtk_box_is_height_for_width (GtkExtendedLayout *layout); static void gtk_box_get_desired_width (GtkExtendedLayout *layout, gint *minimum_size, gint *natural_size); @@ -765,18 +766,26 @@ gtk_box_pack (GtkBox *box, } - static void gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface) { parent_extended_layout_iface = g_type_interface_peek_parent (iface); + iface->is_height_for_width = gtk_box_is_height_for_width; iface->get_desired_width = gtk_box_get_desired_width; iface->get_desired_height = gtk_box_get_desired_height; iface->get_height_for_width = gtk_box_get_height_for_width; iface->get_width_for_height = gtk_box_get_width_for_height; } +static gboolean +gtk_box_is_height_for_width (GtkExtendedLayout *layout) +{ + GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout); + + return (private->orientation == GTK_ORIENTATION_VERTICAL); +} + static void gtk_box_get_desired_size (GtkExtendedLayout *layout, GtkOrientation orientation, diff --git a/gtk/gtkextendedlayout.c b/gtk/gtkextendedlayout.c index c3108f0ea..da4ac26de 100644 --- a/gtk/gtkextendedlayout.c +++ b/gtk/gtkextendedlayout.c @@ -22,6 +22,64 @@ */ +/** + * SECTION:gtkextendedlayout + * @Short_Description: Height for Width Geometry management + * @Title: GtkExtendedLayout + * + * The extended layout is GTK+'s height for width geometry management + * system. + * + * + * Implementing GtkExtendedLayout + * + * Some important things to keep in mind when implementing + * or using the extended layout. + * + * The Extended Layout system will query a logical heirarchy in + * only one orientation at a time. When widgets are initially queried + * for their minimum sizes it is generally done in a dual pass + * in the direction chosen by the toplevel. + * + * For instance when queried in the normal height-for-width mode: + * First the default minimum and natural width for each widget + * in the interface will computed and collectively returned to + * the toplevel by way of gtk_extended_layout_get_desired_width(). + * Next; the toplevel will use the minimum width to query for the + * minimum height contextual to that width using gtk_extended_layout_get_height_for_width() + * which will also be a highly recursive operation. This minimum + * for minimum size can be used to set the minimum size constraint + * on the toplevel. + * + * When allocating; each container can use the minimum and natural + * sizes reported by thier children to allocate natural sizes and + * expose as much content as possible with the given allocation. + * + * That means that the request operation at allocation time will + * usually fire again in contexts of different allocated sizes than + * the ones originally queried for. + * + * A Widget that does not actually do height-for-width + * or width-for-height size negotiations only has to implement + * get_desired_width() and get_desired_height() + * + * If a widget does move content around to smartly use up the + * allocated size, then it must support the request properly in + * both orientations; even if the request only makes sense in + * one orientation. + * + * For instance; a GtkLabel that does height-for-width word wrapping + * will not expect to have get_desired_height() called because that + * call is specific to a width-for-height request, in this case the + * label must return the heights contextual to its minimum possible + * width. By following this rule any widget that handles height-for-width + * or width-for-height requests will always be allocated at least + * enough space to fit its own content. + * + * + */ + + #include #include "gtkextendedlayout.h" #include "gtksizegroup.h" @@ -73,7 +131,11 @@ gtk_extended_layout_get_type (void) } /* looks for a cached size request for this for_size. If not - * found, returns the oldest entry so it can be overwritten */ + * found, returns the oldest entry so it can be overwritten + * + * Note that this caching code was directly derived from + * the Clutter toolkit. + */ static gboolean get_cached_desired_size (gint for_size, DesiredSize *cached_sizes, @@ -283,6 +345,10 @@ compute_size_for_orientation (GtkExtendedLayout *layout, * Returns: %TRUE if the widget prefers height-for-width, %FALSE if * the widget should be treated with a width-for-height preference. * + * #GtkBin widgets generally propagate the preference of thier child, + * container widgets need to request something either in context of their + * children or in context of their allocation capabilities. + * * Since: 3.0 */ gboolean @@ -306,7 +372,9 @@ gtk_extended_layout_is_height_for_width (GtkExtendedLayout *layout) * @minimum_width: location to store the minimum size, or %NULL * @natural_width: location to store the natural size, or %NULL * - * Retreives a widget's minimum and natural size in a single dimension. + * Retreives a widget's initial minimum and natural width. + * + * This call is specific to height for width requests. * * Since: 3.0 */ @@ -327,6 +395,8 @@ gtk_extended_layout_get_desired_width (GtkExtendedLayout *layout, * * Retreives a widget's minimum and natural size in a single dimension. * + * This call is specific to width for height requests. + * * Since: 3.0 */ void diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 05c3e3113..6a3359ed1 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -304,22 +304,22 @@ static void gtk_label_get_link_colors (GtkWidget *widget, static void emit_activate_link (GtkLabel *label, GtkLabelLink *link); -static void gtk_label_extended_layout_init (GtkExtendedLayoutIface *iface); - -static void gtk_label_get_desired_width (GtkExtendedLayout *layout, - gint *minimum_size, - gint *natural_size); -static void gtk_label_get_desired_height (GtkExtendedLayout *layout, - gint *minimum_size, - gint *natural_size); -static void gtk_label_get_width_for_height (GtkExtendedLayout *layout, - gint height, - gint *minimum_width, - gint *natural_width); -static void gtk_label_get_height_for_width (GtkExtendedLayout *layout, - gint width, - gint *minimum_height, - gint *natural_height); +static void gtk_label_extended_layout_init (GtkExtendedLayoutIface *iface); +static gboolean gtk_label_is_height_for_width (GtkExtendedLayout *layout); +static void gtk_label_get_desired_width (GtkExtendedLayout *layout, + gint *minimum_size, + gint *natural_size); +static void gtk_label_get_desired_height (GtkExtendedLayout *layout, + gint *minimum_size, + gint *natural_size); +static void gtk_label_get_width_for_height (GtkExtendedLayout *layout, + gint height, + gint *minimum_width, + gint *natural_width); +static void gtk_label_get_height_for_width (GtkExtendedLayout *layout, + gint width, + gint *minimum_height, + gint *natural_height); static GQuark quark_angle = 0; @@ -3027,7 +3027,6 @@ get_label_width (GtkLabel *label, } else { - /* XXX Do something about width_chars/max_width_chars when no ellipsize/wrap is set */ *minimum = text_width; *natural = *minimum; } @@ -3284,12 +3283,24 @@ get_single_line_height (GtkWidget *widget, static void gtk_label_extended_layout_init (GtkExtendedLayoutIface *iface) { + iface->is_height_for_width = gtk_label_is_height_for_width; iface->get_desired_width = gtk_label_get_desired_width; iface->get_desired_height = gtk_label_get_desired_height; iface->get_width_for_height = gtk_label_get_width_for_height; iface->get_height_for_width = gtk_label_get_height_for_width; } +static gboolean +gtk_label_is_height_for_width (GtkExtendedLayout *layout) +{ + GtkLabel *label = GTK_LABEL (layout); + gdouble angle = gtk_label_get_angle (label); + + if (angle == 90 || angle == 270) + return FALSE; + + return TRUE; +} static void get_size_for_allocation (GtkLabel *label, -- cgit v1.2.1