Root/src/inputdialog.cpp

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 "delegate.h"
25#include "gmenu2x.h"
26#include "iconbutton.h"
27#include "surface.h"
28#include "utilities.h"
29
30#include <SDL_gfxPrimitives.h>
31
32using namespace std;
33
34#define KEY_WIDTH 20
35#define KEY_HEIGHT 20
36#define KB_TOP 90
37
38static bool utf8Code(unsigned char c)
39{
40    return (c>=194 && c<=198) || c==208 || c==209;
41}
42
43InputDialog::InputDialog(GMenu2X *gmenu2x, InputManager &inputMgr_,
44        Touchscreen &ts_, const string &text,
45        const string &startvalue, const string &title, const string &icon)
46    : Dialog(gmenu2x)
47    , inputMgr(inputMgr_)
48    , ts(ts_)
49{
50    if (title.empty()) {
51        this->title = text;
52        this->text = "";
53    } else {
54        this->title = title;
55        this->text = text;
56    }
57    this->icon = "";
58    if (!icon.empty() && gmenu2x->sc[icon] != NULL) {
59        this->icon = icon;
60    }
61
62    input = startvalue;
63    selCol = 0;
64    selRow = 0;
65    keyboard.resize(7);
66
67    keyboard[0].push_back("abcdefghijklm");
68    keyboard[0].push_back("nopqrstuvwxyz");
69    keyboard[0].push_back("0123456789. ");
70
71    keyboard[1].push_back("ABCDEFGHIJKLM");
72    keyboard[1].push_back("NOPQRSTUVWXYZ");
73    keyboard[1].push_back("_\"'`.,:;!? ");
74
75
76    keyboard[2].push_back("¡¿*+-/\\&<=>|");
77    keyboard[2].push_back("()[]{}@#$%^~");
78    keyboard[2].push_back("_\"'`.,:;!? ");
79
80
81    keyboard[3].push_back("àáèéìíòóùúýäõ");
82    keyboard[3].push_back("ëïöüÿâêîôûåãñ");
83    keyboard[3].push_back("čďěľĺňôřŕšťůž");
84    keyboard[3].push_back("ąćęłńśżź ");
85
86    keyboard[4].push_back("ÀÁÈÉÌÍÒÓÙÚÝÄÕ");
87    keyboard[4].push_back("ËÏÖÜŸÂÊÎÔÛÅÃÑ");
88    keyboard[4].push_back("ČĎĚĽĹŇÔŘŔŠŤŮŽ");
89    keyboard[4].push_back("ĄĆĘŁŃŚŻŹ ");
90
91
92    keyboard[5].push_back("æçабвгдеёжзий ");
93    keyboard[5].push_back("клмнопрстуфхцч");
94    keyboard[5].push_back("шщъыьэюяøðßÐÞþ");
95
96    keyboard[6].push_back("ÆÇАБВГДЕЁЖЗИЙ ");
97    keyboard[6].push_back("КЛМНОПРСТУФХЦЧ");
98    keyboard[6].push_back("ШЩЪЫЬЭЮЯØðßÐÞþ");
99
100    setKeyboard(0);
101
102    buttonbox = new ButtonBox(gmenu2x);
103    IconButton *btnBackspace = new IconButton(gmenu2x, ts,
104            "skin:imgs/buttons/l.png", gmenu2x->tr["Backspace"]);
105    btnBackspace->setAction(BIND(&InputDialog::backspace));
106    buttonbox->add(btnBackspace);
107
108    IconButton *btnSpace = new IconButton(gmenu2x, ts,
109            "skin:imgs/buttons/r.png", gmenu2x->tr["Space"]);
110    btnSpace->setAction(BIND(&InputDialog::space));
111    buttonbox->add(btnSpace);
112
113    IconButton *btnConfirm = new IconButton(gmenu2x, ts,
114            "skin:imgs/buttons/accept.png", gmenu2x->tr["Confirm"]);
115    btnConfirm->setAction(BIND(&InputDialog::confirm));
116    buttonbox->add(btnConfirm);
117
118    IconButton *btnChangeKeys = new IconButton(gmenu2x, ts,
119            "skin:imgs/buttons/cancel.png", gmenu2x->tr["Change keys"]);
120    btnChangeKeys->setAction(BIND(&InputDialog::changeKeys));
121    buttonbox->add(btnChangeKeys);
122}
123
124void InputDialog::setKeyboard(int kb) {
125    kb = constrain(kb, 0, keyboard.size() - 1);
126    curKeyboard = kb;
127    this->kb = &(keyboard[kb]);
128    kbLength = this->kb->at(0).length();
129    for (int x = 0, l = kbLength; x < l; x++) {
130        if (utf8Code(this->kb->at(0)[x])) {
131            kbLength--;
132            x++;
133        }
134    }
135
136    kbLeft = 160 - kbLength * KEY_WIDTH / 2;
137    kbWidth = kbLength * KEY_WIDTH + 3;
138    kbHeight = (this->kb->size() + 1) * KEY_HEIGHT + 3;
139
140    kbRect.x = kbLeft - 3;
141    kbRect.y = KB_TOP - 2;
142    kbRect.w = kbWidth;
143    kbRect.h = kbHeight;
144}
145
146bool InputDialog::exec() {
147    SDL_Rect box = {
148        0, 60, 0, static_cast<Uint16>(gmenu2x->font->getHeight() + 4)
149    };
150
151    Uint32 caretTick = 0, curTick;
152    bool caretOn = true;
153
154    close = false;
155    ok = true;
156    while (!close) {
157        gmenu2x->bg->blit(gmenu2x->s,0,0);
158        writeTitle(title);
159        writeSubTitle(text);
160        drawTitleIcon(icon);
161
162        buttonbox->paint(5);
163
164        box.w = gmenu2x->font->getTextWidth(input) + 18;
165        box.x = 160 - box.w / 2;
166        gmenu2x->s->box(box.x, box.y, box.w, box.h,
167        gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
168        gmenu2x->s->rectangle(box.x, box.y, box.w, box.h,
169                gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
170
171        gmenu2x->s->write(gmenu2x->font, input, box.x + 5, box.y + box.h - 2,
172                Font::HAlignLeft, Font::VAlignBottom);
173
174        curTick = SDL_GetTicks();
175        if (curTick - caretTick >= 600) {
176            caretOn = !caretOn;
177            caretTick = curTick;
178        }
179
180        if (caretOn) {
181            gmenu2x->s->box(box.x + box.w - 12, box.y + 3, 8, box.h - 6,
182                    gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
183        }
184
185        if (ts.available()) ts.poll();
186        drawVirtualKeyboard();
187        gmenu2x->s->flip();
188
189        switch (inputMgr.waitForPressedButton()) {
190            case InputManager::SETTINGS:
191                ok = true;
192                close = true;
193                break;
194            case InputManager::MENU:
195                ok = false;
196                close = true;
197                break;
198            case InputManager::UP:
199                selRow--;
200                break;
201            case InputManager::DOWN:
202                selRow++;
203                if (selRow == (int)kb->size()) selCol = selCol < 8 ? 0 : 1;
204                break;
205            case InputManager::LEFT:
206                selCol--;
207                break;
208            case InputManager::RIGHT:
209                selCol++;
210                break;
211            case InputManager::ACCEPT:
212                confirm();
213                break;
214            case InputManager::CANCEL:
215                changeKeys();
216                break;
217            case InputManager::ALTLEFT:
218                backspace();
219                break;
220            case InputManager::ALTRIGHT:
221                space();
222                break;
223            default:
224                break;
225        }
226    }
227
228    return ok;
229}
230
231void InputDialog::backspace() {
232    // Check for UTF8 characters.
233    input = input.substr(0, input.length()
234        - (utf8Code(input[input.length() - 2]) ? 2 : 1));
235}
236
237void InputDialog::space() {
238    input += " ";
239}
240
241void InputDialog::confirm() {
242    if (selRow == (int)kb->size()) {
243        if (selCol == 0) {
244            ok = false;
245        }
246        close = true;
247    } else {
248        int xc = 0;
249        for (uint x = 0; x < kb->at(selRow).length(); x++) {
250            bool utf8 = utf8Code(kb->at(selRow)[x]);
251            if (xc == selCol) input += kb->at(selRow).substr(x, utf8 ? 2 : 1);
252            if (utf8) x++;
253            xc++;
254        }
255    }
256}
257
258void InputDialog::changeKeys() {
259    if (curKeyboard == 6) {
260        setKeyboard(0);
261    } else {
262        setKeyboard(curKeyboard + 1);
263    }
264}
265
266void InputDialog::drawVirtualKeyboard() {
267    //keyboard border
268    gmenu2x->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        gmenu2x->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        gmenu2x->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            //if ts on rect, change selection
308            if (ts.available() && ts.pressed() && ts.inRect(re)) {
309                selCol = xc;
310                selRow = l;
311            }
312
313            gmenu2x->s->rectangle(re,
314                    gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
315            gmenu2x->s->write(gmenu2x->font, charX,
316                    kbLeft + xc * KEY_WIDTH + KEY_WIDTH / 2 - 1,
317                    KB_TOP + l * KEY_HEIGHT + KEY_HEIGHT / 2,
318                    Font::HAlignCenter, Font::VAlignMiddle);
319            xc++;
320        }
321    }
322
323    //Ok/Cancel
324    SDL_Rect re = {
325        static_cast<Sint16>(kbLeft - 1),
326        static_cast<Sint16>(KB_TOP + kb->size() * KEY_HEIGHT),
327        static_cast<Uint16>(kbLength * KEY_WIDTH / 2 - 1),
328        KEY_HEIGHT - 1
329    };
330    gmenu2x->s->rectangle(re, gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
331    if (ts.available() && ts.pressed() && ts.inRect(re)) {
332        selCol = 0;
333        selRow = kb->size();
334    }
335    gmenu2x->s->write(gmenu2x->font, gmenu2x->tr["Cancel"],
336            (int)(160 - kbLength * KEY_WIDTH / 4),
337            KB_TOP + kb->size() * KEY_HEIGHT + KEY_HEIGHT / 2,
338            Font::HAlignCenter, Font::VAlignMiddle);
339
340    re.x = kbLeft + kbLength * KEY_WIDTH / 2 - 1;
341    gmenu2x->s->rectangle(re, gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
342    if (ts.available() && ts.pressed() && ts.inRect(re)) {
343        selCol = 1;
344        selRow = kb->size();
345    }
346    gmenu2x->s->write(gmenu2x->font, gmenu2x->tr["OK"],
347            (int)(160 + kbLength * KEY_WIDTH / 4),
348            KB_TOP + kb->size() * KEY_HEIGHT + KEY_HEIGHT / 2,
349            Font::HAlignCenter, Font::VAlignMiddle);
350}
351

Archive Download this file



interactive