aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2005-01-29 18:04:34 +0000
committerMax Horn2005-01-29 18:04:34 +0000
commitb43a53f74d0dbbd8f74ba64a2548c0005ae5442b (patch)
treeedf3467a1d790650dab257eafced38ed3c0ec7ef
parent66c524f0eec53790f9a8c88b58caa94dac677720 (diff)
downloadscummvm-rg350-b43a53f74d0dbbd8f74ba64a2548c0005ae5442b.tar.gz
scummvm-rg350-b43a53f74d0dbbd8f74ba64a2548c0005ae5442b.tar.bz2
scummvm-rg350-b43a53f74d0dbbd8f74ba64a2548c0005ae5442b.zip
Move more text editing code into class EditableWidget; ListWidget now has all the editing capabilities of EditTextWidget
svn-id: r16694
-rw-r--r--TODO11
-rw-r--r--gui/EditTextWidget.cpp130
-rw-r--r--gui/EditTextWidget.h9
-rw-r--r--gui/ListWidget.cpp84
-rw-r--r--gui/ListWidget.h1
-rw-r--r--gui/editable.cpp126
-rw-r--r--gui/editable.h17
-rw-r--r--gui/launcher.cpp4
8 files changed, 186 insertions, 196 deletions
diff --git a/TODO b/TODO
index b1ee391425..a8d9537ad0 100644
--- a/TODO
+++ b/TODO
@@ -194,11 +194,12 @@ Files
GUI
===
* Remove hard coded 320x200 assumptions, use game screen size
-* Add ability to scale GUI (ie. to make the GUI less tiny in COMI)
-* Remove code duplication between EditTextWidget and ListWidget (i.e. text
- editing code; maybe we can factor that out into a common base or aggregate
- class... not yet sure).
-* Fix EditTextWidget::drawCaret and ListWidget::drawCaret support for alternate
+* EditableWidget: Make it possible to specify a min/max length for the text
+* EditableWidget: Let setEditString filter the string it gets
+* EditableWidget: Right now, custom filtering requires the user to subclass;
+ it would be nice if there was simply a "validator hook" or so.
+ Maybe take some inspiration from Java's Swing in this matter.
+* Improve EditTextWidget::drawCaret and ListWidget::drawCaret support for alternate
fonts (the current code overdraws chars partly, and relies on the fact that
our default built-in font has a separation pixel column on the *left* side;
most other bitmap fonts have it on the right, though). To this end, we maybe
diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp
index 8f16ec417b..2e0fd21db0 100644
--- a/gui/EditTextWidget.cpp
+++ b/gui/EditTextWidget.cpp
@@ -28,16 +28,15 @@ namespace GUI {
EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text)
: EditableWidget(boss, x, y - 1, w, h + 2) {
- _editString = text;
- _backupString = text;
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE;
_type = kEditTextWidget;
- _caretPos = _editString.size();
+ setEditString(text);
+}
- _editScrollOffset = (g_gui.getStringWidth(_editString) - (getEditRect().width()));
- if (_editScrollOffset < 0)
- _editScrollOffset = 0;
+void EditTextWidget::setEditString(const String &str) {
+ EditableWidget::setEditString(str);
+ _backupString = str;
}
void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
@@ -61,75 +60,6 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
draw();
}
-bool EditTextWidget::tryInsertChar(char c, int pos) {
- if (isprint(c)) {
- _editString.insertChar(c, pos);
- return true;
- }
- return false;
-}
-
-
-bool EditTextWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- bool handled = true;
- bool dirty = false;
-
- // First remove caret
- if (_caretVisible)
- drawCaret(true);
-
- switch (keycode) {
- case '\n': // enter/return
- case '\r':
- // confirm edit and exit editmode
- endEditMode();
- dirty = true;
- break;
- case 27: // escape
- abortEditMode();
- dirty = true;
- break;
- case 8: // backspace
- if (_caretPos > 0) {
- _caretPos--;
- _editString.deleteChar(_caretPos);
- }
- dirty = true;
- break;
- case 127: // delete
- _editString.deleteChar(_caretPos);
- dirty = true;
- break;
- case 256 + 20: // left arrow
- if (_caretPos > 0) {
- dirty = setCaretPos(_caretPos - 1);
- }
- break;
- case 256 + 19: // right arrow
- if (_caretPos < (int)_editString.size()) {
- dirty = setCaretPos(_caretPos + 1);
- }
- break;
- case 256 + 22: // home
- dirty = setCaretPos(0);
- break;
- case 256 + 23: // end
- dirty = setCaretPos(_editString.size());
- break;
- default:
- if (tryInsertChar((char)ascii, _caretPos)) {
- _caretPos++;
- dirty = true;
- } else {
- handled = false;
- }
- }
-
- if (dirty)
- draw();
-
- return handled;
-}
void EditTextWidget::drawWidget(bool hilite) {
// Draw a thin frame around us.
@@ -149,16 +79,6 @@ Common::Rect EditTextWidget::getEditRect() const {
return r;
}
-int EditTextWidget::getCaretOffset() const {
- int caretpos = 0;
- for (int i = 0; i < _caretPos; i++)
- caretpos += g_gui.getCharWidth(_editString[i]);
-
- caretpos -= _editScrollOffset;
-
- return caretpos;
-}
-
void EditTextWidget::receivedFocusWidget() {
}
@@ -176,46 +96,8 @@ void EditTextWidget::endEditMode() {
}
void EditTextWidget::abortEditMode() {
- _editString = _backupString;
- _caretPos = _editString.size();
- _editScrollOffset = (g_gui.getStringWidth(_editString) - (getEditRect().width()));
- if (_editScrollOffset < 0)
- _editScrollOffset = 0;
+ setEditString(_backupString);
releaseFocus();
}
-bool EditTextWidget::setCaretPos(int newPos) {
- assert(newPos >= 0 && newPos <= (int)_editString.size());
- _caretPos = newPos;
- return adjustOffset();
-}
-
-bool EditTextWidget::adjustOffset() {
- // check if the caret is still within the textbox; if it isn't,
- // adjust _editScrollOffset
-
- int caretpos = getCaretOffset();
- const int editWidth = getEditRect().width();
-
- if (caretpos < 0) {
- // scroll left
- _editScrollOffset += caretpos;
- return true;
- } else if (caretpos >= editWidth) {
- // scroll right
- _editScrollOffset -= (editWidth - caretpos);
- return true;
- } else if (_editScrollOffset > 0) {
- const int strWidth = g_gui.getStringWidth(_editString);
- if (strWidth - _editScrollOffset < editWidth) {
- // scroll right
- _editScrollOffset = (strWidth - editWidth);
- if (_editScrollOffset < 0)
- _editScrollOffset = 0;
- }
- }
-
- return false;
-}
-
} // End of namespace GUI
diff --git a/gui/EditTextWidget.h b/gui/EditTextWidget.h
index 23410fa0c4..6d074edc63 100644
--- a/gui/EditTextWidget.h
+++ b/gui/EditTextWidget.h
@@ -36,11 +36,9 @@ protected:
public:
EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text);
-// void setString(const String &str) { _editString = str; }
- const String &getString() const { return _editString; }
+ void setEditString(const String &str);
virtual void handleMouseDown(int x, int y, int button, int clickCount);
- virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers);
virtual bool wantsFocus() { return true; };
@@ -54,11 +52,6 @@ protected:
void abortEditMode();
Common::Rect getEditRect() const;
- int getCaretOffset() const;
- bool setCaretPos(int newPos);
- bool adjustOffset();
-
- virtual bool tryInsertChar(char c, int pos);
};
} // End of namespace GUI
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp
index 515f2850f5..327fa2e95a 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -124,7 +124,7 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
// TODO: Determine where inside the string the user clicked and place the
- // caret accordingly.
+ // caret accordingly. See _editScrollOffset and EditTextWidget::handleMouseDown.
draw();
}
@@ -193,35 +193,8 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
scrollToCurrent();
} else if (_editMode) {
-
- if (_caretVisible)
- drawCaret(true);
-
- switch (keycode) {
- case '\n': // enter/return
- case '\r':
- // confirm edit and exit editmode
- endEditMode();
- dirty = true;
- break;
- case 27: // escape
- // abort edit and exit editmode
- abortEditMode();
- dirty = true;
- break;
- case 8: // backspace
- _editString.deleteLastChar();
- dirty = true;
- break;
- default:
- if (isprint((char)ascii)) {
- _editString += (char)ascii;
- dirty = true;
- } else {
- handled = false;
- }
- }
-
+ // Class EditableWidget handles all text editing related key presses for us
+ handled = EditableWidget::handleKeyDown(ascii, keycode, modifiers);
} else {
// not editmode
@@ -313,6 +286,7 @@ void ListWidget::drawWidget(bool hilite) {
NewGui *gui = &g_gui;
int i, pos, len = _list.size();
Common::String buffer;
+ int offset, deltax;
// Draw a thin frame around the list.
gui->hLine(_x, _y, _x + _w - 1, gui->_color);
@@ -321,26 +295,41 @@ void ListWidget::drawWidget(bool hilite) {
// Draw the list items
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
+ const OverlayColor textColor = (_selectedItem == pos && _hasFocus) ? gui->_bgcolor : gui->_textcolor;
+ const int y = _y + 2 + kLineHeight * i;
+
+ // Draw the selected item inverted, on a highlighted background.
+ if (_selectedItem == pos) {
+ if (_hasFocus)
+ gui->fillRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, gui->_textcolorhi);
+ else
+ gui->frameRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, gui->_textcolorhi);
+ }
+
+ // If in numbering mode, we first print a number prefix
if (_numberingMode != kListNumberingOff) {
char temp[10];
sprintf(temp, "%2d. ", (pos + _numberingMode));
buffer = temp;
+ gui->drawString(buffer, _x + 2, y, _w - 4, textColor);
+ offset = gui->getStringWidth(buffer);
} else {
- buffer.clear();
+ offset = 0;
}
- if (_selectedItem == pos && _editMode)
- buffer += _editString;
- else
- buffer += _list[pos];
- if (_selectedItem == pos) {
- if (_hasFocus)
- gui->fillRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, gui->_textcolorhi);
- else
- gui->frameRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, gui->_textcolorhi);
+ Common::Rect r(getEditRect());
+ if (_selectedItem == pos && _editMode) {
+
+ buffer = _editString;
+ adjustOffset();
+ deltax = -_editScrollOffset;
+
+ gui->drawString(buffer, _x + r.left, y, r.width(), textColor, kTextAlignLeft, deltax, false);
+ } else {
+ buffer = _list[pos];
+ deltax = 0;
+ gui->drawString(buffer, _x + r.left, y, r.width(), textColor);
}
- gui->drawString(buffer, _x + 2, _y + 2 + kLineHeight * i, _w - 4,
- (_selectedItem == pos && _hasFocus) ? gui->_bgcolor : gui->_textcolor);
}
}
@@ -359,14 +348,6 @@ Common::Rect ListWidget::getEditRect() const {
return r;
}
-int ListWidget::getCaretOffset() const {
- int caretpos = 0;
-
- caretpos += g_gui.getStringWidth(_editString);
-
- return caretpos;
-}
-
void ListWidget::scrollToCurrent() {
// Only do something if the current item is not in our view port
if (_selectedItem < _currentPos) {
@@ -389,8 +370,7 @@ void ListWidget::scrollToCurrent() {
void ListWidget::startEditMode() {
if (_editable && !_editMode && _selectedItem >= 0) {
_editMode = true;
- _editString = _list[_selectedItem];
- _caretPos = _editString.size();
+ setEditString(_list[_selectedItem]);
draw();
}
}
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index d72bd75983..3a826a490b 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -96,7 +96,6 @@ protected:
void abortEditMode();
Common::Rect getEditRect() const;
- int getCaretOffset() const;
void lostFocusWidget();
void scrollToCurrent();
diff --git a/gui/editable.cpp b/gui/editable.cpp
index 7fed1209bc..5a556ee561 100644
--- a/gui/editable.cpp
+++ b/gui/editable.cpp
@@ -1,5 +1,5 @@
/* ScummVM - Scumm Interpreter
- * Copyright (C) 2002-2005 The ScummVM project
+ * Copyright (C) 2005 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +39,25 @@ EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h)
EditableWidget::~EditableWidget() {
}
+void EditableWidget::setEditString(const String &str) {
+ // TODO: We probably should filter the input string here,
+ // e.g. using tryInsertChar.
+ _editString = str;
+ _caretPos = _editString.size();
+
+ _editScrollOffset = (g_gui.getStringWidth(_editString) - (getEditRect().width()));
+ if (_editScrollOffset < 0)
+ _editScrollOffset = 0;
+}
+
+bool EditableWidget::tryInsertChar(char c, int pos) {
+ if (isprint(c)) {
+ _editString.insertChar(c, pos);
+ return true;
+ }
+ return false;
+}
+
void EditableWidget::handleTickle() {
uint32 time = getMillis();
if (_caretTime < time) {
@@ -47,6 +66,77 @@ void EditableWidget::handleTickle() {
}
}
+bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+ bool handled = true;
+ bool dirty = false;
+
+ // First remove caret
+ if (_caretVisible)
+ drawCaret(true);
+
+ switch (keycode) {
+ case '\n': // enter/return
+ case '\r':
+ // confirm edit and exit editmode
+ endEditMode();
+ dirty = true;
+ break;
+ case 27: // escape
+ abortEditMode();
+ dirty = true;
+ break;
+ case 8: // backspace
+ if (_caretPos > 0) {
+ _caretPos--;
+ _editString.deleteChar(_caretPos);
+ dirty = true;
+ }
+ break;
+ case 127: // delete
+ _editString.deleteChar(_caretPos);
+ dirty = true;
+ break;
+ case 256 + 20: // left arrow
+ if (_caretPos > 0) {
+ dirty = setCaretPos(_caretPos - 1);
+ }
+ break;
+ case 256 + 19: // right arrow
+ if (_caretPos < (int)_editString.size()) {
+ dirty = setCaretPos(_caretPos + 1);
+ }
+ break;
+ case 256 + 22: // home
+ dirty = setCaretPos(0);
+ break;
+ case 256 + 23: // end
+ dirty = setCaretPos(_editString.size());
+ break;
+ default:
+ if (tryInsertChar((char)ascii, _caretPos)) {
+ _caretPos++;
+ dirty = true;
+ } else {
+ handled = false;
+ }
+ }
+
+ if (dirty)
+ draw();
+
+ return handled;
+}
+
+int EditableWidget::getCaretOffset() const {
+ int caretpos = 0;
+ for (int i = 0; i < _caretPos; i++)
+ caretpos += g_gui.getCharWidth(_editString[i]);
+
+ caretpos -= _editScrollOffset;
+
+ return caretpos;
+}
+
void EditableWidget::drawCaret(bool erase) {
// Only draw if item is visible
if (!isVisible() || !_boss->isVisible())
@@ -70,5 +160,39 @@ void EditableWidget::drawCaret(bool erase) {
_caretVisible = !erase;
}
+bool EditableWidget::setCaretPos(int newPos) {
+ assert(newPos >= 0 && newPos <= (int)_editString.size());
+ _caretPos = newPos;
+ return adjustOffset();
+}
+
+bool EditableWidget::adjustOffset() {
+ // check if the caret is still within the textbox; if it isn't,
+ // adjust _editScrollOffset
+
+ int caretpos = getCaretOffset();
+ const int editWidth = getEditRect().width();
+
+ if (caretpos < 0) {
+ // scroll left
+ _editScrollOffset += caretpos;
+ return true;
+ } else if (caretpos >= editWidth) {
+ // scroll right
+ _editScrollOffset -= (editWidth - caretpos);
+ return true;
+ } else if (_editScrollOffset > 0) {
+ const int strWidth = g_gui.getStringWidth(_editString);
+ if (strWidth - _editScrollOffset < editWidth) {
+ // scroll right
+ _editScrollOffset = (strWidth - editWidth);
+ if (_editScrollOffset < 0)
+ _editScrollOffset = 0;
+ }
+ }
+
+ return false;
+}
+
} // End of namespace GUI
diff --git a/gui/editable.h b/gui/editable.h
index 2aa2a88c01..2d637316c8 100644
--- a/gui/editable.h
+++ b/gui/editable.h
@@ -1,5 +1,5 @@
/* ScummVM - Scumm Interpreter
- * Copyright (C) 2002-2005 The ScummVM project
+ * Copyright (C) 2005 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,7 +27,10 @@
namespace GUI {
-
+/**
+ * Base class for widgets which need to edit text, like ListWidget and
+ * EditTextWidget.
+ */
class EditableWidget : public Widget {
public:
typedef Common::String String;
@@ -46,7 +49,11 @@ public:
EditableWidget(GuiObject *boss, int x, int y, int w, int h);
virtual ~EditableWidget();
+ virtual void setEditString(const String &str);
+ virtual const String &getEditString() const { return _editString; }
+
virtual void handleTickle();
+ virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers);
protected:
virtual void startEditMode() = 0;
@@ -54,8 +61,12 @@ protected:
virtual void abortEditMode() = 0;
virtual Common::Rect getEditRect() const = 0;
- virtual int getCaretOffset() const = 0;
+ virtual int getCaretOffset() const;
void drawCaret(bool erase);
+ bool setCaretPos(int newPos);
+ bool adjustOffset();
+
+ virtual bool tryInsertChar(char c, int pos);
};
} // End of namespace GUI
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index d923136782..07acdad6ee 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -303,7 +303,7 @@ void EditGameDialog::open() {
void EditGameDialog::close() {
if (getResult()) {
- ConfMan.set("description", _descriptionWidget->getString(), _domain);
+ ConfMan.set("description", _descriptionWidget->getEditString(), _domain);
Common::Language lang = (Common::Language)_langPopUp->getSelectedTag();
if (lang < 0)
@@ -389,7 +389,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kOKCmd: {
// Write back changes made to config object
- String newDomain(_domainWidget->getString());
+ String newDomain(_domainWidget->getEditString());
if (newDomain != _domain) {
if (newDomain.isEmpty() || ConfMan.hasGameDomain(newDomain)) {
MessageDialog alert("This game ID is already taken. Please choose another one.");