Exemple #1
0
/**
 * gtk_size_group_add_widget:
 * @size_group: a #GtkSizeGroup
 * @widget: the #GtkWidget to add
 * 
 * Adds a widget to a #GtkSizeGroup. In the future, the requisition
 * of the widget will be determined as the maximum of its requisition
 * and the requisition of the other widgets in the size group.
 * Whether this applies horizontally, vertically, or in both directions
 * depends on the mode of the size group. See gtk_size_group_set_mode().
 *
 * When the widget is destroyed or no longer referenced elsewhere, it will 
 * be removed from the size group.
 */
void
gtk_size_group_add_widget (GtkSizeGroup     *size_group,
			   GtkWidget        *widget)
{
  GtkSizeGroupPrivate *priv;
  GSList *groups;
  
  g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
  g_return_if_fail (GTK_IS_WIDGET (widget));

  priv = size_group->priv;

  groups = _gtk_widget_get_sizegroups (widget);

  if (!g_slist_find (groups, size_group))
    {
      _gtk_widget_add_sizegroup (widget, size_group);

      priv->widgets = g_slist_prepend (priv->widgets, widget);

      g_signal_connect (widget, "destroy",
			G_CALLBACK (gtk_size_group_widget_destroyed),
			size_group);

      g_object_ref (size_group);
    }
  
  queue_resize_on_group (size_group);
}
Exemple #2
0
static void
add_widget_to_closure (GHashTable     *widgets,
                       GHashTable     *groups,
                       GtkWidget      *widget,
		       GtkOrientation  orientation)
{
  GSList *tmp_groups, *tmp_widgets;
  gboolean hidden;

  if (g_hash_table_lookup (widgets, widget))
    return;

  g_hash_table_add (widgets, widget);
  hidden = !gtk_widget_is_visible (widget);

  for (tmp_groups = _gtk_widget_get_sizegroups (widget); tmp_groups; tmp_groups = tmp_groups->next)
    {
      GtkSizeGroup        *tmp_group = tmp_groups->data;
      GtkSizeGroupPrivate *tmp_priv  = tmp_group->priv;

      if (g_hash_table_lookup (groups, tmp_group))
        continue;

      if (tmp_priv->ignore_hidden && hidden)
        continue;

      if (!(tmp_priv->mode & (1 << orientation)))
        continue;

      g_hash_table_add (groups, tmp_group);

      for (tmp_widgets = tmp_priv->widgets; tmp_widgets; tmp_widgets = tmp_widgets->next)
        add_widget_to_closure (widgets, groups, tmp_widgets->data, orientation);
    }
}
Exemple #3
0
/* This is the main function that checks for a cached size and
 * possibly queries the widget class to compute the size if it's
 * not cached. If the for_size here is -1, then get_preferred_width()
 * or get_preferred_height() will be used.
 */
void
_gtk_widget_compute_size_for_orientation (GtkWidget        *widget,
                                          GtkOrientation    orientation,
                                          gint              for_size,
                                          gint             *minimum,
                                          gint             *natural)
{
  GHashTable *widgets;
  GHashTableIter iter;
  gpointer key;
  gint    min_result = 0, nat_result = 0;

  if (!gtk_widget_get_visible (widget) && !gtk_widget_is_toplevel (widget))
    {
      if (minimum)
        *minimum = 0;
      if (natural)
        *natural = 0;
      return;
    }

  if (G_LIKELY (!_gtk_widget_get_sizegroups (widget)))
    {
      gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural);
      return;
    }

  widgets = _gtk_size_group_get_widget_peers (widget, orientation);

  g_hash_table_foreach (widgets, (GHFunc) g_object_ref, NULL);
  
  g_hash_table_iter_init (&iter, widgets);
  while (g_hash_table_iter_next (&iter, &key, NULL))
    {
      GtkWidget *tmp_widget = key;
      gint min_dimension, nat_dimension;

      gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension, &nat_dimension);

      min_result = MAX (min_result, min_dimension);
      nat_result = MAX (nat_result, nat_dimension);
    }

  g_hash_table_foreach (widgets, (GHFunc) g_object_unref, NULL);

  g_hash_table_destroy (widgets);

  if (minimum)
    *minimum = min_result;

  if (natural)
    *natural = nat_result;
}
Exemple #4
0
/**
 * _gtk_size_group_bump_requisition:
 * @widget: a #GtkWidget
 * @mode: either %GTK_SIZE_GROUP_HORIZONTAL or %GTK_SIZE_GROUP_VERTICAL, depending
 *        on the dimension in which to bump the size.
 * @minimum: a pointer to the widget's minimum size
 * @natural: a pointer to the widget's natural size
 *
 * Refreshes the sizegroup while returning the groups requested
 * value in the dimension @mode.
 *
 * This function is used both to update sizegroup minimum and natural size 
 * information and widget minimum and natural sizes in multiple passes from 
 * the size request apis.
 */
void
_gtk_size_group_bump_requisition (GtkWidget        *widget,
				  GtkSizeGroupMode  mode,
				  gint             *minimum,
				  gint             *natural)
{
  if (!_gtk_widget_get_sizegroup_bumping (widget))
    {
      /* Avoid recursion here */
      _gtk_widget_set_sizegroup_bumping (widget, TRUE);

      if (_gtk_widget_get_sizegroups (widget))
	compute_dimension (widget, mode, minimum, natural);

      _gtk_widget_set_sizegroup_bumping (widget, FALSE);
    }
}
Exemple #5
0
static void
add_widget_to_closure (GtkWidget       *widget,
		       GtkSizeGroupMode mode,
		       GSList         **groups,
		       GSList         **widgets)
{
  GSList *tmp_groups;

  *widgets = g_slist_prepend (*widgets, widget);
  _gtk_widget_set_sizegroup_visited (widget, TRUE);

  tmp_groups = _gtk_widget_get_sizegroups (widget);
  while (tmp_groups)
    {
      GtkSizeGroup        *tmp_group = tmp_groups->data;
      GtkSizeGroupPrivate *tmp_priv  = tmp_group->priv;

      if ((tmp_priv->mode == GTK_SIZE_GROUP_BOTH || tmp_priv->mode == mode) &&
	  !tmp_group->priv->visited)
	add_group_to_closure (tmp_group, mode, groups, widgets);

      tmp_groups = tmp_groups->next;
    }
}
Exemple #6
0
static void
queue_resize_on_widget (GtkWidget          *widget,
			gboolean            check_siblings,
			GtkQueueResizeFlags flags)
{
  GtkWidget *parent = widget;
  GSList *tmp_list;

  while (parent)
    {
      GSList *widget_groups;
      GSList *groups;
      GSList *widgets;
      
      if (widget == parent && !check_siblings)
	{
	  real_queue_resize (widget, flags);
          parent = gtk_widget_get_parent (parent);
	  continue;
	}
      
      widget_groups = _gtk_widget_get_sizegroups (parent);
      if (!widget_groups)
	{
	  if (widget == parent)
	    real_queue_resize (widget, flags);

          parent = gtk_widget_get_parent (parent);
	  continue;
	}

      groups = NULL;
      widgets = NULL;
	  
      add_widget_to_closure (parent, GTK_SIZE_GROUP_HORIZONTAL, &groups, &widgets);
      g_slist_foreach (widgets, (GFunc)mark_widget_unvisited, NULL);
      g_slist_foreach (groups, (GFunc)mark_group_unvisited, NULL);

      reset_group_sizes (groups);
	      
      tmp_list = widgets;
      while (tmp_list)
	{
	  if (tmp_list->data == parent)
	    {
	      if (widget == parent)
		real_queue_resize (parent, flags);
	    }
	  else if (tmp_list->data == widget)
            {
              g_warning ("A container and its child are part of this SizeGroup");
            }
	  else
	    queue_resize_on_widget (tmp_list->data, FALSE, flags);

	  tmp_list = tmp_list->next;
	}
      
      g_slist_free (widgets);
      g_slist_free (groups);
	      
      groups = NULL;
      widgets = NULL;
	      
      add_widget_to_closure (parent, GTK_SIZE_GROUP_VERTICAL, &groups, &widgets);
      g_slist_foreach (widgets, (GFunc)mark_widget_unvisited, NULL);
      g_slist_foreach (groups, (GFunc)mark_group_unvisited, NULL);

      reset_group_sizes (groups);
	      
      tmp_list = widgets;
      while (tmp_list)
	{
	  if (tmp_list->data == parent)
	    {
	      if (widget == parent)
		real_queue_resize (parent, flags);
	    }
	  else if (tmp_list->data == widget)
            {
              g_warning ("A container and its child are part of this SizeGroup");
            }
	  else
	    queue_resize_on_widget (tmp_list->data, FALSE, flags);

	  tmp_list = tmp_list->next;
	}
      
      g_slist_free (widgets);
      g_slist_free (groups);

      parent = gtk_widget_get_parent (parent);
    }
}
Exemple #7
0
static void
queue_resize_on_widget (GtkWidget          *widget,
			gboolean            check_siblings,
			GtkQueueResizeFlags flags)
{
  GtkWidget *parent = widget;

  while (parent)
    {
      GSList *widget_groups;
      GHashTable *widgets;
      GHashTableIter iter;
      gpointer current;
      
      if (widget == parent && !check_siblings)
	{
	  real_queue_resize (widget, flags);
          parent = gtk_widget_get_parent (parent);
	  continue;
	}
      
      widget_groups = _gtk_widget_get_sizegroups (parent);
      if (!widget_groups)
	{
	  if (widget == parent)
	    real_queue_resize (widget, flags);

          parent = gtk_widget_get_parent (parent);
	  continue;
	}

      widgets = _gtk_size_group_get_widget_peers (parent, GTK_ORIENTATION_HORIZONTAL);

      g_hash_table_iter_init (&iter, widgets);
      while (g_hash_table_iter_next (&iter, &current, NULL))
	{
	  if (current == parent)
	    {
	      if (widget == parent)
		real_queue_resize (parent, flags);
	    }
	  else if (current == widget)
            {
              g_warning ("A container and its child are part of this SizeGroup");
            }
	  else
	    queue_resize_on_widget (current, FALSE, flags);
	}
      
      g_hash_table_destroy (widgets);
      
      widgets = _gtk_size_group_get_widget_peers (parent, GTK_ORIENTATION_VERTICAL);

      g_hash_table_iter_init (&iter, widgets);
      while (g_hash_table_iter_next (&iter, &current, NULL))
	{
	  if (current == parent)
	    {
	      if (widget == parent)
		real_queue_resize (parent, flags);
	    }
	  else if (current == widget)
            {
              g_warning ("A container and its child are part of this SizeGroup");
            }
	  else
	    queue_resize_on_widget (current, FALSE, flags);
	}
      
      g_hash_table_destroy (widgets);

      parent = gtk_widget_get_parent (parent);
    }
}