1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3 * Entry widget for typing color value in css form
4 *//*
5 * Authors:
6 * Tomasz Boczkowski <penginsbacon@gmail.com>
7 *
8 * Copyright (C) 2014 Authors
9 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
10 */
11 #include <glibmm.h>
12 #include <glibmm/i18n.h>
13 #include <iomanip>
14
15 #include "color-entry.h"
16
17 namespace Inkscape {
18 namespace UI {
19 namespace Widget {
20
ColorEntry(SelectedColor & color)21 ColorEntry::ColorEntry(SelectedColor &color)
22 : _color(color)
23 , _updating(false)
24 , _updatingrgba(false)
25 , _prevpos(0)
26 , _lastcolor(0)
27 {
28 _color_changed_connection = color.signal_changed.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged));
29 _color_dragged_connection = color.signal_dragged.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged));
30 signal_activate().connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged));
31 get_buffer()->signal_inserted_text().connect(sigc::mem_fun(this, &ColorEntry::_inputCheck));
32 _onColorChanged();
33
34 // add extra character for pasting a hash, '#11223344'
35 set_max_length(9);
36 set_width_chars(8);
37 set_tooltip_text(_("Hexadecimal RGBA value of the color"));
38 }
39
~ColorEntry()40 ColorEntry::~ColorEntry()
41 {
42 _color_changed_connection.disconnect();
43 _color_dragged_connection.disconnect();
44 }
45
_inputCheck(guint pos,const gchar *,guint n_chars)46 void ColorEntry::_inputCheck(guint pos, const gchar * /*chars*/, guint n_chars)
47 {
48 // remember position of last character, so we can remove it.
49 // we only overflow by 1 character at most.
50 _prevpos = pos + n_chars - 1;
51 }
52
on_changed()53 void ColorEntry::on_changed()
54 {
55 if (_updating) {
56 return;
57 }
58 if (_updatingrgba) {
59 return; // Typing text into entry box
60 }
61
62 Glib::ustring text = get_text();
63 bool changed = false;
64
65 // Coerce the value format to hexadecimal
66 for (auto it = text.begin(); it != text.end(); /*++it*/) {
67 if (!g_ascii_isxdigit(*it)) {
68 text.erase(it);
69 changed = true;
70 } else {
71 ++it;
72 }
73 }
74
75 if (text.size() > 8) {
76 text.erase(_prevpos, 1);
77 changed = true;
78 }
79
80 // autofill rules
81 gchar *str = g_strdup(text.c_str());
82 gchar *end = nullptr;
83 guint64 rgba = g_ascii_strtoull(str, &end, 16);
84 ptrdiff_t len = end - str;
85 if (len < 8) {
86 if (len == 0) {
87 rgba = _lastcolor;
88 } else if (len <= 2) {
89 if (len == 1) {
90 rgba *= 17;
91 }
92 rgba = (rgba << 24) + (rgba << 16) + (rgba << 8);
93 } else if (len <= 4) {
94 // display as rrggbbaa
95 rgba = rgba << (4 * (4 - len));
96 guint64 r = rgba & 0xf000;
97 guint64 g = rgba & 0x0f00;
98 guint64 b = rgba & 0x00f0;
99 guint64 a = rgba & 0x000f;
100 rgba = 17 * ((r << 12) + (g << 8) + (b << 4) + a);
101 } else {
102 rgba = rgba << (4 * (8 - len));
103 }
104
105 if (len == 7) {
106 rgba = (rgba & 0xfffffff0) + (_lastcolor & 0x00f);
107 } else if (len == 5) {
108 rgba = (rgba & 0xfffff000) + (_lastcolor & 0xfff);
109 } else if (len != 4 && len != 8) {
110 rgba = (rgba & 0xffffff00) + (_lastcolor & 0x0ff);
111 }
112 }
113
114 _updatingrgba = true;
115 if (changed) {
116 set_text(str);
117 }
118 SPColor color(rgba);
119 _color.setColorAlpha(color, SP_RGBA32_A_F(rgba));
120 _updatingrgba = false;
121
122 g_free(str);
123 }
124
125
_onColorChanged()126 void ColorEntry::_onColorChanged()
127 {
128 if (_updatingrgba) {
129 return;
130 }
131
132 SPColor color = _color.color();
133 gdouble alpha = _color.alpha();
134
135 _lastcolor = color.toRGBA32(alpha);
136 Glib::ustring text = Glib::ustring::format(std::hex, std::setw(8), std::setfill(L'0'), _lastcolor);
137
138 Glib::ustring old_text = get_text();
139 if (old_text != text) {
140 _updating = true;
141 set_text(text);
142 _updating = false;
143 }
144 }
145 }
146 }
147 }
148 /*
149 Local Variables:
150 mode:c++
151 c-file-style:"stroustrup"
152 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
153 indent-tabs-mode:nil
154 fill-column:99
155 End:
156 */
157 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
158