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:
commit
db76c77b81
@ -33,9 +33,16 @@ in a two-dimensional grid.
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To fulfill its task, a layout container must negotiate the size requirements
|
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
|
with its parent and its children. The basic form of this negotiation is
|
||||||
phases, <firstterm>size requisition</firstterm> and <firstterm>size
|
carried out in two phases, <firstterm>size requisition</firstterm> and
|
||||||
allocation</firstterm>.
|
<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>
|
</para>
|
||||||
<refsect2 id="size-requisition"><title>Size Requisition</title>
|
<refsect2 id="size-requisition"><title>Size Requisition</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -141,7 +141,7 @@ the clipboard. Only labels that contain useful-to-copy information
|
|||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2 id="label-text-layout">
|
||||||
<title>Text layout</title>
|
<title>Text layout</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -159,7 +159,19 @@ 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
|
with one another. If you want to set how the label as a whole
|
||||||
aligns in its available space, see gtk_misc_set_alignment().
|
aligns in its available space, see gtk_misc_set_alignment().
|
||||||
</para>
|
</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>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
|
@ -212,6 +212,7 @@ gtk_public_h_sources = \
|
|||||||
gtkenums.h \
|
gtkenums.h \
|
||||||
gtkeventbox.h \
|
gtkeventbox.h \
|
||||||
gtkexpander.h \
|
gtkexpander.h \
|
||||||
|
gtkextendedlayout.h \
|
||||||
gtkfilechooser.h \
|
gtkfilechooser.h \
|
||||||
gtkfilechooserbutton.h \
|
gtkfilechooserbutton.h \
|
||||||
gtkfilechooserdialog.h \
|
gtkfilechooserdialog.h \
|
||||||
@ -466,6 +467,7 @@ gtk_base_c_sources = \
|
|||||||
gtkentrycompletion.c \
|
gtkentrycompletion.c \
|
||||||
gtkeventbox.c \
|
gtkeventbox.c \
|
||||||
gtkexpander.c \
|
gtkexpander.c \
|
||||||
|
gtkextendedlayout.c \
|
||||||
gtkfilechooser.c \
|
gtkfilechooser.c \
|
||||||
gtkfilechooserbutton.c \
|
gtkfilechooserbutton.c \
|
||||||
gtkfilechooserdefault.c \
|
gtkfilechooserdefault.c \
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
#include <gtk/gtkenums.h>
|
#include <gtk/gtkenums.h>
|
||||||
#include <gtk/gtkeventbox.h>
|
#include <gtk/gtkeventbox.h>
|
||||||
#include <gtk/gtkexpander.h>
|
#include <gtk/gtkexpander.h>
|
||||||
|
#include <gtk/gtkextendedlayout.h>
|
||||||
#include <gtk/gtkfixed.h>
|
#include <gtk/gtkfixed.h>
|
||||||
#include <gtk/gtkfilechooser.h>
|
#include <gtk/gtkfilechooser.h>
|
||||||
#include <gtk/gtkfilechooserbutton.h>
|
#include <gtk/gtkfilechooserbutton.h>
|
||||||
|
@ -1504,6 +1504,17 @@ gtk_expander_set_use_underline
|
|||||||
#endif
|
#endif
|
||||||
#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_HEADER(__GTK_FILE_CHOOSER_H__)
|
||||||
#if IN_FILE(__GTK_FILE_CHOOSER_C__)
|
#if IN_FILE(__GTK_FILE_CHOOSER_C__)
|
||||||
gtk_file_chooser_add_filter
|
gtk_file_chooser_add_filter
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gtkalignment.h"
|
#include "gtkalignment.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtkintl.h"
|
#include "gtkintl.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
@ -73,8 +74,6 @@ struct _GtkAlignmentPrivate
|
|||||||
guint padding_right;
|
guint padding_right;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gtk_alignment_size_request (GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
|
||||||
static void gtk_alignment_size_allocate (GtkWidget *widget,
|
static void gtk_alignment_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation);
|
GtkAllocation *allocation);
|
||||||
static void gtk_alignment_set_property (GObject *object,
|
static void gtk_alignment_set_property (GObject *object,
|
||||||
@ -86,7 +85,17 @@ static void gtk_alignment_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec);
|
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
|
static void
|
||||||
gtk_alignment_class_init (GtkAlignmentClass *class)
|
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->set_property = gtk_alignment_set_property;
|
||||||
gobject_class->get_property = gtk_alignment_get_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;
|
widget_class->size_allocate = gtk_alignment_size_allocate;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class,
|
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
|
static void
|
||||||
gtk_alignment_size_allocate (GtkWidget *widget,
|
gtk_alignment_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
GtkAllocation *allocation)
|
||||||
@ -497,7 +477,6 @@ gtk_alignment_size_allocate (GtkWidget *widget,
|
|||||||
GtkAlignment *alignment;
|
GtkAlignment *alignment;
|
||||||
GtkBin *bin;
|
GtkBin *bin;
|
||||||
GtkAllocation child_allocation;
|
GtkAllocation child_allocation;
|
||||||
GtkRequisition child_requisition;
|
|
||||||
gint width, height;
|
gint width, height;
|
||||||
gint border_width;
|
gint border_width;
|
||||||
gint padding_horizontal, padding_vertical;
|
gint padding_horizontal, padding_vertical;
|
||||||
@ -512,7 +491,10 @@ gtk_alignment_size_allocate (GtkWidget *widget,
|
|||||||
|
|
||||||
if (bin->child && gtk_widget_get_visible (bin->child))
|
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;
|
border_width = GTK_CONTAINER (alignment)->border_width;
|
||||||
|
|
||||||
@ -523,15 +505,36 @@ gtk_alignment_size_allocate (GtkWidget *widget,
|
|||||||
width = MAX (1, allocation->width - padding_horizontal - 2 * border_width);
|
width = MAX (1, allocation->width - padding_horizontal - 2 * border_width);
|
||||||
height = MAX (1, allocation->height - padding_vertical - 2 * border_width);
|
height = MAX (1, allocation->height - padding_vertical - 2 * border_width);
|
||||||
|
|
||||||
if (width > child_requisition.width)
|
if (gtk_extended_layout_is_height_for_width (layout))
|
||||||
child_allocation.width = (child_requisition.width *
|
{
|
||||||
|
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) +
|
(1.0 - alignment->xscale) +
|
||||||
width * alignment->xscale);
|
width * alignment->xscale);
|
||||||
else
|
else
|
||||||
child_allocation.width = width;
|
child_allocation.width = width;
|
||||||
|
|
||||||
if (height > child_requisition.height)
|
if (height > child_height)
|
||||||
child_allocation.height = (child_requisition.height *
|
child_allocation.height = (child_height *
|
||||||
(1.0 - alignment->yscale) +
|
(1.0 - alignment->yscale) +
|
||||||
height * alignment->yscale);
|
height * alignment->yscale);
|
||||||
else
|
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:
|
* gtk_alignment_set_padding:
|
||||||
* @alignment: a #GtkAlignment
|
* @alignment: a #GtkAlignment
|
||||||
|
@ -1167,13 +1167,14 @@ gtk_assistant_size_request (GtkWidget *widget,
|
|||||||
requisition->height = height;
|
requisition->height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_assistant_size_allocate (GtkWidget *widget,
|
gtk_assistant_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
GtkAllocation *allocation)
|
||||||
{
|
{
|
||||||
GtkAssistant *assistant = GTK_ASSISTANT (widget);
|
GtkAssistant *assistant = GTK_ASSISTANT (widget);
|
||||||
GtkAssistantPrivate *priv = assistant->priv;
|
GtkAssistantPrivate *priv = assistant->priv;
|
||||||
GtkRequisition header_requisition;
|
GtkRequisition header_requisition, action_requisition, sidebar_requisition;
|
||||||
GtkAllocation child_allocation, header_allocation;
|
GtkAllocation child_allocation, header_allocation;
|
||||||
gint header_padding, content_padding;
|
gint header_padding, content_padding;
|
||||||
gboolean rtl;
|
gboolean rtl;
|
||||||
@ -1200,24 +1201,28 @@ gtk_assistant_size_allocate (GtkWidget *widget,
|
|||||||
gtk_widget_size_allocate (priv->header_image, &header_allocation);
|
gtk_widget_size_allocate (priv->header_image, &header_allocation);
|
||||||
|
|
||||||
/* Action area */
|
/* Action area */
|
||||||
|
gtk_widget_get_child_requisition (priv->action_area, &action_requisition);
|
||||||
|
|
||||||
child_allocation.x = GTK_CONTAINER (widget)->border_width;
|
child_allocation.x = GTK_CONTAINER (widget)->border_width;
|
||||||
child_allocation.y = allocation->height -
|
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.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);
|
gtk_widget_size_allocate (priv->action_area, &child_allocation);
|
||||||
|
|
||||||
/* Sidebar */
|
/* Sidebar */
|
||||||
|
gtk_widget_get_child_requisition (priv->sidebar_image, &sidebar_requisition);
|
||||||
|
|
||||||
if (rtl)
|
if (rtl)
|
||||||
child_allocation.x = allocation->width -
|
child_allocation.x = allocation->width -
|
||||||
GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
|
GTK_CONTAINER (widget)->border_width - sidebar_requisition.width;
|
||||||
else
|
else
|
||||||
child_allocation.x = GTK_CONTAINER (widget)->border_width;
|
child_allocation.x = GTK_CONTAINER (widget)->border_width;
|
||||||
|
|
||||||
child_allocation.y = GTK_CONTAINER (widget)->border_width +
|
child_allocation.y = GTK_CONTAINER (widget)->border_width +
|
||||||
priv->header_image->allocation.height + 2 * header_padding;
|
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 -
|
child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
|
||||||
priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
|
priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
|
||||||
|
|
||||||
|
121
gtk/gtkbin.c
121
gtk/gtkbin.c
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gtkbin.h"
|
#include "gtkbin.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkintl.h"
|
#include "gtkintl.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
|
|
||||||
@ -53,7 +54,22 @@ static void gtk_bin_forall (GtkContainer *container,
|
|||||||
static GType gtk_bin_child_type (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
|
static void
|
||||||
gtk_bin_class_init (GtkBinClass *class)
|
gtk_bin_class_init (GtkBinClass *class)
|
||||||
@ -141,6 +157,109 @@ gtk_bin_forall (GtkContainer *container,
|
|||||||
(* callback) (bin->child, callback_data);
|
(* 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:
|
* gtk_bin_get_child:
|
||||||
* @bin: a #GtkBin
|
* @bin: a #GtkBin
|
||||||
|
952
gtk/gtkbox.c
952
gtk/gtkbox.c
File diff suppressed because it is too large
Load Diff
148
gtk/gtkbutton.c
148
gtk/gtkbutton.c
@ -37,6 +37,7 @@
|
|||||||
#include "gtkstock.h"
|
#include "gtkstock.h"
|
||||||
#include "gtkiconfactory.h"
|
#include "gtkiconfactory.h"
|
||||||
#include "gtkactivatable.h"
|
#include "gtkactivatable.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtkintl.h"
|
#include "gtkintl.h"
|
||||||
#include "gtkalias.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_map (GtkWidget * widget);
|
||||||
static void gtk_button_unmap (GtkWidget * widget);
|
static void gtk_button_unmap (GtkWidget * widget);
|
||||||
static void gtk_button_style_set (GtkWidget * widget, GtkStyle * prev_style);
|
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,
|
static void gtk_button_size_allocate (GtkWidget * widget,
|
||||||
GtkAllocation * allocation);
|
GtkAllocation * allocation);
|
||||||
static gint gtk_button_expose (GtkWidget * widget, GdkEventExpose * event);
|
static gint gtk_button_expose (GtkWidget * widget, GdkEventExpose * event);
|
||||||
@ -159,11 +158,21 @@ static void gtk_button_set_related_action (GtkButton *button,
|
|||||||
static void gtk_button_set_use_action_appearance (GtkButton *button,
|
static void gtk_button_set_use_action_appearance (GtkButton *button,
|
||||||
gboolean use_appearance);
|
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 };
|
static guint button_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
|
G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
|
||||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
|
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
|
static void
|
||||||
gtk_button_class_init (GtkButtonClass *klass)
|
gtk_button_class_init (GtkButtonClass *klass)
|
||||||
@ -191,7 +200,6 @@ gtk_button_class_init (GtkButtonClass *klass)
|
|||||||
widget_class->map = gtk_button_map;
|
widget_class->map = gtk_button_map;
|
||||||
widget_class->unmap = gtk_button_unmap;
|
widget_class->unmap = gtk_button_unmap;
|
||||||
widget_class->style_set = gtk_button_style_set;
|
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->size_allocate = gtk_button_size_allocate;
|
||||||
widget_class->expose_event = gtk_button_expose;
|
widget_class->expose_event = gtk_button_expose;
|
||||||
widget_class->button_press_event = gtk_button_button_press;
|
widget_class->button_press_event = gtk_button_button_press;
|
||||||
@ -1332,49 +1340,6 @@ gtk_button_get_props (GtkButton *button,
|
|||||||
gtk_widget_style_get (widget, "interior-focus", interior_focus, NULL);
|
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
|
static void
|
||||||
gtk_button_size_allocate (GtkWidget *widget,
|
gtk_button_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
GtkAllocation *allocation)
|
||||||
@ -1803,6 +1768,95 @@ gtk_button_finish_activate (GtkButton *button,
|
|||||||
gtk_button_clicked (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:
|
* gtk_button_set_label:
|
||||||
* @button: a #GtkButton
|
* @button: a #GtkButton
|
||||||
|
@ -1370,6 +1370,9 @@ _gtk_container_queue_resize (GtkContainer *container)
|
|||||||
{
|
{
|
||||||
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
|
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
|
||||||
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_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)) ||
|
if ((resize_container && widget == GTK_WIDGET (resize_container)) ||
|
||||||
!widget->parent)
|
!widget->parent)
|
||||||
break;
|
break;
|
||||||
|
@ -47,7 +47,8 @@ typedef enum {
|
|||||||
GTK_DEBUG_GEOMETRY = 1 << 8,
|
GTK_DEBUG_GEOMETRY = 1 << 8,
|
||||||
GTK_DEBUG_ICONTHEME = 1 << 9,
|
GTK_DEBUG_ICONTHEME = 1 << 9,
|
||||||
GTK_DEBUG_PRINTING = 1 << 10,
|
GTK_DEBUG_PRINTING = 1 << 10,
|
||||||
GTK_DEBUG_BUILDER = 1 << 11
|
GTK_DEBUG_BUILDER = 1 << 11,
|
||||||
|
GTK_DEBUG_EXTENDED_LAYOUT = 1 << 12,
|
||||||
} GtkDebugFlag;
|
} GtkDebugFlag;
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
527
gtk/gtkextendedlayout.c
Normal file
527
gtk/gtkextendedlayout.c
Normal 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
89
gtk/gtkextendedlayout.h
Normal 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__ */
|
@ -323,7 +323,7 @@
|
|||||||
* </variablelist>
|
* </variablelist>
|
||||||
* <note>
|
* <note>
|
||||||
* You can create your own bindings for the
|
* 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
|
* <parameter>path</parameter> strings, and have a crude form
|
||||||
* of easily-to-type bookmarks. For example, say you access
|
* of easily-to-type bookmarks. For example, say you access
|
||||||
* the path <filename>/home/username/misc</filename> very
|
* the path <filename>/home/username/misc</filename> very
|
||||||
@ -504,7 +504,11 @@
|
|||||||
* </listitem>
|
* </listitem>
|
||||||
* </varlistentry>
|
* </varlistentry>
|
||||||
* <varlistentry>
|
* <varlistentry>
|
||||||
|
<<<<<<< HEAD
|
||||||
* <term><parameter>bookmark_indes</parameter> :</term>
|
* <term><parameter>bookmark_indes</parameter> :</term>
|
||||||
|
=======
|
||||||
|
* <term><parameter>bookmark_index</parameter> :</term>
|
||||||
|
>>>>>>> native-layout-incubator
|
||||||
* <listitem>
|
* <listitem>
|
||||||
* <simpara>
|
* <simpara>
|
||||||
* index of the bookmark to switch to; the indices start at 0.
|
* index of the bookmark to switch to; the indices start at 0.
|
||||||
|
156
gtk/gtkframe.c
156
gtk/gtkframe.c
@ -31,6 +31,7 @@
|
|||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtkintl.h"
|
#include "gtkintl.h"
|
||||||
#include "gtkbuildable.h"
|
#include "gtkbuildable.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
|
|
||||||
#define LABEL_PAD 1
|
#define LABEL_PAD 1
|
||||||
@ -81,9 +82,19 @@ static void gtk_frame_buildable_add_child (GtkBuildable *buildable,
|
|||||||
GObject *child,
|
GObject *child,
|
||||||
const gchar *type);
|
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_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
|
||||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
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
|
static void
|
||||||
gtk_frame_class_init (GtkFrameClass *class)
|
gtk_frame_class_init (GtkFrameClass *class)
|
||||||
@ -150,7 +161,6 @@ gtk_frame_class_init (GtkFrameClass *class)
|
|||||||
GTK_PARAM_READWRITE));
|
GTK_PARAM_READWRITE));
|
||||||
|
|
||||||
widget_class->expose_event = gtk_frame_expose;
|
widget_class->expose_event = gtk_frame_expose;
|
||||||
widget_class->size_request = gtk_frame_size_request;
|
|
||||||
widget_class->size_allocate = gtk_frame_size_allocate;
|
widget_class->size_allocate = gtk_frame_size_allocate;
|
||||||
|
|
||||||
container_class->remove = gtk_frame_remove;
|
container_class->remove = gtk_frame_remove;
|
||||||
@ -601,42 +611,6 @@ gtk_frame_expose (GtkWidget *widget,
|
|||||||
return FALSE;
|
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
|
static void
|
||||||
gtk_frame_size_allocate (GtkWidget *widget,
|
gtk_frame_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
GtkAllocation *allocation)
|
||||||
@ -652,11 +626,15 @@ gtk_frame_size_allocate (GtkWidget *widget,
|
|||||||
/* If the child allocation changed, that means that the frame is drawn
|
/* If the child allocation changed, that means that the frame is drawn
|
||||||
* in a new place, so we must redraw the entire widget.
|
* 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.x != frame->child_allocation.x ||
|
||||||
new_allocation.y != frame->child_allocation.y ||
|
new_allocation.y != frame->child_allocation.y ||
|
||||||
new_allocation.width != frame->child_allocation.width ||
|
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);
|
gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
|
||||||
|
|
||||||
if (bin->child && gtk_widget_get_visible (bin->child))
|
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;
|
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__
|
#define __GTK_FRAME_C__
|
||||||
#include "gtkaliasdef.c"
|
#include "gtkaliasdef.c"
|
||||||
|
705
gtk/gtklabel.c
705
gtk/gtklabel.c
@ -48,6 +48,7 @@
|
|||||||
#include "gtkimage.h"
|
#include "gtkimage.h"
|
||||||
#include "gtkshow.h"
|
#include "gtkshow.h"
|
||||||
#include "gtktooltip.h"
|
#include "gtktooltip.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
|
|
||||||
@ -153,6 +154,11 @@ enum {
|
|||||||
PROP_TRACK_VISITED_LINKS
|
PROP_TRACK_VISITED_LINKS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* When rotating ellipsizable text we want the natural size to request
|
||||||
|
* more to ensure the label wont ever ellipsize in an allocation of full natural size.
|
||||||
|
* */
|
||||||
|
#define ROTATION_ELLIPSIZE_PADDING 2
|
||||||
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static const GdkColor default_link_color = { 0, 0, 0, 0xeeee };
|
static const GdkColor default_link_color = { 0, 0, 0, 0xeeee };
|
||||||
@ -168,8 +174,6 @@ static void gtk_label_get_property (GObject *object,
|
|||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
static void gtk_label_destroy (GtkObject *object);
|
static void gtk_label_destroy (GtkObject *object);
|
||||||
static void gtk_label_finalize (GObject *object);
|
static void gtk_label_finalize (GObject *object);
|
||||||
static void gtk_label_size_request (GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
|
||||||
static void gtk_label_size_allocate (GtkWidget *widget,
|
static void gtk_label_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation);
|
GtkAllocation *allocation);
|
||||||
static void gtk_label_state_changed (GtkWidget *widget,
|
static void gtk_label_state_changed (GtkWidget *widget,
|
||||||
@ -236,7 +240,7 @@ static void gtk_label_ensure_select_info (GtkLabel *label);
|
|||||||
static void gtk_label_clear_select_info (GtkLabel *label);
|
static void gtk_label_clear_select_info (GtkLabel *label);
|
||||||
static void gtk_label_update_cursor (GtkLabel *label);
|
static void gtk_label_update_cursor (GtkLabel *label);
|
||||||
static void gtk_label_clear_layout (GtkLabel *label);
|
static void gtk_label_clear_layout (GtkLabel *label);
|
||||||
static void gtk_label_ensure_layout (GtkLabel *label);
|
static void gtk_label_ensure_layout (GtkLabel *label, gboolean guess_wrap_width);
|
||||||
static void gtk_label_invalidate_wrap_width (GtkLabel *label);
|
static void gtk_label_invalidate_wrap_width (GtkLabel *label);
|
||||||
static void gtk_label_select_region_index (GtkLabel *label,
|
static void gtk_label_select_region_index (GtkLabel *label,
|
||||||
gint anchor_index,
|
gint anchor_index,
|
||||||
@ -301,13 +305,32 @@ static void gtk_label_get_link_colors (GtkWidget *widget,
|
|||||||
static void emit_activate_link (GtkLabel *label,
|
static void emit_activate_link (GtkLabel *label,
|
||||||
GtkLabelLink *link);
|
GtkLabelLink *link);
|
||||||
|
|
||||||
|
static void gtk_label_extended_layout_init (GtkExtendedLayoutIface *iface);
|
||||||
|
static gboolean gtk_label_is_height_for_width (GtkExtendedLayout *layout);
|
||||||
|
static void gtk_label_get_desired_width (GtkExtendedLayout *layout,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size);
|
||||||
|
static void gtk_label_get_desired_height (GtkExtendedLayout *layout,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size);
|
||||||
|
static void gtk_label_get_width_for_height (GtkExtendedLayout *layout,
|
||||||
|
gint height,
|
||||||
|
gint *minimum_width,
|
||||||
|
gint *natural_width);
|
||||||
|
static void gtk_label_get_height_for_width (GtkExtendedLayout *layout,
|
||||||
|
gint width,
|
||||||
|
gint *minimum_height,
|
||||||
|
gint *natural_height);
|
||||||
|
|
||||||
static GQuark quark_angle = 0;
|
static GQuark quark_angle = 0;
|
||||||
|
|
||||||
static GtkBuildableIface *buildable_parent_iface = NULL;
|
static GtkBuildableIface *buildable_parent_iface = NULL;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
|
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
|
||||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||||
gtk_label_buildable_interface_init));
|
gtk_label_buildable_interface_init)
|
||||||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
|
||||||
|
gtk_label_extended_layout_init));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_move_binding (GtkBindingSet *binding_set,
|
add_move_binding (GtkBindingSet *binding_set,
|
||||||
@ -348,7 +371,6 @@ gtk_label_class_init (GtkLabelClass *class)
|
|||||||
|
|
||||||
object_class->destroy = gtk_label_destroy;
|
object_class->destroy = gtk_label_destroy;
|
||||||
|
|
||||||
widget_class->size_request = gtk_label_size_request;
|
|
||||||
widget_class->size_allocate = gtk_label_size_allocate;
|
widget_class->size_allocate = gtk_label_size_allocate;
|
||||||
widget_class->state_changed = gtk_label_state_changed;
|
widget_class->state_changed = gtk_label_state_changed;
|
||||||
widget_class->style_set = gtk_label_style_set;
|
widget_class->style_set = gtk_label_style_set;
|
||||||
@ -645,10 +667,11 @@ gtk_label_class_init (GtkLabelClass *class)
|
|||||||
* GtkLabel:width-chars:
|
* GtkLabel:width-chars:
|
||||||
*
|
*
|
||||||
* The desired width of the label, in characters. If this property is set to
|
* The desired width of the label, in characters. If this property is set to
|
||||||
* -1, the width will be calculated automatically, otherwise the label will
|
* -1, the width will be calculated automatically.
|
||||||
* request either 3 characters or the property value, whichever is greater.
|
*
|
||||||
* If the "width-chars" property is set to a positive value, then the
|
* See the section on <link linkend="label-text-layout">text layout</link>
|
||||||
* #GtkLabel:max-width-chars property is ignored.
|
* for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
|
||||||
|
* determine the width of ellipsized and wrapped labels.
|
||||||
*
|
*
|
||||||
* Since: 2.6
|
* Since: 2.6
|
||||||
**/
|
**/
|
||||||
@ -705,10 +728,11 @@ gtk_label_class_init (GtkLabelClass *class)
|
|||||||
* GtkLabel:max-width-chars:
|
* GtkLabel:max-width-chars:
|
||||||
*
|
*
|
||||||
* The desired maximum width of the label, in characters. If this property
|
* The desired maximum width of the label, in characters. If this property
|
||||||
* is set to -1, the width will be calculated automatically, otherwise the
|
* is set to -1, the width will be calculated automatically.
|
||||||
* label will request space for no more than the requested number of
|
*
|
||||||
* characters. If the #GtkLabel:width-chars property is set to a positive
|
* See the section on <link linkend="label-text-layout">text layout</link>
|
||||||
* value, then the "max-width-chars" property is ignored.
|
* for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
|
||||||
|
* determine the width of ellipsized and wrapped labels.
|
||||||
*
|
*
|
||||||
* Since: 2.6
|
* Since: 2.6
|
||||||
**/
|
**/
|
||||||
@ -1131,7 +1155,6 @@ attribute_from_text (GtkBuilder *builder,
|
|||||||
value, &val, error))
|
value, &val, error))
|
||||||
attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
|
attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* PangoAttrString */
|
/* PangoAttrString */
|
||||||
case PANGO_ATTR_FAMILY:
|
case PANGO_ATTR_FAMILY:
|
||||||
attribute = pango_attr_family_new (value);
|
attribute = pango_attr_family_new (value);
|
||||||
@ -2912,17 +2935,25 @@ gtk_label_clear_layout (GtkLabel *label)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
|
||||||
get_label_char_width (GtkLabel *label)
|
static void
|
||||||
|
get_label_width (GtkLabel *label,
|
||||||
|
gint *minimum,
|
||||||
|
gint *natural)
|
||||||
{
|
{
|
||||||
|
GtkWidgetAuxInfo *aux_info;
|
||||||
GtkLabelPrivate *priv;
|
GtkLabelPrivate *priv;
|
||||||
|
PangoLayout *layout;
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
PangoFontMetrics *metrics;
|
PangoFontMetrics *metrics;
|
||||||
gint char_width, digit_width, char_pixels, w;
|
PangoRectangle rect;
|
||||||
|
gint char_width, digit_width, char_pixels, text_width, ellipsize_chars, guess_width;
|
||||||
|
|
||||||
priv = GTK_LABEL_GET_PRIVATE (label);
|
priv = GTK_LABEL_GET_PRIVATE (label);
|
||||||
|
aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (label), FALSE);
|
||||||
|
|
||||||
context = pango_layout_get_context (label->layout);
|
layout = pango_layout_copy (label->layout);
|
||||||
|
context = pango_layout_get_context (layout);
|
||||||
metrics = pango_context_get_metrics (context, GTK_WIDGET (label)->style->font_desc,
|
metrics = pango_context_get_metrics (context, GTK_WIDGET (label)->style->font_desc,
|
||||||
pango_context_get_language (context));
|
pango_context_get_language (context));
|
||||||
|
|
||||||
@ -2931,23 +2962,87 @@ get_label_char_width (GtkLabel *label)
|
|||||||
char_pixels = MAX (char_width, digit_width);
|
char_pixels = MAX (char_width, digit_width);
|
||||||
pango_font_metrics_unref (metrics);
|
pango_font_metrics_unref (metrics);
|
||||||
|
|
||||||
if (priv->width_chars < 0)
|
/* Fetch the length of the complete unwrapped text */
|
||||||
{
|
pango_layout_set_width (layout, -1);
|
||||||
PangoRectangle rect;
|
pango_layout_get_extents (layout, NULL, &rect);
|
||||||
|
text_width = rect.width;
|
||||||
|
|
||||||
pango_layout_set_width (label->layout, -1);
|
/* Fetch the width that was guessed by gtk_label_ensure_layout() */
|
||||||
pango_layout_get_extents (label->layout, NULL, &rect);
|
pango_layout_get_extents (label->layout, NULL, &rect);
|
||||||
|
guess_width = rect.width;
|
||||||
|
|
||||||
w = char_pixels * MAX (priv->max_width_chars, 3);
|
/* enforce minimum width for ellipsized labels at ~3 chars */
|
||||||
w = MIN (rect.width, w);
|
if (label->ellipsize)
|
||||||
|
ellipsize_chars = 3;
|
||||||
|
else
|
||||||
|
ellipsize_chars = 0;
|
||||||
|
|
||||||
|
/* "width-chars" Hard-coded minimum width:
|
||||||
|
* - minimum size should be MAX (width-chars, strlen ("..."));
|
||||||
|
* - natural size should be MAX (width-chars, strlen (label->text));
|
||||||
|
*
|
||||||
|
* "max-width-chars" User specified maximum size requisition
|
||||||
|
* - minimum size should be MAX (width-chars, 0)
|
||||||
|
* - natural size should be MIN (max-width-chars, strlen (label->text))
|
||||||
|
*
|
||||||
|
* For ellipsizing labels; if max-width-chars is specified: either it is used as
|
||||||
|
* a minimum size or the label text as a minimum size (natural size still overflows).
|
||||||
|
*
|
||||||
|
* For wrapping labels; A reasonable minimum size is useful to naturally layout
|
||||||
|
* interfaces automatically. In this case if no "width-chars" is specified, the minimum
|
||||||
|
* width will default to the wrap guess that gtk_label_ensure_layout() does.
|
||||||
|
*
|
||||||
|
* In *any* case the minimum width is completely overridden if an explicit width
|
||||||
|
* request was provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (label->ellipsize || label->wrap)
|
||||||
|
{
|
||||||
|
*minimum = char_pixels * MAX (priv->width_chars, ellipsize_chars);
|
||||||
|
|
||||||
|
/* Default to the minimum width regularly guessed by GTK+ if no minimum
|
||||||
|
* width was specified, only allow unwrapping of these labels.
|
||||||
|
*
|
||||||
|
* Note that when specifying a small width_chars for a long text;
|
||||||
|
* an accordingly large size will be required for the label height.
|
||||||
|
*/
|
||||||
|
if (label->wrap && priv->width_chars <= 0)
|
||||||
|
*minimum = guess_width;
|
||||||
|
|
||||||
|
if (priv->max_width_chars < 0)
|
||||||
|
{
|
||||||
|
*natural = MAX (*minimum, text_width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* enforce minimum width for ellipsized labels at ~3 chars */
|
gint max_char_width = char_pixels * priv->max_width_chars;
|
||||||
w = char_pixels * MAX (priv->width_chars, 3);
|
gint max_width = MIN (text_width, max_char_width);
|
||||||
|
|
||||||
|
/* With max-char-width specified, we let the minimum widths of
|
||||||
|
* ellipsized text crawl up to the max-char-width
|
||||||
|
* (note that we dont want to limit the minimum width for wrapping text).
|
||||||
|
*/
|
||||||
|
if (label->ellipsize)
|
||||||
|
*minimum = MIN (text_width, max_width);
|
||||||
|
|
||||||
|
*natural = MAX (*minimum, max_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*minimum = text_width;
|
||||||
|
*natural = *minimum;
|
||||||
}
|
}
|
||||||
|
|
||||||
return w;
|
/* if a width-request is set, use that as the requested label width */
|
||||||
|
if ((label->wrap || label->ellipsize || priv->width_chars > 0 || priv->max_width_chars > 0) &&
|
||||||
|
aux_info && aux_info->width > 0)
|
||||||
|
{
|
||||||
|
*minimum = aux_info->width * PANGO_SCALE;
|
||||||
|
*natural = MAX (*natural, *minimum);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2969,14 +3064,38 @@ get_label_wrap_width (GtkLabel *label)
|
|||||||
|
|
||||||
if (priv->wrap_width < 0)
|
if (priv->wrap_width < 0)
|
||||||
{
|
{
|
||||||
if (priv->width_chars > 0 || priv->max_width_chars > 0)
|
if (priv->width_chars > 0)
|
||||||
priv->wrap_width = get_label_char_width (label);
|
{
|
||||||
|
PangoLayout *layout;
|
||||||
|
PangoContext *context;
|
||||||
|
PangoFontMetrics *metrics;
|
||||||
|
PangoRectangle rect;
|
||||||
|
gint char_width, digit_width, char_pixels, text_width;
|
||||||
|
|
||||||
|
layout = pango_layout_copy (label->layout);
|
||||||
|
context = pango_layout_get_context (layout);
|
||||||
|
metrics = pango_context_get_metrics (context, GTK_WIDGET (label)->style->font_desc,
|
||||||
|
pango_context_get_language (context));
|
||||||
|
|
||||||
|
char_width = pango_font_metrics_get_approximate_char_width (metrics);
|
||||||
|
digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
|
||||||
|
char_pixels = MAX (char_width, digit_width);
|
||||||
|
pango_font_metrics_unref (metrics);
|
||||||
|
|
||||||
|
pango_layout_set_width (layout, -1);
|
||||||
|
pango_layout_get_extents (layout, NULL, &rect);
|
||||||
|
g_object_unref (layout);
|
||||||
|
|
||||||
|
text_width = rect.width;
|
||||||
|
|
||||||
|
priv->wrap_width = PANGO_PIXELS (MAX (text_width, char_pixels * priv->width_chars));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
|
|
||||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (label),
|
layout = gtk_widget_create_pango_layout (GTK_WIDGET (label),
|
||||||
"This long string gives a good enough length for any line to have.");
|
"This string is just about long enough.");
|
||||||
pango_layout_get_size (layout, &priv->wrap_width, NULL);
|
pango_layout_get_size (layout, &priv->wrap_width, NULL);
|
||||||
g_object_unref (layout);
|
g_object_unref (layout);
|
||||||
}
|
}
|
||||||
@ -2986,7 +3105,7 @@ get_label_wrap_width (GtkLabel *label)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_label_ensure_layout (GtkLabel *label)
|
gtk_label_ensure_layout (GtkLabel *label, gboolean guess_wrap_width)
|
||||||
{
|
{
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
PangoRectangle logical_rect;
|
PangoRectangle logical_rect;
|
||||||
@ -3001,14 +3120,14 @@ gtk_label_ensure_layout (GtkLabel *label)
|
|||||||
PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
|
PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
|
||||||
gdouble angle = gtk_label_get_angle (label);
|
gdouble angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
if (angle != 0.0 && !label->wrap && !label->ellipsize && !label->select_info)
|
if (angle != 0.0 && !label->select_info)
|
||||||
{
|
{
|
||||||
|
PangoMatrix matrix = PANGO_MATRIX_INIT;
|
||||||
|
|
||||||
/* We rotate the standard singleton PangoContext for the widget,
|
/* We rotate the standard singleton PangoContext for the widget,
|
||||||
* depending on the fact that it's meant pretty much exclusively
|
* depending on the fact that it's meant pretty much exclusively
|
||||||
* for our use.
|
* for our use.
|
||||||
*/
|
*/
|
||||||
PangoMatrix matrix = PANGO_MATRIX_INIT;
|
|
||||||
|
|
||||||
pango_matrix_rotate (&matrix, angle);
|
pango_matrix_rotate (&matrix, angle);
|
||||||
|
|
||||||
pango_context_set_matrix (gtk_widget_get_pango_context (widget), &matrix);
|
pango_context_set_matrix (gtk_widget_get_pango_context (widget), &matrix);
|
||||||
@ -3058,15 +3177,29 @@ gtk_label_ensure_layout (GtkLabel *label)
|
|||||||
widget->allocation.width * PANGO_SCALE);
|
widget->allocation.width * PANGO_SCALE);
|
||||||
else if (label->wrap)
|
else if (label->wrap)
|
||||||
{
|
{
|
||||||
GtkWidgetAuxInfo *aux_info;
|
GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
|
||||||
gint longest_paragraph;
|
gint longest_paragraph;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
gint aux_width = 0;
|
||||||
|
|
||||||
|
if ((angle == 90 || angle == 270) && aux_info && aux_info->height > 0)
|
||||||
|
aux_width = aux_info->height;
|
||||||
|
else if (aux_info && aux_info->width > 0)
|
||||||
|
aux_width = aux_info->width;
|
||||||
|
|
||||||
|
if (aux_width > 0)
|
||||||
|
pango_layout_set_width (label->layout, aux_width * PANGO_SCALE);
|
||||||
|
else if (guess_wrap_width == FALSE &&
|
||||||
|
widget->allocation.width > 1 && widget->allocation.height > 1)
|
||||||
|
{
|
||||||
|
if (angle == 90 || angle == 270)
|
||||||
|
width = widget->allocation.height - label->misc.ypad * 2;
|
||||||
|
else
|
||||||
|
width = widget->allocation.width - label->misc.xpad * 2;
|
||||||
|
|
||||||
pango_layout_set_wrap (label->layout, label->wrap_mode);
|
pango_layout_set_wrap (label->layout, label->wrap_mode);
|
||||||
|
pango_layout_set_width (label->layout, MAX (width, 1) * PANGO_SCALE);
|
||||||
aux_info = _gtk_widget_get_aux_info (widget, FALSE);
|
}
|
||||||
if (aux_info && aux_info->width > 0)
|
|
||||||
pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (label));
|
GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (label));
|
||||||
@ -3076,7 +3209,6 @@ gtk_label_ensure_layout (GtkLabel *label)
|
|||||||
pango_layout_get_extents (label->layout, NULL, &logical_rect);
|
pango_layout_get_extents (label->layout, NULL, &logical_rect);
|
||||||
|
|
||||||
width = logical_rect.width;
|
width = logical_rect.width;
|
||||||
|
|
||||||
/* Try to guess a reasonable maximum width */
|
/* Try to guess a reasonable maximum width */
|
||||||
longest_paragraph = width;
|
longest_paragraph = width;
|
||||||
|
|
||||||
@ -3130,77 +3262,15 @@ gtk_label_ensure_layout (GtkLabel *label)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gint
|
||||||
gtk_label_size_request (GtkWidget *widget,
|
get_single_line_height (GtkWidget *widget,
|
||||||
GtkRequisition *requisition)
|
PangoLayout *layout)
|
||||||
{
|
|
||||||
GtkLabel *label = GTK_LABEL (widget);
|
|
||||||
GtkLabelPrivate *priv;
|
|
||||||
gint width, height;
|
|
||||||
PangoRectangle logical_rect;
|
|
||||||
GtkWidgetAuxInfo *aux_info;
|
|
||||||
|
|
||||||
priv = GTK_LABEL_GET_PRIVATE (widget);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If word wrapping is on, then the height requisition can depend
|
|
||||||
* on:
|
|
||||||
*
|
|
||||||
* - Any width set on the widget via gtk_widget_set_size_request().
|
|
||||||
* - The padding of the widget (xpad, set by gtk_misc_set_padding)
|
|
||||||
*
|
|
||||||
* Instead of trying to detect changes to these quantities, if we
|
|
||||||
* are wrapping, we just rewrap for each size request. Since
|
|
||||||
* size requisitions are cached by the GTK+ core, this is not
|
|
||||||
* expensive.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (label->wrap)
|
|
||||||
gtk_label_clear_layout (label);
|
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
|
||||||
|
|
||||||
width = label->misc.xpad * 2;
|
|
||||||
height = label->misc.ypad * 2;
|
|
||||||
|
|
||||||
aux_info = _gtk_widget_get_aux_info (widget, FALSE);
|
|
||||||
|
|
||||||
if (label->have_transform)
|
|
||||||
{
|
|
||||||
PangoRectangle rect;
|
|
||||||
PangoContext *context = pango_layout_get_context (label->layout);
|
|
||||||
const PangoMatrix *matrix = pango_context_get_matrix (context);
|
|
||||||
|
|
||||||
pango_layout_get_extents (label->layout, NULL, &rect);
|
|
||||||
pango_matrix_transform_rectangle (matrix, &rect);
|
|
||||||
pango_extents_to_pixels (&rect, NULL);
|
|
||||||
|
|
||||||
requisition->width = width + rect.width;
|
|
||||||
requisition->height = height + rect.height;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pango_layout_get_extents (label->layout, NULL, &logical_rect);
|
|
||||||
|
|
||||||
if ((label->wrap || label->ellipsize ||
|
|
||||||
priv->width_chars > 0 || priv->max_width_chars > 0) &&
|
|
||||||
aux_info && aux_info->width > 0)
|
|
||||||
width += aux_info->width;
|
|
||||||
else if (label->ellipsize || priv->width_chars > 0 || priv->max_width_chars > 0)
|
|
||||||
{
|
|
||||||
width += PANGO_PIXELS (get_label_char_width (label));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
width += PANGO_PIXELS (logical_rect.width);
|
|
||||||
|
|
||||||
if (label->single_line_mode)
|
|
||||||
{
|
{
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
PangoFontMetrics *metrics;
|
PangoFontMetrics *metrics;
|
||||||
gint ascent, descent;
|
gint ascent, descent;
|
||||||
|
|
||||||
context = pango_layout_get_context (label->layout);
|
context = pango_layout_get_context (layout);
|
||||||
metrics = pango_context_get_metrics (context, widget->style->font_desc,
|
metrics = pango_context_get_metrics (context, widget->style->font_desc,
|
||||||
pango_context_get_language (context));
|
pango_context_get_language (context));
|
||||||
|
|
||||||
@ -3208,13 +3278,293 @@ gtk_label_size_request (GtkWidget *widget,
|
|||||||
descent = pango_font_metrics_get_descent (metrics);
|
descent = pango_font_metrics_get_descent (metrics);
|
||||||
pango_font_metrics_unref (metrics);
|
pango_font_metrics_unref (metrics);
|
||||||
|
|
||||||
height += PANGO_PIXELS (ascent + descent);
|
return ascent + descent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_extended_layout_init (GtkExtendedLayoutIface *iface)
|
||||||
|
{
|
||||||
|
iface->is_height_for_width = gtk_label_is_height_for_width;
|
||||||
|
iface->get_desired_width = gtk_label_get_desired_width;
|
||||||
|
iface->get_desired_height = gtk_label_get_desired_height;
|
||||||
|
iface->get_width_for_height = gtk_label_get_width_for_height;
|
||||||
|
iface->get_height_for_width = gtk_label_get_height_for_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_label_is_height_for_width (GtkExtendedLayout *layout)
|
||||||
|
{
|
||||||
|
GtkLabel *label = GTK_LABEL (layout);
|
||||||
|
gdouble angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
|
if (angle == 90 || angle == 270)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_size_for_allocation (GtkLabel *label,
|
||||||
|
GtkOrientation orientation,
|
||||||
|
gint allocation,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size)
|
||||||
|
{
|
||||||
|
PangoLayout *layout;
|
||||||
|
GtkWidgetAuxInfo *aux_info =
|
||||||
|
_gtk_widget_get_aux_info (GTK_WIDGET (label), FALSE);
|
||||||
|
gint aux_size;
|
||||||
|
gint text_height;
|
||||||
|
|
||||||
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
layout = pango_layout_copy (label->layout);
|
||||||
|
|
||||||
|
if (aux_info)
|
||||||
|
{
|
||||||
|
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||||
|
aux_size = aux_info->width;
|
||||||
|
else
|
||||||
|
aux_size = aux_info->height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
height += PANGO_PIXELS (logical_rect.height);
|
aux_size = 0;
|
||||||
|
|
||||||
requisition->width = width;
|
if (aux_size > 0)
|
||||||
requisition->height = height;
|
pango_layout_set_width (layout, aux_size * PANGO_SCALE);
|
||||||
|
else
|
||||||
|
pango_layout_set_width (layout, allocation * PANGO_SCALE);
|
||||||
|
|
||||||
|
pango_layout_get_pixel_size (layout, NULL, &text_height);
|
||||||
|
|
||||||
|
if (minimum_size)
|
||||||
|
*minimum_size = text_height;
|
||||||
|
|
||||||
|
if (natural_size)
|
||||||
|
*natural_size = text_height;
|
||||||
|
|
||||||
|
g_object_unref (layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_get_desired_size (GtkExtendedLayout *layout,
|
||||||
|
GtkOrientation orientation,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size)
|
||||||
|
{
|
||||||
|
GtkLabel *label = GTK_LABEL (layout);
|
||||||
|
PangoRectangle required_rect;
|
||||||
|
PangoRectangle natural_rect;
|
||||||
|
gdouble angle;
|
||||||
|
|
||||||
|
/* "width-chars" Hard-coded minimum width:
|
||||||
|
* - minimum size should be MAX (width-chars, strlen ("..."));
|
||||||
|
* - natural size should be MAX (width-chars, strlen (label->text));
|
||||||
|
*
|
||||||
|
* "max-width-chars" User specified maximum size requisition
|
||||||
|
* - minimum size should be MAX (width-chars, 0)
|
||||||
|
* - natural size should be MIN (max-width-chars, strlen (label->text))
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* When calculating ->wrap sometimes we need to invent a size; Ideally we should be doing
|
||||||
|
* that stuff here instead of inside gtk_label_ensure_layout() */
|
||||||
|
if (label->wrap)
|
||||||
|
gtk_label_clear_layout (label);
|
||||||
|
gtk_label_ensure_layout (label, TRUE);
|
||||||
|
|
||||||
|
angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
|
/* Start off with the pixel extents of the rendered layout */
|
||||||
|
pango_layout_get_extents (label->layout, NULL, &required_rect);
|
||||||
|
required_rect.x = required_rect.y = 0;
|
||||||
|
|
||||||
|
if (label->single_line_mode || label->wrap)
|
||||||
|
required_rect.height = get_single_line_height (GTK_WIDGET (label), label->layout);
|
||||||
|
|
||||||
|
natural_rect = required_rect;
|
||||||
|
|
||||||
|
/* Calculate text width itself based on GtkLabel property rules */
|
||||||
|
get_label_width (label, &required_rect.width, &natural_rect.width);
|
||||||
|
|
||||||
|
/* Now that we have minimum and natural sizes in pango extents, apply a possible transform */
|
||||||
|
if (label->have_transform)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = pango_layout_copy (label->layout);
|
||||||
|
PangoContext *context = pango_layout_get_context (label->layout);
|
||||||
|
const PangoMatrix *matrix = pango_context_get_matrix (context);
|
||||||
|
|
||||||
|
pango_layout_set_width (layout, -1);
|
||||||
|
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE);
|
||||||
|
|
||||||
|
pango_layout_get_extents (layout, NULL, &natural_rect);
|
||||||
|
g_object_unref (layout);
|
||||||
|
|
||||||
|
pango_matrix_transform_rectangle (matrix, &required_rect);
|
||||||
|
pango_matrix_transform_rectangle (matrix, &natural_rect);
|
||||||
|
|
||||||
|
/* Bump the natural size in case of ellipsize to ensure pango has
|
||||||
|
* enough space in the angles (note, we could alternatively set the
|
||||||
|
* layout to not ellipsize when we know we have been allocated our
|
||||||
|
* full natural size, or it may be that pango needs a fix here).
|
||||||
|
*/
|
||||||
|
if (label->ellipsize && angle != 0 && angle != 90 && angle != 180 && angle != 270 && angle != 360)
|
||||||
|
{
|
||||||
|
/* For some reason we only need this at about 110 degrees, and only
|
||||||
|
* when gaining in height
|
||||||
|
*/
|
||||||
|
natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
|
||||||
|
natural_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required_rect.width = PANGO_PIXELS_CEIL (required_rect.width);
|
||||||
|
required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
|
||||||
|
|
||||||
|
natural_rect.width = PANGO_PIXELS_CEIL (natural_rect.width);
|
||||||
|
natural_rect.height = PANGO_PIXELS_CEIL (natural_rect.height);
|
||||||
|
|
||||||
|
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||||
|
{
|
||||||
|
/* Note, we cant use get_size_for_allocation() when rotating
|
||||||
|
* ellipsized labels.
|
||||||
|
*/
|
||||||
|
if (!(label->ellipsize && label->have_transform) &&
|
||||||
|
(angle == 90 || angle == 270))
|
||||||
|
{
|
||||||
|
/* Doing a h4w request on a rotated label here, return the
|
||||||
|
* required width for the minimum height.
|
||||||
|
*/
|
||||||
|
get_size_for_allocation (label,
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
required_rect.height,
|
||||||
|
minimum_size, natural_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Normal desired width */
|
||||||
|
*minimum_size = required_rect.width;
|
||||||
|
*natural_size = natural_rect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
*minimum_size += label->misc.xpad * 2;
|
||||||
|
*natural_size += label->misc.xpad * 2;
|
||||||
|
}
|
||||||
|
else /* GTK_ORIENTATION_VERTICAL */
|
||||||
|
{
|
||||||
|
/* Note, we cant use get_size_for_allocation() when rotating
|
||||||
|
* ellipsized labels.
|
||||||
|
*/
|
||||||
|
if (!(label->ellipsize && label->have_transform) &&
|
||||||
|
(angle == 0 || angle == 180))
|
||||||
|
{
|
||||||
|
/* Doing a w4h request on a label here, return the required
|
||||||
|
* height for the minimum width.
|
||||||
|
*/
|
||||||
|
get_size_for_allocation (label,
|
||||||
|
GTK_ORIENTATION_HORIZONTAL,
|
||||||
|
required_rect.width,
|
||||||
|
minimum_size, natural_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A vertically rotated label does w4h, so return the base
|
||||||
|
* desired height (text length)
|
||||||
|
*/
|
||||||
|
*minimum_size = required_rect.height;
|
||||||
|
*natural_size = natural_rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
*minimum_size += label->misc.ypad * 2;
|
||||||
|
*natural_size += label->misc.ypad * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore real allocated size of layout; sometimes size-requests
|
||||||
|
* are randomly called without a following allocation; for this case
|
||||||
|
* we need to make sure we dont have a mucked up layout because we
|
||||||
|
* went and guessed the wrap-size.
|
||||||
|
*/
|
||||||
|
if (label->wrap)
|
||||||
|
gtk_label_clear_layout (label);
|
||||||
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_get_desired_width (GtkExtendedLayout *layout,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size)
|
||||||
|
{
|
||||||
|
gtk_label_get_desired_size (layout,
|
||||||
|
GTK_ORIENTATION_HORIZONTAL,
|
||||||
|
minimum_size, natural_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_get_desired_height (GtkExtendedLayout *layout,
|
||||||
|
gint *minimum_size,
|
||||||
|
gint *natural_size)
|
||||||
|
{
|
||||||
|
gtk_label_get_desired_size (layout,
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
minimum_size, natural_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_get_width_for_height (GtkExtendedLayout *layout,
|
||||||
|
gint height,
|
||||||
|
gint *minimum_width,
|
||||||
|
gint *natural_width)
|
||||||
|
{
|
||||||
|
GtkLabel *label = GTK_LABEL (layout);
|
||||||
|
gdouble angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
|
if (label->wrap && (angle == 90 || angle == 270))
|
||||||
|
{
|
||||||
|
if (label->wrap)
|
||||||
|
gtk_label_clear_layout (label);
|
||||||
|
|
||||||
|
get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL,
|
||||||
|
MAX (1, height - (label->misc.ypad * 2)),
|
||||||
|
minimum_width, natural_width);
|
||||||
|
|
||||||
|
if (minimum_width)
|
||||||
|
*minimum_width += label->misc.xpad * 2;
|
||||||
|
|
||||||
|
if (natural_width)
|
||||||
|
*natural_width += label->misc.xpad * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, minimum_width, natural_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_get_height_for_width (GtkExtendedLayout *layout,
|
||||||
|
gint width,
|
||||||
|
gint *minimum_height,
|
||||||
|
gint *natural_height)
|
||||||
|
{
|
||||||
|
GtkLabel *label = GTK_LABEL (layout);
|
||||||
|
gdouble angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
|
if (label->wrap && (angle == 0 || angle == 180 || angle == 360))
|
||||||
|
{
|
||||||
|
if (label->wrap)
|
||||||
|
gtk_label_clear_layout (label);
|
||||||
|
|
||||||
|
get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL,
|
||||||
|
MAX (1, width - label->misc.xpad * 2),
|
||||||
|
minimum_height, natural_height);
|
||||||
|
|
||||||
|
if (minimum_height)
|
||||||
|
*minimum_height += label->misc.ypad * 2;
|
||||||
|
|
||||||
|
if (natural_height)
|
||||||
|
*natural_height += label->misc.ypad * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, minimum_height, natural_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3227,20 +3577,85 @@ gtk_label_size_allocate (GtkWidget *widget,
|
|||||||
|
|
||||||
GTK_WIDGET_CLASS (gtk_label_parent_class)->size_allocate (widget, allocation);
|
GTK_WIDGET_CLASS (gtk_label_parent_class)->size_allocate (widget, allocation);
|
||||||
|
|
||||||
|
/* The layout may have been recently cleared in get_size_for_orientation(),
|
||||||
|
* but the width at that point may not be the same as the allocated width
|
||||||
|
*/
|
||||||
|
if (label->wrap)
|
||||||
|
gtk_label_clear_layout (label);
|
||||||
|
|
||||||
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
if (label->ellipsize)
|
if (label->ellipsize)
|
||||||
{
|
{
|
||||||
if (label->layout)
|
if (label->layout)
|
||||||
{
|
{
|
||||||
gint width;
|
|
||||||
PangoRectangle logical;
|
PangoRectangle logical;
|
||||||
|
PangoRectangle bounds;
|
||||||
|
|
||||||
width = (allocation->width - label->misc.xpad * 2) * PANGO_SCALE;
|
bounds.x = bounds.y = 0;
|
||||||
|
bounds.width = allocation->width - label->misc.xpad * 2;
|
||||||
|
bounds.height = allocation->height - label->misc.ypad * 2;
|
||||||
|
|
||||||
pango_layout_set_width (label->layout, -1);
|
pango_layout_set_width (label->layout, -1);
|
||||||
pango_layout_get_extents (label->layout, NULL, &logical);
|
pango_layout_get_pixel_extents (label->layout, NULL, &logical);
|
||||||
|
|
||||||
if (logical.width > width)
|
if (label->have_transform)
|
||||||
pango_layout_set_width (label->layout, width);
|
{
|
||||||
|
PangoContext *context = gtk_widget_get_pango_context (widget);
|
||||||
|
const PangoMatrix *matrix = pango_context_get_matrix (context);
|
||||||
|
|
||||||
|
const gdouble dx = matrix->xx; /* cos (M_PI * angle / 180) */
|
||||||
|
const gdouble dy = matrix->xy; /* sin (M_PI * angle / 180) */
|
||||||
|
if (fabs (dy) < 0.01)
|
||||||
|
{
|
||||||
|
if (logical.width > bounds.width)
|
||||||
|
pango_layout_set_width (label->layout, bounds.width * PANGO_SCALE);
|
||||||
|
}
|
||||||
|
else if (fabs (dx) < 0.01)
|
||||||
|
{
|
||||||
|
if (logical.width > bounds.height)
|
||||||
|
pango_layout_set_width (label->layout, bounds.height * PANGO_SCALE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gdouble x0, y0, x1, y1, length;
|
||||||
|
gboolean vertical;
|
||||||
|
gint cy;
|
||||||
|
|
||||||
|
x0 = bounds.width / 2;
|
||||||
|
y0 = dx ? x0 * dy / dx : dy * INFINITY;
|
||||||
|
vertical = fabs (y0) > bounds.height / 2;
|
||||||
|
|
||||||
|
if (vertical)
|
||||||
|
{
|
||||||
|
y0 = bounds.height/2;
|
||||||
|
x0 = dy ? y0 * dx / dy : dx * INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = 2 * sqrt (x0 * x0 + y0 * y0);
|
||||||
|
pango_layout_set_width (label->layout, rint (length * PANGO_SCALE));
|
||||||
|
pango_layout_get_pixel_size (label->layout, NULL, &cy);
|
||||||
|
|
||||||
|
x1 = +dy * cy/2;
|
||||||
|
y1 = -dx * cy/2;
|
||||||
|
|
||||||
|
if (vertical)
|
||||||
|
{
|
||||||
|
y0 = bounds.height/2 + y1 - y0;
|
||||||
|
x0 = -y0 * dx/dy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x0 = bounds.width/2 + x1 - x0;
|
||||||
|
y0 = -x0 * dy/dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = length - sqrt (x0 * x0 + y0 * y0) * 2;
|
||||||
|
pango_layout_set_width (label->layout, rint (length * PANGO_SCALE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (logical.width > bounds.width)
|
||||||
|
pango_layout_set_width (label->layout, bounds.width * PANGO_SCALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3339,32 +3754,48 @@ get_layout_location (GtkLabel *label,
|
|||||||
GtkLabelPrivate *priv;
|
GtkLabelPrivate *priv;
|
||||||
gfloat xalign;
|
gfloat xalign;
|
||||||
gint req_width, x, y;
|
gint req_width, x, y;
|
||||||
|
gint req_height;
|
||||||
PangoRectangle logical;
|
PangoRectangle logical;
|
||||||
|
gdouble angle;
|
||||||
|
|
||||||
misc = GTK_MISC (label);
|
misc = GTK_MISC (label);
|
||||||
widget = GTK_WIDGET (label);
|
widget = GTK_WIDGET (label);
|
||||||
priv = GTK_LABEL_GET_PRIVATE (label);
|
priv = GTK_LABEL_GET_PRIVATE (label);
|
||||||
|
angle = gtk_label_get_angle (label);
|
||||||
|
|
||||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||||
xalign = misc->xalign;
|
xalign = misc->xalign;
|
||||||
else
|
else
|
||||||
xalign = 1.0 - misc->xalign;
|
xalign = 1.0 - misc->xalign;
|
||||||
|
|
||||||
pango_layout_get_pixel_extents (label->layout, NULL, &logical);
|
pango_layout_get_extents (label->layout, NULL, &logical);
|
||||||
|
|
||||||
if (label->ellipsize || priv->width_chars > 0)
|
/* Do the wrap width delimiting before the transform
|
||||||
|
*/
|
||||||
|
if (label->wrap || label->ellipsize || priv->width_chars > 0)
|
||||||
{
|
{
|
||||||
int width;
|
int width;
|
||||||
|
|
||||||
width = pango_layout_get_width (label->layout);
|
width = pango_layout_get_width (label->layout);
|
||||||
|
|
||||||
req_width = logical.width;
|
|
||||||
if (width != -1)
|
if (width != -1)
|
||||||
req_width = MIN(PANGO_PIXELS (width), req_width);
|
logical.width = MIN (width, logical.width);
|
||||||
req_width += 2 * misc->xpad;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
req_width = widget->requisition.width;
|
if (label->have_transform)
|
||||||
|
{
|
||||||
|
PangoContext *context = gtk_widget_get_pango_context (widget);
|
||||||
|
const PangoMatrix *matrix = pango_context_get_matrix (context);
|
||||||
|
pango_matrix_transform_rectangle (matrix, &logical);
|
||||||
|
}
|
||||||
|
|
||||||
|
pango_extents_to_pixels (&logical, NULL);
|
||||||
|
|
||||||
|
req_width = logical.width;
|
||||||
|
req_height = logical.height;
|
||||||
|
|
||||||
|
req_width += 2 * misc->xpad;
|
||||||
|
req_height += 2 * misc->ypad;
|
||||||
|
|
||||||
x = floor (widget->allocation.x + (gint)misc->xpad +
|
x = floor (widget->allocation.x + (gint)misc->xpad +
|
||||||
xalign * (widget->allocation.width - req_width));
|
xalign * (widget->allocation.width - req_width));
|
||||||
@ -3373,7 +3804,9 @@ get_layout_location (GtkLabel *label,
|
|||||||
x = MAX (x, widget->allocation.x + misc->xpad);
|
x = MAX (x, widget->allocation.x + misc->xpad);
|
||||||
else
|
else
|
||||||
x = MIN (x, widget->allocation.x + widget->allocation.width - misc->xpad);
|
x = MIN (x, widget->allocation.x + widget->allocation.width - misc->xpad);
|
||||||
x -= logical.x;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* bgo#315462 - For single-line labels, *do* align the requisition with
|
/* bgo#315462 - For single-line labels, *do* align the requisition with
|
||||||
* respect to the allocation, even if we are under-allocated. For multi-line
|
* respect to the allocation, even if we are under-allocated. For multi-line
|
||||||
@ -3390,10 +3823,10 @@ get_layout_location (GtkLabel *label,
|
|||||||
*/
|
*/
|
||||||
if (pango_layout_get_line_count (label->layout) == 1)
|
if (pango_layout_get_line_count (label->layout) == 1)
|
||||||
y = floor (widget->allocation.y + (gint)misc->ypad
|
y = floor (widget->allocation.y + (gint)misc->ypad
|
||||||
+ (widget->allocation.height - widget->requisition.height) * misc->yalign);
|
+ (widget->allocation.height - req_height) * misc->yalign);
|
||||||
else
|
else
|
||||||
y = floor (widget->allocation.y + (gint)misc->ypad
|
y = floor (widget->allocation.y + (gint)misc->ypad
|
||||||
+ MAX (((widget->allocation.height - widget->requisition.height) * misc->yalign),
|
+ MAX (((widget->allocation.height - req_height) * misc->yalign),
|
||||||
0));
|
0));
|
||||||
|
|
||||||
if (xp)
|
if (xp)
|
||||||
@ -3430,7 +3863,7 @@ get_cursor_direction (GtkLabel *label)
|
|||||||
|
|
||||||
g_assert (label->select_info);
|
g_assert (label->select_info);
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
for (l = pango_layout_get_lines_readonly (label->layout); l; l = l->next)
|
for (l = pango_layout_get_lines_readonly (label->layout); l; l = l->next)
|
||||||
{
|
{
|
||||||
@ -3475,7 +3908,7 @@ gtk_label_draw_cursor (GtkLabel *label, gint xoffset, gint yoffset)
|
|||||||
keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget)));
|
keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget)));
|
||||||
cursor_direction = get_cursor_direction (label);
|
cursor_direction = get_cursor_direction (label);
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
pango_layout_get_cursor_pos (label->layout, label->select_info->selection_end,
|
pango_layout_get_cursor_pos (label->layout, label->select_info->selection_end,
|
||||||
&strong_pos, &weak_pos);
|
&strong_pos, &weak_pos);
|
||||||
@ -3559,7 +3992,7 @@ gtk_label_expose (GtkWidget *widget,
|
|||||||
GtkLabelSelectionInfo *info = label->select_info;
|
GtkLabelSelectionInfo *info = label->select_info;
|
||||||
gint x, y;
|
gint x, y;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) &&
|
if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) &&
|
||||||
label->text && (*label->text != '\0'))
|
label->text && (*label->text != '\0'))
|
||||||
@ -3972,7 +4405,7 @@ get_layout_index (GtkLabel *label,
|
|||||||
|
|
||||||
*index = 0;
|
*index = 0;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
window_to_layout_coords (label, &x, &y);
|
window_to_layout_coords (label, &x, &y);
|
||||||
|
|
||||||
@ -5016,7 +5449,7 @@ gtk_label_get_layout (GtkLabel *label)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
|
g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
return label->layout;
|
return label->layout;
|
||||||
}
|
}
|
||||||
@ -5043,7 +5476,7 @@ gtk_label_get_layout_offsets (GtkLabel *label,
|
|||||||
{
|
{
|
||||||
g_return_if_fail (GTK_IS_LABEL (label));
|
g_return_if_fail (GTK_IS_LABEL (label));
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
get_layout_location (label, x, y);
|
get_layout_location (label, x, y);
|
||||||
}
|
}
|
||||||
@ -5188,7 +5621,7 @@ get_better_cursor (GtkLabel *label,
|
|||||||
"gtk-split-cursor", &split_cursor,
|
"gtk-split-cursor", &split_cursor,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
pango_layout_get_cursor_pos (label->layout, index,
|
pango_layout_get_cursor_pos (label->layout, index,
|
||||||
&strong_pos, &weak_pos);
|
&strong_pos, &weak_pos);
|
||||||
@ -5228,7 +5661,7 @@ gtk_label_move_logically (GtkLabel *label,
|
|||||||
gint n_attrs;
|
gint n_attrs;
|
||||||
gint length;
|
gint length;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
length = g_utf8_strlen (label->text, -1);
|
length = g_utf8_strlen (label->text, -1);
|
||||||
|
|
||||||
@ -5272,7 +5705,7 @@ gtk_label_move_visually (GtkLabel *label,
|
|||||||
gboolean split_cursor;
|
gboolean split_cursor;
|
||||||
gboolean strong;
|
gboolean strong;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
|
g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
|
||||||
"gtk-split-cursor", &split_cursor,
|
"gtk-split-cursor", &split_cursor,
|
||||||
@ -5325,7 +5758,7 @@ gtk_label_move_forward_word (GtkLabel *label,
|
|||||||
PangoLogAttr *log_attrs;
|
PangoLogAttr *log_attrs;
|
||||||
gint n_attrs;
|
gint n_attrs;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
|
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
|
||||||
|
|
||||||
@ -5353,7 +5786,7 @@ gtk_label_move_backward_word (GtkLabel *label,
|
|||||||
PangoLogAttr *log_attrs;
|
PangoLogAttr *log_attrs;
|
||||||
gint n_attrs;
|
gint n_attrs;
|
||||||
|
|
||||||
gtk_label_ensure_layout (label);
|
gtk_label_ensure_layout (label, FALSE);
|
||||||
|
|
||||||
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
|
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
|
||||||
|
|
||||||
|
@ -235,7 +235,8 @@ static const GDebugKey gtk_debug_keys[] = {
|
|||||||
{"geometry", GTK_DEBUG_GEOMETRY},
|
{"geometry", GTK_DEBUG_GEOMETRY},
|
||||||
{"icontheme", GTK_DEBUG_ICONTHEME},
|
{"icontheme", GTK_DEBUG_ICONTHEME},
|
||||||
{"printing", GTK_DEBUG_PRINTING},
|
{"printing", GTK_DEBUG_PRINTING},
|
||||||
{"builder", GTK_DEBUG_BUILDER}
|
{"builder", GTK_DEBUG_BUILDER},
|
||||||
|
{"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
|
||||||
};
|
};
|
||||||
#endif /* G_ENABLE_DEBUG */
|
#endif /* G_ENABLE_DEBUG */
|
||||||
|
|
||||||
|
@ -461,6 +461,7 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
gint border_width;
|
gint border_width;
|
||||||
gboolean need_sliders = FALSE;
|
gboolean need_sliders = FALSE;
|
||||||
gint up_slider_offset = 0;
|
gint up_slider_offset = 0;
|
||||||
|
GtkRequisition child_requisition;
|
||||||
|
|
||||||
widget->allocation = *allocation;
|
widget->allocation = *allocation;
|
||||||
|
|
||||||
@ -487,7 +488,9 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
child = BUTTON_DATA (list->data)->button;
|
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)
|
if (list == path_bar->fake_root)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -515,19 +518,23 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
* button, then count backwards.
|
* button, then count backwards.
|
||||||
*/
|
*/
|
||||||
/* Count down the path chain towards the end. */
|
/* 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;
|
list = first_button->prev;
|
||||||
while (list && !reached_end)
|
while (list && !reached_end)
|
||||||
{
|
{
|
||||||
child = BUTTON_DATA (list->data)->button;
|
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)
|
path_bar->spacing + slider_space > allocation_width)
|
||||||
reached_end = TRUE;
|
reached_end = TRUE;
|
||||||
else if (list == path_bar->fake_root)
|
else if (list == path_bar->fake_root)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
width += child->requisition.width + path_bar->spacing;
|
width += child_requisition.width + path_bar->spacing;
|
||||||
|
|
||||||
list = list->prev;
|
list = list->prev;
|
||||||
}
|
}
|
||||||
@ -538,13 +545,15 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
child = BUTTON_DATA (first_button->next->data)->button;
|
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;
|
reached_end = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
width += child->requisition.width + path_bar->spacing;
|
width += child_requisition.width + path_bar->spacing;
|
||||||
if (first_button == path_bar->fake_root)
|
if (first_button == path_bar->fake_root)
|
||||||
break;
|
break;
|
||||||
first_button = first_button->next;
|
first_button = first_button->next;
|
||||||
@ -582,7 +591,9 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
button_data = BUTTON_DATA (list->data);
|
button_data = BUTTON_DATA (list->data);
|
||||||
child = button_data->button;
|
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);
|
allocation_width - (path_bar->spacing + path_bar->slider_width) * 2);
|
||||||
|
|
||||||
if (direction == GTK_TEXT_DIR_RTL)
|
if (direction == GTK_TEXT_DIR_RTL)
|
||||||
@ -601,7 +612,7 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_allocation.width < child->requisition.width)
|
if (child_allocation.width < child_requisition.width)
|
||||||
{
|
{
|
||||||
if (!gtk_widget_get_has_tooltip (child))
|
if (!gtk_widget_get_has_tooltip (child))
|
||||||
gtk_widget_set_tooltip_text (child, button_data->dir_name);
|
gtk_widget_set_tooltip_text (child, button_data->dir_name);
|
||||||
|
@ -47,7 +47,10 @@ typedef enum
|
|||||||
PRIVATE_GTK_CHILD_VISIBLE = 1 << 10, /* If widget should be mapped when parent is mapped */
|
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_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_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_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;
|
} GtkPrivateFlags;
|
||||||
|
|
||||||
/* Macros for extracting a widgets private_flags from GtkWidget.
|
/* Macros for extracting a widgets private_flags from GtkWidget.
|
||||||
@ -66,6 +69,8 @@ typedef enum
|
|||||||
#define GTK_WIDGET_REDRAW_ON_ALLOC(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REDRAW_ON_ALLOC) != 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_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_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.
|
/* Macros for setting and clearing private widget flags.
|
||||||
* we use a preprocessor string concatenation here for a clear
|
* we use a preprocessor string concatenation here for a clear
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms.h>
|
||||||
#include "gtkbindings.h"
|
#include "gtkbindings.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
#include "gtkscrolledwindow.h"
|
#include "gtkscrolledwindow.h"
|
||||||
#include "gtkwindow.h"
|
#include "gtkwindow.h"
|
||||||
@ -113,8 +114,6 @@ static void gtk_scrolled_window_screen_changed (GtkWidget *widge
|
|||||||
GdkScreen *previous_screen);
|
GdkScreen *previous_screen);
|
||||||
static gboolean gtk_scrolled_window_expose (GtkWidget *widget,
|
static gboolean gtk_scrolled_window_expose (GtkWidget *widget,
|
||||||
GdkEventExpose *event);
|
GdkEventExpose *event);
|
||||||
static void gtk_scrolled_window_size_request (GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
|
||||||
static void gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
static void gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation);
|
GtkAllocation *allocation);
|
||||||
static gboolean gtk_scrolled_window_scroll_event (GtkWidget *widget,
|
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_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};
|
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
|
static void
|
||||||
add_scroll_binding (GtkBindingSet *binding_set,
|
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->screen_changed = gtk_scrolled_window_screen_changed;
|
||||||
widget_class->expose_event = gtk_scrolled_window_expose;
|
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->size_allocate = gtk_scrolled_window_size_allocate;
|
||||||
widget_class->scroll_event = gtk_scrolled_window_scroll_event;
|
widget_class->scroll_event = gtk_scrolled_window_scroll_event;
|
||||||
widget_class->focus = gtk_scrolled_window_focus;
|
widget_class->focus = gtk_scrolled_window_focus;
|
||||||
@ -380,9 +397,15 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
|
|||||||
* gtk_scrolled_window_new:
|
* gtk_scrolled_window_new:
|
||||||
* @hadjustment: (allow-none): horizontal adjustment
|
* @hadjustment: (allow-none): horizontal adjustment
|
||||||
* @vadjustment: (allow-none): vertical adjustment
|
* @vadjustment: (allow-none): vertical adjustment
|
||||||
|
<<<<<<< HEAD
|
||||||
*
|
*
|
||||||
* Creates a new scrolled window.
|
* 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
|
* 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
|
* 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
|
* 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);
|
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
|
static void
|
||||||
gtk_scrolled_window_relative_allocation (GtkWidget *widget,
|
gtk_scrolled_window_relative_allocation (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
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__
|
#define __GTK_SCROLLED_WINDOW_C__
|
||||||
#include "gtkaliasdef.c"
|
#include "gtkaliasdef.c"
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtksizegroup.h"
|
#include "gtksizegroup.h"
|
||||||
#include "gtkbuildable.h"
|
#include "gtkbuildable.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -71,6 +72,9 @@ static const gchar size_groups_tag[] = "gtk-size-groups";
|
|||||||
static GQuark visited_quark;
|
static GQuark visited_quark;
|
||||||
static const gchar visited_tag[] = "gtk-size-group-visited";
|
static const gchar visited_tag[] = "gtk-size-group-visited";
|
||||||
|
|
||||||
|
static GQuark bumping_quark;
|
||||||
|
static const gchar bumping_tag[] = "gtk-size-group-bumping";
|
||||||
|
|
||||||
static GSList *
|
static GSList *
|
||||||
get_size_groups (GtkWidget *widget)
|
get_size_groups (GtkWidget *widget)
|
||||||
{
|
{
|
||||||
@ -102,6 +106,18 @@ is_visited (gpointer object)
|
|||||||
return g_object_get_qdata (object, visited_quark) != NULL;
|
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
|
static void
|
||||||
add_group_to_closure (GtkSizeGroup *group,
|
add_group_to_closure (GtkSizeGroup *group,
|
||||||
GtkSizeGroupMode mode,
|
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_ALLOC_NEEDED);
|
||||||
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_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)
|
if (widget->parent)
|
||||||
_gtk_container_queue_resize (GTK_CONTAINER (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);
|
size_groups_quark = g_quark_from_static_string (size_groups_tag);
|
||||||
visited_quark = g_quark_from_static_string (visited_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)
|
if (aux_info && aux_info->width > 0)
|
||||||
return aux_info->width;
|
return aux_info->width;
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
if (aux_info && aux_info->height > 0)
|
if (aux_info && aux_info->height > 0)
|
||||||
return aux_info->height;
|
return aux_info->height;
|
||||||
else
|
else
|
||||||
return widget->requisition.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_size_request (GtkWidget *widget)
|
|
||||||
{
|
{
|
||||||
if (GTK_WIDGET_REQUEST_NEEDED (widget))
|
/* XXX Possibly we should be using natural values and not minimums here. */
|
||||||
{
|
gint height;
|
||||||
gtk_widget_ensure_style (widget);
|
|
||||||
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
|
gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (widget), &height, NULL);
|
||||||
g_signal_emit_by_name (widget,
|
|
||||||
"size-request",
|
return height;
|
||||||
&widget->requisition);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
|
||||||
compute_base_dimension (GtkWidget *widget,
|
|
||||||
GtkSizeGroupMode mode)
|
|
||||||
{
|
|
||||||
do_size_request (widget);
|
|
||||||
|
|
||||||
return get_base_dimension (widget, mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
compute_dimension (GtkWidget *widget,
|
compute_dimension (GtkWidget *widget,
|
||||||
GtkSizeGroupMode mode)
|
GtkSizeGroupMode mode,
|
||||||
|
gint widget_requisition)
|
||||||
{
|
{
|
||||||
GSList *widgets = NULL;
|
GSList *widgets = NULL;
|
||||||
GSList *groups = NULL;
|
GSList *groups = NULL;
|
||||||
@ -658,7 +670,7 @@ compute_dimension (GtkWidget *widget,
|
|||||||
|
|
||||||
if (!groups)
|
if (!groups)
|
||||||
{
|
{
|
||||||
result = compute_base_dimension (widget, mode);
|
result = widget_requisition;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -674,8 +686,12 @@ compute_dimension (GtkWidget *widget,
|
|||||||
while (tmp_list)
|
while (tmp_list)
|
||||||
{
|
{
|
||||||
GtkWidget *tmp_widget = tmp_list->data;
|
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)
|
if (gtk_widget_get_mapped (tmp_widget) || !group->ignore_hidden)
|
||||||
{
|
{
|
||||||
@ -715,122 +731,58 @@ compute_dimension (GtkWidget *widget,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
/**
|
||||||
get_dimension (GtkWidget *widget,
|
* _gtk_size_group_bump_requisition:
|
||||||
GtkSizeGroupMode mode)
|
* @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;
|
gint result = widget_requisition;
|
||||||
GSList *groups = NULL;
|
|
||||||
gint result = 0;
|
|
||||||
|
|
||||||
add_widget_to_closure (widget, mode, &groups, &widgets);
|
if (!is_bumping (widget))
|
||||||
|
|
||||||
g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
|
|
||||||
g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
|
|
||||||
|
|
||||||
if (!groups)
|
|
||||||
{
|
{
|
||||||
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
|
else
|
||||||
{
|
result = compute_dimension (widget, mode, widget_requisition);
|
||||||
GtkSizeGroup *group = groups->data;
|
}
|
||||||
|
else if (aux_info)
|
||||||
if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
|
{
|
||||||
result = group->requisition.width;
|
if (mode == GTK_SIZE_GROUP_HORIZONTAL)
|
||||||
else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
|
result = MAX (aux_info->width, widget_requisition);
|
||||||
result = group->requisition.height;
|
else
|
||||||
|
result = MAX (aux_info->height, widget_requisition);
|
||||||
|
}
|
||||||
|
mark_bumping (widget, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_free (widgets);
|
|
||||||
g_slist_free (groups);
|
|
||||||
|
|
||||||
return result;
|
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:
|
* _gtk_size_group_queue_resize:
|
||||||
|
@ -100,12 +100,13 @@ void gtk_size_group_remove_widget (GtkSizeGroup *size_group,
|
|||||||
GSList * gtk_size_group_get_widgets (GtkSizeGroup *size_group);
|
GSList * gtk_size_group_get_widgets (GtkSizeGroup *size_group);
|
||||||
|
|
||||||
|
|
||||||
void _gtk_size_group_get_child_requisition (GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
gint _gtk_size_group_bump_requisition (GtkWidget *widget,
|
||||||
void _gtk_size_group_compute_requisition (GtkWidget *widget,
|
GtkSizeGroupMode mode,
|
||||||
GtkRequisition *requisition);
|
gint widget_requisition);
|
||||||
void _gtk_size_group_queue_resize (GtkWidget *widget);
|
void _gtk_size_group_queue_resize (GtkWidget *widget);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GTK_SIZE_GROUP_H__ */
|
#endif /* __GTK_SIZE_GROUP_H__ */
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gtkviewport.h"
|
#include "gtkviewport.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkintl.h"
|
#include "gtkintl.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
@ -79,8 +80,6 @@ static gint gtk_viewport_expose (GtkWidget *widget,
|
|||||||
GdkEventExpose *event);
|
GdkEventExpose *event);
|
||||||
static void gtk_viewport_add (GtkContainer *container,
|
static void gtk_viewport_add (GtkContainer *container,
|
||||||
GtkWidget *widget);
|
GtkWidget *widget);
|
||||||
static void gtk_viewport_size_request (GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
|
||||||
static void gtk_viewport_size_allocate (GtkWidget *widget,
|
static void gtk_viewport_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation);
|
GtkAllocation *allocation);
|
||||||
static void gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
|
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,
|
static void gtk_viewport_style_set (GtkWidget *widget,
|
||||||
GtkStyle *previous_style);
|
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
|
static void
|
||||||
gtk_viewport_class_init (GtkViewportClass *class)
|
gtk_viewport_class_init (GtkViewportClass *class)
|
||||||
@ -111,7 +121,6 @@ gtk_viewport_class_init (GtkViewportClass *class)
|
|||||||
widget_class->realize = gtk_viewport_realize;
|
widget_class->realize = gtk_viewport_realize;
|
||||||
widget_class->unrealize = gtk_viewport_unrealize;
|
widget_class->unrealize = gtk_viewport_unrealize;
|
||||||
widget_class->expose_event = gtk_viewport_expose;
|
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->size_allocate = gtk_viewport_size_allocate;
|
||||||
widget_class->style_set = gtk_viewport_style_set;
|
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))
|
if (bin->child && gtk_widget_get_visible (bin->child))
|
||||||
{
|
{
|
||||||
GtkRequisition child_requisition;
|
gint natural_height;
|
||||||
|
|
||||||
gtk_widget_get_child_requisition (bin->child, &child_requisition);
|
gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (bin->child),
|
||||||
vadjustment->upper = MAX (child_requisition.height, view_allocation.height);
|
view_allocation.width,
|
||||||
|
NULL,
|
||||||
|
&natural_height);
|
||||||
|
vadjustment->upper = MAX (natural_height, view_allocation.height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vadjustment->upper = view_allocation.height;
|
vadjustment->upper = view_allocation.height;
|
||||||
@ -740,31 +752,6 @@ gtk_viewport_add (GtkContainer *container,
|
|||||||
GTK_CONTAINER_CLASS (gtk_viewport_parent_class)->add (container, child);
|
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
|
static void
|
||||||
gtk_viewport_size_allocate (GtkWidget *widget,
|
gtk_viewport_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
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__
|
#define __GTK_VIEWPORT_C__
|
||||||
#include "gtkaliasdef.c"
|
#include "gtkaliasdef.c"
|
||||||
|
101
gtk/gtkwidget.c
101
gtk/gtkwidget.c
@ -53,6 +53,7 @@
|
|||||||
#include "gtkinvisible.h"
|
#include "gtkinvisible.h"
|
||||||
#include "gtkbuildable.h"
|
#include "gtkbuildable.h"
|
||||||
#include "gtkbuilderprivate.h"
|
#include "gtkbuilderprivate.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkalias.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,
|
static void gtk_widget_buildable_parser_finished (GtkBuildable *buildable,
|
||||||
GtkBuilder *builder);
|
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_queue_tooltip_query (GtkWidget *widget);
|
||||||
|
|
||||||
static void gtk_widget_set_usize_internal (GtkWidget *widget,
|
static void gtk_widget_set_usize_internal (GtkWidget *widget,
|
||||||
@ -419,6 +428,13 @@ gtk_widget_get_type (void)
|
|||||||
NULL /* interface data */
|
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_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
|
||||||
&widget_info, G_TYPE_FLAG_ABSTRACT);
|
&widget_info, G_TYPE_FLAG_ABSTRACT);
|
||||||
|
|
||||||
@ -426,7 +442,8 @@ gtk_widget_get_type (void)
|
|||||||
&accessibility_info) ;
|
&accessibility_info) ;
|
||||||
g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
|
g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
|
||||||
&buildable_info) ;
|
&buildable_info) ;
|
||||||
|
g_type_add_interface_static (widget_type, GTK_TYPE_EXTENDED_LAYOUT,
|
||||||
|
&layout_info) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget_type;
|
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_REDRAW_ON_ALLOC);
|
||||||
GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_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);
|
||||||
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
|
GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
|
||||||
|
|
||||||
widget->style = gtk_widget_get_default_style ();
|
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
|
* Also remember that the size request is not necessarily the size
|
||||||
* a widget will actually be allocated.
|
* 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
|
void
|
||||||
gtk_widget_size_request (GtkWidget *widget,
|
gtk_widget_size_request (GtkWidget *widget,
|
||||||
@ -3872,10 +3891,11 @@ gtk_widget_size_request (GtkWidget *widget,
|
|||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
if (requisition == &widget->requisition)
|
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 */
|
#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
|
* since the last time a resize was queued. In general, only container
|
||||||
* implementations have this information; applications should use
|
* implementations have this information; applications should use
|
||||||
* gtk_widget_size_request().
|
* gtk_widget_size_request().
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Deprecated: 3.0: Use gtk_extended_layout_get_desired_size() instead.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
gtk_widget_get_child_requisition (GtkWidget *widget,
|
gtk_widget_get_child_requisition (GtkWidget *widget,
|
||||||
GtkRequisition *requisition)
|
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
|
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);
|
aux_info = g_object_get_qdata (G_OBJECT (widget), quark_aux_info);
|
||||||
if (!aux_info && create)
|
if (!aux_info && create)
|
||||||
{
|
{
|
||||||
aux_info = g_slice_new (GtkWidgetAuxInfo);
|
aux_info = g_slice_new0 (GtkWidgetAuxInfo);
|
||||||
|
|
||||||
aux_info->width = -1;
|
aux_info->width = -1;
|
||||||
aux_info->height = -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);
|
g_object_set_qdata (G_OBJECT (widget), quark_aux_info, aux_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return aux_info;
|
return aux_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************
|
/*****************************************
|
||||||
* gtk_widget_aux_info_destroy:
|
* gtk_widget_aux_info_destroy:
|
||||||
*
|
*
|
||||||
@ -10768,6 +10789,66 @@ 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:
|
* gtk_widget_get_clipboard:
|
||||||
|
@ -482,6 +482,7 @@ typedef struct _GtkClipboard GtkClipboard;
|
|||||||
typedef struct _GtkTooltip GtkTooltip;
|
typedef struct _GtkTooltip GtkTooltip;
|
||||||
typedef struct _GtkWindow GtkWindow;
|
typedef struct _GtkWindow GtkWindow;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkAllocation:
|
* GtkAllocation:
|
||||||
* @x: the X position of the widget's area relative to its parents allocation.
|
* @x: the X position of the widget's area relative to its parents allocation.
|
||||||
@ -817,6 +818,7 @@ struct _GtkWidgetAuxInfo
|
|||||||
gint y;
|
gint y;
|
||||||
gint width;
|
gint width;
|
||||||
gint height;
|
gint height;
|
||||||
|
|
||||||
guint x_set : 1;
|
guint x_set : 1;
|
||||||
guint y_set : 1;
|
guint y_set : 1;
|
||||||
};
|
};
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
#include "gtkplug.h"
|
#include "gtkplug.h"
|
||||||
#include "gtkbuildable.h"
|
#include "gtkbuildable.h"
|
||||||
|
#include "gtkextendedlayout.h"
|
||||||
#include "gtkalias.h"
|
#include "gtkalias.h"
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
#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_unmap (GtkWidget *widget);
|
||||||
static void gtk_window_realize (GtkWidget *widget);
|
static void gtk_window_realize (GtkWidget *widget);
|
||||||
static void gtk_window_unrealize (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,
|
static void gtk_window_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation);
|
GtkAllocation *allocation);
|
||||||
static gint gtk_window_event (GtkWidget *widget,
|
static gint gtk_window_event (GtkWidget *widget,
|
||||||
@ -350,9 +349,19 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
|
|||||||
gpointer user_data);
|
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_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
|
||||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
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
|
static void
|
||||||
add_tab_bindings (GtkBindingSet *binding_set,
|
add_tab_bindings (GtkBindingSet *binding_set,
|
||||||
@ -451,7 +460,6 @@ gtk_window_class_init (GtkWindowClass *klass)
|
|||||||
widget_class->unmap = gtk_window_unmap;
|
widget_class->unmap = gtk_window_unmap;
|
||||||
widget_class->realize = gtk_window_realize;
|
widget_class->realize = gtk_window_realize;
|
||||||
widget_class->unrealize = gtk_window_unrealize;
|
widget_class->unrealize = gtk_window_unrealize;
|
||||||
widget_class->size_request = gtk_window_size_request;
|
|
||||||
widget_class->size_allocate = gtk_window_size_allocate;
|
widget_class->size_allocate = gtk_window_size_allocate;
|
||||||
widget_class->configure_event = gtk_window_configure_event;
|
widget_class->configure_event = gtk_window_configure_event;
|
||||||
widget_class->key_press_event = gtk_window_key_press_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);
|
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
|
static void
|
||||||
gtk_window_size_allocate (GtkWidget *widget,
|
gtk_window_size_allocate (GtkWidget *widget,
|
||||||
GtkAllocation *allocation)
|
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:
|
* _gtk_window_unset_focus_and_default:
|
||||||
* @window: a #GtkWindow
|
* @window: a #GtkWindow
|
||||||
|
@ -29,6 +29,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
|||||||
simple \
|
simple \
|
||||||
flicker \
|
flicker \
|
||||||
print-editor \
|
print-editor \
|
||||||
|
extendedlayoutexample \
|
||||||
testaccel \
|
testaccel \
|
||||||
testassistant \
|
testassistant \
|
||||||
testbbox \
|
testbbox \
|
||||||
@ -112,6 +113,7 @@ endif
|
|||||||
flicker_DEPENDENCIES = $(TEST_DEPS)
|
flicker_DEPENDENCIES = $(TEST_DEPS)
|
||||||
simple_DEPENDENCIES = $(TEST_DEPS)
|
simple_DEPENDENCIES = $(TEST_DEPS)
|
||||||
print_editor_DEPENDENCIES = $(TEST_DEPS)
|
print_editor_DEPENDENCIES = $(TEST_DEPS)
|
||||||
|
extendedlayoutexample_DEPENDENCIES = $(TEST_DEPS)
|
||||||
testicontheme_DEPENDENCIES = $(TEST_DEPS)
|
testicontheme_DEPENDENCIES = $(TEST_DEPS)
|
||||||
testiconview_DEPENDENCIES = $(TEST_DEPS)
|
testiconview_DEPENDENCIES = $(TEST_DEPS)
|
||||||
testaccel_DEPENDENCIES = $(TEST_DEPS)
|
testaccel_DEPENDENCIES = $(TEST_DEPS)
|
||||||
@ -176,6 +178,7 @@ testwindows_DEPENDENCIES = $(TEST_DEPS)
|
|||||||
flicker_LDADD = $(LDADDS)
|
flicker_LDADD = $(LDADDS)
|
||||||
simple_LDADD = $(LDADDS)
|
simple_LDADD = $(LDADDS)
|
||||||
print_editor_LDADD = $(LDADDS)
|
print_editor_LDADD = $(LDADDS)
|
||||||
|
extendedlayoutexample_LDADD = $(LDADDS)
|
||||||
testaccel_LDADD = $(LDADDS)
|
testaccel_LDADD = $(LDADDS)
|
||||||
testassistant_LDADD = $(LDADDS)
|
testassistant_LDADD = $(LDADDS)
|
||||||
testbbox_LDADD = $(LDADDS)
|
testbbox_LDADD = $(LDADDS)
|
||||||
|
614
tests/extendedlayoutexample.c
Normal file
614
tests/extendedlayoutexample.c
Normal 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;
|
||||||
|
}
|
@ -25,6 +25,21 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#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
|
static void
|
||||||
combo_changed_cb (GtkWidget *combo,
|
combo_changed_cb (GtkWidget *combo,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@ -33,33 +48,123 @@ combo_changed_cb (GtkWidget *combo,
|
|||||||
gint active;
|
gint active;
|
||||||
|
|
||||||
active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
|
active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
|
||||||
|
|
||||||
gtk_label_set_ellipsize (GTK_LABEL (label), (PangoEllipsizeMode)active);
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
GtkWidget *window, *vbox, *hbox, *label, *combo;
|
GtkWidget *window, *vbox, *label;
|
||||||
|
GtkWidget *combo, *scale, *align, *ebox;
|
||||||
|
|
||||||
gtk_init (&argc, &argv);
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
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);
|
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);
|
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 ();
|
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), "NONE");
|
||||||
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "START");
|
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), "MIDDLE");
|
||||||
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
|
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
|
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 (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);
|
gtk_widget_show_all (window);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user