[gtk+] Move geometry management docs do GtkWidget



commit cba24360b1bae58c690ff6044d6fbc5c5391f707
Author: Timm Bäder <mail baedert org>
Date:   Wed Jan 3 16:14:47 2018 +0100

    Move geometry management docs do GtkWidget
    
    Both GtkWidget and GtkContainer had similar docs regarding hfw/wfh
    geometry management. Move these just to GtkWidget. Also make sure the
    examples compile, port everything from gtk_preferred_* to measure and
    replace some occurrences of "container" with "widget" where container
    was just used to refer to a widget with child widgets.

 gtk/gtkcontainer.c   |  116 ------------------------------------------
 gtk/gtksizerequest.c |    3 +
 gtk/gtkwidget.c      |  138 +++++++++++++++++++++-----------------------------
 3 files changed, 61 insertions(+), 196 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 820af54..9cbe2e5 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -100,122 +100,6 @@
  * in the #GtkWidgetClass.destroy() implementation.
  * See more about implementing custom widgets at https://wiki.gnome.org/HowDoI/CustomWidgets
  *
- * # Height for width geometry management
- *
- * GTK+ uses a height-for-width (and width-for-height) geometry management system.
- * Height-for-width means that a widget can change how much vertical space it needs,
- * depending on the amount of horizontal space that it is given (and similar for
- * width-for-height).
- *
- * There are some things to keep in mind when implementing container widgets
- * that make use of GTK+’s height for width geometry management system. First,
- * it’s important to note that a container must prioritize one of its
- * dimensions, that is to say that a widget or container can only have a
- * #GtkSizeRequestMode that is %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or
- * %GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT. However, every widget and container
- * must be able to respond to the APIs for both dimensions, i.e. even if a
- * widget has a request mode that is height-for-width, it is possible that
- * its parent will request its sizes using the width-for-height APIs.
- *
- * To ensure that everything works properly, here are some guidelines to follow
- * when implementing height-for-width (or width-for-height) containers.
- *
- * Each request mode involves 2 virtual methods. Height-for-width apis run
- * through gtk_widget_get_preferred_width() and then through gtk_widget_get_preferred_height_for_width().
- * When handling requests in the opposite #GtkSizeRequestMode it is important that
- * every widget request at least enough space to display all of its content at all times.
- *
- * When gtk_widget_get_preferred_height() is called on a container that is height-for-width,
- * the container must return the height for its minimum width. This is easily achieved by
- * simply calling the reverse apis implemented for itself as follows:
- *
- * |[<!-- language="C" -->
- * static void
- * foo_container_get_preferred_height (GtkWidget *widget,
- *                                     gint *min_height,
- *                                     gint *nat_height)
- * {
- *    if (i_am_in_height_for_width_mode)
- *      {
- *        gint min_width;
- *
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
- *                                                            &min_width,
- *                                                            NULL);
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width
- *                                                           (widget,
- *                                                            min_width,
- *                                                            min_height,
- *                                                            nat_height);
- *      }
- *    else
- *      {
- *        ... many containers support both request modes, execute the
- *        real width-for-height request here by returning the
- *        collective heights of all widgets that are stacked
- *        vertically (or whatever is appropriate for this container)
- *        ...
- *      }
- * }
- * ]|
- *
- * Similarly, when gtk_widget_get_preferred_width_for_height() is called for a container or widget
- * that is height-for-width, it then only needs to return the base minimum width like so:
- *
- * |[<!-- language="C" -->
- * static void
- * foo_container_get_preferred_width_for_height (GtkWidget *widget,
- *                                               gint for_height,
- *                                               gint *min_width,
- *                                               gint *nat_width)
- * {
- *    if (i_am_in_height_for_width_mode)
- *      {
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
- *                                                            min_width,
- *                                                            nat_width);
- *      }
- *    else
- *      {
- *        ... execute the real width-for-height request here based on
- *        the required width of the children collectively if the
- *        container were to be allocated the said height ...
- *      }
- * }
- * ]|
- *
- * Height for width requests are generally implemented in terms of a virtual allocation
- * of widgets in the input orientation. Assuming an height-for-width request mode, a container
- * would implement the get_preferred_height_for_width() virtual function by first calling
- * gtk_widget_get_preferred_width() for each of its children.
- *
- * For each potential group of children that are lined up horizontally, the values returned by
- * gtk_widget_get_preferred_width() should be collected in an array of #GtkRequestedSize structures.
- * Any child spacing should be removed from the input @for_width and then the collective size should be
- * allocated using the gtk_distribute_natural_allocation() convenience function.
- *
- * The container will then move on to request the preferred height for each child by using
- * gtk_widget_get_preferred_height_for_width() and using the sizes stored in the #GtkRequestedSize array.
- *
- * To allocate a height-for-width container, it’s again important
- * to consider that a container must prioritize one dimension over the other. So if
- * a container is a height-for-width container it must first allocate all widgets horizontally
- * using a #GtkRequestedSize array and gtk_distribute_natural_allocation() and then add any
- * extra space (if and where appropriate) for the widget to expand.
- *
- * After adding all the expand space, the container assumes it was allocated sufficient
- * height to fit all of its content. At this time, the container must use the total horizontal sizes
- * of each widget to request the height-for-width of each of its children and store the requests in a
- * #GtkRequestedSize array for any widgets that stack vertically (for tabular containers this can
- * be generalized into the heights and widths of rows and columns).
- * The vertical space must then again be distributed using gtk_distribute_natural_allocation()
- * while this time considering the allocated height of the widget minus any vertical spacing
- * that the container adds. Then vertical expand space should be added where appropriate and available
- * and the container should go on to actually allocating the child widgets.
- *
- * See [GtkWidget’s geometry management section][geometry-management]
- * to learn more about implementing height-for-width geometry management for widgets.
- *
  * # Child properties
  *
  * GtkContainer introduces child properties.
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 458a6d1..507d0ec 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -392,6 +392,9 @@ gtk_widget_query_size_for_orientation (GtkWidget        *widget,
  * this functions will compute the minimum and natural width of @widget if
  * it is allocated at a height of 300 pixels.
  *
+ * See [GtkWidget’s geometry management section][geometry-management] for
+ * a more details on implementing #GtkWidgetClass.measure().
+ *
  * Since: 3.90
  */
 void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index db7c098..90ded7c 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -106,7 +106,15 @@
  * - #GtkWidgetClass.measure()
  *
  * There are some important things to keep in mind when implementing
- * height-for-width and when using it in container implementations.
+ * height-for-width and when using it in widget implementations.
+ *
+ * If you implement a direct #GtkWidget subclass that supports
+ * height-for-width or width-for-height geometry management for
+ * itself or its child widgets, the #GtkWidgetClass.get_request_mode()
+ * virtual function must be implemented as well and return the widget's
+ * preferred request mode. The default implementation of this virtual function
+ * returns %GTK_SIZE_REQUEST_CONSTANT_SIZE, which means that the widget will only ever
+ * get -1 passed as the for_size value to its #GtkWidgetClass.measure() implementation.
  *
  * The geometry management system will query a widget hierarchy in
  * only one orientation at a time. When widgets are initially queried
@@ -117,8 +125,8 @@
  * %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH mode:
  * First, the default minimum and natural width for each widget
  * in the interface will be computed using gtk_widget_measure() with an orientation
- * or %GTK_ORIENTATION_HORIZONTAL and a for_size of -1.
- * Because the preferred widths for each container depend on the preferred
+ * of %GTK_ORIENTATION_HORIZONTAL and a for_size of -1.
+ * Because the preferred widths for each widget depend on the preferred
  * widths of their children, this information propagates up the hierarchy,
  * and finally a minimum and natural width is determined for the entire
  * toplevel. Next, the toplevel will use the minimum width to query for the
@@ -133,8 +141,8 @@
  * dimensions it can go on to allocate itself a reasonable size (or a size
  * previously specified with gtk_window_set_default_size()). During the
  * recursive allocation process it’s important to note that request cycles
- * will be recursively executed while container widgets allocate their children.
- * Each container widget, once allocated a size, will go on to first share the
+ * will be recursively executed while widgets allocate their children.
+ * Each widget, once allocated a size, will go on to first share the
  * space in one orientation among its children and then request each child's
  * height for its target allocated width or its width for allocated height,
  * depending. In this way a #GtkWidget will typically be requested its size
@@ -143,77 +151,57 @@
  * requested. For this reason, #GtkWidget caches a  small number of results
  * to avoid re-querying for the same sizes in one allocation cycle.
  *
- * See
- * [GtkContainer’s geometry management section][container-geometry-management]
- * to learn more about how height-for-width allocations are performed
- * by container widgets.
- *
  * If a widget does move content around to intelligently use up the
  * allocated size then it must support the request in both
  * #GtkSizeRequestModes even if the widget in question only
  * trades sizes in a single orientation.
  *
  * For instance, a #GtkLabel that does height-for-width word wrapping
- * will not expect to have #GtkWidgetClass.get_preferred_height() called
- * because that call is specific to a width-for-height request. In this
+ * will not expect to have #GtkWidgetClass.measure() with an orientation of
+ * %GTK_ORIENTATION_VERTICAL called because that call is specific to a
+ * width-for-height request. In this
  * case the label must return the height required for its own 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.
  *
  * Here are some examples of how a %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH widget
- * generally deals with width-for-height requests, for #GtkWidgetClass.get_preferred_height()
- * it will do:
+ * generally deals with width-for-height requests:
  *
  * |[<!-- language="C" -->
  * static void
- * foo_widget_get_preferred_height (GtkWidget *widget,
- *                                  gint *min_height,
- *                                  gint *nat_height)
+ * foo_widget_measure (GtkWidget      *widget,
+ *                     GtkOrientation  orientation,
+ *                     int             for_size,
+ *                     int            *minimum_size,
+ *                     int            *natural_size,
+ *                     int            *minimum_baseline,
+ *                     int            *natural_baseline)
  * {
- *    if (i_am_in_height_for_width_mode)
- *      {
- *        gint min_width, nat_width;
- *
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
- *                                                            &min_width,
- *                                                            &nat_width);
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width
- *                                                           (widget,
- *                                                            min_width,
- *                                                            min_height,
- *                                                            nat_height);
- *      }
- *    else
- *      {
- *         ... some widgets do both. For instance, if a GtkLabel is
- *         rotated to 90 degrees it will return the minimum and
- *         natural height for the rotated label here.
- *      }
- * }
- * ]|
- *
- * And in #GtkWidgetClass.get_preferred_width_for_height() it will simply return
- * the minimum and natural width:
- * |[<!-- language="C" -->
- * static void
- * foo_widget_get_preferred_width_for_height (GtkWidget *widget,
- *                                            gint for_height,
- *                                            gint *min_width,
- *                                            gint *nat_width)
- * {
- *    if (i_am_in_height_for_width_mode)
- *      {
- *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
- *                                                            min_width,
- *                                                            nat_width);
- *      }
- *    else
- *      {
- *         ... again if a widget is sometimes operating in
- *         width-for-height mode (like a rotated GtkLabel) it can go
- *         ahead and do its real width for height calculation here.
- *      }
+ *   if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ *     {
+ *       // Calculate minimum and natural width
+ *     }
+ *   else // VERTICAL
+ *     {
+ *        if (i_am_in_height_for_width_mode)
+ *          {
+ *            int min_width;
+ *
+ *            // First, get the minimum width of our widget
+ *            GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
+ *                                                    &min_width, NULL, NULL, NULL);
+ *
+ *            // Now use the minimum width to retrieve the minmimum and natural height to display
+ *            // that width.
+ *            GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_VERTICAL, min_width,
+ *                                                    minimum_size, natural_size, NULL, NULL);
+ *          }
+ *        else
+ *          {
+ *            // ... some widgets do both.
+ *          }
+ *    }
  * }
  * ]|
  *
@@ -221,42 +209,32 @@
  * allocation. For example, when computing height it may need to also
  * compute width. Or when deciding how to use an allocation, the widget
  * may need to know its natural size. In these cases, the widget should
- * be careful to call its virtual methods directly, like this:
- *
- * |[<!-- language="C" -->
- * GTK_WIDGET_GET_CLASS(widget)->get_preferred_width (widget,
- *                                                    &min,
- *                                                    &natural);
- * ]|
- *
- * It will not work to use the wrapper functions, such as
- * gtk_widget_get_preferred_width() inside your own size request
- * implementation. These return a request adjusted by #GtkSizeGroup
- * and by the #GtkWidgetClass.adjust_size_request() virtual method. If a
- * widget used the wrappers inside its virtual method implementations,
+ * be careful to call its virtual methods directly, like in the code
+ * example above.
+ *
+ * It will not work to use the wrapper function gtk_widget_measure()
+ * inside your own #GtkWidgetClass.size-allocate() implementation.
+ * These return a request adjusted by #GtkSizeGroup, the widget's align and expand flags
+ * as well as its CSS style.
+ * If a widget used the wrappers inside its virtual method implementations,
  * then the adjustments (such as widget margins) would be applied
  * twice. GTK+ therefore does not allow this and will warn if you try
  * to do it.
  *
  * Of course if you are getting the size request for
- * another widget, such as a child of a
- * container, you must use the wrapper APIs.
+ * another widget, such as a child widget, you must use gtk_widget_measure().
  * Otherwise, you would not properly consider widget margins,
  * #GtkSizeGroup, and so forth.
  *
  * Since 3.10 GTK+ also supports baseline vertical alignment of widgets. This
  * means that widgets are positioned such that the typographical baseline of
  * widgets in the same row are aligned. This happens if a widget supports baselines,
- * has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside a container
+ * has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside a widget
  * that supports baselines and has a natural “row” that it aligns to the baseline,
  * or a baseline assigned to it by the grandparent.
  *
- * Baseline alignment support for a widget is done by the 
#GtkWidgetClass.get_preferred_height_and_baseline_for_width()
- * virtual function. It allows you to report a baseline in combination with the
- * minimum and natural height. If there is no baseline you can return -1 to indicate
- * this. The default implementation of this virtual function calls into the
- * #GtkWidgetClass.get_preferred_height() and #GtkWidgetClass.get_preferred_height_for_width(),
- * so if baselines are not supported it doesn’t need to be implemented.
+ * Baseline alignment support for a widget is also done by the #GtkWidgetClass.measure()
+ * virtual function. It allows you to report a both a minimum and natural 
  *
  * If a widget ends up baseline aligned it will be allocated all the space in the parent
  * as if it was %GTK_ALIGN_FILL, but the selected baseline can be found via 
gtk_widget_get_allocated_baseline().
@@ -1896,7 +1874,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
    *
    * Returns: %TRUE if stopping keyboard navigation is fine, %FALSE
    *          if the emitting widget should try to handle the keyboard
-   *          navigation attempt in its parent container(s).
+   *          navigation attempt in its parent widget(s).
    *
    * Since: 2.12
    **/


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]