4 #include <gdk/gdkkeysyms.h>
5 #include "cellrendererkey.h"
10 #define CELL_RENDERER_TEXT_PATH "cell-renderer-key-text"
12 #define TOOLTIP_TEXT _("Press key or…")
14 static void cell_renderer_key_finalize (GObject *object);
15 static void cell_renderer_key_init (CellRendererKey *cell_key);
16 static void cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class);
17 static GtkCellEditable *cell_renderer_key_start_editing (GtkCellRenderer *cell,
21 GdkRectangle *background_area,
22 GdkRectangle *cell_area,
23 GtkCellRendererState flags);
25 static void cell_renderer_key_get_property (GObject *object,
29 static void cell_renderer_key_set_property (GObject *object,
33 static void cell_renderer_key_get_size (GtkCellRenderer *cell,
35 GdkRectangle *cell_area,
48 static GtkCellRendererTextClass *parent_class = NULL;
50 GType cell_renderer_key_get_type (void)
52 static GType cell_key_type = 0;
56 static const GTypeInfo cell_key_info =
58 sizeof (CellRendererKeyClass),
60 NULL, /* base_finalize */
61 (GClassInitFunc)cell_renderer_key_class_init,
62 NULL, /* class_finalize */
63 NULL, /* class_data */
64 sizeof (CellRendererKey),
66 (GInstanceInitFunc) cell_renderer_key_init
69 cell_key_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "CellRendererKey", &cell_key_info, 0);
76 cell_renderer_key_init (CellRendererKey *key)
83 marshal_VOID__STRING_UINT (GClosure *closure,
86 const GValue *param_values,
87 gpointer invocation_hint,
88 gpointer marshal_data)
90 typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer data1,
94 register GMarshalFunc_VOID__STRING_UINT callback;
95 register GCClosure *cc = (GCClosure*) closure;
96 register gpointer data1, data2;
98 g_return_if_fail (n_param_values == 3);
100 if (G_CCLOSURE_SWAP_DATA (closure))
102 data1 = closure->data;
103 data2 = g_value_peek_pointer (param_values + 0);
107 data1 = g_value_peek_pointer (param_values + 0);
108 data2 = closure->data;
111 callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
114 g_value_get_string (param_values + 1),
115 g_value_get_uint (param_values + 2),
120 cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class)
122 GObjectClass *object_class;
123 GtkCellRendererClass *cell_renderer_class;
125 object_class = G_OBJECT_CLASS (cell_key_class);
126 cell_renderer_class = GTK_CELL_RENDERER_CLASS (cell_key_class);
127 parent_class = g_type_class_peek_parent (object_class);
129 GTK_CELL_RENDERER_CLASS(cell_key_class)->start_editing = cell_renderer_key_start_editing;
131 object_class->set_property = cell_renderer_key_set_property;
132 object_class->get_property = cell_renderer_key_get_property;
133 cell_renderer_class->get_size = cell_renderer_key_get_size;
135 object_class->finalize = cell_renderer_key_finalize;
137 g_object_class_install_property (object_class,
139 g_param_spec_int ("scancode",
145 G_PARAM_READABLE | G_PARAM_WRITABLE));
147 g_signal_new ("accel_edited",
148 TYPE_CELL_RENDERER_KEY,
150 G_STRUCT_OFFSET(CellRendererKeyClass, accel_edited),
152 marshal_VOID__STRING_UINT,
154 2,G_TYPE_STRING,G_TYPE_UINT);
156 g_signal_new ("accel_cleared",
157 TYPE_CELL_RENDERER_KEY,
159 G_STRUCT_OFFSET(CellRendererKeyClass, accel_cleared),
161 gtk_marshal_VOID__STRING,
168 cell_renderer_key_new (void)
170 return GTK_CELL_RENDERER (g_object_new (TYPE_CELL_RENDERER_KEY, NULL));
174 cell_renderer_key_finalize (GObject *object)
177 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
181 cell_renderer_key_get_property (GObject *object,
186 CellRendererKey *key;
188 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
190 key = CELL_RENDERER_KEY(object);
195 g_value_set_int(value, key->scancode);
199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
204 cell_renderer_key_set_property (GObject *object,
209 CellRendererKey *key;
211 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
213 key = CELL_RENDERER_KEY(object);
218 cell_renderer_key_set_scancode(key, g_value_get_int(value));
222 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
227 cell_renderer_key_get_size (GtkCellRenderer *cell,
229 GdkRectangle *cell_area,
236 CellRendererKey *key = (CellRendererKey *) cell;
237 GtkRequisition requisition;
239 if (!key->sizing_label)
240 key->sizing_label = gtk_label_new(TOOLTIP_TEXT);
242 gtk_widget_size_request (key->sizing_label, &requisition);
243 (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, cell_area, x_offset, y_offset, width, height);
244 /* FIXME: need to take the cell_area et al. into account */
246 *width = MAX (*width, requisition.width);
248 *height = MAX (*height, requisition.height);
253 grab_key_callback (GtkWidget *widget,
258 CellRendererKey* key = CELL_RENDERER_KEY(data);
259 guint scancode = event->hardware_keycode;
261 gdk_keyboard_ungrab (event->time);
262 gdk_pointer_ungrab (event->time);
264 path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
266 gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
267 gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
268 key->edit_widget = NULL;
269 key->grab_widget = NULL;
271 cell_renderer_key_set_scancode(key, scancode);
272 g_signal_emit_by_name (G_OBJECT(key), "accel_edited", path, scancode);
279 clear_key_callback(GtkButton *widget, gpointer data)
282 CellRendererKey* key = CELL_RENDERER_KEY(data);
284 gdk_keyboard_ungrab(GDK_CURRENT_TIME);
285 gdk_pointer_ungrab(GDK_CURRENT_TIME);
287 path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
289 gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
290 gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
291 key->edit_widget = NULL;
292 key->grab_widget = NULL;
294 cell_renderer_key_set_scancode(key, 0);
295 g_signal_emit_by_name (G_OBJECT(key), "accel_cleared", path);
301 ungrab_stuff (GtkWidget *widget, gpointer data)
303 CellRendererKey *key = CELL_RENDERER_KEY(data);
305 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
306 gdk_pointer_ungrab (GDK_CURRENT_TIME);
308 g_signal_handlers_disconnect_by_func (G_OBJECT (key->grab_widget),
309 G_CALLBACK (grab_key_callback), data);
313 pointless_eventbox_start_editing (GtkCellEditable *cell_editable,
316 /* do nothing, because we are pointless */
320 pointless_eventbox_cell_editable_init (GtkCellEditableIface *iface)
322 iface->start_editing = pointless_eventbox_start_editing;
326 pointless_eventbox_subclass_get_type (void)
328 static GType eventbox_type = 0;
332 static const GTypeInfo eventbox_info =
334 sizeof (GtkEventBoxClass),
335 NULL, /* base_init */
336 NULL, /* base_finalize */
338 NULL, /* class_finalize */
339 NULL, /* class_data */
340 sizeof (GtkEventBox),
342 (GInstanceInitFunc) NULL,
345 static const GInterfaceInfo cell_editable_info = {
346 (GInterfaceInitFunc) pointless_eventbox_cell_editable_init,
349 eventbox_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "CellEditableEventBox", &eventbox_info, 0);
351 g_type_add_interface_static (eventbox_type,
352 GTK_TYPE_CELL_EDITABLE,
353 &cell_editable_info);
356 return eventbox_type;
359 static GtkCellEditable *
360 cell_renderer_key_start_editing (GtkCellRenderer *cell,
364 GdkRectangle *background_area,
365 GdkRectangle *cell_area,
366 GtkCellRendererState flags)
368 GtkCellRendererText *celltext;
369 CellRendererKey *key;
372 GtkWidget *clear_button;
375 celltext = GTK_CELL_RENDERER_TEXT (cell);
376 key = CELL_RENDERER_KEY (cell);
378 /* If the cell isn't editable we return NULL. */
379 if (celltext->editable == FALSE)
382 g_return_val_if_fail (widget->window != NULL, NULL);
384 if (gdk_keyboard_grab (widget->window, FALSE,
385 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
388 if (gdk_pointer_grab (widget->window, TRUE,
389 GDK_BUTTON_PRESS_MASK,
391 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
393 gdk_keyboard_ungrab (gdk_event_get_time (event));
397 key->grab_widget = widget;
399 g_signal_connect(G_OBJECT (widget), "key_press_event",
400 G_CALLBACK (grab_key_callback), key);
402 eventbox = g_object_new(pointless_eventbox_subclass_get_type(), NULL);
403 key->edit_widget = eventbox;
404 g_object_add_weak_pointer (G_OBJECT (key->edit_widget),
405 (void**) &key->edit_widget);
408 hbox = gtk_hbox_new(FALSE, 2);
410 label = gtk_label_new(TOOLTIP_TEXT);
411 gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE);
412 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
414 clear_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
415 g_signal_connect(G_OBJECT(clear_button), "clicked",
416 G_CALLBACK(clear_key_callback), key);
418 gtk_widget_modify_bg(eventbox, GTK_STATE_NORMAL,
419 &widget->style->bg[GTK_STATE_SELECTED]);
421 gtk_widget_modify_fg(label, GTK_STATE_NORMAL,
422 &widget->style->fg[GTK_STATE_SELECTED]);
424 gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
425 gtk_box_pack_start(GTK_BOX(hbox), clear_button, FALSE, FALSE, 0);
426 gtk_container_add(GTK_CONTAINER(eventbox), hbox);
427 gtk_container_set_border_width(GTK_CONTAINER(eventbox), 0);
428 gtk_widget_set_size_request(GTK_WIDGET(eventbox),
429 cell_area->width, cell_area->height);
431 g_object_set_data_full(G_OBJECT(eventbox), CELL_RENDERER_TEXT_PATH,
432 g_strdup (path), g_free);
434 gtk_widget_show_all(eventbox);
436 g_signal_connect (G_OBJECT(eventbox), "unrealize",
437 G_CALLBACK (ungrab_stuff), key);
439 return GTK_CELL_EDITABLE(eventbox);
442 void cell_renderer_key_set_scancode (CellRendererKey *key, gint scancode)
446 g_return_if_fail (IS_CELL_RENDERER_KEY(key));
448 g_object_freeze_notify(G_OBJECT(key));
452 if (scancode != key->scancode) {
453 key->scancode = scancode;
454 g_object_notify(G_OBJECT(key), "scancode");
458 g_object_thaw_notify(G_OBJECT(key));
462 /* sync string to the key values */
468 gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
469 scancode, 0, 0, &keyval, NULL, NULL, NULL);
470 text = gdk_keyval_name(keyval);
472 g_object_set(key, "text", text, NULL);
476 gint cell_renderer_keys_get_scancode(CellRendererKey *key)
478 g_return_val_if_fail(IS_CELL_RENDERER_KEY(key), -1);
479 return key->scancode;