mirror of https://github.com/stella-emu/stella.git
First pass at adding a cart-specific bankswitch/info tab to the
debugger. In the process, I had to spend several days extending the UI/dialog class to actually contain multiple tabs. This was harder than expected, and it still isn't quite finished. In many ways, we're beginning to reach the limits of the current code; it was never designed for a full-fledged, graphically rich UI. For now the tab is empty, but eventually it will contain general info about the ROM bankswitch type (size, virtual layout, etc), but also cart-specific info, including the ability to change banks, which can be vary greatly among the different schemes. Eventually, it may even allow to see/modify very cart-specific info (like display RAM in DPC, etc). Better handle errors in opening the serial port (AtariVox support) for Windows and OSX. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2678 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
fbf239798d
commit
ac1bccf454
|
@ -33,8 +33,8 @@ template <class T>
|
||||||
class Array
|
class Array
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
int _capacity;
|
uInt32 _capacity;
|
||||||
int _size;
|
uInt32 _size;
|
||||||
T *_data;
|
T *_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -48,7 +48,7 @@ class Array
|
||||||
_size = array._size;
|
_size = array._size;
|
||||||
_capacity = _size + 128;
|
_capacity = _size + 128;
|
||||||
_data = new T[_capacity];
|
_data = new T[_capacity];
|
||||||
for(int i = 0; i < _size; i++)
|
for(uInt32 i = 0; i < _size; i++)
|
||||||
_data[i] = array._data[i];
|
_data[i] = array._data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class Array
|
||||||
delete [] _data;
|
delete [] _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(int capacity)
|
void reserve(uInt32 capacity)
|
||||||
{
|
{
|
||||||
if(capacity <= _capacity)
|
if(capacity <= _capacity)
|
||||||
return;
|
return;
|
||||||
|
@ -74,11 +74,11 @@ class Array
|
||||||
void push_back(const Array<T>& array)
|
void push_back(const Array<T>& array)
|
||||||
{
|
{
|
||||||
ensureCapacity(_size + array._size);
|
ensureCapacity(_size + array._size);
|
||||||
for(int i = 0; i < array._size; i++)
|
for(uInt32 i = 0; i < array._size; i++)
|
||||||
_data[_size++] = array._data[i];
|
_data[_size++] = array._data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert_at(int idx, const T& element)
|
void insert_at(uInt32 idx, const T& element)
|
||||||
{
|
{
|
||||||
assert(idx >= 0 && idx <= _size);
|
assert(idx >= 0 && idx <= _size);
|
||||||
ensureCapacity(_size + 1);
|
ensureCapacity(_size + 1);
|
||||||
|
@ -87,30 +87,30 @@ class Array
|
||||||
// usually isn't correct (specifically, for any class which has a non-default
|
// usually isn't correct (specifically, for any class which has a non-default
|
||||||
// copy behaviour. E.g. the String class uses a refCounter which has to be
|
// copy behaviour. E.g. the String class uses a refCounter which has to be
|
||||||
// updated whenever a String is copied.
|
// updated whenever a String is copied.
|
||||||
for(int i = _size; i > idx; i--)
|
for(uInt32 i = _size; i > idx; i--)
|
||||||
_data[i] = _data[i-1];
|
_data[i] = _data[i-1];
|
||||||
|
|
||||||
_data[idx] = element;
|
_data[idx] = element;
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
T remove_at(int idx)
|
T remove_at(uInt32 idx)
|
||||||
{
|
{
|
||||||
assert(idx >= 0 && idx < _size);
|
assert(idx >= 0 && idx < _size);
|
||||||
T tmp = _data[idx];
|
T tmp = _data[idx];
|
||||||
for(int i = idx; i < _size - 1; i++)
|
for(uInt32 i = idx; i < _size - 1; i++)
|
||||||
_data[i] = _data[i+1];
|
_data[i] = _data[i+1];
|
||||||
_size--;
|
_size--;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator [](int idx)
|
T& operator [](uInt32 idx)
|
||||||
{
|
{
|
||||||
assert(idx >= 0 && idx < _size);
|
assert(idx >= 0 && idx < _size);
|
||||||
return _data[idx];
|
return _data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator [](int idx) const
|
const T& operator [](uInt32 idx) const
|
||||||
{
|
{
|
||||||
assert(idx >= 0 && idx < _size);
|
assert(idx >= 0 && idx < _size);
|
||||||
return _data[idx];
|
return _data[idx];
|
||||||
|
@ -123,14 +123,14 @@ class Array
|
||||||
_size = array._size;
|
_size = array._size;
|
||||||
_capacity = _size + 128;
|
_capacity = _size + 128;
|
||||||
_data = new T[_capacity];
|
_data = new T[_capacity];
|
||||||
for(int i = 0; i < _size; i++)
|
for(uInt32 i = 0; i < _size; i++)
|
||||||
_data[i] = array._data[i];
|
_data[i] = array._data[i];
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int size() const { return _size; }
|
uInt32 size() const { return _size; }
|
||||||
unsigned int capacity() const { return _capacity; }
|
uInt32 capacity() const { return _capacity; }
|
||||||
|
|
||||||
void clear(bool fullerase = true)
|
void clear(bool fullerase = true)
|
||||||
{
|
{
|
||||||
|
@ -172,7 +172,7 @@ class Array
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ensureCapacity(int new_len)
|
void ensureCapacity(uInt32 new_len)
|
||||||
{
|
{
|
||||||
if (new_len <= _capacity)
|
if (new_len <= _capacity)
|
||||||
return;
|
return;
|
||||||
|
@ -184,7 +184,7 @@ class Array
|
||||||
if (old_data)
|
if (old_data)
|
||||||
{
|
{
|
||||||
// Copy old data
|
// Copy old data
|
||||||
for (int i = 0; i < _size; i++)
|
for (uInt32 i = 0; i < _size; i++)
|
||||||
_data[i] = old_data[i];
|
_data[i] = old_data[i];
|
||||||
delete [] old_data;
|
delete [] old_data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ DebuggerDialog::DebuggerDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
int x, int y, int w, int h)
|
int x, int y, int w, int h)
|
||||||
: Dialog(osystem, parent, x, y, w, h, true), // use base surface
|
: Dialog(osystem, parent, x, y, w, h, true), // use base surface
|
||||||
myTab(NULL),
|
myTab(NULL),
|
||||||
|
myRomTab(NULL),
|
||||||
myFatalError(NULL)
|
myFatalError(NULL)
|
||||||
{
|
{
|
||||||
addTiaArea();
|
addTiaArea();
|
||||||
|
@ -72,7 +73,9 @@ void DebuggerDialog::loadConfig()
|
||||||
myTiaZoom->loadConfig();
|
myTiaZoom->loadConfig();
|
||||||
myCpu->loadConfig();
|
myCpu->loadConfig();
|
||||||
myRam->loadConfig();
|
myRam->loadConfig();
|
||||||
myRom->loadConfig();
|
|
||||||
|
myRomTab->loadConfig();
|
||||||
|
// myRom->loadConfig();
|
||||||
|
|
||||||
myMessageBox->setEditString("");
|
myMessageBox->setEditString("");
|
||||||
}
|
}
|
||||||
|
@ -176,12 +179,14 @@ void DebuggerDialog::addTiaArea()
|
||||||
void DebuggerDialog::addTabArea()
|
void DebuggerDialog::addTabArea()
|
||||||
{
|
{
|
||||||
const GUI::Rect& r = instance().debugger().getTabBounds();
|
const GUI::Rect& r = instance().debugger().getTabBounds();
|
||||||
|
|
||||||
const int vBorder = 4;
|
const int vBorder = 4;
|
||||||
|
|
||||||
// The tab widget
|
// The tab widget
|
||||||
|
// Since there are two tab widgets in this dialog, we specifically
|
||||||
|
// assign an ID of 0
|
||||||
myTab = new TabWidget(this, instance().consoleFont(), r.left, r.top + vBorder,
|
myTab = new TabWidget(this, instance().consoleFont(), r.left, r.top + vBorder,
|
||||||
r.width(), r.height() - vBorder);
|
r.width(), r.height() - vBorder);
|
||||||
|
myTab->setID(0);
|
||||||
addTabWidget(myTab);
|
addTabWidget(myTab);
|
||||||
|
|
||||||
const int widWidth = r.width() - vBorder;
|
const int widWidth = r.width() - vBorder;
|
||||||
|
@ -193,28 +198,28 @@ void DebuggerDialog::addTabArea()
|
||||||
myPrompt = new PromptWidget(myTab, instance().consoleFont(),
|
myPrompt = new PromptWidget(myTab, instance().consoleFont(),
|
||||||
2, 2, widWidth, widHeight);
|
2, 2, widWidth, widHeight);
|
||||||
myTab->setParentWidget(tabID, myPrompt);
|
myTab->setParentWidget(tabID, myPrompt);
|
||||||
addToFocusList(myPrompt->getFocusList(), tabID);
|
addToFocusList(myPrompt->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
// The TIA tab
|
// The TIA tab
|
||||||
tabID = myTab->addTab("TIA");
|
tabID = myTab->addTab("TIA");
|
||||||
TiaWidget* tia = new TiaWidget(myTab, instance().consoleFont(),
|
TiaWidget* tia = new TiaWidget(myTab, instance().consoleFont(),
|
||||||
2, 2, widWidth, widHeight);
|
2, 2, widWidth, widHeight);
|
||||||
myTab->setParentWidget(tabID, tia);
|
myTab->setParentWidget(tabID, tia);
|
||||||
addToFocusList(tia->getFocusList(), tabID);
|
addToFocusList(tia->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
// The input/output tab (includes RIOT and INPTx from TIA)
|
// The input/output tab (includes RIOT and INPTx from TIA)
|
||||||
tabID = myTab->addTab("I/O");
|
tabID = myTab->addTab("I/O");
|
||||||
RiotWidget* riot = new RiotWidget(myTab, instance().consoleFont(),
|
RiotWidget* riot = new RiotWidget(myTab, instance().consoleFont(),
|
||||||
2, 2, widWidth, widHeight);
|
2, 2, widWidth, widHeight);
|
||||||
myTab->setParentWidget(tabID, riot);
|
myTab->setParentWidget(tabID, riot);
|
||||||
addToFocusList(riot->getFocusList(), tabID);
|
addToFocusList(riot->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
// The Audio tab
|
// The Audio tab
|
||||||
tabID = myTab->addTab("Audio");
|
tabID = myTab->addTab("Audio");
|
||||||
AudioWidget* aud = new AudioWidget(myTab, instance().consoleFont(),
|
AudioWidget* aud = new AudioWidget(myTab, instance().consoleFont(),
|
||||||
2, 2, widWidth, widHeight);
|
2, 2, widWidth, widHeight);
|
||||||
myTab->setParentWidget(tabID, aud);
|
myTab->setParentWidget(tabID, aud);
|
||||||
addToFocusList(aud->getFocusList(), tabID);
|
addToFocusList(aud->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
myTab->setActiveTab(0);
|
myTab->setActiveTab(0);
|
||||||
}
|
}
|
||||||
|
@ -248,6 +253,8 @@ void DebuggerDialog::addStatusArea()
|
||||||
void DebuggerDialog::addRomArea()
|
void DebuggerDialog::addRomArea()
|
||||||
{
|
{
|
||||||
const GUI::Rect& r = instance().debugger().getRomBounds();
|
const GUI::Rect& r = instance().debugger().getRomBounds();
|
||||||
|
const int vBorder = 4;
|
||||||
|
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
|
|
||||||
xpos = r.left + 10; ypos = 10;
|
xpos = r.left + 10; ypos = 10;
|
||||||
|
@ -289,14 +296,45 @@ void DebuggerDialog::addRomArea()
|
||||||
bwidth, bheight, "<", kDDRewindCmd);
|
bwidth, bheight, "<", kDDRewindCmd);
|
||||||
myRewindButton->clearFlags(WIDGET_ENABLED);
|
myRewindButton->clearFlags(WIDGET_ENABLED);
|
||||||
|
|
||||||
xpos = r.left + 10; ypos += myRam->getHeight() + 5;
|
|
||||||
myRom = new RomWidget(this, instance().consoleFont(), xpos, ypos);
|
|
||||||
addToFocusList(myRom->getFocusList());
|
|
||||||
|
|
||||||
// Add the DataGridOpsWidget to any widgets which contain a
|
// Add the DataGridOpsWidget to any widgets which contain a
|
||||||
// DataGridWidget which we want controlled
|
// DataGridWidget which we want controlled
|
||||||
myCpu->setOpsWidget(ops);
|
myCpu->setOpsWidget(ops);
|
||||||
myRam->setOpsWidget(ops);
|
myRam->setOpsWidget(ops);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Disassembly area
|
||||||
|
|
||||||
|
xpos = r.left + vBorder; ypos += myRam->getHeight() + 5;
|
||||||
|
const int tabWidth = r.width() - vBorder;
|
||||||
|
const int tabHeight = r.height() - ypos;
|
||||||
|
int tabID;
|
||||||
|
|
||||||
|
// Since there are two tab widgets in this dialog, we specifically
|
||||||
|
// assign an ID of 1
|
||||||
|
myRomTab = new TabWidget(
|
||||||
|
this, instance().consoleFont(), xpos, ypos, tabWidth, tabHeight);
|
||||||
|
myRomTab->setID(1);
|
||||||
|
addTabWidget(myRomTab);
|
||||||
|
|
||||||
|
// The main disassembly tab
|
||||||
|
tabID = myRomTab->addTab(" Disassembly ");
|
||||||
|
myRom = new RomWidget(myRomTab, instance().consoleFont(),
|
||||||
|
2, 2, tabWidth - 1,
|
||||||
|
tabHeight - myRomTab->getTabHeight() - 2);
|
||||||
|
myRomTab->setParentWidget(tabID, myRom);
|
||||||
|
addToFocusList(myRom->getFocusList(), myRomTab, tabID);
|
||||||
|
|
||||||
|
// The 'cart-specific' information tab
|
||||||
|
tabID = myRomTab->addTab(instance().console().cartridge().name());
|
||||||
|
#if 0
|
||||||
|
myRom = new RomWidget(myRomTab, instance().consoleFont(),
|
||||||
|
2, 2, tabWidth - 1,
|
||||||
|
tabHeight - myRomTab->getTabHeight() - 2);
|
||||||
|
myRomTab->setParentWidget(tabID, myRom);
|
||||||
|
addToFocusList(myRom->getFocusList(), myRomTab, tabID);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
myRomTab->setActiveTab(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -72,7 +72,7 @@ class DebuggerDialog : public Dialog
|
||||||
kDDExitFatalCmd = 'DDer'
|
kDDExitFatalCmd = 'DDer'
|
||||||
};
|
};
|
||||||
|
|
||||||
TabWidget* myTab;
|
TabWidget *myTab, *myRomTab;
|
||||||
|
|
||||||
PromptWidget* myPrompt;
|
PromptWidget* myPrompt;
|
||||||
TiaInfoWidget* myTiaInfo;
|
TiaInfoWidget* myTiaInfo;
|
||||||
|
|
|
@ -38,8 +38,9 @@
|
||||||
#include "RomWidget.hxx"
|
#include "RomWidget.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
: Widget(boss, font, x, y, 16, 16),
|
int x, int y, int w, int h)
|
||||||
|
: Widget(boss, font, x, y, w, h),
|
||||||
CommandSender(boss),
|
CommandSender(boss),
|
||||||
myListIsDirty(true),
|
myListIsDirty(true),
|
||||||
myCurrentBank(-1)
|
myCurrentBank(-1)
|
||||||
|
@ -85,18 +86,12 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
||||||
|
|
||||||
// Create rom listing
|
// Create rom listing
|
||||||
xpos = x; ypos += myBank->getHeight() + 4;
|
xpos = x; ypos += myBank->getHeight() + 4;
|
||||||
const GUI::Rect& dialog = instance().debugger().getDialogBounds();
|
|
||||||
int w = dialog.width() - x - 5, h = dialog.height() - ypos - 3;
|
|
||||||
|
|
||||||
myRomList = new RomListWidget(boss, font, xpos, ypos, w, h);
|
myRomList = new RomListWidget(boss, font, xpos, ypos, _w - 4, _h - ypos - 2);
|
||||||
myRomList->setTarget(this);
|
myRomList->setTarget(this);
|
||||||
myRomList->myMenu->setTarget(this);
|
myRomList->myMenu->setTarget(this);
|
||||||
addFocusWidget(myRomList);
|
addFocusWidget(myRomList);
|
||||||
|
|
||||||
// Calculate real dimensions
|
|
||||||
_w = myRomList->getWidth();
|
|
||||||
_h = myRomList->getHeight();
|
|
||||||
|
|
||||||
// Create dialog box for save ROM (get name)
|
// Create dialog box for save ROM (get name)
|
||||||
StringList label;
|
StringList label;
|
||||||
label.push_back("Filename: ");
|
label.push_back("Filename: ");
|
||||||
|
|
|
@ -39,7 +39,7 @@ class StringList;
|
||||||
class RomWidget : public Widget, public CommandSender
|
class RomWidget : public Widget, public CommandSender
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y);
|
RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h);
|
||||||
virtual ~RomWidget();
|
virtual ~RomWidget();
|
||||||
|
|
||||||
void invalidate(bool forcereload = true)
|
void invalidate(bool forcereload = true)
|
||||||
|
|
|
@ -163,11 +163,6 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
|
||||||
// Reset the system to its power-on state
|
// Reset the system to its power-on state
|
||||||
mySystem->reset();
|
mySystem->reset();
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
|
||||||
myOSystem->createDebugger(*this);
|
|
||||||
m6502->attach(myOSystem->debugger());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Finally, add remaining info about the console
|
// Finally, add remaining info about the console
|
||||||
myConsoleInfo.CartName = myProperties.get(Cartridge_Name);
|
myConsoleInfo.CartName = myProperties.get(Cartridge_Name);
|
||||||
myConsoleInfo.CartMD5 = myProperties.get(Cartridge_MD5);
|
myConsoleInfo.CartMD5 = myProperties.get(Cartridge_MD5);
|
||||||
|
@ -920,6 +915,15 @@ void Console::toggleFixedColors() const
|
||||||
myOSystem->frameBuffer().showMessage("Fixed debug colors disabled");
|
myOSystem->frameBuffer().showMessage("Fixed debug colors disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Console::addDebugger()
|
||||||
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myOSystem->createDebugger(*this);
|
||||||
|
mySystem->m6502().attach(myOSystem->debugger());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 Console::ourNTSCPalette[256] = {
|
uInt32 Console::ourNTSCPalette[256] = {
|
||||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||||
|
|
|
@ -170,6 +170,11 @@ class Console : public Serializable
|
||||||
*/
|
*/
|
||||||
const ConsoleInfo& about() const { return myConsoleInfo; }
|
const ConsoleInfo& about() const { return myConsoleInfo; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set up the console to use the debugger.
|
||||||
|
*/
|
||||||
|
void addDebugger();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Overloaded assignment operator
|
Overloaded assignment operator
|
||||||
|
|
|
@ -51,7 +51,6 @@ FrameBuffer::FrameBuffer(OSystem* osystem)
|
||||||
myPausedCount(0)
|
myPausedCount(0)
|
||||||
{
|
{
|
||||||
myMsg.surface = myStatsMsg.surface = NULL;
|
myMsg.surface = myStatsMsg.surface = NULL;
|
||||||
myMsg.surfaceID = myStatsMsg.surfaceID = -1;
|
|
||||||
myMsg.enabled = myStatsMsg.enabled = false;
|
myMsg.enabled = myStatsMsg.enabled = false;
|
||||||
|
|
||||||
// Load NTSC filter settings
|
// Load NTSC filter settings
|
||||||
|
@ -175,13 +174,13 @@ FBInitStatus FrameBuffer::initialize(const string& title,
|
||||||
|
|
||||||
if(myStatsMsg.surface == NULL)
|
if(myStatsMsg.surface == NULL)
|
||||||
{
|
{
|
||||||
myStatsMsg.surfaceID = allocateSurface(myStatsMsg.w, myStatsMsg.h);
|
uInt32 surfaceID = allocateSurface(myStatsMsg.w, myStatsMsg.h);
|
||||||
myStatsMsg.surface = surface(myStatsMsg.surfaceID);
|
myStatsMsg.surface = surface(surfaceID);
|
||||||
}
|
}
|
||||||
if(myMsg.surface == NULL)
|
if(myMsg.surface == NULL)
|
||||||
{
|
{
|
||||||
myMsg.surfaceID = allocateSurface(640, myOSystem->font().getFontHeight()+10);
|
uInt32 surfaceID = allocateSurface(640, myOSystem->font().getFontHeight()+10);
|
||||||
myMsg.surface = surface(myMsg.surfaceID);
|
myMsg.surface = surface(surfaceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, show some information about the framebuffer,
|
// Finally, show some information about the framebuffer,
|
||||||
|
@ -586,22 +585,22 @@ void FrameBuffer::toggleScanlineInterpolation()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FrameBuffer::allocateSurface(int w, int h, bool useBase)
|
uInt32 FrameBuffer::allocateSurface(int w, int h, bool useBase)
|
||||||
{
|
{
|
||||||
// Create a new surface
|
// Create a new surface
|
||||||
FBSurface* surface = createSurface(w, h, useBase);
|
FBSurface* surface = createSurface(w, h, useBase);
|
||||||
|
|
||||||
// Add it to the list
|
// Add it to the list
|
||||||
mySurfaceList.insert(make_pair(int(mySurfaceList.size()), surface));
|
mySurfaceList.insert(make_pair(mySurfaceList.size(), surface));
|
||||||
|
|
||||||
// Return a reference to it
|
// Return a reference to it
|
||||||
return mySurfaceList.size() - 1;
|
return mySurfaceList.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurface* FrameBuffer::surface(int id) const
|
FBSurface* FrameBuffer::surface(uInt32 id) const
|
||||||
{
|
{
|
||||||
map<int,FBSurface*>::const_iterator iter = mySurfaceList.find(id);
|
map<uInt32,FBSurface*>::const_iterator iter = mySurfaceList.find(id);
|
||||||
return iter != mySurfaceList.end() ? iter->second : NULL;
|
return iter != mySurfaceList.end() ? iter->second : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +613,7 @@ void FrameBuffer::resetSurfaces(FBSurface* tiasurface)
|
||||||
// Any derived FrameBuffer classes that call this method should be
|
// Any derived FrameBuffer classes that call this method should be
|
||||||
// aware of these restrictions, and act accordingly
|
// aware of these restrictions, and act accordingly
|
||||||
|
|
||||||
map<int,FBSurface*>::iterator iter;
|
map<uInt32,FBSurface*>::iterator iter;
|
||||||
for(iter = mySurfaceList.begin(); iter != mySurfaceList.end(); ++iter)
|
for(iter = mySurfaceList.begin(); iter != mySurfaceList.end(); ++iter)
|
||||||
iter->second->free();
|
iter->second->free();
|
||||||
if(tiasurface)
|
if(tiasurface)
|
||||||
|
|
|
@ -173,7 +173,7 @@ class FrameBuffer
|
||||||
|
|
||||||
@return A unique ID used to identify this surface
|
@return A unique ID used to identify this surface
|
||||||
*/
|
*/
|
||||||
int allocateSurface(int w, int h, bool useBase = false);
|
uInt32 allocateSurface(int w, int h, bool useBase = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Retrieve the surface associated with the given ID.
|
Retrieve the surface associated with the given ID.
|
||||||
|
@ -181,7 +181,7 @@ class FrameBuffer
|
||||||
@param id The ID for the surface to retrieve.
|
@param id The ID for the surface to retrieve.
|
||||||
@return A pointer to a valid surface object, or NULL.
|
@return A pointer to a valid surface object, or NULL.
|
||||||
*/
|
*/
|
||||||
FBSurface* surface(int id) const;
|
FBSurface* surface(uInt32 id) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the current dimensions of the framebuffer image.
|
Returns the current dimensions of the framebuffer image.
|
||||||
|
@ -633,7 +633,6 @@ class FrameBuffer
|
||||||
MessagePosition position;
|
MessagePosition position;
|
||||||
uInt32 color;
|
uInt32 color;
|
||||||
FBSurface* surface;
|
FBSurface* surface;
|
||||||
int surfaceID;
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
Message myMsg;
|
Message myMsg;
|
||||||
|
@ -645,7 +644,7 @@ class FrameBuffer
|
||||||
VideoModeList* myCurrentModeList;
|
VideoModeList* myCurrentModeList;
|
||||||
|
|
||||||
// Holds a reference to all the surfaces that have been created
|
// Holds a reference to all the surfaces that have been created
|
||||||
map<int,FBSurface*> mySurfaceList;
|
map<uInt32,FBSurface*> mySurfaceList;
|
||||||
|
|
||||||
// Holds static strings for the remap menu (emulation and menu events)
|
// Holds static strings for the remap menu (emulation and menu events)
|
||||||
static GraphicsMode ourGraphicsModes[GFX_NumModes];
|
static GraphicsMode ourGraphicsModes[GFX_NumModes];
|
||||||
|
|
|
@ -531,6 +531,9 @@ bool OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
|
||||||
myConsole = openConsole(myRomFile, myRomMD5, type, id);
|
myConsole = openConsole(myRomFile, myRomMD5, type, id);
|
||||||
if(myConsole)
|
if(myConsole)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myConsole->addDebugger();
|
||||||
|
#endif
|
||||||
#ifdef CHEATCODE_SUPPORT
|
#ifdef CHEATCODE_SUPPORT
|
||||||
myCheatManager->loadCheats(myRomMD5);
|
myCheatManager->loadCheats(myRomMD5);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,31 +46,26 @@ Dialog::Dialog(OSystem* instance, DialogContainer* parent,
|
||||||
_cancelWidget(0),
|
_cancelWidget(0),
|
||||||
_visible(false),
|
_visible(false),
|
||||||
_isBase(isBase),
|
_isBase(isBase),
|
||||||
_ourTab(NULL),
|
_surface(0),
|
||||||
_surface(NULL),
|
_tabID(0)
|
||||||
_focusID(0),
|
|
||||||
_surfaceID(-1)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Dialog::~Dialog()
|
Dialog::~Dialog()
|
||||||
{
|
{
|
||||||
for(unsigned int i = 0; i < _ourFocusList.size(); ++i)
|
_myFocus.list.clear();
|
||||||
_ourFocusList[i].focusList.clear();
|
_myTabList.clear();
|
||||||
|
|
||||||
delete _firstWidget;
|
delete _firstWidget;
|
||||||
_firstWidget = NULL;
|
_firstWidget = NULL;
|
||||||
|
|
||||||
_ourButtonGroup.clear();
|
_buttonGroup.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::open()
|
void Dialog::open()
|
||||||
{
|
{
|
||||||
_result = 0;
|
|
||||||
_visible = true;
|
|
||||||
|
|
||||||
// Make sure we have a valid surface to draw into
|
// Make sure we have a valid surface to draw into
|
||||||
// Technically, this shouldn't be needed until drawDialog(), but some
|
// Technically, this shouldn't be needed until drawDialog(), but some
|
||||||
// dialogs cause drawing to occur within loadConfig()
|
// dialogs cause drawing to occur within loadConfig()
|
||||||
|
@ -80,11 +75,10 @@ void Dialog::open()
|
||||||
// However, this policy is left entirely to the framebuffer
|
// However, this policy is left entirely to the framebuffer
|
||||||
// We suggest the hint here, but specific framebuffers are free to
|
// We suggest the hint here, but specific framebuffers are free to
|
||||||
// ignore it
|
// ignore it
|
||||||
_surface = instance().frameBuffer().surface(_surfaceID);
|
|
||||||
if(_surface == NULL)
|
if(_surface == NULL)
|
||||||
{
|
{
|
||||||
_surfaceID = instance().frameBuffer().allocateSurface(_w, _h, _isBase);
|
uInt32 surfaceID = instance().frameBuffer().allocateSurface(_w, _h, _isBase);
|
||||||
_surface = instance().frameBuffer().surface(_surfaceID);
|
_surface = instance().frameBuffer().surface(surfaceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
center();
|
center();
|
||||||
|
@ -92,7 +86,9 @@ void Dialog::open()
|
||||||
|
|
||||||
// (Re)-build the focus list to use for the widgets which are currently
|
// (Re)-build the focus list to use for the widgets which are currently
|
||||||
// onscreen
|
// onscreen
|
||||||
buildFocusWidgetList(_focusID);
|
buildCurrentFocusList();
|
||||||
|
|
||||||
|
_visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -135,43 +131,75 @@ void Dialog::releaseFocus()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::addFocusWidget(Widget* w)
|
void Dialog::addFocusWidget(Widget* w)
|
||||||
{
|
{
|
||||||
|
if(!w)
|
||||||
|
return;
|
||||||
|
|
||||||
// All focusable widgets should retain focus
|
// All focusable widgets should retain focus
|
||||||
if(w)
|
|
||||||
w->setFlags(WIDGET_RETAIN_FOCUS);
|
w->setFlags(WIDGET_RETAIN_FOCUS);
|
||||||
|
|
||||||
if(_ourFocusList.size() == 0)
|
_myFocus.widget = w;
|
||||||
{
|
_myFocus.list.push_back(w);
|
||||||
Focus f;
|
|
||||||
f.focusedWidget = 0;
|
|
||||||
_ourFocusList.push_back(f);
|
|
||||||
}
|
|
||||||
_ourFocusList[0].focusedWidget = w;
|
|
||||||
_ourFocusList[0].focusList.push_back(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::addToFocusList(WidgetArray& list, int id)
|
void Dialog::addToFocusList(WidgetArray& list)
|
||||||
{
|
{
|
||||||
// All focusable widgets should retain focus
|
// All focusable widgets should retain focus
|
||||||
for(unsigned int i = 0; i < list.size(); ++i)
|
for(uInt32 i = 0; i < list.size(); ++i)
|
||||||
list[i]->setFlags(WIDGET_RETAIN_FOCUS);
|
list[i]->setFlags(WIDGET_RETAIN_FOCUS);
|
||||||
|
|
||||||
id++; // Arrays start at 0, not -1.
|
_myFocus.list.push_back(list);
|
||||||
|
_focusList = _myFocus.list;
|
||||||
// Make sure the array is large enough
|
|
||||||
while((int)_ourFocusList.size() <= id)
|
|
||||||
{
|
|
||||||
Focus f;
|
|
||||||
f.focusedWidget = NULL;
|
|
||||||
_ourFocusList.push_back(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ourFocusList[id].focusList.push_back(list);
|
|
||||||
if(id == 0 && _ourFocusList.size() > 0)
|
|
||||||
_focusList = _ourFocusList[0].focusList;
|
|
||||||
|
|
||||||
if(list.size() > 0)
|
if(list.size() > 0)
|
||||||
_ourFocusList[id].focusedWidget = list[0];
|
_myFocus.widget = list[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Dialog::addToFocusList(WidgetArray& list, TabWidget* w, int tabId)
|
||||||
|
{
|
||||||
|
// Only add the list if the tab actually exists
|
||||||
|
if(!w || w->getID() < 0 || (uInt32)w->getID() >= _myTabList.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(w == _myTabList[w->getID()].widget);
|
||||||
|
|
||||||
|
// All focusable widgets should retain focus
|
||||||
|
for(uInt32 i = 0; i < list.size(); ++i)
|
||||||
|
list[i]->setFlags(WIDGET_RETAIN_FOCUS);
|
||||||
|
|
||||||
|
// First get the appropriate focus list
|
||||||
|
FocusList& focus = _myTabList[w->getID()].focus;
|
||||||
|
|
||||||
|
// Now insert in the correct place in that focus list
|
||||||
|
uInt32 id = tabId;
|
||||||
|
if(id < focus.size())
|
||||||
|
focus[id].list.push_back(list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Make sure the array is large enough
|
||||||
|
while(focus.size() <= id)
|
||||||
|
focus.push_back(Focus());
|
||||||
|
|
||||||
|
focus[id].list.push_back(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(list.size() > 0)
|
||||||
|
focus[id].widget = list[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Dialog::addTabWidget(TabWidget* w)
|
||||||
|
{
|
||||||
|
if(!w || w->getID() < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make sure the array is large enough
|
||||||
|
uInt32 id = w->getID();
|
||||||
|
while(_myTabList.size() < id)
|
||||||
|
_myTabList.push_back(TabFocus());
|
||||||
|
|
||||||
|
_myTabList.push_back(TabFocus(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -183,51 +211,66 @@ void Dialog::setFocus(Widget* w)
|
||||||
{
|
{
|
||||||
// Redraw widgets for new focus
|
// Redraw widgets for new focus
|
||||||
_focusedWidget = Widget::setFocusForChain(this, getFocusList(), w, 0);
|
_focusedWidget = Widget::setFocusForChain(this, getFocusList(), w, 0);
|
||||||
|
|
||||||
|
cerr << "set focus for " << _focusedWidget << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::buildFocusWidgetList(int id)
|
void Dialog::buildCurrentFocusList(int tabID)
|
||||||
{
|
{
|
||||||
// Yes, this is hideously complex. That's the price we pay for
|
// Yes, this is hideously complex. That's the price we pay for
|
||||||
// tab navigation ...
|
// tab navigation ...
|
||||||
|
|
||||||
// Remember which item previously had focus, but only if it belongs
|
|
||||||
// to this focus list
|
|
||||||
if(_focusID < (int)_ourFocusList.size() &&
|
|
||||||
Widget::isWidgetInChain(_ourFocusList[_focusID].focusList, _focusedWidget))
|
|
||||||
_ourFocusList[_focusID].focusedWidget = _focusedWidget;
|
|
||||||
|
|
||||||
_focusID = id;
|
|
||||||
|
|
||||||
// Create a focuslist for items currently onscreen
|
|
||||||
// We do this by starting with any dialog focus list (at index 0 in the
|
|
||||||
// focus lists, then appending the list indicated by 'id'.
|
|
||||||
if(_focusID < (int)_ourFocusList.size())
|
|
||||||
{
|
|
||||||
_focusList.clear();
|
_focusList.clear();
|
||||||
_focusList.push_back(_ourFocusList[0].focusList);
|
|
||||||
|
|
||||||
// Append extra focus list
|
// Remember which tab item previously had focus, if applicable
|
||||||
if(_focusID > 0)
|
// This only applies if this method was called for a tab change
|
||||||
_focusList.push_back(_ourFocusList[_focusID].focusList);
|
Widget* tabFocusWidget = 0;
|
||||||
|
if(tabID >= 0 && tabID < (int)_myTabList.size())
|
||||||
|
{
|
||||||
|
cerr << "save tab, move to next\n";
|
||||||
|
// Save focus in previously selected tab column,
|
||||||
|
// and get focus for new tab column
|
||||||
|
TabFocus& tabfocus = _myTabList[tabID];
|
||||||
|
tabfocus.saveCurrentFocus(_focusedWidget);
|
||||||
|
tabFocusWidget = tabfocus.getNewFocus();
|
||||||
|
|
||||||
|
_tabID = tabID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case for dialogs containing only one tab widget, with all items
|
||||||
|
// arranged in separate tabs
|
||||||
|
bool containsSingleTab = _myFocus.list.size() == 1 && _myTabList.size() == 1;
|
||||||
|
|
||||||
|
// A dialog containing only one tabwidget should be added first
|
||||||
|
if(containsSingleTab)
|
||||||
|
{
|
||||||
|
_focusList.push_back(_myFocus.list);
|
||||||
|
_focusedWidget = _focusList[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add appropriate items from tablist (if present)
|
||||||
|
for(uInt32 id = 0; id < _myTabList.size(); ++id)
|
||||||
|
_myTabList[id].appendFocusList(_focusList);
|
||||||
|
|
||||||
|
// Add remaining items from main focus list
|
||||||
|
if(!containsSingleTab)
|
||||||
|
_focusList.push_back(_myFocus.list);
|
||||||
|
|
||||||
// Add button group at end of current focus list
|
// Add button group at end of current focus list
|
||||||
// We do it this way for TabWidget, so that buttons are scanned
|
// We do it this way for TabWidget, so that buttons are scanned
|
||||||
// *after* the widgets in the current tab
|
// *after* the widgets in the current tab
|
||||||
if(_ourButtonGroup.size() > 0)
|
if(_buttonGroup.size() > 0)
|
||||||
_focusList.push_back(_ourButtonGroup);
|
_focusList.push_back(_buttonGroup);
|
||||||
|
|
||||||
// Only update _focusedWidget if it doesn't belong to the main focus list
|
// Finally, the moment we've all been waiting for :)
|
||||||
// HACK - figure out how to properly deal with only one focus-able widget
|
// Set the actual focus widget
|
||||||
// in a tab -- TabWidget is the spawn of the devil
|
if(tabFocusWidget)
|
||||||
if(_focusList.size() == 1)
|
{cerr << "tab focus changed\n";
|
||||||
_focusedWidget = _focusList[0];
|
_focusedWidget = tabFocusWidget;
|
||||||
else if(!Widget::isWidgetInChain(_ourFocusList[0].focusList, _focusedWidget))
|
|
||||||
_focusedWidget = _ourFocusList[_focusID].focusedWidget;
|
|
||||||
}
|
}
|
||||||
else
|
else if(!_focusedWidget && _focusList.size() > 0)
|
||||||
_focusedWidget = 0;
|
_focusedWidget = _focusList[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -295,20 +338,14 @@ void Dialog::handleKeyDown(StellaKey key, StellaMod mod, char ascii)
|
||||||
// not ascii??
|
// not ascii??
|
||||||
if(instance().eventHandler().kbdShift(mod))
|
if(instance().eventHandler().kbdShift(mod))
|
||||||
{
|
{
|
||||||
if(key == KBDK_LEFT && _ourTab) // left arrow
|
if(key == KBDK_LEFT && cycleTab(-1))
|
||||||
{
|
|
||||||
_ourTab->cycleTab(-1);
|
|
||||||
return;
|
return;
|
||||||
}
|
else if(key == KBDK_RIGHT && cycleTab(+1))
|
||||||
else if(key == KBDK_RIGHT && _ourTab) // right arrow
|
|
||||||
{
|
|
||||||
_ourTab->cycleTab(+1);
|
|
||||||
return;
|
return;
|
||||||
}
|
else if(key == KBDK_TAB)
|
||||||
else if(key == KBDK_TAB) // tab
|
|
||||||
e = Event::UINavPrev;
|
e = Event::UINavPrev;
|
||||||
}
|
}
|
||||||
else if(key == KBDK_TAB) // tab
|
else if(key == KBDK_TAB)
|
||||||
e = Event::UINavNext;
|
e = Event::UINavNext;
|
||||||
|
|
||||||
// Check the keytable now, since we might get one of the above events,
|
// Check the keytable now, since we might get one of the above events,
|
||||||
|
@ -338,22 +375,19 @@ void Dialog::handleKeyUp(StellaKey key, StellaMod mod, char ascii)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::handleMouseDown(int x, int y, int button, int clickCount)
|
void Dialog::handleMouseDown(int x, int y, int button, int clickCount)
|
||||||
{
|
{
|
||||||
Widget* w;
|
Widget* w = findWidget(x, y);
|
||||||
w = findWidget(x, y);
|
|
||||||
|
|
||||||
_dragWidget = w;
|
_dragWidget = w;
|
||||||
|
|
||||||
setFocus(w);
|
setFocus(w);
|
||||||
|
|
||||||
if(w)
|
if(w)
|
||||||
w->handleMouseDown(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button, clickCount);
|
w->handleMouseDown(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y),
|
||||||
|
button, clickCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
|
void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
|
||||||
{
|
{
|
||||||
Widget* w;
|
|
||||||
|
|
||||||
if(_focusedWidget)
|
if(_focusedWidget)
|
||||||
{
|
{
|
||||||
// Lose focus on mouseup unless the widget requested to retain the focus
|
// Lose focus on mouseup unless the widget requested to retain the focus
|
||||||
|
@ -361,10 +395,10 @@ void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
|
||||||
releaseFocus();
|
releaseFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
w = _dragWidget;
|
Widget* w = _dragWidget;
|
||||||
|
|
||||||
if(w)
|
if(w)
|
||||||
w->handleMouseUp(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button, clickCount);
|
w->handleMouseUp(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y),
|
||||||
|
button, clickCount);
|
||||||
|
|
||||||
_dragWidget = 0;
|
_dragWidget = 0;
|
||||||
}
|
}
|
||||||
|
@ -372,13 +406,11 @@ void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::handleMouseWheel(int x, int y, int direction)
|
void Dialog::handleMouseWheel(int x, int y, int direction)
|
||||||
{
|
{
|
||||||
Widget* w;
|
|
||||||
|
|
||||||
// This may look a bit backwards, but I think it makes more sense for
|
// This may look a bit backwards, but I think it makes more sense for
|
||||||
// the mouse wheel to primarily affect the widget the mouse is at than
|
// the mouse wheel to primarily affect the widget the mouse is at than
|
||||||
// the widget that happens to be focused.
|
// the widget that happens to be focused.
|
||||||
|
|
||||||
w = findWidget(x, y);
|
Widget* w = findWidget(x, y);
|
||||||
if(!w)
|
if(!w)
|
||||||
w = _focusedWidget;
|
w = _focusedWidget;
|
||||||
if(w)
|
if(w)
|
||||||
|
@ -441,7 +473,8 @@ bool Dialog::handleMouseClicks(int x, int y, int button)
|
||||||
Widget* w = findWidget(x, y);
|
Widget* w = findWidget(x, y);
|
||||||
|
|
||||||
if(w)
|
if(w)
|
||||||
return w->handleMouseClicks(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button);
|
return w->handleMouseClicks(x - (w->getAbsX() - _x),
|
||||||
|
y - (w->getAbsY() - _y), button);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -554,14 +587,40 @@ bool Dialog::handleNavEvent(Event::Type e)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool Dialog::cycleTab(int direction)
|
||||||
|
{
|
||||||
|
cerr << "cycle " << (direction < 0 ? "left" : "right") << ", tabID = " << _tabID << endl;
|
||||||
|
|
||||||
|
if(_tabID >= 0 && _tabID < (int)_myTabList.size())
|
||||||
|
{
|
||||||
|
_myTabList[_tabID].widget->cycleTab(direction);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(key == KBDK_LEFT && _ourTab) // left arrow
|
||||||
|
{
|
||||||
|
_ourTab->cycleTab(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(key == KBDK_RIGHT && _ourTab) // right arrow
|
||||||
|
{
|
||||||
|
_ourTab->cycleTab(+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
void Dialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
||||||
{
|
{
|
||||||
switch(cmd)
|
switch(cmd)
|
||||||
{
|
{
|
||||||
case kTabChangedCmd:
|
case kTabChangedCmd:
|
||||||
// Add this focus list for the given tab to the global focus list
|
if(_visible)
|
||||||
buildFocusWidgetList(++data);
|
buildCurrentFocusList(id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kCloseCmd:
|
case kCloseCmd:
|
||||||
|
@ -614,3 +673,72 @@ void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
|
||||||
addOKWidget(b);
|
addOKWidget(b);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Dialog::Focus::Focus(Widget* w)
|
||||||
|
: widget(w)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Dialog::Focus::~Focus()
|
||||||
|
{
|
||||||
|
list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Dialog::TabFocus::TabFocus(TabWidget* w)
|
||||||
|
: widget(w),
|
||||||
|
currentTab(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Dialog::TabFocus::~TabFocus()
|
||||||
|
{
|
||||||
|
focus.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Dialog::TabFocus::appendFocusList(WidgetArray& list)
|
||||||
|
{
|
||||||
|
uInt32 active = widget->getActiveTab();
|
||||||
|
|
||||||
|
if(active >= 0 && active < focus.size())
|
||||||
|
list.push_back(focus[active].list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Dialog::TabFocus::saveCurrentFocus(Widget* w)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
if(currentTab >= 0 && currentTab < focus.size())
|
||||||
|
{
|
||||||
|
cerr << "chain len = " << focus[currentTab].list.size() << endl;
|
||||||
|
|
||||||
|
if(Widget::isWidgetInChain(focus[currentTab].list, w))
|
||||||
|
{
|
||||||
|
cerr << "saving widget\n";
|
||||||
|
focus[currentTab].widget = w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cerr << "not in chain\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
if(currentTab >= 0 && currentTab < focus.size() &&
|
||||||
|
Widget::isWidgetInChain(focus[currentTab].list, w))
|
||||||
|
{cerr << "saving widget\n";
|
||||||
|
focus[currentTab].widget = w;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Widget* Dialog::TabFocus::getNewFocus()
|
||||||
|
{
|
||||||
|
currentTab = widget->getActiveTab();
|
||||||
|
|
||||||
|
return (currentTab >= 0 && currentTab < focus.size()) ?
|
||||||
|
focus[currentTab].widget : 0;
|
||||||
|
}
|
||||||
|
|
|
@ -45,12 +45,6 @@ class Dialog : public GuiObject
|
||||||
{
|
{
|
||||||
friend class DialogContainer;
|
friend class DialogContainer;
|
||||||
|
|
||||||
struct Focus {
|
|
||||||
Widget* focusedWidget;
|
|
||||||
WidgetArray focusList;
|
|
||||||
};
|
|
||||||
typedef Common::Array<Focus> FocusList;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Dialog(OSystem* instance, DialogContainer* parent,
|
Dialog(OSystem* instance, DialogContainer* parent,
|
||||||
int x, int y, int w, int h, bool isBase = false);
|
int x, int y, int w, int h, bool isBase = false);
|
||||||
|
@ -69,10 +63,11 @@ class Dialog : public GuiObject
|
||||||
virtual void setDefaults() {}
|
virtual void setDefaults() {}
|
||||||
|
|
||||||
void addFocusWidget(Widget* w);
|
void addFocusWidget(Widget* w);
|
||||||
void addToFocusList(WidgetArray& list, int id = -1);
|
void addToFocusList(WidgetArray& list);
|
||||||
void addBGroupToFocusList(WidgetArray& list) { _ourButtonGroup = list; }
|
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
||||||
|
void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; }
|
||||||
void redrawFocus();
|
void redrawFocus();
|
||||||
void addTabWidget(TabWidget* w) { _ourTab = 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; }
|
||||||
void setFocus(Widget* w);
|
void setFocus(Widget* w);
|
||||||
|
@ -102,12 +97,10 @@ class Dialog : public GuiObject
|
||||||
const string& okText = "",
|
const string& okText = "",
|
||||||
const string& cancelText = "");
|
const string& cancelText = "");
|
||||||
|
|
||||||
void setResult(int result) { _result = result; }
|
|
||||||
int getResult() const { return _result; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void buildFocusWidgetList(int id);
|
void buildCurrentFocusList(int tabID = -1);
|
||||||
bool handleNavEvent(Event::Type e);
|
bool handleNavEvent(Event::Type e);
|
||||||
|
bool cycleTab(int direction);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Widget* _mouseWidget;
|
Widget* _mouseWidget;
|
||||||
|
@ -119,14 +112,36 @@ class Dialog : public GuiObject
|
||||||
bool _isBase;
|
bool _isBase;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FocusList _ourFocusList;
|
struct Focus {
|
||||||
TabWidget* _ourTab;
|
Widget* widget;
|
||||||
WidgetArray _ourButtonGroup;
|
WidgetArray list;
|
||||||
|
|
||||||
|
Focus(Widget* w = 0);
|
||||||
|
virtual ~Focus();
|
||||||
|
};
|
||||||
|
typedef Common::Array<Focus> FocusList;
|
||||||
|
|
||||||
|
struct TabFocus {
|
||||||
|
TabWidget* widget;
|
||||||
|
FocusList focus;
|
||||||
|
uInt32 currentTab;
|
||||||
|
|
||||||
|
TabFocus(TabWidget* w = 0);
|
||||||
|
virtual ~TabFocus();
|
||||||
|
|
||||||
|
void appendFocusList(WidgetArray& list);
|
||||||
|
void saveCurrentFocus(Widget* w);
|
||||||
|
Widget* getNewFocus();
|
||||||
|
};
|
||||||
|
typedef Common::Array<TabFocus> TabFocusList;
|
||||||
|
|
||||||
|
Focus _myFocus; // focus for base dialog
|
||||||
|
TabFocusList _myTabList; // focus for each tab (if any)
|
||||||
|
|
||||||
|
WidgetArray _buttonGroup;
|
||||||
FBSurface* _surface;
|
FBSurface* _surface;
|
||||||
|
|
||||||
int _result;
|
int _tabID;
|
||||||
int _focusID;
|
|
||||||
int _surfaceID;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -178,7 +178,7 @@ GameInfoDialog::GameInfoDialog(
|
||||||
wid.push_back(myType);
|
wid.push_back(myType);
|
||||||
|
|
||||||
// Add items for tab 0
|
// Add items for tab 0
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
|
|
||||||
// 2) Console properties
|
// 2) Console properties
|
||||||
|
@ -216,7 +216,7 @@ GameInfoDialog::GameInfoDialog(
|
||||||
wid.push_back(myTVType);
|
wid.push_back(myTVType);
|
||||||
|
|
||||||
// Add items for tab 1
|
// Add items for tab 1
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
|
|
||||||
// 3) Controller properties
|
// 3) Controller properties
|
||||||
|
@ -326,7 +326,7 @@ GameInfoDialog::GameInfoDialog(
|
||||||
wid.push_back(myMouseY);
|
wid.push_back(myMouseY);
|
||||||
|
|
||||||
// Add items for tab 2
|
// Add items for tab 2
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
|
|
||||||
// 4) Display properties
|
// 4) Display properties
|
||||||
|
@ -389,7 +389,7 @@ GameInfoDialog::GameInfoDialog(
|
||||||
myPPBlendLabel->setFlags(WIDGET_CLEARBG);
|
myPPBlendLabel->setFlags(WIDGET_CLEARBG);
|
||||||
|
|
||||||
// Add items for tab 3
|
// Add items for tab 3
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
|
|
||||||
// Activate the first tab
|
// Activate the first tab
|
||||||
|
|
|
@ -67,7 +67,7 @@ InputDialog::InputDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
myTab->getHeight() - ypos,
|
myTab->getHeight() - ypos,
|
||||||
actions, kEmulationMode);
|
actions, kEmulationMode);
|
||||||
myTab->setParentWidget(tabID, myEmulEventMapper);
|
myTab->setParentWidget(tabID, myEmulEventMapper);
|
||||||
addToFocusList(myEmulEventMapper->getFocusList(), tabID);
|
addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
// 2) Event mapper for UI actions
|
// 2) Event mapper for UI actions
|
||||||
tabID = myTab->addTab("UI Events");
|
tabID = myTab->addTab("UI Events");
|
||||||
|
@ -78,7 +78,7 @@ InputDialog::InputDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
myTab->getHeight() - ypos,
|
myTab->getHeight() - ypos,
|
||||||
actions, kMenuMode);
|
actions, kMenuMode);
|
||||||
myTab->setParentWidget(tabID, myMenuEventMapper);
|
myTab->setParentWidget(tabID, myMenuEventMapper);
|
||||||
addToFocusList(myMenuEventMapper->getFocusList(), tabID);
|
addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID);
|
||||||
|
|
||||||
// 3) Devices & ports
|
// 3) Devices & ports
|
||||||
addDevicePortTab(font);
|
addDevicePortTab(font);
|
||||||
|
@ -197,7 +197,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
|
||||||
wid.push_back(myMouseControl);
|
wid.push_back(myMouseControl);
|
||||||
|
|
||||||
// Add items for virtual device ports
|
// Add items for virtual device ports
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -164,6 +164,12 @@ struct Rect
|
||||||
void moveTo(const Point & p) {
|
void moveTo(const Point & p) {
|
||||||
moveTo(p.x, p.y);
|
moveTo(p.x, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& os, const Rect& r) {
|
||||||
|
os << "x=" << r.x() << ", y=" << r.y()
|
||||||
|
<< ", w=" << r.width() << ", h=" << r.height();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace GUI
|
} // End of namespace GUI
|
||||||
|
|
|
@ -39,6 +39,8 @@ TabWidget::TabWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
_activeTab(-1),
|
_activeTab(-1),
|
||||||
_firstTime(true)
|
_firstTime(true)
|
||||||
{
|
{
|
||||||
|
_id = 0; // For dialogs with multiple tab widgets, they should specifically
|
||||||
|
// call ::setID to differentiate among them
|
||||||
_flags = WIDGET_ENABLED | WIDGET_CLEARBG;
|
_flags = WIDGET_ENABLED | WIDGET_CLEARBG;
|
||||||
_type = kTabWidget;
|
_type = kTabWidget;
|
||||||
_bgcolor = kDlgColor;
|
_bgcolor = kDlgColor;
|
||||||
|
@ -112,7 +114,7 @@ void TabWidget::setActiveTab(int tabID, bool show)
|
||||||
|
|
||||||
// Let parent know about the tab change
|
// Let parent know about the tab change
|
||||||
if(show)
|
if(show)
|
||||||
sendCommand(kTabChangedCmd, _activeTab, -1);
|
sendCommand(kTabChangedCmd, _activeTab, _id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -156,7 +156,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
kTextAlignLeft);
|
kTextAlignLeft);
|
||||||
|
|
||||||
// Add items for tab 0
|
// Add items for tab 0
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// 2) Debugger options
|
// 2) Debugger options
|
||||||
|
@ -211,7 +211,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add items for tab 1
|
// Add items for tab 1
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// 3) Misc. options
|
// 3) Misc. options
|
||||||
|
@ -263,7 +263,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
ypos += lineHeight + 4;
|
ypos += lineHeight + 4;
|
||||||
|
|
||||||
// Add items for tab 2
|
// Add items for tab 2
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
// Activate the first tab
|
// Activate the first tab
|
||||||
myTab->setActiveTab(0);
|
myTab->setActiveTab(0);
|
||||||
|
|
|
@ -236,7 +236,7 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
ypos += lineHeight + 4;
|
ypos += lineHeight + 4;
|
||||||
|
|
||||||
// Add items for tab 0
|
// Add items for tab 0
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// 2) TV effects options
|
// 2) TV effects options
|
||||||
|
@ -326,7 +326,7 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
CREATE_CLONE_BUTTON(Custom, "Revert");
|
CREATE_CLONE_BUTTON(Custom, "Revert");
|
||||||
|
|
||||||
// Add items for tab 2
|
// Add items for tab 2
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, myTab, tabID);
|
||||||
|
|
||||||
// Activate the first tab
|
// Activate the first tab
|
||||||
myTab->setActiveTab(0);
|
myTab->setActiveTab(0);
|
||||||
|
|
|
@ -39,6 +39,7 @@ SerialPortMACOSX::SerialPortMACOSX()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SerialPortMACOSX::~SerialPortMACOSX()
|
SerialPortMACOSX::~SerialPortMACOSX()
|
||||||
{
|
{
|
||||||
|
closePort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -65,7 +66,10 @@ bool SerialPortMACOSX::openPort(const string& device)
|
||||||
void SerialPortMACOSX::closePort()
|
void SerialPortMACOSX::closePort()
|
||||||
{
|
{
|
||||||
if(myHandle)
|
if(myHandle)
|
||||||
|
{
|
||||||
close(myHandle);
|
close(myHandle);
|
||||||
|
myHandle = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -49,7 +49,10 @@ bool SerialPortWin32::openPort(const string& device)
|
||||||
FillMemory(&dcb, sizeof(dcb), 0);
|
FillMemory(&dcb, sizeof(dcb), 0);
|
||||||
dcb.DCBlength = sizeof(dcb);
|
dcb.DCBlength = sizeof(dcb);
|
||||||
if(!BuildCommDCB("19200,n,8,1", &dcb))
|
if(!BuildCommDCB("19200,n,8,1", &dcb))
|
||||||
|
{
|
||||||
|
closePort()
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&dcb, 0, sizeof(DCB));
|
memset(&dcb, 0, sizeof(DCB));
|
||||||
dcb.BaudRate = CBR_19200;
|
dcb.BaudRate = CBR_19200;
|
||||||
|
|
Loading…
Reference in New Issue