/*
* Copyright 2013 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Authors:
* Lars Uebernickel
*/
#include "idoapplicationmenuitem.h"
#include "idoactionhelper.h"
typedef GtkMenuItemClass IdoApplicationMenuItemClass;
struct _IdoApplicationMenuItem
{
GtkMenuItem parent;
gboolean is_running;
GtkWidget *icon;
GtkWidget *label;
};
G_DEFINE_TYPE (IdoApplicationMenuItem, ido_application_menu_item, GTK_TYPE_MENU_ITEM);
static void
ido_application_menu_item_constructed (GObject *object)
{
IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (object);
GtkWidget *grid;
gint icon_height;
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_height);
item->icon = g_object_ref (gtk_image_new ());
gtk_image_set_pixel_size (GTK_IMAGE (item->icon), icon_height);
gtk_widget_set_margin_end(item->icon, 6);
item->label = g_object_ref (gtk_label_new (""));
grid = gtk_grid_new ();
gtk_grid_attach (GTK_GRID (grid), item->icon, 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), item->label, 1, 0, 1, 1);
gtk_container_add (GTK_CONTAINER (object), grid);
gtk_widget_show_all (grid);
G_OBJECT_CLASS (ido_application_menu_item_parent_class)->constructed (object);
}
static void
ido_application_menu_item_dispose (GObject *object)
{
IdoApplicationMenuItem *self = IDO_APPLICATION_MENU_ITEM (object);
g_clear_object (&self->icon);
g_clear_object (&self->label);
G_OBJECT_CLASS (ido_application_menu_item_parent_class)->dispose (object);
}
static gboolean
ido_application_menu_item_draw (GtkWidget *widget,
cairo_t *cr)
{
IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (widget);
GTK_WIDGET_CLASS (ido_application_menu_item_parent_class)->draw (widget, cr);
if (item->is_running)
{
const int arrow_width = 5;
const double half_arrow_height = 4.5;
GtkAllocation alloc;
GdkRGBA color;
double center;
gtk_widget_get_allocation (widget, &alloc);
gtk_style_context_get_color (gtk_widget_get_style_context (widget),
gtk_widget_get_state_flags (widget),
&color);
gdk_cairo_set_source_rgba (cr, &color);
center = alloc.height / 2 + 0.5;
cairo_move_to (cr, 0, center - half_arrow_height);
cairo_line_to (cr, 0, center + half_arrow_height);
cairo_line_to (cr, arrow_width, center);
cairo_close_path (cr);
cairo_fill (cr);
}
return FALSE;
}
void
ido_application_menu_item_class_init (IdoApplicationMenuItemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->constructed = ido_application_menu_item_constructed;
object_class->dispose = ido_application_menu_item_dispose;
widget_class->draw = ido_application_menu_item_draw;
}
static void
ido_application_menu_item_init (IdoApplicationMenuItem *self)
{
}
static void
ido_application_menu_item_set_label (IdoApplicationMenuItem *item,
const gchar *label)
{
gtk_label_set_label (GTK_LABEL (item->label), label);
}
static void
ido_application_menu_item_set_icon (IdoApplicationMenuItem *item,
GIcon *icon)
{
gtk_image_set_from_gicon (GTK_IMAGE (item->icon), icon, GTK_ICON_SIZE_MENU);
}
static void
ido_application_menu_item_state_changed (IdoActionHelper *helper,
GVariant *state,
gpointer user_data)
{
IdoApplicationMenuItem *item = user_data;
item->is_running = g_variant_get_boolean (state);
gtk_widget_queue_draw (GTK_WIDGET (item));
}
GtkMenuItem *
ido_application_menu_item_new_from_model (GMenuItem *menuitem,
GActionGroup *actions)
{
GtkMenuItem *item;
gchar *label;
GVariant *serialized_icon;
gchar *action;
item = g_object_new (IDO_TYPE_APPLICATION_MENU_ITEM, NULL);
gtk_widget_set_margin_end(IDO_APPLICATION_MENU_ITEM(item)->label, 16);
if (g_menu_item_get_attribute (menuitem, "label", "s", &label))
{
ido_application_menu_item_set_label (IDO_APPLICATION_MENU_ITEM (item), label);
g_free (label);
}
serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL);
if (serialized_icon)
{
GIcon *icon;
icon = g_icon_deserialize (serialized_icon);
if (icon)
{
ido_application_menu_item_set_icon (IDO_APPLICATION_MENU_ITEM (item), icon);
g_object_unref (icon);
}
g_variant_unref (serialized_icon);
}
if (g_menu_item_get_attribute (menuitem, "action", "s", &action))
{
IdoActionHelper *helper;
helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL);
g_signal_connect (helper, "action-state-changed",
G_CALLBACK (ido_application_menu_item_state_changed), item);
g_signal_connect_object (item, "activate",
G_CALLBACK (ido_action_helper_activate), helper,
G_CONNECT_SWAPPED);
g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper);
g_free (action);
}
return item;
}