static void
_update_logo (MexContentTile *tile)
{
  ClutterActor *image;
  GError *err = NULL;
  const gchar *logo_url;

  logo_url = mex_content_get_metadata (tile->priv->content,
                                       MEX_CONTENT_METADATA_STATION_LOGO);
  if (!logo_url)
    {
      mex_tile_set_primary_icon (MEX_TILE (tile), NULL);
      return;
    }

  image = mx_image_new ();

  if (g_str_has_prefix (logo_url, "file://"))
    logo_url = logo_url + 7;

  mx_image_set_from_file_at_size (MX_IMAGE (image), logo_url, 26, 26, &err);

  if (err)
    {
      g_warning ("Could not load station logo: %s", err->message);
      g_clear_error (&err);
      return;
    }

  mex_tile_set_primary_icon (MEX_TILE (tile), image);
}
Example #2
0
static void
mex_tile_get_preferred_height (ClutterActor *actor,
                               gfloat        for_width,
                               gfloat       *min_height_p,
                               gfloat       *nat_height_p)
{
  MxPadding padding;
  gfloat box_height, label_h, icon1_h, icon2_h;

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

  CLUTTER_ACTOR_CLASS (mex_tile_parent_class)->
    get_preferred_height (actor, for_width, NULL, nat_height_p);

  mx_widget_get_padding (MX_WIDGET (actor), &padding);
  for_width -= padding.left + padding.right;

  /* Header */
  clutter_actor_get_preferred_height (priv->box_layout, for_width, NULL, &label_h);

  if (priv->icon1)
    clutter_actor_get_preferred_height (priv->icon1, for_width, NULL, &icon1_h);
  else
    icon1_h = 0;

  if (priv->icon2)
    clutter_actor_get_preferred_height (priv->icon2, for_width, NULL, &icon2_h);
  else
    icon2_h = 0;

  box_height = MAX (label_h, MAX (icon1_h, icon2_h)) +
    ((priv->header_padding) ? priv->header_padding->top + priv->header_padding->bottom : 0);


  /* Override the minimum height with the height of the box */
  if (min_height_p)
    *min_height_p = box_height;

  if (nat_height_p)
    {
      gdouble progress;

      /* When the timeline is at 0.5, the actor isn't visible - this is
       * the time where we switch sizes between the natural height and the
       * box height.
       */
      if (clutter_alpha_get_alpha (priv->important_alpha) < 0.5)
        progress = 0.0;
      else
        progress = 1.0;

      if (*nat_height_p < box_height)
        *nat_height_p = box_height;
      else if (progress == 0.0)
        *nat_height_p = box_height;
      else if (progress < 1.0)
        *nat_height_p = (box_height * (1.0 - progress)) +
                        (*nat_height_p * progress);
    }
}
static void
mex_content_box_notify_key_focus_cb (ClutterStage  *stage,
                                     GParamSpec    *pspec,
                                     MexContentBox *self)
{
  MexContentBoxPrivate *priv = self->priv;
  ClutterActor *focus = clutter_stage_get_key_focus (stage);

  if (focus == priv->tile)
    {
      gboolean show_info;

      if (mex_content_get_metadata (priv->content,
                                    MEX_CONTENT_METADATA_SYNOPSIS) ||
          mex_content_get_metadata (priv->content,
                                    MEX_CONTENT_METADATA_DATE) ||
          mex_content_get_metadata (priv->content,
                                    MEX_CONTENT_METADATA_CREATION_DATE) ||
          mex_content_get_metadata (priv->content,
                                    MEX_CONTENT_METADATA_DURATION))
        show_info = TRUE;
      else
        {
          MexActionManager *manager = mex_action_manager_get_default ();
          GList *actions =
            mex_action_manager_get_actions_for_content (manager, priv->content);

          if (actions && actions->next)
            show_info = TRUE;
          else
            show_info = FALSE;

          g_list_free (actions);
        }

      if (show_info)
        {
          ClutterActor *icon = mx_icon_new ();
          mx_stylable_set_style_class (MX_STYLABLE (icon), "Info");
          mex_tile_set_secondary_icon (MEX_TILE (priv->tile), icon);
        }
    }
  else
    mex_tile_set_secondary_icon (MEX_TILE (priv->tile), NULL);
}
Example #4
0
static void
mex_tile_actor_removed (ClutterActor *container,
                        ClutterActor *actor)
{
  MexTilePrivate *priv = MEX_TILE (container)->priv;

  if (priv->child == actor)
    priv->child = NULL;
}
Example #5
0
static void
mex_tile_paint (ClutterActor *actor)
{
  MexTilePrivate *priv = MEX_TILE (actor)->priv;
  MxPadding padding;
  ClutterActorBox box;

  CLUTTER_ACTOR_CLASS (mex_tile_parent_class)->paint (actor);

  clutter_actor_paint (priv->child);

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  if (priv->header_visible)
    {
      clutter_actor_get_allocation_box (actor, &box);


      if (priv->header_background_color)
        {
          cogl_set_source_color4ub (priv->header_background_color->red,
                                    priv->header_background_color->green,
                                    priv->header_background_color->blue,
                                    priv->header_background_color->alpha);

          cogl_rectangle (padding.left, padding.top,
                          box.x2 - box.x1 - padding.right,
                          priv->header_height);
        }


      if (cogl_material_get_n_layers (priv->material) > 0)
        {
          guint8 opacity;

          opacity = clutter_actor_get_paint_opacity (actor);

          cogl_material_set_color4ub (priv->material, opacity, opacity, opacity,
                                      opacity);
          cogl_set_source (priv->material);

          cogl_rectangle (padding.left, padding.top,
                          box.x2 - box.x1 - padding.right,
                          priv->header_height);
        }

      clutter_actor_paint (priv->box_layout);

      if (priv->icon1)
        clutter_actor_paint (priv->icon1);

      if (priv->icon2)
        clutter_actor_paint (priv->icon2);
    }
}
Example #6
0
static void
_update_title (MexContentTile *tile)
{
  MexContentTilePrivate *priv = tile->priv;
  const gchar *title;

  /* set title */
  title = mex_content_get_metadata (priv->content, MEX_CONTENT_METADATA_TITLE);

  mex_tile_set_label (MEX_TILE (tile), title);
}
static gboolean
mex_content_box_key_press_event_cb (ClutterActor    *actor,
                                    ClutterKeyEvent *event,
                                    MexExpanderBox  *drawer)
{
  gboolean open;

  MexActionManager *manager = mex_action_manager_get_default ();
  MexContentBoxPrivate *priv = MEX_CONTENT_BOX (drawer)->priv;

  if (event->keyval != MEX_KEY_OK &&
      event->keyval != MEX_KEY_INFO)
    {
      return FALSE;
    }

  if (event->keyval == MEX_KEY_OK)
    {
      GList *actions;

      actions = mex_action_manager_get_actions_for_content (manager,
                                                            priv->content);

      if (actions)
        {
          MxAction *action = actions->data;

          mex_action_set_content (action, priv->content);
          mex_action_set_context (action, priv->model);

          g_signal_emit_by_name (action, "activated", 0);

          g_list_free (actions);

          return TRUE;
        }
    }

  open = !mex_expander_box_get_open (drawer);

  /* We only want to expand the box if we have either more than one action,
   * or we have description metadata. We already track this when determining
   * if the info icon should be visible, so use that to determine whether
   * we should allow opening here.
   */
  if (open && !mex_tile_get_secondary_icon (MEX_TILE (priv->tile)))
    return FALSE;

  mex_expander_box_set_open (drawer, open);
  mex_expander_box_set_open (MEX_EXPANDER_BOX (priv->box), open);

  return TRUE;
}
Example #8
0
static void
mex_tile_finalize (GObject *object)
{
  MexTile *self = MEX_TILE (object);

  if (self->priv->header_background_color)
    {
      g_boxed_free (CLUTTER_TYPE_COLOR, self->priv->header_background_color);
      self->priv->header_background_color = NULL;
    }

  G_OBJECT_CLASS (mex_tile_parent_class)->finalize (object);
}
Example #9
0
static void
mex_tile_actor_added (ClutterActor *container,
                      ClutterActor *actor)
{
  MexTilePrivate *priv = MEX_TILE (container)->priv;

  if (MX_IS_TOOLTIP (actor))
    return;

  if (priv->child)
    clutter_actor_remove_child (container, priv->child);

  priv->child = actor;
}
static void
tile_created_cb (MexProxy *proxy,
                 GObject  *content,
                 GObject  *object,
                 gpointer  controls)
{
    const gchar *mime_type;
    ClutterEffect *effect;
    ClutterColor color = { 0, 0, 0, 60 };

    /* filter out folders */
    mime_type = mex_content_get_metadata (MEX_CONTENT (content),
                                          MEX_CONTENT_METADATA_MIMETYPE);

    if (g_strcmp0 (mime_type, "x-grl/box") == 0)
    {
        g_signal_stop_emission_by_name (proxy, "object-created");
        return;
    }

    mex_tile_set_important (MEX_TILE (object), TRUE);
    clutter_actor_set_reactive (CLUTTER_ACTOR (object), TRUE);

    g_object_set (object, "thumb-height", 140, "thumb-width", 250, NULL);

    g_signal_connect (object, "key-press-event", G_CALLBACK (key_press_event_cb),
                      controls);
    g_signal_connect (object, "button-release-event",
                      G_CALLBACK (button_release_event_cb), controls);

    effect = g_object_new (MEX_TYPE_SHADOW,
                           "radius-x", 15,
                           "radius-y", 15,
                           "color", &color,
                           "enabled", FALSE,
                           NULL);
    clutter_actor_add_effect_with_name (CLUTTER_ACTOR (object), "shadow", effect);

    effect = g_object_new (MEX_TYPE_SHADOW,
                           "radius-x", 15,
                           "radius-y", 15,
                           "color", &color,
                           NULL);
    clutter_actor_add_effect_with_name (mx_bin_get_child (MX_BIN (object)),
                                        "shadow", effect);

    g_signal_connect (object, "focus-in", G_CALLBACK (tile_focus_in_cb), NULL);
    g_signal_connect (object, "focus-out", G_CALLBACK (tile_focus_out_cb), NULL);
    tile_focus_out_cb (MX_BIN (object));
}
Example #11
0
static void
mex_tile_dispose (GObject *object)
{
  MexTile *self = MEX_TILE (object);
  MexTilePrivate *priv = self->priv;

  /* Use icon setting functions to remove icons */
  mex_tile_set_primary_icon (self, NULL);
  mex_tile_set_secondary_icon (self, NULL);

  if (priv->box_layout)
    {
      clutter_actor_destroy (priv->box_layout);
      priv->box_layout = NULL;

      /* box_layout contains label and secondary_label */
      priv->label = NULL;
      priv->secondary_label = NULL;
    }

  if (priv->header_padding)
    {
      g_boxed_free (MX_TYPE_PADDING, priv->header_padding);
      priv->header_padding = NULL;
    }

  if (priv->important_alpha)
    {
      g_object_unref (priv->important_alpha);
      priv->important_alpha = NULL;
    }

  if (priv->timeline)
    {
      clutter_timeline_stop (priv->timeline);
      g_object_unref (priv->timeline);
      priv->timeline = NULL;
    }

  if (priv->material)
    {
      cogl_object_unref (priv->material);
      priv->material = NULL;
    }

  G_OBJECT_CLASS (mex_tile_parent_class)->dispose (object);
}
Example #12
0
static void
mex_content_box_init (MexContentBox *self)
{
  MexContentBoxPrivate *priv = self->priv = CONTENT_BOX_PRIVATE (self);
  ClutterActor *icon;

  clutter_actor_push_internal (CLUTTER_ACTOR (self));

  priv->info_panel = mex_info_panel_new (MEX_INFO_PANEL_MODE_SIMPLE);
  clutter_actor_set_parent (priv->info_panel, CLUTTER_ACTOR (self));

  /* monitor key press events */
  g_signal_connect (self, "key-press-event",
                    G_CALLBACK (mex_content_box_key_press_event_cb), NULL);

  /* Create tile */
  icon = mx_icon_new ();
  priv->tile = mex_content_tile_new ();
  clutter_actor_set_parent (priv->tile, CLUTTER_ACTOR (self));
  g_object_set (G_OBJECT (priv->tile),
                "thumb-width", DEFAULT_THUMB_WIDTH,
                "thumb-height", DEFAULT_THUMB_HEIGHT,
                NULL);
  mx_stylable_set_style_class (MX_STYLABLE (icon), "Info");
  mex_tile_set_secondary_icon (MEX_TILE (priv->tile), icon);


  clutter_actor_set_reactive (priv->tile, TRUE);
  g_signal_connect (priv->tile, "button-release-event",
                    G_CALLBACK (mex_content_box_tile_clicked_cb), self);

  /* Create the action list */
  priv->action_list = mex_action_list_new ();
  clutter_actor_set_parent (priv->action_list, CLUTTER_ACTOR (self));

  clutter_actor_pop_internal (CLUTTER_ACTOR (self));


  priv->timeline = clutter_timeline_new (200);
  priv->alpha = clutter_alpha_new_full (priv->timeline, CLUTTER_EASE_OUT_CUBIC);

  g_signal_connect_swapped (priv->timeline, "new-frame",
                            G_CALLBACK (clutter_actor_queue_relayout), self);
  g_signal_connect (priv->timeline, "completed",
                    G_CALLBACK (mex_content_box_timeline_completed), self);
}
Example #13
0
static void
mex_tile_get_preferred_width (ClutterActor *actor,
                              gfloat        for_height,
                              gfloat       *min_height_p,
                              gfloat       *nat_height_p)
{
  MexTilePrivate *priv = MEX_TILE (actor)->priv;
  MxPadding padding;

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  for_height -= padding.top + padding.bottom;
  clutter_actor_get_preferred_width (priv->child, for_height, min_height_p,
                                     nat_height_p);
  if (min_height_p)
    *min_height_p += padding.top + padding.bottom;

  if (nat_height_p)
    *nat_height_p += padding.top + padding.bottom;
}
Example #14
0
static void
mex_tile_set_property (GObject      *object,
                       guint         property_id,
                       const GValue *value,
                       GParamSpec   *pspec)
{
  MexTile *self = MEX_TILE (object);

  switch (property_id)
    {
    case PROP_PRIMARY_ICON:
      mex_tile_set_primary_icon (self, g_value_get_object (value));
      break;

    case PROP_SECONDARY_ICON:
      mex_tile_set_secondary_icon (self, g_value_get_object (value));
      break;

    case PROP_LABEL:
      mex_tile_set_label (self, g_value_get_string (value));
      break;

    case PROP_SECONDARY_LABEL:
      mex_tile_set_secondary_label (self, g_value_get_string (value));
      break;

    case PROP_HEADER_VISIBLE:
      mex_tile_set_header_visible (self, g_value_get_boolean (value));
      break;

    case PROP_IMPORTANT:
      mex_tile_set_important (self, g_value_get_boolean (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}
Example #15
0
static void
mex_column_add (ClutterContainer *container,
                ClutterActor     *actor)
{
  MexColumn *self = MEX_COLUMN (container);
  MexColumnPrivate *priv = self->priv;

  if (priv->sort_func)
    priv->children =
      g_list_insert_sorted_with_data (priv->children, actor,
                                      (GCompareDataFunc)priv->sort_func,
                                      priv->sort_data);
  else
    priv->children = g_list_append (priv->children, actor);

  priv->n_items ++;

  /* Expand/collapse any drawer that gets added as appropriate */
  if (MEX_IS_EXPANDER_BOX (actor))
    {
      g_signal_connect (actor, "notify::open",
                        G_CALLBACK (expander_box_open_notify), container);

      mex_expander_box_set_important (MEX_EXPANDER_BOX (actor),
                                      priv->has_focus);

      if (MEX_IS_CONTENT_BOX (actor))
        {
          ClutterActor *tile =
            mex_content_box_get_tile (MEX_CONTENT_BOX (actor));
          mex_tile_set_important (MEX_TILE (tile), priv->has_focus);
        }
    }

  clutter_actor_set_parent (actor, CLUTTER_ACTOR (self));

  g_signal_emit_by_name (self, "actor-added", actor);
}
int
main (int argc, char **argv)
{
  const ClutterColor red = { 0xff, 0x00, 0x00, 0xff };
  ClutterActor *stage, *box, *tile, *rectangle;

  clutter_init (&argc, &argv);

  mex_style_load_default ();

  stage = clutter_stage_get_default ();
  clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);

  tile = mex_tile_new_with_label ("Red rectangle");
  mex_tile_set_important (MEX_TILE (tile), TRUE);
  rectangle = clutter_rectangle_new_with_color (&red);
  clutter_actor_set_size (rectangle, 300, 300);
  mx_bin_set_child (MX_BIN (tile), rectangle);

  box = mex_expander_box_new ();
  clutter_container_add (CLUTTER_CONTAINER (box), tile,
                         clutter_text_new_with_text ("Sans 16", "Hello"),
                         NULL);

  clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);

  clutter_actor_set_reactive (rectangle, TRUE);
  g_signal_connect_swapped (rectangle, "enter-event",
                            G_CALLBACK (toggle_important), box);

  clutter_actor_show (stage);

  clutter_main ();

  return 0;
}
Example #17
0
gboolean
mex_content_box_get_important (MexContentBox *box)
{
  return mex_tile_get_important (MEX_TILE (box->priv->tile));
}
Example #18
0
void
mex_content_box_set_important (MexContentBox *box,
                               gboolean       important)
{
  mex_tile_set_important (MEX_TILE (box->priv->tile), important);
}
Example #19
0
static void
mex_content_box_set_property (GObject      *object,
                              guint         property_id,
                              const GValue *value,
                              GParamSpec   *pspec)
{
  MexContentBox *self = MEX_CONTENT_BOX (object);
  MexContentBoxPrivate *priv = self->priv;

  switch (property_id)
    {
    case PROP_MEDIA_URL:
      g_free (priv->media_url);
      priv->media_url = g_value_dup_string (value);
      break;

    case PROP_LOGO_URL:
      /* FIXME: We want the logo URL to be file:// to share the same
       * underlying texture. This should be handled by a generic "download
       * queue + texture cache" thingy that caches the same URL to a local
       * file and hands over a ClutterTexure (or a MagicTexture) with the
       * same underlying Cogl texture */
    {
      MxTextureCache *cache;
      ClutterActor *logo, *logo_frame;
      GFile *file;
      gchar *path;
      gint bw, bh;
      gfloat ratio;

      g_free (priv->logo_url);
      priv->logo_url = g_value_dup_string (value);

      if (priv->logo_url == NULL)
        break;

      file = g_file_new_for_uri (priv->logo_url);
      path = g_file_get_path (file);
      g_object_unref (file);
      if (G_UNLIKELY (path == NULL))
        {
          g_warning ("The logo URL provided is not local, refusing to load it");
          break;
        }

      cache = mx_texture_cache_get_default ();
      logo = mx_texture_cache_get_actor (cache, path);
      if (G_UNLIKELY (logo == NULL))
        {
          g_warning ("Could not retrieve texture for %s", path);
          break;
        }

      logo_frame = mex_aspect_frame_new ();
      /* FIXME, had to set the size (for now?) provides some GObject properties
       * to tune that? expose it in the CSS */
      clutter_actor_set_size (logo_frame, 60, 40);
      clutter_texture_get_base_size (CLUTTER_TEXTURE (logo), &bw, &bh);
      ratio = bh / 40.;
      mex_aspect_frame_set_ratio (MEX_ASPECT_FRAME (logo_frame), ratio);
      clutter_container_add_actor (CLUTTER_CONTAINER (logo_frame), logo);

      mex_tile_set_primary_icon (MEX_TILE (priv->tile), logo_frame);
    }
    break;

    case PROP_THUMB_WIDTH:
      priv->thumb_width = g_value_get_int (value);
      g_object_set (G_OBJECT (priv->tile),
                    "thumb-width",
                    priv->thumb_width,
                    NULL);
      break;

    case PROP_THUMB_HEIGHT:
      priv->thumb_height = g_value_get_int (value);
      g_object_set (G_OBJECT (priv->tile),
                    "thumb-height",
                    priv->thumb_height,
                    NULL);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}
Example #20
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
add_pictures (ClutterActor *box)
{
  GList *files = get_pictures ();

  while (files)
    {
      gint w, h, i;
      ClutterActor *drawer, *drawer2, *tile, *texture, *menu, *description;

      gchar *file = files->data;

      /* Create texture */
      texture = clutter_texture_new_from_file (file, NULL);
      clutter_texture_get_base_size (CLUTTER_TEXTURE (texture), &w, &h);
      clutter_actor_set_size (texture, 300, 300.0/w * h);

      /* Create menu */
      menu = mx_box_layout_new ();
      mx_box_layout_set_orientation (MX_BOX_LAYOUT (menu),
                                     MX_ORIENTATION_VERTICAL);
      for (i = 0; i < 4; i++)
        {
          ClutterActor *button, *layout, *icon, *label;

          button = mx_button_new ();

          layout = mx_box_layout_new ();
          icon = mx_icon_new ();
          label = mx_label_new ();

          mx_box_layout_set_spacing (MX_BOX_LAYOUT (layout), 8);

          mx_icon_set_icon_size (MX_ICON (icon), 16);
          clutter_actor_set_size (icon, 16, 16);

          clutter_container_add (CLUTTER_CONTAINER (layout),
                                 icon, label, NULL);
          mx_bin_set_child (MX_BIN (button), layout);
          mx_bin_set_alignment (MX_BIN (button),
                                MX_ALIGN_START,
                                MX_ALIGN_MIDDLE);

          clutter_container_add_actor (CLUTTER_CONTAINER (menu), button);
          mx_box_layout_child_set_x_fill (MX_BOX_LAYOUT (menu), button, TRUE);

          switch (i)
            {
            case 0:
              mx_icon_set_icon_name (MX_ICON (icon), "dialog-information");
              mx_label_set_text (MX_LABEL (label), "This");
              break;

            case 1:
              mx_icon_set_icon_name (MX_ICON (icon), "dialog-question");
              mx_label_set_text (MX_LABEL (label), "is");
              break;

            case 2:
              mx_icon_set_icon_name (MX_ICON (icon), "dialog-warning");
              mx_label_set_text (MX_LABEL (label), "a");
              break;

            case 3:
              mx_icon_set_icon_name (MX_ICON (icon), "dialog-error");
              mx_label_set_text (MX_LABEL (label), "menu");
              break;
            }
        }

      /* Create description */
      description = mx_label_new_with_text ("Here you could put a very "
                                            "long description of whatever "
                                            "is above it. Or you could put "
                                            "another focusable widget here "
                                            "and it'd be navigable, like "
                                            "the menu on the right. Whoo!");
      clutter_text_set_line_wrap ((ClutterText *)mx_label_get_clutter_text (
                                    MX_LABEL (description)), TRUE);

      drawer = mex_expander_box_new ();
      mex_expander_box_set_important_on_focus (MEX_EXPANDER_BOX (drawer), TRUE);
      drawer2 = mex_expander_box_new ();
      mex_expander_box_set_grow_direction (MEX_EXPANDER_BOX (drawer2),
                                          MEX_EXPANDER_BOX_RIGHT);
      mex_expander_box_set_important (MEX_EXPANDER_BOX (drawer2), TRUE);

      tile = mex_tile_new_with_label (file);
      mex_tile_set_important (MEX_TILE (tile), TRUE);
      mx_bin_set_child (MX_BIN (tile), texture);

      clutter_container_add (CLUTTER_CONTAINER (drawer2), tile, menu, NULL);
      clutter_container_add (CLUTTER_CONTAINER (drawer),
                             drawer2, description, NULL);

      g_signal_connect (drawer, "notify::open",
                        G_CALLBACK (sync_drawer2_cb), drawer2);

      clutter_container_add_actor (CLUTTER_CONTAINER (box), drawer);

      clutter_actor_set_reactive (texture, TRUE);
      g_signal_connect (texture, "enter-event",
                        G_CALLBACK (texture_enter_cb), drawer);
      g_signal_connect (texture, "leave-event",
                        G_CALLBACK (texture_leave_cb), drawer);
      g_signal_connect (texture, "button-press-event",
                        G_CALLBACK (texture_clicked_cb), drawer);

      g_free (file);
      files = g_list_delete_link (files, files);
    }
}
Example #22
0
static gboolean
_create_settings_dialog (MexInfoBar *self)
{
  MexInfoBarPrivate *priv = self->priv;

  ClutterActor *dialog, *network_graphic;
  ClutterActor *network_tile, *dialog_layout, *dialog_label;
  ClutterActor *network_button;

  MxAction *close_dialog, *network_settings;

  dialog = mx_dialog_new ();
  mx_stylable_set_style_class (MX_STYLABLE (dialog), "MexInfoBarDialog");

  dialog_label = mx_label_new_with_text (_("Settings"));
  mx_stylable_set_style_class (MX_STYLABLE (dialog_label), "DialogHeader");

  /* Create actions for settings dialog */
  network_settings =
    _action_new_from_desktop_file ("mex-networks.desktop");

  close_dialog = mx_action_new_full ("close", _("Close"),
                                     G_CALLBACK (_close_dialog_cb), self);

  dialog_layout = mx_table_new ();
  mx_table_set_column_spacing (MX_TABLE (dialog_layout), 10);
  mx_table_set_row_spacing (MX_TABLE (dialog_layout), 30);

  mx_table_insert_actor (MX_TABLE (dialog_layout),
                         CLUTTER_ACTOR (dialog_label), 0, 0);

  if (network_settings)
    {
      gchar *tmp;
      network_graphic = mx_image_new ();
      mx_stylable_set_style_class (MX_STYLABLE (network_graphic),
                                   "NetworkGraphic");

      tmp = g_build_filename (mex_get_data_dir (), "style",
                              "graphic-network.png", NULL);
      mx_image_set_from_file (MX_IMAGE (network_graphic), tmp, NULL);
      g_free (tmp);

      network_tile = mex_tile_new ();
      mex_tile_set_label (MEX_TILE (network_tile), _("Network"));
      mex_tile_set_important (MEX_TILE (network_tile), TRUE);

      network_button = mx_button_new ();

      mx_button_set_action (MX_BUTTON (network_button), network_settings);

      mx_bin_set_child (MX_BIN (network_tile), network_button);
      mx_bin_set_child (MX_BIN (network_button), network_graphic);

      mx_table_insert_actor (MX_TABLE (dialog_layout),
                             CLUTTER_ACTOR (network_tile), 1, 1);
    }

  if (!network_settings)
    {
      ClutterActor *no_settings;
      no_settings = mx_label_new_with_text (_("No settings helpers installed"));

      clutter_actor_destroy (priv->settings_button);

      mx_table_insert_actor (MX_TABLE (dialog_layout),
                             CLUTTER_ACTOR (no_settings), 1, 0);
    }


  mx_bin_set_child (MX_BIN (dialog), dialog_layout);
  mx_dialog_add_action (MX_DIALOG (dialog), close_dialog);

  priv->settings_dialog = g_object_ref (dialog);

  return TRUE;
}
Example #23
0
static void
mex_column_notify_focused_cb (MxFocusManager *manager,
                              GParamSpec     *pspec,
                              MexColumn      *self)
{
  GList *c;
  guint offset, increment;
  ClutterActor *focused, *focused_cell;
  gboolean cell_has_focus, has_focus, open, set_tile_important;

  MexColumnPrivate *priv = self->priv;

  focused = (ClutterActor *)mx_focus_manager_get_focused (manager);

  /* Check if we have focus, and what child is focused */
  focused_cell = NULL;
  set_tile_important = FALSE;
  cell_has_focus = has_focus = FALSE;

  if (focused)
    {
      gboolean contains_column = FALSE;
      ClutterActor *parent = clutter_actor_get_parent (focused);
      while (parent)
        {
          if (parent == (ClutterActor *)self)
            {
              has_focus = TRUE;

              if (!priv->has_focus)
                {
                  set_tile_important = TRUE;
                  priv->has_focus = TRUE;
                }

              if (focused != priv->header)
                {
                  cell_has_focus = TRUE;
                  focused_cell = focused;
                }

              break;
            }
          else if (MEX_IS_COLUMN (parent))
            {
              contains_column = TRUE;
            }

          focused = parent;
          parent = clutter_actor_get_parent (focused);
        }

      if (!contains_column)
        has_focus = TRUE;
    }

  if (!has_focus && priv->has_focus)
    {
      priv->has_focus = FALSE;
      set_tile_important = TRUE;
    }

  /* Scroll the adjustment to the top */
  if (!cell_has_focus && priv->adjustment)
    mx_adjustment_interpolate (priv->adjustment, 0, 250,
                               CLUTTER_EASE_OUT_CUBIC);

  /* Open/close boxes as appropriate */
  offset = 0;
  increment = 150;

  /* If we're changing the tile importance, initialise the state manager */
  if (set_tile_important && priv->n_items > 0)
    {
      if (priv->expand_timeline)
        g_object_unref (priv->expand_timeline);
      priv->expand_timeline =
        clutter_timeline_new (priv->n_items * increment);
      clutter_timeline_set_delay (priv->expand_timeline, 350);
    }

  /* Loop through children and set the expander box important/unimportant
   * as necessary, and if necessary, do the same for the tile inside the
   * expander-box.
   */
  open = has_focus && !cell_has_focus;
  for (c = priv->children; c; c = c->next)
    {
      gchar signal_name[32+16];
      ClutterActor *child = c->data;

      if ((!priv->collapse && priv->has_focus) || (child == focused_cell))
        open = TRUE;

      if (!MEX_IS_EXPANDER_BOX (child))
        continue;

      /* Note, 'marker-reached::' is 16 characters long */
      g_snprintf (signal_name, G_N_ELEMENTS (signal_name),
                  "marker-reached::%p", child);

      if (MEX_IS_CONTENT_BOX (child))
        {
          ClutterActor *tile =
            mex_content_box_get_tile (MEX_CONTENT_BOX (child));
          mex_tile_set_important (MEX_TILE (tile), priv->has_focus);
        }

      if (!open)
        {
          if (priv->expand_timeline)
            {
              if (clutter_timeline_has_marker (priv->expand_timeline,
                                               signal_name + 16))
                clutter_timeline_remove_marker (priv->expand_timeline,
                                                signal_name + 16);
              g_signal_handlers_disconnect_by_func (priv->expand_timeline,
                                                    mex_column_expand_drawer_cb,
                                                    child);
            }
          mex_expander_box_set_important (MEX_EXPANDER_BOX (child), FALSE);
        }
      else if (set_tile_important)
        {

          mex_expander_box_set_important (MEX_EXPANDER_BOX (child), FALSE);
          clutter_timeline_add_marker_at_time (priv->expand_timeline,
                                               signal_name + 16, offset);
          g_signal_connect_swapped (priv->expand_timeline, signal_name,
                                    G_CALLBACK (mex_column_expand_drawer_cb),
                                    child);

          offset += increment;
        }
      else
        mex_expander_box_set_important (MEX_EXPANDER_BOX (child), TRUE);
    }

  if (priv->expand_timeline && set_tile_important && (offset >= increment))
    clutter_timeline_start (priv->expand_timeline);
}