Merge branch 'native-layout-incubator'

Conflicts:
	configure.in
	docs/reference/gtk/tmpl/gtkaction.sgml
	docs/reference/gtk/tmpl/gtkbuilder.sgml
	gdk/directfb/gdkkeys-directfb.c
	gdk/gdk.symbols
	gdk/x11/gdkwindow-x11.c
	gtk/gtkalignment.c
	gtk/gtkbox.c
	gtk/gtkbutton.c
	gtk/gtkcelleditable.c
	gtk/gtkfilechooser.c
	gtk/gtkframe.c
	gtk/gtkinvisible.c
	gtk/gtklabel.c
	gtk/gtkscrolledwindow.c
	gtk/gtksearchenginetracker.c
	gtk/gtktextview.c
	gtk/gtktoolbutton.c
	gtk/gtktooltip.c
	gtk/gtkviewport.c
	gtk/gtkwidget.c
	gtk/gtkwindow.c
	po-properties/ca@valencia.po
	po-properties/es.po
	po-properties/kn.po
	po-properties/mr.po
	po/ca.po
	po/ca@valencia.po
	po/el.po
	po/es.po
	po/gl.po
	po/id.po
	po/kn.po
	po/lv.po
	po/mr.po
	po/th.po
This commit is contained in:
Matthias Clasen 2010-04-30 17:56:50 -04:00
commit db76c77b81
30 changed files with 3921 additions and 1087 deletions

View File

@ -6,100 +6,107 @@ Base class for widgets which contain other widgets
<!-- ##### SECTION Long_Description ##### -->
<para>
A GTK+ user interface is constructed by nesting widgets inside widgets.
Container widgets are the inner nodes in the resulting tree of widgets:
they contain other widgets. So, for example, you might have a #GtkWindow
containing a #GtkFrame containing a GtkLabel. If you wanted an image instead
of a textual label inside the frame, you might replace the #GtkLabel widget
A GTK+ user interface is constructed by nesting widgets inside widgets.
Container widgets are the inner nodes in the resulting tree of widgets:
they contain other widgets. So, for example, you might have a #GtkWindow
containing a #GtkFrame containing a GtkLabel. If you wanted an image instead
of a textual label inside the frame, you might replace the #GtkLabel widget
with a #GtkImage widget.
</para>
<para>
There are two major kinds of container widgets in GTK+. Both are subclasses
There are two major kinds of container widgets in GTK+. Both are subclasses
of the abstract #GtkContainer base class.
</para>
<para>
The first type of container widget has a single child widget and derives
from #GtkBin. These containers are <firstterm>decorators</firstterm>, which
add some kind of functionality to the child. For example, a #GtkButton makes
its child into a clickable button; a #GtkFrame draws a frame around its child
The first type of container widget has a single child widget and derives
from #GtkBin. These containers are <firstterm>decorators</firstterm>, which
add some kind of functionality to the child. For example, a #GtkButton makes
its child into a clickable button; a #GtkFrame draws a frame around its child
and a #GtkWindow places its child widget inside a top-level window.
</para>
<para>
The second type of container can have more than one child; its purpose is to
manage <firstterm>layout</firstterm>. This means that these containers assign
sizes and positions to their children. For example, a #GtkHBox arranges its
children in a horizontal row, and a #GtkTable arranges the widgets it contains
in a two-dimensional grid.
The second type of container can have more than one child; its purpose is to
manage <firstterm>layout</firstterm>. This means that these containers assign
sizes and positions to their children. For example, a #GtkHBox arranges its
children in a horizontal row, and a #GtkTable arranges the widgets it contains
in a two-dimensional grid.
</para>
<para>
To fulfill its task, a layout container must negotiate the size requirements
with its parent and its children. This negotiation is carried out in two
phases, <firstterm>size requisition</firstterm> and <firstterm>size
allocation</firstterm>.
To fulfill its task, a layout container must negotiate the size requirements
with its parent and its children. The basic form of this negotiation is
carried out in two phases, <firstterm>size requisition</firstterm> and
<firstterm>size allocation</firstterm>, which are implemented by the
size_request() and size_allocate() virtual functions in #GtkWidget.
</para>
<para>
GTK+ also supports a more complicated form of size negotiation called
<firstterm>width-for-height</firstterm> (and its dual
<firstterm>height-for-width</firstterm>). See #GtkExtendedLayout
to learn more about width-for-height geometry management.
</para>
<refsect2 id="size-requisition"><title>Size Requisition</title>
<para>
The size requisition of a widget is it's desired width and height.
The size requisition of a widget is it's desired width and height.
This is represented by a #GtkRequisition.
</para>
<para>
How a widget determines its desired size depends on the widget.
A #GtkLabel, for example, requests enough space to display all its text.
Container widgets generally base their size request on the requisitions
of their children.
How a widget determines its desired size depends on the widget.
A #GtkLabel, for example, requests enough space to display all its text.
Container widgets generally base their size request on the requisitions
of their children.
</para>
<para>
The size requisition phase of the widget layout process operates top-down.
It starts at a top-level widget, typically a #GtkWindow. The top-level widget
asks its child for its size requisition by calling gtk_widget_size_request().
To determine its requisition, the child asks its own children for their
requisitions and so on. Finally, the top-level widget will get a requisition
back from its child.
The size requisition phase of the widget layout process operates top-down.
It starts at a top-level widget, typically a #GtkWindow. The top-level widget
asks its child for its size requisition by calling gtk_widget_size_request().
To determine its requisition, the child asks its own children for their
requisitions and so on. Finally, the top-level widget will get a requisition
back from its child.
</para>
</refsect2>
<refsect2 id="size-allocation"><title>Size Allocation</title>
<para>
When the top-level widget has determined how much space its child would like
to have, the second phase of the size negotiation, size allocation, begins.
Depending on its configuration (see gtk_window_set_resizable()), the top-level
widget may be able to expand in order to satisfy the size request or it may
have to ignore the size request and keep its fixed size. It then tells its
child widget how much space it gets by calling gtk_widget_size_allocate().
The child widget divides the space among its children and tells each child
how much space it got, and so on. Under normal circumstances, a #GtkWindow
When the top-level widget has determined how much space its child would like
to have, the second phase of the size negotiation, size allocation, begins.
Depending on its configuration (see gtk_window_set_resizable()), the top-level
widget may be able to expand in order to satisfy the size request or it may
have to ignore the size request and keep its fixed size. It then tells its
child widget how much space it gets by calling gtk_widget_size_allocate().
The child widget divides the space among its children and tells each child
how much space it got, and so on. Under normal circumstances, a #GtkWindow
will always give its child the amount of space the child requested.
</para>
<para>
A child's size allocation is represented by a #GtkAllocation. This struct
contains not only a width and height, but also a position (i.e. X and Y
A child's size allocation is represented by a #GtkAllocation. This struct
contains not only a width and height, but also a position (i.e. X and Y
coordinates), so that containers can tell their children not only how much
space they have gotten, but also where they are positioned inside the space
available to the container.
space they have gotten, but also where they are positioned inside the space
available to the container.
</para>
<para>
Widgets are required to honor the size allocation they receive; a size
Widgets are required to honor the size allocation they receive; a size
request is only a request, and widgets must be able to cope with any size.
</para>
</refsect2>
<refsect2 id="child-properties"><title>Child properties</title>
<para>
<structname>GtkContainer</structname> introduces <firstterm>child
<structname>GtkContainer</structname> introduces <firstterm>child
properties</firstterm> - these are object properties that are not specific
to either the container or the contained widget, but rather to their relation.
Typical examples of child properties are the position or pack-type of a widget
which is contained in a #GtkBox.</para>
<para>
Use gtk_container_class_install_child_property() to install child properties
Use gtk_container_class_install_child_property() to install child properties
for a container class and gtk_container_class_find_child_property() or
gtk_container_class_list_child_properties() to get information about existing
child properties.
</para>
<para>
To set the value of a child property, use gtk_container_child_set_property(),
gtk_container_child_set() or gtk_container_child_set_valist().
To obtain the value of a child property, use
To set the value of a child property, use gtk_container_child_set_property(),
gtk_container_child_set() or gtk_container_child_set_valist().
To obtain the value of a child property, use
gtk_container_child_get_property(), gtk_container_child_get() or
gtk_container_child_get_valist(). To emit notification about child property
gtk_container_child_get_valist(). To emit notification about child property
changes, use gtk_widget_child_notify().
</para>
</refsect2>
@ -107,7 +114,7 @@ changes, use gtk_widget_child_notify().
<refsect2 id="GtkContainer-BUILDER-UI">
<title>GtkContainer as GtkBuildable</title>
<para>
The GtkContainer implementation of the GtkBuildable interface
The GtkContainer implementation of the GtkBuildable interface
supports a &lt;packing&gt; element for children, which can
contain multiple &lt;property&gt; elements that specify
child properties for the child.
@ -152,7 +159,7 @@ for regular properties.
</para>
@container: the object which received the signal.
@widget:
@widget:
<!-- ##### SIGNAL GtkContainer::check-resize ##### -->
<para>
@ -167,7 +174,7 @@ for regular properties.
</para>
@container: the object which received the signal.
@widget:
@widget:
<!-- ##### SIGNAL GtkContainer::set-focus-child ##### -->
<para>
@ -175,7 +182,7 @@ for regular properties.
</para>
@container: the object which received the signal.
@widget:
@widget:
<!-- ##### ARG GtkContainer:border-width ##### -->
<para>
@ -197,7 +204,7 @@ for regular properties.
</para>
@widget:
@widget:
<!-- ##### MACRO GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID ##### -->
@ -206,7 +213,7 @@ This macro should be used to emit a standard warning about unexpected
properties in set_child_property() and get_child_property() implementations.
</para>
@object: the #GObject on which set_child_property() or get_child_property()
@object: the #GObject on which set_child_property() or get_child_property()
was called
@property_id: the numeric id of the property
@pspec: the #GParamSpec of the property
@ -225,8 +232,8 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@widget:
@container:
@widget:
<!-- ##### FUNCTION gtk_container_remove ##### -->
@ -234,8 +241,8 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@widget:
@container:
@widget:
<!-- ##### FUNCTION gtk_container_add_with_properties ##### -->
@ -243,10 +250,10 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@widget:
@first_prop_name:
@Varargs:
@container:
@widget:
@first_prop_name:
@Varargs:
<!-- ##### FUNCTION gtk_container_get_resize_mode ##### -->
@ -254,8 +261,8 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_resize_mode ##### -->
@ -263,8 +270,8 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@resize_mode:
@container:
@resize_mode:
<!-- ##### FUNCTION gtk_container_check_resize ##### -->
@ -272,7 +279,7 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@container:
<!-- ##### FUNCTION gtk_container_foreach ##### -->
@ -280,9 +287,9 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@callback:
@callback_data:
@container:
@callback:
@callback_data:
<!-- ##### FUNCTION gtk_container_foreach_full ##### -->
@ -290,11 +297,11 @@ Does the same as gtk_container_set_border_width().
</para>
@container:
@callback:
@marshal:
@callback_data:
@notify:
@container:
@callback:
@marshal:
@callback_data:
@notify:
@Deprecated: Use gtk_container_foreach() instead.
@ -311,8 +318,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_reallocate_redraws ##### -->
@ -320,8 +327,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@needs_redraws:
@container:
@needs_redraws:
<!-- ##### FUNCTION gtk_container_get_focus_child ##### -->
@ -329,8 +336,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_focus_child ##### -->
@ -338,8 +345,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@container:
@child:
<!-- ##### FUNCTION gtk_container_get_focus_vadjustment ##### -->
@ -347,8 +354,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_focus_vadjustment ##### -->
@ -356,8 +363,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@adjustment:
@container:
@adjustment:
<!-- ##### FUNCTION gtk_container_get_focus_hadjustment ##### -->
@ -365,8 +372,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_focus_hadjustment ##### -->
@ -374,8 +381,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@adjustment:
@container:
@adjustment:
<!-- ##### FUNCTION gtk_container_resize_children ##### -->
@ -383,7 +390,7 @@ Does the same as gtk_container_get_children().
</para>
@container:
@container:
<!-- ##### FUNCTION gtk_container_child_type ##### -->
@ -391,8 +398,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_child_get ##### -->
@ -400,10 +407,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@first_prop_name:
@Varargs:
@container:
@child:
@first_prop_name:
@Varargs:
<!-- ##### FUNCTION gtk_container_child_set ##### -->
@ -411,10 +418,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@first_prop_name:
@Varargs:
@container:
@child:
@first_prop_name:
@Varargs:
<!-- ##### FUNCTION gtk_container_child_get_property ##### -->
@ -422,10 +429,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@property_name:
@value:
@container:
@child:
@property_name:
@value:
<!-- ##### FUNCTION gtk_container_child_set_property ##### -->
@ -433,10 +440,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@property_name:
@value:
@container:
@child:
@property_name:
@value:
<!-- ##### FUNCTION gtk_container_child_get_valist ##### -->
@ -444,10 +451,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@first_property_name:
@var_args:
@container:
@child:
@first_property_name:
@var_args:
<!-- ##### FUNCTION gtk_container_child_set_valist ##### -->
@ -455,10 +462,10 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@first_property_name:
@var_args:
@container:
@child:
@first_property_name:
@var_args:
<!-- ##### FUNCTION gtk_container_forall ##### -->
@ -466,9 +473,9 @@ Does the same as gtk_container_get_children().
</para>
@container:
@callback:
@callback_data:
@container:
@callback:
@callback_data:
<!-- ##### FUNCTION gtk_container_get_border_width ##### -->
@ -476,8 +483,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@Returns:
@container:
@Returns:
<!-- ##### FUNCTION gtk_container_set_border_width ##### -->
@ -485,8 +492,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@border_width:
@container:
@border_width:
<!-- ##### FUNCTION gtk_container_propagate_expose ##### -->
@ -494,9 +501,9 @@ Does the same as gtk_container_get_children().
</para>
@container:
@child:
@event:
@container:
@child:
@event:
<!-- ##### FUNCTION gtk_container_get_focus_chain ##### -->
@ -504,9 +511,9 @@ Does the same as gtk_container_get_children().
</para>
@container:
@focusable_widgets:
@Returns:
@container:
@focusable_widgets:
@Returns:
<!-- ##### FUNCTION gtk_container_set_focus_chain ##### -->
@ -514,8 +521,8 @@ Does the same as gtk_container_get_children().
</para>
@container:
@focusable_widgets:
@container:
@focusable_widgets:
<!-- ##### FUNCTION gtk_container_unset_focus_chain ##### -->
@ -523,7 +530,7 @@ Does the same as gtk_container_get_children().
</para>
@container:
@container:
<!-- ##### FUNCTION gtk_container_class_find_child_property ##### -->
@ -531,9 +538,9 @@ Does the same as gtk_container_get_children().
</para>
@cclass:
@property_name:
@Returns:
@cclass:
@property_name:
@Returns:
<!-- ##### FUNCTION gtk_container_class_install_child_property ##### -->
@ -541,9 +548,9 @@ Does the same as gtk_container_get_children().
</para>
@cclass:
@property_id:
@pspec:
@cclass:
@property_id:
@pspec:
<!-- ##### FUNCTION gtk_container_class_list_child_properties ##### -->
@ -551,8 +558,8 @@ Does the same as gtk_container_get_children().
</para>
@cclass:
@n_properties:
@Returns:
@cclass:
@n_properties:
@Returns:

View File

@ -141,7 +141,7 @@ the clipboard. Only labels that contain useful-to-copy information
</para>
</refsect2>
<refsect2>
<refsect2 id="label-text-layout">
<title>Text layout</title>
<para>
@ -155,11 +155,23 @@ Labels can automatically wrap text if you call
gtk_label_set_line_wrap().
</para>
<para>
gtk_label_set_justify() sets how the lines in a label align
with one another. If you want to set how the label as a whole
gtk_label_set_justify() sets how the lines in a label align
with one another. If you want to set how the label as a whole
aligns in its available space, see gtk_misc_set_alignment().
</para>
<para>
The #GtkLabel:width-chars and #GtkLabel:max-width-chars properties
can be used to control the size allocation of ellipsized or wrapped
labels. For ellipsizing labels, if either is specified (and less
than the actual text size), it is used as the minimum width, and the actual
text size is used as the natural width of the label. For wrapping labels,
width-chars is used as the minimum width, if specified, and max-width-chars
is used as the natural width. Even if max-width-chars specified, wrapping
labels will be rewrapped to use all of the available width.
</para>
<note><para>Note that the interpretation of #GtkLabel:width-chars and
#GtkLabel:max-width-chars has changed a bit with the introduction of
width-for-height geometry management and #GtkExtendedLayout.</para></note>
</refsect2>
<refsect2>

View File

@ -212,6 +212,7 @@ gtk_public_h_sources = \
gtkenums.h \
gtkeventbox.h \
gtkexpander.h \
gtkextendedlayout.h \
gtkfilechooser.h \
gtkfilechooserbutton.h \
gtkfilechooserdialog.h \
@ -466,6 +467,7 @@ gtk_base_c_sources = \
gtkentrycompletion.c \
gtkeventbox.c \
gtkexpander.c \
gtkextendedlayout.c \
gtkfilechooser.c \
gtkfilechooserbutton.c \
gtkfilechooserdefault.c \

View File

@ -83,6 +83,7 @@
#include <gtk/gtkenums.h>
#include <gtk/gtkeventbox.h>
#include <gtk/gtkexpander.h>
#include <gtk/gtkextendedlayout.h>
#include <gtk/gtkfixed.h>
#include <gtk/gtkfilechooser.h>
#include <gtk/gtkfilechooserbutton.h>

View File

@ -1504,6 +1504,17 @@ gtk_expander_set_use_underline
#endif
#endif
#if IN_HEADER(__GTK_EXTENDED_LAYOUT_H__)
#if IN_FILE(__GTK_EXTENDED_LAYOUT_C__)
gtk_extended_layout_get_type G_GNUC_CONST
gtk_extended_layout_get_desired_height
gtk_extended_layout_get_desired_width
gtk_extended_layout_get_height_for_width
gtk_extended_layout_get_width_for_height
gtk_extended_layout_is_height_for_width
#endif
#endif
#if IN_HEADER(__GTK_FILE_CHOOSER_H__)
#if IN_FILE(__GTK_FILE_CHOOSER_C__)
gtk_file_chooser_add_filter

View File

@ -45,6 +45,7 @@
#include "config.h"
#include "gtkalignment.h"
#include "gtkextendedlayout.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@ -73,8 +74,6 @@ struct _GtkAlignmentPrivate
guint padding_right;
};
static void gtk_alignment_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_alignment_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_alignment_set_property (GObject *object,
@ -86,7 +85,17 @@ static void gtk_alignment_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN)
static void gtk_alignment_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_alignment_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_alignment_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
G_DEFINE_TYPE_WITH_CODE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_alignment_extended_layout_init))
static void
gtk_alignment_class_init (GtkAlignmentClass *class)
@ -100,7 +109,6 @@ gtk_alignment_class_init (GtkAlignmentClass *class)
gobject_class->set_property = gtk_alignment_set_property;
gobject_class->get_property = gtk_alignment_get_property;
widget_class->size_request = gtk_alignment_size_request;
widget_class->size_allocate = gtk_alignment_size_allocate;
g_object_class_install_property (gobject_class,
@ -462,34 +470,6 @@ gtk_alignment_set (GtkAlignment *alignment,
}
static void
gtk_alignment_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkBin *bin;
GtkAlignmentPrivate *priv;
bin = GTK_BIN (widget);
priv = GTK_ALIGNMENT_GET_PRIVATE (widget);
requisition->width = GTK_CONTAINER (widget)->border_width * 2;
requisition->height = GTK_CONTAINER (widget)->border_width * 2;
if (bin->child && gtk_widget_get_visible (bin->child))
{
GtkRequisition child_requisition;
gtk_widget_size_request (bin->child, &child_requisition);
requisition->width += child_requisition.width;
requisition->height += child_requisition.height;
/* Request extra space for the padding: */
requisition->width += (priv->padding_left + priv->padding_right);
requisition->height += (priv->padding_top + priv->padding_bottom);
}
}
static void
gtk_alignment_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
@ -497,7 +477,6 @@ gtk_alignment_size_allocate (GtkWidget *widget,
GtkAlignment *alignment;
GtkBin *bin;
GtkAllocation child_allocation;
GtkRequisition child_requisition;
gint width, height;
gint border_width;
gint padding_horizontal, padding_vertical;
@ -512,7 +491,10 @@ gtk_alignment_size_allocate (GtkWidget *widget,
if (bin->child && gtk_widget_get_visible (bin->child))
{
gtk_widget_get_child_requisition (bin->child, &child_requisition);
GtkExtendedLayout *layout = GTK_EXTENDED_LAYOUT (bin->child);
gint child_nat_width;
gint child_nat_height;
gint child_width, child_height;
border_width = GTK_CONTAINER (alignment)->border_width;
@ -522,16 +504,37 @@ gtk_alignment_size_allocate (GtkWidget *widget,
width = MAX (1, allocation->width - padding_horizontal - 2 * border_width);
height = MAX (1, allocation->height - padding_vertical - 2 * border_width);
if (width > child_requisition.width)
child_allocation.width = (child_requisition.width *
if (gtk_extended_layout_is_height_for_width (layout))
{
gtk_extended_layout_get_desired_width (layout, NULL, &child_nat_width);
child_width = MIN (width, child_nat_width);
gtk_extended_layout_get_height_for_width (layout, child_width, NULL, &child_nat_height);
child_height = MIN (height, child_nat_height);
}
else
{
gtk_extended_layout_get_desired_height (layout, NULL, &child_nat_height);
child_height = MIN (height, child_nat_height);
gtk_extended_layout_get_width_for_height (layout, child_height, NULL, &child_nat_width);
child_width = MIN (width, child_nat_width);
}
if (width > child_width)
child_allocation.width = (child_width *
(1.0 - alignment->xscale) +
width * alignment->xscale);
else
child_allocation.width = width;
if (height > child_requisition.height)
child_allocation.height = (child_requisition.height *
if (height > child_height)
child_allocation.height = (child_height *
(1.0 - alignment->yscale) +
height * alignment->yscale);
else
@ -548,6 +551,75 @@ gtk_alignment_size_allocate (GtkWidget *widget,
}
}
static void
gtk_alignment_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_alignment_get_desired_width;
iface->get_desired_height = gtk_alignment_get_desired_height;
}
static void
gtk_alignment_get_desired_size (GtkExtendedLayout *layout,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size)
{
GtkWidget *child;
GtkAlignmentPrivate *priv;
gint minimum, natural;
priv = GTK_ALIGNMENT_GET_PRIVATE (layout);
natural = minimum = GTK_CONTAINER (layout)->border_width * 2;
if ((child = gtk_bin_get_child (GTK_BIN (layout))) && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
/* Request extra space for the padding: */
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
minimum += (priv->padding_left + priv->padding_right);
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child),
&child_min, &child_nat);
}
else
{
minimum += (priv->padding_top + priv->padding_bottom);
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child),
&child_min, &child_nat);
}
natural = minimum;
minimum += child_min;
natural += child_nat;
}
if (minimum_size)
*minimum_size = minimum;
if (natural_size)
*natural_size = natural;
}
static void
gtk_alignment_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_alignment_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
}
static void
gtk_alignment_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_alignment_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
}
/**
* gtk_alignment_set_padding:
* @alignment: a #GtkAlignment

View File

@ -1167,13 +1167,14 @@ gtk_assistant_size_request (GtkWidget *widget,
requisition->height = height;
}
static void
gtk_assistant_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
GtkRequisition header_requisition;
GtkRequisition header_requisition, action_requisition, sidebar_requisition;
GtkAllocation child_allocation, header_allocation;
gint header_padding, content_padding;
gboolean rtl;
@ -1200,24 +1201,28 @@ gtk_assistant_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (priv->header_image, &header_allocation);
/* Action area */
gtk_widget_get_child_requisition (priv->action_area, &action_requisition);
child_allocation.x = GTK_CONTAINER (widget)->border_width;
child_allocation.y = allocation->height -
GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
GTK_CONTAINER (widget)->border_width - action_requisition.height;
child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
child_allocation.height = priv->action_area->requisition.height;
child_allocation.height = action_requisition.height;
gtk_widget_size_allocate (priv->action_area, &child_allocation);
/* Sidebar */
gtk_widget_get_child_requisition (priv->sidebar_image, &sidebar_requisition);
if (rtl)
child_allocation.x = allocation->width -
GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
GTK_CONTAINER (widget)->border_width - sidebar_requisition.width;
else
child_allocation.x = GTK_CONTAINER (widget)->border_width;
child_allocation.y = GTK_CONTAINER (widget)->border_width +
priv->header_image->allocation.height + 2 * header_padding;
child_allocation.width = priv->sidebar_image->requisition.width;
child_allocation.width = sidebar_requisition.width;
child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;

View File

@ -39,6 +39,7 @@
#include "config.h"
#include "gtkbin.h"
#include "gtkextendedlayout.h"
#include "gtkintl.h"
#include "gtkalias.h"
@ -53,7 +54,22 @@ static void gtk_bin_forall (GtkContainer *container,
static GType gtk_bin_child_type (GtkContainer *container);
G_DEFINE_ABSTRACT_TYPE (GtkBin, gtk_bin, GTK_TYPE_CONTAINER)
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;
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkBin, gtk_bin, GTK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_bin_extended_layout_init))
static void
gtk_bin_class_init (GtkBinClass *class)
@ -141,6 +157,109 @@ gtk_bin_forall (GtkContainer *container,
(* callback) (bin->child, callback_data);
}
/* GtkBin widgets define the padding and borders independantly so
* we cannot provide a generic get_desired_size() for the same reason
* we never implemented size_request() here.
*
* But for cases where the GtkBin class's padding is constant and
* does not vary based on allocation (most cases), we can at least
* deduce a common code path for the get_width_for_height()/get_height_for_width()
* cases by using the delta of the base size requsts.
*/
static void
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,
gint *delta_v)
{
gint hmin, vmin, child_hmin, child_vmin;
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (bin), &hmin, NULL);
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (bin), &vmin, NULL);
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (bin->child), &child_hmin, NULL);
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (bin->child), &child_vmin, NULL);
*delta_h = hmin - child_hmin;
*delta_v = vmin - child_vmin;
}
static void
gtk_bin_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width)
{
GtkBin *bin = GTK_BIN (layout);
gint hdelta, vdelta, child_min, child_nat;
if (bin->child)
{
get_child_padding_delta (bin, &hdelta, &vdelta);
gtk_extended_layout_get_width_for_height (GTK_EXTENDED_LAYOUT (bin->child),
height - vdelta,
&child_min, &child_nat);
if (minimum_width)
*minimum_width = child_min + hdelta;
if (natural_width)
*natural_width = child_nat + hdelta;
}
else
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, minimum_width, natural_width);
}
static void
gtk_bin_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height)
{
GtkBin *bin = GTK_BIN (layout);
gint hdelta, vdelta, child_min, child_nat;
if (bin->child)
{
get_child_padding_delta (bin, &hdelta, &vdelta);
gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (bin->child),
width - hdelta,
&child_min, &child_nat);
if (minimum_height)
*minimum_height = child_min + vdelta;
if (natural_height)
*natural_height = child_nat + vdelta;
}
else
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, minimum_height, natural_height);
}
/**
* gtk_bin_get_child:
* @bin: a #GtkBin

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@
#include "gtkstock.h"
#include "gtkiconfactory.h"
#include "gtkactivatable.h"
#include "gtkextendedlayout.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@ -111,8 +112,6 @@ static void gtk_button_unrealize (GtkWidget * widget);
static void gtk_button_map (GtkWidget * widget);
static void gtk_button_unmap (GtkWidget * widget);
static void gtk_button_style_set (GtkWidget * widget, GtkStyle * prev_style);
static void gtk_button_size_request (GtkWidget * widget,
GtkRequisition * requisition);
static void gtk_button_size_allocate (GtkWidget * widget,
GtkAllocation * allocation);
static gint gtk_button_expose (GtkWidget * widget, GdkEventExpose * event);
@ -148,7 +147,7 @@ static void gtk_button_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
static void gtk_button_activatable_interface_init (GtkActivatableIface *iface);
static void gtk_button_activatable_interface_init(GtkActivatableIface *iface);
static void gtk_button_update (GtkActivatable *activatable,
GtkAction *action,
const gchar *property_name);
@ -159,11 +158,21 @@ static void gtk_button_set_related_action (GtkButton *button,
static void gtk_button_set_use_action_appearance (GtkButton *button,
gboolean use_appearance);
static void gtk_button_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_button_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_button_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static guint button_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
gtk_button_activatable_interface_init))
gtk_button_activatable_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_button_extended_layout_init))
static void
gtk_button_class_init (GtkButtonClass *klass)
@ -191,7 +200,6 @@ gtk_button_class_init (GtkButtonClass *klass)
widget_class->map = gtk_button_map;
widget_class->unmap = gtk_button_unmap;
widget_class->style_set = gtk_button_style_set;
widget_class->size_request = gtk_button_size_request;
widget_class->size_allocate = gtk_button_size_allocate;
widget_class->expose_event = gtk_button_expose;
widget_class->button_press_event = gtk_button_button_press;
@ -1331,49 +1339,6 @@ gtk_button_get_props (GtkButton *button,
if (interior_focus)
gtk_widget_style_get (widget, "interior-focus", interior_focus, NULL);
}
static void
gtk_button_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkButton *button = GTK_BUTTON (widget);
GtkBorder default_border;
GtkBorder inner_border;
gint focus_width;
gint focus_pad;
gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
gtk_widget_style_get (GTK_WIDGET (widget),
"focus-line-width", &focus_width,
"focus-padding", &focus_pad,
NULL);
requisition->width = ((GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->xthickness) * 2 +
inner_border.left + inner_border.right);
requisition->height = ((GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->ythickness) * 2 +
inner_border.top + inner_border.bottom);
if (gtk_widget_get_can_default (widget))
{
requisition->width += default_border.left + default_border.right;
requisition->height += default_border.top + default_border.bottom;
}
if (GTK_BIN (button)->child && gtk_widget_get_visible (GTK_BIN (button)->child))
{
GtkRequisition child_requisition;
gtk_widget_size_request (GTK_BIN (button)->child, &child_requisition);
requisition->width += child_requisition.width;
requisition->height += child_requisition.height;
}
requisition->width += 2 * (focus_width + focus_pad);
requisition->height += 2 * (focus_width + focus_pad);
}
static void
gtk_button_size_allocate (GtkWidget *widget,
@ -1803,6 +1768,95 @@ gtk_button_finish_activate (GtkButton *button,
gtk_button_clicked (button);
}
static void
gtk_button_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_button_get_desired_width;
iface->get_desired_height = gtk_button_get_desired_height;
}
static void
gtk_button_get_desired_size (GtkExtendedLayout *layout,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size)
{
GtkButton *button = GTK_BUTTON (layout);
GtkWidget *child;
GtkBorder default_border;
GtkBorder inner_border;
gint focus_width;
gint focus_pad;
gint minimum, natural;
gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
gtk_widget_style_get (GTK_WIDGET (layout),
"focus-line-width", &focus_width,
"focus-padding", &focus_pad,
NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
minimum = ((GTK_CONTAINER (layout)->border_width +
GTK_WIDGET (layout)->style->xthickness) * 2 +
inner_border.left + inner_border.right);
if (gtk_widget_get_can_default (GTK_WIDGET (layout)))
minimum += default_border.left + default_border.right;
}
else
{
minimum = ((GTK_CONTAINER (layout)->border_width +
GTK_WIDGET (layout)->style->ythickness) * 2 +
inner_border.top + inner_border.bottom);
if (gtk_widget_get_can_default (GTK_WIDGET (layout)))
minimum += default_border.top + default_border.bottom;
}
minimum += 2 * (focus_width + focus_pad);
natural = minimum;
if ((child = gtk_bin_get_child (GTK_BIN (button))) &&
gtk_widget_get_visible (child))
{
gint child_min, child_nat;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child),
&child_min, &child_nat);
else
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child),
&child_min, &child_nat);
minimum += child_min;
natural += child_nat;
}
if (minimum_size)
*minimum_size = minimum;
if (natural_size)
*natural_size = natural;
}
static void
gtk_button_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_button_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
}
static void
gtk_button_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_button_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
}
/**
* gtk_button_set_label:
* @button: a #GtkButton

View File

@ -1370,6 +1370,9 @@ _gtk_container_queue_resize (GtkContainer *container)
{
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_WIDTH_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_HEIGHT_REQUEST_NEEDED);
if ((resize_container && widget == GTK_WIDGET (resize_container)) ||
!widget->parent)
break;

View File

@ -36,18 +36,19 @@
G_BEGIN_DECLS
typedef enum {
GTK_DEBUG_MISC = 1 << 0,
GTK_DEBUG_PLUGSOCKET = 1 << 1,
GTK_DEBUG_TEXT = 1 << 2,
GTK_DEBUG_TREE = 1 << 3,
GTK_DEBUG_UPDATES = 1 << 4,
GTK_DEBUG_KEYBINDINGS = 1 << 5,
GTK_DEBUG_MULTIHEAD = 1 << 6,
GTK_DEBUG_MODULES = 1 << 7,
GTK_DEBUG_GEOMETRY = 1 << 8,
GTK_DEBUG_ICONTHEME = 1 << 9,
GTK_DEBUG_PRINTING = 1 << 10,
GTK_DEBUG_BUILDER = 1 << 11
GTK_DEBUG_MISC = 1 << 0,
GTK_DEBUG_PLUGSOCKET = 1 << 1,
GTK_DEBUG_TEXT = 1 << 2,
GTK_DEBUG_TREE = 1 << 3,
GTK_DEBUG_UPDATES = 1 << 4,
GTK_DEBUG_KEYBINDINGS = 1 << 5,
GTK_DEBUG_MULTIHEAD = 1 << 6,
GTK_DEBUG_MODULES = 1 << 7,
GTK_DEBUG_GEOMETRY = 1 << 8,
GTK_DEBUG_ICONTHEME = 1 << 9,
GTK_DEBUG_PRINTING = 1 << 10,
GTK_DEBUG_BUILDER = 1 << 11,
GTK_DEBUG_EXTENDED_LAYOUT = 1 << 12,
} GtkDebugFlag;
#ifdef G_ENABLE_DEBUG

527
gtk/gtkextendedlayout.c Normal file
View File

@ -0,0 +1,527 @@
/* gtkextendedlayout.c
* Copyright (C) 2007-2010 Openismus GmbH
*
* Authors:
* Mathias Hasselmann <mathias@openismus.com>
* Tristan Van Berkom <tristan.van.berkom@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:gtkextendedlayout
* @Short_Description: Height-for-width geometry management
* @Title: GtkExtendedLayout
*
* The extended layout is GTK+'s height-for-width (and width-for-height)
* geometry management system.
*
* <refsect2>
* <title>Implementing GtkExtendedLayout</title>
* <para>
* Some important things to keep in mind when implementing
* or using the extended layout.
*
* The Extended Layout system will query a logical hierarchy 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 their 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. #GtkExtendedLayout caches a
* small number of results to avoid re-querying for the same
* allocated size in one allocation cycle.
*
* 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.
* </para>
* </refsect2>
*/
#include <config.h>
#include "gtkextendedlayout.h"
#include "gtksizegroup.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
/* With extended layout, a widget may be requested
* its width for 2 or maximum 3 heights in one resize
*/
#define N_CACHED_SIZES 3
typedef struct
{
guint age;
gint for_size;
gint minimum_size;
gint natural_size;
} DesiredSize;
typedef struct {
DesiredSize desired_widths[N_CACHED_SIZES];
DesiredSize desired_heights[N_CACHED_SIZES];
guint8 cached_width_age;
guint8 cached_height_age;
} ExtendedLayoutCache;
static GQuark quark_cache = 0;
GType
gtk_extended_layout_get_type (void)
{
static GType extended_layout_type = 0;
if (G_UNLIKELY(!extended_layout_type))
{
extended_layout_type =
g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkExtendedLayout"),
sizeof (GtkExtendedLayoutIface),
NULL, 0, NULL, 0);
g_type_interface_add_prerequisite (extended_layout_type, GTK_TYPE_WIDGET);
quark_cache = g_quark_from_static_string ("gtk-extended-layout-cache");
}
return extended_layout_type;
}
/* looks for a cached size request for this for_size. If not
* 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,
DesiredSize **result)
{
guint i;
*result = &cached_sizes[0];
for (i = 0; i < N_CACHED_SIZES; i++)
{
DesiredSize *cs;
cs = &cached_sizes[i];
if (cs->age > 0 && cs->for_size == for_size)
{
*result = cs;
return TRUE;
}
else if (cs->age < (*result)->age)
{
*result = cs;
}
}
return FALSE;
}
static void
destroy_cache (ExtendedLayoutCache *cache)
{
g_slice_free (ExtendedLayoutCache, cache);
}
static ExtendedLayoutCache *
get_cache (GtkExtendedLayout *layout,
gboolean create)
{
ExtendedLayoutCache *cache;
cache = g_object_get_qdata (G_OBJECT (layout), quark_cache);
if (!cache && create)
{
cache = g_slice_new0 (ExtendedLayoutCache);
cache->cached_width_age = 1;
cache->cached_height_age = 1;
g_object_set_qdata_full (G_OBJECT (layout), quark_cache, cache,
(GDestroyNotify)destroy_cache);
}
return cache;
}
static void
do_size_request (GtkWidget *widget)
{
if (GTK_WIDGET_REQUEST_NEEDED (widget))
{
gtk_widget_ensure_style (widget);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
g_signal_emit_by_name (widget,
"size-request",
&widget->requisition);
}
}
static void
compute_size_for_orientation (GtkExtendedLayout *layout,
GtkSizeGroupMode orientation,
gint for_size,
gint *minimum_size,
gint *natural_size)
{
ExtendedLayoutCache *cache;
DesiredSize *cached_size;
GtkWidget *widget;
gboolean found_in_cache = FALSE;
g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
g_return_if_fail (minimum_size != NULL || natural_size != NULL);
widget = GTK_WIDGET (layout);
cache = get_cache (layout, TRUE);
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
{
cached_size = &cache->desired_widths[0];
if (!GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout))
found_in_cache = get_cached_desired_size (for_size, cache->desired_widths, &cached_size);
else
{
memset (cache->desired_widths, 0, N_CACHED_SIZES * sizeof (DesiredSize));
cache->cached_width_age = 1;
}
}
else
{
cached_size = &cache->desired_heights[0];
if (!GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout))
found_in_cache = get_cached_desired_size (for_size, cache->desired_heights, &cached_size);
else
{
memset (cache->desired_heights, 0, N_CACHED_SIZES * sizeof (DesiredSize));
cache->cached_height_age = 1;
}
}
if (!found_in_cache)
{
gint min_size = 0, nat_size = 0;
gint group_size, requisition_size;
/* Unconditional size request runs but is often unhandled. */
do_size_request (widget);
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
{
requisition_size = widget->requisition.width;
if (for_size < 0)
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, &min_size, &nat_size);
else
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_width_for_height (layout, for_size, &min_size, &nat_size);
}
else
{
requisition_size = widget->requisition.height;
if (for_size < 0)
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, &min_size, &nat_size);
else
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_height_for_width (layout, for_size, &min_size, &nat_size);
}
/* Support for dangling "size-request" signals and forward derived
* classes that will not default to a ->get_desired_width() that
* returns the values in the ->requisition cache.
*/
min_size = MAX (min_size, requisition_size);
nat_size = MAX (nat_size, requisition_size);
cached_size->minimum_size = min_size;
cached_size->natural_size = nat_size;
cached_size->for_size = for_size;
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
{
cached_size->age = cache->cached_width_age;
cache->cached_width_age++;
GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
}
else
{
cached_size->age = cache->cached_height_age;
cache->cached_height_age++;
GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
}
/* Get size groups to compute the base requisition once one
* of the values have been cached, then go ahead and update
* the cache with the sizegroup computed value.
*
* Note this is also where values from gtk_widget_set_size_request()
* are considered.
*/
group_size =
_gtk_size_group_bump_requisition (GTK_WIDGET (layout),
orientation, cached_size->minimum_size);
cached_size->minimum_size = MAX (cached_size->minimum_size, group_size);
cached_size->natural_size = MAX (cached_size->natural_size, group_size);
}
if (minimum_size)
*minimum_size = cached_size->minimum_size;
if (natural_size)
*natural_size = cached_size->natural_size;
g_assert (cached_size->minimum_size <= cached_size->natural_size);
GTK_NOTE (EXTENDED_LAYOUT,
g_print ("[%p] %s\t%s: %d is minimum %d and natural: %d (hit cache: %s)\n",
layout, G_OBJECT_TYPE_NAME (layout),
orientation == GTK_SIZE_GROUP_HORIZONTAL ?
"width for height" : "height for width" ,
for_size,
cached_size->minimum_size,
cached_size->natural_size,
found_in_cache ? "yes" : "no"));
}
/**
* gtk_extended_layout_is_height_for_width:
* @layout: a #GtkExtendedLayout instance
*
* Gets whether the widget prefers a height-for-width layout
* or a width-for-height layout.
*
* <note><para>#GtkBin widgets generally propagate the preference of
* their child, container widgets need to request something either in
* context of their children or in context of their allocation
* capabilities.</para></note>
*
* Returns: %TRUE if the widget prefers height-for-width, %FALSE if
* the widget should be treated with a width-for-height preference.
*
* Since: 3.0
*/
gboolean
gtk_extended_layout_is_height_for_width (GtkExtendedLayout *layout)
{
GtkExtendedLayoutIface *iface;
g_return_val_if_fail (GTK_IS_EXTENDED_LAYOUT (layout), FALSE);
iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
if (iface->is_height_for_width)
return iface->is_height_for_width (layout);
/* By default widgets are height-for-width. */
return TRUE;
}
/**
* gtk_extended_layout_get_desired_width:
* @layout: a #GtkExtendedLayout instance
* @minimum_width: (allow-none): location to store the minimum width, or %NULL
* @natural_width: (allow-none): location to store the natural width, or %NULL
*
* Retrieves a widget's initial minimum and natural width.
*
* <note><para>This call is specific to height-for-width
* requests.</para></note>
*
* Since: 3.0
*/
void
gtk_extended_layout_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_width,
gint *natural_width)
{
compute_size_for_orientation (layout, GTK_SIZE_GROUP_HORIZONTAL,
-1, minimum_width, natural_width);
}
/**
* gtk_extended_layout_get_desired_height:
* @layout: a #GtkExtendedLayout instance
* @minimum_width: (allow-none): location to store the minimum height, or %NULL
* @natural_width: (allow-none): location to store the natural height, or %NULL
*
* Retrieves a widget's initial minimum and natural height.
*
* <note><para>This call is specific to width-for-height
* requests.</para></note>
*
* Since: 3.0
*/
void
gtk_extended_layout_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_height,
gint *natural_height)
{
compute_size_for_orientation (layout, GTK_SIZE_GROUP_VERTICAL,
-1, minimum_height, natural_height);
}
/**
* gtk_extended_layout_get_width_for_height:
* @layout: a #GtkExtendedLayout instance
* @height: the size which is available for allocation
* @minimum_size: (allow-none): location for storing the minimum size, or %NULL
* @natural_size: (allow-none): location for storing the natural size, or %NULL
*
* Retrieves a widget's desired width if it would be given
* the specified @height.
*
* Since: 3.0
*/
void
gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width)
{
compute_size_for_orientation (layout, GTK_SIZE_GROUP_HORIZONTAL,
height, minimum_width, natural_width);
}
/**
* gtk_extended_layout_get_height_for_width:
* @layout: a #GtkExtendedLayout instance
* @width: the size which is available for allocation
* @minimum_size: (allow-none): location for storing the minimum size, or %NULL
* @natural_size: (allow-none): location for storing the natural size, or %NULL
*
* Retrieves a widget's desired height if it would be given
* the specified @width.
*
* Since: 3.0
*/
void
gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height)
{
compute_size_for_orientation (layout, GTK_SIZE_GROUP_VERTICAL,
width, minimum_height, natural_height);
}
/**
* gtk_extended_layout_get_desired_size:
* @layout: a #GtkExtendedLayout instance
* @width: the size which is available for allocation
* @request_natural: Whether to base the contextual request off of the
* base natural or the base minimum
* @minimum_size: (allow-none): location for storing the minimum size, or %NULL
* @natural_size: (allow-none): location for storing the natural size, or %NULL
*
* Retrieves the minimum and natural size of a widget taking
* into account the widget's preference for height-for-width management.
*
* If request_natural is specified, the non-contextual natural value will
* be used to make the contextual request; otherwise the minimum will be used.
*
* This is used to retrieve a suitable size by container widgets which do
* not impose any restrictions on the child placement.
*
* Since: 3.0
*/
void
gtk_extended_layout_get_desired_size (GtkExtendedLayout *layout,
gboolean request_natural,
GtkRequisition *minimum_size,
GtkRequisition *natural_size)
{
gint min_width, nat_width;
gint min_height, nat_height;
g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
if (gtk_extended_layout_is_height_for_width (layout))
{
gtk_extended_layout_get_desired_width (layout, &min_width, &nat_width);
gtk_extended_layout_get_height_for_width (layout,
request_natural ? nat_width : min_width,
&min_height, &nat_height);
}
else
{
gtk_extended_layout_get_desired_height (layout, &min_height, &nat_height);
gtk_extended_layout_get_width_for_height (layout,
request_natural ? nat_height : min_height,
&min_width, &nat_width);
}
if (minimum_size)
{
minimum_size->width = min_width;
minimum_size->height = min_height;
}
if (natural_size)
{
natural_size->width = nat_width;
natural_size->height = nat_height;
}
}
#define __GTK_EXTENDED_LAYOUT_C__
#include "gtkaliasdef.c"

89
gtk/gtkextendedlayout.h Normal file
View File

@ -0,0 +1,89 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2007-2010 Openismus GmbH
*
* Authors:
* Mathias Hasselmann <mathias@openismus.com>
* Tristan Van Berkom <tristan.van.berkom@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_EXTENDED_LAYOUT_H__
#define __GTK_EXTENDED_LAYOUT_H__
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_EXTENDED_LAYOUT (gtk_extended_layout_get_type ())
#define GTK_EXTENDED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_EXTENDED_LAYOUT, GtkExtendedLayout))
#define GTK_EXTENDED_LAYOUT_CLASS(klass) ((GtkExtendedLayoutIface*)g_type_interface_peek ((klass), GTK_TYPE_EXTENDED_LAYOUT))
#define GTK_IS_EXTENDED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_EXTENDED_LAYOUT))
#define GTK_EXTENDED_LAYOUT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_EXTENDED_LAYOUT, GtkExtendedLayoutIface))
typedef struct _GtkExtendedLayout GtkExtendedLayout;
typedef struct _GtkExtendedLayoutIface GtkExtendedLayoutIface;
struct _GtkExtendedLayoutIface
{
GTypeInterface g_iface;
/* virtual table */
gboolean (* is_height_for_width) (GtkExtendedLayout *layout);
void (* get_desired_width) (GtkExtendedLayout *layout,
gint *minimum_width,
gint *natural_width);
void (* get_desired_height) (GtkExtendedLayout *layout,
gint *minimum_height,
gint *natural_height);
void (* get_width_for_height) (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width);
void (* get_height_for_width) (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height);
};
GType gtk_extended_layout_get_type (void) G_GNUC_CONST;
gboolean gtk_extended_layout_is_height_for_width (GtkExtendedLayout *layout);
void gtk_extended_layout_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_width,
gint *natural_width);
void gtk_extended_layout_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_height,
gint *natural_height);
void gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width);
void gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height);
void gtk_extended_layout_get_desired_size (GtkExtendedLayout *layout,
gboolean request_natural,
GtkRequisition *minimum_size,
GtkRequisition *natural_size);
G_END_DECLS
#endif /* __GTK_EXTENDED_LAYOUT_H__ */

View File

@ -323,7 +323,7 @@
* </variablelist>
* <note>
* You can create your own bindings for the
* GtkFileChooserDefault::location-popup signal with custom
* #GtkFileChooserDefault::location-popup signal with custom
* <parameter>path</parameter> strings, and have a crude form
* of easily-to-type bookmarks. For example, say you access
* the path <filename>/home/username/misc</filename> very
@ -504,7 +504,11 @@
* </listitem>
* </varlistentry>
* <varlistentry>
<<<<<<< HEAD
* <term><parameter>bookmark_indes</parameter>&nbsp;:</term>
=======
* <term><parameter>bookmark_index</parameter>&nbsp;:</term>
>>>>>>> native-layout-incubator
* <listitem>
* <simpara>
* index of the bookmark to switch to; the indices start at 0.

View File

@ -31,6 +31,7 @@
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkbuildable.h"
#include "gtkextendedlayout.h"
#include "gtkalias.h"
#define LABEL_PAD 1
@ -81,9 +82,19 @@ static void gtk_frame_buildable_add_child (GtkBuildable *buildable,
GObject *child,
const gchar *type);
static void gtk_frame_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_frame_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_frame_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
G_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_frame_buildable_init))
gtk_frame_buildable_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_frame_extended_layout_init))
static void
gtk_frame_class_init (GtkFrameClass *class)
@ -150,7 +161,6 @@ gtk_frame_class_init (GtkFrameClass *class)
GTK_PARAM_READWRITE));
widget_class->expose_event = gtk_frame_expose;
widget_class->size_request = gtk_frame_size_request;
widget_class->size_allocate = gtk_frame_size_allocate;
container_class->remove = gtk_frame_remove;
@ -601,42 +611,6 @@ gtk_frame_expose (GtkWidget *widget,
return FALSE;
}
static void
gtk_frame_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkFrame *frame = GTK_FRAME (widget);
GtkBin *bin = GTK_BIN (widget);
GtkRequisition child_requisition;
if (frame->label_widget && gtk_widget_get_visible (frame->label_widget))
{
gtk_widget_size_request (frame->label_widget, &child_requisition);
requisition->width = child_requisition.width + 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD;
requisition->height =
MAX (0, child_requisition.height - widget->style->ythickness);
}
else
{
requisition->width = 0;
requisition->height = 0;
}
if (bin->child && gtk_widget_get_visible (bin->child))
{
gtk_widget_size_request (bin->child, &child_requisition);
requisition->width = MAX (requisition->width, child_requisition.width);
requisition->height += child_requisition.height;
}
requisition->width += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->xthickness) * 2;
requisition->height += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->ythickness) * 2;
}
static void
gtk_frame_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
@ -652,11 +626,15 @@ gtk_frame_size_allocate (GtkWidget *widget,
/* If the child allocation changed, that means that the frame is drawn
* in a new place, so we must redraw the entire widget.
*/
if (gtk_widget_get_mapped (widget) &&
if (gtk_widget_get_mapped (widget)
#if 0
&&
(new_allocation.x != frame->child_allocation.x ||
new_allocation.y != frame->child_allocation.y ||
new_allocation.width != frame->child_allocation.width ||
new_allocation.height != frame->child_allocation.height))
new_allocation.height != frame->child_allocation.height)
#endif
)
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
if (bin->child && gtk_widget_get_visible (bin->child))
@ -728,5 +706,103 @@ gtk_frame_real_compute_child_allocation (GtkFrame *frame,
child_allocation->y += allocation->y;
}
static void
gtk_frame_get_desired_size (GtkExtendedLayout *layout,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size)
{
GtkWidget *widget = GTK_WIDGET (layout);
GtkFrame *frame = GTK_FRAME (widget);
GtkBin *bin = GTK_BIN (widget);
gint child_min, child_nat;
gint minimum, natural;
if (frame->label_widget && gtk_widget_get_visible (frame->label_widget))
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (frame->label_widget),
&child_min, &child_nat);
minimum = child_min + 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD;
natural = child_nat + 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD;
}
else
{
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (frame->label_widget),
&child_min, &child_nat);
minimum = MAX (0, child_min - widget->style->ythickness);
natural = MAX (0, child_nat - widget->style->ythickness);
}
}
else
{
minimum = 0;
natural = 0;
}
if (bin->child && gtk_widget_get_visible (bin->child))
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (bin->child),
&child_min, &child_nat);
minimum = MAX (minimum, child_min);
natural = MAX (natural, child_nat);
}
else
{
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (bin->child),
&child_min, &child_nat);
minimum += child_min;
natural += child_nat;
}
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
minimum += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->xthickness) * 2;
natural += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->xthickness) * 2;
}
else
{
minimum += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->ythickness) * 2;
natural += (GTK_CONTAINER (widget)->border_width +
GTK_WIDGET (widget)->style->ythickness) * 2;
}
if (minimum_size)
*minimum_size = minimum;
if (natural_size)
*natural_size = natural;
}
static void
gtk_frame_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_frame_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
}
static void
gtk_frame_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_frame_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
}
static void
gtk_frame_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_frame_get_desired_width;
iface->get_desired_height = gtk_frame_get_desired_height;
}
#define __GTK_FRAME_C__
#include "gtkaliasdef.c"

File diff suppressed because it is too large Load Diff

View File

@ -235,7 +235,8 @@ static const GDebugKey gtk_debug_keys[] = {
{"geometry", GTK_DEBUG_GEOMETRY},
{"icontheme", GTK_DEBUG_ICONTHEME},
{"printing", GTK_DEBUG_PRINTING},
{"builder", GTK_DEBUG_BUILDER}
{"builder", GTK_DEBUG_BUILDER},
{"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
};
#endif /* G_ENABLE_DEBUG */

View File

@ -461,6 +461,7 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
gint border_width;
gboolean need_sliders = FALSE;
gint up_slider_offset = 0;
GtkRequisition child_requisition;
widget->allocation = *allocation;
@ -481,13 +482,15 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
if (path_bar->fake_root)
width = path_bar->spacing + path_bar->slider_width;
else
width = 0;
width = 0;
for (list = path_bar->button_list; list; list = list->next)
{
child = BUTTON_DATA (list->data)->button;
width += child->requisition.width + path_bar->spacing;
gtk_widget_get_child_requisition (child, &child_requisition);
width += child_requisition.width + path_bar->spacing;
if (list == path_bar->fake_root)
break;
}
@ -515,19 +518,23 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
* button, then count backwards.
*/
/* Count down the path chain towards the end. */
width = BUTTON_DATA (first_button->data)->button->requisition.width;
gtk_widget_get_child_requisition (BUTTON_DATA (first_button->data)->button, &child_requisition);
width = child_requisition.width;
list = first_button->prev;
while (list && !reached_end)
{
child = BUTTON_DATA (list->data)->button;
if (width + child->requisition.width +
gtk_widget_get_child_requisition (child, &child_requisition);
if (width + child_requisition.width +
path_bar->spacing + slider_space > allocation_width)
reached_end = TRUE;
else if (list == path_bar->fake_root)
break;
else
width += child->requisition.width + path_bar->spacing;
width += child_requisition.width + path_bar->spacing;
list = list->prev;
}
@ -538,13 +545,15 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
{
child = BUTTON_DATA (first_button->next->data)->button;
if (width + child->requisition.width + path_bar->spacing + slider_space > allocation_width)
gtk_widget_get_child_requisition (child, &child_requisition);
if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
{
reached_end = TRUE;
}
else
{
width += child->requisition.width + path_bar->spacing;
width += child_requisition.width + path_bar->spacing;
if (first_button == path_bar->fake_root)
break;
first_button = first_button->next;
@ -582,7 +591,9 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
button_data = BUTTON_DATA (list->data);
child = button_data->button;
child_allocation.width = MIN (child->requisition.width,
gtk_widget_get_child_requisition (child, &child_requisition);
child_allocation.width = MIN (child_requisition.width,
allocation_width - (path_bar->spacing + path_bar->slider_width) * 2);
if (direction == GTK_TEXT_DIR_RTL)
@ -601,7 +612,7 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
break;
}
if (child_allocation.width < child->requisition.width)
if (child_allocation.width < child_requisition.width)
{
if (!gtk_widget_get_has_tooltip (child))
gtk_widget_set_tooltip_text (child, button_data->dir_name);

View File

@ -35,37 +35,42 @@ G_BEGIN_DECLS
*/
typedef enum
{
PRIVATE_GTK_USER_STYLE = 1 << 0,
PRIVATE_GTK_RESIZE_PENDING = 1 << 2,
PRIVATE_GTK_HAS_POINTER = 1 << 3, /* If the pointer is above a window belonging to the widget */
PRIVATE_GTK_SHADOWED = 1 << 4, /* If there is a grab in effect shadowing the widget */
PRIVATE_GTK_HAS_SHAPE_MASK = 1 << 5,
PRIVATE_GTK_IN_REPARENT = 1 << 6,
PRIVATE_GTK_DIRECTION_SET = 1 << 7, /* If the reading direction is not DIR_NONE */
PRIVATE_GTK_DIRECTION_LTR = 1 << 8, /* If the reading direction is DIR_LTR */
PRIVATE_GTK_ANCHORED = 1 << 9, /* If widget has a GtkWindow ancestor */
PRIVATE_GTK_CHILD_VISIBLE = 1 << 10, /* If widget should be mapped when parent is mapped */
PRIVATE_GTK_REDRAW_ON_ALLOC = 1 << 11, /* If we should queue a draw on the entire widget when it is reallocated */
PRIVATE_GTK_ALLOC_NEEDED = 1 << 12, /* If we we should allocate even if the allocation is the same */
PRIVATE_GTK_REQUEST_NEEDED = 1 << 13 /* Whether we need to call gtk_widget_size_request */
PRIVATE_GTK_USER_STYLE = 1 << 0,
PRIVATE_GTK_RESIZE_PENDING = 1 << 2,
PRIVATE_GTK_HAS_POINTER = 1 << 3, /* If the pointer is above a window belonging to the widget */
PRIVATE_GTK_SHADOWED = 1 << 4, /* If there is a grab in effect shadowing the widget */
PRIVATE_GTK_HAS_SHAPE_MASK = 1 << 5,
PRIVATE_GTK_IN_REPARENT = 1 << 6,
PRIVATE_GTK_DIRECTION_SET = 1 << 7, /* If the reading direction is not DIR_NONE */
PRIVATE_GTK_DIRECTION_LTR = 1 << 8, /* If the reading direction is DIR_LTR */
PRIVATE_GTK_ANCHORED = 1 << 9, /* If widget has a GtkWindow ancestor */
PRIVATE_GTK_CHILD_VISIBLE = 1 << 10, /* If widget should be mapped when parent is mapped */
PRIVATE_GTK_REDRAW_ON_ALLOC = 1 << 11, /* If we should queue a draw on the entire widget when it is reallocated */
PRIVATE_GTK_ALLOC_NEEDED = 1 << 12, /* If we we should allocate even if the allocation is the same */
PRIVATE_GTK_REQUEST_NEEDED = 1 << 13, /* Whether we need to call gtk_widget_size_request */
PRIVATE_GTK_WIDTH_REQUEST_NEEDED = 1 << 14, /* Whether we need to call gtk_extended_layout_get_desired_width */
PRIVATE_GTK_HEIGHT_REQUEST_NEEDED = 1 << 15 /* Whether we need to call gtk_extended_layout_get_desired_height */
} GtkPrivateFlags;
/* Macros for extracting a widgets private_flags from GtkWidget.
*/
#define GTK_PRIVATE_FLAGS(wid) (GTK_WIDGET (wid)->private_flags)
#define GTK_WIDGET_USER_STYLE(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_USER_STYLE) != 0)
#define GTK_CONTAINER_RESIZE_PENDING(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_RESIZE_PENDING) != 0)
#define GTK_WIDGET_HAS_POINTER(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAS_POINTER) != 0)
#define GTK_WIDGET_SHADOWED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_SHADOWED) != 0)
#define GTK_WIDGET_HAS_SHAPE_MASK(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAS_SHAPE_MASK) != 0)
#define GTK_WIDGET_IN_REPARENT(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_IN_REPARENT) != 0)
#define GTK_WIDGET_DIRECTION_SET(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_DIRECTION_SET) != 0)
#define GTK_WIDGET_DIRECTION_LTR(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_DIRECTION_LTR) != 0)
#define GTK_WIDGET_ANCHORED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ANCHORED) != 0)
#define GTK_WIDGET_CHILD_VISIBLE(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_CHILD_VISIBLE) != 0)
#define GTK_WIDGET_REDRAW_ON_ALLOC(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REDRAW_ON_ALLOC) != 0)
#define GTK_WIDGET_ALLOC_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ALLOC_NEEDED) != 0)
#define GTK_WIDGET_REQUEST_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REQUEST_NEEDED) != 0)
#define GTK_PRIVATE_FLAGS(wid) (GTK_WIDGET (wid)->private_flags)
#define GTK_WIDGET_USER_STYLE(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_USER_STYLE) != 0)
#define GTK_CONTAINER_RESIZE_PENDING(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_RESIZE_PENDING) != 0)
#define GTK_WIDGET_HAS_POINTER(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAS_POINTER) != 0)
#define GTK_WIDGET_SHADOWED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_SHADOWED) != 0)
#define GTK_WIDGET_HAS_SHAPE_MASK(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAS_SHAPE_MASK) != 0)
#define GTK_WIDGET_IN_REPARENT(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_IN_REPARENT) != 0)
#define GTK_WIDGET_DIRECTION_SET(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_DIRECTION_SET) != 0)
#define GTK_WIDGET_DIRECTION_LTR(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_DIRECTION_LTR) != 0)
#define GTK_WIDGET_ANCHORED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ANCHORED) != 0)
#define GTK_WIDGET_CHILD_VISIBLE(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_CHILD_VISIBLE) != 0)
#define GTK_WIDGET_REDRAW_ON_ALLOC(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REDRAW_ON_ALLOC) != 0)
#define GTK_WIDGET_ALLOC_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ALLOC_NEEDED) != 0)
#define GTK_WIDGET_REQUEST_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REQUEST_NEEDED) != 0)
#define GTK_WIDGET_WIDTH_REQUEST_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_WIDTH_REQUEST_NEEDED) != 0)
#define GTK_WIDGET_HEIGHT_REQUEST_NEEDED(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HEIGHT_REQUEST_NEEDED) != 0)
/* Macros for setting and clearing private widget flags.
* we use a preprocessor string concatenation here for a clear

View File

@ -28,6 +28,7 @@
#include <math.h>
#include <gdk/gdkkeysyms.h>
#include "gtkbindings.h"
#include "gtkextendedlayout.h"
#include "gtkmarshalers.h"
#include "gtkscrolledwindow.h"
#include "gtkwindow.h"
@ -113,8 +114,6 @@ static void gtk_scrolled_window_screen_changed (GtkWidget *widge
GdkScreen *previous_screen);
static gboolean gtk_scrolled_window_expose (GtkWidget *widget,
GdkEventExpose *event);
static void gtk_scrolled_window_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_scrolled_window_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gboolean gtk_scrolled_window_scroll_event (GtkWidget *widget,
@ -142,9 +141,28 @@ static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjus
static void gtk_scrolled_window_update_real_placement (GtkScrolledWindow *scrolled_window);
static void gtk_scrolled_window_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_scrolled_window_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_scrolled_window_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_scrolled_window_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height);
static void gtk_scrolled_window_get_width_for_height (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height);
static guint signals[LAST_SIGNAL] = {0};
G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
G_DEFINE_TYPE_WITH_CODE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_scrolled_window_extended_layout_init))
static void
add_scroll_binding (GtkBindingSet *binding_set,
@ -198,7 +216,6 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
widget_class->screen_changed = gtk_scrolled_window_screen_changed;
widget_class->expose_event = gtk_scrolled_window_expose;
widget_class->size_request = gtk_scrolled_window_size_request;
widget_class->size_allocate = gtk_scrolled_window_size_allocate;
widget_class->scroll_event = gtk_scrolled_window_scroll_event;
widget_class->focus = gtk_scrolled_window_focus;
@ -380,9 +397,15 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
* gtk_scrolled_window_new:
* @hadjustment: (allow-none): horizontal adjustment
* @vadjustment: (allow-none): vertical adjustment
<<<<<<< HEAD
*
* Creates a new scrolled window.
*
=======
*
* Creates a new scrolled window.
*
>>>>>>> native-layout-incubator
* The two arguments are the scrolled window's adjustments; these will be
* shared with the scrollbars and the child widget to keep the bars in sync
* with the child. Usually you want to pass %NULL for the adjustments, which
@ -1229,98 +1252,6 @@ gtk_scrolled_window_move_focus_out (GtkScrolledWindow *scrolled_window,
g_object_unref (scrolled_window);
}
static void
gtk_scrolled_window_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkScrolledWindow *scrolled_window;
GtkBin *bin;
gint extra_width;
gint extra_height;
gint scrollbar_spacing;
GtkRequisition hscrollbar_requisition;
GtkRequisition vscrollbar_requisition;
GtkRequisition child_requisition;
g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
g_return_if_fail (requisition != NULL);
scrolled_window = GTK_SCROLLED_WINDOW (widget);
bin = GTK_BIN (scrolled_window);
scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window);
extra_width = 0;
extra_height = 0;
requisition->width = 0;
requisition->height = 0;
gtk_widget_size_request (scrolled_window->hscrollbar,
&hscrollbar_requisition);
gtk_widget_size_request (scrolled_window->vscrollbar,
&vscrollbar_requisition);
if (bin->child && gtk_widget_get_visible (bin->child))
{
gtk_widget_size_request (bin->child, &child_requisition);
if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
requisition->width += child_requisition.width;
else
{
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
if (aux_info && aux_info->width > 0)
{
requisition->width += aux_info->width;
extra_width = -1;
}
else
requisition->width += vscrollbar_requisition.width;
}
if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER)
requisition->height += child_requisition.height;
else
{
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
if (aux_info && aux_info->height > 0)
{
requisition->height += aux_info->height;
extra_height = -1;
}
else
requisition->height += hscrollbar_requisition.height;
}
}
if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC ||
scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
{
requisition->width = MAX (requisition->width, hscrollbar_requisition.width);
if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
extra_height = scrollbar_spacing + hscrollbar_requisition.height;
}
if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC ||
scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
{
requisition->height = MAX (requisition->height, vscrollbar_requisition.height);
if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
extra_width = scrollbar_spacing + vscrollbar_requisition.width;
}
requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width);
requisition->height += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_height);
if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
{
requisition->width += 2 * widget->style->xthickness;
requisition->height += 2 * widget->style->ythickness;
}
}
static void
gtk_scrolled_window_relative_allocation (GtkWidget *widget,
GtkAllocation *allocation)
@ -1795,5 +1726,193 @@ _gtk_scrolled_window_get_scrollbar_spacing (GtkScrolledWindow *scrolled_window)
}
}
static void
gtk_scrolled_window_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_scrolled_window_get_desired_width;
iface->get_desired_height = gtk_scrolled_window_get_desired_height;
iface->get_height_for_width = gtk_scrolled_window_get_height_for_width;
iface->get_width_for_height = gtk_scrolled_window_get_width_for_height;
}
static void
gtk_scrolled_window_get_desired_size (GtkExtendedLayout *layout,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size)
{
GtkScrolledWindow *scrolled_window;
GtkBin *bin;
gint extra_width;
gint extra_height;
gint scrollbar_spacing;
GtkRequisition hscrollbar_requisition;
GtkRequisition vscrollbar_requisition;
GtkRequisition minimum_req, natural_req;
gint min_child_size, nat_child_size;
scrolled_window = GTK_SCROLLED_WINDOW (layout);
bin = GTK_BIN (scrolled_window);
scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window);
extra_width = 0;
extra_height = 0;
minimum_req.width = 0;
minimum_req.height = 0;
natural_req.width = 0;
natural_req.height = 0;
gtk_widget_size_request (scrolled_window->hscrollbar,
&hscrollbar_requisition);
gtk_widget_size_request (scrolled_window->vscrollbar,
&vscrollbar_requisition);
if (bin->child && gtk_widget_get_visible (bin->child))
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (bin->child),
&min_child_size,
&nat_child_size);
if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
{
minimum_req.width += min_child_size;
natural_req.width += nat_child_size;
}
else
{
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
if (aux_info && aux_info->width > 0)
{
minimum_req.width += aux_info->width;
natural_req.width += aux_info->width;
extra_width = -1;
}
else
{
minimum_req.width += vscrollbar_requisition.width;
natural_req.width += vscrollbar_requisition.width;
}
}
}
else /* GTK_ORIENTATION_VERTICAL */
{
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (bin->child),
&min_child_size,
&nat_child_size);
if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER)
{
minimum_req.height += min_child_size;
natural_req.height += nat_child_size;
}
else
{
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
if (aux_info && aux_info->height > 0)
{
minimum_req.height += aux_info->height;
natural_req.height += aux_info->height;
extra_height = -1;
}
else
{
minimum_req.height += hscrollbar_requisition.height;
natural_req.height += hscrollbar_requisition.height;
}
}
}
}
if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC ||
scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
{
minimum_req.width = MAX (minimum_req.width, hscrollbar_requisition.width);
natural_req.width = MAX (natural_req.width, hscrollbar_requisition.width);
if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
extra_height = scrollbar_spacing + hscrollbar_requisition.height;
}
if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC ||
scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
{
minimum_req.height = MAX (minimum_req.height, vscrollbar_requisition.height);
natural_req.height = MAX (natural_req.height, vscrollbar_requisition.height);
if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
extra_width = scrollbar_spacing + vscrollbar_requisition.width;
}
minimum_req.width += GTK_CONTAINER (layout)->border_width * 2 + MAX (0, extra_width);
minimum_req.height += GTK_CONTAINER (layout)->border_width * 2 + MAX (0, extra_height);
natural_req.width += GTK_CONTAINER (layout)->border_width * 2 + MAX (0, extra_width);
natural_req.height += GTK_CONTAINER (layout)->border_width * 2 + MAX (0, extra_height);
if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
{
minimum_req.width += 2 * GTK_WIDGET (layout)->style->xthickness;
minimum_req.height += 2 * GTK_WIDGET (layout)->style->ythickness;
natural_req.width += 2 * GTK_WIDGET (layout)->style->xthickness;
natural_req.height += 2 * GTK_WIDGET (layout)->style->ythickness;
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (minimum_size)
*minimum_size = minimum_req.width;
if (natural_size)
*natural_size = natural_req.width;
}
else
{
if (minimum_size)
*minimum_size = minimum_req.height;
if (natural_size)
*natural_size = natural_req.height;
}
}
static void
gtk_scrolled_window_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_scrolled_window_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
}
static void
gtk_scrolled_window_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_scrolled_window_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
}
static void
gtk_scrolled_window_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height)
{
g_return_if_fail (GTK_IS_WIDGET (layout));
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, minimum_height, natural_height);
}
static void
gtk_scrolled_window_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width)
{
g_return_if_fail (GTK_IS_WIDGET (layout));
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, minimum_width, natural_width);
}
#define __GTK_SCROLLED_WINDOW_C__
#include "gtkaliasdef.c"

View File

@ -25,6 +25,7 @@
#include "gtkprivate.h"
#include "gtksizegroup.h"
#include "gtkbuildable.h"
#include "gtkextendedlayout.h"
#include "gtkalias.h"
enum {
@ -71,6 +72,9 @@ static const gchar size_groups_tag[] = "gtk-size-groups";
static GQuark visited_quark;
static const gchar visited_tag[] = "gtk-size-group-visited";
static GQuark bumping_quark;
static const gchar bumping_tag[] = "gtk-size-group-bumping";
static GSList *
get_size_groups (GtkWidget *widget)
{
@ -102,6 +106,18 @@ is_visited (gpointer object)
return g_object_get_qdata (object, visited_quark) != NULL;
}
static void
mark_bumping (gpointer object, gboolean bumping)
{
g_object_set_qdata (object, bumping_quark, bumping ? "bumping" : NULL);
}
static gboolean
is_bumping (gpointer object)
{
return g_object_get_qdata (object, bumping_quark) != NULL;
}
static void
add_group_to_closure (GtkSizeGroup *group,
GtkSizeGroupMode mode,
@ -154,6 +170,8 @@ real_queue_resize (GtkWidget *widget)
{
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_WIDTH_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_HEIGHT_REQUEST_NEEDED);
if (widget->parent)
_gtk_container_queue_resize (GTK_CONTAINER (widget->parent));
@ -284,6 +302,7 @@ initialize_size_group_quarks (void)
{
size_groups_quark = g_quark_from_static_string (size_groups_tag);
visited_quark = g_quark_from_static_string (visited_tag);
bumping_quark = g_quark_from_static_string (bumping_tag);
}
}
@ -607,42 +626,35 @@ get_base_dimension (GtkWidget *widget,
if (aux_info && aux_info->width > 0)
return aux_info->width;
else
return widget->requisition.width;
{
/* XXX Possibly we should be using natural values and not minimums here. */
gint width;
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (widget), &width, NULL);
return width;
}
}
else
{
if (aux_info && aux_info->height > 0)
return aux_info->height;
else
return widget->requisition.height;
{
/* XXX Possibly we should be using natural values and not minimums here. */
gint height;
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (widget), &height, NULL);
return height;
}
}
}
static void
do_size_request (GtkWidget *widget)
{
if (GTK_WIDGET_REQUEST_NEEDED (widget))
{
gtk_widget_ensure_style (widget);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
g_signal_emit_by_name (widget,
"size-request",
&widget->requisition);
}
}
static gint
compute_base_dimension (GtkWidget *widget,
GtkSizeGroupMode mode)
{
do_size_request (widget);
return get_base_dimension (widget, mode);
}
static gint
compute_dimension (GtkWidget *widget,
GtkSizeGroupMode mode)
GtkSizeGroupMode mode,
gint widget_requisition)
{
GSList *widgets = NULL;
GSList *groups = NULL;
@ -658,7 +670,7 @@ compute_dimension (GtkWidget *widget,
if (!groups)
{
result = compute_base_dimension (widget, mode);
result = widget_requisition;
}
else
{
@ -674,8 +686,12 @@ compute_dimension (GtkWidget *widget,
while (tmp_list)
{
GtkWidget *tmp_widget = tmp_list->data;
gint dimension;
gint dimension = compute_base_dimension (tmp_widget, mode);
if (tmp_widget == widget)
dimension = widget_requisition;
else
dimension = get_base_dimension (tmp_widget, mode);
if (gtk_widget_get_mapped (tmp_widget) || !group->ignore_hidden)
{
@ -715,122 +731,58 @@ compute_dimension (GtkWidget *widget,
return result;
}
static gint
get_dimension (GtkWidget *widget,
GtkSizeGroupMode mode)
/**
* _gtk_size_group_bump_requisition:
* @widget: a #GtkWidget
* @mode: either %GTK_SIZE_GROUP_HORIZONTAL or %GTK_SIZE_GROUP_VERTICAL, depending
* on the dimension in which to bump the size.
*
* Refreshes the sizegroup while returning the groups requested
* value in the dimension @mode.
*
* This function is used to update sizegroup minimum size information
* in multiple passes from the new #GtkExtendedLayout manager.
*/
gint
_gtk_size_group_bump_requisition (GtkWidget *widget,
GtkSizeGroupMode mode,
gint widget_requisition)
{
GSList *widgets = NULL;
GSList *groups = NULL;
gint result = 0;
gint result = widget_requisition;
add_widget_to_closure (widget, mode, &groups, &widgets);
g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
if (!groups)
if (!is_bumping (widget))
{
result = get_base_dimension (widget, mode);
GtkWidgetAuxInfo *aux_info =
_gtk_widget_get_aux_info (widget, FALSE);
/* Avoid recursion here */
mark_bumping (widget, TRUE);
if (get_size_groups (widget))
{
if (aux_info)
{
if (mode == GTK_SIZE_GROUP_HORIZONTAL)
result = compute_dimension (widget, mode, MAX (aux_info->width, widget_requisition));
else
result = compute_dimension (widget, mode, MAX (aux_info->height, widget_requisition));
}
else
result = compute_dimension (widget, mode, widget_requisition);
}
else if (aux_info)
{
if (mode == GTK_SIZE_GROUP_HORIZONTAL)
result = MAX (aux_info->width, widget_requisition);
else
result = MAX (aux_info->height, widget_requisition);
}
mark_bumping (widget, FALSE);
}
else
{
GtkSizeGroup *group = groups->data;
if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
result = group->requisition.width;
else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
result = group->requisition.height;
}
g_slist_free (widgets);
g_slist_free (groups);
return result;
}
static void
get_fast_child_requisition (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
*requisition = widget->requisition;
if (aux_info)
{
if (aux_info->width > 0)
requisition->width = aux_info->width;
if (aux_info && aux_info->height > 0)
requisition->height = aux_info->height;
}
}
/**
* _gtk_size_group_get_child_requisition:
* @widget: a #GtkWidget
* @requisition: location to store computed requisition.
*
* Retrieve the "child requisition" of the widget, taking account grouping
* of the widget's requisition with other widgets.
**/
void
_gtk_size_group_get_child_requisition (GtkWidget *widget,
GtkRequisition *requisition)
{
initialize_size_group_quarks ();
if (requisition)
{
if (get_size_groups (widget))
{
requisition->width = get_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
requisition->height = get_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
/* Only do the full computation if we actually have size groups */
}
else
get_fast_child_requisition (widget, requisition);
}
}
/**
* _gtk_size_group_compute_requisition:
* @widget: a #GtkWidget
* @requisition: location to store computed requisition.
*
* Compute the requisition of a widget taking into account grouping of
* the widget's requisition with other widgets.
**/
void
_gtk_size_group_compute_requisition (GtkWidget *widget,
GtkRequisition *requisition)
{
gint width;
gint height;
initialize_size_group_quarks ();
if (get_size_groups (widget))
{
/* Only do the full computation if we actually have size groups */
width = compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
height = compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
if (requisition)
{
requisition->width = width;
requisition->height = height;
}
}
else
{
do_size_request (widget);
if (requisition)
get_fast_child_requisition (widget, requisition);
}
}
/**
* _gtk_size_group_queue_resize:

View File

@ -100,11 +100,12 @@ void gtk_size_group_remove_widget (GtkSizeGroup *size_group,
GSList * gtk_size_group_get_widgets (GtkSizeGroup *size_group);
void _gtk_size_group_get_child_requisition (GtkWidget *widget,
GtkRequisition *requisition);
void _gtk_size_group_compute_requisition (GtkWidget *widget,
GtkRequisition *requisition);
void _gtk_size_group_queue_resize (GtkWidget *widget);
gint _gtk_size_group_bump_requisition (GtkWidget *widget,
GtkSizeGroupMode mode,
gint widget_requisition);
void _gtk_size_group_queue_resize (GtkWidget *widget);
G_END_DECLS

View File

@ -26,6 +26,7 @@
#include "config.h"
#include "gtkviewport.h"
#include "gtkextendedlayout.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
@ -79,8 +80,6 @@ static gint gtk_viewport_expose (GtkWidget *widget,
GdkEventExpose *event);
static void gtk_viewport_add (GtkContainer *container,
GtkWidget *widget);
static void gtk_viewport_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_viewport_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
@ -88,7 +87,18 @@ static void gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
static void gtk_viewport_style_set (GtkWidget *widget,
GtkStyle *previous_style);
G_DEFINE_TYPE (GtkViewport, gtk_viewport, GTK_TYPE_BIN)
static void gtk_viewport_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_viewport_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_viewport_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
G_DEFINE_TYPE_WITH_CODE (GtkViewport, gtk_viewport, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_viewport_extended_layout_init))
static void
gtk_viewport_class_init (GtkViewportClass *class)
@ -111,7 +121,6 @@ gtk_viewport_class_init (GtkViewportClass *class)
widget_class->realize = gtk_viewport_realize;
widget_class->unrealize = gtk_viewport_unrealize;
widget_class->expose_event = gtk_viewport_expose;
widget_class->size_request = gtk_viewport_size_request;
widget_class->size_allocate = gtk_viewport_size_allocate;
widget_class->style_set = gtk_viewport_style_set;
@ -436,10 +445,13 @@ viewport_set_vadjustment_values (GtkViewport *viewport,
if (bin->child && gtk_widget_get_visible (bin->child))
{
GtkRequisition child_requisition;
gint natural_height;
gtk_widget_get_child_requisition (bin->child, &child_requisition);
vadjustment->upper = MAX (child_requisition.height, view_allocation.height);
gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (bin->child),
view_allocation.width,
NULL,
&natural_height);
vadjustment->upper = MAX (natural_height, view_allocation.height);
}
else
vadjustment->upper = view_allocation.height;
@ -740,31 +752,6 @@ gtk_viewport_add (GtkContainer *container,
GTK_CONTAINER_CLASS (gtk_viewport_parent_class)->add (container, child);
}
static void
gtk_viewport_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkBin *bin = GTK_BIN (widget);
GtkRequisition child_requisition;
requisition->width = GTK_CONTAINER (widget)->border_width;
requisition->height = GTK_CONTAINER (widget)->border_width;
if (GTK_VIEWPORT (widget)->shadow_type != GTK_SHADOW_NONE)
{
requisition->width += 2 * widget->style->xthickness;
requisition->height += 2 * widget->style->ythickness;
}
if (bin->child && gtk_widget_get_visible (bin->child))
{
gtk_widget_size_request (bin->child, &child_requisition);
requisition->width += child_requisition.width;
requisition->height += child_requisition.height;
}
}
static void
gtk_viewport_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
@ -868,5 +855,74 @@ gtk_viewport_style_set (GtkWidget *widget,
}
}
static void
gtk_viewport_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_viewport_get_desired_width;
iface->get_desired_height = gtk_viewport_get_desired_height;
}
static void
gtk_viewport_get_desired_size (GtkExtendedLayout *layout,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size)
{
GtkWidget *child;
gint child_min, child_nat;
gint minimum, natural;
child = gtk_bin_get_child (GTK_BIN (layout));
/* XXX This should probably be (border_width * 2); but GTK+ has
* been doing this with a single border for a while now...
*/
minimum = GTK_CONTAINER (layout)->border_width;
if (GTK_VIEWPORT (layout)->shadow_type != GTK_SHADOW_NONE)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
minimum += 2 * GTK_WIDGET (layout)->style->xthickness;
else
minimum += 2 * GTK_WIDGET (layout)->style->ythickness;
}
natural = minimum;
if (child && gtk_widget_get_visible (child))
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child), &child_min, &child_nat);
else
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child), &child_min, &child_nat);
minimum += child_min;
natural += child_nat;
}
if (minimum_size)
*minimum_size = minimum;
if (natural_size)
*natural_size = natural;
}
static void
gtk_viewport_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_viewport_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
}
static void
gtk_viewport_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
gtk_viewport_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
}
#define __GTK_VIEWPORT_C__
#include "gtkaliasdef.c"

View File

@ -53,6 +53,7 @@
#include "gtkinvisible.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtkextendedlayout.h"
#include "gtkalias.h"
/**
@ -344,6 +345,14 @@ static void gtk_widget_buildable_custom_finished (GtkBuildable
static void gtk_widget_buildable_parser_finished (GtkBuildable *buildable,
GtkBuilder *builder);
static void gtk_widget_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_widget_real_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_widget_real_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_widget_queue_tooltip_query (GtkWidget *widget);
static void gtk_widget_set_usize_internal (GtkWidget *widget,
@ -419,6 +428,13 @@ gtk_widget_get_type (void)
NULL /* interface data */
};
const GInterfaceInfo layout_info =
{
(GInterfaceInitFunc) gtk_widget_extended_layout_init,
(GInterfaceFinalizeFunc) NULL,
NULL /* interface data */
};
widget_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
&widget_info, G_TYPE_FLAG_ABSTRACT);
@ -426,7 +442,8 @@ gtk_widget_get_type (void)
&accessibility_info) ;
g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
&buildable_info) ;
g_type_add_interface_static (widget_type, GTK_TYPE_EXTENDED_LAYOUT,
&layout_info) ;
}
return widget_type;
@ -2836,6 +2853,8 @@ gtk_widget_init (GtkWidget *widget)
GTK_PRIVATE_SET_FLAG (widget, GTK_REDRAW_ON_ALLOC);
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_WIDTH_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_HEIGHT_REQUEST_NEEDED);
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
widget->style = gtk_widget_get_default_style ();
@ -3862,7 +3881,7 @@ gtk_widget_draw (GtkWidget *widget,
* Also remember that the size request is not necessarily the size
* a widget will actually be allocated.
*
* See also gtk_widget_get_child_requisition().
* Deprecated: 3.0: Use gtk_extended_layout_get_desired_size() instead.
**/
void
gtk_widget_size_request (GtkWidget *widget,
@ -3872,10 +3891,11 @@ gtk_widget_size_request (GtkWidget *widget,
#ifdef G_ENABLE_DEBUG
if (requisition == &widget->requisition)
g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly.");
g_warning ("gtk_widget_size_request() called on child widget with request equal\n"
"to widget->requisition. gtk_widget_set_usize() may not work properly.");
#endif /* G_ENABLE_DEBUG */
_gtk_size_group_compute_requisition (widget, requisition);
gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), FALSE, requisition, NULL);
}
/**
@ -3901,12 +3921,15 @@ gtk_widget_size_request (GtkWidget *widget,
* since the last time a resize was queued. In general, only container
* implementations have this information; applications should use
* gtk_widget_size_request().
*
*
* Deprecated: 3.0: Use gtk_extended_layout_get_desired_size() instead.
**/
void
gtk_widget_get_child_requisition (GtkWidget *widget,
GtkRequisition *requisition)
{
_gtk_size_group_get_child_requisition (widget, requisition);
gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), FALSE, requisition, NULL);
}
static gboolean
@ -9322,20 +9345,18 @@ _gtk_widget_get_aux_info (GtkWidget *widget,
aux_info = g_object_get_qdata (G_OBJECT (widget), quark_aux_info);
if (!aux_info && create)
{
aux_info = g_slice_new (GtkWidgetAuxInfo);
aux_info = g_slice_new0 (GtkWidgetAuxInfo);
aux_info->width = -1;
aux_info->height = -1;
aux_info->x = 0;
aux_info->y = 0;
aux_info->x_set = FALSE;
aux_info->y_set = FALSE;
g_object_set_qdata (G_OBJECT (widget), quark_aux_info, aux_info);
}
return aux_info;
}
/*****************************************
* gtk_widget_aux_info_destroy:
*
@ -10768,7 +10789,67 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
}
}
/*
* GtkExtendedLayout implementation
*/
static void
gtk_widget_real_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
/* Set the initial values so that unimplemented classes will fall back
* on the "size-request" collected values (see gtksizegroup.c:do_size_request()).
*/
if (minimum_size)
*minimum_size = GTK_WIDGET (layout)->requisition.width;
if (natural_size)
*natural_size = GTK_WIDGET (layout)->requisition.width;
}
static void
gtk_widget_real_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
/* Set the initial values so that unimplemented classes will fall back
* on the "size-request" collected values (see gtksizegroup.c:do_size_request()).
*/
if (minimum_size)
*minimum_size = GTK_WIDGET (layout)->requisition.height;
if (natural_size)
*natural_size = GTK_WIDGET (layout)->requisition.height;
}
static void
gtk_widget_real_get_height_for_width (GtkExtendedLayout *layout,
gint width,
gint *minimum_height,
gint *natural_height)
{
gtk_extended_layout_get_desired_height (layout, minimum_height, natural_height);
}
static void
gtk_widget_real_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
gint *natural_width)
{
gtk_extended_layout_get_desired_width (layout, minimum_width, natural_width);
}
static void
gtk_widget_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_widget_real_get_desired_width;
iface->get_desired_height = gtk_widget_real_get_desired_height;
iface->get_width_for_height = gtk_widget_real_get_width_for_height;
iface->get_height_for_width = gtk_widget_real_get_height_for_width;
}
/**
* gtk_widget_get_clipboard:
* @widget: a #GtkWidget

View File

@ -482,6 +482,7 @@ typedef struct _GtkClipboard GtkClipboard;
typedef struct _GtkTooltip GtkTooltip;
typedef struct _GtkWindow GtkWindow;
/**
* GtkAllocation:
* @x: the X position of the widget's area relative to its parents allocation.
@ -817,6 +818,7 @@ struct _GtkWidgetAuxInfo
gint y;
gint width;
gint height;
guint x_set : 1;
guint y_set : 1;
};

View File

@ -48,6 +48,7 @@
#include "gtkmarshalers.h"
#include "gtkplug.h"
#include "gtkbuildable.h"
#include "gtkextendedlayout.h"
#include "gtkalias.h"
#ifdef GDK_WINDOWING_X11
@ -207,8 +208,6 @@ static void gtk_window_map (GtkWidget *widget);
static void gtk_window_unmap (GtkWidget *widget);
static void gtk_window_realize (GtkWidget *widget);
static void gtk_window_unrealize (GtkWidget *widget);
static void gtk_window_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_window_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gint gtk_window_event (GtkWidget *widget,
@ -350,9 +349,19 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
gpointer user_data);
static void gtk_window_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_window_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
static void gtk_window_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size);
G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_window_buildable_interface_init))
gtk_window_buildable_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
gtk_window_extended_layout_init))
static void
add_tab_bindings (GtkBindingSet *binding_set,
@ -451,7 +460,6 @@ gtk_window_class_init (GtkWindowClass *klass)
widget_class->unmap = gtk_window_unmap;
widget_class->realize = gtk_window_realize;
widget_class->unrealize = gtk_window_unrealize;
widget_class->size_request = gtk_window_size_request;
widget_class->size_allocate = gtk_window_size_allocate;
widget_class->configure_event = gtk_window_configure_event;
widget_class->key_press_event = gtk_window_key_press_event;
@ -4933,30 +4941,6 @@ gtk_window_unrealize (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
}
static void
gtk_window_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkWindow *window;
GtkBin *bin;
window = GTK_WINDOW (widget);
bin = GTK_BIN (window);
requisition->width = GTK_CONTAINER (window)->border_width * 2;
requisition->height = GTK_CONTAINER (window)->border_width * 2;
if (bin->child && gtk_widget_get_visible (bin->child))
{
GtkRequisition child_requisition;
gtk_widget_size_request (bin->child, &child_requisition);
requisition->width += child_requisition.width;
requisition->height += child_requisition.height;
}
}
static void
gtk_window_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
@ -5546,6 +5530,64 @@ gtk_window_real_set_focus (GtkWindow *window,
}
}
static void
gtk_window_extended_layout_init (GtkExtendedLayoutIface *iface)
{
iface->get_desired_width = gtk_window_get_desired_width;
iface->get_desired_height = gtk_window_get_desired_height;
}
static void
gtk_window_get_desired_width (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
GtkWindow *window;
GtkWidget *child;
window = GTK_WINDOW (layout);
child = gtk_bin_get_child (GTK_BIN (window));
*minimum_size = GTK_CONTAINER (window)->border_width * 2;
*natural_size = GTK_CONTAINER (window)->border_width * 2;
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child), &child_min, &child_nat);
*minimum_size += child_min;
*natural_size += child_nat;
}
}
static void
gtk_window_get_desired_height (GtkExtendedLayout *layout,
gint *minimum_size,
gint *natural_size)
{
GtkWindow *window;
GtkWidget *child;
window = GTK_WINDOW (layout);
child = gtk_bin_get_child (GTK_BIN (window));
*minimum_size = GTK_CONTAINER (window)->border_width * 2;
*natural_size = GTK_CONTAINER (window)->border_width * 2;
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child), &child_min, &child_nat);
*minimum_size += child_min;
*natural_size += child_nat;
}
}
/**
* _gtk_window_unset_focus_and_default:
* @window: a #GtkWindow

View File

@ -29,6 +29,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
simple \
flicker \
print-editor \
extendedlayoutexample \
testaccel \
testassistant \
testbbox \
@ -112,6 +113,7 @@ endif
flicker_DEPENDENCIES = $(TEST_DEPS)
simple_DEPENDENCIES = $(TEST_DEPS)
print_editor_DEPENDENCIES = $(TEST_DEPS)
extendedlayoutexample_DEPENDENCIES = $(TEST_DEPS)
testicontheme_DEPENDENCIES = $(TEST_DEPS)
testiconview_DEPENDENCIES = $(TEST_DEPS)
testaccel_DEPENDENCIES = $(TEST_DEPS)
@ -176,6 +178,7 @@ testwindows_DEPENDENCIES = $(TEST_DEPS)
flicker_LDADD = $(LDADDS)
simple_LDADD = $(LDADDS)
print_editor_LDADD = $(LDADDS)
extendedlayoutexample_LDADD = $(LDADDS)
testaccel_LDADD = $(LDADDS)
testassistant_LDADD = $(LDADDS)
testbbox_LDADD = $(LDADDS)

View File

@ -0,0 +1,614 @@
/* extendedlayoutexample.c
* Copyright (C) 2010 Openismus GmbH
*
* Author:
* Tristan Van Berkom <tristan.van.berkom@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gtk/gtk.h>
typedef struct {
const gchar *name;
const gchar *tooltip;
const gchar *interface;
GtkWidget *window;
} TestInterface;
/* These strings were generated with:
*
* IFS=""; while read line; do echo -n \"; echo -n $line | sed -e 's|\"|\\"|g'; echo \"; done < file.glade
*/
TestInterface interfaces[] = {
{
"Ellipsizing Labels",
"Demonstrates how labels will request a natural size in a horizontal space",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">450</property>"
" <property name=\"default_height\">50</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox5\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label9\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some labels do ellipsize</property>"
" <property name=\"ellipsize\">end</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#09610feefe03\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label10\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">but some</property>"
" <property name=\"ellipsize\">end</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#0000af6b0993\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label11\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">do not at all</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Wrapping Label",
"Demonstrates how a wrapping label can require a height contextual to its allocated width",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.18\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"border_width\">12</property>"
" <property name=\"default_width\">300</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox2\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A short static label.</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This is a really long label for the purpose of testing line wrapping is working correctly in conjunction with height-for-width support in GTK+</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"max_width_chars\">30</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#18c52119f796\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkButton\" id=\"button2\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A really really long label inside a button to demonstrate height for width working inside buttons</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"max_width_chars\">25</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#1e3687ab0a52\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This static label\n"
"can shrink.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Horizontal Box",
"Demonstrates how a horizontal box can calculate the collective height for an allocated width",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_height\">200</property>"
" <property name=\"default_width\">600</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkButton\" id=\"button1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <property name=\"use_action_appearance\">False</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A button that wraps.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#0000041dffff\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Lets try setting up some long text to wrap up in this hbox and see if the height-for-width is gonna work !</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">30</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#07d0a9b20972\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkButton\" id=\"button2\">"
" <property name=\"label\" translatable=\"yes\">A button that expands in the vbox</property>"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <property name=\"use_action_appearance\">False</property>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label is\n"
"set to shrink inside\n"
"the paned window.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Vertical Labels",
"Demonstrates how a horizontal box will consider width-for-height when allocating children "
"even if the toplevel window is requested as height-for-width.",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">400</property>"
" <property name=\"default_height\">300</property>"
" <child>"
" <object class=\"GtkVPaned\" id=\"vpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some long width-for-height text that wraps</property>"
" <property name=\"justify\">center</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"angle\">90</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e307ddfb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkFrame\" id=\"frame1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label_xalign\">0</property>"
" <property name=\"shadow_type\">out</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label5\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Neither of the panes are\n"
"set to shrink.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" </child>"
" <child type=\"label_item\">"
" <placeholder/>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox2\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkFrame\" id=\"frame2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label_xalign\">0</property>"
" <property name=\"shadow_type\">out</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">The interface is allocated as height\n"
"for width, but the horizontal boxes\n"
"allocate in width for height mode.</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#000097970808\"/>"
" </attributes>"
" </object>"
" </child>"
" <child type=\"label_item\">"
" <placeholder/>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some long width-for-height text that wraps</property>"
" <property name=\"justify\">center</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"angle\">270</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e307ddfb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Label Parameters",
"This test demonstrates how \"width-chars\" and \"max-width-chars\" can be used "
"to effect minimum and natural widths in wrapping labels.",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">900</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <property name=\"spacing\">6</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">The first 2 labels require 10 characters.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"fill\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label has a maximum natural width of 20 characters. The second two labels expand.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"max_width_chars\">20</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#05c2a161134b\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">True</property>"
" <property name=\"fill\">True</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label requires a default minimum size.</property>"
" <property name=\"wrap\">True</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e30758fb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This test demonstrates how the \"width-chars\" and \"max-width-chars\"\n"
"properties can be used to specify the minimum requested wrap width\n"
"and the maximum natural wrap width respectively.</property>"
" <property name=\"ellipsize\">end</property>"
" <property name=\"width_chars\">30</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#05470000abaf\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label5\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some static\n"
"text that shrinks.\n"
"\n"
"You will need to stretch\n"
"this window quite wide\n"
"to see the effects.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
};
static void
test_clicked (GtkWidget *button,
TestInterface *interface)
{
if (!interface->window)
{
GtkBuilder *builder = gtk_builder_new ();
gtk_builder_add_from_string (builder, interface->interface, -1, NULL);
interface->window = (GtkWidget *)gtk_builder_get_object (builder, "window");
g_signal_connect (interface->window, "delete_event",
G_CALLBACK (gtk_widget_hide_on_delete), NULL);
}
gtk_widget_show (interface->window);
}
static GtkWidget *
create_window (void)
{
GtkWidget *window, *vbox, *button;
gint i;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
for (i = 0; i < G_N_ELEMENTS (interfaces); i++)
{
button = gtk_button_new_with_label (interfaces[i].name);
gtk_widget_set_tooltip_text (button, interfaces[i].tooltip);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (test_clicked), &interfaces[i]);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
}
return window;
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = create_window ();
g_signal_connect (window, "delete-event",
G_CALLBACK (gtk_main_quit), window);
gtk_widget_show (window);
gtk_main ();
return 0;
}

View File

@ -25,6 +25,21 @@
#include <gtk/gtk.h>
static void
redraw_event_box (GtkWidget *widget)
{
while (widget)
{
if (GTK_IS_EVENT_BOX (widget))
{
gtk_widget_queue_draw (widget);
break;
}
widget = gtk_widget_get_parent (widget);
}
}
static void
combo_changed_cb (GtkWidget *combo,
gpointer data)
@ -33,33 +48,123 @@ combo_changed_cb (GtkWidget *combo,
gint active;
active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
gtk_label_set_ellipsize (GTK_LABEL (label), (PangoEllipsizeMode)active);
redraw_event_box (label);
}
static void
scale_changed_cb (GtkRange *range,
gpointer data)
{
double angle = gtk_range_get_value (range);
GtkWidget *label = GTK_WIDGET (data);
gtk_label_set_angle (GTK_LABEL (label), angle);
redraw_event_box (label);
}
static gboolean
ebox_expose_event_cb (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
PangoLayout *layout;
const double dashes[] = { 6, 18 };
GtkRequisition minimum_size, natural_size;
GtkWidget *label = data;
cairo_t *cr;
gint x, y;
cr = gdk_cairo_create (widget->window);
cairo_translate (cr, -0.5, -0.5);
cairo_set_line_width (cr, 1);
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_rectangle (cr, 0, 0, widget->allocation.width, widget->allocation.height);
cairo_fill (cr);
gtk_widget_translate_coordinates (label, widget, 0, 0, &x, &y);
layout = gtk_widget_create_pango_layout (widget, "");
gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (label), FALSE,
&minimum_size, &natural_size);
pango_layout_set_markup (layout,
"<span color='#c33'>\342\227\217 requisition</span>\n"
"<span color='#3c3'>\342\227\217 natural size</span>\n"
"<span color='#33c'>\342\227\217 allocation</span>", -1);
pango_cairo_show_layout (cr, layout);
g_object_unref (layout);
cairo_rectangle (cr,
x + 0.5 * (label->allocation.width - minimum_size.width),
y + 0.5 * (label->allocation.height - minimum_size.height),
minimum_size.width, minimum_size.height);
cairo_set_source_rgb (cr, 0.8, 0.2, 0.2);
cairo_set_dash (cr, NULL, 0, 0);
cairo_stroke (cr);
cairo_rectangle (cr, x, y, label->allocation.width, label->allocation.height);
cairo_set_source_rgb (cr, 0.2, 0.2, 0.8);
cairo_set_dash (cr, dashes, 2, 0.5);
cairo_stroke (cr);
cairo_rectangle (cr,
x + 0.5 * (label->allocation.width - natural_size.width),
y + 0.5 * (label->allocation.height - natural_size.height),
natural_size.width, natural_size.height);
cairo_set_source_rgb (cr, 0.2, 0.8, 0.2);
cairo_set_dash (cr, dashes, 2, 12.5);
cairo_stroke (cr);
cairo_destroy (cr);
return FALSE;
}
int
main (int argc, char *argv[])
{
GtkWidget *window, *vbox, *hbox, *label, *combo;
GtkWidget *window, *vbox, *label;
GtkWidget *combo, *scale, *align, *ebox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (window), 12);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
vbox = gtk_vbox_new (0, FALSE);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (window), vbox);
hbox = gtk_hbox_new (0, FALSE);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
combo = gtk_combo_box_new_text ();
scale = gtk_hscale_new_with_range (0, 360, 1);
label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "NONE");
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "START");
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "MIDDLE");
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), label);
ebox = gtk_event_box_new ();
gtk_widget_set_app_paintable (ebox, TRUE);
gtk_container_add (GTK_CONTAINER (ebox), align);
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), ebox, TRUE, TRUE, 0);
g_object_set_data (G_OBJECT (label), "combo", combo);
g_signal_connect (combo, "changed", G_CALLBACK (combo_changed_cb), label);
g_signal_connect (scale, "value-changed", G_CALLBACK (scale_changed_cb), label);
g_signal_connect (ebox, "expose-event", G_CALLBACK (ebox_expose_event_cb), label);
gtk_widget_show_all (window);