31
32
#include "cairo-dock-desktop-manager.h" // gldi_desktop_get_height
32
33
#include "cairo-dock-log.h"
33
34
#include "cairo-dock-draw.h"
35
#include "cairo-dock-backends-manager.h" // cairo_dock_get_dialog_decorator
36
#include "cairo-dock-dialog-manager.h" // myDialogsParam
37
#include "cairo-dock-style-manager.h"
34
38
#include "cairo-dock-menu.h"
40
#if GTK_MAJOR_VERSION > 2
41
static gboolean _draw_menu_item (GtkWidget *widget, cairo_t *cr, G_GNUC_UNUSED gpointer data);
42
static gboolean _on_select_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data);
43
static gboolean _on_deselect_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data);
44
static void _on_destroy_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data);
51
#if GTK_MAJOR_VERSION > 2
53
static void _init_menu_style (void)
55
static GtkCssProvider *cssProvider = NULL;
58
if (index == gldi_style_colors_get_index())
60
index = gldi_style_colors_get_index();
61
g_print ("%s (%d)\n", __func__, index);
63
if (myDialogsParam.bUseDefaultColors && myStyleParam.bUseSystemColors)
65
if (cssProvider != NULL)
67
gldi_style_colors_freeze ();
68
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider));
69
gldi_style_colors_freeze ();
70
g_object_unref (cssProvider);
76
if (cssProvider == NULL)
78
cssProvider = gtk_css_provider_new ();
79
gldi_style_colors_freeze ();
80
gtk_style_context_add_provider_for_screen (gdk_screen_get_default(), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_USER);
81
gldi_style_colors_freeze ();
84
double *bg_color = (myDialogsParam.bUseDefaultColors ? myStyleParam.fBgColor : myDialogsParam.fBgColor);
85
double *text_color = (myDialogsParam.bUseDefaultColors ? myStyleParam.textDescription.fColorStart : myDialogsParam.dialogTextDescription.fColorStart);
88
gldi_style_color_shade (bg_color, .2, rgb);
90
gldi_style_color_shade (bg_color, .2, rgbs);
92
gldi_style_color_shade (bg_color, .3, rgbb);
94
gchar *css = g_strdup_printf ("@define-color menuitem_bg_color rgb (%d, %d, %d); \
95
@define-color menuitem_text_color rgb (%d, %d, %d); \
96
@define-color menuitem_insensitive_text_color rgba (%d, %d, %d, .5); \
97
@define-color menuitem_separator_color rgb (%d, %d, %d); \
98
@define-color menuitem_bg_color2 rgb (%d, %d, %d); \
99
@define-color menu_bg_color rgba (%d, %d, %d, %d); \
102
border-image: none; \
104
background: transparent; \
105
color: @menuitem_text_color; \
107
.menuitem2 GtkImage { \
108
background: transparent; \
110
.menuitem2.separator, \
111
.menuitem2 .separator { \
112
color: @menuitem_separator_color; \
114
border-style: solid; \
115
border-image: none; \
116
border-color: @menuitem_separator_color; \
117
border-bottom-color: alpha (@menuitem_separator_color, 0.6); \
118
border-right-color: alpha (@menuitem_separator_color, 0.6); \
121
.menuitem2 *:hover { \
122
background: @menuitem_bg_color; \
123
background-image: none; \
125
border-image: none; \
127
color: @menuitem_text_color; \
129
.menuitem2 *:insensitive { \
131
color: @menuitem_insensitive_text_color; \
135
background: @menuitem_bg_color; \
136
border-image: none; \
137
border-color: transparent; \
138
color: @menuitem_text_color; \
140
.menuitem2 .button, \
141
.menuitem2.button { \
142
background: @menuitem_bg_color; \
143
background-image: none; \
145
border-color: transparent; \
150
background: @menuitem_bg_color2; \
151
background-image: none; \
152
color: @menuitem_text_color; \
153
border-image: none; \
155
.menuitem2 .scale.left, \
156
.menuitem2.scale.left { \
157
background: @menuitem_bg_color; \
158
background-image: none; \
159
border-image: none; \
161
.menuitem2 .scale.slider, \
162
.menuitem2.scale.slider { \
163
background: @menuitem_text_color; \
164
background-image: none; \
165
border-image: none; \
167
.menuitem2 GtkCalendar, \
168
.menuitem2 GtkCalendar.button, \
169
.menuitem2 GtkCalendar.header, \
170
.menuitem2 GtkCalendar.view { \
171
background-color: @menuitem_bg_color; \
172
background-image: none; \
173
color: @menuitem_text_color; \
175
.menuitem2 GtkCalendar { \
176
background-color: @menuitem_bg_color2; \
177
background-image: none; \
179
.menuitem2 GtkCalendar:inconsistent { \
180
color: shade (@menuitem_bg_color2, 0.6); \
183
background: @menu_bg_color; \
184
background-image: none; \
185
color: @menuitem_text_color; \
187
(int)(rgb[0]*255), (int)(rgb[1]*255), (int)(rgb[2]*255),
188
(int)(text_color[0]*255), (int)(text_color[1]*255), (int)(text_color[2]*255),
189
(int)(text_color[0]*255), (int)(text_color[1]*255), (int)(text_color[2]*255),
190
(int)(rgbs[0]*255), (int)(rgbs[1]*255), (int)(rgbs[2]*255),
191
(int)(rgbb[0]*255), (int)(rgbb[1]*255), (int)(rgbb[2]*255),
192
(int)(bg_color[0]*255), (int)(bg_color[1]*255), (int)(bg_color[2]*255), (int)(bg_color[3]*255)); // we also define ".menu", so that custom widgets (like in the SoundMenu) can get our colors.
194
gldi_style_colors_freeze ();
195
gtk_css_provider_load_from_data (cssProvider,
196
css, -1, NULL); // (should) clear any previously loaded information
197
gldi_style_colors_freeze ();
202
static gboolean _draw_menu (GtkWidget *pWidget,
203
cairo_t *pCairoContext,
204
G_GNUC_UNUSED GtkWidget *menu)
206
// erase the default background
207
cairo_dock_erase_cairo_context (pCairoContext);
209
// draw the background/outline and set the clip
210
CairoDialogDecorator *pDecorator = cairo_dock_get_dialog_decorator (myDialogsParam.cDecoratorName);
212
pDecorator->render_menu (pWidget, pCairoContext);
215
cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 1.0);
217
GtkWidgetClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_FROM_INSTANCE (pWidget)));
218
parent_class = g_type_class_peek_parent (parent_class); // skip the direct parent (GtkBin, which does anyway nothing usually), because dbusmenu-gtk draws it
219
parent_class->draw (pWidget, pCairoContext);
224
static void _set_margin_position (GtkWidget *pMenu, GldiMenuParams *pParams)
227
pParams = g_object_get_data (G_OBJECT (pMenu), "gldi-params");
228
g_return_if_fail (pParams);
229
Icon *pIcon = pParams->pIcon;
230
g_return_if_fail (pIcon);
231
GldiContainer *pContainer = cairo_dock_get_icon_container (pIcon);
232
g_return_if_fail (pContainer);
234
// define where the menu will point
235
int iMarginPosition; // b, t, r, l
236
int y0 = pContainer->iWindowPositionY + pIcon->fDrawY;
237
if (pContainer->bDirectionUp)
238
y0 += pIcon->fHeight * pIcon->fScale - pIcon->image.iHeight; // the icon might not be maximised yet
239
int Hs = (pContainer->bIsHorizontal ? gldi_desktop_get_height() : gldi_desktop_get_width());
240
if (pContainer->bIsHorizontal)
242
iMarginPosition = (y0 > Hs/2 ? 0 : 1);
246
iMarginPosition = (y0 > Hs/2 ? 2 : 3);
249
// store the result, and allocate some space to draw the arrow
250
if (iMarginPosition != pParams->iMarginPosition) // margin position is now defined or has changed -> update it on the menu
252
g_print ("margin position: %d -> %d\n", pParams->iMarginPosition, iMarginPosition);
254
pParams->iMarginPosition = iMarginPosition;
256
// get/add a css (gtk_widget_set_margin_xxx doesn't work as expected :-/)
257
GtkCssProvider *cssProvider = pParams->cssProvider;
258
if (cssProvider) // unfortunately, GTK doesn't update correctly a css provider if we load some new data inside (the previous padding values are kept, along with the new ones, although 'gtk_css_provider_load_from_data' is supposed to "clear any previously loaded information"), so we have to remove/add it :-/
260
gtk_style_context_remove_provider (gtk_widget_get_style_context(pMenu), GTK_STYLE_PROVIDER(cssProvider));
261
g_object_unref (cssProvider);
263
pParams->cssProvider = NULL;
265
if (cssProvider == NULL)
267
cssProvider = gtk_css_provider_new ();
268
gtk_style_context_add_provider (gtk_widget_get_style_context(pMenu), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_USER); // this adds a reference on the provider, plus the one we own
269
pParams->cssProvider = cssProvider;
270
g_print (" + css\n");
273
// load the new padding rule into the css
275
int ah = pParams->iArrowHeight;
276
int b=0, t=0, r=0, l=0;
277
switch (iMarginPosition)
279
case 0: b = ah; break;
280
case 1: t = ah; break;
281
case 2: r = ah; break;
282
case 3: l = ah; break;
285
css = g_strdup_printf ("GtkMenu { \
286
padding-bottom: %dpx; \
288
padding-right: %dpx; \
289
padding-left: %dpx; \
290
}", b, t, r, l); // we must define all the paddings, else if the margin position changes, clearing the css won't make the padding disappear :-/
291
gtk_css_provider_load_from_data (cssProvider,
41
298
GtkWidget *gldi_menu_new (G_GNUC_UNUSED Icon *pIcon)
43
300
GtkWidget *pMenu = gtk_menu_new ();
50
307
static gboolean _on_icon_destroyed (GtkWidget *pMenu, G_GNUC_UNUSED Icon *pIcon)
52
g_object_set_data (G_OBJECT (pMenu), "gldi-icon", NULL);
309
GldiMenuParams *pParams = g_object_get_data (G_OBJECT (pMenu), "gldi-params");
311
pParams->pIcon = NULL;
53
312
return GLDI_NOTIFICATION_LET_PASS;
56
315
static void _on_menu_destroyed (GtkWidget *pMenu, G_GNUC_UNUSED gpointer data)
58
Icon *pIcon = g_object_get_data (G_OBJECT(pMenu), "gldi-icon");
317
GldiMenuParams *pParams = g_object_get_data (G_OBJECT (pMenu), "gldi-params");
320
Icon *pIcon = pParams->pIcon;
60
322
gldi_object_remove_notification (pIcon,
61
323
NOTIFICATION_DESTROY,
62
324
(GldiNotificationFunc) _on_icon_destroyed,
66
void gldi_menu_init (G_GNUC_UNUSED GtkWidget *pMenu, G_GNUC_UNUSED Icon *pIcon)
326
#if GTK_MAJOR_VERSION > 2
327
if (pParams->cssProvider)
329
g_object_unref (pParams->cssProvider); /// need to remove the provider from the style context ?... probably not since the style context will be destroyed and will release its reference on the provider
335
#if GTK_MAJOR_VERSION > 2
336
static void _on_menu_deactivated (GtkMenuShell *pMenu, G_GNUC_UNUSED gpointer data)
338
GldiMenuParams *pParams = g_object_get_data (G_OBJECT (pMenu), "gldi-params");
341
Icon *pIcon = pParams->pIcon;
342
if (pIcon->iHideLabel > 0)
344
pIcon->iHideLabel --;
345
GldiContainer *pContainer = cairo_dock_get_icon_container (pIcon);
346
if (pIcon->iHideLabel == 0 && pContainer)
347
gtk_widget_queue_draw (pContainer->pWidget);
352
void gldi_menu_init (G_GNUC_UNUSED GtkWidget *pMenu, Icon *pIcon)
68
354
#if (CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1)
69
355
gtk_menu_set_reserve_toggle_size (GTK_MENU(pMenu), TRUE);
358
#if GTK_MAJOR_VERSION > 2
359
// connect to 'draw' event to draw the menu (background and items)
360
GtkWidget *pWindow = gtk_widget_get_toplevel (pMenu);
361
cairo_dock_set_default_rgba_visual (pWindow);
363
g_signal_connect (G_OBJECT (pMenu),
365
G_CALLBACK (_draw_menu),
370
gtk_style_context_add_class (gtk_widget_get_style_context (pMenu), "menu2");
374
GldiMenuParams *pParams = g_new0 (GldiMenuParams, 1);
375
g_object_set_data (G_OBJECT (pMenu), "gldi-params", pParams);
376
g_signal_connect (G_OBJECT (pMenu),
378
G_CALLBACK (_on_menu_destroyed),
72
382
if (pIcon != NULL) // the menu points on an icon
74
384
// link it to the icon
75
385
g_object_set_data (G_OBJECT (pMenu), "gldi-icon", pIcon);
386
pParams->pIcon = pIcon;
76
387
gldi_object_register_notification (pIcon,
77
388
NOTIFICATION_DESTROY,
78
389
(GldiNotificationFunc) _on_icon_destroyed,
79
GLDI_RUN_AFTER, pMenu); // when the icon is destroyed, unlink the menu from it
80
g_signal_connect (G_OBJECT (pMenu),
82
G_CALLBACK (_on_menu_destroyed),
83
NULL); // when the menu is destroyed, unregister the above notification on the icon
390
GLDI_RUN_AFTER, pMenu); // when the icon is destroyed, unlink the menu from it; when the menu is destroyed, the above notification will be unregistered on the icon in the "destroy" callback
392
GldiContainer *pContainer = cairo_dock_get_icon_container (pIcon);
393
if (pContainer != NULL)
395
#if GTK_MAJOR_VERSION > 2
396
// init the rendering --> align, margin-height
397
CairoDialogDecorator *pDecorator = cairo_dock_get_dialog_decorator (myDialogsParam.cDecoratorName);
399
pDecorator->setup_menu (pMenu);
401
// define where the menu will point, and allocate some space to draw the arrow
402
pParams->iMarginPosition = -1;
403
_set_margin_position (pMenu, pParams);
405
// show the icon's label back when the menu is hidden
406
g_signal_connect (G_OBJECT (pMenu),
408
G_CALLBACK (_on_menu_deactivated),
412
const gchar *orientation = "";
413
int ah = pParams->iArrowHeight;
414
switch (pParams->iMarginPosition)
416
case 0: orientation = "bottom"; break;
417
case 1: orientation = "top"; break;
418
case 2: orientation = "right"; break;
419
case 3: orientation = "left"; break;
423
GtkCssProvider *cssProvider = gtk_css_provider_new ();
424
css = g_strdup_printf ("GtkMenu { \
426
}", orientation, ah);
427
gtk_css_provider_load_from_data (cssProvider,
429
gtk_style_context_add_provider (gtk_widget_get_style_context(pMenu), GTK_STYLE_PROVIDER(cssProvider), GTK_STYLE_PROVIDER_PRIORITY_USER);
87
436
static void _place_menu_on_icon (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, G_GNUC_UNUSED gpointer data)
90
Icon *pIcon = g_object_get_data (G_OBJECT(menu), "gldi-icon");
439
GldiMenuParams *pParams = g_object_get_data (G_OBJECT(menu), "gldi-params");
440
g_return_if_fail (pParams != NULL);
442
Icon *pIcon = pParams->pIcon;
91
443
GldiContainer *pContainer = (pIcon ? cairo_dock_get_icon_container (pIcon) : NULL);
92
444
int x0 = pContainer->iWindowPositionX + pIcon->fDrawX;
93
445
int y0 = pContainer->iWindowPositionY + pIcon->fDrawY;
104
456
w = requisition.width;
105
457
h = requisition.height;
459
/// TODO: use iMarginPosition...
460
#if GTK_MAJOR_VERSION > 2
461
double fAlign = pParams->fAlign;
462
int r = pParams->iRadius;
463
int ah = pParams->iArrowHeight;
466
int iAimedX, iAimedY;
107
467
int Hs = (pContainer->bIsHorizontal ? gldi_desktop_get_height() : gldi_desktop_get_width());
108
//g_print ("%d;%d %dx%d\n", x0, y0, w, h);
109
468
if (pContainer->bIsHorizontal)
470
iAimedX = x0 + pIcon->image.iWidth/2;
471
#if GTK_MAJOR_VERSION > 2
474
*x = MAX (0, iAimedX - fAlign * w_ - r);
112
478
if (y0 > Hs/2) // pContainer->bDirectionUp
115
485
*y = y0 + pIcon->fHeight * pIcon->fScale;
486
iAimedY = y0 + pIcon->image.iHeight;
119
*y = MIN (x0, gldi_desktop_get_height() - h);
491
iAimedY = x0 + pIcon->image.iWidth/2;
492
#if GTK_MAJOR_VERSION > 2
495
*y = MIN (iAimedY - fAlign * h_ - r, gldi_desktop_get_height() - h);
497
*y = MIN (iAimedY, gldi_desktop_get_height() - h);
120
499
if (y0 > Hs/2) // pContainer->bDirectionUp
123
*x = y0 + pIcon->fHeight * pIcon->fScale;
506
*x = y0 + pIcon->image.iHeight;
507
iAimedX = y0 + pIcon->image.iHeight;
510
pParams->iAimedX = iAimedX;
511
pParams->iAimedY = iAimedY;
514
#if GTK_MAJOR_VERSION > 2
515
static void _init_menu_item (GtkWidget *pMenuItem)
517
int index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pMenuItem), "gldi-text-color"));
520
// the following code is to draw the menu item; this is more like a proof of concept
521
/**g_signal_connect (G_OBJECT (pMenuItem),
523
G_CALLBACK (_draw_menu_item),
525
g_signal_connect (G_OBJECT (pMenuItem),
527
G_CALLBACK (_on_select_menu_item),
529
g_signal_connect (G_OBJECT (pMenuItem),
531
G_CALLBACK (_on_deselect_menu_item),
533
g_signal_connect (G_OBJECT (pMenuItem),
535
G_CALLBACK (_on_destroy_menu_item),
538
gtk_style_context_add_class (gtk_widget_get_style_context (pMenuItem), "menuitem2");
540
g_object_set_data (G_OBJECT (pMenuItem), "gldi-text-color", GINT_TO_POINTER(1));
543
GtkWidget *pSubMenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (pMenuItem));
544
if (pSubMenu != NULL) /// TODO: if it's a sub-menu not made by us (for instance, the NetworkManager indicator), set the drawing callback...
545
gtk_container_forall (GTK_CONTAINER (pSubMenu), (GtkCallback) _init_menu_item, NULL);
126
549
static void _popup_menu (GtkWidget *menu, guint32 time)
128
Icon *pIcon = g_object_get_data (G_OBJECT(menu), "gldi-icon");
551
GldiMenuParams *pParams = g_object_get_data (G_OBJECT(menu), "gldi-params");
552
g_return_if_fail (pParams != NULL);
554
Icon *pIcon = pParams->pIcon;
129
555
GldiContainer *pContainer = (pIcon ? cairo_dock_get_icon_container (pIcon) : NULL);
131
557
// setup the menu for the container
132
if (pContainer != NULL)
134
if (pContainer->iface.setup_menu)
135
pContainer->iface.setup_menu (pContainer, pIcon, menu);
558
if (pContainer && pContainer->iface.setup_menu)
559
pContainer->iface.setup_menu (pContainer, pIcon, menu);
561
#if GTK_MAJOR_VERSION > 2
566
if (pIcon && pContainer)
568
// hide the icon's label, since menus are placed right above the icon (and therefore, the arrow overlaps the label, which makes it hard to see if both colors are similar).
569
if (pIcon->iHideLabel == 0 && pContainer)
570
gtk_widget_queue_draw (pContainer->pWidget);
571
pIcon->iHideLabel ++;
573
// ensure margin position is still correct
574
_set_margin_position (menu, pParams);
139
578
gtk_widget_show_all (GTK_WIDGET (menu));
580
#if GTK_MAJOR_VERSION > 2
581
// to draw the items ourselves
582
gtk_container_forall (GTK_CONTAINER (menu), (GtkCallback) _init_menu_item, NULL);
141
585
gtk_menu_popup (GTK_MENU (menu),
173
617
/// MENU ITEM ///
174
618
/////////////////
620
#if GTK_MAJOR_VERSION > 2
626
get_arrow_size (GtkWidget *widget,
631
PangoContext *context;
632
PangoFontMetrics *metrics;
633
gfloat arrow_scaling;
638
gtk_widget_style_get (widget,
639
"arrow-scaling", &arrow_scaling,
640
"arrow-spacing", &arrow_spacing,
644
*spacing = arrow_spacing;
646
context = gtk_widget_get_pango_context (child);
648
metrics = pango_context_get_metrics (context,
649
pango_context_get_font_description (context),
650
pango_context_get_language (context));
652
*size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
653
pango_font_metrics_get_descent (metrics)));
655
pango_font_metrics_unref (metrics);
657
*size = *size * arrow_scaling;
659
static gboolean _draw_menu_item (GtkWidget *widget,
661
G_GNUC_UNUSED gpointer data)
663
//GtkStateFlags state;
664
GtkStyleContext *context;
666
gint x, y, w, h, width, height;
667
guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
669
child = gtk_bin_get_child (GTK_BIN (widget));
671
//state = gtk_widget_get_state_flags (widget);
672
context = gtk_widget_get_style_context (widget);
673
width = gtk_widget_get_allocated_width (widget);
674
height = gtk_widget_get_allocated_height (widget);
678
w = width - border_width * 2;
679
h = height - border_width * 2;
681
// draw the background
682
int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "gldi-step"));
683
if (n != 0) // so we only draw the barkground if the item is or was selected
685
double a = (double)n/N;
690
cairo_dock_draw_rounded_rectangle (cr, r, l, w - 2*r, h);
693
gldi_style_colors_set_selected_bg_color (cr);
694
cairo_paint_with_alpha (cr, a);
699
// draw the arrow in case of a sub-menu
700
if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)))
702
gint arrow_x, arrow_y;
703
gint arrow_size, spacing;
704
GtkTextDirection direction;
707
direction = gtk_widget_get_direction (widget);
708
get_arrow_size (widget, child, &arrow_size, &spacing);
710
if (direction == GTK_TEXT_DIR_LTR)
712
arrow_x = x + w - arrow_size - spacing;
717
arrow_x = x + spacing;
718
angle = (3 * G_PI) / 2;
721
arrow_y = y + (h - arrow_size) / 2;
723
gtk_render_arrow (context, cr, angle, arrow_x, arrow_y, arrow_size);
725
else if (!child) // separator
727
gboolean wide_separators;
728
gint separator_height;
731
g_print ("SEPARATOR\n");
732
gtk_style_context_get_padding (context, 0, &padding);
733
gtk_widget_style_get (widget,
734
"wide-separators", &wide_separators,
735
"separator-height", &separator_height,
738
gtk_render_frame (context, cr,
741
w - padding.left - padding.right,
744
gtk_render_line (context, cr,
747
x + w - padding.right - 1,
751
// draw the item's content
752
GtkWidgetClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_FROM_INSTANCE (widget)));
753
parent_class = g_type_class_peek_parent (parent_class);
755
cairo_set_source_rgba (cr, 1, 1, 1, 1);
757
parent_class->draw (widget, cr);
758
return TRUE; // intercept
761
static gboolean _update_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data)
763
int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-step"));
764
gboolean bInside = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-inside"));
776
g_object_set_data (G_OBJECT(pMenuItem), "gldi-step", GINT_TO_POINTER (n));
778
gtk_widget_queue_draw (pMenuItem);
780
if (n == 0 || n == N)
782
guint iSidAnimation = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-animation"));
783
if (iSidAnimation != 0)
785
g_source_remove (iSidAnimation);
786
g_object_set_data (G_OBJECT(pMenuItem), "gldi-animation", NULL);
792
static gboolean _on_select_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data)
794
guint iSidAnimation = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-animation"));
795
if (iSidAnimation != 0)
796
g_source_remove (iSidAnimation);
797
iSidAnimation = g_timeout_add (dt1, (GSourceFunc)_update_menu_item, pMenuItem);
798
g_object_set_data (G_OBJECT(pMenuItem), "gldi-animation", GUINT_TO_POINTER (iSidAnimation));
800
g_object_set_data (G_OBJECT(pMenuItem), "gldi-inside", GINT_TO_POINTER (TRUE));
804
static gboolean _on_deselect_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data)
806
guint iSidAnimation = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-animation"));
807
if (iSidAnimation != 0)
808
g_source_remove (iSidAnimation);
809
iSidAnimation = g_timeout_add (dt2, (GSourceFunc)_update_menu_item, pMenuItem);
810
g_object_set_data (G_OBJECT(pMenuItem), "gldi-animation", GUINT_TO_POINTER (iSidAnimation));
812
g_object_set_data (G_OBJECT(pMenuItem), "gldi-inside", GINT_TO_POINTER (FALSE));
816
static void _on_destroy_menu_item (GtkWidget* pMenuItem, G_GNUC_UNUSED gpointer data)
818
guint iSidAnimation = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(pMenuItem), "gldi-animation"));
819
if (iSidAnimation != 0)
821
g_source_remove (iSidAnimation);
822
g_object_set_data (G_OBJECT(pMenuItem), "gldi-animation", NULL);
176
827
GtkWidget *gldi_menu_item_new_full (const gchar *cLabel, const gchar *cImage, gboolean bUseMnemonic, GtkIconSize iSize)
185
return gtk_menu_item_new ();
836
pMenuItem = gtk_menu_item_new ();
187
return (bUseMnemonic ? gtk_menu_item_new_with_mnemonic (cLabel) : gtk_menu_item_new_with_label (cLabel));
838
pMenuItem = (bUseMnemonic ? gtk_menu_item_new_with_mnemonic (cLabel) : gtk_menu_item_new_with_label (cLabel));
190
GtkWidget *image = NULL;
842
GtkWidget *image = NULL;
191
843
#if (! GTK_CHECK_VERSION (3, 10, 0)) || (CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1)
195
gtk_icon_size_lookup (iSize, &size, NULL);
196
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cImage, size, size, NULL);
197
image = gtk_image_new_from_pixbuf (pixbuf);
198
g_object_unref (pixbuf);
200
else if (*cImage != '\0')
202
#if GTK_CHECK_VERSION (3, 10, 0)
203
image = gtk_image_new_from_icon_name (cImage, iSize); /// actually, this will not work until we replace all the gtk-stock names by standard icon names... which is a PITA, and will be done do later
847
gtk_icon_size_lookup (iSize, &size, NULL);
848
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cImage, size, size, NULL);
849
image = gtk_image_new_from_pixbuf (pixbuf);
850
g_object_unref (pixbuf);
852
else if (*cImage != '\0')
854
#if GTK_CHECK_VERSION (3, 10, 0)
855
image = gtk_image_new_from_icon_name (cImage, iSize); /// actually, this will not work until we replace all the gtk-stock names by standard icon names... which is a PITA, and will be done do later
857
image = gtk_image_new_from_stock (cImage, iSize);
862
#if GTK_CHECK_VERSION (3, 10, 0)
863
#if (CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1)
865
pMenuItem = gtk3_image_menu_item_new ();
867
pMenuItem = (bUseMnemonic ? gtk3_image_menu_item_new_with_mnemonic (cLabel) : gtk3_image_menu_item_new_with_label (cLabel));
868
gtk3_image_menu_item_set_image (GTK3_IMAGE_MENU_ITEM (pMenuItem), image);
205
image = gtk_image_new_from_stock (cImage, iSize);
871
pMenuItem = gtk_menu_item_new ();
873
pMenuItem = (bUseMnemonic ? gtk_menu_item_new_with_mnemonic (cLabel) : gtk_menu_item_new_with_label (cLabel));
210
#if GTK_CHECK_VERSION (3, 10, 0)
211
#if (CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1)
213
pMenuItem = gtk3_image_menu_item_new ();
215
pMenuItem = (bUseMnemonic ? gtk3_image_menu_item_new_with_mnemonic (cLabel) : gtk3_image_menu_item_new_with_label (cLabel));
216
gtk3_image_menu_item_set_image (GTK3_IMAGE_MENU_ITEM (pMenuItem), image);
219
pMenuItem = gtk_menu_item_new ();
221
pMenuItem = (bUseMnemonic ? gtk_menu_item_new_with_mnemonic (cLabel) : gtk_menu_item_new_with_label (cLabel));
225
pMenuItem = gtk_image_menu_item_new ();
227
pMenuItem = (bUseMnemonic ? gtk_image_menu_item_new_with_mnemonic (cLabel) : gtk_image_menu_item_new_with_label (cLabel));
228
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pMenuItem), image);
229
#if ((CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1) && (GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION >= 16))
230
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (pMenuItem), TRUE);
877
pMenuItem = gtk_image_menu_item_new ();
879
pMenuItem = (bUseMnemonic ? gtk_image_menu_item_new_with_mnemonic (cLabel) : gtk_image_menu_item_new_with_label (cLabel));
880
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pMenuItem), image);
881
#if ((CAIRO_DOCK_FORCE_ICON_IN_MENUS == 1) && (GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION >= 16))
882
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (pMenuItem), TRUE);
234
886
gtk_widget_show_all (pMenuItem); // show immediately, so that the menu-item is realized when the menu is popped up
236
888
return pMenuItem;