Code

Some improvements to my title/desc stuff of revision 18759 (see bug 171024).
[inkscape.git] / src / dialogs / input.cpp
1 #define __SP_INPUT_C__
3 /*
4  * Extended input devices dialog
5  *
6  * Authors:
7  *   Nicklas Lindgren <nili@lysator.liu.se>
8  *   Johan Engelen <goejendaagh@zonnet.nl>
9  *
10  * Copyright (C) 2005-2006 Authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
18 #include <gtk/gtksignal.h>
19 #include <gtk/gtkinputdialog.h>
20 #include <glibmm/ustring.h>
22 #include "../inkscape.h"
23 #include "../macros.h"
24 #include "../verbs.h"
25 #include "../interface.h"
26 #include "../xml/repr.h"
28 #include "dialog-events.h"
29 #include "../prefs-utils.h"
31 #define MIN_ONSCREEN_DISTANCE 50
33 static GtkWidget *dlg = NULL;
34 static win_data wd;
36 // impossible original values to make sure they are read from prefs
37 static gint x = -1000, y = -1000, w = 0, h = 0;
38 static const gchar *prefs_path = "dialogs.input";
40 static void
41 sp_input_dialog_destroy (GtkObject */*object*/, gpointer /*data*/)
42 {
43     sp_signal_disconnect_by_data (INKSCAPE, dlg);
44     wd.win = dlg = NULL;
45     wd.stop = 0;
46 }
48 static gboolean
49 sp_input_dialog_delete (GtkObject */*object*/, GdkEvent */*event*/, gpointer /*data*/)
50 {
51     gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
52     gtk_window_get_size ((GtkWindow *) dlg, &w, &h);
54     if (x<0) x=0;
55     if (y<0) y=0;
57     prefs_set_int_attribute (prefs_path, "x", x);
58     prefs_set_int_attribute (prefs_path, "y", y);
59     prefs_set_int_attribute (prefs_path, "w", w);
60     prefs_set_int_attribute (prefs_path, "h", h);
62     return FALSE; // which means, go ahead and destroy it
64 }
66 static const gchar *axis_use_strings[GDK_AXIS_LAST] = {
67     "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel"
68 };
70 void
71 sp_input_load_from_preferences (void)
72 {
73     Inkscape::XML::Node *devices = inkscape_get_repr(INKSCAPE, "devices");
74     if (devices == NULL)
75         return;
77     Inkscape::XML::Node *repr;
78     GList *list_ptr;
80     for (list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
81         GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
82         repr = sp_repr_lookup_child(devices, "id", device->name);
83         if (repr != NULL) {
84             GdkInputMode mode;
85             const gchar *attribute = repr->attribute("mode");
87             if (attribute == NULL)
88                 mode = GDK_MODE_DISABLED;
89             else if (!strcmp(attribute, "screen"))
90                 mode = GDK_MODE_SCREEN;
91             else if (!strcmp(attribute, "window"))
92                 mode = GDK_MODE_WINDOW;
93             else
94                 mode = GDK_MODE_DISABLED;
96             if (device->mode != mode) {
97                 gdk_device_set_mode(device, mode);
98             }
100             const gchar *temp_ptr;
101             Glib::ustring::size_type pos0;
102             Glib::ustring::size_type pos1;
103             gint i;
104             gint j;
106             GdkAxisUse axis_use;
108             temp_ptr = repr->attribute("axes");
109             if (temp_ptr != NULL) {
110                 const Glib::ustring temp_str = temp_ptr;
111                 pos0 = pos1 = 0;
112                 for (i=0; i < device->num_axes; i++) {
113                     pos1 = temp_str.find(";", pos0);
114                     if (pos1 == Glib::ustring::npos)
115                         break;  // Too few axis specifications
117                     axis_use = GDK_AXIS_IGNORE;
118                     for (j=0; j < GDK_AXIS_LAST; j++)
119                         if (!strcmp(temp_str.substr(pos0, pos1-pos0).c_str(), axis_use_strings[j])) {
120                             axis_use = static_cast<GdkAxisUse>(j);
121                             break;
122                         }
123                     gdk_device_set_axis_use(device, i, axis_use);
124                     pos0 = pos1 + 1;
125                 }
126             }
128             guint keyval;
129             GdkModifierType modifier;
131             temp_ptr = repr->attribute("keys");
132             if (temp_ptr != NULL) {
133                 const Glib::ustring temp_str = temp_ptr;
134                 pos0 = pos1 = 0;
135                 for (i=0; i < device->num_keys; i++) {
136                     pos1 = temp_str.find(";", pos0);
137                     if (pos1 == Glib::ustring::npos)
138                         break;  // Too few key specifications
140                     gtk_accelerator_parse(temp_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier);
141                     gdk_device_set_key(device, i, keyval, modifier);
142                     pos0 = pos1 + 1;
143                 }
144             }
145         }
146     }
149 void
150 sp_input_save_to_preferences (void)
152     Inkscape::XML::Node *devices = inkscape_get_repr(INKSCAPE, "devices");
153     if (devices == NULL)
154         // TODO: find a clean way to add a node to the preferences root, or
155         // give an error message
156         return;
158     Inkscape::XML::Node *repr;
159     GList *list_ptr;
161     for (list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
162         gint i;
163         Glib::ustring temp_attribute;
164         GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
166         repr = sp_repr_lookup_child(devices, "id", device->name);
167         if (repr == NULL) {
168             repr = devices->document()->createElement("group");
169             repr->setAttribute("id", device->name);
170             devices->appendChild(repr);
171             Inkscape::GC::release(repr);
172         }
173         switch (device->mode) {
174             default:
175             case GDK_MODE_DISABLED: {
176                 repr->setAttribute("mode", "disabled");
177                 break;
178             }
179             case GDK_MODE_SCREEN: {
180                 repr->setAttribute("mode", "screen");
181                 break;
182             }
183             case GDK_MODE_WINDOW: {
184                 repr->setAttribute("mode", "window");
185                 break;
186             }
187         }
189         temp_attribute = "";
190         for (i=0; i < device->num_axes; i++) {
191             temp_attribute += axis_use_strings[device->axes[i].use];
192             temp_attribute += ";";
193         }
194         repr->setAttribute("axes", temp_attribute.c_str());
196         temp_attribute = "";
197         for (i=0; i < device->num_keys; i++) {
198             temp_attribute += gtk_accelerator_name(device->keys[i].keyval, device->keys[i].modifiers);
199             temp_attribute += ";";
200         }
201         repr->setAttribute("keys", temp_attribute.c_str());
202     }
205 static void
206 sp_input_save_button (GtkObject */*object*/, gpointer /*data*/)
208     sp_input_save_to_preferences();
211 /**
212  * \brief  Dialog
213  *
214  */
215 void
216 sp_input_dialog (void)
218     if (dlg == NULL) {
220         gchar title[500];
221         sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_INPUT), title);
223         dlg = gtk_input_dialog_new();
225         if (x == -1000 || y == -1000) {
226             x = prefs_get_int_attribute (prefs_path, "x", -1000);
227             y = prefs_get_int_attribute (prefs_path, "y", -1000);
228         }
230         if (w ==0 || h == 0) {
231             w = prefs_get_int_attribute (prefs_path, "w", 0);
232             h = prefs_get_int_attribute (prefs_path, "h", 0);
233         }
235 //        if (x<0) x=0;
236 //        if (y<0) y=0;
238         if (w && h) {
239             gtk_window_resize ((GtkWindow *) dlg, w, h);
240         }
241         if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) {
242             gtk_window_move ((GtkWindow *) dlg, x, y);
243         } else {
244             gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
245         }
248         sp_transientize (dlg);
249         wd.win = dlg;
250         wd.stop = 0;
252         g_signal_connect   ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_transientize_callback), &wd);
253         gtk_signal_connect ( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
254         gtk_signal_connect ( GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_input_dialog_destroy), dlg);
255         gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_input_dialog_delete), dlg);
256         g_signal_connect   ( G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_input_dialog_delete), dlg);
257         g_signal_connect   ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg);
258         g_signal_connect   ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg);
260         // Dialog-specific stuff
261         gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->close_button),
262                                    "clicked",
263                                    (GtkSignalFunc)gtk_widget_destroy,
264                                    GTK_OBJECT(dlg));
265         gtk_signal_connect (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->save_button),
266                             "clicked",
267                             (GtkSignalFunc)sp_input_save_button, NULL);
268     }
270     gtk_window_present ((GtkWindow *) dlg);
274 /*
275   Local Variables:
276   mode:c++
277   c-file-style:"stroustrup"
278   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
279   indent-tabs-mode:nil
280   fill-column:99
281   End:
282 */
283 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :