3 #include <gdk/gdkkeysyms.h>
4 #include "cellrendererkey.h"
8 #define CELL_RENDERER_TEXT_PATH "cell-renderer-key-text"
10 #define TOOLTIP_TEXT _("Press key or…")
12 static void cell_renderer_key_finalize (GObject *object);
13 static void cell_renderer_key_init (CellRendererKey *cell_key);
14 static void cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class);
15 static GtkCellEditable *cell_renderer_key_start_editing (GtkCellRenderer *cell,
19 GdkRectangle *background_area,
20 GdkRectangle *cell_area,
21 GtkCellRendererState flags);
23 static void cell_renderer_key_get_property (GObject *object,
27 static void cell_renderer_key_set_property (GObject *object,
31 static void cell_renderer_key_get_size (GtkCellRenderer *cell,
33 GdkRectangle *cell_area,
46 static GtkCellRendererTextClass *parent_class = NULL;
48 GType cell_renderer_key_get_type (void)
50 static GType cell_key_type = 0;
54 static const GTypeInfo cell_key_info =
56 sizeof (CellRendererKeyClass),
58 NULL, /* base_finalize */
59 (GClassInitFunc)cell_renderer_key_class_init,
60 NULL, /* class_finalize */
61 NULL, /* class_data */
62 sizeof (CellRendererKey),
64 (GInstanceInitFunc) cell_renderer_key_init
67 cell_key_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "CellRendererKey", &cell_key_info, 0);
74 cell_renderer_key_init (CellRendererKey *key)
81 marshal_VOID__STRING_UINT (GClosure *closure,
84 const GValue *param_values,
85 gpointer invocation_hint,
86 gpointer marshal_data)
88 typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer data1,
92 register GMarshalFunc_VOID__STRING_UINT callback;
93 register GCClosure *cc = (GCClosure*) closure;
94 register gpointer data1, data2;
96 g_return_if_fail (n_param_values == 3);
98 if (G_CCLOSURE_SWAP_DATA (closure))
100 data1 = closure->data;
101 data2 = g_value_peek_pointer (param_values + 0);
105 data1 = g_value_peek_pointer (param_values + 0);
106 data2 = closure->data;
109 callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
112 g_value_get_string (param_values + 1),
113 g_value_get_uint (param_values + 2),
118 cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class)
120 GObjectClass *object_class;
121 GtkCellRendererClass *cell_renderer_class;
123 object_class = G_OBJECT_CLASS (cell_key_class);
124 cell_renderer_class = GTK_CELL_RENDERER_CLASS (cell_key_class);
125 parent_class = g_type_class_peek_parent (object_class);
127 GTK_CELL_RENDERER_CLASS(cell_key_class)->start_editing = cell_renderer_key_start_editing;
129 object_class->set_property = cell_renderer_key_set_property;
130 object_class->get_property = cell_renderer_key_get_property;
131 cell_renderer_class->get_size = cell_renderer_key_get_size;
133 object_class->finalize = cell_renderer_key_finalize;
135 g_object_class_install_property (object_class,
137 g_param_spec_int ("scancode",
143 G_PARAM_READABLE | G_PARAM_WRITABLE));
145 g_signal_new ("accel_edited",
146 TYPE_CELL_RENDERER_KEY,
148 G_STRUCT_OFFSET(CellRendererKeyClass, accel_edited),
150 marshal_VOID__STRING_UINT,
152 2,G_TYPE_STRING,G_TYPE_UINT);
154 g_signal_new ("accel_cleared",
155 TYPE_CELL_RENDERER_KEY,
157 G_STRUCT_OFFSET(CellRendererKeyClass, accel_cleared),
159 gtk_marshal_VOID__STRING,
166 cell_renderer_key_new (void)
168 return GTK_CELL_RENDERER (g_object_new (TYPE_CELL_RENDERER_KEY, NULL));
172 cell_renderer_key_finalize (GObject *object)
175 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
179 cell_renderer_key_get_property (GObject *object,
184 CellRendererKey *key;
186 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
188 key = CELL_RENDERER_KEY(object);
193 g_value_set_int(value, key->scancode);
197 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
202 cell_renderer_key_set_property (GObject *object,
207 CellRendererKey *key;
209 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
211 key = CELL_RENDERER_KEY(object);
216 cell_renderer_key_set_scancode(key, g_value_get_int(value));
220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
225 cell_renderer_key_get_size (GtkCellRenderer *cell,
227 GdkRectangle *cell_area,
234 CellRendererKey *key = (CellRendererKey *) cell;
235 GtkRequisition requisition;
237 if (!key->sizing_label)
238 key->sizing_label = gtk_label_new(TOOLTIP_TEXT);
240 gtk_widget_size_request (key->sizing_label, &requisition);
241 (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, cell_area, x_offset, y_offset, width, height);
242 /* FIXME: need to take the cell_area et al. into account */
244 *width = MAX (*width, requisition.width);
246 *height = MAX (*height, requisition.height);
251 grab_key_callback (GtkWidget *widget,
256 CellRendererKey* key = CELL_RENDERER_KEY(data);
257 guint scancode = event->hardware_keycode;
259 gdk_keyboard_ungrab (event->time);
260 gdk_pointer_ungrab (event->time);
262 path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
264 gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
265 gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
266 key->edit_widget = NULL;
267 key->grab_widget = NULL;
269 cell_renderer_key_set_scancode(key, scancode);
270 g_signal_emit_by_name (G_OBJECT(key), "accel_edited", path, scancode);
277 clear_key_callback(GtkButton *widget, gpointer data)
280 CellRendererKey* key = CELL_RENDERER_KEY(data);
282 gdk_keyboard_ungrab(GDK_CURRENT_TIME);
283 gdk_pointer_ungrab(GDK_CURRENT_TIME);
285 path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
287 gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
288 gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
289 key->edit_widget = NULL;
290 key->grab_widget = NULL;
292 cell_renderer_key_set_scancode(key, 0);
293 g_signal_emit_by_name (G_OBJECT(key), "accel_cleared", path);
299 ungrab_stuff (GtkWidget *widget, gpointer data)
301 CellRendererKey *key = CELL_RENDERER_KEY(data);
303 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
304 gdk_pointer_ungrab (GDK_CURRENT_TIME);
306 g_signal_handlers_disconnect_by_func (G_OBJECT (key->grab_widget),
307 G_CALLBACK (grab_key_callback), data);
311 pointless_eventbox_start_editing (GtkCellEditable *cell_editable,
314 /* do nothing, because we are pointless */
318 pointless_eventbox_cell_editable_init (GtkCellEditableIface *iface)
320 iface->start_editing = pointless_eventbox_start_editing;
324 pointless_eventbox_subclass_get_type (void)
326 static GType eventbox_type = 0;
330 static const GTypeInfo eventbox_info =
332 sizeof (GtkEventBoxClass),
333 NULL, /* base_init */
334 NULL, /* base_finalize */
336 NULL, /* class_finalize */
337 NULL, /* class_data */
338 sizeof (GtkEventBox),
340 (GInstanceInitFunc) NULL,
343 static const GInterfaceInfo cell_editable_info = {
344 (GInterfaceInitFunc) pointless_eventbox_cell_editable_init,
347 eventbox_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "CellEditableEventBox", &eventbox_info, 0);
349 g_type_add_interface_static (eventbox_type,
350 GTK_TYPE_CELL_EDITABLE,
351 &cell_editable_info);
354 return eventbox_type;
357 static GtkCellEditable *
358 cell_renderer_key_start_editing (GtkCellRenderer *cell,
362 GdkRectangle *background_area,
363 GdkRectangle *cell_area,
364 GtkCellRendererState flags)
366 GtkCellRendererText *celltext;
367 CellRendererKey *key;
370 GtkWidget *clear_button;
373 celltext = GTK_CELL_RENDERER_TEXT (cell);
374 key = CELL_RENDERER_KEY (cell);
376 /* If the cell isn't editable we return NULL. */
377 if (celltext->editable == FALSE)
380 g_return_val_if_fail (widget->window != NULL, NULL);
382 if (gdk_keyboard_grab (widget->window, FALSE,
383 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
386 if (gdk_pointer_grab (widget->window, TRUE,
387 GDK_BUTTON_PRESS_MASK,
389 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
391 gdk_keyboard_ungrab (gdk_event_get_time (event));
395 key->grab_widget = widget;
397 g_signal_connect(G_OBJECT (widget), "key_press_event",
398 G_CALLBACK (grab_key_callback), key);
400 eventbox = g_object_new(pointless_eventbox_subclass_get_type(), NULL);
401 key->edit_widget = eventbox;
402 g_object_add_weak_pointer (G_OBJECT (key->edit_widget),
403 (void**) &key->edit_widget);
406 hbox = gtk_hbox_new(FALSE, 2);
408 label = gtk_label_new(TOOLTIP_TEXT);
409 gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE);
410 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
412 clear_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
413 g_signal_connect(G_OBJECT(clear_button), "clicked",
414 G_CALLBACK(clear_key_callback), key);
416 gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL,
417 &widget->style->bg[GTK_STATE_SELECTED]);
419 gtk_widget_modify_fg(label, GTK_STATE_NORMAL,
420 &widget->style->fg[GTK_STATE_SELECTED]);
422 gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
423 gtk_box_pack_start(GTK_BOX(hbox), clear_button, FALSE, FALSE, 0);
424 gtk_container_add(GTK_CONTAINER(eventbox), hbox);
425 gtk_container_set_border_width(GTK_CONTAINER(eventbox), 0);
426 gtk_widget_set_size_request(GTK_WIDGET(eventbox),
427 cell_area->width, cell_area->height);
429 g_object_set_data_full(G_OBJECT(eventbox), CELL_RENDERER_TEXT_PATH,
430 g_strdup (path), g_free);
432 gtk_widget_show_all(eventbox);
434 g_signal_connect (G_OBJECT(eventbox), "unrealize",
435 G_CALLBACK (ungrab_stuff), key);
437 return GTK_CELL_EDITABLE(eventbox);
440 void cell_renderer_key_set_scancode (CellRendererKey *key, gint scancode)
444 g_return_if_fail (IS_CELL_RENDERER_KEY(key));
446 g_object_freeze_notify(G_OBJECT(key));
450 if (scancode != key->scancode) {
451 key->scancode = scancode;
452 g_object_notify(G_OBJECT(key), "scancode");
456 g_object_thaw_notify(G_OBJECT(key));
460 /* sync string to the key values */
466 gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
467 scancode, 0, 0, &keyval, NULL, NULL, NULL);
468 text = gdk_keyval_name(keyval);
470 g_object_set(key, "text", text, NULL);
474 gint cell_renderer_keys_get_scancode(CellRendererKey *key)
476 g_return_val_if_fail(IS_CELL_RENDERER_KEY(key), -1);
477 return key->scancode;