コード例 #1
0
ファイル: st-private.c プロジェクト: meetparikh7/gnome-shell
/**
 * _st_actor_get_preferred_height:
 * @actor: a #ClutterActor
 * @for_width: as with clutter_actor_get_preferred_height()
 * @x_fill: %TRUE if @actor will fill its allocation horizontally
 * @min_height_p: as with clutter_actor_get_preferred_height()
 * @natural_height_p: as with clutter_actor_get_preferred_height()
 *
 * Like clutter_actor_get_preferred_height(), but if @x_fill is
 * %FALSE, then it will compute a height request based on the
 * assumption that @actor will be given an allocation no wider than
 * its natural width.
 */
void
_st_actor_get_preferred_height (ClutterActor *actor,
                                gfloat        for_width,
                                gboolean      x_fill,
                                gfloat       *min_height_p,
                                gfloat       *natural_height_p)
{
    if (!x_fill && for_width != -1)
    {
        ClutterRequestMode mode;
        gfloat natural_width;

        mode = clutter_actor_get_request_mode (actor);
        if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
        {
            clutter_actor_get_preferred_width (actor, -1, NULL, &natural_width);
            if (for_width > natural_width)
                for_width = natural_width;
        }
    }

    clutter_actor_get_preferred_height (actor, for_width, min_height_p, natural_height_p);
}
コード例 #2
0
ファイル: st-private.c プロジェクト: meetparikh7/gnome-shell
/**
 * _st_actor_get_preferred_width:
 * @actor: a #ClutterActor
 * @for_height: as with clutter_actor_get_preferred_width()
 * @y_fill: %TRUE if @actor will fill its allocation vertically
 * @min_width_p: as with clutter_actor_get_preferred_width()
 * @natural_width_p: as with clutter_actor_get_preferred_width()
 *
 * Like clutter_actor_get_preferred_width(), but if @y_fill is %FALSE,
 * then it will compute a width request based on the assumption that
 * @actor will be given an allocation no taller than its natural
 * height.
 */
void
_st_actor_get_preferred_width  (ClutterActor *actor,
                                gfloat        for_height,
                                gboolean      y_fill,
                                gfloat       *min_width_p,
                                gfloat       *natural_width_p)
{
    if (!y_fill && for_height != -1)
    {
        ClutterRequestMode mode;
        gfloat natural_height;

        mode = clutter_actor_get_request_mode (actor);
        if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
        {
            clutter_actor_get_preferred_height (actor, -1, NULL, &natural_height);
            if (for_height > natural_height)
                for_height = natural_height;
        }
    }

    clutter_actor_get_preferred_width (actor, for_height, min_width_p, natural_width_p);
}
コード例 #3
0
ファイル: st-scroll-view.c プロジェクト: aldatsa/Cinnamon
static void
st_scroll_view_allocate (ClutterActor          *actor,
                         const ClutterActorBox *box,
                         ClutterAllocationFlags flags)
{
  ClutterActorBox content_box, child_box;
  ClutterActorClass *parent_parent_class;
  gfloat avail_width, avail_height, sb_width, sb_height;
  gboolean hscrollbar_visible, vscrollbar_visible;

  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));

  /* Chain up to the parent's parent class
   *
   * We do this because we do not want StBin to allocate the child, as we
   * give it a different allocation later, depending on whether the scrollbars
   * are visible
   */
  parent_parent_class
    = g_type_class_peek_parent (st_scroll_view_parent_class);

  CLUTTER_ACTOR_CLASS (parent_parent_class)->
  allocate (actor, box, flags);

  st_theme_node_get_content_box (theme_node, box, &content_box);

  avail_width = content_box.x2 - content_box.x1;
  avail_height = content_box.y2 - content_box.y1;

  if (clutter_actor_get_request_mode (actor) == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
    {
      sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), -1);
      sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), sb_width);
    }
  else
    {
      sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), -1);
      sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), sb_height);
    }

  /* Determine what scrollbars are visible. The basic idea of the
   * handling of an automatic scrollbars is that we start off with the
   * assumption that we don't need any scrollbars, see if that works,
   * and if not add horizontal and vertical scrollbars until we are no
   * longer overflowing.
   */
  if (priv->child)
    {
      gfloat child_min_width;
      gfloat child_min_height;

      clutter_actor_get_preferred_width (priv->child, -1,
                                         &child_min_width, NULL);

      if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
        {
          if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
            {
              /* Pass one, try without a vertical scrollbar */
              clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL);
              vscrollbar_visible = child_min_height > avail_height;
              hscrollbar_visible = child_min_width > avail_width - (vscrollbar_visible ? sb_width : 0);
              vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0);

              /* Pass two - if we needed a vertical scrollbar, get a new preferred height */
              if (vscrollbar_visible)
                {
                  clutter_actor_get_preferred_height (priv->child, MAX (avail_width - sb_width, 0),
                                                      &child_min_height, NULL);
                  hscrollbar_visible = child_min_width > avail_width - sb_width;
                }
            }
          else
            {
              hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;

              /* try without a vertical scrollbar */
              clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL);
              vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0);
            }
        }
      else
        {
          vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;

          if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
            hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width);
          else
            hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
        }
    }
  else
    {
      hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
      vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
    }

  /* Whether or not we show the scrollbars, if the scrollbars are visible
   * actors, we need to give them some allocation, so we unconditionally
   * give them the "right" allocation; that might overlap the child when
   * the scrollbars are not visible, but it doesn't matter because we
   * don't include them in pick or paint.
   */

  /* Vertical scrollbar */
  if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
    {
      if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL)
        {
          child_box.x1 = content_box.x1;
          child_box.x2 = content_box.x1 + sb_width;
        }
      else
        {
          child_box.x1 = content_box.x2 - sb_width;
          child_box.x2 = content_box.x2;
        }
      child_box.y1 = content_box.y1;
      child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0);

      clutter_actor_allocate (priv->vscroll, &child_box, flags);
    }

  /* Horizontal scrollbar */
  if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll))
    {
      if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL)
        {
          child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0);
          child_box.x2 = content_box.x2;
        }
      else
        {
          child_box.x1 = content_box.x1;
          child_box.x2 = content_box.x2 - (vscrollbar_visible ? sb_width : 0);
        }
      child_box.y1 = content_box.y2 - sb_height;
      child_box.y2 = content_box.y2;

      clutter_actor_allocate (priv->hscroll, &child_box, flags);
    }

  /* Now fold visibility into the scrollbar sizes to simplify the rest
   * of the computations.
   */
  if (!hscrollbar_visible)
    sb_height = 0;
  if (!vscrollbar_visible)
    sb_width = 0;

  /* Child */
  if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL)
    {
      child_box.x1 = content_box.x1 + sb_width;
      child_box.x2 = content_box.x2;
    }
  else
    {
      child_box.x1 = content_box.x1;
      child_box.x2 = content_box.x2 - sb_width;
    }
  child_box.y1 = content_box.y1;
  child_box.y2 = content_box.y2 - sb_height;

  if (priv->child)
    clutter_actor_allocate (priv->child, &child_box, flags);

  if (priv->hscrollbar_visible != hscrollbar_visible)
    {
      g_object_freeze_notify (G_OBJECT (actor));
      priv->hscrollbar_visible = hscrollbar_visible;
      g_object_notify (G_OBJECT (actor), "hscrollbar-visible");
      g_object_thaw_notify (G_OBJECT (actor));
    }

  if (priv->vscrollbar_visible != vscrollbar_visible)
    {
      g_object_freeze_notify (G_OBJECT (actor));
      priv->vscrollbar_visible = vscrollbar_visible;
      g_object_notify (G_OBJECT (actor), "vscrollbar-visible");
      g_object_thaw_notify (G_OBJECT (actor));
    }

}
コード例 #4
0
static void
mx_stack_allocate (ClutterActor           *actor,
                   const ClutterActorBox  *box,
                   ClutterAllocationFlags  flags)
{
  GList *c;
  ClutterActorBox avail_space;

  MxStackPrivate *priv = MX_STACK (actor)->priv;

  CLUTTER_ACTOR_CLASS (mx_stack_parent_class)->allocate (actor, box, flags);

  mx_widget_get_available_area (MX_WIDGET (actor), box, &avail_space);

  memcpy (&priv->allocation, box, sizeof (priv->allocation));

  for (c = priv->children; c; c = c->next)
    {
      gboolean x_fill, y_fill, fit, crop;
      MxAlign x_align, y_align;

      ClutterActor *child = c->data;
      ClutterActorBox child_box = avail_space;

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      clutter_container_child_get (CLUTTER_CONTAINER (actor),
                                   child,
                                   "x-fill", &x_fill,
                                   "y-fill", &y_fill,
                                   "x-align", &x_align,
                                   "y-align", &y_align,
                                   "fit", &fit,
                                   "crop", &crop,
                                   NULL);

      /* when "crop" is set, fit and fill properties are ignored */
      if (crop)
        {
          gfloat available_height, available_width;
          gfloat natural_width, natural_height;
          gfloat ratio_width, ratio_height, ratio_child;

          available_width  = avail_space.x2 - avail_space.x1;
          available_height = avail_space.y2 - avail_space.y1;

          clutter_actor_get_preferred_size (child,
                                            NULL, NULL,
                                            &natural_width,
                                            &natural_height);

          ratio_child = natural_width / natural_height;
          ratio_width = available_width / natural_width;
          ratio_height = available_height / natural_height;
          if (ratio_width > ratio_height)
            {
              natural_width = available_width;
              natural_height = natural_width / ratio_child;
            }
          else
            {
              natural_height = available_height;
              natural_width = ratio_child * natural_height;
            }

          child_box.x1 = (available_width - natural_width) / 2;
          child_box.y1 = (available_height - natural_height) / 2;
          child_box.x2 = natural_width;
          child_box.y2 = natural_height;

          clutter_actor_allocate (child, &child_box, flags);
          continue;
        }

      /* when "fit" is set, fill properties are ignored */
      if (fit)
        {
          gfloat available_height, available_width, width, height;
          gfloat min_width, natural_width, min_height, natural_height;
          ClutterRequestMode request_mode;

          available_height = avail_space.y2 - avail_space.y1;
          available_width  = avail_space.x2 - avail_space.x1;
          request_mode = clutter_actor_get_request_mode (child);

          if (request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
            {
              clutter_actor_get_preferred_width (child, available_height,
                                                 &min_width,
                                                 &natural_width);
              width = CLAMP (natural_width, min_width, available_width);

              clutter_actor_get_preferred_height (child, width,
                                                  &min_height,
                                                  &natural_height);
              height = CLAMP (natural_height, min_height, available_height);
            }
          else
            {
              clutter_actor_get_preferred_height (child, available_width,
                                                  &min_height,
                                                  &natural_height);
              height = CLAMP (natural_height, min_height, available_height);

              clutter_actor_get_preferred_width (child, height,
                                                 &min_width,
                                                 &natural_width);
              width = CLAMP (natural_width, min_width, available_width);
            }

          child_box.x1 = 0;
          child_box.y1 = 0;

          switch (x_align)
            {
            case MX_ALIGN_START:
              break;
            case MX_ALIGN_MIDDLE:
              child_box.x1 += (gint)(available_width / 2 - width / 2);
              break;

            case MX_ALIGN_END:
              child_box.x1 = avail_space.x2 - width;
              break;
            }

          switch (y_align)
            {
            case MX_ALIGN_START:
              break;
            case MX_ALIGN_MIDDLE:
              child_box.y1 += (gint)(available_height / 2 - height / 2);
              break;

            case MX_ALIGN_END:
              child_box.y1 = avail_space.y2 - height;
              break;
            }

          child_box.x2 = child_box.x1 + width;
          child_box.y2 = child_box.y1 + height;

          clutter_actor_allocate (child, &child_box, flags);
          continue;
        }

      /* Adjust the available space when not filling, otherwise
       * actors that support width-for-height or height-for-width
       * allocation won't shrink correctly.
       */
      if (!x_fill)
        {
          gfloat width;

          clutter_actor_get_preferred_width (child, -1, NULL, &width);

          switch (x_align)
            {
            case MX_ALIGN_START:
              break;
            case MX_ALIGN_MIDDLE:
              child_box.x1 += (gint)((avail_space.x2 - avail_space.x1) / 2 -
                                     width / 2);
              break;

            case MX_ALIGN_END:
              child_box.x1 = avail_space.x2 - width;
              break;
            }

          child_box.x2 = child_box.x1 + width;
          if (child_box.x2 > avail_space.x2)
            child_box.x2 = avail_space.x2;
          if (child_box.x1 < avail_space.x1)
            child_box.x1 = avail_space.x1;
        }

      if (!y_fill)
        {
          gfloat height;

          clutter_actor_get_preferred_height (child, -1, NULL, &height);

          switch (y_align)
            {
            case MX_ALIGN_START:
              break;
            case MX_ALIGN_MIDDLE:
              child_box.y1 += (gint)((avail_space.y2 - avail_space.y1) / 2 -
                                     height / 2);
              break;

            case MX_ALIGN_END:
              child_box.y1 = avail_space.y2 - height;
              break;
            }

          child_box.y2 = child_box.y1 + height;
          if (child_box.y2 > avail_space.y2)
            child_box.y2 = avail_space.y2;
          if (child_box.y1 < avail_space.y1)
            child_box.y1 = avail_space.y1;
        }

      mx_allocate_align_fill (child,
                              &child_box,
                              x_align,
                              y_align,
                              x_fill,
                              y_fill);

      clutter_actor_allocate (child, &child_box, flags);
    }
}
コード例 #5
0
ファイル: st-private.c プロジェクト: 2gud4u/Cinnamon
/**
 * _st_allocate_fill:
 * @parent: the parent #StWidget
 * @child: the child (not necessarily an #StWidget)
 * @childbox: total space that could be allocated to @child
 * @x_alignment: horizontal alignment within @childbox
 * @y_alignment: vertical alignment within @childbox
 * @x_fill: whether or not to fill @childbox horizontally
 * @y_fill: whether or not to fill @childbox vertically
 *
 * Given @childbox, containing the initial allocation of @child, this
 * adjusts the horizontal allocation if @x_fill is %FALSE, and the
 * vertical allocation if @y_fill is %FALSE, by:
 *
 *     - reducing the allocation if it is larger than @child's natural
 *       size.
 *
 *     - adjusting the position of the child within the allocation
 *       according to @x_alignment/@y_alignment (and flipping
 *       @x_alignment if @parent has %ST_TEXT_DIRECTION_RTL)
 *
 * If @x_fill and @y_fill are both %TRUE, or if @child's natural size
 * is larger than the initial allocation in @childbox, then @childbox
 * will be unchanged.
 *
 * If you are allocating children with _st_allocate_fill(), you should
 * determine their preferred sizes using
 * _st_actor_get_preferred_width() and
 * _st_actor_get_preferred_height(), not with the corresponding
 * Clutter methods.
 */
void
_st_allocate_fill (StWidget        *parent,
                   ClutterActor    *child,
                   ClutterActorBox *childbox,
                   StAlign          x_alignment,
                   StAlign          y_alignment,
                   gboolean         x_fill,
                   gboolean         y_fill)
{
  gfloat natural_width, natural_height;
  gfloat min_width, min_height;
  gfloat child_width, child_height;
  gfloat available_width, available_height;
  ClutterRequestMode request;
  gdouble x_align, y_align;

  available_width  = childbox->x2 - childbox->x1;
  available_height = childbox->y2 - childbox->y1;

  if (available_width < 0)
    {
      available_width = 0;
      childbox->x2 = childbox->x1;
    }

  if (available_height < 0)
    {
      available_height = 0;
      childbox->y2 = childbox->y1;
    }

  /* If we are filling both horizontally and vertically then we don't
   * need to do anything else.
   */
  if (x_fill && y_fill)
    return;

  _st_get_align_factors (parent, x_alignment, y_alignment,
                         &x_align, &y_align);

  /* The following is based on clutter_actor_get_preferred_size(), but
   * modified to cope with the fact that the available size may be
   * less than the preferred size.
   */
  request = clutter_actor_get_request_mode (child);

  if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
    {
      clutter_actor_get_preferred_width (child, -1,
                                         &min_width,
                                         &natural_width);

      child_width = CLAMP (natural_width, min_width, available_width);

      clutter_actor_get_preferred_height (child, child_width,
                                          &min_height,
                                          &natural_height);

      child_height = CLAMP (natural_height, min_height, available_height);
    }
  else
    {
      clutter_actor_get_preferred_height (child, -1,
                                          &min_height,
                                          &natural_height);

      child_height = CLAMP (natural_height, min_height, available_height);

      clutter_actor_get_preferred_width (child, child_height,
                                         &min_width,
                                         &natural_width);

      child_width = CLAMP (natural_width, min_width, available_width);
    }

  if (!x_fill)
    {
      childbox->x1 += (int)((available_width - child_width) * x_align);
      childbox->x2 = childbox->x1 + (int) child_width;
    }

  if (!y_fill)
    {
      childbox->y1 += (int)((available_height - child_height) * y_align);
      childbox->y2 = childbox->y1 + (int) child_height;
    }
}
コード例 #6
0
/* Updates the minimum number of rows and columns needed for layout */
static void _xfdashboard_scaled_table_layout_update_rows_and_columns(XfdashboardScaledTableLayout *self,
        ClutterContainer *inContainer)
{
    XfdashboardScaledTableLayoutPrivate		*priv;
    ClutterRequestMode						requestMode;
    ClutterActorIter						iter;
    ClutterActor							*child;
    gint									numberChildren;
    gint									rows;
    gint									columns;

    g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self));
    g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
    g_return_if_fail(CLUTTER_IS_ACTOR(inContainer));

    priv=self->priv;

    /* Freeze notification */
    g_object_freeze_notify(G_OBJECT(self));

    /* Get number of visible child actors */
    numberChildren=0;
    clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
    while(clutter_actor_iter_next(&iter, &child))
    {
        if(CLUTTER_ACTOR_IS_VISIBLE(child)) numberChildren++;
    }

    if(numberChildren!=priv->numberChildren)
    {
        priv->numberChildren=numberChildren;
        g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_NUMBER_CHILDREN]);
    }

    /* Get request mode to determine if more rows than colums are needed
     * or the opposite
     */
    requestMode=clutter_actor_get_request_mode(CLUTTER_ACTOR(inContainer));

    /* Calculate and update number of rows and columns */
    if(requestMode==CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
    {
        rows=ceil(sqrt((double)priv->numberChildren));
        columns=ceil((double)priv->numberChildren / (double)priv->rows);
    }
    else
    {
        columns=ceil(sqrt((double)priv->numberChildren));
        rows=ceil((double)priv->numberChildren / (double)priv->columns);
    }

    if(rows!=priv->rows)
    {
        priv->rows=rows;
        g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_ROWS]);
    }

    if(columns!=priv->columns)
    {
        priv->columns=columns;
        g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_COLUMNS]);
    }

    /* Thaw notification */
    g_object_thaw_notify(G_OBJECT(self));
}