[gtk+] Move geometry management docs do GtkWidget
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Move geometry management docs do GtkWidget
- Date: Wed, 3 Jan 2018 16:10:07 +0000 (UTC)
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]