3 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4 *
5 */
6 /* ***** BEGIN LICENSE BLOCK *****
7 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
8 *
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
13 *
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
18 *
19 * The Original Code is EGE Adjustment Action.
20 *
21 * The Initial Developer of the Original Code is
22 * Jon A. Cruz.
23 * Portions created by the Initial Developer are Copyright (C) 2006
24 * the Initial Developer. All Rights Reserved.
25 *
26 * Contributor(s):
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
39 *
40 * ***** END LICENSE BLOCK ***** */
42 /* Note: this file should be kept compliable as both .cpp and .c */
44 #include <string.h>
46 #include <gdk/gdkkeysyms.h>
47 #include <gtk/gtktoolitem.h>
48 #include <gtk/gtkspinbutton.h>
49 #include <gtk/gtkhbox.h>
50 #include <gtk/gtklabel.h>
51 #include <gtk/gtkmisc.h>
52 #include <gtk/gtktoolbar.h>
53 #include <gtk/gtkradiomenuitem.h>
55 #include "ege-adjustment-action.h"
58 static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass );
59 static void ege_adjustment_action_init( EgeAdjustmentAction* action );
60 static void ege_adjustment_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
61 static void ege_adjustment_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
63 static GtkWidget* create_menu_item( GtkAction* action );
64 static GtkWidget* create_tool_item( GtkAction* action );
65 static void connect_proxy( GtkAction *action, GtkWidget *proxy );
66 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy );
68 static gboolean focus_in_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
69 static gboolean focus_out_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
70 static gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
72 static void ege_adjustment_action_defocus( EgeAdjustmentAction* action );
75 static GtkActionClass* gParentClass = 0;
76 static GQuark gDataName = 0;
78 struct _EgeAdjustmentActionPrivate
79 {
80 GtkAdjustment* adj;
81 GtkWidget* focusWidget;
82 gdouble climbRate;
83 guint digits;
84 gchar* selfId;
85 EgeWidgetFixup toolPost;
86 gdouble lastVal;
87 gdouble step;
88 gdouble page;
89 gboolean transferFocus;
90 };
92 #define EGE_ADJUSTMENT_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_ADJUSTMENT_ACTION_TYPE, EgeAdjustmentActionPrivate ) )
94 enum {
95 PROP_ADJUSTMENT = 1,
96 PROP_FOCUS_WIDGET,
97 PROP_CLIMB_RATE,
98 PROP_DIGITS,
99 PROP_SELFID,
100 PROP_TOOL_POST
101 };
103 enum {
104 BUMP_TOP = 0,
105 BUMP_PAGE_UP,
106 BUMP_UP,
107 BUMP_NONE,
108 BUMP_DOWN,
109 BUMP_PAGE_DOWN,
110 BUMP_BOTTOM
111 };
113 GType ege_adjustment_action_get_type( void )
114 {
115 static GType myType = 0;
116 if ( !myType ) {
117 static const GTypeInfo myInfo = {
118 sizeof( EgeAdjustmentActionClass ),
119 NULL, /* base_init */
120 NULL, /* base_finalize */
121 (GClassInitFunc)ege_adjustment_action_class_init,
122 NULL, /* class_finalize */
123 NULL, /* class_data */
124 sizeof( EgeAdjustmentAction ),
125 0, /* n_preallocs */
126 (GInstanceInitFunc)ege_adjustment_action_init,
127 NULL
128 };
130 myType = g_type_register_static( GTK_TYPE_ACTION, "EgeAdjustmentAction", &myInfo, (GTypeFlags)0 );
131 }
133 return myType;
134 }
137 static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass )
138 {
139 if ( klass ) {
140 gParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
141 GObjectClass * objClass = G_OBJECT_CLASS( klass );
143 gDataName = g_quark_from_string("ege-adj-action");
145 objClass->get_property = ege_adjustment_action_get_property;
146 objClass->set_property = ege_adjustment_action_set_property;
148 klass->parent_class.create_menu_item = create_menu_item;
149 klass->parent_class.create_tool_item = create_tool_item;
150 klass->parent_class.connect_proxy = connect_proxy;
151 klass->parent_class.disconnect_proxy = disconnect_proxy;
153 g_object_class_install_property( objClass,
154 PROP_ADJUSTMENT,
155 g_param_spec_object( "adjustment",
156 "Adjustment",
157 "The adjustment to change",
158 GTK_TYPE_ADJUSTMENT,
159 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
161 g_object_class_install_property( objClass,
162 PROP_FOCUS_WIDGET,
163 g_param_spec_pointer( "focus-widget",
164 "Focus Widget",
165 "The widget to return focus to",
166 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
168 g_object_class_install_property( objClass,
169 PROP_CLIMB_RATE,
170 g_param_spec_double( "climb-rate",
171 "Climb Rate",
172 "The acelleraton rate",
173 0.0, G_MAXDOUBLE, 0.0,
174 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
176 g_object_class_install_property( objClass,
177 PROP_DIGITS,
178 g_param_spec_uint( "digits",
179 "Digits",
180 "The number of digits to show",
181 0, 20, 0,
182 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
184 g_object_class_install_property( objClass,
185 PROP_SELFID,
186 g_param_spec_string( "self-id",
187 "Self ID",
188 "Marker for self pointer",
189 0,
190 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
192 g_object_class_install_property( objClass,
193 PROP_TOOL_POST,
194 g_param_spec_pointer( "tool-post",
195 "Tool Widget post process",
196 "Function for final adjustments",
197 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
199 g_type_class_add_private( klass, sizeof(EgeAdjustmentActionClass) );
200 }
201 }
203 static void ege_adjustment_action_init( EgeAdjustmentAction* action )
204 {
205 action->private_data = EGE_ADJUSTMENT_ACTION_GET_PRIVATE( action );
206 action->private_data->adj = 0;
207 action->private_data->focusWidget = 0;
208 action->private_data->climbRate = 0.0;
209 action->private_data->digits = 2;
210 action->private_data->selfId = 0;
211 action->private_data->toolPost = 0;
212 action->private_data->lastVal = 0.0;
213 action->private_data->step = 0.0;
214 action->private_data->page = 0.0;
215 action->private_data->transferFocus = FALSE;
216 }
218 EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment,
219 const gchar *name,
220 const gchar *label,
221 const gchar *tooltip,
222 const gchar *stock_id,
223 gdouble climb_rate,
224 guint digits )
225 {
226 GObject* obj = (GObject*)g_object_new( EGE_ADJUSTMENT_ACTION_TYPE,
227 "name", name,
228 "label", label,
229 "tooltip", tooltip,
230 "stock_id", stock_id,
231 "adjustment", adjustment,
232 "climb-rate", climb_rate,
233 "digits", digits,
234 NULL );
236 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
238 return action;
239 }
241 static void ege_adjustment_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
242 {
243 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
244 switch ( propId ) {
245 case PROP_ADJUSTMENT:
246 g_value_set_object( value, action->private_data->adj );
247 break;
249 case PROP_FOCUS_WIDGET:
250 g_value_set_pointer( value, action->private_data->focusWidget );
251 break;
253 case PROP_CLIMB_RATE:
254 g_value_set_double( value, action->private_data->climbRate );
255 break;
257 case PROP_DIGITS:
258 g_value_set_uint( value, action->private_data->digits );
259 break;
261 case PROP_SELFID:
262 g_value_set_string( value, action->private_data->selfId );
263 break;
265 case PROP_TOOL_POST:
266 g_value_set_pointer( value, (void*)action->private_data->toolPost );
267 break;
269 default:
270 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
271 }
272 }
274 void ege_adjustment_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
275 {
276 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
277 switch ( propId ) {
278 case PROP_ADJUSTMENT:
279 {
280 action->private_data->adj = GTK_ADJUSTMENT( g_value_get_object( value ) );
281 g_object_get( G_OBJECT(action->private_data->adj),
282 "step-increment", &action->private_data->step,
283 "page-increment", &action->private_data->page,
284 NULL );
285 }
286 break;
288 case PROP_FOCUS_WIDGET:
289 {
290 /* TODO unhook prior */
291 action->private_data->focusWidget = (GtkWidget*)g_value_get_pointer( value );
292 }
293 break;
295 case PROP_CLIMB_RATE:
296 {
297 /* TODO pass on */
298 action->private_data->climbRate = g_value_get_double( value );
299 }
300 break;
302 case PROP_DIGITS:
303 {
304 /* TODO pass on */
305 action->private_data->digits = g_value_get_uint( value );
306 }
307 break;
309 case PROP_SELFID:
310 {
311 /* TODO pass on */
312 gchar* prior = action->private_data->selfId;
313 action->private_data->selfId = g_value_dup_string( value );
314 g_free( prior );
315 }
316 break;
318 case PROP_TOOL_POST:
319 {
320 action->private_data->toolPost = (EgeWidgetFixup)g_value_get_pointer( value );
321 }
322 break;
324 default:
325 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
326 }
327 }
329 GtkAdjustment* ege_adjustment_action_get_adjustment( EgeAdjustmentAction* action )
330 {
331 g_return_val_if_fail( IS_EGE_ADJUSTMENT_ACTION(action), NULL );
333 return action->private_data->adj;
334 }
336 void ege_adjustment_action_set_focuswidget( EgeAdjustmentAction* action, GtkWidget* widget )
337 {
338 g_return_if_fail( IS_EGE_ADJUSTMENT_ACTION(action) );
340 /* TODO unhook prior */
342 action->private_data->focusWidget = widget;
343 }
345 GtkWidget* ege_adjustment_action_get_focuswidget( EgeAdjustmentAction* action )
346 {
347 g_return_val_if_fail( IS_EGE_ADJUSTMENT_ACTION(action), NULL );
349 return action->private_data->focusWidget;
350 }
352 static void process_menu_action( GtkWidget* obj, gpointer data )
353 {
354 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(obj);
355 if ( item->active ) {
356 EgeAdjustmentAction* act = (EgeAdjustmentAction*)g_object_get_qdata( G_OBJECT(obj), gDataName );
357 gint what = GPOINTER_TO_INT(data);
360 gdouble base = gtk_adjustment_get_value( act->private_data->adj );
361 gdouble lower = 0.0;
362 gdouble upper = 0.0;
363 gdouble step = 0.0;
364 gdouble page = 0.0;
365 g_object_get( G_OBJECT(act->private_data->adj),
366 "lower", &lower,
367 "upper", &upper,
368 "step-increment", &step,
369 "page-increment", &page,
370 NULL );
372 switch ( what ) {
373 case BUMP_TOP:
374 gtk_adjustment_set_value( act->private_data->adj, upper );
375 break;
377 case BUMP_PAGE_UP:
378 gtk_adjustment_set_value( act->private_data->adj, base + page );
379 break;
381 case BUMP_UP:
382 gtk_adjustment_set_value( act->private_data->adj, base + step );
383 break;
385 case BUMP_DOWN:
386 gtk_adjustment_set_value( act->private_data->adj, base - step );
387 break;
389 case BUMP_PAGE_DOWN:
390 gtk_adjustment_set_value( act->private_data->adj, base - page );
391 break;
393 case BUMP_BOTTOM:
394 gtk_adjustment_set_value( act->private_data->adj, lower );
395 break;
396 }
397 }
398 }
400 static void create_single_menu( GCallback toggleCb, int val, GtkWidget* menu, EgeAdjustmentAction* act, GtkWidget** dst, GSList** group, gdouble num, gboolean active )
401 {
402 char* fmt = g_strdup_printf("%%0.%df", act->private_data->digits);
403 char *str = g_strdup_printf ( fmt, num );
405 *dst = gtk_radio_menu_item_new_with_label( *group, str );
406 if ( !*group) {
407 *group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(*dst) );
408 }
409 if ( active ) {
410 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(*dst), TRUE );
411 }
412 gtk_menu_shell_append( GTK_MENU_SHELL(menu), *dst );
413 g_object_set_qdata( G_OBJECT(*dst), gDataName, act );
415 g_signal_connect( G_OBJECT(*dst), "toggled", toggleCb, GINT_TO_POINTER(val) );
417 g_free(str);
418 g_free(fmt);
419 }
421 static GtkWidget* create_popup_number_menu( EgeAdjustmentAction* act )
422 {
423 GtkWidget* menu = gtk_menu_new();
425 GSList* group = 0;
426 GtkWidget* single = 0;
428 gdouble base = gtk_adjustment_get_value( act->private_data->adj );
429 gdouble lower = 0.0;
430 gdouble upper = 0.0;
431 gdouble step = 0.0;
432 gdouble page = 0.0;
433 g_object_get( G_OBJECT(act->private_data->adj),
434 "lower", &lower,
435 "upper", &upper,
436 "step-increment", &step,
437 "page-increment", &page,
438 NULL );
440 if ( base < upper ) {
441 create_single_menu( G_CALLBACK(process_menu_action), BUMP_TOP, menu, act, &single, &group, upper, FALSE );
442 if ( (base + page) < upper ) {
443 create_single_menu( G_CALLBACK(process_menu_action), BUMP_PAGE_UP, menu, act, &single, &group, base + page, FALSE );
444 }
445 if ( (base + step) < upper ) {
446 create_single_menu( G_CALLBACK(process_menu_action), BUMP_UP, menu, act, &single, &group, base + step, FALSE );
447 }
448 }
450 create_single_menu( G_CALLBACK(process_menu_action), BUMP_NONE, menu, act, &single, &group, base, TRUE );
451 if ( base > lower ) {
452 if ( (base - step) > lower ) {
453 create_single_menu( G_CALLBACK(process_menu_action), BUMP_DOWN, menu, act, &single, &group, base - step, FALSE );
454 }
455 if ( (base - page) > lower ) {
456 create_single_menu( G_CALLBACK(process_menu_action), BUMP_PAGE_DOWN, menu, act, &single, &group, base - page, FALSE );
457 }
458 create_single_menu( G_CALLBACK(process_menu_action), BUMP_BOTTOM, menu, act, &single, &group, lower, FALSE );
459 }
461 return menu;
462 }
464 static GtkWidget* create_menu_item( GtkAction* action )
465 {
466 GtkWidget* item = 0;
468 if ( IS_EGE_ADJUSTMENT_ACTION(action) ) {
469 EgeAdjustmentAction* act = EGE_ADJUSTMENT_ACTION( action );
470 GValue value;
471 const gchar* sss = 0;
472 GtkWidget* subby = 0;
474 memset( &value, 0, sizeof(value) );
475 g_value_init( &value, G_TYPE_STRING );
476 g_object_get_property( G_OBJECT(action), "label", &value );
478 sss = g_value_get_string( &value );
480 item = gtk_menu_item_new_with_label( sss );
482 subby = create_popup_number_menu( act );
483 gtk_menu_item_set_submenu( GTK_MENU_ITEM(item), subby );
484 gtk_widget_show_all( subby );
485 } else {
486 item = gParentClass->create_menu_item( action );
487 }
489 return item;
490 }
492 void value_changed_cb( GtkSpinButton* spin, EgeAdjustmentAction* act )
493 {
494 if ( GTK_WIDGET_HAS_FOCUS( GTK_WIDGET(spin) ) ) {
495 ege_adjustment_action_defocus( act );
496 }
497 }
499 static gboolean event_cb( EgeAdjustmentAction* act, GdkEvent* evt )
500 {
501 gboolean handled = FALSE;
502 if ( evt->type == GDK_BUTTON_PRESS ) {
503 if ( evt->button.button == 3 ) {
504 if ( IS_EGE_ADJUSTMENT_ACTION(act) ) {
505 GdkEventButton* btnevt = (GdkEventButton*)evt;
506 GtkWidget* menu = create_popup_number_menu(act);
507 gtk_widget_show_all( menu );
508 gtk_menu_popup( GTK_MENU(menu), NULL, NULL, NULL, NULL, btnevt->button, btnevt->time );
509 }
510 handled = TRUE;
511 }
512 }
514 return handled;
515 }
517 static GtkWidget* create_tool_item( GtkAction* action )
518 {
519 GtkWidget* item = 0;
521 if ( IS_EGE_ADJUSTMENT_ACTION(action) ) {
522 EgeAdjustmentAction* act = EGE_ADJUSTMENT_ACTION( action );
523 GtkWidget* spinbutton = gtk_spin_button_new( act->private_data->adj, act->private_data->climbRate, act->private_data->digits );
524 GtkWidget* hb = gtk_hbox_new( FALSE, 5 );
525 GValue value;
527 item = GTK_WIDGET( gtk_tool_item_new() );
529 memset( &value, 0, sizeof(value) );
530 g_value_init( &value, G_TYPE_STRING );
531 g_object_get_property( G_OBJECT(action), "label", &value );
532 const gchar* sss = g_value_get_string( &value );
533 GtkWidget* lbl = gtk_label_new( sss ? sss : "wwww" );
535 gtk_misc_set_alignment( GTK_MISC(lbl), 1.0, 0.5 );
537 gtk_box_pack_start( GTK_BOX(hb), lbl, FALSE, FALSE, 0 );
538 gtk_box_pack_end( GTK_BOX(hb), spinbutton, FALSE, FALSE, 0 );
539 gtk_container_add( GTK_CONTAINER(item), hb );
541 if ( act->private_data->selfId ) {
542 g_object_set_data( G_OBJECT(spinbutton), act->private_data->selfId, spinbutton );
543 }
545 g_signal_connect( G_OBJECT(spinbutton), "focus-in-event", G_CALLBACK(focus_in_cb), action );
546 g_signal_connect( G_OBJECT(spinbutton), "focus-out-event", G_CALLBACK(focus_out_cb), action );
547 g_signal_connect( G_OBJECT(spinbutton), "key-press-event", G_CALLBACK(keypress_cb), action );
549 g_signal_connect( G_OBJECT(spinbutton), "value-changed", G_CALLBACK(value_changed_cb), action );
551 g_signal_connect_swapped( G_OBJECT(spinbutton), "event", G_CALLBACK(event_cb), action );
553 gtk_widget_show_all( item );
555 /* Shrink or whatnot after shown */
556 if ( act->private_data->toolPost ) {
557 act->private_data->toolPost( item );
558 }
559 } else {
560 item = gParentClass->create_tool_item( action );
561 }
563 return item;
564 }
566 static void connect_proxy( GtkAction *action, GtkWidget *proxy )
567 {
568 gParentClass->connect_proxy( action, proxy );
569 }
571 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy )
572 {
573 gParentClass->disconnect_proxy( action, proxy );
574 }
576 void ege_adjustment_action_defocus( EgeAdjustmentAction* action )
577 {
578 if ( action->private_data->transferFocus ) {
579 if ( action->private_data->focusWidget ) {
580 gtk_widget_grab_focus( action->private_data->focusWidget );
581 }
582 }
583 }
585 gboolean focus_in_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
586 {
587 (void)event;
588 if ( IS_EGE_ADJUSTMENT_ACTION(data) ) {
589 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( data );
590 action->private_data->lastVal = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
591 action->private_data->transferFocus = TRUE;
592 }
594 return FALSE; /* report event not consumed */
595 }
597 static gboolean focus_out_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
598 {
599 (void)widget;
600 (void)event;
601 if ( IS_EGE_ADJUSTMENT_ACTION(data) ) {
602 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( data );
603 action->private_data->transferFocus = FALSE;
604 }
606 return FALSE; /* report event not consumed */
607 }
610 static gboolean process_tab( GtkWidget* widget, int direction )
611 {
612 gboolean handled = FALSE;
613 GtkWidget* parent = gtk_widget_get_parent(widget);
614 GtkWidget* gp = parent ? gtk_widget_get_parent(parent) : 0;
615 GtkWidget* ggp = gp ? gtk_widget_get_parent(gp) : 0;
617 if ( ggp && GTK_IS_TOOLBAR(ggp) ) {
618 GList* kids = gtk_container_get_children( GTK_CONTAINER(ggp) );
619 if ( kids ) {
620 GtkWidget* curr = widget;
621 while ( curr && (gtk_widget_get_parent(curr) != ggp) ) {
622 curr = gtk_widget_get_parent( curr );
623 }
624 if ( curr ) {
625 GList* mid = g_list_find( kids, curr );
626 while ( mid ) {
627 mid = ( direction < 0 ) ? g_list_previous(mid) : g_list_next(mid);
628 if ( mid && GTK_IS_TOOL_ITEM(mid->data) ) {
629 /* potential target */
630 GtkWidget* child = gtk_bin_get_child( GTK_BIN(mid->data) );
631 if ( child && GTK_IS_HBOX(child) ) { /* could be ours */
632 GList* subChildren = gtk_container_get_children( GTK_CONTAINER(child) );
633 if ( subChildren ) {
634 GList* last = g_list_last(subChildren);
635 if ( last && GTK_IS_SPIN_BUTTON(last->data) && GTK_WIDGET_IS_SENSITIVE( GTK_WIDGET(last->data) ) ) {
636 gtk_widget_grab_focus( GTK_WIDGET(last->data) );
637 handled = TRUE;
638 mid = 0; /* to stop loop */
639 }
641 g_list_free(subChildren);
642 }
643 }
644 }
645 }
646 }
647 g_list_free( kids );
648 }
649 }
651 return handled;
652 }
654 gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
655 {
656 gboolean wasConsumed = FALSE; /* default to report event not consumed */
657 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION(data);
658 guint key = 0;
659 gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ),
660 event->hardware_keycode, (GdkModifierType)event->state,
661 0, &key, 0, 0, 0 );
663 switch ( key ) {
664 case GDK_Escape:
665 {
666 action->private_data->transferFocus = TRUE;
667 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal );
668 ege_adjustment_action_defocus( action );
669 wasConsumed = TRUE;
670 }
671 break;
673 case GDK_Return:
674 case GDK_KP_Enter:
675 {
676 action->private_data->transferFocus = TRUE;
677 ege_adjustment_action_defocus( action );
678 wasConsumed = TRUE;
679 }
680 break;
682 case GDK_Tab:
683 {
684 action->private_data->transferFocus = FALSE;
685 wasConsumed = process_tab( widget, 1 );
686 }
687 break;
689 case GDK_ISO_Left_Tab:
690 {
691 action->private_data->transferFocus = FALSE;
692 wasConsumed = process_tab( widget, -1 );
693 }
694 break;
696 case GDK_Up:
697 case GDK_KP_Up:
698 {
699 action->private_data->transferFocus = FALSE;
700 gdouble val = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
701 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), val + action->private_data->step );
702 wasConsumed = TRUE;
703 }
704 break;
706 case GDK_Down:
707 case GDK_KP_Down:
708 {
709 action->private_data->transferFocus = FALSE;
710 gdouble val = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
711 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), val - action->private_data->step );
712 wasConsumed = TRUE;
713 }
714 break;
716 case GDK_Page_Up:
717 case GDK_KP_Page_Up:
718 {
719 action->private_data->transferFocus = FALSE;
720 gdouble val = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
721 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), val + action->private_data->page );
722 wasConsumed = TRUE;
723 }
724 break;
726 case GDK_Page_Down:
727 case GDK_KP_Page_Down:
728 {
729 action->private_data->transferFocus = FALSE;
730 gdouble val = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
731 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), val - action->private_data->page );
732 wasConsumed = TRUE;
733 }
734 break;
736 case GDK_z:
737 case GDK_Z:
738 {
739 action->private_data->transferFocus = FALSE;
740 gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal );
741 wasConsumed = TRUE;
742 }
743 break;
745 }
747 return wasConsumed;
748 }