summaryrefslogtreecommitdiffstats
path: root/src/widgets/spinbutton-events.cpp
blob: 9800cf5fb4071cafef151b8fe078aef9906b4523 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Common callbacks for spinbuttons
 *
 * Authors:
 *   bulia byak <bulia@users.sourceforge.net>
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2013 authors
 * Copyright (C) 2003 authors
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "ui/tools/tool-base.h"

#include "spinbutton-events.h"

gboolean spinbutton_focus_in(GtkWidget *w, GdkEventKey * /*event*/, gpointer /*data*/)
{
    gdouble *ini = static_cast<gdouble *>(g_object_get_data(G_OBJECT(w), "ini"));
    if (ini) {
        g_free(ini); // free the old value if any
    }

    // retrieve the value
    ini = g_new(gdouble, 1);
    *ini = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));

    // remember it
    g_object_set_data(G_OBJECT(w), "ini", ini);

    return FALSE; // I didn't consume the event
}

void spinbutton_undo(GtkWidget *w)
{
    gdouble *ini = static_cast<gdouble *>(g_object_get_data(G_OBJECT(w), "ini"));
    if (ini) {
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), *ini);
    }
}

void spinbutton_defocus(GtkWidget *container)
{
    // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
    gboolean stay = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(container), "stay"));
    if (stay) {
        g_object_set_data(G_OBJECT(container), "stay", GINT_TO_POINTER(FALSE));
    } else {
        GtkWidget *canvas = GTK_WIDGET(g_object_get_data(G_OBJECT(container), "dtw"));
        if (canvas) {
            gtk_widget_grab_focus(GTK_WIDGET(canvas));
        }
    }
}

gboolean spinbutton_keypress(GtkWidget *w, GdkEventKey *event, gpointer /*data*/)
{
    gboolean result = FALSE; // I didn't consume the event

    switch (Inkscape::UI::Tools::get_latin_keyval(event)) {
	case GDK_KEY_Escape: // defocus
            spinbutton_undo(w);
            spinbutton_defocus(w);
            result = TRUE; // I consumed the event
            break;
	case GDK_KEY_Return: // defocus
	case GDK_KEY_KP_Enter:
            spinbutton_defocus(w);
            result = TRUE; // I consumed the event
            break;
	case GDK_KEY_Tab:
	case GDK_KEY_ISO_Left_Tab:
            // set the flag meaning "do not leave toolbar when changing value"
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            result = FALSE; // I didn't consume the event
            break;

            // The following keys are processed manually because GTK implements them in strange ways
            // (increments start with double step value and seem to grow as you press the key continuously)

	case GDK_KEY_Up:
	case GDK_KEY_KP_Up:
        {
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            gdouble v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
            gdouble step = 0;
            gdouble page = 0;
            gtk_spin_button_get_increments(GTK_SPIN_BUTTON(w), &step, &page);
            v += step;
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
            result = TRUE; // I consumed the event
            break;
        }
	case GDK_KEY_Down:
	case GDK_KEY_KP_Down:
        {
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            gdouble v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
            gdouble step = 0;
            gdouble page = 0;
            gtk_spin_button_get_increments(GTK_SPIN_BUTTON(w), &step, &page);
            v -= step;
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
            result = TRUE; // I consumed the event
            break;
        }
	case GDK_KEY_Page_Up:
	case GDK_KEY_KP_Page_Up:
        {
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            gdouble v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
            gdouble step = 0;
            gdouble page = 0;
            gtk_spin_button_get_increments(GTK_SPIN_BUTTON(w), &step, &page);
            v += page;
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
            result = TRUE; // I consumed the event
            break;
        }
	case GDK_KEY_Page_Down:
	case GDK_KEY_KP_Page_Down:
        {
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            gdouble v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
            gdouble step = 0;
            gdouble page = 0;
            gtk_spin_button_get_increments(GTK_SPIN_BUTTON(w), &step, &page);
            v -= page;
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
            result = TRUE; // I consumed the event
            break;
        }
	case GDK_KEY_z:
	case GDK_KEY_Z:
            g_object_set_data(G_OBJECT(w), "stay", GINT_TO_POINTER(TRUE));
            if (event->state & GDK_CONTROL_MASK) {
                spinbutton_undo(w);
                result = TRUE; // I consumed the event
            }
            break;
	default:
            result = FALSE;
            break;
    }

    return result;
}

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :