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 <gtk/gtktoolitem.h>
47 #include <gtk/gtkspinbutton.h>
48 #include <gtk/gtkhbox.h>
49 #include <gtk/gtklabel.h>
50 #include <gtk/gtkmisc.h>
52 #include "ege-adjustment-action.h"
55 static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass );
56 static void ege_adjustment_action_init( EgeAdjustmentAction* action );
57 static void ege_adjustment_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
58 static void ege_adjustment_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
60 static GtkWidget* create_menu_item( GtkAction* action );
61 static GtkWidget* create_tool_item( GtkAction* action );
62 static void connect_proxy( GtkAction *action, GtkWidget *proxy );
63 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy );
65 static gboolean focus_in_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
66 static gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
68 static GtkActionClass* gParentClass = 0;
71 struct _EgeAdjustmentActionPrivate
72 {
73 GtkAdjustment* adj;
74 GtkWidget* focusWidget;
75 gdouble lastVal;
76 gboolean keepFocus;
77 };
79 #define EGE_ADJUSTMENT_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_ADJUSTMENT_ACTION_TYPE, EgeAdjustmentActionPrivate ) )
81 enum {
82 PROP_ADJUSTMENT = 1,
83 PROP_FOCUS_WIDGET
84 };
86 GType ege_adjustment_action_get_type( void )
87 {
88 static GType myType = 0;
89 if ( !myType ) {
90 static const GTypeInfo myInfo = {
91 sizeof( EgeAdjustmentActionClass ),
92 NULL, /* base_init */
93 NULL, /* base_finalize */
94 (GClassInitFunc)ege_adjustment_action_class_init,
95 NULL, /* class_finalize */
96 NULL, /* class_data */
97 sizeof( EgeAdjustmentAction ),
98 0, /* n_preallocs */
99 (GInstanceInitFunc)ege_adjustment_action_init,
100 NULL
101 };
103 myType = g_type_register_static( GTK_TYPE_ACTION, "EgeAdjustmentAction", &myInfo, (GTypeFlags)0 );
104 }
106 return myType;
107 }
110 static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass )
111 {
112 if ( klass ) {
113 gParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
114 GObjectClass * objClass = G_OBJECT_CLASS( klass );
116 objClass->get_property = ege_adjustment_action_get_property;
117 objClass->set_property = ege_adjustment_action_set_property;
119 klass->parent_class.create_menu_item = create_menu_item;
120 klass->parent_class.create_tool_item = create_tool_item;
121 klass->parent_class.connect_proxy = connect_proxy;
122 klass->parent_class.disconnect_proxy = disconnect_proxy;
124 g_object_class_install_property( objClass,
125 PROP_ADJUSTMENT,
126 g_param_spec_pointer( "adjustment",
127 "Adjustment",
128 "The adjustment to change",
129 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
131 g_object_class_install_property( objClass,
132 PROP_FOCUS_WIDGET,
133 g_param_spec_pointer( "focus-widget",
134 "Focus Widget",
135 "The widget to return focus to",
136 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
138 g_type_class_add_private( klass, sizeof(EgeAdjustmentActionClass) );
139 }
140 }
142 static void ege_adjustment_action_init( EgeAdjustmentAction* action )
143 {
144 action->private_data = EGE_ADJUSTMENT_ACTION_GET_PRIVATE( action );
145 action->private_data->adj = 0;
146 action->private_data->focusWidget = 0;
147 action->private_data->lastVal = 0.0;
148 action->private_data->keepFocus = FALSE;
149 }
151 EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment,
152 const gchar *name,
153 const gchar *label,
154 const gchar *tooltip,
155 const gchar *stock_id )
156 {
157 GObject* obj = (GObject*)g_object_new( EGE_ADJUSTMENT_ACTION_TYPE,
158 "name", name,
159 "label", label,
160 "tooltip", tooltip,
161 "stock_id", stock_id,
162 "adjustment", adjustment,
163 NULL );
165 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
167 return action;
168 }
170 static void ege_adjustment_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
171 {
172 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
173 switch ( propId ) {
174 case PROP_ADJUSTMENT:
175 {
176 g_value_set_pointer( value, action->private_data->adj );
177 }
178 break;
180 case PROP_FOCUS_WIDGET:
181 {
182 g_value_set_pointer( value, action->private_data->focusWidget );
183 }
184 break;
186 default:
187 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
188 }
189 }
191 void ege_adjustment_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
192 {
193 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj );
194 switch ( propId ) {
195 case PROP_ADJUSTMENT:
196 {
197 action->private_data->adj = (GtkAdjustment*)g_value_get_pointer( value );
198 }
199 break;
201 case PROP_FOCUS_WIDGET:
202 {
203 /* TODO unhook prior */
204 action->private_data->focusWidget = (GtkWidget*)g_value_get_pointer( value );
205 }
206 break;
208 default:
209 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
210 }
211 }
213 GtkAdjustment* ege_adjustment_action_get_adjustment( EgeAdjustmentAction* action )
214 {
215 g_return_val_if_fail( IS_EGE_ADJUSTMENT_ACTION(action), NULL );
217 return action->private_data->adj;
218 }
220 void ege_adjustment_action_set_focuswidget( EgeAdjustmentAction* action, GtkWidget* widget )
221 {
222 g_return_if_fail( IS_EGE_ADJUSTMENT_ACTION(action) );
224 /* TODO unhook prior */
226 action->private_data->focusWidget = widget;
227 }
229 GtkWidget* ege_adjustment_action_get_focuswidget( EgeAdjustmentAction* action )
230 {
231 g_return_val_if_fail( IS_EGE_ADJUSTMENT_ACTION(action), NULL );
233 return action->private_data->focusWidget;
234 }
236 static GtkWidget* create_menu_item( GtkAction* action )
237 {
238 GtkWidget* item = 0;
240 item = gParentClass->create_menu_item( action );
242 return item;
243 }
245 /* void flippy(GtkAdjustment *adj, GtkWidget *) */
246 /* { */
247 /* g_message("flippy on %p to %f", adj, gtk_adjustment_get_value(adj) ); */
248 /* } */
250 /* void floppy(GtkSpinButton *spin, GtkWidget *) */
251 /* { */
252 /* g_message("f__ppy on %p to %f", spin, gtk_spin_button_get_value(spin) ); */
253 /* } */
255 static GtkWidget* create_tool_item( GtkAction* action )
256 {
257 GtkWidget* item = 0;
259 if ( IS_EGE_ADJUSTMENT_ACTION(action) ) {
260 GtkWidget* spinbutton = gtk_spin_button_new( EGE_ADJUSTMENT_ACTION(action)->private_data->adj, 0.1, 2 );
261 GtkWidget* hb = gtk_hbox_new( FALSE, 5 );
262 GValue value;
264 item = GTK_WIDGET( gtk_tool_item_new() );
266 memset( &value, 0, sizeof(value) );
267 g_value_init( &value, G_TYPE_STRING );
268 g_object_get_property( G_OBJECT(action), "label", &value );
269 const gchar* sss = g_value_get_string( &value );
270 GtkWidget* lbl = gtk_label_new( sss ? sss : "wwww" );
272 gtk_misc_set_alignment( GTK_MISC(lbl), 1.0, 0.5 );
274 gtk_box_pack_start( GTK_BOX(hb), lbl, FALSE, FALSE, 0 );
275 gtk_box_pack_end( GTK_BOX(hb), spinbutton, FALSE, FALSE, 0 );
276 gtk_container_add( GTK_CONTAINER(item), hb );
278 g_signal_connect( G_OBJECT(spinbutton), "focus-in-event", G_CALLBACK(focus_in_cb), action );
279 g_signal_connect( G_OBJECT(spinbutton), "key-press-event", G_CALLBACK(keypress_cb), action );
281 /* g_signal_connect( G_OBJECT(spinbutton), "value-changed", G_CALLBACK(floppy), action ); */
282 /* g_signal_connect( G_OBJECT(EGE_ADJUSTMENT_ACTION(action)->private_data->adj), "value-changed", G_CALLBACK(flippy), action ); */
285 gtk_widget_show_all( item );
286 } else {
287 item = gParentClass->create_tool_item( action );
288 }
290 return item;
291 }
293 static void connect_proxy( GtkAction *action, GtkWidget *proxy )
294 {
295 gParentClass->connect_proxy( action, proxy );
296 }
298 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy )
299 {
300 gParentClass->disconnect_proxy( action, proxy );
301 }
303 void ege_adjustment_action_defocus( EgeAdjustmentAction* action )
304 {
305 if ( action->private_data->keepFocus ) {
306 action->private_data->keepFocus = FALSE;
307 } else {
308 if ( action->private_data->focusWidget ) {
309 gtk_widget_grab_focus( action->private_data->focusWidget );
310 }
311 }
312 }
314 gboolean focus_in_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
315 {
316 if ( IS_EGE_ADJUSTMENT_ACTION(data) ) {
317 EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( data );
318 action->private_data->lastVal = gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) );
319 }
321 return FALSE; /* report event not consumed */
322 }
324 gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
325 {
327 return FALSE; /* report event not consumed */
328 }