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 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) 4.5 to 4.6: (March 21, 2015)
* Finally fixed fullscreen rendering issues on some OpenGL * Finally fixed fullscreen rendering issues on some OpenGL
@ -46,8 +54,6 @@
* Updated included PNG library to latest stable version. * Updated included PNG library to latest stable version.
-Have fun!
4.2 to 4.5: (January 1, 2015) 4.2 to 4.5: (January 1, 2015)

View File

@ -51,7 +51,7 @@ else
endif endif
CXXFLAGS+= -Wall CXXFLAGS+= -Wall
ifdef HAVE_GCC 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 endif
ifdef PROFILE ifdef PROFILE

View File

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

View File

@ -82,6 +82,24 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
_scrollBar->_entriesPerPage = 1; _scrollBar->_entriesPerPage = 1;
_scrollBar->_wheel_lines = 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() << ", _valueStringList.size() = " << _valueStringList.size()
<< ", _rows*_cols = " << _rows * _cols << endl << endl; << ", _rows*_cols = " << _rows * _cols << endl << endl;
*/ */
_editMode = false; enableEditMode(false);
// Send item selected signal for starting with cell 0 // Send item selected signal for starting with cell 0
sendCommand(DataGridWidget::kSelectionChangedCmd, _selectedItem, _id); 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()) if(position >= 0 && uInt32(position) < _valueList.size())
{ {
// Correctly format the data for viewing // 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; _changedList[position] = changed;
_valueList[position] = value; _valueList[position] = value;
@ -248,7 +266,7 @@ void DataGridWidget::handleMouseUp(int x, int y, int button, int clickCount)
sendCommand(DataGridWidget::kItemDoubleClickedCmd, _selectedItem, _id); sendCommand(DataGridWidget::kItemDoubleClickedCmd, _selectedItem, _id);
// Start edit mode // Start edit mode
if(_editable && !_editMode) if(isEditable() && !_editMode)
startEditMode(); startEditMode();
} }
} }
@ -258,7 +276,7 @@ void DataGridWidget::handleMouseWheel(int x, int y, int direction)
{ {
if(_scrollBar) if(_scrollBar)
_scrollBar->handleMouseWheel(x, y, direction); _scrollBar->handleMouseWheel(x, y, direction);
else if(_editable) else if(isEditable())
{ {
if(direction > 0) if(direction > 0)
decrementCell(); decrementCell();
@ -413,39 +431,39 @@ bool DataGridWidget::handleKeyDown(StellaKey key, StellaMod mod)
break; break;
case KBDK_N: // negate case KBDK_N: // negate
if(_editable) if(isEditable())
negateCell(); negateCell();
break; break;
case KBDK_I: // invert case KBDK_I: // invert
if(_editable) if(isEditable())
invertCell(); invertCell();
break; break;
case KBDK_MINUS: // decrement case KBDK_MINUS: // decrement
case KBDK_KP_MINUS: case KBDK_KP_MINUS:
if(_editable) if(isEditable())
decrementCell(); decrementCell();
break; break;
case KBDK_EQUALS: // increment case KBDK_EQUALS: // increment
case KBDK_KP_PLUS: case KBDK_KP_PLUS:
if(_editable) if(isEditable())
incrementCell(); incrementCell();
break; break;
case KBDK_COMMA: // shift left case KBDK_COMMA: // shift left
if(_editable) if(isEditable())
lshiftCell(); lshiftCell();
break; break;
case KBDK_PERIOD: // shift right case KBDK_PERIOD: // shift right
if(_editable) if(isEditable())
rshiftCell(); rshiftCell();
break; break;
case KBDK_Z: // zero case KBDK_Z: // zero
if(_editable) if(isEditable())
zeroCell(); zeroCell();
break; break;
@ -491,7 +509,7 @@ void DataGridWidget::receivedFocusWidget()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::lostFocusWidget() void DataGridWidget::lostFocusWidget()
{ {
_editMode = false; enableEditMode(false);
// Disable the operations widget // Disable the operations widget
if(_opsWidget) if(_opsWidget)
@ -542,7 +560,6 @@ void DataGridWidget::handleCommand(CommandSender* sender, int cmd,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::drawWidget(bool hilite) void DataGridWidget::drawWidget(bool hilite)
{ {
//cerr << "DataGridWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
int row, col; int row, col;
@ -571,8 +588,7 @@ void DataGridWidget::drawWidget(bool hilite)
if (_selectedItem == pos && _editMode) if (_selectedItem == pos && _editMode)
{ {
adjustOffset(); adjustOffset();
s.drawString(_font, editString(), x, y, _colWidth, kTextColor,
s.drawString(_font, _editString, x, y, _colWidth, kTextColor,
kTextAlignLeft, -_editScrollOffset, false); kTextAlignLeft, -_editScrollOffset, false);
} }
else else
@ -627,9 +643,9 @@ int DataGridWidget::getWidth() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::startEditMode() 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 setText("", true); // Erase current entry when starting editing
} }
} }
@ -640,11 +656,11 @@ void DataGridWidget::endEditMode()
if (!_editMode) if (!_editMode)
return; return;
_editMode = false; enableEditMode(false);
// Update the both the string representation and the real data // Update the both the string representation and the real data
if(_editString.size() > 0 && !(_editString[0] == '$' || if(editString().size() > 0 && !(editString()[0] == '$' ||
_editString[0] == '#' || _editString[0] == '\\')) editString()[0] == '#' || editString()[0] == '\\'))
{ {
switch(_base) switch(_base)
{ {
@ -653,21 +669,21 @@ void DataGridWidget::endEditMode()
case Common::Base::F_16_2: case Common::Base::F_16_2:
case Common::Base::F_16_4: case Common::Base::F_16_4:
case Common::Base::F_16_8: case Common::Base::F_16_8:
_editString.insert(0, 1, '$'); editString().insert(0, 1, '$');
break; break;
case Common::Base::F_2: case Common::Base::F_2:
case Common::Base::F_2_8: case Common::Base::F_2_8:
case Common::Base::F_2_16: case Common::Base::F_2_16:
_editString.insert(0, 1, '\\'); editString().insert(0, 1, '\\');
break; break;
case Common::Base::F_10: case Common::Base::F_10:
_editString.insert(0, 1, '#'); editString().insert(0, 1, '#');
break; break;
case Common::Base::F_DEFAULT: case Common::Base::F_DEFAULT:
break; break;
} }
} }
int value = instance().debugger().stringToValue(_editString); int value = instance().debugger().stringToValue(editString());
if(value < _lowerBound || value >= _upperBound) if(value < _lowerBound || value >= _upperBound)
{ {
abortEditMode(); abortEditMode();
@ -680,42 +696,12 @@ void DataGridWidget::endEditMode()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::abortEditMode() void DataGridWidget::abortEditMode()
{ {
// undo any changes made if(_editMode)
assert(_selectedItem >= 0);
_editMode = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DataGridWidget::tryInsertChar(char c, int pos)
{ {
// Input is very strict here, to eliminate time-consuming error checking // Undo any changes made
// elsewhere, and includes the following restrictions: assert(_selectedItem >= 0);
// Cannot contain spaces enableEditMode(false);
// 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;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -71,21 +71,10 @@ class DataGridWidget : public EditableWidget
void setRange(int lower, int upper); void setRange(int lower, int upper);
virtual void handleMouseDown(int x, int y, int button, int clickCount); bool wantsFocus() { return true; }
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; }
// Account for the extra width of embedded scrollbar // Account for the extra width of embedded scrollbar
virtual int getWidth() const; int getWidth() const;
void startEditMode();
void endEditMode();
int colWidth() { return _colWidth; } int colWidth() { return _colWidth; }
@ -96,6 +85,8 @@ class DataGridWidget : public EditableWidget
int findItem(int x, int y); int findItem(int x, int y);
void startEditMode();
void endEditMode();
void abortEditMode(); void abortEditMode();
GUI::Rect getEditRect() const; GUI::Rect getEditRect() const;
@ -103,7 +94,13 @@ class DataGridWidget : public EditableWidget
void receivedFocusWidget(); void receivedFocusWidget();
void lostFocusWidget(); 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: protected:
int _rows; int _rows;
@ -141,6 +138,8 @@ class DataGridWidget : public EditableWidget
void lshiftCell(); void lshiftCell();
void rshiftCell(); void rshiftCell();
void zeroCell(); void zeroCell();
void enableEditMode(bool state) { _editMode = state; }
}; };
#endif #endif

View File

@ -88,6 +88,33 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
myCheckList.push_back(t); 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 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))) if (clickCount == 2 && (_selectedItem == findItem(x, y)))
{ {
// Start edit mode // Start edit mode
if(_editable && !_editMode) if(isEditable() && !_editMode)
startEditMode(); startEditMode();
} }
} }
@ -345,7 +363,7 @@ bool RomListWidget::handleEvent(Event::Type e)
case Event::UISelect: case Event::UISelect:
if (_selectedItem >= 0) if (_selectedItem >= 0)
{ {
if (_editable) if (isEditable())
startEditMode(); startEditMode();
} }
break; break;
@ -431,7 +449,6 @@ void RomListWidget::lostFocusWidget()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListWidget::drawWidget(bool hilite) void RomListWidget::drawWidget(bool hilite)
{ {
//cerr << "RomListWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
const CartDebug::DisassemblyList& dlist = myDisasm->list; const CartDebug::DisassemblyList& dlist = myDisasm->list;
int i, pos, xpos, ypos, len = (int)dlist.size(); int i, pos, xpos, ypos, len = (int)dlist.size();
@ -506,7 +523,7 @@ void RomListWidget::drawWidget(bool hilite)
if (_selectedItem == pos && _editMode) if (_selectedItem == pos && _editMode)
{ {
adjustOffset(); 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); kTextAlignLeft, -_editScrollOffset, false);
drawCaret(); drawCaret();
@ -553,44 +570,10 @@ GUI::Rect RomListWidget::getEditRect() const
return r; 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() void RomListWidget::startEditMode()
{ {
if (_editable && !_editMode && _selectedItem >= 0) if (isEditable() && !_editMode && _selectedItem >= 0)
{ {
// Does this line represent an editable area? // Does this line represent an editable area?
if(myDisasm->list[_selectedItem].bytes == "") if(myDisasm->list[_selectedItem].bytes == "")

View File

@ -59,10 +59,6 @@ class RomListWidget : public EditableWidget
void setSelected(int item); void setSelected(int item);
void setHighlighted(int item); void setHighlighted(int item);
const string& getText() const;
void startEditMode();
void endEditMode();
protected: protected:
void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseUp(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; int findItem(int x, int y) const;
void recalc(); void recalc();
bool tryInsertChar(char c, int pos); void startEditMode();
void endEditMode();
void abortEditMode(); void abortEditMode();
void lostFocusWidget(); void lostFocusWidget();
void scrollToSelected() { scrollToCurrent(_selectedItem); } void scrollToSelected() { scrollToCurrent(_selectedItem); }

View File

@ -87,7 +87,6 @@ void CheckListWidget::drawWidget(bool hilite)
//cerr << "CheckListWidget::drawWidget\n"; //cerr << "CheckListWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
int i, pos, len = (int)_list.size(); int i, pos, len = (int)_list.size();
string buffer;
// Draw a thin frame around the list and to separate columns // Draw a thin frame around the list and to separate columns
s.hLine(_x, _y, _x + _w - 1, kColor); s.hLine(_x, _y, _x + _w - 1, kColor);
@ -121,17 +120,12 @@ void CheckListWidget::drawWidget(bool hilite)
if (_selectedItem == pos && _editMode) if (_selectedItem == pos && _editMode)
{ {
buffer = _editString;
adjustOffset(); adjustOffset();
s.drawString(_font, editString(), _x + r.left, y, r.width(), kTextColor,
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor,
kTextAlignLeft, -_editScrollOffset, false); kTextAlignLeft, -_editScrollOffset, false);
} }
else else
{ s.drawString(_font, _list[pos], _x + r.left, y, r.width(), kTextColor);
buffer = _list[pos];
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor);
}
} }
// Only draw the caret while editing, and if it's in the current viewport // 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) if (_mouseWidget)
{ {
_mouseWidget->handleMouseLeft(0); _mouseWidget->handleMouseLeft(0);
_mouseWidget = 0; _mouseWidget = nullptr;
} }
releaseFocus(); releaseFocus();
@ -118,7 +118,7 @@ void Dialog::releaseFocus()
if(_focusedWidget) if(_focusedWidget)
{ {
_focusedWidget->lostFocus(); _focusedWidget->lostFocus();
_focusedWidget = 0; _focusedWidget = nullptr;
} }
} }
@ -253,24 +253,12 @@ void Dialog::buildCurrentFocusList(int tabID)
_focusedWidget = _focusList[0]; _focusedWidget = _focusList[0];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::redrawFocus()
{
if(_focusedWidget)
_focusedWidget = Widget::setFocusForChain(this, getFocusList(), _focusedWidget, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::addSurface(shared_ptr<FBSurface> surface) void Dialog::addSurface(shared_ptr<FBSurface> surface)
{ {
mySurfaceStack.push(surface); mySurfaceStack.push(surface);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::draw()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::drawDialog() void Dialog::drawDialog()
{ {
@ -298,7 +286,11 @@ void Dialog::drawDialog()
} }
// Draw outlines for focused widgets // 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 // Tell the surface(s) this area is dirty
s.setDirty(); s.setDirty();

View File

@ -67,7 +67,6 @@ class Dialog : public GuiObject
void addToFocusList(WidgetArray& list); void addToFocusList(WidgetArray& list);
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; } void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; }
void redrawFocus();
void addTabWidget(TabWidget* w); void addTabWidget(TabWidget* w);
void addOKWidget(Widget* w) { _okWidget = w; } void addOKWidget(Widget* w) { _okWidget = w; }
void addCancelWidget(Widget* w) { _cancelWidget = w; } void addCancelWidget(Widget* w) { _cancelWidget = w; }
@ -84,7 +83,7 @@ class Dialog : public GuiObject
void addSurface(shared_ptr<FBSurface> surface); void addSurface(shared_ptr<FBSurface> surface);
protected: protected:
virtual void draw(); virtual void draw() { };
void releaseFocus(); void releaseFocus();
virtual void handleText(char text); 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) void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount)
{ {
if(!_editable) if(!isEditable())
return; return;
x += _editScrollOffset; x += _editScrollOffset;
@ -55,9 +55,9 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount)
int width = 0; int width = 0;
uInt32 i; 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) if (width >= x)
break; break;
} }
@ -69,7 +69,6 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::drawWidget(bool hilite) void EditTextWidget::drawWidget(bool hilite)
{ {
//cerr << "EditTextWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
// Highlight changes // Highlight changes
@ -84,7 +83,7 @@ void EditTextWidget::drawWidget(bool hilite)
// Draw the text // Draw the text
adjustOffset(); adjustOffset();
s.drawString(_font, _editString, _x + 2, _y + 2, getEditRect().width(), s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().width(),
!_changed ? _textcolor : kDbgChangedTextColor, !_changed ? _textcolor : kDbgChangedTextColor,
kTextAlignLeft, -_editScrollOffset, false); kTextAlignLeft, -_editScrollOffset, false);
@ -103,7 +102,7 @@ GUI::Rect EditTextWidget::getEditRect() const
void EditTextWidget::lostFocusWidget() void EditTextWidget::lostFocusWidget()
{ {
// If we loose focus, 'commit' the user changes // 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) if (_editScrollOffset < 0)
_editScrollOffset = 0; _editScrollOffset = 0;
if(_editable)
startEditMode();
setDirty(); setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -198,7 +195,6 @@ int EditableWidget::getCaretOffset() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditableWidget::drawCaret() void EditableWidget::drawCaret()
{ {
//cerr << "EditableWidget::drawCaret()\n";
// Only draw if item is visible // Only draw if item is visible
if (!_editable || !isVisible() || !_boss->isVisible() || !_hasFocus) if (!_editable || !isVisible() || !_boss->isVisible() || !_hasFocus)
return; return;

View File

@ -28,11 +28,15 @@
/** /**
* Base class for widgets which need to edit text, like ListWidget and * Base class for widgets which need to edit text, like ListWidget and
* EditTextWidget. * EditTextWidget.
*
* Widgets wishing to enforce their own editing restrictions are able
* to use a 'TextFilter' as described below.
*/ */
class EditableWidget : public Widget, public CommandSender class EditableWidget : public Widget, public CommandSender
{ {
public: 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)>; using TextFilter = std::function<bool(char)>;
enum { enum {
@ -47,7 +51,7 @@ class EditableWidget : public Widget, public CommandSender
virtual ~EditableWidget(); virtual ~EditableWidget();
virtual void setText(const string& str, bool changed = false); 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; } bool isEditable() const { return _editable; }
void setEditable(bool 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 // We only want to focus this widget when we can edit its contents
virtual bool wantsFocus() { return _editable; } 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; } void setTextFilter(TextFilter& filter) { _filter = filter; }
protected: protected:
@ -72,10 +76,9 @@ class EditableWidget : public Widget, public CommandSender
bool setCaretPos(int newPos); bool setCaretPos(int newPos);
bool adjustOffset(); bool adjustOffset();
// This method will use the current TextFilter to insert a character // This method is used internally by child classes wanting to
// Note that classes which override this method will no longer use the // access/edit the internal buffer
// current TextFilter, and will assume all responsibility for filtering string& editString() { return _editString; }
virtual bool tryInsertChar(char c, int pos);
private: private:
// Line editing // Line editing
@ -89,7 +92,11 @@ class EditableWidget : public Widget, public CommandSender
void copySelectedText(); void copySelectedText();
void pasteSelectedText(); void pasteSelectedText();
protected: // Use the current TextFilter to insert a character into the
// internal buffer
bool tryInsertChar(char c, int pos);
private:
bool _editable; bool _editable;
string _editString; string _editString;
@ -97,6 +104,7 @@ class EditableWidget : public Widget, public CommandSender
int _caretTime; int _caretTime;
int _caretPos; int _caretPos;
protected:
bool _caretInverse; bool _caretInverse;
int _editScrollOffset; int _editScrollOffset;

View File

@ -225,7 +225,7 @@ void ListWidget::handleMouseUp(int x, int y, int button, int clickCount)
sendCommand(ListWidget::kDoubleClickedCmd, _selectedItem, _id); sendCommand(ListWidget::kDoubleClickedCmd, _selectedItem, _id);
// Start edit mode // Start edit mode
if(_editable && !_editMode) if(isEditable() && !_editMode)
startEditMode(); startEditMode();
} }
} }
@ -346,7 +346,7 @@ bool ListWidget::handleEvent(Event::Type e)
case Event::UISelect: case Event::UISelect:
if (_selectedItem >= 0) if (_selectedItem >= 0)
{ {
if (_editable) if (isEditable())
startEditMode(); startEditMode();
else else
sendCommand(ListWidget::kActivatedCmd, _selectedItem, _id); sendCommand(ListWidget::kActivatedCmd, _selectedItem, _id);
@ -462,7 +462,7 @@ void ListWidget::scrollToCurrent(int item)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ListWidget::startEditMode() void ListWidget::startEditMode()
{ {
if (_editable && !_editMode && _selectedItem >= 0) if (isEditable() && !_editMode && _selectedItem >= 0)
{ {
_editMode = true; _editMode = true;
setText(_list[_selectedItem]); setText(_list[_selectedItem]);
@ -480,7 +480,7 @@ void ListWidget::endEditMode()
// Send a message that editing finished with a return/enter key press // Send a message that editing finished with a return/enter key press
_editMode = false; _editMode = false;
_list[_selectedItem] = _editString; _list[_selectedItem] = editString();
sendCommand(ListWidget::kDataChangedCmd, _selectedItem, _id); sendCommand(ListWidget::kDataChangedCmd, _selectedItem, _id);
// Reset to normal data entry // Reset to normal data entry

View File

@ -49,7 +49,6 @@ void StringListWidget::drawWidget(bool hilite)
{ {
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
int i, pos, len = (int)_list.size(); int i, pos, len = (int)_list.size();
string buffer;
// Draw a thin frame around the list. // Draw a thin frame around the list.
s.hLine(_x, _y, _x + _w - 1, kColor); s.hLine(_x, _y, _x + _w - 1, kColor);
@ -73,17 +72,12 @@ void StringListWidget::drawWidget(bool hilite)
GUI::Rect r(getEditRect()); GUI::Rect r(getEditRect());
if (_selectedItem == pos && _editMode) if (_selectedItem == pos && _editMode)
{ {
buffer = _editString;
adjustOffset(); adjustOffset();
s.drawString(_font, editString(), _x + r.left, y, r.width(), kTextColor,
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor,
kTextAlignLeft, -_editScrollOffset, false); kTextAlignLeft, -_editScrollOffset, false);
} }
else else
{ s.drawString(_font, _list[pos], _x + r.left, y, r.width(), kTextColor);
buffer = _list[pos];
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor);
}
} }
// Only draw the caret while editing, and if it's in the current viewport // 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* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
Widget* wid, int direction) Widget* wid, int direction,
bool emitFocusEvents)
{ {
FBSurface& s = boss->dialog().surface(); FBSurface& s = boss->dialog().surface();
int size = (int)arr.size(), pos = -1; int size = (int)arr.size(), pos = -1;
@ -220,7 +221,11 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
// First clear area surrounding all widgets // First clear area surrounding all widgets
if(tmp->_hasFocus) if(tmp->_hasFocus)
{ {
if(emitFocusEvents)
tmp->lostFocus(); tmp->lostFocus();
else
tmp->_hasFocus = false;
s.frameRect(x, y, w, h, kDlgColor); s.frameRect(x, y, w, h, kDlgColor);
tmp->setDirty(); tmp->setDirty();
@ -230,7 +235,7 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
// Figure out which which should be active // Figure out which which should be active
if(pos == -1) if(pos == -1)
return 0; return nullptr;
else else
{ {
switch(direction) switch(direction)
@ -263,7 +268,11 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
int x = tmp->getAbsX() - 1, y = tmp->getAbsY() - 1, int x = tmp->getAbsX() - 1, y = tmp->getAbsY() - 1,
w = tmp->getWidth() + 2, h = tmp->getHeight() + 2; w = tmp->getWidth() + 2, h = tmp->getHeight() + 2;
if(emitFocusEvents)
tmp->receivedFocus(); tmp->receivedFocus();
else
tmp->_hasFocus = true;
s.frameRect(x, y, w, h, kWidFrameColor, kDashLine); s.frameRect(x, y, w, h, kWidFrameColor, kDashLine);
tmp->setDirty(); tmp->setDirty();

View File

@ -152,7 +152,8 @@ class Widget : public GuiObject
/** Select either previous, current, or next widget in chain to have /** Select either previous, current, or next widget in chain to have
focus, and deselects all others */ focus, and deselects all others */
static Widget* setFocusForChain(GuiObject* boss, WidgetArray& arr, 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) */ /** Sets all widgets in this chain to be dirty (must be redrawn) */
static void setDirtyInChain(Widget* start); static void setDirtyInChain(Widget* start);