Code

Use subdirectories with icon sizes.
[inkscape.git] / src / widgets / button.cpp
1 #define __SP_BUTTON_C__
3 /*
4  * Generic button widget
5  *
6  * Authors:
7  *   MenTaLguY <mental@rydia.net>
8  *   Lauris Kaplinski <lauris@kaplinski.com>
9  *   bulia byak <buliabyak@users.sf.net>
10  *
11  * Copyright (C) 2002 Lauris Kaplinski
12  *
13  * This code is in public domain
14  */
16 #ifdef HAVE_CONFIG_H
17 # include "config.h"
18 #endif
21 #if HAVE_STRING_H
22 #endif
27 #include "shortcuts.h"
28 #include "interface.h"
30 #include <gdk/gdkkeysyms.h>
32 #include "icon.h"
33 #include "button.h"
35 static void sp_button_class_init (SPButtonClass *klass);
36 static void sp_button_init (SPButton *button);
37 static void sp_button_destroy (GtkObject *object);
39 static void sp_button_size_request (GtkWidget *widget, GtkRequisition *requisition);
40 static void sp_button_clicked (GtkButton *button);
41 static void sp_button_perform_action (SPButton *button, gpointer data);
42 static gint sp_button_process_event (SPButton *button, GdkEvent *event);
44 static void sp_button_set_action (SPButton *button, SPAction *action);
45 static void sp_button_set_doubleclick_action (SPButton *button, SPAction *action);
46 static void sp_button_action_set_active (SPAction *action, unsigned int active, void *data);
47 static void sp_button_action_set_sensitive (SPAction *action, unsigned int sensitive, void *data);
48 static void sp_button_action_set_shortcut (SPAction *action, unsigned int shortcut, void *data);
49 static void sp_button_set_composed_tooltip (GtkTooltips *tooltips, GtkWidget *widget, SPAction *action);
51 static GtkToggleButtonClass *parent_class;
52 SPActionEventVector button_event_vector = {
53         {NULL},
54          NULL,
55          sp_button_action_set_active,
56          sp_button_action_set_sensitive,
57          sp_button_action_set_shortcut,
58          NULL
59 };
61 GType sp_button_get_type(void)
62 {
63     static GType type = 0;
64     if (!type) {
65         GTypeInfo info = {
66             sizeof(SPButtonClass),
67             0, // base_init
68             0, // base_finalize
69             (GClassInitFunc)sp_button_class_init,
70             0, // class_finalize
71             0, // class_data
72             sizeof(SPButton),
73             0, // n_preallocs
74             (GInstanceInitFunc)sp_button_init,
75             0 // value_table
76         };
77         type = g_type_register_static(GTK_TYPE_TOGGLE_BUTTON, "SPButton", &info, static_cast<GTypeFlags>(0));
78     }
79     return type;
80 }
82 static void
83 sp_button_class_init (SPButtonClass *klass)
84 {
85         GtkObjectClass *object_class=(GtkObjectClass *)klass;
86         GtkWidgetClass *widget_class=(GtkWidgetClass *)klass;
87         GtkButtonClass *button_class=(GtkButtonClass *)klass;
89         parent_class = (GtkToggleButtonClass *)g_type_class_peek_parent (klass);
91         object_class->destroy = sp_button_destroy;
92         widget_class->size_request = sp_button_size_request;
93         button_class->clicked = sp_button_clicked;
94 }
96 static void
97 sp_button_init (SPButton *button)
98 {
99         button->action = NULL;
100         button->doubleclick_action = NULL;
101         button->tooltips = NULL;
103         gtk_container_set_border_width (GTK_CONTAINER (button), 0);
105         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (button), GTK_CAN_FOCUS);
106         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (button), GTK_CAN_DEFAULT);
108         g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_button_perform_action), NULL);
109         g_signal_connect_after (G_OBJECT (button), "event", G_CALLBACK (sp_button_process_event), NULL);
112 static void
113 sp_button_destroy (GtkObject *object)
115         SPButton *button;
117         button = SP_BUTTON (object);
119         if (button->tooltips) {
120                 g_object_unref (G_OBJECT (button->tooltips));
121                 button->tooltips = NULL;
122         }
124         if (button->action) {
125                 sp_button_set_action (button, NULL);
126         }
128         if (button->doubleclick_action) {
129                 sp_button_set_doubleclick_action (button, NULL);
130         }
132         ((GtkObjectClass *) (parent_class))->destroy (object);
135 static void
136 sp_button_size_request (GtkWidget *widget, GtkRequisition *requisition)
138         GtkWidget *child;
140         child = gtk_bin_get_child (GTK_BIN (widget));
141         if (child) {
142                 gtk_widget_size_request (GTK_WIDGET (child), requisition);
143         } else {
144                 requisition->width = 0;
145                 requisition->height = 0;
146         }
148         requisition->width += 2 + 2 * MAX (2, widget->style->xthickness);
149         requisition->height += 2 + 2 * MAX (2, widget->style->ythickness);
152 static void
153 sp_button_clicked (GtkButton *button)
155         SPButton *sp_button=SP_BUTTON (button);
157         if (sp_button->type == SP_BUTTON_TYPE_TOGGLE) {
158                 ((GtkButtonClass *) (parent_class))->clicked (button);
159         }
162 static gint 
163 sp_button_process_event (SPButton *button, GdkEvent *event)
165         switch (event->type) {
166         case GDK_2BUTTON_PRESS:
167                 if (button->doubleclick_action) {
168                         sp_action_perform (button->doubleclick_action, NULL);
169                 }
170                 return TRUE;
171                 break;
172         default:
173                 break;
174         }
176         return FALSE;
179 static void
180 sp_button_perform_action (SPButton *button, gpointer /*data*/)
182         if (button->action) {
183                 sp_action_perform (button->action, NULL);
184         }
188 GtkWidget *
189 sp_button_new( Inkscape::IconSize size, SPButtonType type, SPAction *action, SPAction *doubleclick_action, GtkTooltips *tooltips )
191         SPButton *button;
193         button = (SPButton *)g_object_new (SP_TYPE_BUTTON, NULL);
195         button->type = type;
196         button->lsize = CLAMP( size, Inkscape::ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION );
197         button->tooltips = tooltips;
199         if (tooltips) g_object_ref ((GObject *) tooltips);
201         sp_button_set_action (button, action);
202         if (doubleclick_action)
203                 sp_button_set_doubleclick_action (button, doubleclick_action);
205         // The Inkscape style is no-relief buttons
206         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
208         return (GtkWidget *) button;
211 void
212 sp_button_toggle_set_down (SPButton *button, gboolean down)
214         g_return_if_fail (button->type == SP_BUTTON_TYPE_TOGGLE);
215         g_signal_handlers_block_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
216         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), (unsigned int)down);
217         g_signal_handlers_unblock_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
220 static void
221 sp_button_set_doubleclick_action (SPButton *button, SPAction *action)
223         if (button->doubleclick_action) {
224                 nr_object_unref ((NRObject *) button->doubleclick_action);
225         }
226         button->doubleclick_action = action;
227         if (action) {
228                 button->doubleclick_action = (SPAction *) nr_object_ref ((NRObject *) action);
229         }
232 static void
233 sp_button_set_action (SPButton *button, SPAction *action)
235         GtkWidget *child;
237         if (button->action) {
238                 nr_active_object_remove_listener_by_data ((NRActiveObject *) button->action, button);
239                 nr_object_unref ((NRObject *) button->action);
240                 child = gtk_bin_get_child (GTK_BIN (button));
241                 if (child) {
242                         gtk_container_remove (GTK_CONTAINER (button), child);
243                 }
244         }
245         button->action = action;
246         if (action) {
247                 button->action = (SPAction *) nr_object_ref ((NRObject *) action);
248                 nr_active_object_add_listener ((NRActiveObject *) action, (NRObjectEventVector *) &button_event_vector, sizeof (SPActionEventVector), button);
249                 if (action->image) {
250                         child = sp_icon_new (button->lsize, action->image);
251                         gtk_widget_show (child);
252                         gtk_container_add (GTK_CONTAINER (button), child);
253                 }
254         }
256         if (button->tooltips) {
257                 sp_button_set_composed_tooltip (button->tooltips, (GtkWidget *) button, action);
258         }
261 static void
262 sp_button_action_set_active (SPAction */*action*/, unsigned int active, void *data)
264         SPButton *button;
265         button = (SPButton *) data;
266         if (button->type != SP_BUTTON_TYPE_TOGGLE) {
267                 return;
268         }
270         /* temporarily lobotomized until SPActions are per-view */
271         if (0 && !active != !SP_BUTTON_IS_DOWN (button)) {
272                 sp_button_toggle_set_down (button, active);
273         }
276 static void
277 sp_button_action_set_sensitive (SPAction */*action*/, unsigned int sensitive, void *data)
279         gtk_widget_set_sensitive (GTK_WIDGET (data), sensitive);
282 static void
283 sp_button_action_set_shortcut (SPAction *action, unsigned int /*shortcut*/, void *data)
285         SPButton *button=SP_BUTTON (data);
286         if (button->tooltips) {
287                 sp_button_set_composed_tooltip (button->tooltips, GTK_WIDGET (button), action);
288         }
291 static void sp_button_set_composed_tooltip(GtkTooltips *tooltips, GtkWidget *widget, SPAction *action)
293     if (action) {
294         unsigned int shortcut = sp_shortcut_get_primary (action->verb);
295         if (shortcut != GDK_VoidSymbol) {
296             // there's both action and shortcut
298             gchar *key = sp_shortcut_get_label(shortcut);
300             gchar *tip = g_strdup_printf ("%s (%s)", action->tip, key);
301             gtk_tooltips_set_tip(tooltips, widget, tip, NULL);
302             g_free(tip);
303             g_free(key);
304         } else {
305             // action has no shortcut
306             gtk_tooltips_set_tip(tooltips, widget, action->tip, NULL);
307         }
308     } else {
309         // no action
310         gtk_tooltips_set_tip(tooltips, widget, NULL, NULL);
311     }
314 GtkWidget *
315 sp_button_new_from_data( Inkscape::IconSize size,
316                          SPButtonType type,
317                          Inkscape::UI::View::View *view,
318                          const gchar *name,
319                          const gchar *tip,
320                          GtkTooltips *tooltips )
322         GtkWidget *button;
323         SPAction *action=sp_action_new(view, name, name, tip, name, 0);
324         button = sp_button_new (size, type, action, NULL, tooltips);
325         nr_object_unref ((NRObject *) action);
326         return button;