← Back to team overview

ayatana-commits team mailing list archive

[Branch ~dbusmenu-team/dbusmenu/trunk] Rev 9: Merging in support for image items. Including encoding and decoding the images across DBus.

 

Merge authors:
  Ted Gould (ted)
Related merge proposals:
  https://code.launchpad.net/~ted/dbusmenu/imageitem/+merge/11141
  proposed by: Ted Gould (ted)
  review: Approve - Cody Russell (bratsche)
------------------------------------------------------------
revno: 9 [merge]
committer: Ted Gould <ted@xxxxxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2009-09-03 14:16:01 -0500
message:
  Merging in support for image items.  Including encoding and decoding the images across DBus.
added:
  libdbusmenu-gtk/menuitem.c
  libdbusmenu-gtk/menuitem.h
modified:
  .bzrignore
  libdbusmenu-gtk/Makefile.am
  libdbusmenu-gtk/client.c
  tests/test-gtk-label-server.c
  tests/test-gtk-label.json


--
lp:dbusmenu
https://code.launchpad.net/~dbusmenu-team/dbusmenu/trunk

Your team ayatana-commits is subscribed to branch lp:dbusmenu.
To unsubscribe from this branch go to https://code.launchpad.net/~dbusmenu-team/dbusmenu/trunk/+edit-subscription.
=== modified file '.bzrignore'
--- .bzrignore	2009-07-01 05:34:05 +0000
+++ .bzrignore	2009-09-02 18:29:01 +0000
@@ -41,3 +41,4 @@
 dbusmenu.py
 mago.results
 test-glib-simple-items
+libdbusmenu-gtk/libdbusmenu_gtk_la-menuitem.lo

=== modified file 'libdbusmenu-gtk/Makefile.am'
--- libdbusmenu-gtk/Makefile.am	2009-06-24 04:05:44 +0000
+++ libdbusmenu-gtk/Makefile.am	2009-09-02 18:29:01 +0000
@@ -9,13 +9,16 @@
 
 libdbusmenu_gtkinclude_HEADERS = \
 	client.h \
-	menu.h
+	menu.h \
+	menuitem.h
 
 libdbusmenu_gtk_la_SOURCES = \
 	client.h \
 	client.c \
 	menu.h \
-	menu.c
+	menu.c \
+	menuitem.h \
+	menuitem.c
 
 libdbusmenu_gtk_la_LDFLAGS = \
 	-version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \

=== modified file 'libdbusmenu-gtk/client.c'
--- libdbusmenu-gtk/client.c	2009-09-02 14:48:52 +0000
+++ libdbusmenu-gtk/client.c	2009-09-03 19:16:01 +0000
@@ -33,6 +33,7 @@
 #include <gtk/gtk.h>
 
 #include "client.h"
+#include "menuitem.h"
 
 /* Prototypes */
 static void dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass);
@@ -302,6 +303,8 @@
 	return mi;
 }
 
+/* The base type handler that builds a plain ol'
+   GtkMenuItem to represent, well, the GtkMenuItem */
 static gboolean
 new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
 {
@@ -321,6 +324,8 @@
 	return TRUE;
 }
 
+/* Type handler for the seperators where it builds
+   a GtkSeparator to act as the GtkMenuItem */
 static gboolean
 new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
 {
@@ -340,9 +345,124 @@
 	return TRUE;
 }
 
+/* This handler looks at property changes for items that are
+   image menu items. */
+static void
+image_property_handle (DbusmenuMenuitem * item, const gchar * property, const gchar * value, gpointer userdata)
+{
+	/* We're only looking at these two properties here */
+	g_return_if_fail(!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON) || !g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_DATA));
+
+	if (value == NULL || value[0] == '\0') {
+		/* This means that we're unsetting a value. */
+		/* Try to use the other one */
+		if (g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON)) {
+			property = DBUSMENU_MENUITEM_PROP_ICON_DATA;
+		} else {
+			property = DBUSMENU_MENUITEM_PROP_ICON;
+		}
+	}
+
+	/* Grab the data of the items that we've got, so that
+	   we can know how things need to change. */
+	GtkMenuItem * gimi = dbusmenu_gtkclient_menuitem_get (DBUSMENU_GTKCLIENT(userdata), item);
+	if (gimi == NULL) {
+		g_warning("Oddly we're handling image properties on a menuitem that doesn't have any GTK structures associated with it.");
+		return;
+	}
+	GtkWidget * gtkimage = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(gimi));
+
+	if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_DATA)) {
+		/* If we have an image already built from a name that is
+		   way better than a pixbuf.  Keep it. */
+		if (gtk_image_get_storage_type(GTK_IMAGE(gtkimage)) == GTK_IMAGE_ICON_NAME) {
+			return;
+		}
+	}
+
+	/* Now figure out what to change */
+	if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON)) {
+		const gchar * iconname = dbusmenu_menuitem_property_get(item, property);
+		if (iconname == NULL) {
+			/* If there is no name, by golly we want no
+			   icon either. */
+			gtkimage = NULL;
+		} else {
+			/* If we don't have an image, we need to build
+			   one so that we can set the name.  Otherwise we
+			   can just convert it to this name. */
+			if (gtkimage == NULL) {
+				gtkimage = gtk_image_new_from_icon_name(iconname, GTK_ICON_SIZE_MENU);
+			} else {
+				gtk_image_set_from_icon_name(GTK_IMAGE(gtkimage), iconname, GTK_ICON_SIZE_MENU);
+			}
+		}
+	} else {
+		GdkPixbuf * image = dbusmenu_menuitem_property_get_image(item, property);
+		if (image == NULL) {
+			/* If there is no pixbuf, by golly we want no
+			   icon either. */
+			gtkimage = NULL;
+		} else {
+			/* Resize the pixbuf */
+			gint width, height;
+			gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+			if (gdk_pixbuf_get_width(image) > width ||
+					gdk_pixbuf_get_height(image) > height) {
+				GdkPixbuf * newimage = gdk_pixbuf_scale_simple(image,
+				                                               width,
+				                                               height,
+				                                               GDK_INTERP_BILINEAR);
+				g_object_unref(image);
+				image = newimage;
+			}
+			
+			/* If we don't have an image, we need to build
+			   one so that we can set the pixbuf. */
+			if (gtkimage == NULL) {
+				gtkimage = gtk_image_new_from_pixbuf(image);
+			} else {
+				gtk_image_set_from_pixbuf(GTK_IMAGE(gtkimage), image);
+			}
+		}
+
+	}
+
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gimi), gtkimage);
+
+	return;
+}
+
+/* This is a type call back for the image type where
+   it uses the GtkImageMenuitem to create the menu item. */
 static gboolean
 new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
 {
+	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+	g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+	/* Note: not checking parent, it's reasonable for it to be NULL */
+
+	GtkMenuItem * gmi;
+	gmi = GTK_MENU_ITEM(gtk_image_menu_item_new_with_label(dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_LABEL)));
+
+	if (gmi != NULL) {
+		dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+	} else {
+		return FALSE;
+	}
+
+	image_property_handle(newitem,
+	                      DBUSMENU_MENUITEM_PROP_ICON,
+	                      dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_ICON),
+	                      client);
+	image_property_handle(newitem,
+	                      DBUSMENU_MENUITEM_PROP_ICON_DATA,
+	                      dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_ICON_DATA),
+	                      client);
+	g_signal_connect(G_OBJECT(newitem),
+	                 DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED,
+	                 G_CALLBACK(image_property_handle),
+	                 client);
 
 	return TRUE;
 }

=== added file 'libdbusmenu-gtk/menuitem.c'
--- libdbusmenu-gtk/menuitem.c	1970-01-01 00:00:00 +0000
+++ libdbusmenu-gtk/menuitem.c	2009-09-02 18:50:29 +0000
@@ -0,0 +1,130 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the 
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public 
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public 
+License version 3 and version 2.1 along with this program.  If not, see 
+<http://www.gnu.org/licenses/>
+*/
+
+#include "menuitem.h"
+
+/**
+	dbusmenu_menuitem_property_set_image:
+	@menuitem: The #DbusmenuMenuitem to set the property on.
+	@property: Name of the property to set.
+	@data: The image to place on the property.
+
+	This function takes the pixbuf that is stored in @data and
+	turns it into a base64 encoded PNG so that it can be placed
+	onto a standard #DbusmenuMenuitem property.
+
+	Return value: Whether the function was able to set the property
+		or not.
+*/
+gboolean
+dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data)
+{
+	g_return_val_if_fail(GDK_IS_PIXBUF(data), FALSE);
+	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE);
+	g_return_val_if_fail(property != NULL && property[0] != '\0', FALSE);
+
+	GError * error = NULL;
+	gchar * png_data;
+	gsize png_data_len;
+
+	if (!gdk_pixbuf_save_to_buffer((GdkPixbuf *)data, &png_data, &png_data_len, "png", &error, NULL)) {
+		if (error == NULL) {
+			g_warning("Unable to create pixbuf data stream: %d", png_data_len);
+		} else {
+			g_warning("Unable to create pixbuf data stream: %s", error->message);
+			g_error_free(error);
+			error = NULL;
+		}
+
+		return FALSE;
+	}
+
+	gchar * prop_str = g_base64_encode((guchar *)png_data, png_data_len);
+	gboolean propreturn = FALSE;
+	propreturn = dbusmenu_menuitem_property_set(menuitem, property, prop_str);
+
+	g_free(prop_str);
+	g_free(png_data);
+
+	return propreturn;
+}
+
+/**
+	dbusmenu_menuitem_property_get_image:
+	@menuitem: The #DbusmenuMenuite to look for the property on
+	@property: The name of the property to look for.
+
+	This function looks on the menu item for a property by the
+	name of @property.  If one exists it tries to turn it into
+	a #GdkPixbuf.  It assumes that the property is a base64 encoded
+	PNG file like the one created by #dbusmenu_menuite_property_set_image.
+
+	Return value: A pixbuf or #NULL to signal error.
+*/
+GdkPixbuf *
+dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property)
+{
+	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), NULL);
+	g_return_val_if_fail(property != NULL && property[0] != '\0', NULL);
+
+	const gchar * value = dbusmenu_menuitem_property_get(menuitem, property);
+
+	/* There is no icon */
+	if (value == NULL || value[0] == '\0') {
+		return NULL;
+	}
+
+	gsize length = 0;
+	guchar * icondata = g_base64_decode(value, &length);
+	
+	GInputStream * input = g_memory_input_stream_new_from_data(icondata, length, NULL);
+	if (input == NULL) {
+		g_warning("Cound not create input stream from icon property data");
+		g_free(icondata);
+		return NULL;
+	}
+
+	GError * error = NULL;
+	GdkPixbuf * icon = gdk_pixbuf_new_from_stream(input, NULL, &error);
+
+	if (error != NULL) {
+		g_warning("Unable to build Pixbuf from icon data: %s", error->message);
+		g_error_free(error);
+	}
+
+	error = NULL;
+	g_input_stream_close(input, NULL, &error);
+	if (error != NULL) {
+		g_warning("Unable to close input stream: %s", error->message);
+		g_error_free(error);
+	}
+	g_free(icondata);
+
+	return icon;
+}
+

=== added file 'libdbusmenu-gtk/menuitem.h'
--- libdbusmenu-gtk/menuitem.h	1970-01-01 00:00:00 +0000
+++ libdbusmenu-gtk/menuitem.h	2009-09-02 18:29:01 +0000
@@ -0,0 +1,39 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the 
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public 
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public 
+License version 3 and version 2.1 along with this program.  If not, see 
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_GTKMENUITEM_H__
+#define __DBUSMENU_GTKMENUITEM_H__ 1
+
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+gboolean dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data);
+GdkPixbuf * dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property);
+
+#endif

=== modified file 'tests/test-gtk-label-server.c'
--- tests/test-gtk-label-server.c	2009-07-20 21:04:00 +0000
+++ tests/test-gtk-label-server.c	2009-09-02 20:13:15 +0000
@@ -156,7 +156,7 @@
 	server = dbusmenu_server_new("/org/test");
 
 	timer_func(NULL);
-	g_timeout_add_seconds(15, timer_func, NULL);
+	g_timeout_add_seconds(5, timer_func, NULL);
 
 	mainloop = g_main_loop_new(NULL, FALSE);
 	g_main_loop_run(mainloop);

=== modified file 'tests/test-gtk-label.json'
--- tests/test-gtk-label.json	2009-09-02 14:56:21 +0000
+++ tests/test-gtk-label.json	2009-09-03 19:16:01 +0000
@@ -200,5 +200,123 @@
 		 ]
 		},
 	 ]
-	}
+	},
+	{"id": 8, "type": "menuitem",
+	 "label": "value1",
+	 "submenu": [
+	 	{"id": 80,
+		 "type": "imageitem",
+		 "icon": "face-angel",
+		 "label": "angel"},
+	 	{"id": 81,
+		 "type": "imageitem",
+		 "icon": "face-angry",
+		 "label": "angry"},
+	 	{"id": 82,
+		 "type": "imageitem",
+		 "icon": "face-cool",
+		 "label": "cool"},
+	 	{"id": 83,
+		 "type":"imageitem",
+		 "icon": "face-devilish",
+		 "label": "devilish"},
+	 	{"id": 84,
+		 "type": "imageitem",
+		 "icon": "face-embarrassed",
+		 "label": "embarrassed"},
+	 	{"id": 85,
+		 "type": "imageitem",
+		 "icon": "face-kiss",
+		 "label": "kiss"},
+	 	{"id": 86,
+		 "type": "imageitem",
+		 "icon": "face-laugh",
+		 "label": "laugh"},
+	 	{"id": 87,
+		 "type": "imageitem",
+		 "icon": "face-monkey",
+		 "label": "monkey"},
+	 	{"id": 88,
+		 "type": "imageitem",
+		 "icon": "face-sad",
+		 "label": "sad"},
+	 	{"id": 89,
+		 "type": "imageitem",
+		 "icon": "face-sick",
+		 "label": "sick"}
+	 ]
+	},
+	{"id": 9, "type": "menuitem",
+	 "label": "value1",
+	 "submenu": [
+	 	{"id": 90,
+		 "type": "imageitem",
+		 "icon-data":
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACPUlEQVR4nGJgoBAAAAAA///Ch1gW
+BzK0LQ5iaGNgYGDBpQgAAAD//8KpeY4/Q9+DCV7/H/S4/p8byDABlyEAAAAA///CqnluAMOEx5O8
+/3/f0/P/+47m/4967P7PC2GYysDAwIquGAAAAP//YkLXPC+AodfNyStfRMuegenvdwamP98ZhJWM
+GJzNzLIWhGMaAgAAAP//YkLT3Odq75InomrBwPT7CwPDr68M//98Y2D+951BREadwdFAL3VxJMNM
+ZEMAAAAA//9ihPs5gKHPzdo2V0TNkoGZ4T/D//9/GRj+/WJg+PeT4f/vHwwMf78z/P31jeHN89sM
++6/dXpS4lCGFgYHhNwAAAP//ghkguDqC4Z0CNwMDLwsDgxAHAwOfdQrD/1+fGP5/e83w/9tbhq/P
+LjG8+8PA8PkPA8PDbwwMIXMYhBkYGN4BAAAA//80zDEOQDAAAMBLZ2MnITEafEziK2YfM/QBLDoX
+g4jJPeD+IGJAgypNlrbuvNfBcxLYb/rZiIINK/IHAAD//zTRoRHAIBAAsMAU3X8iZCUSy5W7R0EN
+rJDcmoEXFU8sVq/ko5SIDQoaJj74AQAA//+CGfADKoEIGZhmZiQ+RM0D5FgAAAAA//9Cj0aEKNRm
+uGZmrCoZAAAAAP//wm4AskZkg7AAAAAAAP//wpo8n/6A2siEoJ/+wG4AAAAA///CZq4EAwODAZRG
+Bi8YEIEIBwAAAAD//8JmAAcDA4MAlEYGPxgYGD5AaTgAAAAA//8DAD6xjTP5Y+A7AAAAAElFTkSu
+QmCC",
+		 "label": "up"},
+	 	{"id": 91,
+		 "type": "imageitem",
+		 "icon-data":
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACl0lEQVR4nGJgoBAAAAAA//9ixCLG
+sSWS4bs0B1QWip/+YGDwWcLAycDA8ANZMQAAAP//YsFigIA0JwODdvIsBob/fxgY/vxk+P/7OwPD
+6ioGBgYGAQYGhhfIigEAAAD//8JmAAcDEwMDw5/vDAz/fjP8//uLgeHvDwYGJqgcGgAAAAD//8Jm
+AAMDIwPD/99fGBj+/WVg+PeLgeHvTwYGZqwqGQAAAAD//8JuADMDA8PPLwwMDH8Z/v//AzGACbsB
+AAAAAP//wmoAJwsDw/8/XxgY/v9l+P/rM8P/ry8ZONmwGwAAAAD//4LFAsfqaIbvCtwMDLxsDAxC
+7AwMPMqWDP+/Pmf4//01w//fXxm+/2NgePebgeHLHwaGR98ZGIKmQ2IEAAAA//80zisSQFAAAMAd
+wczzKRSvCIqrO4XqGoIkGTOv+SV7gv1j1XqY2jiI/agoSve2eM7VeyUyQk5X0gT2ZEYNHwAAAP//
+gnnhb+lWhuk//90TD1dncBThYGBgYWGA+JsRQv9lYGB4/5uBYcdDhotZSxhaGRgY/jEwMDAAAAAA
+//+CueALAwPDnZrtDK3r7jIcefuHgeEvI5JmRgaG938YGHY9YriatYShkoGB4TYDA8MnBgYGBgAA
+AAD//4IZ8JuBgeE1AwPDjfLNDE2b7jGcfPsLYutfRgaGD78ZGPY+ZrievpChjIGB4SoDA8NLqB4G
+AAAAAP//QkesDAwMMgwMDG6TwxnO3q5i+H+nhuH/nESGawwMDF4MDAzyDAwMKPEBAAAA///CZYgs
+AwODR18kw4UJ0QyX8WkGAAAA///ClpkYoAolGBgYFKBqHjAwMDxnYGD4ha4QAAAA///CZQDMEG4o
++ys2zQwMDAwAAAAA//8DAAF5nhyE7tENAAAAAElFTkSuQmCC",
+		 "label": "down"},
+	 	{"id": 92,
+		 "type": "imageitem",
+		 "icon": "up",
+		 "icon-data":
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACl0lEQVR4nGJgoBAAAAAA//9ixCLG
+sSWS4bs0B1QWip/+YGDwWcLAycDA8ANZMQAAAP//YsFigIA0JwODdvIsBob/fxgY/vxk+P/7OwPD
+6ioGBgYGAQYGhhfIigEAAAD//8JmAAcDEwMDw5/vDAz/fjP8//uLgeHvDwYGJqgcGgAAAAD//8Jm
+AAMDIwPD/99fGBj+/WVg+PeLgeHvTwYGZqwqGQAAAAD//8JuADMDA8PPLwwMDH8Z/v//AzGACbsB
+AAAAAP//wmoAJwsDw/8/XxgY/v9l+P/rM8P/ry8ZONmwGwAAAAD//4LFAsfqaIbvCtwMDLxsDAxC
+7AwMPMqWDP+/Pmf4//01w//fXxm+/2NgePebgeHLHwaGR98ZGIKmQ2IEAAAA//80zisSQFAAAMAd
+wczzKRSvCIqrO4XqGoIkGTOv+SV7gv1j1XqY2jiI/agoSve2eM7VeyUyQk5X0gT2ZEYNHwAAAP//
+gnnhb+lWhuk//90TD1dncBThYGBgYWGA+JsRQv9lYGB4/5uBYcdDhotZSxhaGRgY/jEwMDAAAAAA
+//+CueALAwPDnZrtDK3r7jIcefuHgeEvI5JmRgaG938YGHY9YriatYShkoGB4TYDA8MnBgYGBgAA
+AAD//4IZ8JuBgeE1AwPDjfLNDE2b7jGcfPsLYutfRgaGD78ZGPY+ZrievpChjIGB4SoDA8NLqB4G
+AAAAAP//QkesDAwMMgwMDG6TwxnO3q5i+H+nhuH/nESGawwMDF4MDAzyDAwMKPEBAAAA///CZYgs
+AwODR18kw4UJ0QyX8WkGAAAA///ClpkYoAolGBgYFKBqHjAwMDxnYGD4ha4QAAAA///CZQDMEG4o
++ys2zQwMDAwAAAAA//8DAAF5nhyE7tENAAAAAElFTkSuQmCC",
+		 "label": "up"},
+	 	{"id": 93,
+		 "type": "imageitem",
+		 "icon": "down",
+		 "icon-data":
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACPUlEQVR4nGJgoBAAAAAA///Ch1gW
+BzK0LQ5iaGNgYGDBpQgAAAD//8KpeY4/Q9+DCV7/H/S4/p8byDABlyEAAAAA///CqnluAMOEx5O8
+/3/f0/P/+47m/4967P7PC2GYysDAwIquGAAAAP//YkLXPC+AodfNyStfRMuegenvdwamP98ZhJWM
+GJzNzLIWhGMaAgAAAP//YkLT3Odq75InomrBwPT7CwPDr68M//98Y2D+951BREadwdFAL3VxJMNM
+ZEMAAAAA//9ihPs5gKHPzdo2V0TNkoGZ4T/D//9/GRj+/WJg+PeT4f/vHwwMf78z/P31jeHN89sM
++6/dXpS4lCGFgYHhNwAAAP//ghkguDqC4Z0CNwMDLwsDgxAHAwOfdQrD/1+fGP5/e83w/9tbhq/P
+LjG8+8PA8PkPA8PDbwwMIXMYhBkYGN4BAAAA//80zDEOQDAAAMBLZ2MnITEafEziK2YfM/QBLDoX
+g4jJPeD+IGJAgypNlrbuvNfBcxLYb/rZiIINK/IHAAD//zTRoRHAIBAAsMAU3X8iZCUSy5W7R0EN
+rJDcmoEXFU8sVq/ko5SIDQoaJj74AQAA//+CGfADKoEIGZhmZiQ+RM0D5FgAAAAA//9Cj0aEKNRm
+uGZmrCoZAAAAAP//wm4AskZkg7AAAAAAAP//wpo8n/6A2siEoJ/+wG4AAAAA///CZq4EAwODAZRG
+Bi8YEIEIBwAAAAD//8JmAAcDA4MAlEYGPxgYGD5AaTgAAAAA//8DAD6xjTP5Y+A7AAAAAElFTkSu
+QmCC",
+		 "label": "down"}
+	 ]
+	},
 ]