コード例 #1
0
ファイル: mx-combo-box.c プロジェクト: ebassi/mx
static void
mx_combo_box_init (MxComboBox *self)
{
  MxComboBoxPrivate *priv;
  ClutterActor *menu;

  priv = self->priv = COMBO_BOX_PRIVATE (self);

  priv->spacing = 8;

  priv->label = clutter_text_new ();
  clutter_actor_add_child (CLUTTER_ACTOR (self), priv->label);

  menu = mx_menu_new ();
  mx_widget_set_menu (MX_WIDGET (self), MX_MENU (menu));

  g_signal_connect (menu, "action-activated",
                    G_CALLBACK (mx_combo_box_action_activated_cb),
                    self);

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

  clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
}
コード例 #2
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static gboolean
mx_menu_captured_event_handler (ClutterActor *actor,
                                ClutterEvent *event,
                                ClutterActor *menu)
{
    int i;
    ClutterActor *source;
    MxMenuPrivate *priv = MX_MENU (menu)->priv;

    /* allow the event to continue if it is applied to the menu or any of its
     * children
     */
    source = clutter_event_get_source (event);
    if (source == menu)
        return FALSE;
    for (i = 0; i < priv->children->len; i++)
    {
        MxMenuChild *child;

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

        if (source == (ClutterActor*) child->box)
            return FALSE;
    }
    if (source == priv->up_button || source == priv->down_button)
        return FALSE;

    /* hide the menu if the user clicks outside the menu */
    if (event->type == CLUTTER_BUTTON_PRESS)
        mx_menu_close (menu);

    return TRUE;
}
コード例 #3
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_map (ClutterActor *actor)
{
    gint i;
    MxMenuPrivate *priv = MX_MENU (actor)->priv;

    CLUTTER_ACTOR_CLASS (mx_menu_parent_class)->map (actor);

    clutter_actor_map (priv->up_button);
    clutter_actor_map (priv->down_button);
    for (i = 0; i < priv->children->len; i++)
    {
        MxMenuChild *child = &g_array_index (priv->children, MxMenuChild,
                                             i);
        clutter_actor_map (CLUTTER_ACTOR (child->box));
    }

    /* set up a capture so we can close the menu if the user clicks outside it */
    priv->stage = clutter_actor_get_stage (actor);
    g_object_weak_ref (G_OBJECT (priv->stage), (GWeakNotify) stage_weak_notify,
                       actor);

    priv->captured_event_handler =
        g_signal_connect (priv->stage,
                          "captured-event",
                          G_CALLBACK (mx_menu_captured_event_handler),
                          actor);
}
コード例 #4
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_unmap (ClutterActor *actor)
{
    gint i;
    MxMenuPrivate *priv = MX_MENU (actor)->priv;

    CLUTTER_ACTOR_CLASS (mx_menu_parent_class)->unmap (actor);

    clutter_actor_unmap (priv->up_button);
    clutter_actor_unmap (priv->down_button);
    for (i = 0; i < priv->children->len; i++)
    {
        MxMenuChild *child = &g_array_index (priv->children, MxMenuChild,
                                             i);
        clutter_actor_unmap (CLUTTER_ACTOR (child->box));
    }

    if (priv->stage)
    {
        g_signal_handler_disconnect (priv->stage, priv->captured_event_handler);
        priv->captured_event_handler = 0;

        g_object_weak_unref (G_OBJECT (priv->stage),
                             (GWeakNotify) stage_weak_notify,
                             actor);
        priv->stage = NULL;
    }
}
コード例 #5
0
ファイル: mx-menu.c プロジェクト: jku/mx
static void
mx_menu_button_clicked_cb (ClutterActor *box,
                           MxAction     *action)
{
  MxMenu *menu;

  menu = MX_MENU (clutter_actor_get_parent (box));

  /* set the menu unreactive to prevent other items being hilighted */
  clutter_actor_set_reactive ((ClutterActor*) menu, FALSE);


  g_object_ref (menu);
  g_object_ref (action);

  g_signal_emit (menu, signals[ACTION_ACTIVATED], 0, action);
  g_signal_emit_by_name (action, "activated");

  clutter_actor_animate (CLUTTER_ACTOR (menu), CLUTTER_LINEAR, 250,
                         "opacity", (guchar) 0,
                         "signal-swapped::completed", clutter_actor_hide, menu,
                         NULL);

  g_object_unref (action);
  g_object_unref (menu);
}
コード例 #6
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_floating_pick (ClutterActor       *menu,
                       const ClutterColor *color)
{
    gint i;
    MxMenuPrivate *priv = MX_MENU (menu)->priv;

    /* chain up to get bounding rectangle */

    MX_FLOATING_WIDGET_CLASS (mx_menu_parent_class)->floating_pick (menu, color);

    /* pick children */
    for (i = priv->id_offset; i <= priv->last_shown_id; i++)
    {
        MxMenuChild *child = &g_array_index (priv->children, MxMenuChild, i);

        if (clutter_actor_should_pick_paint (CLUTTER_ACTOR (child->box)))
        {
            clutter_actor_paint (CLUTTER_ACTOR (child->box));
        }
    }
    if(priv->scrolling_mode)
    {
        clutter_actor_paint(priv->up_button);
        clutter_actor_paint(priv->down_button);
    }
}
コード例 #7
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static MxFocusable*
mx_menu_accept_focus (MxFocusable *focusable,
                      MxFocusHint  hint)
{
    MxMenuPrivate *priv = MX_MENU (focusable)->priv;
    MxMenuChild *child;

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

    return mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);
}
コード例 #8
0
ファイル: mx-menu.c プロジェクト: jku/mx
static gboolean
mx_menu_captured_event_handler (ClutterActor *actor,
                                ClutterEvent *event,
                                ClutterActor *menu)
{
  int i;
  ClutterActor *source;
  MxMenuPrivate *priv = MX_MENU (menu)->priv;

  /* allow the event to continue if it is applied to the menu or any of its
   * children
   */
  source = clutter_event_get_source (event);
  if (source == menu)
    return FALSE;
  for (i = 0; i < priv->children->len; i++)
    {
      MxMenuChild *child;

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

      if (source == (ClutterActor*) child->box)
        return FALSE;
    }
  if (source == priv->up_button || source == priv->down_button)
    return FALSE;

  /* hide the menu if the user clicks outside the menu */
  if (event->type == CLUTTER_BUTTON_PRESS)
    {
      if (clutter_actor_get_animation (menu))
        {
          clutter_animation_completed (clutter_actor_get_animation (menu));

          return FALSE;
        }


      clutter_actor_set_reactive (menu, FALSE);
      clutter_actor_animate (menu, CLUTTER_LINEAR, 250,
                             "opacity", (guchar) 0,
                             "signal-swapped::completed", clutter_actor_hide,
                             menu,
                             NULL);
    }


  return TRUE;
}
コード例 #9
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_dispose (GObject *object)
{
    MxMenu *menu = MX_MENU (object);
    MxMenuPrivate *priv = menu->priv;

    if (priv->children)
    {
        gint i;
        for (i = 0; i < priv->children->len; i++)
            mx_menu_free_action_at (menu, i, FALSE);
        g_array_free (priv->children, TRUE);
        priv->children = NULL;
    }


    G_OBJECT_CLASS (mx_menu_parent_class)->dispose (object);
}
コード例 #10
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_button_clicked_cb (ClutterActor *box,
                           MxAction     *action)
{
    MxMenu *menu;

    menu = MX_MENU (clutter_actor_get_parent (box));

    g_object_ref (menu);
    g_object_ref (action);

    g_signal_emit (menu, signals[ACTION_ACTIVATED], 0, action);
    g_signal_emit_by_name (action, "activated");

    mx_menu_close (CLUTTER_ACTOR (menu));

    g_object_unref (action);
    g_object_unref (menu);
}
コード例 #11
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static gboolean
mx_menu_button_enter_event_cb (ClutterActor *box,
                               ClutterEvent *event,
                               gpointer      user_data)
{
    MxMenuPrivate *priv = MX_MENU (user_data)->priv;
    ClutterStage *stage;

    /* each menu item grabs focus when hovered */

    stage = (ClutterStage *) clutter_actor_get_stage (box);

    /* ensure the menu is not closed when focus is pushed to another actor */
    priv->internal_focus_push = TRUE;

    mx_focus_manager_push_focus (mx_focus_manager_get_for_stage (stage),
                                 MX_FOCUSABLE (box));

    /* prevent the hover pseudo-class from being applied */
    return TRUE;
}
コード例 #12
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_get_preferred_width (ClutterActor *actor,
                             gfloat        for_height,
                             gfloat       *min_width_p,
                             gfloat       *natural_width_p)
{
    gint i;
    MxPadding padding;
    gfloat min_width, nat_width;

    MxMenuPrivate *priv = MX_MENU (actor)->priv;

    /* Add padding and the size of the widest child */
    mx_widget_get_padding (MX_WIDGET (actor), &padding);
    min_width = nat_width = 0;
    for (i = 0; i < priv->children->len; i++)
    {
        gfloat child_min_width, child_nat_width;
        MxMenuChild *child;

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

        clutter_actor_get_preferred_width (CLUTTER_ACTOR (child->box),
                                           for_height,
                                           &child_min_width,
                                           &child_nat_width);

        if (child_min_width > min_width)
            min_width = child_min_width;
        if (child_nat_width > nat_width)
            nat_width = child_nat_width;
    }

    if (min_width_p)
        *min_width_p = min_width + padding.left + padding.right;
    if (natural_width_p)
        *natural_width_p = nat_width + padding.left + padding.right;
}
コード例 #13
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_floating_paint (ClutterActor *menu)
{
    gint i;
    MxMenuPrivate *priv = MX_MENU (menu)->priv;

    /* Chain up to get background */
    MX_FLOATING_WIDGET_CLASS (mx_menu_parent_class)->floating_paint (menu);

    /* Paint children */
    for (i = priv->id_offset; i <= priv->last_shown_id; i++)
    {
        MxMenuChild *child = &g_array_index (priv->children, MxMenuChild,
                                             i);
        clutter_actor_paint (CLUTTER_ACTOR (child->box));
    }

    if(priv->scrolling_mode)
    {
        clutter_actor_paint (priv->up_button);
        clutter_actor_paint (priv->down_button);
    }
}
コード例 #14
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static void
mx_menu_get_preferred_height (ClutterActor *actor,
                              gfloat        for_width,
                              gfloat       *min_height_p,
                              gfloat       *natural_height_p)
{
    gint i;
    MxPadding padding;
    gfloat min_height, nat_height;

    MxMenuPrivate *priv = MX_MENU (actor)->priv;

    /* Add padding and the cumulative height of the children */
    mx_widget_get_padding (MX_WIDGET (actor), &padding);
    min_height = nat_height = padding.top + padding.bottom;
    for (i = 0; i < priv->children->len; i++)
    {
        gfloat child_min_height, child_nat_height;

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

        clutter_actor_get_preferred_height (CLUTTER_ACTOR (child->box),
                                            for_width,
                                            &child_min_height,
                                            &child_nat_height);

        min_height += child_min_height + 1;
        nat_height += child_nat_height + 1;
    }

    if (min_height_p)
        *min_height_p = min_height;
    if (natural_height_p)
        *natural_height_p = nat_height;
}
コード例 #15
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
static MxFocusable*
mx_menu_move_focus (MxFocusable      *focusable,
                    MxFocusDirection  direction,
                    MxFocusable      *from)
{
    MxMenuPrivate *priv = MX_MENU (focusable)->priv;
    MxFocusable *result;
    MxMenuChild *child;
    gint i, start;

    /* find the current focused child */
    for (i = 0; i < priv->children->len; i++)
    {
        child = &g_array_index (priv->children, MxMenuChild, i);
        if ((MxFocusable*) child->box == from)
            break;
        else
            child = NULL;
    }

    if (!child)
        return NULL;

    start = i;

    switch (direction)
    {
    case MX_FOCUS_DIRECTION_UP:
        if (i == 0)
        {
            i = priv->children->len - 1;
            gint nb_elts = priv->last_shown_id - priv->id_offset;
            priv->id_offset = i - nb_elts;
            clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
        }
        else
        {
            i--;
            if (i < priv->id_offset)
            {
                priv->id_offset--;
                clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
            }
        }

        while (i >= 0)
        {
            if (i == start)
                break;

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

            result = mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);

            if (result)
                return result;

            /* loop */
            if (i == 0)
                i = priv->children->len;

            i--;
        }


    case MX_FOCUS_DIRECTION_DOWN:
        if (i == priv->children->len - 1)
        {
            priv->id_offset = 0;
            i = 0;
            clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
        }
        else
        {
            i++;
            if (i > priv->last_shown_id)
            {
                priv->id_offset++;
                clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
            }
        }

        while (i < priv->children->len)
        {
            if (i == start)
                break;

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

            result = mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);

            if (result)
                return result;

            /* loop */
            if (i == priv->children->len - 1)
                i = -1;

            i++;
        }

    case MX_FOCUS_DIRECTION_OUT:
        if (priv->internal_focus_push)
        {
            /* do nothing if this notification was caused internally */
            priv->internal_focus_push = FALSE;
            return NULL;
        }

    default:
        break;
    }

    clutter_actor_hide (CLUTTER_ACTOR (focusable));
    return NULL;
}
コード例 #16
0
ファイル: mx-menu.c プロジェクト: jonnylamb/mx
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);
}