From 72ec5f237113177b7c396908790f660bc4fe76fc Mon Sep 17 00:00:00 2001 From: stephena Date: Wed, 22 Apr 2015 15:02:17 +0000 Subject: [PATCH] Finally fixed text-entry bug in the debugger. In the process, moved to C++11 lambdas for enabling per-widget text filtering. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3159 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- Changes.txt | 10 ++- Makefile | 2 +- src/common/Version.hxx | 2 +- src/debugger/gui/DataGridWidget.cxx | 110 ++++++++++++---------------- src/debugger/gui/DataGridWidget.hxx | 27 ++++--- src/debugger/gui/RomListWidget.cxx | 79 ++++++++------------ src/debugger/gui/RomListWidget.hxx | 8 +- src/gui/CheckListWidget.cxx | 10 +-- src/gui/Dialog.cxx | 22 ++---- src/gui/Dialog.hxx | 11 ++- src/gui/EditTextWidget.cxx | 11 ++- src/gui/EditableWidget.cxx | 4 - src/gui/EditableWidget.hxx | 26 ++++--- src/gui/ListWidget.cxx | 8 +- src/gui/StringListWidget.cxx | 10 +-- src/gui/Widget.cxx | 17 ++++- src/gui/Widget.hxx | 3 +- 17 files changed, 161 insertions(+), 199 deletions(-) diff --git a/Changes.txt b/Changes.txt index a495d860f..eccebc37a 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,6 +12,14 @@ Release History =========================================================================== +4.6 to 4.6.1: (April xx, 2015) + + * Fixed bug whereby text input could not be entered in certain widgets + in the debugger. + +-Have fun! + + 4.5 to 4.6: (March 21, 2015) * Finally fixed fullscreen rendering issues on some OpenGL @@ -46,8 +54,6 @@ * Updated included PNG library to latest stable version. --Have fun! - 4.2 to 4.5: (January 1, 2015) diff --git a/Makefile b/Makefile index 3d0e00593..bef0600cb 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ else endif CXXFLAGS+= -Wall ifdef HAVE_GCC - CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -std=c++11 + CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++11 endif ifdef PROFILE diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 9a3870902..a81d860a3 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -22,7 +22,7 @@ #include -#define STELLA_VERSION "4.7_pre" +#define STELLA_VERSION "4.6.1_pre" #define STELLA_BUILD atoi("$Rev$" + 6) #endif diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index ae5204c89..7aab03b0b 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -82,6 +82,24 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font, _scrollBar->_entriesPerPage = 1; _scrollBar->_wheel_lines = 1; } + + // Add filtering + EditableWidget::TextFilter f = [&](char c) { + bool isBin = c == '0' || c == '1', + isDec = c >= '0' && c <= '9', + isHex = isDec || (c >= 'a' && c <= 'f'), + isOp = c == '$' || c == '#' || c == '\\'; + + if(BSPF_startsWithIgnoreCase(editString(), "$")) + return isHex; + else if(BSPF_startsWithIgnoreCase(editString(), "#")) + return isDec; + else if(BSPF_startsWithIgnoreCase(editString(), "\\")) + return isBin; + else + return isHex || isDec || isBin || isOp; + }; + setTextFilter(f); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -123,7 +141,7 @@ cerr << "_addrList.size() = " << _addrList.size() << ", _valueStringList.size() = " << _valueStringList.size() << ", _rows*_cols = " << _rows * _cols << endl << endl; */ - _editMode = false; + enableEditMode(false); // Send item selected signal for starting with cell 0 sendCommand(DataGridWidget::kSelectionChangedCmd, _selectedItem, _id); @@ -193,9 +211,9 @@ void DataGridWidget::setValue(int position, int value, bool changed) if(position >= 0 && uInt32(position) < _valueList.size()) { // Correctly format the data for viewing - _editString = Common::Base::toString(value, _base); + editString() = Common::Base::toString(value, _base); - _valueStringList[position] = _editString; + _valueStringList[position] = editString(); _changedList[position] = changed; _valueList[position] = value; @@ -248,7 +266,7 @@ void DataGridWidget::handleMouseUp(int x, int y, int button, int clickCount) sendCommand(DataGridWidget::kItemDoubleClickedCmd, _selectedItem, _id); // Start edit mode - if(_editable && !_editMode) + if(isEditable() && !_editMode) startEditMode(); } } @@ -258,7 +276,7 @@ void DataGridWidget::handleMouseWheel(int x, int y, int direction) { if(_scrollBar) _scrollBar->handleMouseWheel(x, y, direction); - else if(_editable) + else if(isEditable()) { if(direction > 0) decrementCell(); @@ -413,39 +431,39 @@ bool DataGridWidget::handleKeyDown(StellaKey key, StellaMod mod) break; case KBDK_N: // negate - if(_editable) + if(isEditable()) negateCell(); break; case KBDK_I: // invert - if(_editable) + if(isEditable()) invertCell(); break; case KBDK_MINUS: // decrement case KBDK_KP_MINUS: - if(_editable) + if(isEditable()) decrementCell(); break; case KBDK_EQUALS: // increment case KBDK_KP_PLUS: - if(_editable) + if(isEditable()) incrementCell(); break; case KBDK_COMMA: // shift left - if(_editable) + if(isEditable()) lshiftCell(); break; case KBDK_PERIOD: // shift right - if(_editable) + if(isEditable()) rshiftCell(); break; case KBDK_Z: // zero - if(_editable) + if(isEditable()) zeroCell(); break; @@ -491,7 +509,7 @@ void DataGridWidget::receivedFocusWidget() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::lostFocusWidget() { - _editMode = false; + enableEditMode(false); // Disable the operations widget if(_opsWidget) @@ -542,7 +560,6 @@ void DataGridWidget::handleCommand(CommandSender* sender, int cmd, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::drawWidget(bool hilite) { -//cerr << "DataGridWidget::drawWidget\n"; FBSurface& s = _boss->dialog().surface(); int row, col; @@ -571,8 +588,7 @@ void DataGridWidget::drawWidget(bool hilite) if (_selectedItem == pos && _editMode) { adjustOffset(); - - s.drawString(_font, _editString, x, y, _colWidth, kTextColor, + s.drawString(_font, editString(), x, y, _colWidth, kTextColor, kTextAlignLeft, -_editScrollOffset, false); } else @@ -627,10 +643,10 @@ int DataGridWidget::getWidth() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::startEditMode() { - if (_editable && !_editMode && _selectedItem >= 0) + if (isEditable() && !_editMode && _selectedItem >= 0) { - _editMode = true; - setText("", true ); // Erase current entry when starting editing + enableEditMode(true); + setText("", true); // Erase current entry when starting editing } } @@ -640,11 +656,11 @@ void DataGridWidget::endEditMode() if (!_editMode) return; - _editMode = false; + enableEditMode(false); // Update the both the string representation and the real data - if(_editString.size() > 0 && !(_editString[0] == '$' || - _editString[0] == '#' || _editString[0] == '\\')) + if(editString().size() > 0 && !(editString()[0] == '$' || + editString()[0] == '#' || editString()[0] == '\\')) { switch(_base) { @@ -653,21 +669,21 @@ void DataGridWidget::endEditMode() case Common::Base::F_16_2: case Common::Base::F_16_4: case Common::Base::F_16_8: - _editString.insert(0, 1, '$'); + editString().insert(0, 1, '$'); break; case Common::Base::F_2: case Common::Base::F_2_8: case Common::Base::F_2_16: - _editString.insert(0, 1, '\\'); + editString().insert(0, 1, '\\'); break; case Common::Base::F_10: - _editString.insert(0, 1, '#'); + editString().insert(0, 1, '#'); break; case Common::Base::F_DEFAULT: break; } } - int value = instance().debugger().stringToValue(_editString); + int value = instance().debugger().stringToValue(editString()); if(value < _lowerBound || value >= _upperBound) { abortEditMode(); @@ -680,42 +696,12 @@ void DataGridWidget::endEditMode() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DataGridWidget::abortEditMode() { - // undo any changes made - assert(_selectedItem >= 0); - _editMode = false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool DataGridWidget::tryInsertChar(char c, int pos) -{ - // Input is very strict here, to eliminate time-consuming error checking - // elsewhere, and includes the following restrictions: - // Cannot contain spaces - // Starts with leading specifier ($, #, \), or with a base character - // Only one specifier is allowed - // If starting with a specifier, only allow numbers applicable to that - // base to follow - - c = tolower(c); - bool isBin = c == '0' || c == '1', - isDec = c >= '0' && c <= '9', - isHex = isDec || (c >= 'a' && c <= 'f'), - isOp = c == '$' || c == '#' || c == '\\', - insert = false; - - if(BSPF_startsWithIgnoreCase(_editString, "$")) - insert = isHex && pos > 0; - else if(BSPF_startsWithIgnoreCase(_editString, "#")) - insert = isDec && pos > 0; - else if(BSPF_startsWithIgnoreCase(_editString, "\\")) - insert = isBin && pos > 0; - else - insert = isHex || isDec || isBin || isOp; - - if(insert) - _editString.insert(pos, 1, c); - - return insert; + if(_editMode) + { + // Undo any changes made + assert(_selectedItem >= 0); + enableEditMode(false); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/DataGridWidget.hxx b/src/debugger/gui/DataGridWidget.hxx index fded8f4f5..20424dbb2 100644 --- a/src/debugger/gui/DataGridWidget.hxx +++ b/src/debugger/gui/DataGridWidget.hxx @@ -71,21 +71,10 @@ class DataGridWidget : public EditableWidget void setRange(int lower, int upper); - virtual void handleMouseDown(int x, int y, int button, int clickCount); - virtual void handleMouseUp(int x, int y, int button, int clickCount); - virtual void handleMouseWheel(int x, int y, int direction); - virtual bool handleText(char text); - virtual bool handleKeyDown(StellaKey key, StellaMod mod); - virtual bool handleKeyUp(StellaKey key, StellaMod mod); - virtual void handleCommand(CommandSender* sender, int cmd, int data, int id); - - virtual bool wantsFocus() { return true; } + bool wantsFocus() { return true; } // Account for the extra width of embedded scrollbar - virtual int getWidth() const; - - void startEditMode(); - void endEditMode(); + int getWidth() const; int colWidth() { return _colWidth; } @@ -96,6 +85,8 @@ class DataGridWidget : public EditableWidget int findItem(int x, int y); + void startEditMode(); + void endEditMode(); void abortEditMode(); GUI::Rect getEditRect() const; @@ -103,7 +94,13 @@ class DataGridWidget : public EditableWidget void receivedFocusWidget(); void lostFocusWidget(); - bool tryInsertChar(char c, int pos); + void handleMouseDown(int x, int y, int button, int clickCount); + void handleMouseUp(int x, int y, int button, int clickCount); + void handleMouseWheel(int x, int y, int direction); + bool handleText(char text); + bool handleKeyDown(StellaKey key, StellaMod mod); + bool handleKeyUp(StellaKey key, StellaMod mod); + void handleCommand(CommandSender* sender, int cmd, int data, int id); protected: int _rows; @@ -141,6 +138,8 @@ class DataGridWidget : public EditableWidget void lshiftCell(); void rshiftCell(); void zeroCell(); + + void enableEditMode(bool state) { _editMode = state; } }; #endif diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 1c68e048f..b468a12cd 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -88,6 +88,33 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont, myCheckList.push_back(t); } + + // Add filtering + EditableWidget::TextFilter f = [&](char c) + { + switch(_base) + { + case Common::Base::F_16: + case Common::Base::F_16_1: + case Common::Base::F_16_2: + case Common::Base::F_16_4: + case Common::Base::F_16_8: + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || c == ' '; + + case Common::Base::F_2: + case Common::Base::F_2_8: + case Common::Base::F_2_16: + return c == '0' || c == '1' || c == ' '; + + case Common::Base::F_10: + return (c >= '0' && c <= '9') || c == ' '; + + case Common::Base::F_DEFAULT: + return false; + } + return false; + }; + setTextFilter(f); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -153,15 +180,6 @@ void RomListWidget::setHighlighted(int item) } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string& RomListWidget::getText() const -{ - if(_selectedItem < -1 || _selectedItem >= (int)myDisasm->list.size()) - return EmptyString; - else - return _editString; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int RomListWidget::findItem(int x, int y) const { @@ -258,7 +276,7 @@ void RomListWidget::handleMouseUp(int x, int y, int button, int clickCount) if (clickCount == 2 && (_selectedItem == findItem(x, y))) { // Start edit mode - if(_editable && !_editMode) + if(isEditable() && !_editMode) startEditMode(); } } @@ -345,7 +363,7 @@ bool RomListWidget::handleEvent(Event::Type e) case Event::UISelect: if (_selectedItem >= 0) { - if (_editable) + if (isEditable()) startEditMode(); } break; @@ -431,7 +449,6 @@ void RomListWidget::lostFocusWidget() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomListWidget::drawWidget(bool hilite) { -//cerr << "RomListWidget::drawWidget\n"; FBSurface& s = _boss->dialog().surface(); const CartDebug::DisassemblyList& dlist = myDisasm->list; int i, pos, xpos, ypos, len = (int)dlist.size(); @@ -506,7 +523,7 @@ void RomListWidget::drawWidget(bool hilite) if (_selectedItem == pos && _editMode) { adjustOffset(); - s.drawString(_font, _editString, _x + r.x(), ypos, r.width(), kTextColor, + s.drawString(_font, editString(), _x + r.x(), ypos, r.width(), kTextColor, kTextAlignLeft, -_editScrollOffset, false); drawCaret(); @@ -553,44 +570,10 @@ GUI::Rect RomListWidget::getEditRect() const return r; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool RomListWidget::tryInsertChar(char c, int pos) -{ - // Not sure how efficient this is, or should we even care? - bool insert = false; - c = tolower(c); - switch(_base) - { - case Common::Base::F_16: - case Common::Base::F_16_1: - case Common::Base::F_16_2: - case Common::Base::F_16_4: - case Common::Base::F_16_8: - insert = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || c == ' '; - break; - case Common::Base::F_2: - case Common::Base::F_2_8: - case Common::Base::F_2_16: - insert = c == '0' || c == '1' || c == ' '; - break; - case Common::Base::F_10: - if((c >= '0' && c <= '9') || c == ' ') - insert = true; - break; - case Common::Base::F_DEFAULT: - break; - } - - if(insert) - _editString.insert(pos, 1, c); - - return insert; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomListWidget::startEditMode() { - if (_editable && !_editMode && _selectedItem >= 0) + if (isEditable() && !_editMode && _selectedItem >= 0) { // Does this line represent an editable area? if(myDisasm->list[_selectedItem].bytes == "") diff --git a/src/debugger/gui/RomListWidget.hxx b/src/debugger/gui/RomListWidget.hxx index f0960d908..feb3144d1 100644 --- a/src/debugger/gui/RomListWidget.hxx +++ b/src/debugger/gui/RomListWidget.hxx @@ -59,10 +59,6 @@ class RomListWidget : public EditableWidget void setSelected(int item); void setHighlighted(int item); - const string& getText() const; - void startEditMode(); - void endEditMode(); - protected: void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount); @@ -80,8 +76,8 @@ class RomListWidget : public EditableWidget int findItem(int x, int y) const; void recalc(); - bool tryInsertChar(char c, int pos); - + void startEditMode(); + void endEditMode(); void abortEditMode(); void lostFocusWidget(); void scrollToSelected() { scrollToCurrent(_selectedItem); } diff --git a/src/gui/CheckListWidget.cxx b/src/gui/CheckListWidget.cxx index 289dcf8bd..03ffd2554 100644 --- a/src/gui/CheckListWidget.cxx +++ b/src/gui/CheckListWidget.cxx @@ -87,7 +87,6 @@ void CheckListWidget::drawWidget(bool hilite) //cerr << "CheckListWidget::drawWidget\n"; FBSurface& s = _boss->dialog().surface(); int i, pos, len = (int)_list.size(); - string buffer; // Draw a thin frame around the list and to separate columns s.hLine(_x, _y, _x + _w - 1, kColor); @@ -121,17 +120,12 @@ void CheckListWidget::drawWidget(bool hilite) if (_selectedItem == pos && _editMode) { - buffer = _editString; adjustOffset(); - - s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor, + s.drawString(_font, editString(), _x + r.left, y, r.width(), kTextColor, kTextAlignLeft, -_editScrollOffset, false); } else - { - buffer = _list[pos]; - s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor); - } + s.drawString(_font, _list[pos], _x + r.left, y, r.width(), kTextColor); } // Only draw the caret while editing, and if it's in the current viewport diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 3058a1591..288818873 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -90,7 +90,7 @@ void Dialog::close(bool refresh) if (_mouseWidget) { _mouseWidget->handleMouseLeft(0); - _mouseWidget = 0; + _mouseWidget = nullptr; } releaseFocus(); @@ -118,7 +118,7 @@ void Dialog::releaseFocus() if(_focusedWidget) { _focusedWidget->lostFocus(); - _focusedWidget = 0; + _focusedWidget = nullptr; } } @@ -253,24 +253,12 @@ void Dialog::buildCurrentFocusList(int tabID) _focusedWidget = _focusList[0]; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::redrawFocus() -{ - if(_focusedWidget) - _focusedWidget = Widget::setFocusForChain(this, getFocusList(), _focusedWidget, 0); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::addSurface(shared_ptr surface) { mySurfaceStack.push(surface); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::draw() -{ -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::drawDialog() { @@ -298,7 +286,11 @@ void Dialog::drawDialog() } // Draw outlines for focused widgets - redrawFocus(); + // Don't change focus, since this will trigger lost and received + // focus events + if(_focusedWidget) + _focusedWidget = Widget::setFocusForChain(this, getFocusList(), + _focusedWidget, 0, false); // Tell the surface(s) this area is dirty s.setDirty(); diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 8eea48913..0cc65a016 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -59,17 +59,16 @@ class Dialog : public GuiObject virtual void center(); virtual void drawDialog(); - virtual void loadConfig() {} - virtual void saveConfig() {} - virtual void setDefaults() {} + virtual void loadConfig() { } + virtual void saveConfig() { } + virtual void setDefaults() { } void addFocusWidget(Widget* w); void addToFocusList(WidgetArray& list); void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; } - void redrawFocus(); void addTabWidget(TabWidget* w); - void addOKWidget(Widget* w) { _okWidget = w; } + void addOKWidget(Widget* w) { _okWidget = w; } void addCancelWidget(Widget* w) { _cancelWidget = w; } void setFocus(Widget* w); @@ -84,7 +83,7 @@ class Dialog : public GuiObject void addSurface(shared_ptr surface); protected: - virtual void draw(); + virtual void draw() { }; void releaseFocus(); virtual void handleText(char text); diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index 3e98ca33f..1529f6421 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -47,7 +47,7 @@ void EditTextWidget::setText(const string& str, bool changed) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) { - if(!_editable) + if(!isEditable()) return; x += _editScrollOffset; @@ -55,9 +55,9 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) int width = 0; uInt32 i; - for (i = 0; i < _editString.size(); ++i) + for (i = 0; i < editString().size(); ++i) { - width += _font.getCharWidth(_editString[i]); + width += _font.getCharWidth(editString()[i]); if (width >= x) break; } @@ -69,7 +69,6 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EditTextWidget::drawWidget(bool hilite) { -//cerr << "EditTextWidget::drawWidget\n"; FBSurface& s = _boss->dialog().surface(); // Highlight changes @@ -84,7 +83,7 @@ void EditTextWidget::drawWidget(bool hilite) // Draw the text adjustOffset(); - s.drawString(_font, _editString, _x + 2, _y + 2, getEditRect().width(), + s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().width(), !_changed ? _textcolor : kDbgChangedTextColor, kTextAlignLeft, -_editScrollOffset, false); @@ -103,7 +102,7 @@ GUI::Rect EditTextWidget::getEditRect() const void EditTextWidget::lostFocusWidget() { // If we loose focus, 'commit' the user changes - _backupString = _editString; + _backupString = editString(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 99ffe31ed..7e6d2bc96 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -65,9 +65,6 @@ void EditableWidget::setText(const string& str, bool) if (_editScrollOffset < 0) _editScrollOffset = 0; - if(_editable) - startEditMode(); - setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -198,7 +195,6 @@ int EditableWidget::getCaretOffset() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EditableWidget::drawCaret() { -//cerr << "EditableWidget::drawCaret()\n"; // Only draw if item is visible if (!_editable || !isVisible() || !_boss->isVisible() || !_hasFocus) return; diff --git a/src/gui/EditableWidget.hxx b/src/gui/EditableWidget.hxx index ec1ef46d9..c34f74e61 100644 --- a/src/gui/EditableWidget.hxx +++ b/src/gui/EditableWidget.hxx @@ -28,11 +28,15 @@ /** * Base class for widgets which need to edit text, like ListWidget and * EditTextWidget. + * + * Widgets wishing to enforce their own editing restrictions are able + * to use a 'TextFilter' as described below. */ class EditableWidget : public Widget, public CommandSender { public: - /** Function used by 'tryInsertChar' to test validity of a character */ + /** Function used to test if a specified character can be inserted + into the internal buffer */ using TextFilter = std::function; enum { @@ -47,7 +51,7 @@ class EditableWidget : public Widget, public CommandSender virtual ~EditableWidget(); virtual void setText(const string& str, bool changed = false); - virtual const string& getText() const { return _editString; } + const string& getText() const { return _editString; } bool isEditable() const { return _editable; } void setEditable(bool editable); @@ -58,7 +62,7 @@ class EditableWidget : public Widget, public CommandSender // We only want to focus this widget when we can edit its contents virtual bool wantsFocus() { return _editable; } - // Set filter used by 'tryInsertChar' + // Set filter used to test whether a character can be inserted void setTextFilter(TextFilter& filter) { _filter = filter; } protected: @@ -71,11 +75,10 @@ class EditableWidget : public Widget, public CommandSender void drawCaret(); bool setCaretPos(int newPos); bool adjustOffset(); - - // This method will use the current TextFilter to insert a character - // Note that classes which override this method will no longer use the - // current TextFilter, and will assume all responsibility for filtering - virtual bool tryInsertChar(char c, int pos); + + // This method is used internally by child classes wanting to + // access/edit the internal buffer + string& editString() { return _editString; } private: // Line editing @@ -89,7 +92,11 @@ class EditableWidget : public Widget, public CommandSender void copySelectedText(); void pasteSelectedText(); - protected: + // Use the current TextFilter to insert a character into the + // internal buffer + bool tryInsertChar(char c, int pos); + + private: bool _editable; string _editString; @@ -97,6 +104,7 @@ class EditableWidget : public Widget, public CommandSender int _caretTime; int _caretPos; + protected: bool _caretInverse; int _editScrollOffset; diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index 54789a61d..f512b2584 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -225,7 +225,7 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) sendCommand(ListWidget::kDoubleClickedCmd, _selectedItem, _id); // Start edit mode - if(_editable && !_editMode) + if(isEditable() && !_editMode) startEditMode(); } } @@ -346,7 +346,7 @@ bool ListWidget::handleEvent(Event::Type e) case Event::UISelect: if (_selectedItem >= 0) { - if (_editable) + if (isEditable()) startEditMode(); else sendCommand(ListWidget::kActivatedCmd, _selectedItem, _id); @@ -462,7 +462,7 @@ void ListWidget::scrollToCurrent(int item) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ListWidget::startEditMode() { - if (_editable && !_editMode && _selectedItem >= 0) + if (isEditable() && !_editMode && _selectedItem >= 0) { _editMode = true; setText(_list[_selectedItem]); @@ -480,7 +480,7 @@ void ListWidget::endEditMode() // Send a message that editing finished with a return/enter key press _editMode = false; - _list[_selectedItem] = _editString; + _list[_selectedItem] = editString(); sendCommand(ListWidget::kDataChangedCmd, _selectedItem, _id); // Reset to normal data entry diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index 4003cba8a..37db654aa 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -49,7 +49,6 @@ void StringListWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); int i, pos, len = (int)_list.size(); - string buffer; // Draw a thin frame around the list. s.hLine(_x, _y, _x + _w - 1, kColor); @@ -73,17 +72,12 @@ void StringListWidget::drawWidget(bool hilite) GUI::Rect r(getEditRect()); if (_selectedItem == pos && _editMode) { - buffer = _editString; adjustOffset(); - - s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor, + s.drawString(_font, editString(), _x + r.left, y, r.width(), kTextColor, kTextAlignLeft, -_editScrollOffset, false); } else - { - buffer = _list[pos]; - s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor); - } + s.drawString(_font, _list[pos], _x + r.left, y, r.width(), kTextColor); } // Only draw the caret while editing, and if it's in the current viewport diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 2d193e027..e471ad4ab 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -197,7 +197,8 @@ bool Widget::isWidgetInChain(WidgetArray& list, Widget* find) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, - Widget* wid, int direction) + Widget* wid, int direction, + bool emitFocusEvents) { FBSurface& s = boss->dialog().surface(); int size = (int)arr.size(), pos = -1; @@ -220,7 +221,11 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, // First clear area surrounding all widgets if(tmp->_hasFocus) { - tmp->lostFocus(); + if(emitFocusEvents) + tmp->lostFocus(); + else + tmp->_hasFocus = false; + s.frameRect(x, y, w, h, kDlgColor); tmp->setDirty(); @@ -230,7 +235,7 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, // Figure out which which should be active if(pos == -1) - return 0; + return nullptr; else { switch(direction) @@ -263,7 +268,11 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr, int x = tmp->getAbsX() - 1, y = tmp->getAbsY() - 1, w = tmp->getWidth() + 2, h = tmp->getHeight() + 2; - tmp->receivedFocus(); + if(emitFocusEvents) + tmp->receivedFocus(); + else + tmp->_hasFocus = true; + s.frameRect(x, y, w, h, kWidFrameColor, kDashLine); tmp->setDirty(); diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 8fd936f57..f4f89ca76 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -152,7 +152,8 @@ class Widget : public GuiObject /** Select either previous, current, or next widget in chain to have focus, and deselects all others */ static Widget* setFocusForChain(GuiObject* boss, WidgetArray& arr, - Widget* w, int direction); + Widget* w, int direction, + bool emitFocusEvents = true); /** Sets all widgets in this chain to be dirty (must be redrawn) */ static void setDirtyInChain(Widget* start);