Exemplo n.º 1
0
static void
mex_tile_init (MexTile *self)
{
  MexTilePrivate *priv = self->priv = TILE_PRIVATE (self);
  const ClutterColor opaque = { 0x00, 0x00, 0x00, 0x00 };
  ClutterEffect *fade;

  /* create a template material for the header background from which cheap
   * copies can be made for each instance */
  if (G_UNLIKELY (!template_material))
    template_material = cogl_material_new ();

  priv->material = cogl_material_copy (template_material);


  /* layout for primary and secondary labels */
  priv->box_layout = mx_box_layout_new ();
  mx_box_layout_set_spacing (MX_BOX_LAYOUT (priv->box_layout), 12);

  /* add fade effect to the box layout */
  fade = (ClutterEffect*) mx_fade_effect_new ();
  mx_fade_effect_set_border (MX_FADE_EFFECT (fade), 0, 50, 0, 0);
  mx_fade_effect_set_color (MX_FADE_EFFECT (fade), &opaque);
  clutter_actor_add_effect_with_name (priv->box_layout, "fade", fade);
  clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (fade), TRUE);

  clutter_actor_push_internal (CLUTTER_ACTOR (self));
  clutter_actor_set_parent (priv->box_layout, CLUTTER_ACTOR (self));
  clutter_actor_pop_internal (CLUTTER_ACTOR (self));


  priv->label = clutter_text_new ();
  priv->secondary_label = clutter_text_new ();
  clutter_actor_set_opacity (priv->secondary_label, 128);

  clutter_container_add (CLUTTER_CONTAINER (priv->box_layout), priv->label,
                         priv->secondary_label, NULL);

  priv->header_visible = TRUE;

  priv->timeline = clutter_timeline_new (DURATION);
  priv->important_alpha =
    clutter_alpha_new_full (priv->timeline, CLUTTER_EASE_OUT_QUAD);
  g_signal_connect_object (priv->timeline, "new-frame",
                           G_CALLBACK (mex_tile_important_new_frame_cb), self,
                           0);
  g_signal_connect_object (priv->timeline, "completed",
                           G_CALLBACK (mex_tile_timeline_completed_cb), self,
                           0);

  g_signal_connect (self, "style-changed",
                    G_CALLBACK (mex_tile_style_changed_cb), NULL);

  g_signal_connect (self, "actor-added",
                    G_CALLBACK (mex_tile_actor_added), NULL);
  g_signal_connect (self, "actor-removed",
                    G_CALLBACK (mex_tile_actor_removed), NULL);
}
Exemplo n.º 2
0
static void
mx_fade_effect_post_paint (ClutterEffect *effect)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (effect)->priv;

  if (!priv->freeze_update)
    CLUTTER_EFFECT_CLASS (mx_fade_effect_parent_class)->post_paint (effect);
  else
    {
      CoglMatrix modelview;
      ClutterActor *actor, *stage;

      actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
      stage = clutter_actor_get_stage (actor);

      /* Set up the draw matrix so we draw the offscreen texture at the
       * absolute coordinates of the actor-box. We need to do this to
       * avoid transforming by the actor matrix twice, as when it's drawn
       * into the offscreen surface, it'll already be transformed.
       */
      cogl_push_matrix ();

      cogl_matrix_init_identity (&modelview);
      CLUTTER_ACTOR_CLASS (G_OBJECT_GET_CLASS (stage))->
        apply_transform (stage, &modelview);
      cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.f);
      cogl_set_modelview_matrix (&modelview);

      clutter_offscreen_effect_paint_target (CLUTTER_OFFSCREEN_EFFECT (effect));

      cogl_pop_matrix ();
    }
}
Exemplo n.º 3
0
static gboolean
mx_fade_effect_pre_paint (ClutterEffect *effect)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (effect)->priv;

  if (!priv->freeze_update)
    {
      return CLUTTER_EFFECT_CLASS (mx_fade_effect_parent_class)->
        pre_paint (effect);
    }
  else
    {
      ClutterActorBox box;
      ClutterActor *actor =
        clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));

      /* Store the stage coordinates of the actor for when we post-paint */
      clutter_actor_get_paint_box (actor, &box);
      clutter_actor_box_get_origin (&box, &priv->x_offset, &priv->y_offset);

      /* Connect to the paint signal so we can block it */
      priv->blocked_id =
        g_signal_connect (actor, "paint",
                          G_CALLBACK (mx_fade_effect_paint_cb), effect);

      return TRUE;
    }
}
static void
mx_label_label_changed_cb (MxLabel *label)
{
  MxLabelPrivate *priv = label->priv;

  /* Enable updating of the off-screen texture */
  _mx_fade_effect_set_freeze_update (MX_FADE_EFFECT (priv->fade_effect), FALSE);
}
Exemplo n.º 5
0
static void
mx_fade_effect_set_property (GObject      *object,
                             guint         property_id,
                             const GValue *value,
                             GParamSpec   *pspec)
{
  MxFadeEffect *effect = MX_FADE_EFFECT (object);
  MxFadeEffectPrivate *priv = effect->priv;

  switch (property_id)
    {
    case PROP_BOUNDS_X:
      priv->x = g_value_get_int (value);
      break;

    case PROP_BOUNDS_Y:
      priv->y = g_value_get_int (value);
      break;

    case PROP_BOUNDS_WIDTH:
      priv->bounds_width = g_value_get_uint (value);
      break;

    case PROP_BOUNDS_HEIGHT:
      priv->bounds_height = g_value_get_uint (value);
      break;

    case PROP_BORDER_TOP:
      priv->border[0] = g_value_get_uint (value);
      break;

    case PROP_BORDER_RIGHT:
      priv->border[1] = g_value_get_uint (value);
      break;

    case PROP_BORDER_BOTTOM:
      priv->border[2] = g_value_get_uint (value);
      break;

    case PROP_BORDER_LEFT:
      priv->border[3] = g_value_get_uint (value);
      break;

    case PROP_COLOR:
      priv->color = *(clutter_value_get_color (value));
      break;

    case PROP_FREEZE_UPDATE:
      priv->freeze_update = g_value_get_boolean (value);
      return;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      return;
    }

  priv->update_vbo = TRUE;
}
Exemplo n.º 6
0
static void
mx_fade_effect_get_property (GObject    *object,
                             guint       property_id,
                             GValue     *value,
                             GParamSpec *pspec)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (object)->priv;

  switch (property_id)
    {
    case PROP_BOUNDS_X:
      g_value_set_int (value, priv->x);
      break;

    case PROP_BOUNDS_Y:
      g_value_set_int (value, priv->y);
      break;

    case PROP_BOUNDS_WIDTH:
      g_value_set_uint (value, priv->bounds_width);
      break;

    case PROP_BOUNDS_HEIGHT:
      g_value_set_uint (value, priv->bounds_height);
      break;

    case PROP_BORDER_TOP:
      g_value_set_uint (value, priv->border[0]);
      break;

    case PROP_BORDER_RIGHT:
      g_value_set_uint (value, priv->border[1]);
      break;

    case PROP_BORDER_BOTTOM:
      g_value_set_uint (value, priv->border[2]);
      break;

    case PROP_BORDER_LEFT:
      g_value_set_uint (value, priv->border[3]);
      break;

    case PROP_COLOR:
      clutter_value_set_color (value, &priv->color);
      break;

    case PROP_FREEZE_UPDATE:
      g_value_set_boolean (value, priv->freeze_update);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}
static void
mx_label_paint (ClutterActor *actor)
{
  MxLabelPrivate *priv = MX_LABEL (actor)->priv;
  ClutterActorClass *parent_class;

  parent_class = CLUTTER_ACTOR_CLASS (mx_label_parent_class);
  parent_class->paint (actor);

  clutter_actor_paint (priv->label);
  _mx_fade_effect_set_freeze_update (MX_FADE_EFFECT (priv->fade_effect), TRUE);
}
Exemplo n.º 8
0
static void
mx_fade_effect_paint_target (ClutterOffscreenEffect *effect)
{
  guint8 opacity;
  CoglColor color;
  ClutterActor *actor;

  CoglMaterial *material = clutter_offscreen_effect_get_target (effect);
  MxFadeEffect *self = MX_FADE_EFFECT (effect);
  MxFadeEffectPrivate *priv = self->priv;

  if (priv->update_vbo)
    mx_fade_effect_update_vbo (self);

  if (!priv->vbo || !priv->indices || !material)
    return;

  /* Set the blend string if the material has changed so we can blend with
   * the paint opacity.
   */
  if (material != priv->old_material)
    {
      GError *error = NULL;
      priv->old_material = material;

      if (!cogl_material_set_layer_combine (material, 1,
                                            "RGBA = MODULATE(PREVIOUS,CONSTANT)", &error))
        {
          g_warning (G_STRLOC ": Error setting layer combine blend string: %s",
                     error->message);
          g_error_free (error);
        }
    }

  /* Set the layer-combine constant so the texture is blended with the paint
   * opacity when painted.
   */
  actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
  opacity = clutter_actor_get_paint_opacity (actor);
  cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
  cogl_material_set_layer_combine_constant (material, 1, &color);

  /* Draw the texture */
  cogl_set_source (material);
  cogl_vertex_buffer_draw_elements (priv->vbo,
                                    COGL_VERTICES_MODE_TRIANGLES,
                                    priv->indices,
                                    0,
                                    (priv->n_quads * 4) - 1,
                                    0,
                                    priv->n_quads * 6);
}
Exemplo n.º 9
0
static CoglHandle
mx_fade_effect_create_texture (ClutterOffscreenEffect *effect,
                               gfloat                  width,
                               gfloat                  height)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (effect)->priv;

  priv->width = width;
  priv->height = height;
  priv->update_vbo = TRUE;

  return CLUTTER_OFFSCREEN_EFFECT_CLASS (mx_fade_effect_parent_class)->
    create_texture (effect, width, height);
}
Exemplo n.º 10
0
static void
notify_vertical_changed_cb (MxAdjustment     *adjustment,
                            MexMediaControls *controls)
{
    MexMediaControlsPrivate *priv = controls->priv;
    gint bottom;
    gdouble value, max, page_size;

    max = mx_adjustment_get_upper (adjustment);
    value = mx_adjustment_get_value (adjustment);
    page_size = mx_adjustment_get_page_size (adjustment);

    bottom = MIN (50, (max - value - page_size));

    mx_fade_effect_set_border (MX_FADE_EFFECT (priv->vertical_effect),
                               0, 0, bottom, 0);
}
Exemplo n.º 11
0
static void
notify_horizontal_changed_cb (MxAdjustment     *adjustment,
                              MexMediaControls *controls)
{
    MexMediaControlsPrivate *priv = controls->priv;
    gint left, right;
    gdouble value, min, max, page_size;

    min = mx_adjustment_get_lower (adjustment);
    max = mx_adjustment_get_upper (adjustment);
    value = mx_adjustment_get_value (adjustment);
    page_size = mx_adjustment_get_page_size (adjustment);

    left = MIN (136, (value - min));
    right = MIN (136, (max - value - page_size));

    mx_fade_effect_set_border (MX_FADE_EFFECT (priv->horizontal_effect),
                               0, right, 0, left);
}
static void
mx_label_fade_new_frame_cb (ClutterTimeline *timeline,
                            gint             msecs,
                            MxLabel         *self)
{
  guint8 a;
  ClutterColor color;

  MxLabelPrivate *priv = self->priv;

  a = (1.0 - clutter_alpha_get_alpha (priv->fade_alpha)) * 255;

  color.red = a;
  color.green = a;
  color.blue = a;
  color.alpha = a;

  mx_fade_effect_set_color (MX_FADE_EFFECT (priv->fade_effect), &color);

  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
Exemplo n.º 13
0
static void
mx_fade_effect_dispose (GObject *object)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (object)->priv;

  if (priv->vbo)
    {
      cogl_handle_unref (priv->vbo);
      priv->vbo = NULL;
    }

  if (priv->blocked_id)
    {
      ClutterActor *actor =
        clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (object));

      g_signal_handler_disconnect (actor, priv->blocked_id);
      priv->blocked_id = 0;
    }

  G_OBJECT_CLASS (mx_fade_effect_parent_class)->dispose (object);
}
static void
mx_label_init (MxLabel *label)
{
  MxLabelPrivate *priv;
  const ClutterColor opaque = { 0xff, 0xff, 0xff, 0xff };

  label->priv = priv = MX_LABEL_GET_PRIVATE (label);

  priv->label = g_object_new (CLUTTER_TYPE_TEXT,
                              "ellipsize", PANGO_ELLIPSIZE_END,
                              NULL);

  clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label));

  priv->fade_effect = mx_fade_effect_new ();
  mx_fade_effect_set_color (MX_FADE_EFFECT (priv->fade_effect), &opaque);
  clutter_actor_add_effect (priv->label, priv->fade_effect);
  clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (priv->fade_effect),
                                  FALSE);

  g_signal_connect (label, "style-changed",
                    G_CALLBACK (mx_label_style_changed), NULL);
  g_signal_connect (priv->label, "notify::single-line-mode",
                    G_CALLBACK (mx_label_single_line_mode_cb), label);
  g_signal_connect_swapped (priv->label, "queue-redraw",
                            G_CALLBACK (mx_label_label_changed_cb), label);

  priv->fade_timeline = clutter_timeline_new (250);
  priv->fade_alpha = clutter_alpha_new_full (priv->fade_timeline,
                                             CLUTTER_EASE_OUT_QUAD);
  g_signal_connect (priv->fade_timeline, "new-frame",
                    G_CALLBACK (mx_label_fade_new_frame_cb), label);
  g_signal_connect (priv->fade_timeline, "started",
                    G_CALLBACK (mx_label_fade_started_cb), label);
  g_signal_connect (priv->fade_timeline, "completed",
                    G_CALLBACK (mx_label_fade_completed_cb), label);
}
static void
mx_label_font_description_cb (ClutterText *text,
                              GParamSpec  *pspec,
                              MxLabel     *self)
{
  PangoFontDescription *font;

  MxLabelPrivate *priv = self->priv;

  /* Find out the em-width - code pretty much copied from Clutter,
   * clutter-backend.c, get_units_per_em ()
   */
  font = clutter_text_get_font_description (text);
  if (font)
    {
      gint i_dpi;
      gdouble dpi;

      gdouble font_size = 0;
      gint pango_size = pango_font_description_get_size (font);
      ClutterSettings *settings = clutter_settings_get_default ();

      g_object_get (G_OBJECT (settings), "font-dpi", &i_dpi, NULL);
      dpi = i_dpi / 1024.0;

      if (pango_font_description_get_size_is_absolute (font))
        font_size = pango_size / PANGO_SCALE;
      else
        font_size = pango_size / PANGO_SCALE * dpi / 96.f;

      priv->em_width = (1.2f * font_size) * dpi / 96.f;

      mx_fade_effect_set_border (MX_FADE_EFFECT (priv->fade_effect),
                                 0, priv->em_width * 5, 0, 0);
    }
}
Exemplo n.º 16
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);
    }
}