Code

Adds 'Save as SVG' button / dialog to clarify when saving file, that it
[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 "icon.h"
31 #include "button.h"
33 static void sp_button_class_init (SPButtonClass *klass);
34 static void sp_button_init (SPButton *button);
35 static void sp_button_destroy (GtkObject *object);
37 static void sp_button_size_request (GtkWidget *widget, GtkRequisition *requisition);
38 static void sp_button_clicked (GtkButton *button);
39 static void sp_button_perform_action (SPButton *button, gpointer data);
40 static gint sp_button_process_event (SPButton *button, GdkEvent *event);
42 static void sp_button_set_action (SPButton *button, SPAction *action);
43 static void sp_button_set_doubleclick_action (SPButton *button, SPAction *action);
44 static void sp_button_action_set_active (SPAction *action, unsigned int active, void *data);
45 static void sp_button_action_set_sensitive (SPAction *action, unsigned int sensitive, void *data);
46 static void sp_button_action_set_shortcut (SPAction *action, unsigned int shortcut, void *data);
47 static void sp_button_set_composed_tooltip (GtkTooltips *tooltips, GtkWidget *widget, SPAction *action);
49 static GtkToggleButtonClass *parent_class;
50 SPActionEventVector button_event_vector = {
51         {NULL},
52          NULL,
53          sp_button_action_set_active,
54          sp_button_action_set_sensitive,
55          sp_button_action_set_shortcut,
56          NULL
57 };
59 GtkType
60 sp_button_get_type (void)
61 {
62         static GtkType type = 0;
63         if (!type) {
64                 GtkTypeInfo info = {
65                         "SPButton",
66                         sizeof (SPButton),
67                         sizeof (SPButtonClass),
68                         (GtkClassInitFunc) sp_button_class_init,
69                         (GtkObjectInitFunc) sp_button_init,
70                         NULL, NULL, NULL
71                 };
72                 type = gtk_type_unique (GTK_TYPE_TOGGLE_BUTTON, &info);
73         }
74         return type;
75 }
77 static void
78 sp_button_class_init (SPButtonClass *klass)
79 {
80         GtkObjectClass *object_class=(GtkObjectClass *)klass;
81         GtkWidgetClass *widget_class=(GtkWidgetClass *)klass;
82         GtkButtonClass *button_class=(GtkButtonClass *)klass;
84         parent_class = (GtkToggleButtonClass *)g_type_class_peek_parent (klass);
86         object_class->destroy = sp_button_destroy;
87         widget_class->size_request = sp_button_size_request;
88         button_class->clicked = sp_button_clicked;
89 }
91 static void
92 sp_button_init (SPButton *button)
93 {
94         button->action = NULL;
95         button->doubleclick_action = NULL;
96         button->tooltips = NULL;
98         gtk_container_set_border_width (GTK_CONTAINER (button), 0);
100         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (button), GTK_CAN_FOCUS);
101         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (button), GTK_CAN_DEFAULT);
103         g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_button_perform_action), NULL);
104         g_signal_connect_after (G_OBJECT (button), "event", G_CALLBACK (sp_button_process_event), NULL);
107 static void
108 sp_button_destroy (GtkObject *object)
110         SPButton *button;
112         button = SP_BUTTON (object);
114         if (button->tooltips) {
115                 g_object_unref (G_OBJECT (button->tooltips));
116                 button->tooltips = NULL;
117         }
119         if (button->action) {
120                 sp_button_set_action (button, NULL);
121         }
123         if (button->doubleclick_action) {
124                 sp_button_set_doubleclick_action (button, NULL);
125         }
127         ((GtkObjectClass *) (parent_class))->destroy (object);
130 static void
131 sp_button_size_request (GtkWidget *widget, GtkRequisition *requisition)
133         GtkWidget *child;
135         child = gtk_bin_get_child (GTK_BIN (widget));
136         if (child) {
137                 gtk_widget_size_request (GTK_WIDGET (child), requisition);
138         } else {
139                 requisition->width = 0;
140                 requisition->height = 0;
141         }
143         requisition->width += 2 + 2 * MAX (2, widget->style->xthickness);
144         requisition->height += 2 + 2 * MAX (2, widget->style->ythickness);
147 static void
148 sp_button_clicked (GtkButton *button)
150         SPButton *sp_button=SP_BUTTON (button);
152         if (sp_button->type == SP_BUTTON_TYPE_TOGGLE) {
153                 ((GtkButtonClass *) (parent_class))->clicked (button);
154         }
157 static gint 
158 sp_button_process_event (SPButton *button, GdkEvent *event)
160         switch (event->type) {
161         case GDK_2BUTTON_PRESS:
162                 if (button->doubleclick_action) {
163                         sp_action_perform (button->doubleclick_action, NULL);
164                 }
165                 return TRUE;
166                 break;
167         default:
168                 break;
169         }
171         return FALSE;
174 static void
175 sp_button_perform_action (SPButton *button, gpointer /*data*/)
177         if (button->action) {
178                 sp_action_perform (button->action, NULL);
179         }
183 GtkWidget *
184 sp_button_new( Inkscape::IconSize size, SPButtonType type, SPAction *action, SPAction *doubleclick_action, GtkTooltips *tooltips )
186         SPButton *button;
188         button = (SPButton *)g_object_new (SP_TYPE_BUTTON, NULL);
190         button->type = type;
191         button->lsize = CLAMP( size, Inkscape::ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION );
192         button->tooltips = tooltips;
194         if (tooltips) g_object_ref ((GObject *) tooltips);
196         sp_button_set_action (button, action);
197         if (doubleclick_action)
198                 sp_button_set_doubleclick_action (button, doubleclick_action);
200         // The Inkscape style is no-relief buttons
201         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
203         return (GtkWidget *) button;
206 void
207 sp_button_toggle_set_down (SPButton *button, gboolean down)
209         g_return_if_fail (button->type == SP_BUTTON_TYPE_TOGGLE);
210         g_signal_handlers_block_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
211         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), (unsigned int)down);
212         g_signal_handlers_unblock_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
215 static void
216 sp_button_set_doubleclick_action (SPButton *button, SPAction *action)
218         if (button->doubleclick_action) {
219                 nr_object_unref ((NRObject *) button->doubleclick_action);
220         }
221         button->doubleclick_action = action;
222         if (action) {
223                 button->doubleclick_action = (SPAction *) nr_object_ref ((NRObject *) action);
224         }
227 static void
228 sp_button_set_action (SPButton *button, SPAction *action)
230         GtkWidget *child;
232         if (button->action) {
233                 nr_active_object_remove_listener_by_data ((NRActiveObject *) button->action, button);
234                 nr_object_unref ((NRObject *) button->action);
235                 child = gtk_bin_get_child (GTK_BIN (button));
236                 if (child) {
237                         gtk_container_remove (GTK_CONTAINER (button), child);
238                 }
239         }
240         button->action = action;
241         if (action) {
242                 button->action = (SPAction *) nr_object_ref ((NRObject *) action);
243                 nr_active_object_add_listener ((NRActiveObject *) action, (NRObjectEventVector *) &button_event_vector, sizeof (SPActionEventVector), button);
244                 if (action->image) {
245                         child = sp_icon_new (button->lsize, action->image);
246                         gtk_widget_show (child);
247                         gtk_container_add (GTK_CONTAINER (button), child);
248                 }
249         }
251         if (button->tooltips) {
252                 sp_button_set_composed_tooltip (button->tooltips, (GtkWidget *) button, action);
253         }
256 static void
257 sp_button_action_set_active (SPAction */*action*/, unsigned int active, void *data)
259         SPButton *button;
260         button = (SPButton *) data;
261         if (button->type != SP_BUTTON_TYPE_TOGGLE) {
262                 return;
263         }
265         /* temporarily lobotomized until SPActions are per-view */
266         if (0 && !active != !SP_BUTTON_IS_DOWN (button)) {
267                 sp_button_toggle_set_down (button, active);
268         }
271 static void
272 sp_button_action_set_sensitive (SPAction */*action*/, unsigned int sensitive, void *data)
274         gtk_widget_set_sensitive (GTK_WIDGET (data), sensitive);
277 static void
278 sp_button_action_set_shortcut (SPAction *action, unsigned int /*shortcut*/, void *data)
280         SPButton *button=SP_BUTTON (data);
281         if (button->tooltips) {
282                 sp_button_set_composed_tooltip (button->tooltips, GTK_WIDGET (button), action);
283         }
286 static void
287 sp_button_set_composed_tooltip (GtkTooltips *tooltips, GtkWidget *widget, SPAction *action)
289         if (action) {
290                 unsigned int shortcut = sp_shortcut_get_primary (action->verb);
291                 if (shortcut) {
292                         // there's both action and shortcut
294                         gchar        key[256];
295                         sp_ui_shortcut_string (shortcut, key);
297                         gchar *tip = g_strdup_printf ("%s (%s)", action->tip, key);
298                         gtk_tooltips_set_tip (tooltips, widget, tip, NULL);
299                         g_free (tip);
301                 } else {
302                         // action has no shortcut
303                         gtk_tooltips_set_tip (tooltips, widget, action->tip, NULL);
304                 }
305         } else {
306                 // no action
307                 gtk_tooltips_set_tip (tooltips, widget, NULL, NULL);
308         }
311 GtkWidget *
312 sp_button_new_from_data( Inkscape::IconSize size,
313                          SPButtonType type,
314                          Inkscape::UI::View::View *view,
315                          const gchar *name,
316                          const gchar *tip,
317                          GtkTooltips *tooltips )
319         GtkWidget *button;
320         SPAction *action=sp_action_new(view, name, name, tip, name, 0);
321         button = sp_button_new (size, type, action, NULL, tooltips);
322         nr_object_unref ((NRObject *) action);
323         return button;