summaryrefslogtreecommitdiffstats
path: root/src/ui/widget/spinbutton.cpp
blob: f63ffd49ee860f0201ecbfe5d9fe51f1ea3c2109 (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
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Author:
 *   Johan B. C. Engelen
 *
 * Copyright (C) 2011 Author
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#include "spinbutton.h"

#include "scroll-utils.h"
#include "unit-menu.h"
#include "unit-tracker.h"
#include "util/expression-evaluator.h"
#include "ui/tools/tool-base.h"

namespace Inkscape {
namespace UI {
namespace Widget {

MathSpinButton::MathSpinButton(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade)
    : Gtk::SpinButton(cobject)
{
    drag_dest_unset();
}

int MathSpinButton::on_input(double *newvalue)
{
    try {
        auto eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), nullptr);
        auto result = eval.evaluate();
        *newvalue = result.value;
    } catch (Inkscape::Util::EvaluatorException &e) {
        g_message ("%s", e.what());
        return false;
    }
    return true;
}

int SpinButton::on_input(double* newvalue)
{
    if (_dont_evaluate) return false;

    try {
        Inkscape::Util::EvaluatorQuantity result;
        if (_unit_menu || _unit_tracker) {
            Unit const *unit = nullptr;
            if (_unit_menu) {
                unit = _unit_menu->getUnit();
            } else {
                unit = _unit_tracker->getActiveUnit();
            }
            Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), unit);
            result = eval.evaluate();
            // check if output dimension corresponds to input unit
            if (result.dimension != (unit->isAbsolute() ? 1 : 0) ) {
                throw Inkscape::Util::EvaluatorException("Input dimensions do not match with parameter dimensions.","");
            }
        } else {
            Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), nullptr);
            result = eval.evaluate();
        }
        *newvalue = result.value;
    }
    catch(Inkscape::Util::EvaluatorException &e) {
        g_message ("%s", e.what());

        return false;
    }

    return true;
}

bool SpinButton::on_focus_in_event(GdkEventFocus *event)
{
    _on_focus_in_value = get_value();
    return parent_type::on_focus_in_event(event);
}

bool SpinButton::on_key_press_event(GdkEventKey* event)
{
    switch (Inkscape::UI::Tools::get_latin_keyval (event)) {
    case GDK_KEY_Escape: // defocus
        undo();
        defocus();
        break;
    case GDK_KEY_Return: // defocus
    case GDK_KEY_KP_Enter:
        defocus();
        break;
    case GDK_KEY_Tab:
    case GDK_KEY_ISO_Left_Tab:
        // set the flag meaning "do not leave toolbar when changing value"
        _stay = true;
        break;
    case GDK_KEY_z:
    case GDK_KEY_Z:
        _stay = true;
        if (event->state & GDK_CONTROL_MASK) {
            undo();
            return true; // I consumed the event
        }
        break;
    default:
        break;
    }

    return parent_type::on_key_press_event(event);
}

void SpinButton::undo()
{
    set_value(_on_focus_in_value);
}

void SpinButton::defocus()
{
    // defocus spinbutton by moving focus to the canvas, unless "stay" is on
    if (_stay) {
        _stay = false;
    } else {
        Gtk::Widget *widget = _defocus_widget ? _defocus_widget : get_scrollable_ancestor(this);
        if (widget) {
            widget->grab_focus();
        }
    }
}

} // namespace Widget
} // namespace UI
} // namespace Inkscape

/*
  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 :