Ticket #8217: EditTextWidget.cpp

File EditTextWidget.cpp, 4.9 KB (added by wjp, 16 years ago)

EditTextWidget.cpp

Line 
1/* ScummVM - Scumm Interpreter
2 * Copyright (C) 2002-2003 The ScummVM project
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 *
18 * $Header: /cvsroot/scummvm/scummvm/gui/EditTextWidget.cpp,v 1.11 2003/05/05 10:38:16 olki Exp $
19 */
20
21#include "stdafx.h"
22#include "EditTextWidget.h"
23#include "dialog.h"
24#include "newgui.h"
25
26EditTextWidget::EditTextWidget(Dialog *boss, int x, int y, int w, int h, const String &text)
27        : StaticTextWidget(boss, x, y-1, w, h+2, text, kTextAlignLeft), _backupString(text) {
28        _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE;
29        _type = kEditTextWidget;
30
31        _caretVisible = false;
32        _caretTime = 0;
33
34        _pos = _label.size();
35
36        NewGui *gui = _boss->getGui();
37        _labelOffset = (gui->getStringWidth(_label) - (_w - 6));
38        if (_labelOffset < 0)
39                _labelOffset = 0;
40}
41
42void EditTextWidget::handleTickle() {
43        uint32 time = _boss->getGui()->get_time();
44        if (_caretTime < time) {
45                _caretTime = time + kCaretBlinkTime;
46                if (_caretVisible) {
47                        drawCaret(true);
48                } else {
49                        drawCaret(false);
50                }
51        }
52}
53
54void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
55        // TODO - once we support "real editing" (i.e. caret can be at any spot),
56        // a mouse click should place the caret.
57}
58
59bool EditTextWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
60        bool handled = true;
61        bool dirty = false;
62
63        // First remove caret
64        if (_caretVisible)
65                drawCaret(true);
66
67        switch (keycode) {
68                case '\n':      // enter/return
69                case '\r':
70                        _boss->releaseFocus();
71                        dirty = true;
72                        break;
73                case 27:        // escape
74                        _label = _backupString;
75                        _pos = _label.size() - 1;
76                        _labelOffset = (_boss->getGui()->getStringWidth(_label) - (_w-6));
77                        if (_labelOffset < 0)
78                                _labelOffset = 0;
79                        _boss->releaseFocus();
80                        dirty = true;
81                        break;
82                case 8:         // backspace
83                        if (_pos > 0) {
84                                _pos--;
85                                _label.deleteChar(_pos);
86                        }
87                        dirty = true;
88                        break;
89                case 127:       // delete
90                        _label.deleteChar(_pos);
91                        dirty = true;
92                        break;
93                case 256 + 20:  // left arrow
94                        if (_pos > 0) {
95                                _pos--;
96                                dirty = adjustOffset();
97                        }
98                        break;
99                case 256 + 19:  // right arrow
100                        if (_pos < _label.size()) {
101                                _pos++;
102                                dirty = adjustOffset();
103                        }
104                        break;
105                case 256 + 22:  // home
106                        _pos = 0;
107                        dirty = adjustOffset();
108                        break;
109                case 256 + 23:  // end
110                        _pos = _label.size();
111                        dirty = adjustOffset();
112                        break;
113                default:
114                        if (isprint((char)ascii)) {
115                                _label.insertChar((char)ascii, _pos++);
116                                //_label += (char)ascii;
117                                dirty = true;
118                        } else {
119                                handled = false;
120                        }
121        }
122
123        if (dirty)
124                draw();
125
126        return handled;
127}
128
129void EditTextWidget::drawWidget(bool hilite) {
130        NewGui *gui = _boss->getGui();
131
132        // Draw a thin frame around us.
133        gui->hline(_x, _y, _x + _w - 1, gui->_color);
134        gui->hline(_x, _y + _h - 1, _x +_w - 1, gui->_shadowcolor);
135        gui->vline(_x, _y, _y + _h - 1, gui->_color);
136        gui->vline(_x + _w - 1, _y, _y + _h - 1, gui->_shadowcolor);
137
138        // Draw the text
139        adjustOffset();
140        gui->drawString(_label, _x + 2, _y + 3, _w - 6, gui->_textcolor, kTextAlignLeft, -_labelOffset);
141}
142
143int EditTextWidget::getCaretPos() {
144        NewGui *gui = _boss->getGui();
145        int caretpos = 0;
146        for (int i = 0; i < _pos; i++)
147                caretpos += gui->getCharWidth(_label[i]);
148
149        caretpos -= _labelOffset;
150
151        return caretpos;
152}
153
154void EditTextWidget::drawCaret(bool erase) {
155        // Only draw if item is visible
156        if (!isVisible() || !_boss->isVisible())
157                return;
158
159        NewGui *gui = _boss->getGui();
160
161        int16 color = erase ? gui->_bgcolor : gui->_textcolorhi;
162        int x = _x + _boss->getX() + 2;
163        int y = _y + _boss->getY() + 1;
164
165        int width = getCaretPos();
166        x += width;
167
168        gui->vline(x, y, y + kLineHeight, color);
169        gui->addDirtyRect(x, y, 2, kLineHeight);
170
171        _caretVisible = !erase;
172}
173
174
175
176bool EditTextWidget::adjustOffset() {
177        // check if the caret is still within the textbox; if it isn't,
178        // adjust _labelOffset
179
180        int caretpos = getCaretPos();
181
182        if (caretpos < 0) {
183                // scroll left
184                _labelOffset += caretpos;
185                return true;
186        }
187        else if (caretpos >= _w - 6)
188        {
189                // scroll right
190                _labelOffset -= (_w - 6 - caretpos);
191                return true;
192        }
193        else if (_labelOffset > 0)
194        {
195                int width = _boss->getGui()->getStringWidth(_label);
196                if (width - _labelOffset < (_w - 6)) {
197                        // scroll right
198                        _labelOffset = (width - (_w - 6));
199                        if (_labelOffset < 0)
200                                _labelOffset = 0;
201                }
202        }
203
204        return false;
205}