1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "common/events.h"
26 #include "gui/editable.h"
27 #include "gui/GuiManager.h"
31 EditableWidget::EditableWidget(GuiObject
*boss
, int x
, int y
, int w
, int h
, uint32 cmd
)
32 : Widget(boss
, x
, y
, w
, h
), CommandSender(boss
), _cmd(cmd
) {
36 EditableWidget::EditableWidget(GuiObject
*boss
, const String
&name
, uint32 cmd
)
37 : Widget(boss
, name
), CommandSender(boss
), _cmd(cmd
) {
41 void EditableWidget::init() {
42 _caretVisible
= false;
46 _caretInverse
= false;
48 _editScrollOffset
= 0;
50 _font
= ThemeEngine::kFontStyleBold
;
53 EditableWidget::~EditableWidget() {
56 void EditableWidget::reflowLayout() {
57 Widget::reflowLayout();
59 _editScrollOffset
= g_gui
.getStringWidth(_editString
, _font
) - getEditRect().width();
60 if (_editScrollOffset
< 0)
61 _editScrollOffset
= 0;
64 void EditableWidget::setEditString(const String
&str
) {
65 // TODO: We probably should filter the input string here,
66 // e.g. using tryInsertChar.
68 _caretPos
= _editString
.size();
71 bool EditableWidget::tryInsertChar(byte c
, int pos
) {
72 if ((c
>= 32 && c
<= 127) || c
>= 160) {
73 _editString
.insertChar(c
, pos
);
79 void EditableWidget::handleTickle() {
80 uint32 time
= getMillis();
81 if (_caretTime
< time
) {
82 _caretTime
= time
+ kCaretBlinkTime
;
83 drawCaret(_caretVisible
);
87 bool EditableWidget::handleKeyDown(Common::KeyState state
) {
90 bool forcecaret
= false;
96 switch (state
.keycode
) {
97 case Common::KEYCODE_RETURN
:
98 case Common::KEYCODE_KP_ENTER
:
99 // confirm edit and exit editmode
103 case Common::KEYCODE_ESCAPE
:
107 case Common::KEYCODE_BACKSPACE
:
110 _editString
.deleteChar(_caretPos
);
113 sendCommand(_cmd
, 0);
117 case Common::KEYCODE_DELETE
:
118 if (_caretPos
< (int)_editString
.size()) {
119 _editString
.deleteChar(_caretPos
);
122 sendCommand(_cmd
, 0);
126 case Common::KEYCODE_LEFT
:
128 dirty
= setCaretPos(_caretPos
- 1);
133 case Common::KEYCODE_RIGHT
:
134 if (_caretPos
< (int)_editString
.size()) {
135 dirty
= setCaretPos(_caretPos
+ 1);
140 case Common::KEYCODE_HOME
:
141 dirty
= setCaretPos(0);
144 case Common::KEYCODE_END
:
145 dirty
= setCaretPos(_editString
.size());
149 if (tryInsertChar((byte
)state
.ascii
, _caretPos
)) {
154 sendCommand(_cmd
, 0);
169 int EditableWidget::getCaretOffset() const {
171 for (int i
= 0; i
< _caretPos
; i
++)
172 caretpos
+= g_gui
.getCharWidth(_editString
[i
], _font
);
174 caretpos
-= _editScrollOffset
;
179 void EditableWidget::drawCaret(bool erase
) {
180 // Only draw if item is visible
181 if (!isVisible() || !_boss
->isVisible())
184 Common::Rect editRect
= getEditRect();
186 int x
= editRect
.left
;
187 int y
= editRect
.top
+ 1;
189 x
+= getCaretOffset();
191 if (y
< 0 || y
+ editRect
.height() - 2 >= _h
)
197 g_gui
.theme()->drawCaret(Common::Rect(x
, y
, x
+ 1, y
+ editRect
.height() - 2), erase
);
199 _caretVisible
= !erase
;
202 bool EditableWidget::setCaretPos(int newPos
) {
203 assert(newPos
>= 0 && newPos
<= (int)_editString
.size());
205 return adjustOffset();
208 bool EditableWidget::adjustOffset() {
209 // check if the caret is still within the textbox; if it isn't,
210 // adjust _editScrollOffset
212 int caretpos
= getCaretOffset();
213 const int editWidth
= getEditRect().width();
217 _editScrollOffset
+= caretpos
;
219 } else if (caretpos
>= editWidth
) {
221 _editScrollOffset
-= (editWidth
- caretpos
);
223 } else if (_editScrollOffset
> 0) {
224 const int strWidth
= g_gui
.getStringWidth(_editString
, _font
);
225 if (strWidth
- _editScrollOffset
< editWidth
) {
227 _editScrollOffset
= (strWidth
- editWidth
);
228 if (_editScrollOffset
< 0)
229 _editScrollOffset
= 0;
236 void EditableWidget::makeCaretVisible() {
237 _caretTime
= getMillis() + kCaretBlinkTime
;
238 _caretVisible
= true;
242 } // End of namespace GUI