static void
penge_calendar_pane_allocate (ClutterActor          *actor,
                              const ClutterActorBox *box,
                              ClutterAllocationFlags flags)
{
  PengeCalendarPanePrivate *priv = GET_PRIVATE (actor);
  gfloat events_nat_h, tasks_nat_h, events_header_nat_h, tasks_header_nat_h;
  gfloat width, height, remaining_height, last_y;
  gfloat tasks_available_h, events_available_h;
  ClutterActorBox child_box;
  MxPadding padding = { 0, };

  if (CLUTTER_ACTOR_CLASS (penge_calendar_pane_parent_class)->allocate)
    CLUTTER_ACTOR_CLASS (penge_calendar_pane_parent_class)->allocate (actor, box, flags);

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  width = box->x2 - box->x1;
  height = box->y2 - box->y1;

  clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->events_header_table),
                                      width,
                                      NULL,
                                      &events_header_nat_h);

  clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->events_pane),
                                      width,
                                      NULL,
                                      &events_nat_h);

  clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->tasks_header_table),
                                      width,
                                      NULL,
                                      &tasks_header_nat_h);

  clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->tasks_pane),
                                      width,
                                      NULL,
                                      &tasks_nat_h);

  child_box.x1 = padding.left;
  child_box.x2 = width - padding.right;
  child_box.y1 = padding.top;
  child_box.y2 = child_box.y1 + events_header_nat_h;
  last_y = child_box.y2;
  clutter_actor_allocate (CLUTTER_ACTOR (priv->events_header_table),
                          &child_box,
                          flags);

  remaining_height = height - padding.top - padding.bottom -
                     events_header_nat_h - tasks_header_nat_h;

  if (tasks_nat_h <= (remaining_height / 2.0))
  {
    tasks_available_h = tasks_nat_h;
  } else {
    tasks_available_h = (remaining_height / 2.0);
  }

  events_available_h = remaining_height - tasks_available_h;
  if (events_available_h > events_nat_h)
  {
    tasks_available_h += (tasks_available_h - events_nat_h);
    events_available_h = events_nat_h;
  }

  child_box.x1 = padding.left;
  child_box.x2 = width - padding.right;
  child_box.y1 = last_y;
  child_box.y2 = child_box.y1 + (int)events_available_h;
  last_y = child_box.y2;

  clutter_actor_allocate (CLUTTER_ACTOR (priv->events_pane),
                          &child_box,
                          flags);

  child_box.x1 = padding.left;
  child_box.x2 = width - padding.right;
  child_box.y1 = last_y;
  child_box.y2 = child_box.y1 + tasks_header_nat_h;
  last_y = child_box.y2;
  clutter_actor_allocate (CLUTTER_ACTOR (priv->tasks_header_table),
                          &child_box,
                          flags);


  child_box.x1 = padding.left;
  child_box.x2 = width - padding.right;
  child_box.y1 = last_y;
  child_box.y2 = child_box.y1 + (int)tasks_available_h;

  clutter_actor_allocate (CLUTTER_ACTOR (priv->tasks_pane),
                          &child_box,
                          flags);

}
Beispiel #2
0
static void
st_table_homogeneous_allocate (ClutterActor          *self,
                               const ClutterActorBox *content_box,
                               gboolean               flags)
{
  GList *list, *children;
  gfloat col_width, row_height;
  gint row_spacing, col_spacing;
  StTablePrivate *priv = ST_TABLE (self)->priv;
  gboolean ltr = st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR;

  col_spacing = priv->col_spacing;
  row_spacing = priv->row_spacing;

  col_width = (int) ((content_box->x2 - content_box->x1
                      - (col_spacing * (priv->n_cols - 1)))
                     / priv->n_cols + 0.5);
  row_height = (int) ((content_box->y2 - content_box->y1
                      - (row_spacing * (priv->n_rows - 1)))
                      / priv->n_rows + 0.5);

  children = st_container_get_children_list (ST_CONTAINER (self));
  for (list = children; list; list = list->next)
    {
      gint row, col, row_span, col_span;
      StTableChild *meta;
      ClutterActor *child;
      ClutterActorBox childbox;
      StAlign x_align, y_align;
      gboolean x_fill, y_fill;

      child = CLUTTER_ACTOR (list->data);

      meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child);

      if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      /* get child properties */
      col = meta->col;
      row = meta->row;
      row_span = meta->row_span;
      col_span = meta->col_span;
      x_align = meta->x_align;
      y_align = meta->y_align;
      x_fill = meta->x_fill;
      y_fill = meta->y_fill;

      if (ltr)
        {
          childbox.x1 = content_box->x1 + (col_width + col_spacing) * col;
          childbox.x2 = childbox.x1 + (col_width * col_span) + (col_spacing * (col_span - 1));
        }
      else
        {
          childbox.x2 = content_box->x2 - (col_width + col_spacing) * col;
          childbox.x1 = childbox.x2 - (col_width * col_span) - (col_spacing * (col_span - 1));
        }

      childbox.y1 = content_box->y1 + (row_height + row_spacing) * row;
      childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1));

      _st_allocate_fill (ST_WIDGET (self), child, &childbox,
                         x_align, y_align, x_fill, y_fill);

      clutter_actor_allocate (child, &childbox, flags);
    }

}
Beispiel #3
0
static void
mx_combo_box_allocate (ClutterActor          *actor,
                       const ClutterActorBox *box,
                       ClutterAllocationFlags flags)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv;
  MxPadding padding;
  gfloat x, y, width, height;
  gfloat min_menu_h, nat_menu_h;
  gfloat label_h;
  gfloat nat_icon_h, icon_h, icon_w;
  gfloat nat_marker_h, marker_h, marker_w;
  ClutterActorBox childbox;
  ClutterActor *menu, *stage;

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

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  x = padding.left;
  y = padding.top;
  width = box->x2 - box->x1 - padding.left - padding.right;
  height = box->y2 - box->y1 - padding.top - padding.bottom;

  icon_w = marker_w = 0;

  if (priv->icon)
    {
      /* Allocate the icon, if there is one, the space not used by the text */
      clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h);

      if (height >= nat_icon_h)
        {
          icon_h = nat_icon_h;
          clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w);
        }
      else
        {
          icon_h = height;
          clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w);
        }

      childbox.x1 = (int)(x);
      childbox.y1 = (int)(y + (height - icon_h) / 2);
      childbox.x2 = (int)(x + icon_w);
      childbox.y2 = (int)(childbox.y1 + icon_h);

      clutter_actor_allocate (priv->icon, &childbox, flags);

      icon_w += priv->spacing;
    }

  if (priv->marker)
    {
      clutter_actor_get_preferred_height (priv->marker, -1,
                                          NULL, &nat_marker_h);

      if (height >= nat_marker_h)
        {
          marker_h = nat_marker_h;
          clutter_actor_get_preferred_width (priv->marker, -1, NULL,
                                             &marker_w);
        }
      else
        {
          marker_h = height;
          clutter_actor_get_preferred_width (priv->marker, marker_h,
                                             NULL, &marker_w);
        }

      childbox.x2 = (int)(x + width);
      childbox.x1 = (int)(childbox.x2 - marker_w);
      childbox.y1 = (int)(y + (height - marker_h) / 2);
      childbox.y2 = (int)(childbox.y1 + marker_h);

      clutter_actor_allocate (priv->marker, &childbox, flags);

      marker_w += priv->spacing;
    }

  clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h);

  childbox.x1 = (int)(x + icon_w);
  childbox.y1 = (int)(y + (height / 2 - label_h / 2));
  childbox.x2 = (int)(x + width - marker_w);
  childbox.y2 = (int)(childbox.y1 + label_h);
  clutter_actor_allocate (priv->label, &childbox, flags);

  menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor));
  clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h,
                                      &nat_menu_h);

  childbox.x1 = 0;
  childbox.x2 = (box->x2 - box->x1);
  childbox.y1 = (box->y2 - box->y1);

  childbox.y2 = childbox.y1 + nat_menu_h;

  stage = clutter_actor_get_stage (actor);
  if (stage != NULL)
    {
      ClutterVertex point = { 0, };
      gfloat stage_w, stage_h, combo_h = box->y2 - box->y1;

      clutter_actor_get_size (stage, &stage_w, &stage_h);
      point.y = combo_h + nat_menu_h;
      clutter_actor_apply_transform_to_point (actor, &point, &point);

      /* If the menu would appear off the stage, flip it around. */
      if ((point.y < 0) || (point.y >= stage_h))
        {
          childbox.y1 = -nat_menu_h;
          point.y = -nat_menu_h;
          clutter_actor_apply_transform_to_point (actor, &point, &point);
          /* if the menu would still appear out of the stage, force
           * it to appear on the top of the stage.
           */
          if (point.y < 0)
            {
              gfloat xactor, yactor;
              clutter_actor_get_transformed_position (actor, &xactor,
                                                      &yactor);
              childbox.y1 = -yactor;
            }
        }

      point.y = childbox.y1 + nat_menu_h;
      clutter_actor_apply_transform_to_point (actor, &point, &point);
      if (point.y >= stage_h)
        {
          gfloat xactor, yactor;
          clutter_actor_get_transformed_position (actor, &xactor, &yactor);
          /*
           * clamp so that the menu doesn't appear out of the screen
           */
          clutter_actor_transform_stage_point (actor, xactor, stage_h,
                                               NULL, &childbox.y2);
          /*
           * The previous transformation can lead to negative height
           * allocation if the top-left corner of the menu is already
           * flipped around. This happens when you put a combobox deep
           * enough in a scrollview taller that the stage.
           */
          childbox.y2 = MAX (childbox.y1, childbox.y2);
        }
      else
        {
          childbox.y2 = childbox.y1 + nat_menu_h;
        }

    }
  clutter_actor_allocate (menu, &childbox, flags);
}
Beispiel #4
0
static void
st_scroll_view_allocate (ClutterActor          *actor,
                         const ClutterActorBox *box,
                         ClutterAllocationFlags flags)
{
  ClutterActorBox content_box, child_box;
  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));

  clutter_actor_set_allocation (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_get_text_direction (actor) == CLUTTER_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_get_text_direction (actor) == CLUTTER_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);

  /* In case the scrollbar policy is NEVER or scrollbars should be
   * overlayed, we don't trim the content box allocation by the
   * scrollbar size.
   * Fold this into the scrollbar sizes to simplify the rest of the
   * computations.
   */
  if (priv->hscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
    sb_height = 0;
  if (priv->vscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
    sb_width = 0;

  /* Child */
  if (clutter_actor_get_text_direction (actor) == CLUTTER_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));
    }

}
Beispiel #5
0
static void
mex_column_allocate (ClutterActor          *actor,
                     const ClutterActorBox *box,
                     ClutterAllocationFlags flags)
{
  ClutterActorBox child_box;
  MxPadding padding;
  GList *c;

  MexColumn *column = MEX_COLUMN (actor);
  MexColumnPrivate *priv = column->priv;

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

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  child_box.x1 = padding.left;
  child_box.x2 = box->x2 - box->x1 - padding.right;
  child_box.y1 = padding.top;
  child_box.y2 = box->y2 - box->y1 - padding.bottom;

  if (priv->n_items)
    {
      /* Calculate child height multiplier */
      gfloat width, pref_height, avail_height, ratio, remainder;

      if (!priv->adjustment)
        {
          /* Find out the height available for each actor as a ratio of
           * their preferred height.
           */
          clutter_actor_get_preferred_height (actor, box->x2 - box->x1,
                                              NULL, &pref_height);
          pref_height -= padding.top + padding.bottom;

          avail_height = child_box.y2 - child_box.y1;

          ratio = avail_height / pref_height;
        }
      else
        ratio = 1;

      /* Allocate children */
      remainder = 0;
      width = child_box.x2 - child_box.x1;

      for (c = priv->children; c; c = c->next)
        {
          gfloat min_height, nat_height, height;
          ClutterActor *child = c->data;

          clutter_actor_get_preferred_height (child, width,
                                              &min_height, &nat_height);

          /* Calculate the allocatable height and keep an accumulator so
           * when we round to a pixel, we don't end up with a lot of
           * empty space at the end of the actor.
           */
          height = MAX (min_height, nat_height / ratio);
          remainder += (height - (gint)height);
          height = (gint)height;

          while (remainder >= 1.f)
            {
              height += 1.f;
              remainder -= 1.f;
            }

          /* Allocate the child */
          child_box.y2 = child_box.y1 + height;
          clutter_actor_allocate (child, &child_box, flags);

          /* Set the top position of the next child box */
          child_box.y1 = child_box.y2;
        }
    }

  /* Make sure the adjustment reflects the column's allocation */
  if (priv->adjustment)
    {
      gdouble page_size = box->y2 - box->y1 - padding.top - padding.bottom;
      mx_adjustment_set_values (priv->adjustment,
                                mx_adjustment_get_value (priv->adjustment),
                                0.0,
                                child_box.y2 - padding.top,
                                1.0,
                                page_size,
                                page_size);
    }
}
Beispiel #6
0
static void
mx_scroll_bar_allocate (ClutterActor          *actor,
                        const ClutterActorBox *box,
                        ClutterAllocationFlags flags)
{
  MxScrollBarPrivate *priv = MX_SCROLL_BAR (actor)->priv;
  MxPadding padding;
  ClutterActorBox bw_box, fw_box, trough_box;
  gfloat x, y, width, height, stepper_size;

  /* Chain up */
  CLUTTER_ACTOR_CLASS (mx_scroll_bar_parent_class)->allocate (actor, box,
                                                              flags);

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  /* calculate the child area */
  x = padding.left;
  y = padding.top;
  width = (box->x2 - box->x1) - padding.left - padding.right;
  height = (box->y2 - box->y1) - padding.top - padding.bottom;

  if (priv->orientation == MX_ORIENTATION_VERTICAL)
    {
      stepper_size = width;

      /* Backward stepper */
      bw_box.x1 = x;
      bw_box.y1 = y;
      bw_box.x2 = bw_box.x1 + stepper_size;
      bw_box.y2 = bw_box.y1 + stepper_size;
      clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);

      /* Forward stepper */
      fw_box.x1 = x;
      fw_box.y1 = y + height - stepper_size;
      fw_box.x2 = fw_box.x1 + stepper_size;
      fw_box.y2 = fw_box.y1 + stepper_size;
      clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);

      /* Trough */
      trough_box.x1 = x;
      trough_box.y1 = y + stepper_size;
      trough_box.x2 = x + width;
      trough_box.y2 = y + height - stepper_size;
      clutter_actor_allocate (priv->trough, &trough_box, flags);

    }
  else
    {
      stepper_size = height;

      /* Backward stepper */
      bw_box.x1 = x;
      bw_box.y1 = y;
      bw_box.x2 = bw_box.x1 + stepper_size;
      bw_box.y2 = bw_box.y1 + stepper_size;
      clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);

      /* Forward stepper */
      fw_box.x1 = x + width - stepper_size;
      fw_box.y1 = y;
      fw_box.x2 = fw_box.x1 + stepper_size;
      fw_box.y2 = fw_box.y1 + stepper_size;
      clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);

      /* Trough */
      trough_box.x1 = x + stepper_size;
      trough_box.y1 = y;
      trough_box.x2 = x + width - stepper_size;
      trough_box.y2 = y + height;
      clutter_actor_allocate (priv->trough, &trough_box, flags);
    }


  if (priv->adjustment)
    {
      gfloat handle_size, position, avail_size, handle_pos;
      gdouble value, lower, upper, page_size, increment;
      ClutterActorBox handle_box = { 0, };
      guint min_size, max_size;

      mx_adjustment_get_values (priv->adjustment,
                                &value,
                                &lower,
                                &upper,
                                NULL,
                                NULL,
                                &page_size);

      value = mx_adjustment_get_value (priv->adjustment);

      if ((upper == lower)
          || (page_size >= (upper - lower)))
        increment = 1.0;
      else
        increment = page_size / (upper - lower);

      min_size = priv->handle_min_size;

      mx_stylable_get (MX_STYLABLE (actor),
                       "mx-max-size", &max_size,
                       NULL);

      if (upper - lower - page_size <= 0)
        position = 0;
      else
        position = (value - lower) / (upper - lower - page_size);

      if (priv->orientation == MX_ORIENTATION_VERTICAL)
        {
          avail_size = height - stepper_size * 2;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_box.x1 = x;
          handle_pos = bw_box.y2 + position * (avail_size - handle_size);
          handle_box.y1 = CLAMP (handle_pos,
                                 bw_box.y2, fw_box.y1 - min_size);

          handle_box.x2 = handle_box.x1 + width;
          handle_box.y2 = CLAMP (handle_pos + handle_size,
                                 bw_box.y2 + min_size, fw_box.y1);
        }
      else
        {
          avail_size = width - stepper_size * 2;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_pos = bw_box.x2 + position * (avail_size - handle_size);
          handle_box.x1 = CLAMP (handle_pos,
                                 bw_box.x2, fw_box.x1 - min_size);
          handle_box.y1 = y;

          handle_box.x2 = CLAMP (handle_pos + handle_size,
                                 bw_box.x2 + min_size, fw_box.x1);
          handle_box.y2 = handle_box.y1 + height;
        }

      /* snap to pixel */
      handle_box.x1 = (int) handle_box.x1;
      handle_box.y1 = (int) handle_box.y1;
      handle_box.x2 = (int) handle_box.x2;
      handle_box.y2 = (int) handle_box.y2;

      clutter_actor_allocate (priv->handle,
                              &handle_box,
                              flags);
    }
}
/* Re-layout and allocate children of container we manage */
static void _xfdashboard_fill_box_layout_allocate(ClutterLayoutManager *inLayoutManager,
													ClutterContainer *inContainer,
													const ClutterActorBox *inAllocation,
													ClutterAllocationFlags inFlags)
{
	XfdashboardFillBoxLayout			*self;
	XfdashboardFillBoxLayoutPrivate		*priv;
	ClutterActor						*child;
	ClutterActorIter					iter;
	gfloat								parentWidth, parentHeight;
	gfloat								homogeneousSize;
	gfloat								x, y, w, h;
	gfloat								aspectRatio;
	ClutterActorBox						childAllocation;

	g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(inLayoutManager));
	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));

	self=XFDASHBOARD_FILL_BOX_LAYOUT(inLayoutManager);
	priv=self->priv;

	/* Get dimension of allocation */
	parentWidth=clutter_actor_box_get_width(inAllocation);
	parentHeight=clutter_actor_box_get_height(inAllocation);

	/* If homogeneous determine sizes for all children */
	if(priv->isHomogeneous==TRUE)
	{
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
		{
			_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, &homogeneousSize, NULL, NULL);
		}
			else
			{
				_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, NULL, NULL, &homogeneousSize);
			}
	}

	/* Iterate through children and set their sizes */
	x=y=0.0f;

	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
	while(clutter_actor_iter_next(&iter, &child))
	{
		/* Only set sizes on visible children */
		if(!clutter_actor_is_visible(child)) continue;

		/* Calculate and set new allocation of child */
		if(priv->isHomogeneous==FALSE)
		{
			clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &w, &h);
			if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
			{
				aspectRatio=w/h;
				h=parentHeight;
				w=h*aspectRatio;
			}
				else
				{
					aspectRatio=h/w;
					w=parentWidth;
					h=w*aspectRatio;
				}
		}
			else
			{
				if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
				{
					w=homogeneousSize;
					h=parentHeight;
				}
					else
					{
						w=parentWidth;
						h=homogeneousSize;
					}
			}

		/* Set new allocation of child */
		childAllocation.x1=ceil(x);
		childAllocation.y1=ceil(y);
		childAllocation.x2=ceil(childAllocation.x1+w);
		childAllocation.y2=ceil(childAllocation.y1+h);
		clutter_actor_allocate(child, &childAllocation, inFlags);

		/* Set up for next child */
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) x+=(w+priv->spacing);
			else y+=(h+priv->spacing);
	}
}
static void
mx_label_allocate (ClutterActor          *actor,
                   const ClutterActorBox *box,
                   ClutterAllocationFlags flags)
{
  MxLabelPrivate *priv = MX_LABEL (actor)->priv;
  gboolean label_did_fade = priv->label_should_fade;

  ClutterActorClass *parent_class;
  ClutterActorBox child_box;
  gboolean x_fill, y_fill;
  gfloat avail_width;

  parent_class = CLUTTER_ACTOR_CLASS (mx_label_parent_class);
  parent_class->allocate (actor, box, flags);

  mx_widget_get_available_area (MX_WIDGET (actor), box, &child_box);
  avail_width = child_box.x2 - child_box.x1;

  /* The default behaviour of ClutterText is to align to the
   * top-left when it gets more space than is needed. Because
   * of this behaviour, if we're aligning to the left, we can
   * assign all our horizontal space to the label without
   * measuring it (i.e. x-fill), and the same applies for
   * aligning to the top and vertical space.
   */
  x_fill = (priv->x_align == MX_ALIGN_START) ? TRUE : FALSE;
  y_fill = (priv->y_align == MX_ALIGN_START) ? TRUE : FALSE;

  mx_allocate_align_fill (priv->label, &child_box, priv->x_align,
                          priv->y_align, x_fill, y_fill);

  priv->label_should_fade = FALSE;

  if (priv->fade_out)
    {
      /* If we're fading out, make sure the label has its full width
       * allocated. This ensures that the offscreen effect has the full
       * label inside its texture.
       */
      gfloat label_width;

      clutter_actor_get_preferred_width (priv->label, -1, NULL, &label_width);

      if (label_width > avail_width)
        {
          priv->label_should_fade = TRUE;
          child_box.x2 = child_box.x1 + label_width;
        }

      mx_fade_effect_set_bounds (MX_FADE_EFFECT (priv->fade_effect),
                                 0, 0, MIN (label_width, avail_width), 0);
    }

  /* Allocate the label */
  clutter_actor_allocate (priv->label, &child_box, flags);

  if (priv->show_tooltip)
    {
      PangoLayout *layout;
      const gchar *text;

      layout = clutter_text_get_layout (CLUTTER_TEXT (priv->label));

      if (pango_layout_is_ellipsized (layout))
        text = clutter_text_get_text (CLUTTER_TEXT (priv->label));
      else
        text = NULL;

      mx_widget_set_tooltip_text (MX_WIDGET (actor), text);
    }

  /* Animate in/out the faded end of the label */
  if (label_did_fade != priv->label_should_fade)
    {
      /* Begin/reverse the fading timeline when necessary */
      if (priv->label_should_fade)
        clutter_timeline_set_direction (priv->fade_timeline,
                                        CLUTTER_TIMELINE_FORWARD);
      else
        clutter_timeline_set_direction (priv->fade_timeline,
                                        CLUTTER_TIMELINE_BACKWARD);

      if (!clutter_timeline_is_playing (priv->fade_timeline))
        clutter_timeline_rewind (priv->fade_timeline);

      clutter_timeline_start (priv->fade_timeline);
    }
}
Beispiel #9
0
static void
mx_menu_allocate (ClutterActor           *actor,
                  const ClutterActorBox  *box,
                  ClutterAllocationFlags  flags)
{
    gint i;
    MxPadding padding;
    ClutterActorBox child_box;
    MxMenuPrivate *priv = MX_MENU (actor)->priv;

    gfloat available_h = box->y2-box->y1;

    /*
     * first of all, we have to check if the allocated height is our
     * natural height...
     */
    gfloat menu_nat_h;
    mx_menu_get_preferred_height (actor, box->x2-box->x1, NULL, &menu_nat_h);
    if (available_h < menu_nat_h)
    {
        /*
         * ...if not, we have to draw 2 buttons in order to let the
         * user be able to navigate in the whole menu.
         */
        priv->scrolling_mode = TRUE;
    }
    else
    {
        priv->scrolling_mode = FALSE;
    }

    /* Allocate children */
    mx_widget_get_padding (MX_WIDGET (actor), &padding);
    child_box.x1 = padding.left;
    child_box.y1 = padding.top;
    child_box.x2 = box->x2 - box->x1 - padding.right;

    gfloat down_but_height;
    clutter_actor_get_preferred_height (priv->down_button,
                                        child_box.x2 - child_box.x1,
                                        NULL,
                                        &down_but_height);

    if (priv->scrolling_mode)
    {
        clutter_actor_get_preferred_height (priv->up_button,
                                            child_box.x2 - child_box.x1,
                                            NULL,
                                            &child_box.y2);
        child_box.y2 += child_box.y1;
        clutter_actor_allocate (priv->up_button, &child_box, flags);
        child_box.y1 = child_box.y2 + 1;

        available_h -= down_but_height;
    }


    for (i = priv->id_offset; i < priv->children->len; i++)
    {
        gfloat natural_height;

        MxMenuChild *child = &g_array_index (priv->children, MxMenuChild,
                                             i);

        clutter_actor_get_preferred_height (CLUTTER_ACTOR (child->box),
                                            child_box.x2 - child_box.x1,
                                            NULL,
                                            &natural_height);
        child_box.y2 = child_box.y1 + natural_height;
        if (child_box.y2 >= available_h)
        {
            priv->last_shown_id = i-1;
            break;
        }

        clutter_actor_allocate (CLUTTER_ACTOR (child->box), &child_box, flags);

        child_box.y1 = child_box.y2 + 1;
    }
    if (priv->children->len == i)
    {
        priv->last_shown_id = i-1;
    }

    if (priv->scrolling_mode)
    {
        child_box.y2 = child_box.y1 + down_but_height;
        clutter_actor_allocate (priv->down_button, &child_box, flags);
    }
    /* Chain up and allocate background */
    CLUTTER_ACTOR_CLASS (mx_menu_parent_class)->allocate (actor, box, flags);
}
Beispiel #10
0
static void
tidy_grid_allocate (ClutterActor          *self,
                              const ClutterActorBox *box,
                              gboolean               absolute_origin_changed)
{
  TidyGrid *layout = (TidyGrid *) self;
  TidyGridPrivate *priv = layout->priv;

  ClutterUnit current_a;
  ClutterUnit current_b;
  ClutterUnit next_b;
  ClutterUnit agap;
  ClutterUnit bgap;

  gboolean homogenous_a;
  gboolean homogenous_b;
  gdouble  aalign;
  gdouble  balign;
 
  current_a = current_b = next_b = 0;

  GList *iter;

  /* chain up to set actor->allocation */
  CLUTTER_ACTOR_CLASS (tidy_grid_parent_class)
    ->allocate (self, box, absolute_origin_changed);

  priv->alloc_width = box->x2 - box->x1;
  priv->alloc_height = box->y2 - box->y1;
  priv->absolute_origin_changed = absolute_origin_changed;

  /* Make sure we have calculated the preferred size */
  /* what does this do? */
  clutter_actor_get_preferred_size (self, NULL, NULL, NULL, NULL);


  if (priv->column_major)
    {
      priv->a_wrap = priv->alloc_height;
      homogenous_b = priv->homogenous_columns;
      homogenous_a = priv->homogenous_rows;
      aalign = priv->valign;
      balign = priv->halign;
      agap          = priv->row_gap;
      bgap          = priv->column_gap;
    }
  else
    {
      priv->a_wrap = priv->alloc_width;
      homogenous_a = priv->homogenous_columns;
      homogenous_b = priv->homogenous_rows;
      aalign = priv->halign;
      balign = priv->valign;
      agap          = priv->column_gap;
      bgap          = priv->row_gap;
    }

  priv->max_extent_a = 0;
  priv->max_extent_b = 0;

  priv->first_of_batch = TRUE;
  
  if (homogenous_a ||
      homogenous_b)
    {
      for (iter = priv->list; iter; iter = iter->next)
        {
          ClutterActor *child = iter->data;
          ClutterUnit natural_width;
          ClutterUnit natural_height;

          /* each child will get as much space as they require */
          clutter_actor_get_preferred_size (CLUTTER_ACTOR (child),
                                            NULL, NULL,
                                            &natural_width, &natural_height);
          if (natural_width > priv->max_extent_a)
            priv->max_extent_a = natural_width;
          if (natural_height > priv->max_extent_b)
            priv->max_extent_b = natural_width;
        }
    }

  if (priv->column_major)
    {
      ClutterUnit temp = priv->max_extent_a;
      priv->max_extent_a = priv->max_extent_b;
      priv->max_extent_b = temp;
    }

  for (iter = priv->list; iter; iter=iter->next)
    {
      ClutterActor *child = iter->data;
      ClutterUnit natural_a;
      ClutterUnit natural_b;

      /* each child will get as much space as they require */
      clutter_actor_get_preferred_size (CLUTTER_ACTOR (child),
                                        NULL, NULL,
                                        &natural_a, &natural_b);

      if (priv->column_major) /* swap axes around if column is major */
        {
          ClutterUnit temp = natural_a;
          natural_a = natural_b;
          natural_b = temp;
        }

      /* if the child is overflowing, we wrap to next line */
      if (current_a + natural_a > priv->a_wrap ||
          (homogenous_a && current_a + priv->max_extent_a > priv->a_wrap))
        {
          current_b = next_b + bgap;
          current_a = 0;
          next_b = current_b + bgap;
          priv->first_of_batch = TRUE;
        }

      if (priv->end_align &&
          priv->first_of_batch)
        {
          current_a = compute_row_start (iter, current_a, priv);
          priv->first_of_batch = FALSE;
        }

      if (next_b-current_b < natural_b)
          next_b = current_b + natural_b;

        {
          ClutterUnit     row_height;
          ClutterActorBox child_box;

          if (homogenous_b)
            {
              row_height = priv->max_extent_b;
            }
          else
            {
              row_height = compute_row_height (iter, next_b-current_b,
                                               current_a, priv);
            }

          if (homogenous_a)
            {
              child_box.x1 = current_a + (priv->max_extent_a-natural_a) * aalign;
              child_box.x2 = child_box.x1 + natural_a;

            }
          else
            {
              child_box.x1 = current_a;
              child_box.x2 = child_box.x1 + natural_a;
            }

          child_box.y1 = current_b + (row_height-natural_b) * balign;
          child_box.y2 = child_box.y1 + natural_b;


          if (priv->column_major)
            {
              ClutterUnit temp = child_box.x1;
              child_box.x1 = child_box.y1;
              child_box.y1 = temp;

              temp = child_box.x2;
              child_box.x2 = child_box.y2;
              child_box.y2 = temp;
            }

          /* update the allocation */
          clutter_actor_allocate (CLUTTER_ACTOR (child),
                                  &child_box,
                                  absolute_origin_changed);

          if (homogenous_a)
            {
              current_a += priv->max_extent_a + agap;
            }
          else
            {
              current_a += natural_a + agap;
            }
        }
    }
}
Beispiel #11
0
static void
clutter_table_layout_allocate (ClutterLayoutManager   *layout,
                               ClutterContainer       *container,
                               const ClutterActorBox  *box,
                               ClutterAllocationFlags  flags)
{
  ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout);
  ClutterTableLayoutPrivate *priv = self->priv;
  ClutterActor *actor, *child;
  gint row_spacing, col_spacing;
  gint i;
  DimensionData *rows, *columns;

  update_row_col (self, container);
  if (priv->n_cols < 1 || priv->n_rows < 1)
    return;

  actor = CLUTTER_ACTOR (container);

  if (clutter_actor_get_n_children (actor) == 0)
    return;

  col_spacing = (priv->col_spacing);
  row_spacing = (priv->row_spacing);

  calculate_table_dimensions (self, container,
                              box->x2 - box->x1,
                              box->y2 - box->y1);

  rows = (DimensionData *) (void *) priv->rows->data;
  columns = (DimensionData *) (void *) priv->columns->data;

  for (child = clutter_actor_get_first_child (actor);
       child != NULL;
       child = clutter_actor_get_next_sibling (child))
    {
      gint row, col, row_span, col_span;
      gint col_width, row_height;
      ClutterTableChild *meta;
      ClutterActorBox childbox;
      gint child_x, child_y;

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      meta =
        CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (layout,
                                                                    container,
                                                                    child));

      /* get child properties */
      col = meta->col;
      row = meta->row;
      row_span = meta->row_span;
      col_span = meta->col_span;

      /* initialise the width and height */
      col_width = columns[col].final_size;
      row_height = rows[row].final_size;

      /* Add the widths of the spanned columns:
       *
       * First check that we have a non-zero span. Then we loop over each of
       * the columns that we're spanning but we stop short if we go past the
       * number of columns in the table. This is necessary to avoid accessing
       * uninitialised memory. We add the spacing in here too since we only
       * want to add as much spacing as times we successfully span.
       */
      if (col + col_span > priv->n_cols)
        g_warning (G_STRLOC ": column-span exceeds number of columns");
      if (row + row_span > priv->n_rows)
        g_warning (G_STRLOC ": row-span exceeds number of rows");

      if (col_span > 1)
        {
          for (i = col + 1; i < col + col_span && i < priv->n_cols; i++)
            {
              col_width += columns[i].final_size;
              col_width += col_spacing;
            }
        }

      /* add the height of the spanned rows */
      if (row_span > 1)
        {
          for (i = row + 1; i < row + row_span && i < priv->n_rows; i++)
            {
              row_height += rows[i].final_size;
              row_height += row_spacing;
            }
        }

      /* calculate child x */
      child_x = clutter_actor_box_get_x (box);
      for (i = 0; i < col; i++)
        {
          if (columns[i].visible)
            {
              child_x += columns[i].final_size;
              child_x += col_spacing;
            }
        }

      /* calculate child y */
      child_y = clutter_actor_box_get_y (box);
      for (i = 0; i < row; i++)
        {
          if (rows[i].visible)
            {
              child_y += rows[i].final_size;
              child_y += row_spacing;
            }
        }

      /* set up childbox */
      childbox.x1 = (float) child_x;
      childbox.x2 = (float) MAX (0, child_x + col_width);

      childbox.y1 = (float) child_y;
      childbox.y2 = (float) MAX (0, child_y + row_height);

      clutter_actor_allocate (child, &childbox, flags);
    }
}
static void
penge_block_container_allocate (ClutterActor           *actor,
                                const ClutterActorBox  *box,
                                ClutterAllocationFlags  flags)
{
  PengeBlockContainer *pbc = PENGE_BLOCK_CONTAINER (actor);
  PengeBlockContainerPrivate *priv = GET_PRIVATE (actor);
  GList *l, *children;
  gfloat width, height;
  gint col_span;
  gint y_count, x_count;
  ClutterActor *child;
  ClutterActorBox child_box;
  gboolean fit_found = FALSE;

  width = box->x2 - box->x1;
  height = box->y2 - box->y1;

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


  if (priv->prev_width != width || priv->prev_height != height)
  {
    penge_block_container_generate_counts (pbc,
                                           width,
                                           height);
  }

  children = g_list_copy (priv->children);

  if (!children)
    return;

  children = g_list_reverse (children);

  for (y_count = 0; y_count < priv->row_count; y_count++)
  {
    for (x_count = 0; x_count < priv->column_count; /* nop */)
    {
      /* Find first that can fit */
      fit_found = FALSE;

      for (l = children; l; l = l->next)
      {
        child = (ClutterActor *)l->data;
        col_span = penge_block_container_get_child_column_span (pbc,
                                                                child);

        /* Check if it fits */
        if (x_count + col_span <= priv->column_count)
        {
          child_box.x1 = x_count * priv->actual_tile_width +
                         x_count * priv->spacing +
                         priv->padding;
          child_box.x2 = child_box.x1 +
                         priv->actual_tile_width * col_span +
                         priv->spacing * (col_span - 1);
          child_box.y1 = y_count * priv->actual_tile_height +
                         y_count * priv->spacing +
                         priv->padding;
          child_box.y2 = child_box.y1 + priv->actual_tile_height;

          clutter_actor_allocate (child, &child_box, flags);
          children = g_list_remove (children, child);

          /* Increment with the col-span to take into consideration how many
           * "blocks" we are occupying
           */
          x_count += col_span;

          fit_found = TRUE;
          break;
        }
      }

      /* If we didn't find something that fits then we just leave a gap. This
       * is basically fine.
       */
      if (!fit_found)
      {
        /* We couldn't find something that fitted */
        break;
      }
    }

    if (!children)
      break;
  }

  /* Allocate all children we don't get round to with {0,0,0,0}. We skip such
   * children in the paint.
   */
  for (l = children; l; l = l->next)
  {
    ClutterActor *actor = CLUTTER_ACTOR (l->data);
    ClutterActorBox zero_box = { 0, };
    clutter_actor_allocate (actor, &zero_box, flags);
  }

  g_list_free (children);
}
Beispiel #13
0
static void
mx_table_preferred_allocate (ClutterActor          *self,
                             const ClutterActorBox *box,
                             gboolean               flags)
{
  gint row_spacing, col_spacing;
  gint i;
  MxTable *table;
  MxTablePrivate *priv;
  MxPadding padding;
  DimensionData *rows, *columns;
  ClutterActorIter iter;
  ClutterActor *child;

  table = MX_TABLE (self);
  priv = MX_TABLE (self)->priv;

  mx_widget_get_padding (MX_WIDGET (self), &padding);

  col_spacing = (priv->col_spacing);
  row_spacing = (priv->row_spacing);

  mx_table_calculate_dimensions (table, box->x2 - box->x1, box->y2 - box->y1);

  rows = &g_array_index (priv->rows, DimensionData, 0);
  columns = &g_array_index (priv->columns, DimensionData, 0);

  clutter_actor_iter_init (&iter, self);
  while (clutter_actor_iter_next (&iter, &child))
    {
      gint row, col, row_span, col_span;
      gint col_width, row_height;
      MxTableChild *meta;
      ClutterActorBox childbox;
      gint child_x, child_y;
      gdouble x_align_d, y_align_d;
      gboolean x_fill, y_fill;
      MxAlign x_align, y_align;

      meta = (MxTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child);

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      /* get child properties */
      col = meta->col;
      row = meta->row;
      row_span = meta->row_span;
      col_span = meta->col_span;
      x_align_d = meta->x_align;
      y_align_d = meta->y_align;
      x_fill = meta->x_fill;
      y_fill = meta->y_fill;

      /* Convert to MxAlign */
      if (x_align_d < 1.0 / 3.0)
        x_align = MX_ALIGN_START;
      else if (x_align_d > 2.0 / 3.0)
        x_align = MX_ALIGN_END;
      else
        x_align = MX_ALIGN_MIDDLE;
      if (y_align_d < 1.0 / 3.0)
        y_align = MX_ALIGN_START;
      else if (y_align_d > 2.0 / 3.0)
        y_align = MX_ALIGN_END;
      else
        y_align = MX_ALIGN_MIDDLE;

      /* initialise the width and height */
      col_width = columns[col].final_size;
      row_height = rows[row].final_size;

      /* Add the widths of the spanned columns:
       *
       * First check that we have a non-zero span. Then we loop over each of
       * the columns that we're spanning but we stop short if we go past the
       * number of columns in the table. This is necessary to avoid accessing
       * uninitialised memory. We add the spacing in here too since we only
       * want to add as much spacing as times we successfully span.
       */
      if (col + col_span > priv->n_cols)
        g_warning ("MxTable: col-span exceeds number of columns");
      if (row + row_span > priv->n_rows)
        g_warning ("MxTable: row-span exceeds number of rows");

      if (col_span > 1)
        {
          for (i = col + 1; i < col + col_span && i < priv->n_cols; i++)
            {
              col_width += columns[i].final_size;
              col_width += col_spacing;
            }
        }

      /* add the height of the spanned rows */
      if (row_span > 1)
        {
          for (i = row + 1; i < row + row_span && i < priv->n_rows; i++)
            {
              row_height += rows[i].final_size;
              row_height += row_spacing;
            }
        }

      /* calculate child x */
      child_x = (int) padding.left;
      for (i = 0; i < col; i++)
        {
          if (columns[i].is_visible)
            {
              child_x += columns[i].final_size;
              child_x += col_spacing;
            }
        }

      /* calculate child y */
      child_y = (int) padding.top;
      for (i = 0; i < row; i++)
        {
          if (rows[i].is_visible)
            {
              child_y += rows[i].final_size;
              child_y += row_spacing;
            }
        }

      /* set up childbox */
      childbox.x1 = (float) child_x;
      childbox.x2 = (float) MAX (0, child_x + col_width);

      childbox.y1 = (float) child_y;
      childbox.y2 = (float) MAX (0, child_y + row_height);


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

      clutter_actor_allocate (child, &childbox, flags);
    }
}
Beispiel #14
0
static void
st_table_preferred_allocate (ClutterActor          *self,
                             const ClutterActorBox *content_box,
                             gboolean               flags)
{
  GList *list, *children;
  gint row_spacing, col_spacing;
  gint i;
  StTable *table;
  StTablePrivate *priv;
  gboolean ltr;
  DimensionData *rows, *columns;

  table = ST_TABLE (self);
  priv = ST_TABLE (self)->priv;

  col_spacing = (priv->col_spacing);
  row_spacing = (priv->row_spacing);

  st_table_calculate_dimensions (table,
                                 content_box->x2 - content_box->x1,
                                 content_box->y2 - content_box->y1);

  ltr = (st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR);
  rows = &g_array_index (priv->rows, DimensionData, 0);
  columns = &g_array_index (priv->columns, DimensionData, 0);

  children = st_container_get_children_list (ST_CONTAINER (self));
  for (list = children; list; list = list->next)
    {
      gint row, col, row_span, col_span;
      gint col_width, row_height;
      StTableChild *meta;
      ClutterActor *child;
      ClutterActorBox childbox;
      gint child_x, child_y;
      StAlign x_align, y_align;
      gboolean x_fill, y_fill;

      child = CLUTTER_ACTOR (list->data);

      meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child);

      if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      /* get child properties */
      col = meta->col;
      row = meta->row;
      row_span = meta->row_span;
      col_span = meta->col_span;
      x_align = meta->x_align;
      y_align = meta->y_align;
      x_fill = meta->x_fill;
      y_fill = meta->y_fill;

      /* initialise the width and height */
      col_width = columns[col].final_size;
      row_height = rows[row].final_size;

      /* Add the widths of the spanned columns:
       *
       * First check that we have a non-zero span. Then we loop over each of
       * the columns that we're spanning but we stop short if we go past the
       * number of columns in the table. This is necessary to avoid accessing
       * uninitialised memory. We add the spacing in here too since we only
       * want to add as much spacing as times we successfully span.
       */
      if (col + col_span > priv->n_cols)
        g_warning ("StTable: the child at %d,%d's col-span, %d, exceeds number of columns, %d",
                   col, row, col_span, priv->n_cols);
      if (row + row_span > priv->n_rows)
        g_warning ("StTable: the child at %d,%d's row-span, %d, exceeds number of rows, %d",
                   col, row, row_span, priv->n_rows);

      if (col_span > 1)
        {
          for (i = col + 1; i < col + col_span && i < priv->n_cols; i++)
            {
              col_width += columns[i].final_size;
              col_width += col_spacing;
            }
        }

      /* add the height of the spanned rows */
      if (row_span > 1)
        {
          for (i = row + 1; i < row + row_span && i < priv->n_rows; i++)
            {
              row_height += rows[i].final_size;
              row_height += row_spacing;
            }
        }

      /* calculate child x */
      if (ltr)
        {
          child_x = (int) content_box->x1
                    + col_spacing * col;
          for (i = 0; i < col; i++)
            child_x += columns[i].final_size;
        }
      else
        {
          child_x = (int) content_box->x2
                    - col_spacing * col;
          for (i = 0; i < col; i++)
            child_x -= columns[i].final_size;
        }

      /* calculate child y */
      child_y = (int) content_box->y1
                + row_spacing * row;
      for (i = 0; i < row; i++)
        child_y += rows[i].final_size;

      /* set up childbox */
      if (ltr)
        {
          childbox.x1 = (float) child_x;
          childbox.x2 = (float) MAX (0, child_x + col_width);
        }
      else
        {
          childbox.x2 = (float) child_x;
          childbox.x1 = (float) MAX (0, child_x - col_width);
        }

      childbox.y1 = (float) child_y;
      childbox.y2 = (float) MAX (0, child_y + row_height);


      _st_allocate_fill (ST_WIDGET (self), child, &childbox,
                         x_align, y_align, x_fill, y_fill);

      clutter_actor_allocate (child, &childbox, flags);
    }
}
Beispiel #15
0
static void
scroll_bar_allocate_children (StScrollBar           *bar,
                              const ClutterActorBox *box,
                              ClutterAllocationFlags flags)
{
  StScrollBarPrivate *priv = bar->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (bar));
  ClutterActorBox content_box, trough_box;

  st_theme_node_get_content_box (theme_node, box, &content_box);

  if (priv->vertical)
    {
      trough_box.x1 = content_box.x1;
      trough_box.y1 = content_box.y1;
      trough_box.x2 = content_box.x2;
      trough_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->trough, &trough_box, flags);
    }
  else
    {
      trough_box.x1 = content_box.x1;
      trough_box.y1 = content_box.y1;
      trough_box.x2 = content_box.x2;
      trough_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->trough, &trough_box, flags);
    }


  if (priv->adjustment)
    {
      float handle_size, position, avail_size;
      gdouble value, lower, upper, page_size, increment, min_size, max_size;
      ClutterActorBox handle_box = { 0, };

      st_adjustment_get_values (priv->adjustment,
                                &value,
                                &lower,
                                &upper,
                                NULL,
                                NULL,
                                &page_size);

      if ((upper == lower)
          || (page_size >= (upper - lower)))
        increment = 1.0;
      else
        increment = page_size / (upper - lower);

      min_size = 32.;
      st_theme_node_lookup_length (theme_node, "min-size", FALSE, &min_size);
      max_size = G_MAXINT16;
      st_theme_node_lookup_length (theme_node, "max-size", FALSE, &max_size);

      if (upper - lower - page_size <= 0)
        position = 0;
      else
        position = (value - lower) / (upper - lower - page_size);

      if (priv->vertical)
        {
          avail_size = content_box.y2 - content_box.y1;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_box.x1 = content_box.x1;
          handle_box.y1 = content_box.y1 + position * (avail_size - handle_size);

          handle_box.x2 = content_box.x2;
          handle_box.y2 = handle_box.y1 + handle_size;
        }
      else
        {
          avail_size = content_box.x2 - content_box.x1;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_box.x1 = content_box.x1 + position * (avail_size - handle_size);
          handle_box.y1 = content_box.y1;

          handle_box.x2 = handle_box.x1 + handle_size;
          handle_box.y2 = content_box.y2;
        }

      clutter_actor_allocate (priv->handle,
                              &handle_box,
                              flags);
    }
}
Beispiel #16
0
static void
shell_overflow_list_allocate (ClutterActor           *actor,
                              const ClutterActorBox  *box,
                              ClutterAllocationFlags  flags)
{
  ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor);
  ShellOverflowListPrivate *priv = self->priv;
  GList *children, *iter;
  int n_pages;
  int n_children;
  int n_fits;
  float width;
  float curheight;
  float avail_height;
  gboolean overflow;

  /* chain up to set actor->allocation */
  (CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ())))->allocate (actor, box, flags);

  width = box->x2 - box->x1;
  curheight = 0;
  avail_height = box->y2 - box->y1;

  children = clutter_container_get_children (CLUTTER_CONTAINER (self));
  n_children = g_list_length (children);

  n_fits = 0;
  n_pages = 1;
  overflow = FALSE;
  for (iter = children; iter; iter = iter->next)
    {
      ClutterActor *actor = CLUTTER_ACTOR (iter->data);
      ClutterActorBox child_box;

      if ((curheight + priv->item_height) > avail_height)
        {
          overflow = TRUE;
          curheight = 0;
          n_pages++;
        }
      else if (!overflow)
        n_fits++;

      child_box.x1 = 0;
      child_box.x2 = width;
      child_box.y1 = curheight;
      child_box.y2 = child_box.y1 + priv->item_height;
      clutter_actor_allocate (actor, &child_box, flags);

      curheight += priv->item_height;
      if (iter != children)
        curheight += priv->spacing;
    }

  priv->items_per_page = n_fits;
  if (n_pages != priv->n_pages)
    {
      priv->n_pages = n_pages;
      g_object_notify (G_OBJECT (self), "n-pages");
    }

  g_list_free (children);
}
Beispiel #17
0
/* Allocate position and size of actor and its children */
static void _xfdashboard_viewpad_allocate(ClutterActor *self,
											const ClutterActorBox *inBox,
											ClutterAllocationFlags inFlags)
{
	XfdashboardViewpadPrivate	*priv=XFDASHBOARD_VIEWPAD(self)->priv;
	ClutterActorClass			*actorClass=CLUTTER_ACTOR_CLASS(xfdashboard_viewpad_parent_class);
	gfloat						viewWidth, viewHeight;
	gfloat						vScrollbarWidth, vScrollbarHeight;
	gfloat						hScrollbarWidth, hScrollbarHeight;
	gboolean					hScrollbarVisible, vScrollbarVisible;
	ClutterActorBox				*box;
	gfloat						x, y, w, h;

	/* Chain up to store the allocation of the actor */
	if(actorClass->allocate) actorClass->allocate(self, inBox, inFlags);

	/* Initialize largest possible allocation for view and determine
	 * real size of view to show. The real size is used to determine
	 * scroll bar visibility if policy is automatic */
	viewWidth=clutter_actor_box_get_width(inBox);
	viewHeight=clutter_actor_box_get_height(inBox);

	/* Determine visibility of scroll bars */
	hScrollbarVisible=FALSE;
	if(priv->hScrollbarPolicy==XFDASHBOARD_POLICY_ALWAYS ||
		(priv->hScrollbarPolicy==XFDASHBOARD_POLICY_AUTOMATIC &&
			xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->hScrollbar))>viewWidth))
	{
		hScrollbarVisible=TRUE;
	}
	if(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_HORIZONTAL ||
		xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_BOTH)
	{
		hScrollbarVisible=FALSE;
	}

	vScrollbarVisible=FALSE;
	if(priv->vScrollbarPolicy==XFDASHBOARD_POLICY_ALWAYS ||
		(priv->vScrollbarPolicy==XFDASHBOARD_POLICY_AUTOMATIC &&
			xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->vScrollbar))>viewHeight))
	{
		vScrollbarVisible=TRUE;
	}
	if(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_VERTICAL ||
		xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_BOTH)
	{
		vScrollbarVisible=FALSE;
	}

	/* Set allocation for visible scroll bars */
	vScrollbarWidth=0.0f;
	vScrollbarHeight=viewHeight;
	clutter_actor_get_preferred_width(priv->vScrollbar, -1, NULL, &vScrollbarWidth);

	hScrollbarWidth=viewWidth;
	hScrollbarHeight=0.0f;
	clutter_actor_get_preferred_height(priv->hScrollbar, -1, NULL, &hScrollbarHeight);

	if(hScrollbarVisible && vScrollbarVisible)
	{
		vScrollbarHeight-=hScrollbarHeight;
		hScrollbarWidth-=vScrollbarWidth;
	}

	if(vScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0);
		else box=clutter_actor_box_new(viewWidth-vScrollbarWidth, 0, viewWidth, vScrollbarHeight);
	clutter_actor_allocate(priv->vScrollbar, box, inFlags);
	clutter_actor_box_free(box);

	if(hScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0);
		else box=clutter_actor_box_new(0, viewHeight-hScrollbarHeight, hScrollbarWidth, viewHeight);
	clutter_actor_allocate(priv->hScrollbar, box, inFlags);
	clutter_actor_box_free(box);

	/* Reduce allocation for view by any visible scroll bar
	 * and set allocation and clipping of view
	 */
	if(priv->activeView)
	{
		/* Set allocation */
		if(vScrollbarVisible) viewWidth-=vScrollbarWidth;
		if(hScrollbarVisible) viewHeight-=hScrollbarHeight;

		x=y=0.0f;
		if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView)))
		{
			clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, NULL, NULL);
		}

		switch(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView)))
		{
			case XFDASHBOARD_FIT_MODE_BOTH:
				w=viewWidth;
				h=viewHeight;
				break;

			case XFDASHBOARD_FIT_MODE_HORIZONTAL:
				w=viewWidth;
				clutter_actor_get_preferred_height(CLUTTER_ACTOR(priv->activeView), w, NULL, &h);
				break;

			case XFDASHBOARD_FIT_MODE_VERTICAL:
				h=viewHeight;
				clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->activeView), h, NULL, &w);
				break;

			default:
				clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->activeView), NULL, NULL, &w, &h);
				break;
		}

		box=clutter_actor_box_new(0, 0, w, h);
		clutter_actor_allocate(CLUTTER_ACTOR(priv->activeView), box, inFlags);
		clutter_actor_box_free(box);

		clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, viewWidth, viewHeight);
	}

	/* Only set value if it changes */
	if(priv->hScrollbarVisible!=hScrollbarVisible)
	{
		/* Set new value */
		priv->hScrollbarVisible=hScrollbarVisible;

		/* Notify about property change */
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_HSCROLLBAR_VISIBLE]);
	}

	if(priv->vScrollbarVisible!=vScrollbarVisible)
	{
		/* Set new value */
		priv->vScrollbarVisible=vScrollbarVisible;

		/* Notify about property change */
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_VSCROLLBAR_VISIBLE]);
	}
}
Beispiel #18
0
static void
mx_slider_allocate_fill_handle (MxSlider               *self,
                                const ClutterActorBox  *box,
                                ClutterAllocationFlags  flags)
{
  MxSliderPrivate *priv = self->priv;
  MxPadding        padding;
  ClutterActorBox  bar_box;
  ClutterActorBox  fill_box;
  ClutterActorBox  buffer_box;
  ClutterActorBox  handle_box;
  guint            handle_width_2;

  if (box == NULL)
    {
      clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &bar_box);
      box = &bar_box;
    }

  mx_widget_get_padding (MX_WIDGET (self), &padding);

  handle_width_2 = priv->handle_width >> 1;

  /* fill */
  fill_box.x1 = padding.left;
  fill_box.y1 = priv->trough_box_y1;
  fill_box.x2 = ((box->x2 - box->x1 - padding.left - padding.right -
                  priv->handle_width) * priv->value) + padding.left +
                  handle_width_2;
  fill_box.x2 = CLAMP (fill_box.x2,
                       priv->handle_middle_start,
                       priv->handle_middle_end);
  fill_box.y2 = priv->trough_box_y2;

  clutter_actor_allocate (priv->fill, &fill_box, flags);


  /* buffer */
  buffer_box.x1 = padding.left;
  buffer_box.y1 = priv->trough_box_y1;
  buffer_box.x2 = buffer_box.x1
    + ((box->x2 - box->x1 - padding.left - padding.right) * priv->buffer_value);
  buffer_box.y2 = priv->trough_box_y2;

  clutter_actor_allocate (priv->buffer, &buffer_box, flags);

  /* handle */
  handle_box.x1 = fill_box.x2 - handle_width_2;
  handle_box.x2 = handle_box.x1 + priv->handle_width;

  /* If the handle height is unset, occupy all available space.
   * Otherwise we want it to be centred in the trough.
   */
  if (priv->handle_height == 0)
    {
      handle_box.y1 = padding.top;
      handle_box.y2 = (box->y2 - box->y1) - padding.bottom;
    }
  else
    {
      handle_box.y1 = (box->y2 - box->y1 - priv->handle_height) / 2.f;
      handle_box.y2 = handle_box.y1 + priv->handle_height;
    }

  /* snap to pixel */
  handle_box.x1 = (int) handle_box.x1;
  handle_box.y1 = (int) handle_box.y1;
  handle_box.x2 = (int) handle_box.x2;
  handle_box.y2 = (int) handle_box.y2;

  clutter_actor_allocate (priv->handle, &handle_box, flags);
}
Beispiel #19
0
static void
clutter_flow_layout_allocate (ClutterLayoutManager   *manager,
                              ClutterContainer       *container,
                              const ClutterActorBox  *allocation,
                              ClutterAllocationFlags  flags)
{
  ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv;
  GList *l, *children = clutter_container_get_children (container);
  gfloat avail_width, avail_height;
  gfloat item_x, item_y;
  gint line_item_count;
  gint items_per_line;
  gint line_index;

  if (children == NULL)
    return;

  clutter_actor_box_get_size (allocation, &avail_width, &avail_height);

  items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager),
                                  avail_width, avail_height);

  item_x = item_y = 0;

  line_item_count = 0;
  line_index = 0;

  for (l = children; l != NULL; l = l->next)
    {
      ClutterActor *child = l->data;
      ClutterActorBox child_alloc;
      gfloat item_width, item_height;
      gfloat new_x, new_y;

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      new_x = new_y = 0;

      if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
        {
          if (line_item_count == items_per_line && line_item_count > 0)
            {
              item_y += g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

              if (line_index >= 0)
                item_y += priv->row_spacing;

              line_item_count = 0;
              line_index += 1;

              item_x = 0;
            }

          new_x = ((line_item_count + 1) * (avail_width + priv->col_spacing))
                / items_per_line;
          item_width = new_x - item_x - priv->col_spacing;
          item_height = g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

          if (!priv->is_homogeneous)
            {
              gfloat child_min, child_natural;

              clutter_actor_get_preferred_width (child, item_height,
                                                 &child_min,
                                                 &child_natural);
              item_width = MIN (item_width, child_natural);

              clutter_actor_get_preferred_height (child, item_width,
                                                  &child_min,
                                                  &child_natural);
              item_height = MIN (item_height, child_natural);
            }
        }
      else
        {
          if (line_item_count == items_per_line && line_item_count > 0)
            {
              item_x += g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

              if (line_index >= 0)
                item_x += priv->col_spacing;

              line_item_count = 0;
              line_index += 1;

              item_y = 0;
            }

          new_y = ((line_item_count + 1) * (avail_height + priv->row_spacing))
                / items_per_line;
          item_height = new_y - item_y - priv->row_spacing;
          item_width = g_array_index (priv->line_natural,
                                      gfloat,
                                      line_index);

          if (!priv->is_homogeneous)
            {
              gfloat child_min, child_natural;

              clutter_actor_get_preferred_width (child, item_height,
                                                 &child_min,
                                                 &child_natural);
              item_width = MIN (item_width, child_natural);

              clutter_actor_get_preferred_height (child, item_width,
                                                  &child_min,
                                                  &child_natural);
              item_height = MIN (item_height, child_natural);
            }
        }

      CLUTTER_NOTE (LAYOUT,
                    "flow[line:%d, item:%d/%d] ="
                    "{ %.2f, %.2f, %.2f, %.2f }",
                    line_index, line_item_count + 1, items_per_line,
                    item_x, item_y, item_width, item_height);

      child_alloc.x1 = ceil (item_x);
      child_alloc.y1 = ceil (item_y);
      child_alloc.x2 = ceil (child_alloc.x1 + item_width);
      child_alloc.y2 = ceil (child_alloc.y1 + item_height);
      clutter_actor_allocate (child, &child_alloc, flags);

      if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
        item_x = new_x;
      else
        item_y = new_y;

      line_item_count += 1;
    }

  g_list_free (children);
}
Beispiel #20
0
static void
mx_combo_box_allocate (ClutterActor          *actor,
                       const ClutterActorBox *box,
                       ClutterAllocationFlags flags)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv;
  MxPadding padding;
  gfloat x, y, width, height;
  gfloat min_menu_h, nat_menu_h;
  gfloat label_h;
  gfloat nat_icon_h, icon_h, icon_w;
  gfloat nat_marker_h, marker_h, marker_w;
  ClutterActorBox childbox;
  ClutterActor *menu, *stage;

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

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  x = padding.left;
  y = padding.top;
  width = box->x2 - box->x1 - padding.left - padding.right;
  height = box->y2 - box->y1 - padding.top - padding.bottom;

  icon_w = marker_w = 0;

  if (priv->icon)
    {
      /* Allocate the icon, if there is one, the space not used by the text */
      clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h);

      if (height >= nat_icon_h)
        {
          icon_h = nat_icon_h;
          clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w);
        }
      else
        {
          icon_h = height;
          clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w);
        }

      childbox.x1 = (int)(x);
      childbox.y1 = (int)(y + (height - icon_h) / 2);
      childbox.x2 = (int)(x + icon_w);
      childbox.y2 = (int)(childbox.y1 + icon_h);

      clutter_actor_allocate (priv->icon, &childbox, flags);

      icon_w += priv->spacing;
    }

  if (priv->marker)
    {
      clutter_actor_get_preferred_height (priv->marker, -1,
                                          NULL, &nat_marker_h);

      if (height >= nat_marker_h)
        {
          marker_h = nat_marker_h;
          clutter_actor_get_preferred_width (priv->marker, -1, NULL, &marker_w);
        }
      else
        {
          marker_h = height;
          clutter_actor_get_preferred_width (priv->marker, marker_h,
                                             NULL, &marker_w);
        }

      childbox.x2 = (int)(x + width);
      childbox.x1 = (int)(childbox.x2 - marker_w);
      childbox.y1 = (int)(y + (height - marker_h) / 2);
      childbox.y2 = (int)(childbox.y1 + marker_h);

      clutter_actor_allocate (priv->marker, &childbox, flags);

      marker_w += priv->spacing;
    }

  clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h);

  childbox.x1 = (int)(x + icon_w);
  childbox.y1 = (int)(y + (height / 2 - label_h / 2));
  childbox.x2 = (int)(x + width - marker_w);
  childbox.y2 = (int)(childbox.y1 + label_h);
  clutter_actor_allocate (priv->label, &childbox, flags);

  menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor));
  clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h,
                                      &nat_menu_h);

  childbox.x1 = 0;
  childbox.x2 = (box->x2 - box->x1);
  childbox.y1 = (box->y2 - box->y1);

  stage = clutter_actor_get_stage (actor);
  if (stage != NULL)
    {
      ClutterVertex point = { 0, };
      gfloat stage_w, stage_h, combo_h = box->y2 - box->y1;

      clutter_actor_get_size (stage, &stage_w, &stage_h);
      point.y = combo_h + nat_menu_h;
      clutter_actor_apply_transform_to_point (actor, &point, &point);

      /* If the menu would appear off the stage, flip it around. */
      if ((point.x < 0) || (point.x >= stage_w) ||
          (point.y < 0) || (point.y >= stage_h))
        {
          childbox.y1 = -nat_menu_h;
        }
    }

  childbox.y2 = childbox.y1 + nat_menu_h;
  clutter_actor_allocate (menu, &childbox, flags);
}
Beispiel #21
0
static void
scroll_bar_allocate_children (StScrollBar           *bar,
                              const ClutterActorBox *box,
                              ClutterAllocationFlags flags)
{
  StScrollBarPrivate *priv = bar->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (bar));
  ClutterActorBox content_box, bw_box, fw_box, trough_box;
  gfloat bw_stepper_size, fw_stepper_size, min_size, natural_size;

  st_theme_node_get_content_box (theme_node, box, &content_box);

  if (priv->vertical)
    {
      gfloat width = content_box.x2 - content_box.x1;

      clutter_actor_get_preferred_height (priv->bw_stepper, width,
                                          &min_size, &natural_size);
      bw_stepper_size = MAX (min_size, natural_size);

      /* Backward stepper */
      bw_box.x1 = content_box.x1;
      bw_box.y1 = content_box.y1;
      bw_box.x2 = content_box.x2;
      bw_box.y2 = bw_box.y1 + bw_stepper_size;
      clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);


      clutter_actor_get_preferred_height (priv->fw_stepper, width,
                                          &min_size, &natural_size);
      fw_stepper_size = MAX (min_size, natural_size);

      /* Forward stepper */
      fw_box.x1 = content_box.x1;
      fw_box.y1 = content_box.y2 - fw_stepper_size;
      fw_box.x2 = content_box.x2;
      fw_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);

      /* Trough */
      trough_box.x1 = content_box.x1;
      trough_box.y1 = content_box.y1 + bw_stepper_size;
      trough_box.x2 = content_box.x2;
      trough_box.y2 = content_box.y2 - fw_stepper_size;
      clutter_actor_allocate (priv->trough, &trough_box, flags);

    }
  else
    {
      gfloat height = content_box.y2 - content_box.y1;

      clutter_actor_get_preferred_width (priv->bw_stepper, height,
                                         &min_size, &natural_size);
      bw_stepper_size = MAX (min_size, natural_size);

      /* Backward stepper */
      bw_box.x1 = content_box.x1;
      bw_box.y1 = content_box.y1;
      bw_box.x2 = bw_box.x1 + bw_stepper_size;
      bw_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);


      clutter_actor_get_preferred_width (priv->fw_stepper, height,
                                         &min_size, &natural_size);
      fw_stepper_size = MAX (min_size, natural_size);

      /* Forward stepper */
      fw_box.x1 = content_box.x2 - fw_stepper_size;
      fw_box.y1 = content_box.y1;
      fw_box.x2 = content_box.x2;
      fw_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);

      /* Trough */
      trough_box.x1 = content_box.x1 + bw_stepper_size;
      trough_box.y1 = content_box.y1;
      trough_box.x2 = content_box.x2 - fw_stepper_size;
      trough_box.y2 = content_box.y2;
      clutter_actor_allocate (priv->trough, &trough_box, flags);
    }


  if (priv->adjustment)
    {
      float handle_size, position, avail_size, stepper_size;
      gdouble value, lower, upper, page_size, increment, min_size, max_size;
      ClutterActorBox handle_box = { 0, };

      stepper_size = bw_stepper_size + fw_stepper_size;

      st_adjustment_get_values (priv->adjustment,
                                &value,
                                &lower,
                                &upper,
                                NULL,
                                NULL,
                                &page_size);

      if ((upper == lower)
          || (page_size >= (upper - lower)))
        increment = 1.0;
      else
        increment = page_size / (upper - lower);

      min_size = 32.;
      st_theme_node_lookup_length (theme_node, "min-size", FALSE, &min_size);
      max_size = G_MAXINT16;
      st_theme_node_lookup_length (theme_node, "max-size", FALSE, &max_size);

      if (upper - lower - page_size <= 0)
        position = 0;
      else
        position = (value - lower) / (upper - lower - page_size);

      if (priv->vertical)
        {
          avail_size = content_box.y2 - content_box.y1 - stepper_size;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_box.x1 = content_box.x1;
          handle_box.y1 = bw_box.y2 + position * (avail_size - handle_size);

          handle_box.x2 = content_box.x2;
          handle_box.y2 = handle_box.y1 + handle_size;
        }
      else
        {
          avail_size = content_box.x2 - content_box.x1 - stepper_size;
          handle_size = increment * avail_size;
          handle_size = CLAMP (handle_size, min_size, max_size);

          handle_box.x1 = bw_box.x2 + position * (avail_size - handle_size);
          handle_box.y1 = content_box.y1;

          handle_box.x2 = handle_box.x1 + handle_size;
          handle_box.y2 = content_box.y2;
        }

      /* snap to pixel */
      handle_box.x1 = (int) handle_box.x1;
      handle_box.y1 = (int) handle_box.y1;
      handle_box.x2 = (int) handle_box.x2;
      handle_box.y2 = (int) handle_box.y2;

      clutter_actor_allocate (priv->handle,
                              &handle_box,
                              flags);
    }
}
Beispiel #22
0
static void
mex_tile_allocate (ClutterActor           *actor,
                   const ClutterActorBox  *box,
                   ClutterAllocationFlags  flags)
{
  MxPadding padding;
  ClutterActorBox child_box;
  gfloat available_width, available_height;
  ClutterEffect *fade;

  MexTilePrivate *priv = MEX_TILE (actor)->priv;

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

  mx_widget_get_padding (MX_WIDGET (actor), &padding);
  available_width = box->x2 - box->x1 - padding.left - padding.right;
  available_height = box->y2 - box->y1 - padding.top - padding.bottom;

  if (priv->child)
    {
      gfloat child_width, full_width, full_height;

      clutter_actor_get_preferred_size (priv->child, NULL, NULL,
                                        &full_width, &full_height);

      child_box.y1 = padding.top;

      if (clutter_alpha_get_alpha (priv->important_alpha) < 0.5)
        {
          child_width = full_width * (available_height / full_height);
          if (child_width > available_width)
            child_width = available_width;

          child_box.y2 = child_box.y1 + available_height;

          /* When we're in unimportant state, make sure the label
           * doesn't overlap the image.
           */
          if (available_height < full_height)
            available_width -= child_width *
              ((0.5 - clutter_alpha_get_alpha (priv->important_alpha)) * 2);
        }
      else
        {
          child_width = available_width;
          clutter_actor_set_clip_to_allocation (
            actor, (full_height > available_height));

          child_box.y2 = child_box.y1 + full_height;
        }

      child_box.x2 = box->x2 - box->x1 - padding.right;
      child_box.x1 = child_box.x2 - child_width;

      mx_allocate_align_fill (priv->child, &child_box,
                              MX_ALIGN_MIDDLE, MX_ALIGN_MIDDLE, FALSE, FALSE);
      clutter_actor_allocate (priv->child, &child_box, flags);
    }

  /* Allocate Header */
  if (priv->header_visible)
    {
      gfloat icon1_w, icon1_h, icon2_w, icon2_h, label_h, label_w, header_h;
      gfloat middle_w;

      if (priv->header_padding)
        {
          padding.top += priv->header_padding->top;
          padding.right += priv->header_padding->right;
          padding.bottom += priv->header_padding->bottom;
          padding.left += priv->header_padding->left;
        }

      clutter_actor_get_preferred_size (priv->box_layout, NULL, NULL, &label_w,
                                        &label_h);

      if (priv->icon1)
        clutter_actor_get_preferred_size (priv->icon1, NULL, NULL, &icon1_w,
                                          &icon1_h);
      else
        icon1_h = icon1_w = 0;

      if (priv->icon2)
        clutter_actor_get_preferred_size (priv->icon2, NULL, NULL, &icon2_w,
                                          &icon2_h);
      else
        icon2_h = icon2_w = 0;

      header_h = MAX (icon1_h, MAX (icon2_h, label_h));

      /* primary icon */
      if (priv->icon1)
        {
          child_box.y1 = padding.top + (header_h / 2.0) - (icon1_h / 2.0);
          child_box.x1 = padding.left;
          child_box.y2 = child_box.y1 + icon1_h;
          child_box.x2 = child_box.x1 + icon1_w;

          clutter_actor_allocate (priv->icon1, &child_box, flags);
          child_box.x1 += icon1_w + 8;
        }
      else
        child_box.x1 = padding.left;

      /* label */
      child_box.x2 = child_box.x1 + label_w;
      child_box.y1 = (int) (padding.top + (header_h / 2.0) - (label_h / 2.0));
      child_box.y2 = child_box.y1 + label_h;

      fade = clutter_actor_get_effect (priv->box_layout, "fade");

      middle_w = available_width - icon1_w - icon2_w;
      if (priv->header_padding)
        middle_w -= priv->header_padding->left + priv->header_padding->right;
      clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (fade),
                                      !(middle_w > label_w));
      mx_fade_effect_set_bounds (MX_FADE_EFFECT (fade), 0, 0, middle_w, 0);

      clutter_actor_allocate (priv->box_layout, &child_box, flags);

      /* secondary icon */
      if (priv->icon2)
        {
          child_box.x2 = (box->x2 - box->x1) - padding.right;
          child_box.x1 = child_box.x2 - icon2_w;
          child_box.y1 = padding.top + (header_h / 2.0) - (icon2_h / 2.0);
          child_box.y2 = child_box.y1 + icon2_h;

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

      priv->header_height = header_h;
      if (priv->header_padding)
        priv->header_height += priv->header_padding->top
          + priv->header_padding->bottom;
    }
}
/* Re-layout and allocate children of container we manage */
static void _xfdashboard_scaled_table_layout_allocate(ClutterLayoutManager *self,
        ClutterContainer *inContainer,
        const ClutterActorBox *inAllocation,
        ClutterAllocationFlags inFlags)
{
    XfdashboardScaledTableLayoutPrivate		*priv;
    gint									row, col;
    ClutterActor							*child;
    ClutterActorIter						iter;
    gfloat									cellWidth, cellHeight;
    gfloat									childWidth, childHeight;
    gfloat									scaledChildWidth, scaledChildHeight;
    gfloat									largestWidth, largestHeight;
    gfloat									scaleWidth, scaleHeight;
    gfloat									aspectRatio;
    gfloat									x, y;
    ClutterActorBox							childAllocation;

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

    priv=XFDASHBOARD_SCALED_TABLE_LAYOUT(self)->priv;

    /* Get size of container holding children to layout and
     * determine size of a cell
     */
    clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &childWidth, &childHeight);

    cellWidth=childWidth-((priv->columns-1)*priv->columnSpacing);
    cellWidth=floor(cellWidth/priv->columns);

    cellHeight=childHeight-((priv->rows-1)*priv->rowSpacing);
    cellHeight=floor(cellHeight/priv->rows);

    /* Iterate through children and find largest one
     * if relative scale was set
     */
    largestWidth=largestHeight=0.0f;
    if(priv->relativeScale==TRUE)
    {
        gfloat								w, h;

        clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
        while(clutter_actor_iter_next(&iter, &child))
        {
            if(!CLUTTER_ACTOR_IS_VISIBLE(child)) continue;

            clutter_actor_get_preferred_size(child, NULL, NULL, &w, &h);
            if(w>largestWidth) largestWidth=w;
            if(h>largestHeight) largestHeight=h;
        }
    }

    /* Iterate through child actors and set their new allocation */
    row=col=0;
    x=y=0.0f;
    clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
    while(clutter_actor_iter_next(&iter, &child))
    {
        if(!CLUTTER_ACTOR_IS_VISIBLE(child)) continue;

        /* Get natural size of actor */
        clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);

        /* If either width or height is 0 then it is visually hidden and we
         * skip expensive calculation. This also has the nice effect that
         * do not perform invalid divisions by zero ;)
         */
        if(childWidth>0.0f && childHeight>0.0f)
        {
            /* Get scale factor needed to apply to width and height.
             * If no relative scaling should be performed the scale is always 1.0
             * otherwise it is the scale factor for this actor to the largest one.
             */
            if(priv->relativeScale==TRUE)
            {
                /* Get scale factors */
                scaleWidth=childWidth/largestWidth;
                scaleHeight=childHeight/largestHeight;
            }
            else scaleWidth=scaleHeight=1.0f;

            /* Get aspect ratio factor */
            aspectRatio=childHeight/childWidth;

            /* Calculate new size of child */
            scaledChildWidth=cellWidth*scaleWidth;
            scaledChildHeight=scaledChildWidth*aspectRatio;
            if(scaledChildHeight>cellHeight)
            {
                scaledChildHeight=cellHeight*scaleHeight;
                scaledChildWidth=scaledChildHeight/aspectRatio;
            }

            /* If upscaling should be prevent check if we are upscaling now */
            if(priv->preventUpscaling)
            {
                if(scaledChildWidth>childWidth)
                {
                    scaledChildWidth=childWidth;
                    scaledChildHeight=childWidth*aspectRatio;
                }

                if(scaledChildHeight>childHeight)
                {
                    scaledChildHeight=childHeight;
                    scaledChildWidth=childHeight/aspectRatio;
                }
            }
        }
        else
        {
            /* Visually hidden so do not allocate any space */
            scaledChildWidth=0.0f;
            scaledChildHeight=0.0f;
        }

        /* Set new allocation of child */
        childAllocation.x1=ceil(x+((cellWidth-scaledChildWidth)/2.0f));
        childAllocation.y1=ceil(y+((cellHeight-scaledChildHeight)/2.0f));
        childAllocation.x2=ceil(childAllocation.x1+scaledChildWidth);
        childAllocation.y2=ceil(childAllocation.y1+scaledChildHeight);
        clutter_actor_allocate(child, &childAllocation, inFlags);

        /* Set up for next child */
        col=(col+1) % priv->columns;
        if(col==0) row++;
        x=col*(cellWidth+priv->columnSpacing);
        y=row*(cellHeight+priv->rowSpacing);
    }
}
Beispiel #24
0
static void
st_box_layout_allocate (ClutterActor          *actor,
                        const ClutterActorBox *box,
                        ClutterAllocationFlags flags)
{
  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
  ClutterActorBox content_box;
  gfloat avail_width, avail_height, min_width, natural_width, min_height, natural_height;
  gfloat position, next_position;
  GList *l, *children;
  gint n_expand_children = 0, i;
  gfloat expand_amount, shrink_amount;
  BoxChildShrink *shrinks = NULL;
  gboolean flip = (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL)
                   && (!priv->is_vertical);

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

  children = st_container_get_children_list (ST_CONTAINER (actor));
  if (children == NULL)
    return;

  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;

  get_content_preferred_width (ST_BOX_LAYOUT (actor), avail_height,
                               &min_width, &natural_width);
  get_content_preferred_height (ST_BOX_LAYOUT (actor), MAX (avail_width, min_width),
                                &min_height, &natural_height);


  /* update adjustments for scrolling */
  if (priv->vadjustment)
    {
      gdouble prev_value;

      g_object_set (G_OBJECT (priv->vadjustment),
                    "lower", 0.0,
                    "upper", MAX (min_height, avail_height),
                    "page-size", avail_height,
                    "step-increment", avail_height / 6,
                    "page-increment", avail_height - avail_height / 6,
                    NULL);

      prev_value = st_adjustment_get_value (priv->vadjustment);
      st_adjustment_set_value (priv->vadjustment, prev_value);
    }

  if (priv->hadjustment)
    {
      gdouble prev_value;

      g_object_set (G_OBJECT (priv->hadjustment),
                    "lower", 0.0,
                    "upper", MAX (min_width, avail_width),
                    "page-size", avail_width,
                    "step-increment", avail_width / 6,
                    "page-increment", avail_width - avail_width / 6,
                    NULL);

      prev_value = st_adjustment_get_value (priv->hadjustment);
      st_adjustment_set_value (priv->hadjustment, prev_value);
    }

  if (avail_height < min_height)
    {
      avail_height = min_height;
      content_box.y2 = content_box.y1 + avail_height;
    }

  if (avail_width < min_width)
    {
      avail_width = min_width;
      content_box.x2 = content_box.x1 + avail_width;
    }

  if (priv->is_vertical)
    {
      expand_amount = MAX (0, avail_height - natural_height);
      shrink_amount = MAX (0, natural_height - avail_height);
    }
  else
    {
      expand_amount = MAX (0, avail_width - natural_width);
      shrink_amount = MAX (0, natural_width - avail_width);
    }


  if (expand_amount > 0)
    {
      /* count the number of children with expand set to TRUE */
      n_expand_children = 0;
      for (l = children; l; l = l->next)
        {
          ClutterActor *child = l->data;
          gboolean expand;

          if (!CLUTTER_ACTOR_IS_VISIBLE (child) ||
              clutter_actor_get_fixed_position_set (child))
            continue;

          clutter_container_child_get ((ClutterContainer *) actor,
                                       child,
                                       "expand", &expand,
                                       NULL);
          if (expand)
            n_expand_children++;
        }

      if (n_expand_children == 0)
        expand_amount = 0;
    }
  else if (shrink_amount > 0)
    {
      shrinks = compute_shrinks (ST_BOX_LAYOUT (actor),
                                 priv->is_vertical ? avail_width : avail_height,
                                 shrink_amount);
     }

  if (priv->is_vertical)
    position = content_box.y1;
  else if (flip)
    position = content_box.x2;
  else
    position = content_box.x1;

  if (priv->is_pack_start)
    {
      l = g_list_last (children);
      i = g_list_length (children);
    }
  else
    {
      l = children;
      i = 0;
    }
    
  gboolean firstchild = TRUE;
  gfloat init_padding = (avail_width/2) - (natural_width/2);
  while (l)
    {
      ClutterActor *child = (ClutterActor*) l->data;
      ClutterActorBox child_box;
      gfloat child_min, child_nat, child_allocated;
      gboolean xfill, yfill, expand, fixed;
      StAlign xalign, yalign;

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        goto next_child;

      fixed = clutter_actor_get_fixed_position_set (child);
      if (fixed)
        {
          clutter_actor_allocate_preferred_size (child, flags);
          goto next_child;
        }

      clutter_container_child_get ((ClutterContainer*) actor, child,
                                   "x-fill", &xfill,
                                   "y-fill", &yfill,
                                   "x-align", &xalign,
                                   "y-align", &yalign,
                                   "expand", &expand,
                                   NULL);

      if (priv->is_vertical)
        {
          _st_actor_get_preferred_height (child, avail_width, xfill,
                                          &child_min, &child_nat);
        }
      else
        {
          _st_actor_get_preferred_width (child, avail_height, yfill,
                                         &child_min, &child_nat);
        }

      child_allocated = child_nat;
      if (expand_amount > 0 && expand)
        child_allocated +=  expand_amount / n_expand_children;
      else if (shrink_amount > 0)
        child_allocated -= shrinks[i].shrink_amount;

      if (flip) {
        next_position = position - child_allocated;
        if (xalign == ST_ALIGN_CENTER_SPECIAL && next_position < content_box.x1)
          next_position = content_box.x1;
      }
      else {
        next_position = position + child_allocated;
        if (xalign == ST_ALIGN_CENTER_SPECIAL && next_position > content_box.x2)
          next_position = content_box.x2;
      }

      if (priv->is_vertical)
        {
          child_box.y1 = (int)(0.5 + position);
          child_box.y2 = (int)(0.5 + next_position);
          child_box.x1 = content_box.x1;
          child_box.x2 = content_box.x2;

          _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
                             xalign, yalign, xfill, yfill);
          clutter_actor_allocate (child, &child_box, flags);

        }
      else
        {
          if (flip)
            {
              if (firstchild && xalign == ST_ALIGN_CENTER_SPECIAL)
                {
                  position -= init_padding;
                  next_position = position - child_allocated;
                  firstchild = FALSE;
                }
                if (xalign == ST_ALIGN_CENTER_SPECIAL && position > content_box.x2) {
                  position = content_box.x2;
                }
              child_box.x1 = (int)(0.5 + next_position);
              child_box.x2 = (int)(0.5 + position);
            }
          else
            {
              if (firstchild && xalign == ST_ALIGN_CENTER_SPECIAL)
                {
                  position += init_padding;
                  if (position < content_box.x1) {
                    position = content_box.x1;
                  }
                  next_position = position + child_allocated;
                  firstchild = FALSE;
                }
              if (xalign == ST_ALIGN_CENTER_SPECIAL && position < content_box.x1) {
                    position = content_box.x1;
                  }
              child_box.x1 = (int)(0.5 + position);
              child_box.x2 = (int)(0.5 + next_position);
            }

          child_box.y1 = content_box.y1;
          child_box.y2 = content_box.y2;

          _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
                             xalign, yalign, xfill, yfill);
          clutter_actor_allocate (child, &child_box, flags);
        }

      if (flip)
        position = next_position - priv->spacing;
      else
        position = next_position + priv->spacing;

    next_child:
      if (priv->is_pack_start)
        {
          l = l->prev;
          i--;
        }
      else
        {
          l = l->next;
          i++;
        }
    }

  if (shrinks)
    g_free (shrinks);
}
Beispiel #25
0
static void
mx_expander_allocate (ClutterActor          *actor,
                      const ClutterActorBox *box,
                      ClutterAllocationFlags flags)
{
  MxExpanderPrivate *priv = MX_EXPANDER (actor)->priv;
  ClutterActorBox child_box;
  MxPadding padding;
  gfloat label_w, label_h;
  gfloat available_w, available_h, min_w, min_h, arrow_h, arrow_w;

  /* chain up to store allocation */
  CLUTTER_ACTOR_CLASS (mx_expander_parent_class)->allocate (actor, box, flags);

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  available_w = (box->x2 - box->x1) - padding.left - padding.right;
  available_h = (box->y2 - box->y1) - padding.top - padding.bottom;

  /* arrow */
  clutter_actor_get_preferred_width (priv->arrow, -1, NULL, &arrow_w);
  arrow_w = MIN (arrow_w, available_w);

  clutter_actor_get_preferred_height (priv->arrow, -1, NULL, &arrow_h);
  arrow_h = MIN (arrow_h, available_h);

  child_box.x1 = padding.left;
  child_box.x2 = child_box.x1 + arrow_w;
  child_box.y1 = padding.top;
  child_box.y2 = child_box.y1 + arrow_h;
  clutter_actor_allocate (priv->arrow, &child_box, flags);

  /* label */
  min_h = 0;
  min_w = 0;

  clutter_actor_get_preferred_width (priv->label,
                                     available_h, &min_w, &label_w);
  label_w = CLAMP (label_w, min_w, available_w);

  clutter_actor_get_preferred_height (priv->label,
                                      label_w, &min_h, &label_h);
  label_h = CLAMP (label_h, min_h, available_h);

  /* TODO: make a style property for padding between arrow and label */
  child_box.x1 = padding.left + arrow_w + 6.0f;
  child_box.x2 = child_box.x1 + label_w;
  child_box.y1 = padding.top;
  child_box.y2 = child_box.y1 + MAX (label_h, arrow_h);
  mx_allocate_align_fill (priv->label, &child_box, MX_ALIGN_START,
                          MX_ALIGN_MIDDLE, FALSE, FALSE);
  clutter_actor_allocate (priv->label, &child_box, flags);

  /* remove label height and spacing for child calculations */
  available_h -= MAX (label_h, arrow_h) + priv->spacing;

  /* child */
  if (priv->expanded && priv->child && CLUTTER_ACTOR_IS_VISIBLE (priv->child))
    {
      child_box.x1 = padding.left;
      child_box.x2 = child_box.x1 + available_w;
      child_box.y1 = padding.top + priv->spacing + MAX (label_h, arrow_h);
      child_box.y2 = child_box.y1 + available_h;

      clutter_actor_allocate (priv->child, &child_box, flags);
    }
}
Beispiel #26
0
static void
clutter_flow_layout_allocate (ClutterLayoutManager   *manager,
                              ClutterContainer       *container,
                              const ClutterActorBox  *allocation,
                              ClutterAllocationFlags  flags)
{
  ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv;
  ClutterActor *actor, *child;
  ClutterActorIter iter;
  gfloat x_off, y_off;
  gfloat avail_width, avail_height;
  gfloat item_x, item_y;
  gint line_item_count;
  gint items_per_line;
  gint line_index;

  actor = CLUTTER_ACTOR (container);
  if (clutter_actor_get_n_children (actor) == 0)
    return;

  clutter_actor_box_get_origin (allocation, &x_off, &y_off);
  clutter_actor_box_get_size (allocation, &avail_width, &avail_height);

  /* blow the cached preferred size and re-compute with the given
   * available size in case the FlowLayout wasn't given the exact
   * size it requested
   */
  if ((priv->req_width >= 0 && avail_width != priv->req_width) ||
      (priv->req_height >= 0 && avail_height != priv->req_height))
    {
      clutter_flow_layout_get_preferred_width (manager, container,
                                               avail_height,
                                               NULL, NULL);
      clutter_flow_layout_get_preferred_height (manager, container,
                                                avail_width,
                                                NULL, NULL);
    }

  items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager),
                                  avail_width, avail_height);

  item_x = x_off;
  item_y = y_off;

  line_item_count = 0;
  line_index = 0;

  clutter_actor_iter_init (&iter, actor);
  while (clutter_actor_iter_next (&iter, &child))
    {
      ClutterActorBox child_alloc;
      gfloat item_width, item_height;
      gfloat new_x, new_y;
      gfloat child_min, child_natural;

      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      new_x = new_y = 0;

      if (!priv->snap_to_grid)
        clutter_actor_get_preferred_size (child,
                                          NULL, NULL,
                                          &item_width,
                                          &item_height);

      if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
        {
          if ((priv->snap_to_grid &&
               line_item_count == items_per_line && line_item_count > 0) ||
              (!priv->snap_to_grid && item_x + item_width > avail_width))
            {
              item_y += g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

              if (line_index >= 0)
                item_y += priv->row_spacing;

              line_item_count = 0;
              line_index += 1;

              item_x = x_off;
            }

          if (priv->snap_to_grid)
            {
              new_x = x_off + ((line_item_count + 1) * (avail_width + priv->col_spacing))
                    / items_per_line;
              item_width = new_x - item_x - priv->col_spacing;
            }
          else
            {
              new_x = item_x + item_width + priv->col_spacing;
            }

          item_height = g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

        }
      else
        {
          if ((priv->snap_to_grid &&
               line_item_count == items_per_line && line_item_count > 0) ||
              (!priv->snap_to_grid && item_y + item_height > avail_height))
            {
              item_x += g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);

              if (line_index >= 0)
                item_x += priv->col_spacing;

              line_item_count = 0;
              line_index += 1;

              item_y = y_off;
            }

          if (priv->snap_to_grid)
            {
              new_y = y_off + ((line_item_count + 1) * (avail_height + priv->row_spacing))
                    / items_per_line;
              item_height = new_y - item_y - priv->row_spacing;
            }
          else
            {
              new_y = item_y + item_height + priv->row_spacing;
            }

          item_width = g_array_index (priv->line_natural,
                                      gfloat,
                                      line_index);
        }

      if (!priv->is_homogeneous &&
          !clutter_actor_needs_expand (child,
                                       CLUTTER_ORIENTATION_HORIZONTAL))
        {
          clutter_actor_get_preferred_width (child, item_height,
                                             &child_min,
                                             &child_natural);
          item_width = MIN (item_width, child_natural);
        }

      if (!priv->is_homogeneous &&
          !clutter_actor_needs_expand (child,
                                       CLUTTER_ORIENTATION_VERTICAL))
        {
          clutter_actor_get_preferred_height (child, item_width,
                                              &child_min,
                                              &child_natural);
          item_height = MIN (item_height, child_natural);
        }

      CLUTTER_NOTE (LAYOUT,
                    "flow[line:%d, item:%d/%d] ="
                    "{ %.2f, %.2f, %.2f, %.2f }",
                    line_index, line_item_count + 1, items_per_line,
                    item_x, item_y, item_width, item_height);

      child_alloc.x1 = ceil (item_x);
      child_alloc.y1 = ceil (item_y);
      child_alloc.x2 = ceil (child_alloc.x1 + item_width);
      child_alloc.y2 = ceil (child_alloc.y1 + item_height);
      clutter_actor_allocate (child, &child_alloc, flags);

      if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
        item_x = new_x;
      else
        item_y = new_y;

      line_item_count += 1;
    }
}