Added widget to Cheats area for changing memory. It's not quite working

correctly yet, but we're close.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@502 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-06-15 18:45:28 +00:00
parent 34c7e84d45
commit d6d73fff6f
6 changed files with 589 additions and 25 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES.
##
## $Id: makefile,v 1.96 2005-06-14 18:55:35 stephena Exp $
## $Id: makefile,v 1.97 2005-06-15 18:45:27 stephena Exp $
##============================================================================
##============================================================================
@ -157,7 +157,7 @@ M6502_OBJS = D6502.o Device.o M6502.o M6502Low.o M6502Hi.o NullDev.o System.o
GUI_OBJS = Font.o Menu.o Launcher.o \
Widget.o PopUpWidget.o ScrollBarWidget.o ListWidget.o TabWidget.o \
EditableWidget.o EditTextWidget.o EditNumWidget.o \
EditableWidget.o EditTextWidget.o EditNumWidget.o AddrValueWidget.o \
Dialog.o DialogContainer.o OptionsDialog.o VideoDialog.o AudioDialog.o \
EventMappingDialog.o GameInfoDialog.o HelpDialog.o AboutDialog.o \
LauncherDialog.o LauncherOptionsDialog.o BrowserDialog.o GameList.o \
@ -417,6 +417,9 @@ EditTextWidget.o: $(GUI)/EditTextWidget.cxx $(GUI)/EditTextWidget.hxx
EditNumWidget.o: $(GUI)/EditNumWidget.cxx $(GUI)/EditNumWidget.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/EditNumWidget.cxx
AddrValueWidget.o: $(GUI)/AddrValueWidget.cxx $(GUI)/AddrValueWidget.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/AddrValueWidget.cxx
Dialog.o: $(GUI)/Dialog.cxx $(GUI)/Dialog.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/Dialog.cxx

View File

@ -0,0 +1,451 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: AddrValueWidget.cxx,v 1.1 2005-06-15 18:45:28 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include <cctype>
#include <algorithm>
#include "OSystem.hxx"
#include "Widget.hxx"
#include "ScrollBarWidget.hxx"
#include "Dialog.hxx"
#include "FrameBuffer.hxx"
#include "AddrValueWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AddrValueWidget::AddrValueWidget(GuiObject* boss, int x, int y, int w, int h)
: EditableWidget(boss, x, y, w, h),
CommandSender(boss)
{
_w = w - kScrollBarWidth;
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS |
WIDGET_TAB_NAVIGATE;
_type = kListWidget; // we're just a slightly modified listwidget
_editMode = false;
_numberingMode = kHexNumbering;
_entriesPerPage = (_h - 2) / kLineHeight;
_currentPos = 0;
_selectedItem = -1;
_scrollBar = new ScrollBarWidget(boss, _x + _w, _y, kScrollBarWidth, _h);
_scrollBar->setTarget(this);
_currentKeyDown = 0;
_quickSelectTime = 0;
// The item is selected, thus _bgcolor is used to draw the caret and
// _textcolorhi to erase it
_caretInverse = true;
// FIXME: This flag should come from widget definition
_editable = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AddrValueWidget::~AddrValueWidget()
{
}
/*
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::setSelected(int item)
{
assert(item >= -1 && item < (int)_list.size());
if (isEnabled() && _selectedItem != item)
{
if (_editMode)
abortEditMode();
_selectedItem = item;
sendCommand(kAVSelectionChangedCmd, _selectedItem);
_currentPos = _selectedItem - _entriesPerPage / 2;
scrollToCurrent();
draw();
instance()->frameBuffer().refresh();
}
}
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::setList(const AddrList& alist, const ValueList& vlist)
{
_addrList.clear();
_valueList.clear();
_addrStringList.clear();
_valueStringList.clear();
_addrList = alist;
_valueList = vlist;
int size = _addrList.size(); // assume vlist is the same size
// An efficiency thing
char temp[10];
for(unsigned int i = 0; i < (unsigned int)size; ++i)
{
sprintf(temp, "%.4x:", _addrList[i]);
_addrStringList.push_back(temp);
sprintf(temp, "%.3d", _valueList[i]);
_valueStringList.push_back(temp);
}
if (_currentPos >= size)
_currentPos = size - 1;
if (_currentPos < 0)
_currentPos = 0;
_selectedItem = -1;
_editMode = false;
scrollBarRecalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::scrollTo(int item)
{
int size = _valueList.size();
if (item >= size)
item = size - 1;
if (item < 0)
item = 0;
if (_currentPos != item)
{
_currentPos = item;
scrollBarRecalc();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::scrollBarRecalc()
{
_scrollBar->_numEntries = _valueList.size();
_scrollBar->_entriesPerPage = _entriesPerPage;
_scrollBar->_currentPos = _currentPos;
_scrollBar->recalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::handleMouseDown(int x, int y, int button, int clickCount)
{
if (!isEnabled())
return;
// A click indicates this widget has been selected
// It should receive focus (because it has the WIDGET_TAB_NAVIGATE property)
receivedFocus();
// First check whether the selection changed
int newSelectedItem;
newSelectedItem = findItem(x, y);
if (newSelectedItem > (int)_valueList.size() - 1)
newSelectedItem = -1;
if (_selectedItem != newSelectedItem)
{
if (_editMode)
abortEditMode();
_selectedItem = newSelectedItem;
sendCommand(kAVSelectionChangedCmd, _selectedItem);
instance()->frameBuffer().refresh();
}
// TODO: Determine where inside the string the user clicked and place the
// caret accordingly. See _editScrollOffset and EditTextWidget::handleMouseDown.
draw();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::handleMouseUp(int x, int y, int button, int clickCount)
{
// If this was a double click and the mouse is still over the selected item,
// send the double click command
if (clickCount == 2 && (_selectedItem == findItem(x, y)))
{
sendCommand(kAVItemDoubleClickedCmd, _selectedItem);
// Start edit mode
if(_editable && !_editMode)
startEditMode();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::handleMouseWheel(int x, int y, int direction)
{
_scrollBar->handleMouseWheel(x, y, direction);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int AddrValueWidget::findItem(int x, int y) const
{
return (y - 1) / kLineHeight + _currentPos;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AddrValueWidget::handleKeyDown(int ascii, int keycode, int modifiers)
{
// Ignore all mod keys
if(instance()->eventHandler().kbdControl(modifiers) ||
instance()->eventHandler().kbdAlt(modifiers))
return true;
bool handled = true;
bool dirty = false;
int oldSelectedItem = _selectedItem;
if (_editMode)
{
// Class EditableWidget handles all text editing related key presses for us
handled = EditableWidget::handleKeyDown(ascii, keycode, modifiers);
}
else
{
// not editmode
switch (keycode)
{
case '\n': // enter/return
case '\r':
if (_selectedItem >= 0)
{
// override continuous enter keydown
if (_editable && (_currentKeyDown != '\n' && _currentKeyDown != '\r'))
{
dirty = true;
startEditMode();
}
else
sendCommand(kAVItemActivatedCmd, _selectedItem);
}
break;
case 256+17: // up arrow
if (_selectedItem > 0)
_selectedItem--;
break;
case 256+18: // down arrow
if (_selectedItem < (int)_valueList.size() - 1)
_selectedItem++;
break;
case 256+24: // pageup
_selectedItem -= _entriesPerPage - 1;
if (_selectedItem < 0)
_selectedItem = 0;
break;
case 256+25: // pagedown
_selectedItem += _entriesPerPage - 1;
if (_selectedItem >= (int)_valueList.size() )
_selectedItem = _valueList.size() - 1;
break;
case 256+22: // home
_selectedItem = 0;
break;
case 256+23: // end
_selectedItem = _valueList.size() - 1;
break;
default:
handled = false;
}
scrollToCurrent();
}
if (dirty || _selectedItem != oldSelectedItem)
draw();
if (_selectedItem != oldSelectedItem)
{
sendCommand(kAVSelectionChangedCmd, _selectedItem);
// also draw scrollbar
_scrollBar->draw();
instance()->frameBuffer().refresh();
}
_currentKeyDown = keycode;
return handled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AddrValueWidget::handleKeyUp(int ascii, int keycode, int modifiers)
{
if (keycode == _currentKeyDown)
_currentKeyDown = 0;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::lostFocusWidget()
{
_editMode = false;
draw();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::handleCommand(CommandSender* sender, int cmd, int data)
{
switch (cmd)
{
case kSetPositionCmd:
if (_currentPos != (int)data)
{
_currentPos = data;
draw();
}
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::drawWidget(bool hilite)
{
FrameBuffer& fb = _boss->instance()->frameBuffer();
int i, pos, len = _valueList.size();
string buffer;
int deltax;
// Draw a thin frame around the list.
fb.hLine(_x, _y, _x + _w - 1, kColor);
fb.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
fb.vLine(_x, _y, _y + _h - 1, kColor);
// Draw the list items
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++)
{
const OverlayColor textColor = (_selectedItem == pos && _editMode)
? kTextColor : kTextColor;
const int y = _y + 2 + kLineHeight * i;
// Draw the selected item inverted, on a highlighted background.
if (_selectedItem == pos)
{
if (_hasFocus && !_editMode)
fb.fillRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);
else
fb.frameRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);
}
// Print the address
fb.drawString(_font, _addrStringList[pos], _x + 2, y, _w - 4, textColor);
GUI::Rect r(getEditRect());
if (_selectedItem == pos && _editMode)
{
buffer = _editString;
adjustOffset();
deltax = -_editScrollOffset;
fb.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor,
kTextAlignLeft, deltax, false);
}
else
{
buffer = _valueStringList[pos];
deltax = 0;
fb.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor);
}
}
// Only draw the caret while editing, and if it's in the current viewport
if(_editMode && (_selectedItem >= _scrollBar->_currentPos) &&
(_selectedItem < _scrollBar->_currentPos + _entriesPerPage))
drawCaret();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GUI::Rect AddrValueWidget::getEditRect() const
{
GUI::Rect r(2, 1, _w - 2 , kLineHeight);
const int offset = (_selectedItem - _currentPos) * kLineHeight;
r.top += offset;
r.bottom += offset;
r.left += 9 * _font->getMaxCharWidth(); // address takes 9 characters
return r;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::scrollToCurrent()
{
// Only do something if the current item is not in our view port
if (_selectedItem < _currentPos)
{
// it's above our view
_currentPos = _selectedItem;
}
else if (_selectedItem >= _currentPos + _entriesPerPage )
{
// it's below our view
_currentPos = _selectedItem - _entriesPerPage + 1;
}
if (_currentPos < 0 || _entriesPerPage > (int)_valueList.size())
_currentPos = 0;
else if (_currentPos + _entriesPerPage > (int)_valueList.size())
_currentPos = _valueList.size() - _entriesPerPage;
_scrollBar->_currentPos = _currentPos;
_scrollBar->recalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::startEditMode()
{
cerr << "AddrValueWidget::startEditMode()\n";
if (_editable && !_editMode && _selectedItem >= 0)
{
_editMode = true;
setEditString(_valueStringList[_selectedItem]);
draw();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::endEditMode()
{
if (!_editMode)
return;
// send a message that editing finished with a return/enter key press
_editMode = false;
// Update the both the string representation and the real data
_valueStringList[_selectedItem] = _editString;
int value = atoi(_editString.c_str());
cerr << "new value: " << value << endl;
_valueList[_selectedItem] = value; // FIXME - do error checking
sendCommand(kAVItemDataChangedCmd, _selectedItem);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AddrValueWidget::abortEditMode()
{
cerr << "AddrValueWidget::abortEditMode()\n";
// undo any changes made
assert(_selectedItem >= 0);
_editMode = false;
}

View File

@ -0,0 +1,115 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: AddrValueWidget.hxx,v 1.1 2005-06-15 18:45:28 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef ADDR_VALUE_WIDGET_HXX
#define ADDR_VALUE_WIDGET_HXX
#include "GuiObject.hxx"
#include "Widget.hxx"
#include "Command.hxx"
#include "StringList.hxx"
#include "EditableWidget.hxx"
#include "Array.hxx"
#include "Rect.hxx"
class ScrollBarWidget;
typedef GUI::Array<int> AddrList;
typedef GUI::Array<int> ValueList;
enum NumberingMode {
kHexNumbering,
kDecimalNumbering,
kBinaryNumbering
};
// Some special commands
enum {
kAVItemDoubleClickedCmd = 'AVdb',
kAVItemActivatedCmd = 'AVac',
kAVItemDataChangedCmd = 'AVch',
kAVSelectionChangedCmd = 'AVsc'
};
/* AddrValueWidget */
class AddrValueWidget : public EditableWidget, public CommandSender
{
public:
AddrValueWidget(GuiObject* boss, int x, int y, int w, int h);
virtual ~AddrValueWidget();
void setList(const StringList& list);
void setList(const AddrList& alist, const ValueList& vlist);
// int getSelected() const { return _selectedItem; }
// void setSelected(int item);
// const string& getSelectedString() const { return _list[_selectedItem]; }
bool isEditable() const { return _editable; }
void setEditable(bool editable) { _editable = editable; }
void setNumberingMode(NumberingMode numberingMode) { _numberingMode = numberingMode; }
void scrollTo(int item);
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 handleKeyDown(int ascii, int keycode, int modifiers);
virtual bool handleKeyUp(int ascii, int keycode, int modifiers);
virtual void handleCommand(CommandSender* sender, int cmd, int data);
virtual bool wantsFocus() { return true; }
void startEditMode();
void endEditMode();
protected:
void drawWidget(bool hilite);
int findItem(int x, int y) const;
void scrollBarRecalc();
void abortEditMode();
GUI::Rect getEditRect() const;
void lostFocusWidget();
void scrollToCurrent();
protected:
AddrList _addrList;
ValueList _valueList;
StringList _addrStringList;
StringList _valueStringList;
bool _editable;
bool _editMode;
NumberingMode _numberingMode;
int _currentPos;
int _entriesPerPage;
int _selectedItem;
ScrollBarWidget* _scrollBar;
int _currentKeyDown;
string _backupString;
string _quickSelectStr;
int _quickSelectTime;
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CheatWidget.cxx,v 1.4 2005-06-15 15:34:35 stephena Exp $
// $Id: CheatWidget.cxx,v 1.5 2005-06-15 18:45:28 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -28,7 +28,7 @@
#include "Debugger.hxx"
#include "Widget.hxx"
#include "EditNumWidget.hxx"
#include "ListWidget.hxx"
#include "AddrValueWidget.hxx"
#include "CheatWidget.hxx"
@ -83,15 +83,13 @@ CheatWidget::CheatWidget(GuiObject* boss, int x, int y, int w, int h)
myRestartButton->setTarget(this);
// Add the list showing the results of a search/compare
// FIXME - change this to a AddrValueWidget (or something like that)
xpos = 200; ypos = border/2;
new StaticTextWidget(boss, xpos + 10, ypos, 70, kLineHeight,
"Address Value", kTextAlignLeft);
ypos += kLineHeight;
myResultsList = new ListWidget(boss, xpos, ypos, 100, 75);
myResultsList->setNumberingMode(kListNumberingOff);
myResultsList = new AddrValueWidget(boss, xpos, ypos, 100, 75);
myResultsList->setNumberingMode(kHexNumbering);
myResultsList->setFont(instance()->consoleFont());
myResultsList->setTarget(this);
@ -123,15 +121,15 @@ void CheatWidget::handleCommand(CommandSender* sender, int cmd, int data)
doRestart();
break;
case kListItemDataChangedCmd:
case kAVItemDataChangedCmd:
cerr << "data changed\n";
break;
case kListItemDoubleClickedCmd:
case kAVItemDoubleClickedCmd:
cerr << "kListItemDoubleClickedCmd\n";
break;
case kListItemActivatedCmd:
case kAVItemActivatedCmd:
cerr << "kListItemActivatedCmd\n";
break;
}
@ -300,17 +298,14 @@ void CheatWidget::doRestart()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatWidget::fillResultsList()
{
StringList l;
char buf[1024];
AddrList alist;
ValueList vlist;
// FIXME - add to an editable two-column widget instead
for(unsigned int i = 0; i < mySearchArray.size(); i++)
{
snprintf(buf, 1023, "%s : %3d",
Debugger::to_hex_16(kRamStart + mySearchArray[i].addr),
mySearchArray[i].value);
l.push_back(buf);
alist.push_back(kRamStart + mySearchArray[i].addr);
vlist.push_back(mySearchArray[i].value);
}
myResultsList->setList(l);
myResultsList->setList(alist, vlist);
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CheatWidget.hxx,v 1.3 2005-06-14 18:55:36 stephena Exp $
// $Id: CheatWidget.hxx,v 1.4 2005-06-15 18:45:28 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -26,7 +26,7 @@ class GuiObject;
class ButtonWidget;
class StaticTextWidget;
class EditNumWidget;
class ListWidget;
class AddrValueWidget;
#include "Array.hxx"
#include "Widget.hxx"
@ -71,7 +71,7 @@ class CheatWidget : public Widget, public CommandSender
ButtonWidget* myCompareButton;
ButtonWidget* myRestartButton;
ListWidget* myResultsList;
AddrValueWidget* myResultsList;
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: ListWidget.cxx,v 1.17 2005-06-15 15:48:09 stephena Exp $
// $Id: ListWidget.cxx,v 1.18 2005-06-15 18:45:28 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -357,8 +357,8 @@ 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)
? kBGColor : kTextColor;
const OverlayColor textColor = (_selectedItem == pos && _editMode)
? kColor : kTextColor;
const int y = _y + 2 + kLineHeight * i;
// Draw the selected item inverted, on a highlighted background.