diff options
author | Max Horn | 2005-01-29 18:04:34 +0000 |
---|---|---|
committer | Max Horn | 2005-01-29 18:04:34 +0000 |
commit | b43a53f74d0dbbd8f74ba64a2548c0005ae5442b (patch) | |
tree | edf3467a1d790650dab257eafced38ed3c0ec7ef | |
parent | 66c524f0eec53790f9a8c88b58caa94dac677720 (diff) | |
download | scummvm-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-- | TODO | 11 | ||||
-rw-r--r-- | gui/EditTextWidget.cpp | 130 | ||||
-rw-r--r-- | gui/EditTextWidget.h | 9 | ||||
-rw-r--r-- | gui/ListWidget.cpp | 84 | ||||
-rw-r--r-- | gui/ListWidget.h | 1 | ||||
-rw-r--r-- | gui/editable.cpp | 126 | ||||
-rw-r--r-- | gui/editable.h | 17 | ||||
-rw-r--r-- | gui/launcher.cpp | 4 |
8 files changed, 186 insertions, 196 deletions
@@ -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."); |