native-layout: Introduce GtkExtendedLayout interface.
This commit is contained in:
		
				
					committed by
					
						
						Johannes Schmid
					
				
			
			
				
	
			
			
			
						parent
						
							a8ec02c930
						
					
				
				
					commit
					e08d04b561
				
			@ -202,6 +202,7 @@ gtk_public_h_sources =          \
 | 
			
		||||
	gtkenums.h		\
 | 
			
		||||
	gtkeventbox.h		\
 | 
			
		||||
	gtkexpander.h		\
 | 
			
		||||
	gtkextendedlayout.h	\
 | 
			
		||||
	gtkfilechooser.h        \
 | 
			
		||||
	gtkfilechooserbutton.h  \
 | 
			
		||||
	gtkfilechooserdialog.h  \
 | 
			
		||||
@ -455,6 +456,7 @@ gtk_base_c_sources =            \
 | 
			
		||||
	gtkentrycompletion.c	\
 | 
			
		||||
	gtkeventbox.c		\
 | 
			
		||||
	gtkexpander.c		\
 | 
			
		||||
	gtkextendedlayout.c	\
 | 
			
		||||
	gtkfilechooser.c	\
 | 
			
		||||
	gtkfilechooserbutton.c	\
 | 
			
		||||
	gtkfilechooserdefault.c	\
 | 
			
		||||
 | 
			
		||||
@ -83,6 +83,7 @@
 | 
			
		||||
#include <gtk/gtkenums.h>
 | 
			
		||||
#include <gtk/gtkeventbox.h>
 | 
			
		||||
#include <gtk/gtkexpander.h>
 | 
			
		||||
#include <gtk/gtkextendedlayout.h>
 | 
			
		||||
#include <gtk/gtkfixed.h>
 | 
			
		||||
#include <gtk/gtkfilechooser.h>
 | 
			
		||||
#include <gtk/gtkfilechooserbutton.h>
 | 
			
		||||
 | 
			
		||||
@ -1500,6 +1500,24 @@ gtk_expander_set_use_underline
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IN_HEADER(__GTK_EXTENDED_LAYOUT_H__)
 | 
			
		||||
#if IN_FILE(__GTK_EXTENDED_LAYOUT_C__)
 | 
			
		||||
gtk_extended_layout_get_type G_GNUC_CONST
 | 
			
		||||
gtk_extended_layout_get_desired_size
 | 
			
		||||
gtk_extended_layout_get_height_for_width
 | 
			
		||||
gtk_extended_layout_get_width_for_height
 | 
			
		||||
#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_size
 | 
			
		||||
gtk_extended_layout_get_height_for_width
 | 
			
		||||
gtk_extended_layout_get_width_for_height
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if IN_HEADER(__GTK_FILE_CHOOSER_H__)
 | 
			
		||||
#if IN_FILE(__GTK_FILE_CHOOSER_C__)
 | 
			
		||||
gtk_file_chooser_add_filter
 | 
			
		||||
@ -2248,6 +2266,7 @@ gtk_label_get_type G_GNUC_CONST
 | 
			
		||||
gtk_label_get_use_markup
 | 
			
		||||
gtk_label_get_use_underline
 | 
			
		||||
gtk_label_get_width_chars
 | 
			
		||||
gtk_label_get_full_size
 | 
			
		||||
gtk_label_new
 | 
			
		||||
gtk_label_new_with_mnemonic
 | 
			
		||||
gtk_label_select_region
 | 
			
		||||
@ -2271,6 +2290,7 @@ gtk_label_set_use_markup
 | 
			
		||||
gtk_label_set_use_underline
 | 
			
		||||
gtk_label_set_width_chars
 | 
			
		||||
gtk_label_get_current_uri
 | 
			
		||||
gtk_label_set_full_size
 | 
			
		||||
gtk_label_set_track_visited_links
 | 
			
		||||
gtk_label_get_track_visited_links
 | 
			
		||||
#endif
 | 
			
		||||
@ -5200,6 +5220,9 @@ gtk_widget_show_all
 | 
			
		||||
gtk_widget_show_now
 | 
			
		||||
gtk_widget_size_allocate
 | 
			
		||||
gtk_widget_size_request
 | 
			
		||||
gtk_widget_get_desired_size
 | 
			
		||||
gtk_widget_get_height_for_width
 | 
			
		||||
gtk_widget_get_width_for_height
 | 
			
		||||
gtk_widget_style_get G_GNUC_NULL_TERMINATED
 | 
			
		||||
gtk_widget_style_get_property
 | 
			
		||||
gtk_widget_style_get_valist
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "gtkalignment.h"
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkprivate.h"
 | 
			
		||||
#include "gtkintl.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
@ -458,7 +459,9 @@ gtk_alignment_size_allocate (GtkWidget     *widget,
 | 
			
		||||
  
 | 
			
		||||
  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
 | 
			
		||||
    {
 | 
			
		||||
      gtk_widget_get_child_requisition (bin->child, &child_requisition);
 | 
			
		||||
      GtkExtendedLayout *layout = GTK_EXTENDED_LAYOUT (bin->child);
 | 
			
		||||
 | 
			
		||||
      gtk_extended_layout_get_desired_size (layout, NULL, &child_requisition);
 | 
			
		||||
 | 
			
		||||
      border_width = GTK_CONTAINER (alignment)->border_width;
 | 
			
		||||
 | 
			
		||||
@ -469,6 +472,13 @@ gtk_alignment_size_allocate (GtkWidget     *widget,
 | 
			
		||||
      width  = MAX (1, allocation->width - padding_horizontal - 2 * border_width);
 | 
			
		||||
      height = MAX (1, allocation->height - padding_vertical - 2 * border_width);
 | 
			
		||||
 | 
			
		||||
      if (child_requisition.width > width)
 | 
			
		||||
        gtk_extended_layout_get_height_for_width (layout, width, NULL,
 | 
			
		||||
                                                  &child_requisition.height);
 | 
			
		||||
      else if (child_requisition.height > height)
 | 
			
		||||
        gtk_extended_layout_get_width_for_height (layout, height, NULL,
 | 
			
		||||
                                                  &child_requisition.width);
 | 
			
		||||
 | 
			
		||||
      if (width > child_requisition.width)
 | 
			
		||||
	child_allocation.width = (child_requisition.width *
 | 
			
		||||
				  (1.0 - alignment->xscale) +
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										629
									
								
								gtk/gtkbox.c
									
									
									
									
									
								
							
							
						
						
									
										629
									
								
								gtk/gtkbox.c
									
									
									
									
									
								
							@ -28,6 +28,7 @@
 | 
			
		||||
 | 
			
		||||
#include "gtkbox.h"
 | 
			
		||||
#include "gtkorientable.h"
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkprivate.h"
 | 
			
		||||
#include "gtkintl.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
@ -60,6 +61,27 @@ struct _GtkBoxPrivate
 | 
			
		||||
 | 
			
		||||
#define GTK_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_BOX, GtkBoxPrivate))
 | 
			
		||||
 | 
			
		||||
typedef struct _GtkBoxDesiredSizes GtkBoxDesiredSizes;
 | 
			
		||||
typedef struct _GtkBoxSpreading    GtkBoxSpreading;
 | 
			
		||||
 | 
			
		||||
struct _GtkBoxDesiredSizes
 | 
			
		||||
{
 | 
			
		||||
  gint minimum_size;
 | 
			
		||||
  gint natural_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _GtkBoxSpreading
 | 
			
		||||
{
 | 
			
		||||
  GtkBoxChild *child;
 | 
			
		||||
  gint index;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void gtk_box_get_desired_size      (GtkExtendedLayout      *layout,
 | 
			
		||||
                                           GtkRequisition         *minimum_size,
 | 
			
		||||
                                           GtkRequisition         *natural_size);
 | 
			
		||||
static void gtk_box_size_allocate         (GtkWidget              *widget,
 | 
			
		||||
                                           GtkAllocation          *allocation);
 | 
			
		||||
static void gtk_box_layout_interface_init (GtkExtendedLayoutIface *iface);
 | 
			
		||||
 | 
			
		||||
static void gtk_box_set_property       (GObject        *object,
 | 
			
		||||
                                        guint           prop_id,
 | 
			
		||||
@ -70,11 +92,6 @@ static void gtk_box_get_property       (GObject        *object,
 | 
			
		||||
                                        GValue         *value,
 | 
			
		||||
                                        GParamSpec     *pspec);
 | 
			
		||||
 | 
			
		||||
static void gtk_box_size_request       (GtkWidget      *widget,
 | 
			
		||||
                                        GtkRequisition *requisition);
 | 
			
		||||
static void gtk_box_size_allocate      (GtkWidget      *widget,
 | 
			
		||||
                                        GtkAllocation  *allocation);
 | 
			
		||||
 | 
			
		||||
static void gtk_box_add                (GtkContainer   *container,
 | 
			
		||||
                                        GtkWidget      *widget);
 | 
			
		||||
static void gtk_box_remove             (GtkContainer   *container,
 | 
			
		||||
@ -98,7 +115,9 @@ static GType gtk_box_child_type        (GtkContainer   *container);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER,
 | 
			
		||||
                                  G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
 | 
			
		||||
                                                         NULL));
 | 
			
		||||
                                                         NULL)
 | 
			
		||||
                                  G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
 | 
			
		||||
                                                         gtk_box_layout_interface_init));
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_box_class_init (GtkBoxClass *class)
 | 
			
		||||
@ -110,7 +129,6 @@ gtk_box_class_init (GtkBoxClass *class)
 | 
			
		||||
  object_class->set_property = gtk_box_set_property;
 | 
			
		||||
  object_class->get_property = gtk_box_get_property;
 | 
			
		||||
 | 
			
		||||
  widget_class->size_request = gtk_box_size_request;
 | 
			
		||||
  widget_class->size_allocate = gtk_box_size_allocate;
 | 
			
		||||
 | 
			
		||||
  container_class->add = gtk_box_add;
 | 
			
		||||
@ -181,6 +199,12 @@ gtk_box_class_init (GtkBoxClass *class)
 | 
			
		||||
  g_type_class_add_private (object_class, sizeof (GtkBoxPrivate));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_box_layout_interface_init (GtkExtendedLayoutIface *iface)
 | 
			
		||||
{
 | 
			
		||||
  iface->get_desired_size = gtk_box_get_desired_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_box_init (GtkBox *box)
 | 
			
		||||
{
 | 
			
		||||
@ -252,78 +276,143 @@ gtk_box_get_property (GObject    *object,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_box_size_request (GtkWidget      *widget,
 | 
			
		||||
                      GtkRequisition *requisition)
 | 
			
		||||
gtk_box_get_desired_size (GtkExtendedLayout *layout,
 | 
			
		||||
                          GtkRequisition    *minimum_size,
 | 
			
		||||
                          GtkRequisition    *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GtkBox *box = GTK_BOX (widget);
 | 
			
		||||
  GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (box);
 | 
			
		||||
  GtkBoxChild *child;
 | 
			
		||||
  GtkBox *box;
 | 
			
		||||
  GtkBoxPrivate *private;
 | 
			
		||||
  GList *children;
 | 
			
		||||
  gint nvis_children;
 | 
			
		||||
  gint width;
 | 
			
		||||
  gint height;
 | 
			
		||||
  gint border_width;
 | 
			
		||||
 | 
			
		||||
  box = GTK_BOX (layout);
 | 
			
		||||
  private = GTK_BOX_GET_PRIVATE (box);
 | 
			
		||||
  border_width = GTK_CONTAINER (box)->border_width;
 | 
			
		||||
 | 
			
		||||
  minimum_size->width = minimum_size->height = 0;
 | 
			
		||||
  natural_size->width = natural_size->height = 0;
 | 
			
		||||
 | 
			
		||||
  requisition->width = 0;
 | 
			
		||||
  requisition->height = 0;
 | 
			
		||||
  nvis_children = 0;
 | 
			
		||||
 | 
			
		||||
  children = box->children;
 | 
			
		||||
  while (children)
 | 
			
		||||
    {
 | 
			
		||||
      GtkBoxChild *child;
 | 
			
		||||
 | 
			
		||||
      child = children->data;
 | 
			
		||||
      children = children->next;
 | 
			
		||||
 | 
			
		||||
      if (GTK_WIDGET_VISIBLE (child->widget))
 | 
			
		||||
	{
 | 
			
		||||
	  GtkRequisition child_requisition;
 | 
			
		||||
        {
 | 
			
		||||
          GtkRequisition child_minimum_size;
 | 
			
		||||
          GtkRequisition child_natural_size;
 | 
			
		||||
 | 
			
		||||
	  gtk_widget_size_request (child->widget, &child_requisition);
 | 
			
		||||
 | 
			
		||||
	  if (box->homogeneous)
 | 
			
		||||
	    {
 | 
			
		||||
	      width = child_requisition.width + child->padding * 2;
 | 
			
		||||
	      height = child_requisition.height + child->padding * 2;
 | 
			
		||||
 | 
			
		||||
              if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                requisition->width = MAX (requisition->width, width);
 | 
			
		||||
              else
 | 
			
		||||
                requisition->height = MAX (requisition->height, height);
 | 
			
		||||
	    }
 | 
			
		||||
	  else
 | 
			
		||||
	    {
 | 
			
		||||
              if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                requisition->width += child_requisition.width + child->padding * 2;
 | 
			
		||||
              else
 | 
			
		||||
                requisition->height += child_requisition.height + child->padding * 2;
 | 
			
		||||
	    }
 | 
			
		||||
          gtk_widget_get_desired_size (child->widget,
 | 
			
		||||
                                       &child_minimum_size,
 | 
			
		||||
                                       &child_natural_size);
 | 
			
		||||
 | 
			
		||||
          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
            requisition->height = MAX (requisition->height, child_requisition.height);
 | 
			
		||||
            {
 | 
			
		||||
              if (box->homogeneous)
 | 
			
		||||
                {
 | 
			
		||||
                  gint width;
 | 
			
		||||
 | 
			
		||||
                  width = child_minimum_size.width + child->padding * 2;
 | 
			
		||||
                  minimum_size->width = MAX (minimum_size->width, width);
 | 
			
		||||
 | 
			
		||||
                  width = child_natural_size.width + child->padding * 2;
 | 
			
		||||
                  natural_size->width = MAX (natural_size->width, width);
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
                  minimum_size->width += child_minimum_size.width + child->padding * 2;
 | 
			
		||||
                  natural_size->width += child_natural_size.width + child->padding * 2;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              minimum_size->height = MAX (minimum_size->height, child_minimum_size.height);
 | 
			
		||||
              natural_size->height = MAX (natural_size->height, child_natural_size.height);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            requisition->width = MAX (requisition->width, child_requisition.width);
 | 
			
		||||
            {
 | 
			
		||||
              if (box->homogeneous)
 | 
			
		||||
                {
 | 
			
		||||
                  gint height;
 | 
			
		||||
 | 
			
		||||
	  nvis_children += 1;
 | 
			
		||||
	}
 | 
			
		||||
                  height = child_minimum_size.height + child->padding * 2;
 | 
			
		||||
                  minimum_size->height = MAX (minimum_size->height, height);
 | 
			
		||||
 | 
			
		||||
                  height = child_natural_size.height + child->padding * 2;
 | 
			
		||||
                  natural_size->height = MAX (natural_size->height, height);
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
                  minimum_size->height += child_minimum_size.height + child->padding * 2;
 | 
			
		||||
                  natural_size->height += child_natural_size.height + child->padding * 2;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              minimum_size->width = MAX (minimum_size->width, child_minimum_size.width);
 | 
			
		||||
              natural_size->width = MAX (natural_size->width, child_natural_size.width);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
          nvis_children += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (nvis_children > 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (box->homogeneous)
 | 
			
		||||
        {
 | 
			
		||||
          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
            requisition->width *= nvis_children;
 | 
			
		||||
          else
 | 
			
		||||
            requisition->height *= nvis_children;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
        requisition->width += (nvis_children - 1) * box->spacing;
 | 
			
		||||
        {
 | 
			
		||||
          if (box->homogeneous)
 | 
			
		||||
            {
 | 
			
		||||
             minimum_size->width *= nvis_children;
 | 
			
		||||
             natural_size->width *= nvis_children;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          minimum_size->width += (nvis_children - 1) * box->spacing;
 | 
			
		||||
          natural_size->width += (nvis_children - 1) * box->spacing;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        requisition->height += (nvis_children - 1) * box->spacing;
 | 
			
		||||
        {
 | 
			
		||||
          if (box->homogeneous)
 | 
			
		||||
            {
 | 
			
		||||
             minimum_size->height *= nvis_children;
 | 
			
		||||
             natural_size->height *= nvis_children;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          minimum_size->height += (nvis_children - 1) * box->spacing;
 | 
			
		||||
          natural_size->height += (nvis_children - 1) * box->spacing;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  requisition->width += GTK_CONTAINER (box)->border_width * 2;
 | 
			
		||||
  requisition->height += GTK_CONTAINER (box)->border_width * 2;
 | 
			
		||||
  minimum_size->width += border_width * 2;
 | 
			
		||||
  minimum_size->height += border_width * 2;
 | 
			
		||||
 | 
			
		||||
  natural_size->width += border_width * 2;
 | 
			
		||||
  natural_size->height += border_width * 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
gtk_box_compare_gap (gconstpointer p1,
 | 
			
		||||
                      gconstpointer p2,
 | 
			
		||||
                      gpointer      data)
 | 
			
		||||
{
 | 
			
		||||
  GtkBoxDesiredSizes *sizes = data;
 | 
			
		||||
  const GtkBoxSpreading *c1 = p1;
 | 
			
		||||
  const GtkBoxSpreading *c2 = p2;
 | 
			
		||||
 | 
			
		||||
  const gint d1 = MAX (sizes[c1->index].natural_size -
 | 
			
		||||
                       sizes[c1->index].minimum_size,
 | 
			
		||||
                       0);
 | 
			
		||||
  const gint d2 = MAX (sizes[c2->index].natural_size -
 | 
			
		||||
                       sizes[c2->index].minimum_size,
 | 
			
		||||
                       0);
 | 
			
		||||
 | 
			
		||||
  gint delta = (d2 - d1);
 | 
			
		||||
 | 
			
		||||
  if (0 == delta)
 | 
			
		||||
    delta = (c2->index - c1->index);
 | 
			
		||||
 | 
			
		||||
  return delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -334,21 +423,13 @@ gtk_box_size_allocate (GtkWidget     *widget,
 | 
			
		||||
  GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (box);
 | 
			
		||||
  GtkBoxChild *child;
 | 
			
		||||
  GList *children;
 | 
			
		||||
  GtkAllocation child_allocation;
 | 
			
		||||
  gint nvis_children = 0;
 | 
			
		||||
  gint nexpand_children = 0;
 | 
			
		||||
  gint child_width = 0;
 | 
			
		||||
  gint child_height = 0;
 | 
			
		||||
  gint width = 0;
 | 
			
		||||
  gint height = 0;
 | 
			
		||||
  gint extra = 0;
 | 
			
		||||
  gint x = 0;
 | 
			
		||||
  gint y = 0;
 | 
			
		||||
  GtkTextDirection direction;
 | 
			
		||||
  gint nvis_children;
 | 
			
		||||
  gint nexpand_children;
 | 
			
		||||
 | 
			
		||||
  widget->allocation = *allocation;
 | 
			
		||||
 | 
			
		||||
  direction = gtk_widget_get_direction (widget);
 | 
			
		||||
  nvis_children = 0;
 | 
			
		||||
  nexpand_children = 0;
 | 
			
		||||
 | 
			
		||||
  for (children = box->children; children; children = children->next)
 | 
			
		||||
    {
 | 
			
		||||
@ -364,239 +445,221 @@ gtk_box_size_allocate (GtkWidget     *widget,
 | 
			
		||||
 | 
			
		||||
  if (nvis_children > 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (box->homogeneous)
 | 
			
		||||
	{
 | 
			
		||||
          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
            {
 | 
			
		||||
              width = (allocation->width -
 | 
			
		||||
                       GTK_CONTAINER (box)->border_width * 2 -
 | 
			
		||||
                       (nvis_children - 1) * box->spacing);
 | 
			
		||||
              extra = width / nvis_children;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              height = (allocation->height -
 | 
			
		||||
                        GTK_CONTAINER (box)->border_width * 2 -
 | 
			
		||||
                        (nvis_children - 1) * box->spacing);
 | 
			
		||||
              extra = height / nvis_children;
 | 
			
		||||
            }
 | 
			
		||||
	}
 | 
			
		||||
      else if (nexpand_children > 0)
 | 
			
		||||
	{
 | 
			
		||||
          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
            {
 | 
			
		||||
              width = (gint) allocation->width - (gint) widget->requisition.width;
 | 
			
		||||
              extra = width / nexpand_children;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              height = (gint) allocation->height - (gint) widget->requisition.height;
 | 
			
		||||
              extra = height / nexpand_children;
 | 
			
		||||
            }
 | 
			
		||||
	}
 | 
			
		||||
      gint border_width = GTK_CONTAINER (box)->border_width;
 | 
			
		||||
      GtkTextDirection direction = gtk_widget_get_direction (widget);
 | 
			
		||||
      GtkAllocation child_allocation;
 | 
			
		||||
 | 
			
		||||
      GtkBoxSpreading *spreading = g_newa (GtkBoxSpreading, nvis_children);
 | 
			
		||||
      GtkBoxDesiredSizes *sizes = g_newa (GtkBoxDesiredSizes, nvis_children);
 | 
			
		||||
 | 
			
		||||
      GtkPackType packing;
 | 
			
		||||
 | 
			
		||||
      gint size;
 | 
			
		||||
      gint extra;
 | 
			
		||||
      gint x, y, i;
 | 
			
		||||
      gint child_size;
 | 
			
		||||
 | 
			
		||||
      if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
        {
 | 
			
		||||
          x = allocation->x + GTK_CONTAINER (box)->border_width;
 | 
			
		||||
          child_allocation.y = allocation->y + GTK_CONTAINER (box)->border_width;
 | 
			
		||||
          child_allocation.height = MAX (1, (gint) allocation->height - (gint) GTK_CONTAINER (box)->border_width * 2);
 | 
			
		||||
        size = allocation->width - border_width * 2 - (nvis_children - 1) * box->spacing;
 | 
			
		||||
      else
 | 
			
		||||
        size = allocation->height - border_width * 2 - (nvis_children - 1) * box->spacing;
 | 
			
		||||
 | 
			
		||||
      if (box->homogeneous)
 | 
			
		||||
	{
 | 
			
		||||
          extra = size / nvis_children;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          y = allocation->y + GTK_CONTAINER (box)->border_width;
 | 
			
		||||
          child_allocation.x = allocation->x + GTK_CONTAINER (box)->border_width;
 | 
			
		||||
          child_allocation.width = MAX (1, (gint) allocation->width - (gint) GTK_CONTAINER (box)->border_width * 2);
 | 
			
		||||
	{
 | 
			
		||||
          /* Retrieve desired size for visible children */
 | 
			
		||||
 | 
			
		||||
          i = 0;
 | 
			
		||||
          children = box->children;
 | 
			
		||||
          while (children)
 | 
			
		||||
            {
 | 
			
		||||
              child = children->data;
 | 
			
		||||
              children = children->next;
 | 
			
		||||
 | 
			
		||||
              if (GTK_WIDGET_VISIBLE (child->widget))
 | 
			
		||||
                {
 | 
			
		||||
                  if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                    gtk_widget_get_width_for_height (child->widget,
 | 
			
		||||
                                                     allocation->height,
 | 
			
		||||
                                                     &sizes[i].minimum_size,
 | 
			
		||||
                                                     &sizes[i].natural_size);
 | 
			
		||||
                  else
 | 
			
		||||
                    gtk_widget_get_height_for_width (child->widget,
 | 
			
		||||
                                                     allocation->width,
 | 
			
		||||
                                                     &sizes[i].minimum_size,
 | 
			
		||||
                                                     &sizes[i].natural_size);
 | 
			
		||||
 | 
			
		||||
                  size -= sizes[i].minimum_size;
 | 
			
		||||
 | 
			
		||||
                  spreading[i].index = i;
 | 
			
		||||
                  spreading[i].child = child;
 | 
			
		||||
 | 
			
		||||
                  i += 1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          /* Distribute the container's extra space c_gap. We want to assign
 | 
			
		||||
           * this space such that the sum of extra space assigned to children
 | 
			
		||||
           * (c^i_gap) is equal to c_cap. The case that there's not enough
 | 
			
		||||
           * space for all children to take their natural size needs some
 | 
			
		||||
           * attention. The goals we want to achieve are:
 | 
			
		||||
           *
 | 
			
		||||
           *   a) Maximize number of children taking their natural size.
 | 
			
		||||
           *   b) The allocated size of children should be a continuous
 | 
			
		||||
           *   function of c_gap.  That is, increasing the container size by
 | 
			
		||||
           *   one pixel should never make drastic changes in the distribution.
 | 
			
		||||
           *   c) If child i takes its natural size and child j doesn't,
 | 
			
		||||
           *   child j should have received at least as much gap as child i.
 | 
			
		||||
           *
 | 
			
		||||
           * The following code distributes the additional space by following
 | 
			
		||||
           * this rules.
 | 
			
		||||
           */
 | 
			
		||||
 | 
			
		||||
          /* Sort descending by gap and position. */
 | 
			
		||||
 | 
			
		||||
          g_qsort_with_data (spreading,
 | 
			
		||||
                             nvis_children, sizeof (GtkBoxSpreading),
 | 
			
		||||
                             gtk_box_compare_gap, sizes);
 | 
			
		||||
 | 
			
		||||
          /* Distribute available space.
 | 
			
		||||
           * This master piece of a loop was conceived by Behdad Esfahbod.
 | 
			
		||||
           */
 | 
			
		||||
          for (i = nvis_children - 1; i >= 0; --i)
 | 
			
		||||
            {
 | 
			
		||||
              /* Divide remaining space by number of remaining children.
 | 
			
		||||
               * Sort order and reducing remaining space by assigned space
 | 
			
		||||
               * ensures that space is distributed equally.
 | 
			
		||||
               */
 | 
			
		||||
              gint glue = (size + i) / (i + 1);
 | 
			
		||||
              gint gap = sizes[spreading[i].index].natural_size
 | 
			
		||||
                       - sizes[spreading[i].index].minimum_size;
 | 
			
		||||
 | 
			
		||||
              extra = MIN (glue, gap);
 | 
			
		||||
              sizes[spreading[i].index].minimum_size += extra;
 | 
			
		||||
 | 
			
		||||
              size -= extra;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          /* Calculate space which hasn't distributed yet,
 | 
			
		||||
           * and is available for expanding children.
 | 
			
		||||
           */
 | 
			
		||||
          if (nexpand_children > 0)
 | 
			
		||||
            extra = size / nexpand_children;
 | 
			
		||||
          else
 | 
			
		||||
            extra = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      children = box->children;
 | 
			
		||||
      while (children)
 | 
			
		||||
	{
 | 
			
		||||
	  child = children->data;
 | 
			
		||||
	  children = children->next;
 | 
			
		||||
      /* Allocate child positions. */
 | 
			
		||||
 | 
			
		||||
	  if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
 | 
			
		||||
	    {
 | 
			
		||||
	      if (box->homogeneous)
 | 
			
		||||
		{
 | 
			
		||||
		  if (nvis_children == 1)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_width = width;
 | 
			
		||||
                      child_height = height;
 | 
			
		||||
                    }
 | 
			
		||||
		  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_width = extra;
 | 
			
		||||
                      child_height = extra;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
		  nvis_children -= 1;
 | 
			
		||||
		  width -= extra;
 | 
			
		||||
                  height -= extra;
 | 
			
		||||
		}
 | 
			
		||||
	      else
 | 
			
		||||
		{
 | 
			
		||||
		  GtkRequisition child_requisition;
 | 
			
		||||
 | 
			
		||||
		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
 | 
			
		||||
 | 
			
		||||
		  child_width = child_requisition.width + child->padding * 2;
 | 
			
		||||
		  child_height = child_requisition.height + child->padding * 2;
 | 
			
		||||
 | 
			
		||||
		  if (child->expand)
 | 
			
		||||
		    {
 | 
			
		||||
		      if (nexpand_children == 1)
 | 
			
		||||
                        {
 | 
			
		||||
                          child_width += width;
 | 
			
		||||
                          child_height += height;
 | 
			
		||||
                        }
 | 
			
		||||
		      else
 | 
			
		||||
                        {
 | 
			
		||||
                          child_width += extra;
 | 
			
		||||
                          child_height += extra;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
		      nexpand_children -= 1;
 | 
			
		||||
		      width -= extra;
 | 
			
		||||
                      height -= extra;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	      if (child->fill)
 | 
			
		||||
		{
 | 
			
		||||
                  if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
 | 
			
		||||
                      child_allocation.x = x + child->padding;
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
 | 
			
		||||
                      child_allocation.y = y + child->padding;
 | 
			
		||||
                    }
 | 
			
		||||
		}
 | 
			
		||||
	      else
 | 
			
		||||
		{
 | 
			
		||||
		  GtkRequisition child_requisition;
 | 
			
		||||
 | 
			
		||||
		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
 | 
			
		||||
                  if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.width = child_requisition.width;
 | 
			
		||||
                      child_allocation.x = x + (child_width - child_allocation.width) / 2;
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.height = child_requisition.height;
 | 
			
		||||
                      child_allocation.y = y + (child_height - child_allocation.height) / 2;
 | 
			
		||||
                    }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	      if (direction == GTK_TEXT_DIR_RTL &&
 | 
			
		||||
                  private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                {
 | 
			
		||||
                  child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
	      gtk_widget_size_allocate (child->widget, &child_allocation);
 | 
			
		||||
 | 
			
		||||
	      x += child_width + box->spacing;
 | 
			
		||||
	      y += child_height + box->spacing;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      x = allocation->x + allocation->width - GTK_CONTAINER (box)->border_width;
 | 
			
		||||
      y = allocation->y + allocation->height - GTK_CONTAINER (box)->border_width;
 | 
			
		||||
 | 
			
		||||
      children = box->children;
 | 
			
		||||
      while (children)
 | 
			
		||||
	{
 | 
			
		||||
	  child = children->data;
 | 
			
		||||
	  children = children->next;
 | 
			
		||||
 | 
			
		||||
	  if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
 | 
			
		||||
	    {
 | 
			
		||||
	      GtkRequisition child_requisition;
 | 
			
		||||
 | 
			
		||||
	      gtk_widget_get_child_requisition (child->widget, &child_requisition);
 | 
			
		||||
 | 
			
		||||
              if (box->homogeneous)
 | 
			
		||||
                {
 | 
			
		||||
                  if (nvis_children == 1)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_width = width;
 | 
			
		||||
                      child_height = height;
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_width = extra;
 | 
			
		||||
                      child_height = extra;
 | 
			
		||||
                   }
 | 
			
		||||
 | 
			
		||||
                  nvis_children -= 1;
 | 
			
		||||
                  width -= extra;
 | 
			
		||||
                  height -= extra;
 | 
			
		||||
                }
 | 
			
		||||
      for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
 | 
			
		||||
        {
 | 
			
		||||
          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
            {
 | 
			
		||||
              child_allocation.y = allocation->y + border_width;
 | 
			
		||||
              child_allocation.height = MAX (1, allocation->height - border_width * 2);
 | 
			
		||||
              if (packing == GTK_PACK_START)
 | 
			
		||||
                x = allocation->x + border_width;
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
		  child_width = child_requisition.width + child->padding * 2;
 | 
			
		||||
		  child_height = child_requisition.height + child->padding * 2;
 | 
			
		||||
                x = allocation->x + allocation->width - border_width;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              child_allocation.x = allocation->x + border_width;
 | 
			
		||||
              child_allocation.width = MAX (1, allocation->width - border_width * 2);
 | 
			
		||||
              if (packing == GTK_PACK_START)
 | 
			
		||||
                y = allocation->y + border_width;
 | 
			
		||||
              else
 | 
			
		||||
                y = allocation->y + allocation->height - border_width;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                  if (child->expand)
 | 
			
		||||
          i = 0;
 | 
			
		||||
          children = box->children;
 | 
			
		||||
          while (children)
 | 
			
		||||
	    {
 | 
			
		||||
	      child = children->data;
 | 
			
		||||
	      children = children->next;
 | 
			
		||||
 | 
			
		||||
	      if (GTK_WIDGET_VISIBLE (child->widget))
 | 
			
		||||
	        {
 | 
			
		||||
                  if (child->pack == packing)
 | 
			
		||||
                    {
 | 
			
		||||
                      if (nexpand_children == 1)
 | 
			
		||||
                      /* Assign the child's size. */
 | 
			
		||||
 | 
			
		||||
	              if (box->homogeneous)
 | 
			
		||||
		        {
 | 
			
		||||
		          if (nvis_children == 1)
 | 
			
		||||
                            child_size = size;
 | 
			
		||||
		          else
 | 
			
		||||
                            child_size = extra;
 | 
			
		||||
 | 
			
		||||
		          nvis_children -= 1;
 | 
			
		||||
		          size -= extra;
 | 
			
		||||
		        }
 | 
			
		||||
	              else
 | 
			
		||||
		        {
 | 
			
		||||
		          child_size = sizes[i].minimum_size + child->padding * 2;
 | 
			
		||||
 | 
			
		||||
		          if (child->expand)
 | 
			
		||||
		            {
 | 
			
		||||
		              if (nexpand_children == 1)
 | 
			
		||||
                                child_size += size;
 | 
			
		||||
		              else
 | 
			
		||||
                                child_size += extra;
 | 
			
		||||
 | 
			
		||||
		              nexpand_children -= 1;
 | 
			
		||||
		              size -= extra;
 | 
			
		||||
		            }
 | 
			
		||||
		        }
 | 
			
		||||
 | 
			
		||||
                      /* Assign the child's position. */
 | 
			
		||||
 | 
			
		||||
                      if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                        {
 | 
			
		||||
                          child_width += width;
 | 
			
		||||
                          child_height += height;
 | 
			
		||||
                         }
 | 
			
		||||
	                  if (child->fill)
 | 
			
		||||
		            {
 | 
			
		||||
                              child_allocation.width = MAX (1, child_size - child->padding * 2);
 | 
			
		||||
                              child_allocation.x = x + child->padding;
 | 
			
		||||
		            }
 | 
			
		||||
	                  else
 | 
			
		||||
		            {
 | 
			
		||||
                              child_allocation.width = sizes[i].minimum_size;
 | 
			
		||||
                              child_allocation.x = x + (child_size - child_allocation.width) / 2;
 | 
			
		||||
		            }
 | 
			
		||||
 | 
			
		||||
	                  if (direction == GTK_TEXT_DIR_RTL)
 | 
			
		||||
                            child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
 | 
			
		||||
 | 
			
		||||
                          if (packing == GTK_PACK_START)
 | 
			
		||||
	                    x += child_size + box->spacing;
 | 
			
		||||
                          else
 | 
			
		||||
	                    x -= child_size + box->spacing;
 | 
			
		||||
                        }
 | 
			
		||||
                      else
 | 
			
		||||
                        {
 | 
			
		||||
                          child_width += extra;
 | 
			
		||||
                          child_height += extra;
 | 
			
		||||
	                  if (child->fill)
 | 
			
		||||
		            {
 | 
			
		||||
                              child_allocation.height = MAX (1, child_size - child->padding * 2);
 | 
			
		||||
                              child_allocation.y = y + child->padding;
 | 
			
		||||
		            }
 | 
			
		||||
	                  else
 | 
			
		||||
		            {
 | 
			
		||||
                              child_allocation.height = sizes[i].minimum_size;
 | 
			
		||||
                              child_allocation.y = y + (child_size - child_allocation.height) / 2;
 | 
			
		||||
		            }
 | 
			
		||||
 | 
			
		||||
                         if (packing == GTK_PACK_START)
 | 
			
		||||
	                   y += child_size + box->spacing;
 | 
			
		||||
                         else
 | 
			
		||||
	                   y -= child_size + box->spacing;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                      nexpand_children -= 1;
 | 
			
		||||
                      width -= extra;
 | 
			
		||||
                      height -= extra;
 | 
			
		||||
	              gtk_widget_size_allocate (child->widget, &child_allocation);
 | 
			
		||||
                    }
 | 
			
		||||
                  i += 1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              if (child->fill)
 | 
			
		||||
                {
 | 
			
		||||
                  if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.width = MAX (1, (gint)child_width - (gint)child->padding * 2);
 | 
			
		||||
                      child_allocation.x = x + child->padding - child_width;
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
 | 
			
		||||
                      child_allocation.y = y + child->padding - child_height;
 | 
			
		||||
                     }
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
                  if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.width = child_requisition.width;
 | 
			
		||||
                      child_allocation.x = x + (child_width - child_allocation.width) / 2 - child_width;
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    {
 | 
			
		||||
                      child_allocation.height = child_requisition.height;
 | 
			
		||||
                      child_allocation.y = y + (child_height - child_allocation.height) / 2 - child_height;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
	      if (direction == GTK_TEXT_DIR_RTL &&
 | 
			
		||||
                  private->orientation == GTK_ORIENTATION_HORIZONTAL)
 | 
			
		||||
                {
 | 
			
		||||
                  child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              gtk_widget_size_allocate (child->widget, &child_allocation);
 | 
			
		||||
 | 
			
		||||
              x -= (child_width + box->spacing);
 | 
			
		||||
              y -= (child_height + box->spacing);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										146
									
								
								gtk/gtkextendedlayout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								gtk/gtkextendedlayout.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
/* gtkextendedlayout.c
 | 
			
		||||
 * Copyright (C) 2007 Openismus GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * Author:
 | 
			
		||||
 *      Mathias Hasselmann <mathias@openismus.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 <config.h>
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkintl.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
  return extended_layout_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_extended_layout_get_desired_size:
 | 
			
		||||
 * @layout: a #GtkExtendedLayout instance
 | 
			
		||||
 * @minimum_size: location for storing the minimum size, or %NULL
 | 
			
		||||
 * @natural_size: location for storing the preferred size, or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Retreives an extended layout item's desired size.
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.16
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gtk_extended_layout_get_desired_size (GtkExtendedLayout *layout,
 | 
			
		||||
                                      GtkRequisition    *minimum_size,
 | 
			
		||||
                                      GtkRequisition    *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GtkExtendedLayoutIface *iface;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
 | 
			
		||||
  g_return_if_fail (NULL != minimum_size || NULL != natural_size);
 | 
			
		||||
 | 
			
		||||
  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
 | 
			
		||||
  iface->get_desired_size (layout, minimum_size, natural_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_extended_layout_get_width_for_height:
 | 
			
		||||
 * @layout: a #GtkExtendedLayout instance
 | 
			
		||||
 * @height: the size which is available for allocation
 | 
			
		||||
 * @minimum_size: location for storing the minimum size, or %NULL
 | 
			
		||||
 * @natural_size: location for storing the preferred size, or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Retreives an extended layout item's desired width if it would given
 | 
			
		||||
 * the size specified in @height.
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.16
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
 | 
			
		||||
                                          gint               height,
 | 
			
		||||
                                          gint              *minimum_width,
 | 
			
		||||
                                          gint              *natural_width)
 | 
			
		||||
{
 | 
			
		||||
  GtkExtendedLayoutIface *iface;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
 | 
			
		||||
  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
 | 
			
		||||
 | 
			
		||||
  if (iface->get_width_for_height)
 | 
			
		||||
    iface->get_width_for_height (layout, height, minimum_width, natural_width);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkRequisition minimum_size;
 | 
			
		||||
      GtkRequisition natural_size;
 | 
			
		||||
 | 
			
		||||
      iface->get_desired_size (layout, &minimum_size, &natural_size);
 | 
			
		||||
 | 
			
		||||
      if (minimum_width)
 | 
			
		||||
        *minimum_width = minimum_size.width;
 | 
			
		||||
      if (natural_width)
 | 
			
		||||
        *natural_width = natural_size.width;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_extended_layout_get_height_for_width:
 | 
			
		||||
 * @layout: a #GtkExtendedLayout instance
 | 
			
		||||
 * @width: the size which is available for allocation
 | 
			
		||||
 * @minimum_size: location for storing the minimum size, or %NULL
 | 
			
		||||
 * @natural_size: location for storing the preferred size, or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Retreives an extended layout item's desired height if it would given
 | 
			
		||||
 * the size specified in @width.
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.16
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
 | 
			
		||||
                                          gint               width,
 | 
			
		||||
                                          gint              *minimum_height,
 | 
			
		||||
                                          gint              *natural_height)
 | 
			
		||||
{
 | 
			
		||||
  GtkExtendedLayoutIface *iface;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
 | 
			
		||||
  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
 | 
			
		||||
 | 
			
		||||
  if (iface->get_height_for_width)
 | 
			
		||||
    iface->get_height_for_width (layout, width, minimum_height, natural_height);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkRequisition minimum_size;
 | 
			
		||||
      GtkRequisition natural_size;
 | 
			
		||||
 | 
			
		||||
      iface->get_desired_size (layout, &minimum_size, &natural_size);
 | 
			
		||||
 | 
			
		||||
      if (minimum_height)
 | 
			
		||||
        *minimum_height = minimum_size.height;
 | 
			
		||||
      if (natural_height)
 | 
			
		||||
        *natural_height = natural_size.height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define __GTK_EXTENDED_LAYOUT_C__
 | 
			
		||||
#include "gtkaliasdef.c"
 | 
			
		||||
							
								
								
									
										74
									
								
								gtk/gtkextendedlayout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								gtk/gtkextendedlayout.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
			
		||||
/* GTK - The GIMP Toolkit
 | 
			
		||||
 * Copyright (C) 2007 Openismus GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * Author:
 | 
			
		||||
 *      Mathias Hasselmann <mathias@openismus.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 */
 | 
			
		||||
 | 
			
		||||
  void (*get_desired_size)     (GtkExtendedLayout  *layout,
 | 
			
		||||
                                GtkRequisition     *minimum_size,
 | 
			
		||||
                                GtkRequisition     *natural_size);
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
void  gtk_extended_layout_get_desired_size     (GtkExtendedLayout *layout,
 | 
			
		||||
                                                GtkRequisition    *minimum_size,
 | 
			
		||||
                                                GtkRequisition    *natural_size);
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __GTK_EXTENDED_LAYOUT_H__ */
 | 
			
		||||
							
								
								
									
										308
									
								
								gtk/gtklabel.c
									
									
									
									
									
								
							
							
						
						
									
										308
									
								
								gtk/gtklabel.c
									
									
									
									
									
								
							@ -48,6 +48,7 @@
 | 
			
		||||
#include "gtkimage.h"
 | 
			
		||||
#include "gtkshow.h"
 | 
			
		||||
#include "gtktooltip.h"
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkprivate.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
 | 
			
		||||
@ -58,6 +59,7 @@ typedef struct
 | 
			
		||||
  gint wrap_width;
 | 
			
		||||
  gint width_chars;
 | 
			
		||||
  gint max_width_chars;
 | 
			
		||||
  gboolean full_size;
 | 
			
		||||
} GtkLabelPrivate;
 | 
			
		||||
 | 
			
		||||
/* Notes about the handling of links:
 | 
			
		||||
@ -148,7 +150,8 @@ enum {
 | 
			
		||||
  PROP_SINGLE_LINE_MODE,
 | 
			
		||||
  PROP_ANGLE,
 | 
			
		||||
  PROP_MAX_WIDTH_CHARS,
 | 
			
		||||
  PROP_TRACK_VISITED_LINKS
 | 
			
		||||
  PROP_TRACK_VISITED_LINKS,
 | 
			
		||||
  PROP_FULL_SIZE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0 };
 | 
			
		||||
@ -166,8 +169,6 @@ static void gtk_label_get_property      (GObject          *object,
 | 
			
		||||
					 GParamSpec       *pspec);
 | 
			
		||||
static void gtk_label_destroy           (GtkObject        *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,
 | 
			
		||||
                                         GtkAllocation    *allocation);
 | 
			
		||||
static void gtk_label_state_changed     (GtkWidget        *widget,
 | 
			
		||||
@ -291,13 +292,29 @@ static void          gtk_label_get_link_colors  (GtkWidget  *widget,
 | 
			
		||||
static void          emit_activate_link         (GtkLabel     *label,
 | 
			
		||||
                                                 GtkLabelLink *link);
 | 
			
		||||
 | 
			
		||||
static void gtk_label_layout_interface_init (GtkExtendedLayoutIface *iface);
 | 
			
		||||
 | 
			
		||||
static void gtk_label_get_desired_size      (GtkExtendedLayout      *layout,
 | 
			
		||||
                                             GtkRequisition         *minimum_size,
 | 
			
		||||
                                             GtkRequisition         *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 GtkBuildableIface *buildable_parent_iface = NULL;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
 | 
			
		||||
			 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_layout_interface_init));
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
add_move_binding (GtkBindingSet  *binding_set,
 | 
			
		||||
@ -322,6 +339,14 @@ add_move_binding (GtkBindingSet  *binding_set,
 | 
			
		||||
				G_TYPE_BOOLEAN, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_label_layout_interface_init (GtkExtendedLayoutIface *iface)
 | 
			
		||||
{
 | 
			
		||||
  iface->get_desired_size = gtk_label_get_desired_size;
 | 
			
		||||
  iface->get_width_for_height = gtk_label_get_width_for_height;
 | 
			
		||||
  iface->get_height_for_width = gtk_label_get_height_for_width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_label_class_init (GtkLabelClass *class)
 | 
			
		||||
{
 | 
			
		||||
@ -338,7 +363,6 @@ gtk_label_class_init (GtkLabelClass *class)
 | 
			
		||||
 | 
			
		||||
  object_class->destroy = gtk_label_destroy;
 | 
			
		||||
 | 
			
		||||
  widget_class->size_request = gtk_label_size_request;
 | 
			
		||||
  widget_class->size_allocate = gtk_label_size_allocate;
 | 
			
		||||
  widget_class->state_changed = gtk_label_state_changed;
 | 
			
		||||
  widget_class->style_set = gtk_label_style_set;
 | 
			
		||||
@ -728,6 +752,24 @@ gtk_label_class_init (GtkLabelClass *class)
 | 
			
		||||
                                                         P_("Whether visited links should be tracked"),
 | 
			
		||||
                                                         TRUE,
 | 
			
		||||
                                                         GTK_PARAM_READWRITE));
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * GtkLabel:full-size:
 | 
			
		||||
   *
 | 
			
		||||
   * Use the entire space the widget got assigned for text wrapping. Overrides
 | 
			
		||||
   * any #GtkLabel:width-chars, #GtkLabel:max-width-chars and screen size based
 | 
			
		||||
   * constraints. Requires #GtkLabel:angle to be 0°, 90°, 180° or 270°.
 | 
			
		||||
   *
 | 
			
		||||
   * Since: 2.18
 | 
			
		||||
   **/
 | 
			
		||||
  g_object_class_install_property (gobject_class,
 | 
			
		||||
                                   PROP_FULL_SIZE,
 | 
			
		||||
                                   g_param_spec_boolean ("full-size",
 | 
			
		||||
							 P_("Full size"),
 | 
			
		||||
							 P_("Use the entire size of the widget to wrap text"),
 | 
			
		||||
                                                        FALSE,
 | 
			
		||||
                                                        GTK_PARAM_READWRITE));
 | 
			
		||||
  
 | 
			
		||||
  /*
 | 
			
		||||
   * Key bindings
 | 
			
		||||
   */
 | 
			
		||||
@ -914,6 +956,9 @@ gtk_label_set_property (GObject      *object,
 | 
			
		||||
    case PROP_TRACK_VISITED_LINKS:
 | 
			
		||||
      gtk_label_set_track_visited_links (label, g_value_get_boolean (value));
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_FULL_SIZE:
 | 
			
		||||
      gtk_label_set_full_size (label, g_value_get_boolean (value));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
@ -1000,6 +1045,9 @@ gtk_label_get_property (GObject     *object,
 | 
			
		||||
    case PROP_TRACK_VISITED_LINKS:
 | 
			
		||||
      g_value_set_boolean (value, gtk_label_get_track_visited_links (label));
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_FULL_SIZE:
 | 
			
		||||
      g_value_set_int (value, gtk_label_get_full_size (label));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
@ -1119,7 +1167,6 @@ attribute_from_text (GtkBuilder   *builder,
 | 
			
		||||
					      value, &val, error))
 | 
			
		||||
	attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
      /* PangoAttrString */	  
 | 
			
		||||
    case PANGO_ATTR_FAMILY:
 | 
			
		||||
      attribute = pango_attr_family_new (value);
 | 
			
		||||
@ -2891,14 +2938,14 @@ gtk_label_ensure_layout (GtkLabel *label)
 | 
			
		||||
      PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
 | 
			
		||||
      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,
 | 
			
		||||
	   * depending on the fact that it's meant pretty much exclusively
 | 
			
		||||
	   * for our use.
 | 
			
		||||
	   */
 | 
			
		||||
	  PangoMatrix matrix = PANGO_MATRIX_INIT;
 | 
			
		||||
	  
 | 
			
		||||
	  pango_matrix_rotate (&matrix, angle);
 | 
			
		||||
 | 
			
		||||
	  pango_context_set_matrix (gtk_widget_get_pango_context (widget), &matrix);
 | 
			
		||||
@ -2944,8 +2991,8 @@ gtk_label_ensure_layout (GtkLabel *label)
 | 
			
		||||
      pango_layout_set_single_paragraph_mode (label->layout, label->single_line_mode);
 | 
			
		||||
 | 
			
		||||
      if (label->ellipsize)
 | 
			
		||||
	pango_layout_set_width (label->layout, 
 | 
			
		||||
				widget->allocation.width * PANGO_SCALE);
 | 
			
		||||
        pango_layout_set_width (label->layout,
 | 
			
		||||
                                widget->allocation.width * PANGO_SCALE);
 | 
			
		||||
      else if (label->wrap)
 | 
			
		||||
	{
 | 
			
		||||
	  GtkWidgetAuxInfo *aux_info;
 | 
			
		||||
@ -3020,17 +3067,33 @@ gtk_label_ensure_layout (GtkLabel *label)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_label_size_request (GtkWidget      *widget,
 | 
			
		||||
			GtkRequisition *requisition)
 | 
			
		||||
static gint
 | 
			
		||||
get_single_line_height (GtkWidget   *widget,
 | 
			
		||||
                        PangoLayout *layout)
 | 
			
		||||
{
 | 
			
		||||
  GtkLabel *label = GTK_LABEL (widget);
 | 
			
		||||
  GtkLabelPrivate *priv;
 | 
			
		||||
  gint width, height;
 | 
			
		||||
  PangoRectangle logical_rect;
 | 
			
		||||
  GtkWidgetAuxInfo *aux_info;
 | 
			
		||||
  PangoContext *context;
 | 
			
		||||
  PangoFontMetrics *metrics;
 | 
			
		||||
  gint ascent, descent;
 | 
			
		||||
 | 
			
		||||
  priv = GTK_LABEL_GET_PRIVATE (widget);
 | 
			
		||||
  context = pango_layout_get_context (layout);
 | 
			
		||||
  metrics = pango_context_get_metrics (context, widget->style->font_desc,
 | 
			
		||||
                                       pango_context_get_language (context));
 | 
			
		||||
 | 
			
		||||
  ascent = pango_font_metrics_get_ascent (metrics);
 | 
			
		||||
  descent = pango_font_metrics_get_descent (metrics);
 | 
			
		||||
  pango_font_metrics_unref (metrics);
 | 
			
		||||
 | 
			
		||||
  return PANGO_PIXELS (ascent + descent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_label_get_desired_size (GtkExtendedLayout *layout,
 | 
			
		||||
                            GtkRequisition    *minimum_size,
 | 
			
		||||
                            GtkRequisition    *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (layout);
 | 
			
		||||
  GtkLabel *label = GTK_LABEL (layout);
 | 
			
		||||
  PangoRectangle required_rect;
 | 
			
		||||
 | 
			
		||||
  /*  
 | 
			
		||||
   * If word wrapping is on, then the height requisition can depend
 | 
			
		||||
@ -3050,61 +3113,152 @@ gtk_label_size_request (GtkWidget      *widget,
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
  if (minimum_size)
 | 
			
		||||
    {
 | 
			
		||||
      PangoRectangle rect;
 | 
			
		||||
      PangoContext *context = pango_layout_get_context (label->layout);
 | 
			
		||||
      const PangoMatrix *matrix = pango_context_get_matrix (context);
 | 
			
		||||
      GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (label), FALSE);
 | 
			
		||||
 | 
			
		||||
      pango_layout_get_extents (label->layout, NULL, &rect);
 | 
			
		||||
      pango_matrix_transform_rectangle (matrix, &rect);
 | 
			
		||||
      pango_extents_to_pixels (&rect, NULL);
 | 
			
		||||
      pango_layout_get_extents (label->layout, NULL, &required_rect);
 | 
			
		||||
      required_rect.x = required_rect.y = 0;
 | 
			
		||||
 | 
			
		||||
      requisition->width = width + rect.width;
 | 
			
		||||
      requisition->height = height + rect.height;
 | 
			
		||||
      if (label->ellipsize || priv->width_chars > 0 || priv->max_width_chars > 0)
 | 
			
		||||
        {
 | 
			
		||||
          /* backup the Pango layout, as get_label_char_width() scrambles it */
 | 
			
		||||
 | 
			
		||||
      return;
 | 
			
		||||
          PangoLayout *backup = label->layout;
 | 
			
		||||
          label->layout = pango_layout_copy (label->layout);
 | 
			
		||||
 | 
			
		||||
          required_rect.width = get_label_char_width (label);
 | 
			
		||||
 | 
			
		||||
          g_object_unref (label->layout);
 | 
			
		||||
          label->layout = backup;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (label->single_line_mode)
 | 
			
		||||
        required_rect.height = get_single_line_height (GTK_WIDGET (label), label->layout);
 | 
			
		||||
 | 
			
		||||
      if (label->have_transform)
 | 
			
		||||
        {
 | 
			
		||||
          PangoContext *context = pango_layout_get_context (label->layout);
 | 
			
		||||
          const PangoMatrix *matrix = pango_context_get_matrix (context);
 | 
			
		||||
          pango_matrix_transform_rectangle (matrix, &required_rect);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      required_rect.width = PANGO_PIXELS_CEIL (required_rect.width);
 | 
			
		||||
      required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
 | 
			
		||||
 | 
			
		||||
      if ((label->wrap || label->ellipsize ||
 | 
			
		||||
           priv->width_chars > 0 || priv->max_width_chars > 0) &&
 | 
			
		||||
          aux_info && aux_info->width > 0)
 | 
			
		||||
        required_rect.width = aux_info->width;
 | 
			
		||||
 | 
			
		||||
      minimum_size->width = required_rect.width + label->misc.xpad * 2;
 | 
			
		||||
      minimum_size->height = required_rect.height + label->misc.ypad * 2;
 | 
			
		||||
    }
 | 
			
		||||
  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)
 | 
			
		||||
  if (natural_size)
 | 
			
		||||
    {
 | 
			
		||||
      width += PANGO_PIXELS (get_label_char_width (label));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    width += PANGO_PIXELS (logical_rect.width);
 | 
			
		||||
      PangoLayout *natural_layout = pango_layout_copy (label->layout);
 | 
			
		||||
 | 
			
		||||
  if (label->single_line_mode)
 | 
			
		||||
      pango_layout_set_width (natural_layout, -1);
 | 
			
		||||
      pango_layout_set_ellipsize (natural_layout, PANGO_ELLIPSIZE_NONE);
 | 
			
		||||
 | 
			
		||||
      pango_layout_get_extents (natural_layout, NULL, &required_rect);
 | 
			
		||||
      required_rect.x = required_rect.y = 0;
 | 
			
		||||
 | 
			
		||||
      if (label->single_line_mode)
 | 
			
		||||
        required_rect.height = get_single_line_height (GTK_WIDGET (label), label->layout);
 | 
			
		||||
 | 
			
		||||
      if (label->have_transform)
 | 
			
		||||
        {
 | 
			
		||||
          PangoContext *context = pango_layout_get_context (natural_layout);
 | 
			
		||||
          const PangoMatrix *matrix = pango_context_get_matrix (context);
 | 
			
		||||
          pango_matrix_transform_rectangle (matrix, &required_rect);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      required_rect.width = PANGO_PIXELS_CEIL (required_rect.width);
 | 
			
		||||
      required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
 | 
			
		||||
 | 
			
		||||
      natural_size->width = required_rect.width + label->misc.xpad * 2;
 | 
			
		||||
      natural_size->height = required_rect.height + label->misc.ypad * 2;
 | 
			
		||||
 | 
			
		||||
      g_object_unref (natural_layout);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_size_for_allocation (GtkLabel *label,
 | 
			
		||||
                         gint      allocation,
 | 
			
		||||
                         gint     *minimum_size,
 | 
			
		||||
                         gint     *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  PangoLayout *layout;
 | 
			
		||||
 | 
			
		||||
  gtk_label_ensure_layout (label);
 | 
			
		||||
  layout = pango_layout_copy (label->layout);
 | 
			
		||||
  pango_layout_set_width (layout, PANGO_SCALE * allocation);
 | 
			
		||||
 | 
			
		||||
  if (minimum_size)
 | 
			
		||||
    pango_layout_get_pixel_size (layout, NULL, minimum_size);
 | 
			
		||||
 | 
			
		||||
  if (natural_size)
 | 
			
		||||
    {
 | 
			
		||||
      PangoContext *context;
 | 
			
		||||
      PangoFontMetrics *metrics;
 | 
			
		||||
      gint ascent, descent;
 | 
			
		||||
 | 
			
		||||
      context = pango_layout_get_context (label->layout);
 | 
			
		||||
      metrics = pango_context_get_metrics (context, widget->style->font_desc,
 | 
			
		||||
                                           pango_context_get_language (context));
 | 
			
		||||
 | 
			
		||||
      ascent = pango_font_metrics_get_ascent (metrics);
 | 
			
		||||
      descent = pango_font_metrics_get_descent (metrics);
 | 
			
		||||
      pango_font_metrics_unref (metrics);
 | 
			
		||||
    
 | 
			
		||||
      height += PANGO_PIXELS (ascent + descent);
 | 
			
		||||
//      pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE);
 | 
			
		||||
      pango_layout_get_pixel_size (layout, NULL, natural_size);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    height += PANGO_PIXELS (logical_rect.height);
 | 
			
		||||
 | 
			
		||||
  requisition->width = width;
 | 
			
		||||
  requisition->height = height;
 | 
			
		||||
  g_object_unref (layout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 (90 == angle || 270 == angle)
 | 
			
		||||
    get_size_for_allocation (label, height, minimum_width, natural_width);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkRequisition minimum_size, natural_size;
 | 
			
		||||
 | 
			
		||||
      gtk_extended_layout_get_desired_size (layout,
 | 
			
		||||
                                            minimum_width ? &minimum_size : NULL,
 | 
			
		||||
                                            natural_width ? &natural_size : NULL);
 | 
			
		||||
 | 
			
		||||
      if (minimum_width)
 | 
			
		||||
        *minimum_width = minimum_size.width;
 | 
			
		||||
      if (natural_width)
 | 
			
		||||
        *natural_width = natural_size.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 (0 == angle || 180 == angle)
 | 
			
		||||
    get_size_for_allocation (label, width, minimum_height, natural_height);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkRequisition minimum_size, natural_size;
 | 
			
		||||
 | 
			
		||||
      gtk_extended_layout_get_desired_size (layout,
 | 
			
		||||
                                            minimum_height ? &minimum_size : NULL,
 | 
			
		||||
                                            natural_height ? &natural_size : NULL);
 | 
			
		||||
 | 
			
		||||
      if (minimum_height)
 | 
			
		||||
        *minimum_height = minimum_size.height;
 | 
			
		||||
      if (natural_height)
 | 
			
		||||
        *natural_height = natural_size.height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -4945,6 +5099,32 @@ gtk_label_set_use_underline (GtkLabel *label,
 | 
			
		||||
  gtk_label_recalculate (label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gtk_label_get_full_size (GtkLabel *label)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
 | 
			
		||||
  return GTK_LABEL_GET_PRIVATE (label)->full_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gtk_label_set_full_size (GtkLabel *label,
 | 
			
		||||
			 gboolean  setting)
 | 
			
		||||
{
 | 
			
		||||
  GtkLabelPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GTK_IS_LABEL (label));
 | 
			
		||||
  priv = GTK_LABEL_GET_PRIVATE (label);
 | 
			
		||||
 | 
			
		||||
  if (priv->full_size != setting)
 | 
			
		||||
    {
 | 
			
		||||
      priv->full_size = setting;
 | 
			
		||||
 | 
			
		||||
      g_object_notify (G_OBJECT (label), "full-size");
 | 
			
		||||
      gtk_label_invalidate_wrap_width (label);
 | 
			
		||||
      gtk_widget_queue_resize (GTK_WIDGET (label));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_label_get_use_underline:
 | 
			
		||||
 * @label: a #GtkLabel
 | 
			
		||||
 | 
			
		||||
@ -126,6 +126,9 @@ gboolean              gtk_label_get_use_markup    (GtkLabel      *label);
 | 
			
		||||
void                  gtk_label_set_use_underline (GtkLabel      *label,
 | 
			
		||||
						   gboolean       setting);
 | 
			
		||||
gboolean              gtk_label_get_use_underline (GtkLabel      *label);
 | 
			
		||||
void                  gtk_label_set_full_size     (GtkLabel      *label,
 | 
			
		||||
						   gboolean       setting);
 | 
			
		||||
gboolean              gtk_label_get_full_size     (GtkLabel      *label);
 | 
			
		||||
 | 
			
		||||
void     gtk_label_set_markup_with_mnemonic       (GtkLabel         *label,
 | 
			
		||||
						   const gchar      *str);
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,18 @@
 | 
			
		||||
#include "gtkprivate.h"
 | 
			
		||||
#include "gtksizegroup.h"
 | 
			
		||||
#include "gtkbuildable.h"
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
 | 
			
		||||
#define GTK_SIZE_GROUP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_SIZE_GROUP, GtkSizeGroupPrivate))
 | 
			
		||||
 | 
			
		||||
typedef struct _GtkSizeGroupPrivate GtkSizeGroupPrivate;
 | 
			
		||||
 | 
			
		||||
struct _GtkSizeGroupPrivate
 | 
			
		||||
{
 | 
			
		||||
  GtkRequisition natural_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_MODE,
 | 
			
		||||
@ -322,6 +332,7 @@ gtk_size_group_class_init (GtkSizeGroupClass *klass)
 | 
			
		||||
							 GTK_PARAM_READWRITE));
 | 
			
		||||
  
 | 
			
		||||
  initialize_size_group_quarks ();
 | 
			
		||||
  g_type_class_add_private (klass, sizeof (GtkSizeGroupPrivate));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -596,25 +607,49 @@ gtk_size_group_get_widgets (GtkSizeGroup *size_group)
 | 
			
		||||
  return size_group->widgets;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
get_base_dimension (GtkWidget        *widget,
 | 
			
		||||
		    GtkSizeGroupMode  mode)
 | 
			
		||||
static void
 | 
			
		||||
get_base_dimensions (GtkWidget        *widget,
 | 
			
		||||
                     GtkSizeGroupMode  mode,
 | 
			
		||||
                     gint             *minimum_size,
 | 
			
		||||
                     gint             *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (mode == GTK_SIZE_GROUP_HORIZONTAL)
 | 
			
		||||
    {
 | 
			
		||||
      if (aux_info && aux_info->width > 0)
 | 
			
		||||
	return aux_info->width;
 | 
			
		||||
      else
 | 
			
		||||
	return widget->requisition.width;
 | 
			
		||||
      if (minimum_size)
 | 
			
		||||
        {
 | 
			
		||||
          if (aux_info && aux_info->width > 0)
 | 
			
		||||
            *minimum_size = aux_info->width;
 | 
			
		||||
          else
 | 
			
		||||
            *minimum_size = widget->requisition.width;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (natural_size)
 | 
			
		||||
        {
 | 
			
		||||
          if (aux_info)
 | 
			
		||||
            *natural_size = aux_info->natural_size.width;
 | 
			
		||||
          else
 | 
			
		||||
            *natural_size = widget->requisition.width;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (aux_info && aux_info->height > 0)
 | 
			
		||||
	return aux_info->height;
 | 
			
		||||
      else
 | 
			
		||||
	return widget->requisition.height;
 | 
			
		||||
      if (minimum_size)
 | 
			
		||||
        {
 | 
			
		||||
          if (aux_info && aux_info->height > 0)
 | 
			
		||||
            *minimum_size = aux_info->height;
 | 
			
		||||
          else
 | 
			
		||||
            *minimum_size = widget->requisition.height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (natural_size)
 | 
			
		||||
        {
 | 
			
		||||
          if (aux_info)
 | 
			
		||||
            *natural_size = aux_info->natural_size.height;
 | 
			
		||||
          else
 | 
			
		||||
            *natural_size = widget->requisition.height;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -623,26 +658,35 @@ do_size_request (GtkWidget *widget)
 | 
			
		||||
{
 | 
			
		||||
  if (GTK_WIDGET_REQUEST_NEEDED (widget))
 | 
			
		||||
    {
 | 
			
		||||
      GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE);
 | 
			
		||||
 | 
			
		||||
      gtk_widget_ensure_style (widget);      
 | 
			
		||||
      GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
 | 
			
		||||
      g_signal_emit_by_name (widget,
 | 
			
		||||
			     "size-request",
 | 
			
		||||
			     &widget->requisition);
 | 
			
		||||
 | 
			
		||||
      gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget),
 | 
			
		||||
                                            &widget->requisition,
 | 
			
		||||
                                            &aux_info->natural_size);
 | 
			
		||||
 | 
			
		||||
      g_assert (widget->requisition.width <= aux_info->natural_size.width);
 | 
			
		||||
      g_assert (widget->requisition.height <= aux_info->natural_size.height);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
compute_base_dimension (GtkWidget        *widget,
 | 
			
		||||
			GtkSizeGroupMode  mode)
 | 
			
		||||
static void
 | 
			
		||||
compute_base_dimensions (GtkWidget        *widget,
 | 
			
		||||
		 	 GtkSizeGroupMode  mode,
 | 
			
		||||
                         gint             *minimum_size,
 | 
			
		||||
                         gint             *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  do_size_request (widget);
 | 
			
		||||
 | 
			
		||||
  return get_base_dimension (widget, mode);
 | 
			
		||||
  get_base_dimensions (widget, mode, minimum_size, natural_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
compute_dimension (GtkWidget        *widget,
 | 
			
		||||
		   GtkSizeGroupMode  mode)
 | 
			
		||||
		   GtkSizeGroupMode  mode,
 | 
			
		||||
                   gint             *minimum_size,
 | 
			
		||||
                   gint             *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GSList *widgets = NULL;
 | 
			
		||||
  GSList *groups = NULL;
 | 
			
		||||
@ -658,16 +702,26 @@ compute_dimension (GtkWidget        *widget,
 | 
			
		||||
  
 | 
			
		||||
  if (!groups)
 | 
			
		||||
    {
 | 
			
		||||
      result = compute_base_dimension (widget, mode);
 | 
			
		||||
      compute_base_dimensions (widget, mode, minimum_size, natural_size);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkSizeGroup *group = groups->data;
 | 
			
		||||
      GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (group);
 | 
			
		||||
 | 
			
		||||
      gint result_minimum_size = 0;
 | 
			
		||||
      gint result_natural_size = 0;
 | 
			
		||||
 | 
			
		||||
      if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
 | 
			
		||||
	result = group->requisition.width;
 | 
			
		||||
        {
 | 
			
		||||
          result_minimum_size = group->requisition.width;
 | 
			
		||||
          result_natural_size = priv->natural_size.width;
 | 
			
		||||
        }
 | 
			
		||||
      else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
 | 
			
		||||
	result = group->requisition.height;
 | 
			
		||||
        {
 | 
			
		||||
          result_minimum_size = group->requisition.height;
 | 
			
		||||
          result_natural_size = priv->natural_size.height;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  tmp_list = widgets;
 | 
			
		||||
@ -675,13 +729,20 @@ compute_dimension (GtkWidget        *widget,
 | 
			
		||||
	    {
 | 
			
		||||
	      GtkWidget *tmp_widget = tmp_list->data;
 | 
			
		||||
 | 
			
		||||
	      gint dimension = compute_base_dimension (tmp_widget, mode);
 | 
			
		||||
              gint tmp_widget_minimum_size;
 | 
			
		||||
              gint tmp_widget_natural_size;
 | 
			
		||||
 | 
			
		||||
	      if (GTK_WIDGET_MAPPED (tmp_widget) || !group->ignore_hidden)
 | 
			
		||||
		{
 | 
			
		||||
		  if (dimension > result)
 | 
			
		||||
		    result = dimension;
 | 
			
		||||
		}
 | 
			
		||||
              compute_base_dimensions (tmp_widget, mode,
 | 
			
		||||
                                       &tmp_widget_minimum_size,
 | 
			
		||||
                                       &tmp_widget_natural_size);
 | 
			
		||||
 | 
			
		||||
              if (GTK_WIDGET_MAPPED (tmp_widget) || !group->ignore_hidden)
 | 
			
		||||
                {
 | 
			
		||||
                  if (result_minimum_size < tmp_widget_minimum_size)
 | 
			
		||||
                    result_minimum_size = tmp_widget_minimum_size;
 | 
			
		||||
                  if (result_natural_size < tmp_widget_natural_size)
 | 
			
		||||
                    result_natural_size = tmp_widget_natural_size;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
	      tmp_list = tmp_list->next;
 | 
			
		||||
	    }
 | 
			
		||||
@ -690,38 +751,45 @@ compute_dimension (GtkWidget        *widget,
 | 
			
		||||
	  while (tmp_list)
 | 
			
		||||
	    {
 | 
			
		||||
	      GtkSizeGroup *tmp_group = tmp_list->data;
 | 
			
		||||
              GtkSizeGroupPrivate *tmp_priv = GTK_SIZE_GROUP_GET_PRIVATE (tmp_group);
 | 
			
		||||
 | 
			
		||||
	      if (mode == GTK_SIZE_GROUP_HORIZONTAL)
 | 
			
		||||
		{
 | 
			
		||||
		  tmp_group->have_width = TRUE;
 | 
			
		||||
		  tmp_group->requisition.width = result;
 | 
			
		||||
                  tmp_group->requisition.width = result_minimum_size;
 | 
			
		||||
                  tmp_priv->natural_size.width = result_natural_size;
 | 
			
		||||
		}
 | 
			
		||||
	      else
 | 
			
		||||
		{
 | 
			
		||||
		  tmp_group->have_height = TRUE;
 | 
			
		||||
		  tmp_group->requisition.height = result;
 | 
			
		||||
                  tmp_group->requisition.height = result_minimum_size;
 | 
			
		||||
                  tmp_priv->natural_size.height = result_natural_size;
 | 
			
		||||
		}
 | 
			
		||||
	      
 | 
			
		||||
	      tmp_list = tmp_list->next;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      if (minimum_size)
 | 
			
		||||
        *minimum_size = result_minimum_size;
 | 
			
		||||
      if (natural_size)
 | 
			
		||||
        *natural_size = result_natural_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_slist_foreach (widgets, (GFunc)g_object_unref, NULL);
 | 
			
		||||
 | 
			
		||||
  g_slist_free (widgets);
 | 
			
		||||
  g_slist_free (groups);
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
get_dimension (GtkWidget        *widget,
 | 
			
		||||
	       GtkSizeGroupMode  mode)
 | 
			
		||||
static void
 | 
			
		||||
get_dimensions (GtkWidget        *widget,
 | 
			
		||||
                GtkSizeGroupMode  mode,
 | 
			
		||||
                gint             *minimum_size,
 | 
			
		||||
                gint             *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GSList *widgets = NULL;
 | 
			
		||||
  GSList *groups = NULL;
 | 
			
		||||
  gint result = 0;
 | 
			
		||||
 | 
			
		||||
  add_widget_to_closure (widget, mode, &groups, &widgets);
 | 
			
		||||
 | 
			
		||||
@ -730,22 +798,31 @@ get_dimension (GtkWidget        *widget,
 | 
			
		||||
 | 
			
		||||
  if (!groups)
 | 
			
		||||
    {
 | 
			
		||||
      result = get_base_dimension (widget, mode);
 | 
			
		||||
      get_base_dimensions (widget, mode, minimum_size, natural_size);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GtkSizeGroup *group = groups->data;
 | 
			
		||||
      GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (group);
 | 
			
		||||
 | 
			
		||||
      if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
 | 
			
		||||
	result = group->requisition.width;
 | 
			
		||||
        {
 | 
			
		||||
          if (minimum_size)
 | 
			
		||||
            *minimum_size = group->requisition.width;
 | 
			
		||||
          if (natural_size)
 | 
			
		||||
            *natural_size = priv->natural_size.width;
 | 
			
		||||
        }
 | 
			
		||||
      else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
 | 
			
		||||
	result = group->requisition.height;
 | 
			
		||||
        {
 | 
			
		||||
          if (minimum_size)
 | 
			
		||||
            *minimum_size = group->requisition.height;
 | 
			
		||||
          if (natural_size)
 | 
			
		||||
            *natural_size = priv->natural_size.height;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_slist_free (widgets);
 | 
			
		||||
  g_slist_free (groups);
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -760,11 +837,23 @@ get_fast_child_requisition (GtkWidget      *widget,
 | 
			
		||||
    {
 | 
			
		||||
      if (aux_info->width > 0)
 | 
			
		||||
	requisition->width = aux_info->width;
 | 
			
		||||
      if (aux_info && aux_info->height > 0)
 | 
			
		||||
      if (aux_info->height > 0)
 | 
			
		||||
	requisition->height = aux_info->height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_fast_natural_size (GtkWidget      *widget,
 | 
			
		||||
                       GtkRequisition *requisition)
 | 
			
		||||
{
 | 
			
		||||
  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (aux_info)
 | 
			
		||||
    *requisition = aux_info->natural_size;
 | 
			
		||||
  else
 | 
			
		||||
    *requisition = widget->requisition;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * _gtk_size_group_get_child_requisition:
 | 
			
		||||
 * @widget: a #GtkWidget
 | 
			
		||||
@ -783,8 +872,8 @@ _gtk_size_group_get_child_requisition (GtkWidget      *widget,
 | 
			
		||||
    {
 | 
			
		||||
      if (get_size_groups (widget))
 | 
			
		||||
	{
 | 
			
		||||
	  requisition->width = get_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
 | 
			
		||||
	  requisition->height = get_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
 | 
			
		||||
	  get_dimensions (widget, GTK_SIZE_GROUP_HORIZONTAL, &requisition->width, NULL);
 | 
			
		||||
	  get_dimensions (widget, GTK_SIZE_GROUP_VERTICAL, &requisition->height, NULL);
 | 
			
		||||
 | 
			
		||||
	  /* Only do the full computation if we actually have size groups */
 | 
			
		||||
	}
 | 
			
		||||
@ -794,41 +883,40 @@ _gtk_size_group_get_child_requisition (GtkWidget      *widget,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * _gtk_size_group_compute_requisition:
 | 
			
		||||
 * _gtk_size_group_compute_desired_size:
 | 
			
		||||
 * @widget: a #GtkWidget
 | 
			
		||||
 * @requisition: location to store computed requisition.
 | 
			
		||||
 * @minimum_size: location to store computed minimum size
 | 
			
		||||
 * @natural_size: location to store computed natural size
 | 
			
		||||
 * 
 | 
			
		||||
 * Compute the requisition of a widget taking into account grouping of
 | 
			
		||||
 * Compute the desired size 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)
 | 
			
		||||
_gtk_size_group_compute_desired_size (GtkWidget      *widget,
 | 
			
		||||
                                      GtkRequisition *minimum_size,
 | 
			
		||||
                                      GtkRequisition *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  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;
 | 
			
		||||
	}
 | 
			
		||||
      compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL,
 | 
			
		||||
                         minimum_size ? &minimum_size->width : NULL,
 | 
			
		||||
                         natural_size ? &natural_size->width : NULL);
 | 
			
		||||
      compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL,
 | 
			
		||||
                         minimum_size ? &minimum_size->height : NULL,
 | 
			
		||||
                         natural_size ? &natural_size->height : NULL);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      do_size_request (widget);
 | 
			
		||||
 | 
			
		||||
      if (requisition)
 | 
			
		||||
	get_fast_child_requisition (widget, requisition);
 | 
			
		||||
      if (minimum_size)
 | 
			
		||||
        get_fast_child_requisition (widget, minimum_size);
 | 
			
		||||
      if (natural_size)
 | 
			
		||||
        get_fast_natural_size (widget, natural_size);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -102,8 +102,9 @@ GSList *         gtk_size_group_get_widgets   (GtkSizeGroup     *size_group);
 | 
			
		||||
 | 
			
		||||
void _gtk_size_group_get_child_requisition (GtkWidget      *widget,
 | 
			
		||||
					    GtkRequisition *requisition);
 | 
			
		||||
void _gtk_size_group_compute_requisition   (GtkWidget      *widget,
 | 
			
		||||
					    GtkRequisition *requisition);
 | 
			
		||||
void _gtk_size_group_compute_desired_size  (GtkWidget      *widget,
 | 
			
		||||
                                            GtkRequisition *minimum_size,
 | 
			
		||||
                                            GtkRequisition *natural_size);
 | 
			
		||||
void _gtk_size_group_queue_resize          (GtkWidget      *widget);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								gtk/gtkwidget.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								gtk/gtkwidget.c
									
									
									
									
									
								
							@ -53,6 +53,7 @@
 | 
			
		||||
#include "gtkinvisible.h"
 | 
			
		||||
#include "gtkbuildable.h"
 | 
			
		||||
#include "gtkbuilderprivate.h"
 | 
			
		||||
#include "gtkextendedlayout.h"
 | 
			
		||||
#include "gtkalias.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -343,6 +344,11 @@ static void             gtk_widget_buildable_custom_finished    (GtkBuildable
 | 
			
		||||
static void             gtk_widget_buildable_parser_finished    (GtkBuildable     *buildable,
 | 
			
		||||
                                                                 GtkBuilder       *builder);
 | 
			
		||||
 | 
			
		||||
static void             gtk_widget_layout_interface_init        (GtkExtendedLayoutIface *iface);
 | 
			
		||||
static void             gtk_widget_real_get_desired_size        (GtkExtendedLayout *layout,
 | 
			
		||||
                                                                 GtkRequisition    *minimum_size,
 | 
			
		||||
                                                                 GtkRequisition    *natural_size);
 | 
			
		||||
 | 
			
		||||
static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
 | 
			
		||||
     
 | 
			
		||||
static void gtk_widget_set_usize_internal (GtkWidget *widget,
 | 
			
		||||
@ -418,6 +424,13 @@ gtk_widget_get_type (void)
 | 
			
		||||
	NULL /* interface data */
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const GInterfaceInfo layout_info =
 | 
			
		||||
      {
 | 
			
		||||
	(GInterfaceInitFunc) gtk_widget_layout_interface_init,
 | 
			
		||||
	(GInterfaceFinalizeFunc) NULL,
 | 
			
		||||
	NULL /* interface data */
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      widget_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
 | 
			
		||||
                                           &widget_info, G_TYPE_FLAG_ABSTRACT);
 | 
			
		||||
 | 
			
		||||
@ -425,7 +438,8 @@ gtk_widget_get_type (void)
 | 
			
		||||
                                   &accessibility_info) ;
 | 
			
		||||
      g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
 | 
			
		||||
                                   &buildable_info) ;
 | 
			
		||||
 | 
			
		||||
      g_type_add_interface_static (widget_type, GTK_TYPE_EXTENDED_LAYOUT,
 | 
			
		||||
                                   &layout_info) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return widget_type;
 | 
			
		||||
@ -3869,10 +3883,11 @@ gtk_widget_size_request (GtkWidget	*widget,
 | 
			
		||||
 | 
			
		||||
#ifdef G_ENABLE_DEBUG
 | 
			
		||||
  if (requisition == &widget->requisition)
 | 
			
		||||
    g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly.");
 | 
			
		||||
    g_warning ("gtk_widget_size_request() called on child widget with request equal\n"
 | 
			
		||||
               "to widget->requisition. gtk_widget_set_usize() may not work properly.");
 | 
			
		||||
#endif /* G_ENABLE_DEBUG */
 | 
			
		||||
 | 
			
		||||
  _gtk_size_group_compute_requisition (widget, requisition);
 | 
			
		||||
  _gtk_size_group_compute_desired_size (widget, requisition, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -9116,14 +9131,11 @@ _gtk_widget_get_aux_info (GtkWidget *widget,
 | 
			
		||||
  aux_info = g_object_get_qdata (G_OBJECT (widget), quark_aux_info);
 | 
			
		||||
  if (!aux_info && create)
 | 
			
		||||
    {
 | 
			
		||||
      aux_info = g_slice_new (GtkWidgetAuxInfo);
 | 
			
		||||
      aux_info = g_slice_new0 (GtkWidgetAuxInfo);
 | 
			
		||||
 | 
			
		||||
      aux_info->width = -1;
 | 
			
		||||
      aux_info->height = -1;
 | 
			
		||||
      aux_info->x = 0;
 | 
			
		||||
      aux_info->y = 0;
 | 
			
		||||
      aux_info->x_set = FALSE;
 | 
			
		||||
      aux_info->y_set = FALSE;
 | 
			
		||||
 | 
			
		||||
      g_object_set_qdata (G_OBJECT (widget), quark_aux_info, aux_info);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
@ -10559,6 +10571,101 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * GtkExtendedLayout implementation
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
gtk_widget_real_get_desired_size (GtkExtendedLayout *layout,
 | 
			
		||||
                                  GtkRequisition    *minimum_size,
 | 
			
		||||
                                  GtkRequisition    *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  GtkWidget *widget = GTK_WIDGET (layout);
 | 
			
		||||
  GtkRequisition requisition = widget->requisition;
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (widget, widget_signals[SIZE_REQUEST], 0, &requisition);
 | 
			
		||||
 | 
			
		||||
  if (minimum_size)
 | 
			
		||||
    *minimum_size = requisition;
 | 
			
		||||
  if (natural_size)
 | 
			
		||||
    *natural_size = requisition;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_widget_get_desired_size:
 | 
			
		||||
 * @widget: a #GtkWidget
 | 
			
		||||
 * @minimum_size: location for storing the @widget's minimum size, or %NULL
 | 
			
		||||
 * @natural_size: location for storing the @widget's preferred size, or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Retreives a widget's desired size, considering restrictions imposed by
 | 
			
		||||
 * #GtkSizeGroup<!-- -->s. See also: gtk_extended_layout_get_desired_size().
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.20
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gtk_widget_get_desired_size (GtkWidget      *widget,
 | 
			
		||||
                             GtkRequisition *minimum_size,
 | 
			
		||||
                             GtkRequisition *natural_size)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (GTK_IS_WIDGET (widget));
 | 
			
		||||
  _gtk_size_group_compute_desired_size (widget, minimum_size, natural_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gtk_widget_get_height_for_width (GtkWidget *widget,
 | 
			
		||||
                                 gint       width,
 | 
			
		||||
                                 gint      *minimum_height,
 | 
			
		||||
                                 gint      *natural_height)
 | 
			
		||||
{
 | 
			
		||||
  GtkRequisition minimum_size;
 | 
			
		||||
  GtkRequisition natural_size;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GTK_IS_WIDGET (widget));
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  TODO: integrate height-for-width with size-groups
 | 
			
		||||
#else
 | 
			
		||||
  gtk_widget_get_desired_size (widget,
 | 
			
		||||
                               minimum_height ? &minimum_size : NULL,
 | 
			
		||||
                               natural_height ? &natural_size : NULL);
 | 
			
		||||
 | 
			
		||||
  if (minimum_height)
 | 
			
		||||
    *minimum_height = minimum_size.height;
 | 
			
		||||
  if (natural_height)
 | 
			
		||||
    *natural_height = natural_size.height;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gtk_widget_get_width_for_height (GtkWidget *widget,
 | 
			
		||||
                                 gint       height,
 | 
			
		||||
                                 gint      *minimum_width,
 | 
			
		||||
                                 gint      *natural_width)
 | 
			
		||||
{
 | 
			
		||||
  GtkRequisition minimum_size;
 | 
			
		||||
  GtkRequisition natural_size;
 | 
			
		||||
 
 | 
			
		||||
  g_return_if_fail (GTK_IS_WIDGET (widget));
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  TODO: integrate width-for-height with size-groups
 | 
			
		||||
#else
 | 
			
		||||
  gtk_widget_get_desired_size (widget,
 | 
			
		||||
                               minimum_width ? &minimum_size : NULL,
 | 
			
		||||
                               natural_width ? &natural_size : NULL);
 | 
			
		||||
 | 
			
		||||
  if (minimum_width)
 | 
			
		||||
    *minimum_width = minimum_size.width;
 | 
			
		||||
  if (natural_width)
 | 
			
		||||
    *natural_width = natural_size.width;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gtk_widget_layout_interface_init (GtkExtendedLayoutIface *iface)
 | 
			
		||||
{
 | 
			
		||||
  iface->get_desired_size = gtk_widget_real_get_desired_size;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
/**
 | 
			
		||||
 * gtk_widget_get_clipboard:
 | 
			
		||||
 | 
			
		||||
@ -705,8 +705,11 @@ struct _GtkWidgetAuxInfo
 | 
			
		||||
  gint y;
 | 
			
		||||
  gint width;
 | 
			
		||||
  gint height;
 | 
			
		||||
 | 
			
		||||
  guint x_set : 1;
 | 
			
		||||
  guint y_set : 1;
 | 
			
		||||
 | 
			
		||||
  GtkRequisition natural_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _GtkWidgetShapeInfo
 | 
			
		||||
@ -771,6 +774,17 @@ void	   gtk_widget_size_request	  (GtkWidget	       *widget,
 | 
			
		||||
					   GtkRequisition      *requisition);
 | 
			
		||||
void	   gtk_widget_size_allocate	  (GtkWidget	       *widget,
 | 
			
		||||
					   GtkAllocation       *allocation);
 | 
			
		||||
void       gtk_widget_get_desired_size    (GtkWidget           *widget,
 | 
			
		||||
					   GtkRequisition      *minimum_size,
 | 
			
		||||
					   GtkRequisition      *natural_size);
 | 
			
		||||
void       gtk_widget_get_height_for_width(GtkWidget           *widget,
 | 
			
		||||
					   gint                 width,
 | 
			
		||||
					   gint                *minimum_height,
 | 
			
		||||
					   gint                *natural_height);
 | 
			
		||||
void       gtk_widget_get_width_for_height(GtkWidget           *widget,
 | 
			
		||||
					   gint                 height,
 | 
			
		||||
					   gint                *minimum_width,
 | 
			
		||||
					   gint                *natural_width);
 | 
			
		||||
void       gtk_widget_get_child_requisition (GtkWidget	       *widget,
 | 
			
		||||
					     GtkRequisition    *requisition);
 | 
			
		||||
void	   gtk_widget_add_accelerator	  (GtkWidget           *widget,
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@ noinst_PROGRAMS =  $(TEST_PROGS)	\
 | 
			
		||||
	testellipsise			\
 | 
			
		||||
	testentrycompletion 		\
 | 
			
		||||
	testentryicons			\
 | 
			
		||||
	testextendedlayout		\
 | 
			
		||||
	testfilechooser			\
 | 
			
		||||
	testfilechooserbutton		\
 | 
			
		||||
	testframe			\
 | 
			
		||||
@ -127,6 +128,7 @@ testdnd_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testellipsise_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testentrycompletion_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testentryicons_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testextendedlayout_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testfilechooser_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testfilechooserbutton_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
testgtk_DEPENDENCIES = $(TEST_DEPS)
 | 
			
		||||
@ -188,6 +190,7 @@ testdnd_LDADD = $(LDADDS)
 | 
			
		||||
testellipsise_LDADD = $(LDADDS)
 | 
			
		||||
testentrycompletion_LDADD = $(LDADDS)
 | 
			
		||||
testentryicons_LDADD = $(LDADDS)
 | 
			
		||||
testextendedlayout_LDADD = $(LDADDS)
 | 
			
		||||
testfilechooser_LDADD = $(LDADDS)
 | 
			
		||||
testfilechooserbutton_LDADD = $(LDADDS)
 | 
			
		||||
testgtk_LDADD = $(LDADDS)
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,21 @@
 | 
			
		||||
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
redraw_event_box (GtkWidget *widget)
 | 
			
		||||
{
 | 
			
		||||
  while (widget)
 | 
			
		||||
    {
 | 
			
		||||
      if (GTK_IS_EVENT_BOX (widget))
 | 
			
		||||
        {
 | 
			
		||||
          gtk_widget_queue_draw (widget);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      widget = gtk_widget_get_parent (widget);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
combo_changed_cb (GtkWidget *combo,
 | 
			
		||||
		  gpointer   data)
 | 
			
		||||
@ -33,33 +48,135 @@ combo_changed_cb (GtkWidget *combo,
 | 
			
		||||
  gint active;
 | 
			
		||||
 | 
			
		||||
  active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
 | 
			
		||||
  
 | 
			
		||||
  gtk_label_set_ellipsize (GTK_LABEL (label), (PangoEllipsizeMode)active);
 | 
			
		||||
  redraw_event_box (label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
scale_changed_cb (GtkRange *range,
 | 
			
		||||
		  gpointer   data)
 | 
			
		||||
{
 | 
			
		||||
  double angle = gtk_range_get_value (range);
 | 
			
		||||
  GtkWidget *label = GTK_WIDGET (data);
 | 
			
		||||
 | 
			
		||||
  gtk_label_set_angle (GTK_LABEL (label), angle);
 | 
			
		||||
  redraw_event_box (label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
ebox_expose_event_cb (GtkWidget      *widget,
 | 
			
		||||
                      GdkEventExpose *event,
 | 
			
		||||
                      gpointer        data)
 | 
			
		||||
{
 | 
			
		||||
  PangoLayout *layout;
 | 
			
		||||
  const double dashes[] = { 6, 18 };
 | 
			
		||||
  GtkRequisition natural_size;
 | 
			
		||||
  GtkWidget *label = data;
 | 
			
		||||
  gint x, y, dx, dy;
 | 
			
		||||
  gchar *markup;
 | 
			
		||||
  cairo_t *cr;
 | 
			
		||||
 | 
			
		||||
  gtk_widget_translate_coordinates (label, widget, 0, 0, &x, &y);
 | 
			
		||||
 | 
			
		||||
  cr = gdk_cairo_create (widget->window);
 | 
			
		||||
  cairo_translate (cr, -0.5, -0.5);
 | 
			
		||||
  cairo_set_line_width (cr, 1);
 | 
			
		||||
 | 
			
		||||
  cairo_rectangle (cr,
 | 
			
		||||
                   x + 0.5 * (label->allocation.width - label->requisition.width),
 | 
			
		||||
                   y + 0.5 * (label->allocation.height - label->requisition.height),
 | 
			
		||||
                   label->requisition.width, label->requisition.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);
 | 
			
		||||
 | 
			
		||||
  gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (label),
 | 
			
		||||
                                        NULL, &natural_size);
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  markup = g_strdup_printf (
 | 
			
		||||
    "<span color='#c33'>\342\200\242 requisition:\t%dx%d</span>\n"
 | 
			
		||||
    "<span color='#3c3'>\342\200\242 natural size:\t%dx%d</span>\n"
 | 
			
		||||
    "<span color='#33c'>\342\200\242 allocation:\t%dx%d</span>",
 | 
			
		||||
    label->requisition.width, label->requisition.height,
 | 
			
		||||
    natural_size.width, natural_size.height,
 | 
			
		||||
    label->allocation.width, label->allocation.height);
 | 
			
		||||
 | 
			
		||||
  layout = gtk_widget_create_pango_layout (widget, NULL);
 | 
			
		||||
  pango_layout_set_markup (layout, markup, -1);
 | 
			
		||||
  pango_layout_get_pixel_size (layout, &dx, &dy);
 | 
			
		||||
 | 
			
		||||
  g_free (markup);
 | 
			
		||||
 | 
			
		||||
  cairo_translate (cr, 0, widget->allocation.height - dy - 8);
 | 
			
		||||
 | 
			
		||||
  cairo_set_source_rgba (cr, 1, 1, 1, 0.8);
 | 
			
		||||
  cairo_rectangle (cr, 0, 0, dx + 12, dy + 8);
 | 
			
		||||
  cairo_fill (cr);
 | 
			
		||||
 | 
			
		||||
  cairo_translate (cr, 6, 4);
 | 
			
		||||
  pango_cairo_show_layout (cr, layout);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (layout);
 | 
			
		||||
  cairo_destroy (cr);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  GtkWidget *window, *vbox, *hbox, *label, *combo;
 | 
			
		||||
  GtkWidget *window, *vbox, *label;
 | 
			
		||||
  GtkWidget *combo, *scale, *align, *ebox;
 | 
			
		||||
 | 
			
		||||
  gtk_init (&argc, &argv);
 | 
			
		||||
 | 
			
		||||
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
			
		||||
  gtk_container_set_border_width (GTK_CONTAINER (window), 12);
 | 
			
		||||
  gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
 | 
			
		||||
  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
 | 
			
		||||
  vbox = gtk_vbox_new (0, FALSE);
 | 
			
		||||
 | 
			
		||||
  vbox = gtk_vbox_new (FALSE, 6);
 | 
			
		||||
  gtk_container_add (GTK_CONTAINER (window), vbox);
 | 
			
		||||
  hbox = gtk_hbox_new (0, FALSE);
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 | 
			
		||||
  label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
  combo = gtk_combo_box_new_text ();
 | 
			
		||||
  scale = gtk_hscale_new_with_range (0, 360, 1);
 | 
			
		||||
  label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
 | 
			
		||||
 | 
			
		||||
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "NONE");
 | 
			
		||||
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "START");
 | 
			
		||||
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "MIDDLE");
 | 
			
		||||
  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
 | 
			
		||||
  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
  align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 | 
			
		||||
  gtk_container_add (GTK_CONTAINER (align), label);
 | 
			
		||||
 | 
			
		||||
  ebox = gtk_event_box_new ();
 | 
			
		||||
  gtk_widget_set_app_paintable (ebox, TRUE);
 | 
			
		||||
  gtk_container_add (GTK_CONTAINER (ebox), align);
 | 
			
		||||
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 0);
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 0);
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), ebox, TRUE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
  g_object_set_data (G_OBJECT (label), "combo", combo);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (combo, "changed", G_CALLBACK (combo_changed_cb), label);
 | 
			
		||||
  g_signal_connect (scale, "value-changed", G_CALLBACK (scale_changed_cb), label);
 | 
			
		||||
  g_signal_connect_after (ebox, "expose-event", G_CALLBACK (ebox_expose_event_cb), label);
 | 
			
		||||
 | 
			
		||||
  gtk_widget_show_all (window);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										120
									
								
								tests/testextendedlayout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								tests/testextendedlayout.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
size_group_toggled_cb (GtkToggleButton *button,
 | 
			
		||||
                       GtkSizeGroup    *group)
 | 
			
		||||
{
 | 
			
		||||
  if (gtk_toggle_button_get_active (button))
 | 
			
		||||
    gtk_size_group_set_mode (group, GTK_SIZE_GROUP_HORIZONTAL);
 | 
			
		||||
  else
 | 
			
		||||
    gtk_size_group_set_mode (group, GTK_SIZE_GROUP_NONE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ellipsize_toggled_cb (GtkToggleButton *button,
 | 
			
		||||
                      GtkWidget       *vbox)
 | 
			
		||||
{
 | 
			
		||||
  GList *rows, *row_iter, *cells, *cell_iter;
 | 
			
		||||
  PangoEllipsizeMode mode;
 | 
			
		||||
 | 
			
		||||
  if (gtk_toggle_button_get_active (button))
 | 
			
		||||
    mode = PANGO_ELLIPSIZE_END;
 | 
			
		||||
  else
 | 
			
		||||
    mode = PANGO_ELLIPSIZE_NONE;
 | 
			
		||||
 | 
			
		||||
  rows = gtk_container_get_children (GTK_CONTAINER (vbox));
 | 
			
		||||
  for (row_iter = rows; row_iter; row_iter = row_iter->next)
 | 
			
		||||
    {
 | 
			
		||||
      if (!GTK_IS_CONTAINER (row_iter->data))
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      cells = gtk_container_get_children (row_iter->data);
 | 
			
		||||
 | 
			
		||||
      for (cell_iter = cells; cell_iter; cell_iter = cell_iter->next)
 | 
			
		||||
        if (GTK_IS_LABEL (cell_iter->data))
 | 
			
		||||
          gtk_label_set_ellipsize (cell_iter->data, mode);
 | 
			
		||||
 | 
			
		||||
      g_list_free (cells);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (rows);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int   argc,
 | 
			
		||||
      char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  GtkWidget *window, *vbox, *button;
 | 
			
		||||
  GtkSizeGroup *groups[5];
 | 
			
		||||
  gint x, y;
 | 
			
		||||
 | 
			
		||||
  gtk_init (&argc, &argv);
 | 
			
		||||
 | 
			
		||||
  for (x = 0; x < G_N_ELEMENTS (groups); ++x)
 | 
			
		||||
    groups[x] = gtk_size_group_new (GTK_SIZE_GROUP_NONE);
 | 
			
		||||
 | 
			
		||||
  vbox = gtk_vbox_new (FALSE, 6);
 | 
			
		||||
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < 4; ++y)
 | 
			
		||||
    {
 | 
			
		||||
      GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
 | 
			
		||||
 | 
			
		||||
      for (x = 0; x < G_N_ELEMENTS (groups); ++x)
 | 
			
		||||
        {
 | 
			
		||||
          gchar *text = g_strdup_printf ("Label #%.0f.%d", pow(10, y), x + 1);
 | 
			
		||||
          GtkWidget *label = gtk_label_new (text);
 | 
			
		||||
          g_free (text);
 | 
			
		||||
 | 
			
		||||
          text = g_strdup_printf ("label/%d/%d", y, x);
 | 
			
		||||
          gtk_widget_set_name (label, text);
 | 
			
		||||
          g_free (text);
 | 
			
		||||
 | 
			
		||||
          if (1 != x)
 | 
			
		||||
            gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
 | 
			
		||||
          if (x > 0)
 | 
			
		||||
            gtk_box_pack_start (GTK_BOX (hbox), gtk_vseparator_new (), FALSE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, 1 == x, TRUE, 0);
 | 
			
		||||
          gtk_size_group_add_widget (groups[x], label);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
  for (x = 0; x < G_N_ELEMENTS (groups); ++x)
 | 
			
		||||
    {
 | 
			
		||||
      gchar *text = g_strdup_printf ("Size Group #%d", x + 1);
 | 
			
		||||
 | 
			
		||||
      button = gtk_check_button_new_with_label (text);
 | 
			
		||||
      gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
 | 
			
		||||
      g_free (text);
 | 
			
		||||
 | 
			
		||||
      g_signal_connect (button, "toggled", G_CALLBACK (size_group_toggled_cb), groups[x]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, TRUE, 0);
 | 
			
		||||
 | 
			
		||||
  button = gtk_check_button_new_with_label ("Ellipsize");
 | 
			
		||||
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
 | 
			
		||||
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (button, "toggled",
 | 
			
		||||
                    G_CALLBACK (ellipsize_toggled_cb),
 | 
			
		||||
                    vbox);
 | 
			
		||||
 | 
			
		||||
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
			
		||||
  gtk_container_add (GTK_CONTAINER (window), vbox);
 | 
			
		||||
  gtk_widget_show_all (window);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (window, "destroy",
 | 
			
		||||
                    G_CALLBACK (gtk_main_quit),
 | 
			
		||||
                    NULL);
 | 
			
		||||
 | 
			
		||||
  gtk_main ();
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user