예제 #1
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_get_property (GObject    *object,
                           guint       property_id,
                           GValue     *value,
                           GParamSpec *pspec)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (object)->priv;

  switch (property_id)
    {
    case PROP_ACTIVE_TEXT:
      g_value_set_string (value,
                          clutter_text_get_text ((ClutterText*) priv->label));
      break;

    case PROP_ACTIVE_ICON_NAME:
      g_value_set_string (value,
                          mx_combo_box_get_active_icon_name (
                                                        MX_COMBO_BOX (object)));
      break;

    case PROP_INDEX:
      g_value_set_int (value, priv->index);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}
예제 #2
0
파일: main.cpp 프로젝트: aalex/proto-mx
int main(int argc, char *argv[])
{
    clutter_init(&argc, &argv);

    ClutterActor *stage = NULL;
    ClutterColor black = { 0x00, 0x00, 0x00, 0xff };
    stage = clutter_stage_get_default();
    clutter_stage_set_title(CLUTTER_STAGE(stage), "Mx test");
    clutter_stage_set_color(CLUTTER_STAGE(stage), &black);
    clutter_actor_set_size(stage, WIN_W, WIN_H);

    Assistant *assistant = g_new0(Assistant, 1);
    assistant->script = require_script(GUI_SCRIPT);
    assistant->stage = stage;
    ClutterActor *root = CLUTTER_ACTOR(require_object_from_script(assistant->script, "root"));
    assistant->slider = CLUTTER_ACTOR(require_object_from_script(assistant->script, "slider"));
    assistant->combo_box = CLUTTER_ACTOR(require_object_from_script(assistant->script, "combo_box"));
    clutter_container_add_actor(CLUTTER_CONTAINER(stage), root);

    // Combo box contents:
    MxComboBox *combo_box = MX_COMBO_BOX(assistant->combo_box);
    mx_combo_box_append_text(combo_box, "Foo");
    mx_combo_box_append_text(combo_box, "Spam");
    mx_combo_box_append_text(combo_box, "Lorem ipsum");
    mx_combo_box_set_index(combo_box, 0);

    // DONE
    g_signal_connect(stage, "key-press-event", G_CALLBACK(key_event_cb), assistant);
    clutter_script_connect_signals(assistant->script, assistant);
    assistant->ready_ = TRUE;
    clutter_actor_show(stage);
    clutter_main();
    return 0;
}
static void
anerley_presence_chooser_init (AnerleyPresenceChooser *self)
{
    MxComboBox *combo = MX_COMBO_BOX (self);
    AnerleyPresenceChooserPrivate *priv = GET_PRIVATE (self);

    priv->am = tp_account_manager_dup ();

    g_signal_connect (priv->am,
                      "most-available-presence-changed",
                      G_CALLBACK (_account_manager_presence_changed),
                      self);

    priv->combo_entries = g_array_sized_new (FALSE, TRUE, sizeof (ComboEntry), 7);

    /* add some entries */
    _append_presence (combo, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
    _append_presence (combo, TP_CONNECTION_PRESENCE_TYPE_BUSY);
    _append_presence (combo, TP_CONNECTION_PRESENCE_TYPE_AWAY);
    _append_presence (combo, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
    /* FIXME: Hidden ? */

    g_signal_connect (self,
                      "notify::index",
                      G_CALLBACK (_combo_index_changed),
                      NULL);

    tp_proxy_prepare_async (TP_PROXY (priv->am),
                            NULL,
                            (GAsyncReadyCallback)_account_manager_ready,
                            self);
}
예제 #4
0
static void
create_new_chooser (MnbPeoplePanel *self)
{
  MnbPeoplePanelPrivate *priv = GET_PRIVATE (self);

  priv->new_chooser = mx_combo_box_new ();
  mx_combo_box_append_text (MX_COMBO_BOX (priv->new_chooser), _("New contact"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->new_chooser), _("New group chat"));

  mx_combo_box_set_active_text (MX_COMBO_BOX (priv->new_chooser), _("New"));

  g_signal_connect (priv->new_chooser,
                    "notify::index",
                    G_CALLBACK (new_index_changed_cb),
                    self);
}
static void
_combo_index_changed (AnerleyPresenceChooser *self,
                      GParamSpec             *pspec,
                      gpointer                user_data)
{
    AnerleyPresenceChooserPrivate *priv = GET_PRIVATE (self);
    MxComboBox *combo = MX_COMBO_BOX (self);
    gint index = mx_combo_box_get_index (combo);
    ComboEntry *entry;
    gchar *message;

    if (index >= 0)
        entry = &g_array_index (priv->combo_entries, ComboEntry, index);
    else
        return;

    priv->presence = entry->presence;

    /* Get current message to not modify it */
    tp_account_manager_get_most_available_presence (priv->am,
            NULL,
            &message);

    tp_account_manager_set_all_requested_presences (priv->am,
            entry->presence,
            presences[entry->presence].status,
            message);

    g_free (message);
}
예제 #6
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_dispose (GObject *object)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (object)->priv;

  if (priv->label)
    {
      clutter_actor_destroy (priv->label);
      priv->label = NULL;
    }

  if (priv->icon)
    {
      clutter_actor_destroy (priv->icon);
      priv->icon = NULL;
    }

  if (priv->marker)
    {
      clutter_actor_destroy (priv->marker);
      priv->marker = NULL;
    }

  G_OBJECT_CLASS (mx_combo_box_parent_class)->dispose (object);
}
static void
update_combox_index (AnerleyPresenceChooser *self)
{
    AnerleyPresenceChooserPrivate *priv = GET_PRIVATE (self);
    MxComboBox *combo = MX_COMBO_BOX (self);

    g_signal_handlers_block_by_func (combo, _combo_index_changed, NULL);
    switch (priv->presence)
    {
    case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
        mx_combo_box_set_index (combo, 0);
        break;
    case TP_CONNECTION_PRESENCE_TYPE_BUSY:
        mx_combo_box_set_index (combo, 1);
        break;
    case TP_CONNECTION_PRESENCE_TYPE_AWAY:
    case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
        mx_combo_box_set_index (combo, 2);
        break;
    default:
        mx_combo_box_set_index (combo, 3);
        break;
    }
    g_signal_handlers_unblock_by_func (combo, _combo_index_changed, NULL);
}
예제 #8
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_apply_style (MxWidget *widget,
                          MxStyle  *style)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (widget)->priv;

  if (priv->icon != NULL)
    mx_stylable_set_style (MX_STYLABLE (priv->icon), style);
}
예제 #9
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_finalize (GObject *object)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (object)->priv;

  if (priv->actions)
    {
      g_slist_foreach (priv->actions, (GFunc) g_object_unref, NULL);
      g_slist_free (priv->actions);
    }

  G_OBJECT_CLASS (mx_combo_box_parent_class)->finalize (object);
}
예제 #10
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static gboolean
mx_combo_box_key_press_event (ClutterActor    *actor,
                              ClutterKeyEvent *event)
{
  switch (event->keyval)
    {
    case CLUTTER_KEY_Return:
      return mx_combo_box_open_menu (MX_COMBO_BOX (actor));

    default:
      return FALSE;
    }
}
예제 #11
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_paint (ClutterActor *actor)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv;

  CLUTTER_ACTOR_CLASS (mx_combo_box_parent_class)->paint (actor);

  clutter_actor_paint (priv->label);

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

  if (priv->marker)
    clutter_actor_paint (priv->marker);
}
예제 #12
0
파일: mx-combo-box.c 프로젝트: ManMower/mx
static gboolean
mx_combo_box_touch_event (ClutterActor      *actor,
                          ClutterTouchEvent *event)
{
  switch (event->type)
    {
    case CLUTTER_TOUCH_BEGIN:
      return mx_combo_box_open_menu (MX_COMBO_BOX (actor));

    default:
      return FALSE;
    }

  return FALSE;
}
예제 #13
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_get_preferred_height (ClutterActor *actor,
                                   gfloat        for_width,
                                   gfloat       *min_height_p,
                                   gfloat       *natural_height_p)
{
  MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv;
  gfloat min_label_h, nat_label_h;
  gfloat min_icon_h = 0, nat_icon_h = 0;
  gfloat min_marker_h = 0, nat_marker_h = 0;
  gfloat min_h, nat_h;
  MxPadding padding;

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  clutter_actor_get_preferred_height (priv->label,
                                      -1,
                                      &min_label_h,
                                      &nat_label_h);

  if (priv->icon)
    {
      clutter_actor_get_preferred_height (priv->icon,
                                          -1,
                                          &min_icon_h,
                                          &nat_icon_h);
    }

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

  min_h = MAX (MAX (min_icon_h, min_label_h), min_marker_h);
  nat_h = MAX (MAX (nat_icon_h, nat_label_h), nat_marker_h);

  if (min_height_p)
    *min_height_p = padding.top + padding.bottom + min_h;

  if (natural_height_p)
    *natural_height_p = padding.top + padding.bottom + nat_h;
}
예제 #14
0
static void
create_sort_by_chooser (MnbPeoplePanel *self)
{
  MnbPeoplePanelPrivate *priv = GET_PRIVATE (self);

  priv->sort_by_chooser = mx_combo_box_new ();
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("Sort by:"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("- Presence"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("- Name"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("Show:"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("- Only online"));
  mx_combo_box_append_text (MX_COMBO_BOX (priv->sort_by_chooser), _("- All contacts"));

  mx_combo_box_set_active_text (MX_COMBO_BOX (priv->sort_by_chooser), _("Sort by"));

  g_signal_connect (priv->sort_by_chooser,
                    "notify::index",
                    G_CALLBACK (sort_by_index_changed_cb),
                    self);
}
예제 #15
0
파일: test-widgets.c 프로젝트: 3v1n0/mx
static ClutterActor *
create_property_editor (GObject    *object,
                        GParamSpec *pspec)
{
  ClutterActor *box, *label, *value;
  gint i;

  /* skip properties that are not writable */
  if (!(pspec->flags & G_PARAM_WRITABLE))
    return NULL;

  /* skip other properties */
  for (i = 0; i < G_N_ELEMENTS (skip_properties); i++)
    {
      if (g_str_equal (pspec->name, skip_properties[i]))
        return NULL;
    }


  box = mx_box_layout_new ();

  label = mx_label_new_with_text (pspec->name);
  clutter_actor_set_width (label, 150);
  clutter_actor_add_child (box, label);

  if (pspec->value_type == G_TYPE_BOOLEAN)
    {
      value = mx_toggle_new ();

      g_object_bind_property (object, pspec->name, value, "active",
                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
    }
  else if (pspec->value_type == G_TYPE_STRING)
    {
      value = mx_entry_new ();

      g_object_bind_property (object, pspec->name, value, "text",
                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
    }
  else if (pspec->value_type == G_TYPE_INT || pspec->value_type == G_TYPE_UINT
           || pspec->value_type == G_TYPE_FLOAT
           || pspec->value_type == G_TYPE_DOUBLE)
    {
      value = mx_entry_new ();

      g_object_bind_property_full (object, pspec->name, value, "text",
                                   G_BINDING_BIDIRECTIONAL
                                   | G_BINDING_SYNC_CREATE,
                                   num_to_string,
                                   string_to_num,
                                   NULL, NULL);
    }
  else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
    {
      GEnumValue *evalue;
      GEnumClass *eclass;
      gint init = 0;

      value = mx_combo_box_new ();
      clutter_actor_set_width (value, 100);

      eclass = g_type_class_ref (pspec->value_type);

      while ((evalue = g_enum_get_value (eclass, init)))
        {
          mx_combo_box_append_text (MX_COMBO_BOX (value), evalue->value_nick);
          init++;
        }

      g_type_class_unref (eclass);

      g_object_bind_property (object, pspec->name, value, "index",
                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

    }
  else
    value = NULL;

  if (value)
    {
      clutter_actor_add_child (box, value);
      return box;
    }
  else
    return NULL;
}
예제 #16
0
파일: mx-combo-box.c 프로젝트: ManMower/mx
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);
}
예제 #17
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static gboolean
mx_combo_box_button_press_event (ClutterActor       *actor,
                                 ClutterButtonEvent *event)
{
  return mx_combo_box_open_menu (MX_COMBO_BOX (actor));
}
예제 #18
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
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);
}
예제 #19
0
파일: mx-combo-box.c 프로젝트: ebassi/mx
static void
mx_combo_box_get_preferred_width (ClutterActor *actor,
                                  gfloat        for_height,
                                  gfloat       *min_width_p,
                                  gfloat       *natural_height_p)
{
  gfloat height;
  gfloat min_w, nat_w;
  gfloat min_label_w, nat_label_w;

  gfloat min_icon_w = 0, nat_icon_w = 0;
  gfloat min_menu_w = 0, nat_menu_w = 0;
  gfloat min_marker_w = 0, nat_marker_w = 0;
  MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv;

  MxPadding padding;
  ClutterActor *menu;

  mx_widget_get_padding (MX_WIDGET (actor), &padding);

  height = for_height - padding.top - padding.bottom;

  menu = (ClutterActor *) mx_widget_get_menu (MX_WIDGET (actor));
  if (menu)
    {
      clutter_actor_get_preferred_width (menu, -1, &min_menu_w, &nat_menu_w);
    }

  clutter_actor_get_preferred_width (priv->label,
                                     height,
                                     &min_label_w,
                                     &nat_label_w);

  min_w = min_label_w;
  nat_w = nat_label_w;

  if (priv->icon)
    {
      clutter_actor_get_preferred_width (priv->icon,
                                         height,
                                         &min_icon_w,
                                         &nat_icon_w);

      min_w += min_icon_w + priv->spacing;
      nat_w += nat_icon_w + priv->spacing;
    }

  if (min_menu_w > min_w)
    min_w = min_menu_w;
  if (nat_menu_w > nat_w)
    nat_w = nat_menu_w;

  if (priv->marker)
    {
      clutter_actor_get_preferred_width (priv->marker,
                                         height,
                                         &min_marker_w,
                                         &nat_marker_w);

      min_w += min_marker_w + priv->spacing;
      nat_w += nat_marker_w + priv->spacing;
    }

  if (min_width_p)
    *min_width_p = padding.left + padding.right + min_w;

  if (natural_height_p)
    *natural_height_p = padding.left + padding.right + nat_w;
}