1 /*
2 * Off-the-Record Messaging plugin for pidgin
3 * Copyright (C) 2004-2012 Ian Goldberg, Rob Smits,
4 * Chris Alexander, Willy Lew,
5 * Nikita Borisov
6 * <otr@cypherpunks.ca>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /* This file is based on a copy of gtkkmenutray.c */
23
24
25 /*
26 * Pidgin is the legal property of its developers, whose names are too numerous
27 * to list here. Please refer to the COPYRIGHT file distributed with this
28 * source distribution.
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
43 */
44 #include "debug.h"
45
46 #include "tooltipmenu.h"
47
48 #include <gtk/gtkeventbox.h>
49 #include <gtk/gtkiconfactory.h>
50 #include <gtk/gtkversion.h>
51
52 /******************************************************************************
53 * Enums
54 *****************************************************************************/
55 enum {
56 PROP_ZERO = 0,
57 PROP_BOX
58 };
59
60 /******************************************************************************
61 * Globals
62 *****************************************************************************/
63 static GObjectClass *parent_class = NULL;
64
65 /******************************************************************************
66 * Internal Stuff
67 *****************************************************************************/
68
69 /******************************************************************************
70 * Item Stuff
71 *****************************************************************************/
72 /*static void
73 tooltip_menu_select(GtkItem *item) {
74
75 }
76
77 static void
78 tooltip_menu_deselect(GtkItem *item) {
79
80 }*/
81
82 /******************************************************************************
83 * Widget Stuff
84 *****************************************************************************/
85
86 /******************************************************************************
87 * Object Stuff
88 *****************************************************************************/
89 static void
tooltip_menu_get_property(GObject * obj,guint param_id,GValue * value,GParamSpec * pspec)90 tooltip_menu_get_property(GObject *obj, guint param_id, GValue *value,
91 GParamSpec *pspec)
92 {
93 TooltipMenu *tooltip_menu = TOOLTIP_MENU(obj);
94
95 switch(param_id) {
96 case PROP_BOX:
97 g_value_set_object(value, tooltip_menu_get_box(tooltip_menu));
98 break;
99 default:
100 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
101 break;
102 }
103 }
104
105 static void
tooltip_menu_finalize(GObject * obj)106 tooltip_menu_finalize(GObject *obj) {
107 #if 0
108 /* This _might_ be leaking, but I have a sneaking suspicion that the widget is
109 * getting destroyed in GtkContainer's finalize function. But if were are
110 * leaking here, be sure to figure out why this causes a crash.
111 * -- Gary
112 */
113 TooltipMenu *tray = TOOLTIP_MENU(obj);
114
115 if(GTK_IS_WIDGET(tray->tray))
116 gtk_widget_destroy(GTK_WIDGET(tray->tray));
117 #endif
118
119 G_OBJECT_CLASS(parent_class)->finalize(obj);
120 }
121
122 static void
tooltip_menu_class_init(TooltipMenuClass * klass)123 tooltip_menu_class_init(TooltipMenuClass *klass) {
124 GObjectClass *object_class = G_OBJECT_CLASS(klass);
125 GParamSpec *pspec;
126
127 parent_class = g_type_class_peek_parent(klass);
128
129 object_class->finalize = tooltip_menu_finalize;
130 object_class->get_property = tooltip_menu_get_property;
131
132 pspec = g_param_spec_object("box", "The box",
133 "The box",
134 GTK_TYPE_BOX,
135 G_PARAM_READABLE);
136 g_object_class_install_property(object_class, PROP_BOX, pspec);
137 }
138
139 static void
tooltip_menu_init(TooltipMenu * tooltip_menu)140 tooltip_menu_init(TooltipMenu *tooltip_menu) {
141 GtkWidget *widget = GTK_WIDGET(tooltip_menu);
142 gtk_menu_item_set_right_justified(GTK_MENU_ITEM(tooltip_menu), TRUE);
143
144 if(!GTK_IS_WIDGET(tooltip_menu->tray))
145 tooltip_menu->tray = gtk_hbox_new(FALSE, 0);
146
147 tooltip_menu->tooltips = gtk_tooltips_new();
148
149 gtk_widget_set_size_request(widget, -1, -1);
150
151 gtk_container_add(GTK_CONTAINER(tooltip_menu), tooltip_menu->tray);
152
153 gtk_widget_show(tooltip_menu->tray);
154 }
155
156 /******************************************************************************
157 * API
158 *****************************************************************************/
159 GType
tooltip_menu_get_gtype(void)160 tooltip_menu_get_gtype(void) {
161 static GType type = 0;
162
163 if(type == 0) {
164 static const GTypeInfo info = {
165 sizeof(TooltipMenuClass),
166 NULL,
167 NULL,
168 (GClassInitFunc)tooltip_menu_class_init,
169 NULL,
170 NULL,
171 sizeof(TooltipMenu),
172 0,
173 (GInstanceInitFunc)tooltip_menu_init,
174 NULL
175 };
176
177 type = g_type_register_static(GTK_TYPE_MENU_ITEM,
178 "TooltipMenu",
179 &info, 0);
180 }
181
182 return type;
183 }
184
185 GtkWidget *
tooltip_menu_new()186 tooltip_menu_new() {
187 return g_object_new(TYPE_TOOLTIP_MENU, NULL);
188 }
189
190 GtkWidget *
tooltip_menu_get_box(TooltipMenu * tooltip_menu)191 tooltip_menu_get_box(TooltipMenu *tooltip_menu) {
192 g_return_val_if_fail(IS_TOOLTIP_MENU(tooltip_menu), NULL);
193 return tooltip_menu->tray;
194 }
195
196 static void
tooltip_menu_add(TooltipMenu * tooltip_menu,GtkWidget * widget,const char * tooltip,gboolean prepend)197 tooltip_menu_add(TooltipMenu *tooltip_menu, GtkWidget *widget,
198 const char *tooltip, gboolean prepend)
199 {
200 g_return_if_fail(IS_TOOLTIP_MENU(tooltip_menu));
201 g_return_if_fail(GTK_IS_WIDGET(widget));
202
203 if (GTK_WIDGET_NO_WINDOW(widget))
204 {
205 GtkWidget *event;
206
207 event = gtk_event_box_new();
208 gtk_container_add(GTK_CONTAINER(event), widget);
209 gtk_widget_show(event);
210 widget = event;
211 }
212
213 tooltip_menu_set_tooltip(tooltip_menu, widget, tooltip);
214
215 if (prepend)
216 gtk_box_pack_start(GTK_BOX(tooltip_menu->tray), widget, FALSE, FALSE, 0);
217 else
218 gtk_box_pack_end(GTK_BOX(tooltip_menu->tray), widget, FALSE, FALSE, 0);
219 }
220
221 void
tooltip_menu_append(TooltipMenu * tooltip_menu,GtkWidget * widget,const char * tooltip)222 tooltip_menu_append(TooltipMenu *tooltip_menu, GtkWidget *widget, const char *tooltip)
223 {
224 tooltip_menu_add(tooltip_menu, widget, tooltip, FALSE);
225 }
226
227 void
tooltip_menu_prepend(TooltipMenu * tooltip_menu,GtkWidget * widget,const char * tooltip)228 tooltip_menu_prepend(TooltipMenu *tooltip_menu, GtkWidget *widget, const char *tooltip)
229 {
230 tooltip_menu_add(tooltip_menu, widget, tooltip, TRUE);
231 }
232
233 void
tooltip_menu_set_tooltip(TooltipMenu * tooltip_menu,GtkWidget * widget,const char * tooltip)234 tooltip_menu_set_tooltip(TooltipMenu *tooltip_menu, GtkWidget *widget, const char *tooltip)
235 {
236 if (!tooltip_menu->tooltips)
237 return;
238
239 /* Should we check whether widget is a child of tooltip_menu? */
240
241 /*
242 * If the widget does not have it's own window, then it
243 * must have automatically been added to an event box
244 * when it was added to the menu tray. If this is the
245 * case, we want to set the tooltip on the widget's parent,
246 * not on the widget itself.
247 */
248 if (GTK_WIDGET_NO_WINDOW(widget))
249 widget = widget->parent;
250
251 gtk_tooltips_set_tip(tooltip_menu->tooltips, widget, tooltip, NULL);
252 }
253
254