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
This commit is contained in:
stephena 2015-04-22 15:02:17 +00:00
parent 8232045971
commit 72ec5f2371
17 changed files with 161 additions and 199 deletions

View File

@ -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)

View File

@ -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

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "4.7_pre"
#define STELLA_VERSION "4.6.1_pre"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -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,9 +643,9 @@ int DataGridWidget::getWidth() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::startEditMode()
{
if (_editable && !_editMode && _selectedItem >= 0)
if (isEditable() && !_editMode && _selectedItem >= 0)
{
_editMode = true;
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)
if(_editMode)
{
// 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;
// Undo any changes made
assert(_selectedItem >= 0);
enableEditMode(false);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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

View File

@ -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 == "")

View File

@ -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); }

View File

@ -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

View File

@ -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<FBSurface> 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();

View File

@ -67,7 +67,6 @@ class Dialog : public GuiObject
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 addCancelWidget(Widget* w) { _cancelWidget = w; }
@ -84,7 +83,7 @@ class Dialog : public GuiObject
void addSurface(shared_ptr<FBSurface> surface);
protected:
virtual void draw();
virtual void draw() { };
void releaseFocus();
virtual void handleText(char text);

View File

@ -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();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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;

View File

@ -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<bool(char)>;
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:
@ -72,10 +76,9 @@ class EditableWidget : public Widget, public CommandSender
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;

View File

@ -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

View File

@ -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

View File

@ -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)
{
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;
if(emitFocusEvents)
tmp->receivedFocus();
else
tmp->_hasFocus = true;
s.frameRect(x, y, w, h, kWidFrameColor, kDashLine);
tmp->setDirty();

View File

@ -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);