Ejemplo n.º 1
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;
    }
}
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);
    }
}