Root/src/inputdialog.cpp

Source at commit 7b10f9448bb9965e94f9a37a59f0999e9c51e68f created 7 years 5 months ago.
By Maarten ter Huurne, Suppress Clang analyzer warnings about dead assignments
1/***************************************************************************
2 * Copyright (C) 2006 by Massimiliano Torromeo *
3 * massimiliano.torromeo@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#include "inputdialog.h"
22
23#include "buttonbox.h"
24#include "gmenu2x.h"
25#include "iconbutton.h"
26#include "surface.h"
27#include "utilities.h"
28
29using namespace std;
30
31#define KEY_WIDTH 20
32#define KEY_HEIGHT 20
33#define KB_TOP 90
34
35static bool utf8Code(unsigned char c)
36{
37    return (c>=194 && c<=198) || c==208 || c==209;
38}
39
40InputDialog::InputDialog(GMenu2X& gmenu2x, InputManager &inputMgr_,
41        const string &text,
42        const string &startvalue, const string &title, const string &icon)
43    : Dialog(gmenu2x)
44    , inputMgr(inputMgr_)
45{
46    if (title.empty()) {
47        this->title = text;
48        this->text = "";
49    } else {
50        this->title = title;
51        this->text = text;
52    }
53    this->icon = "";
54    if (!icon.empty() && gmenu2x.sc[icon] != NULL) {
55        this->icon = icon;
56    }
57
58    input = startvalue;
59    selCol = 0;
60    selRow = 0;
61    keyboard.resize(7);
62
63    keyboard[0].push_back("abcdefghijklm");
64    keyboard[0].push_back("nopqrstuvwxyz");
65    keyboard[0].push_back("0123456789. ");
66
67    keyboard[1].push_back("ABCDEFGHIJKLM");
68    keyboard[1].push_back("NOPQRSTUVWXYZ");
69    keyboard[1].push_back("_\"'`.,:;!? ");
70
71
72    keyboard[2].push_back("¡¿*+-/\\&<=>|");
73    keyboard[2].push_back("()[]{}@#$%^~");
74    keyboard[2].push_back("_\"'`.,:;!? ");
75
76
77    keyboard[3].push_back("àáèéìíòóùúýäõ");
78    keyboard[3].push_back("ëïöüÿâêîôûåãñ");
79    keyboard[3].push_back("čďěľĺňôřŕšťůž");
80    keyboard[3].push_back("ąćęłńśżź ");
81
82    keyboard[4].push_back("ÀÁÈÉÌÍÒÓÙÚÝÄÕ");
83    keyboard[4].push_back("ËÏÖÜŸÂÊÎÔÛÅÃÑ");
84    keyboard[4].push_back("ČĎĚĽĹŇÔŘŔŠŤŮŽ");
85    keyboard[4].push_back("ĄĆĘŁŃŚŻŹ ");
86
87
88    keyboard[5].push_back("æçабвгдеёжзий ");
89    keyboard[5].push_back("клмнопрстуфхцч");
90    keyboard[5].push_back("шщъыьэюяøðßÐÞþ");
91
92    keyboard[6].push_back("ÆÇАБВГДЕЁЖЗИЙ ");
93    keyboard[6].push_back("КЛМНОПРСТУФХЦЧ");
94    keyboard[6].push_back("ШЩЪЫЬЭЮЯØðßÐÞþ");
95
96    setKeyboard(0);
97
98    buttonbox.add(unique_ptr<IconButton>(new IconButton(
99            gmenu2x, "skin:imgs/buttons/l.png",
100            gmenu2x.tr["Backspace"],
101            bind(&InputDialog::backspace, this))));
102
103    buttonbox.add(unique_ptr<IconButton>(new IconButton(
104            gmenu2x, "skin:imgs/buttons/r.png",
105            gmenu2x.tr["Space"],
106            bind(&InputDialog::space, this))));
107
108    buttonbox.add(unique_ptr<IconButton>(new IconButton(
109            gmenu2x, "skin:imgs/buttons/accept.png",
110            gmenu2x.tr["Confirm"],
111            bind(&InputDialog::confirm, this))));
112
113    buttonbox.add(unique_ptr<IconButton>(new IconButton(
114            gmenu2x, "skin:imgs/buttons/cancel.png",
115            gmenu2x.tr["Change keys"],
116            bind(&InputDialog::changeKeys, this))));
117}
118
119void InputDialog::setKeyboard(int kb) {
120    kb = constrain(kb, 0, keyboard.size() - 1);
121    curKeyboard = kb;
122    this->kb = &(keyboard[kb]);
123    kbLength = this->kb->at(0).length();
124    for (int x = 0, l = kbLength; x < l; x++) {
125        if (utf8Code(this->kb->at(0)[x])) {
126            kbLength--;
127            x++;
128        }
129    }
130
131    kbLeft = 160 - kbLength * KEY_WIDTH / 2;
132    kbWidth = kbLength * KEY_WIDTH + 3;
133    kbHeight = (this->kb->size() + 1) * KEY_HEIGHT + 3;
134
135    kbRect.x = kbLeft - 3;
136    kbRect.y = KB_TOP - 2;
137    kbRect.w = kbWidth;
138    kbRect.h = kbHeight;
139}
140
141bool InputDialog::exec() {
142    SDL_Rect box = {
143        0, 60, 0, static_cast<Uint16>(gmenu2x.font->getLineSpacing() + 4)
144    };
145
146    Uint32 caretTick = 0, curTick;
147    bool caretOn = true;
148
149    OffscreenSurface bg(*gmenu2x.bg);
150    drawTitleIcon(bg, icon, false);
151    writeTitle(bg, title);
152    writeSubTitle(bg, text);
153    buttonbox.paint(bg, 5, gmenu2x.resY - 1);
154    bg.convertToDisplayFormat();
155
156    close = false;
157    ok = true;
158    while (!close) {
159        OutputSurface& s = *gmenu2x.s;
160
161        bg.blit(s, 0, 0);
162
163        box.w = gmenu2x.font->getTextWidth(input) + 18;
164        box.x = 160 - box.w / 2;
165        s.box(box.x, box.y, box.w, box.h,
166        gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
167        s.rectangle(box.x, box.y, box.w, box.h,
168                gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
169
170        gmenu2x.font->write(s, input, box.x + 5, box.y + box.h - 2,
171                Font::HAlignLeft, Font::VAlignBottom);
172
173        curTick = SDL_GetTicks();
174        if (curTick - caretTick >= 600) {
175            caretOn = !caretOn;
176            caretTick = curTick;
177        }
178
179        if (caretOn) {
180            s.box(box.x + box.w - 12, box.y + 3, 8, box.h - 6,
181                    gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
182        }
183
184        drawVirtualKeyboard();
185        s.flip();
186
187        switch (inputMgr.waitForPressedButton()) {
188            case InputManager::SETTINGS:
189                ok = true;
190                close = true;
191                break;
192            case InputManager::MENU:
193                ok = false;
194                close = true;
195                break;
196            case InputManager::UP:
197                selRow--;
198                break;
199            case InputManager::DOWN:
200                selRow++;
201                if (selRow == (int)kb->size()) selCol = selCol < 8 ? 0 : 1;
202                break;
203            case InputManager::LEFT:
204                selCol--;
205                break;
206            case InputManager::RIGHT:
207                selCol++;
208                break;
209            case InputManager::ACCEPT:
210                confirm();
211                break;
212            case InputManager::CANCEL:
213                changeKeys();
214                break;
215            case InputManager::ALTLEFT:
216                backspace();
217                break;
218            case InputManager::ALTRIGHT:
219                space();
220                break;
221            default:
222                break;
223        }
224    }
225
226    return ok;
227}
228
229void InputDialog::backspace() {
230    // Check for UTF8 characters.
231    input = input.substr(0, input.length()
232        - (utf8Code(input[input.length() - 2]) ? 2 : 1));
233}
234
235void InputDialog::space() {
236    input += " ";
237}
238
239void InputDialog::confirm() {
240    if (selRow == (int)kb->size()) {
241        if (selCol == 0) {
242            ok = false;
243        }
244        close = true;
245    } else {
246        int xc = 0;
247        for (uint x = 0; x < kb->at(selRow).length(); x++) {
248            bool utf8 = utf8Code(kb->at(selRow)[x]);
249            if (xc == selCol) input += kb->at(selRow).substr(x, utf8 ? 2 : 1);
250            if (utf8) x++;
251            xc++;
252        }
253    }
254}
255
256void InputDialog::changeKeys() {
257    if (curKeyboard == 6) {
258        setKeyboard(0);
259    } else {
260        setKeyboard(curKeyboard + 1);
261    }
262}
263
264void InputDialog::drawVirtualKeyboard() {
265    Surface& s = *gmenu2x.s;
266
267    //keyboard border
268    s.rectangle(kbRect, gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
269
270    if (selCol<0) selCol = selRow==(int)kb->size() ? 1 : kbLength-1;
271    if (selCol>=(int)kbLength) selCol = 0;
272    if (selRow<0) selRow = kb->size()-1;
273    if (selRow>(int)kb->size()) selRow = 0;
274
275    //selection
276    if (selRow<(int)kb->size())
277        s.box(kbLeft + selCol * KEY_WIDTH - 1,
278                KB_TOP + selRow * KEY_HEIGHT, KEY_WIDTH - 1, KEY_HEIGHT - 2,
279                gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
280    else {
281        if (selCol > 1) selCol = 0;
282        if (selCol < 0) selCol = 1;
283        s.box(kbLeft + selCol * kbLength * KEY_WIDTH / 2 - 1,
284                KB_TOP + kb->size() * KEY_HEIGHT, kbLength * KEY_WIDTH / 2 - 1,
285                KEY_HEIGHT - 1, gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
286    }
287
288    //keys
289    for (uint l=0; l<kb->size(); l++) {
290        string line = kb->at(l);
291        for (uint x=0, xc=0; x<line.length(); x++) {
292            string charX;
293            //utf8 characters
294            if (utf8Code(line[x])) {
295                charX = line.substr(x,2);
296                x++;
297            } else
298                charX = line[x];
299
300            SDL_Rect re = {
301                static_cast<Sint16>(kbLeft + xc * KEY_WIDTH - 1),
302                static_cast<Sint16>(KB_TOP + l * KEY_HEIGHT),
303                KEY_WIDTH - 1,
304                KEY_HEIGHT - 2
305            };
306
307            s.rectangle(re,
308                    gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
309            gmenu2x.font->write(s, charX,
310                    kbLeft + xc * KEY_WIDTH + KEY_WIDTH / 2 - 1,
311                    KB_TOP + l * KEY_HEIGHT + KEY_HEIGHT / 2,
312                    Font::HAlignCenter, Font::VAlignMiddle);
313            xc++;
314        }
315    }
316
317    //Ok/Cancel
318    SDL_Rect re = {
319        static_cast<Sint16>(kbLeft - 1),
320        static_cast<Sint16>(KB_TOP + kb->size() * KEY_HEIGHT),
321        static_cast<Uint16>(kbLength * KEY_WIDTH / 2 - 1),
322        KEY_HEIGHT - 1
323    };
324    s.rectangle(re, gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
325    gmenu2x.font->write(s, gmenu2x.tr["Cancel"],
326            (int)(160 - kbLength * KEY_WIDTH / 4),
327            KB_TOP + kb->size() * KEY_HEIGHT + KEY_HEIGHT / 2,
328            Font::HAlignCenter, Font::VAlignMiddle);
329
330    re.x = kbLeft + kbLength * KEY_WIDTH / 2 - 1;
331    s.rectangle(re, gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
332    gmenu2x.font->write(s, gmenu2x.tr["OK"],
333            (int)(160 + kbLength * KEY_WIDTH / 4),
334            KB_TOP + kb->size() * KEY_HEIGHT + KEY_HEIGHT / 2,
335            Font::HAlignCenter, Font::VAlignMiddle);
336}
337

Archive Download this file



interactive