Merge branch 'master' into feature/precise-audio

This commit is contained in:
Christian Speckner 2018-01-29 21:18:36 +01:00
commit 89f3f4c9b8
112 changed files with 2278 additions and 1851 deletions

View File

@ -69,7 +69,8 @@
* Fixed swapped ports being displayed wrong in System Logs and debugger.
* Added options to erase the AtariVox/Savekey flash memory, either for
all ROMs or only the current one.
all ROMs or only the current one. Also added a message (configurable)
when the flash memory is accessed.
* Moved various developer related settings in new Developer Settings
dialog. These settings now come in two groups (player/developer) and

View File

@ -56,7 +56,7 @@ endif
ifdef CLANG_WARNINGS
CXXFLAGS+= -Weverything -Wno-c++17-extensions -Wno-c++98-compat -Wno-c++98-compat-pedantic \
-Wno-double-promotion -Wno-switch-enum -Wno-conversion -Wno-covered-switch-default \
-Wno-inconsistent-missing-destructor-override \
-Wno-inconsistent-missing-destructor-override -Wno-float-equal \
-Wno-exit-time-destructors -Wno-global-constructors -Wno-weak-vtables \
-Wno-four-char-constants -Wno-padded
endif

View File

@ -268,7 +268,7 @@
joysticks or mouse</li>
<li>Emulates the Sega Genesis Controller using your computer's keyboard,
joysticks or mouse</li>
<li>Emulates CX22/CX80 style trakballs and Amiga/Atari Mouse using your
<li>Emulates CX22/CX80 style trackballs and Amiga/Atari Mouse using your
computer's mouse</li>
<li>Emulates <a href="http://en.wikipedia.org/wiki/CompuMate">Spectravideo CompuMate</a> system using your computer's keyboard,
including mapping of CompuMate 'Backspace', 'Space' and 'Enter' functionality to
@ -645,8 +645,8 @@
<tr>
<td>Enter/exit options mode</td>
<td>Tab</td>
<td>Tab</td>
<td>Tab/Escape</td>
<td>Tab/Escape</td>
</tr>
<tr>
@ -1745,12 +1745,12 @@
<td> &#x2713;</td>
</tr>
<tr>
<th> Trakball/Mouse</th>
<th> Trackball/Mouse</th>
<td> &#x2715;</td>
<td> &#x2715;</td>
<td> &#x2713;</td>
<td> &#x2713; (axis ignored)</td>
<td> &#x2715;</td>
<td> &#x2713;</td>
</tr>
<tr>
<th> CompuMate</th>
@ -2103,7 +2103,7 @@
<td><pre>-usemouse &lt;always|analog|never&gt;</pre></td>
<td>Use mouse as a controller as specified by ROM properties in specific case.
Always and never are self-explanatory, analog means only for analog-type devices
(paddles, trakball, etc.).</td>
(paddles, trackball, etc.).</td>
</tr>
<tr>
@ -2995,8 +2995,9 @@
<h2><b><a name="Adaptor">Stelladaptor/2600-daptor Support</a></b></h2>
<blockquote>
<p>Stella supports real Atari 2600 joysticks, paddles and driving controllers
using the <a href="http://www.grandideastudio.com/portfolio/stelladaptor-2600">Stelladaptor</a> and
<p>Stella supports real Atari 2600 joysticks, paddles, driving controllers
and trackballs (CX22/CX80 'Trak-Ball', Atari and Amiga mouse) using the
<a href="http://www.grandideastudio.com/portfolio/stelladaptor-2600">Stelladaptor</a> and
<a href="http://2600-daptor.com">2600-daptor</a> devices.</p>
<p>Stella can use up to <b>two</b> adaptors; any extra ones are ignored.
@ -3190,8 +3191,7 @@
going back further in time. To reach the horizon, save states
will be compressed (*). This means that more and more intermediate
states will be removed and the interval between save states
becomes larger the further they are back in time. The very first
save state will not be removed.<br>
becomes larger the further they are back in time.<br>
(*) Compresion only works if 'Uncompressed size' is smaller than
'Buffer size'.
</td>

View File

@ -33,46 +33,48 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent)
: Dialog(osystem, parent, font, "Cheat codes")
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
const int HBORDER = 10;
const int VBORDER = 10 + _th;
int xpos, ypos;
WidgetArray wid;
ButtonWidget* b;
// Set real dimensions
_w = 46 * fontWidth + 10;
_h = 11 * (lineHeight + 4) + 10;
_w = 45 * fontWidth + HBORDER * 2;
_h = 11 * (lineHeight + 4) + VBORDER;
// List of cheats, with checkboxes to enable/disable
xpos = 10; ypos = 10;
xpos = HBORDER; ypos = VBORDER;
myCheatList =
new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - 25,
_h - 2*buttonHeight - 10);
new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - 8,
_h - 2*buttonHeight - VBORDER);
myCheatList->setEditable(false);
wid.push_back(myCheatList);
xpos += myCheatList->getWidth() + 5; ypos = 15;
xpos += myCheatList->getWidth() + 8; ypos = VBORDER;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Add" + ELLIPSIS, kAddCheatCmd);
wid.push_back(b);
ypos += lineHeight + 10;
ypos += lineHeight + 8;
myEditButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Edit" + ELLIPSIS, kEditCheatCmd);
wid.push_back(myEditButton);
ypos += lineHeight + 10;
ypos += lineHeight + 8;
myRemoveButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Remove", kRemCheatCmd);
wid.push_back(myRemoveButton);
ypos += lineHeight + 10;
ypos += lineHeight + 8 * 3;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"One shot" + ELLIPSIS, kAddOneShotCmd);
@ -82,7 +84,7 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
StringList labels;
labels.push_back("Name ");
labels.push_back("Code (hex) ");
myCheatInput = make_unique<InputTextDialog>(this, font, labels);
myCheatInput = make_unique<InputTextDialog>(this, font, labels, "Cheat code");
myCheatInput->setTarget(this);
// Add filtering for each textfield
@ -154,7 +156,7 @@ void CheatCodeDialog::addCheat()
myCheatInput->show(); // Center input dialog over entire screen
myCheatInput->setText("", 0);
myCheatInput->setText("", 1);
myCheatInput->setTitle("");
myCheatInput->setMessage("");
myCheatInput->setFocus(0);
myCheatInput->setEmitSignal(kCheatAdded);
}
@ -173,7 +175,7 @@ void CheatCodeDialog::editCheat()
myCheatInput->show(); // Center input dialog over entire screen
myCheatInput->setText(name, 0);
myCheatInput->setText(code, 1);
myCheatInput->setTitle("");
myCheatInput->setMessage("");
myCheatInput->setFocus(1);
myCheatInput->setEmitSignal(kCheatEdited);
}
@ -191,7 +193,7 @@ void CheatCodeDialog::addOneShotCheat()
myCheatInput->show(); // Center input dialog over entire screen
myCheatInput->setText("One-shot cheat", 0);
myCheatInput->setText("", 1);
myCheatInput->setTitle("");
myCheatInput->setMessage("");
myCheatInput->setFocus(1);
myCheatInput->setEmitSignal(kOneShotCheatAdded);
}
@ -234,7 +236,7 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
loadConfig(); // show changes onscreen
}
else
myCheatInput->setTitle("Invalid code");
myCheatInput->setMessage("Invalid code");
break;
}
@ -251,7 +253,7 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
loadConfig(); // show changes onscreen
}
else
myCheatInput->setTitle("Invalid code");
myCheatInput->setMessage("Invalid code");
break;
}
@ -273,7 +275,7 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
instance().cheat().addOneShot(name, code);
}
else
myCheatInput->setTitle("Invalid code");
myCheatInput->setMessage("Invalid code");
break;
}

View File

@ -68,10 +68,14 @@ string Base::toString(int value, Common::Base::Format outputBase)
std::snprintf(vToS_buf, 6, "%5d", value);
break;
case Base::F_10_2: // base 10: 2 digits
case Base::F_10_02: // base 10: 2 digits (with leading zero)
std::snprintf(vToS_buf, 3, "%02d", value);
break;
case Base::F_10_4: // base 10: 4 digits
std::snprintf(vToS_buf, 5, "%4d", value);
break;
case Base::F_16_1: // base 16: 1 byte wide
std::snprintf(vToS_buf, 2, myFmt[0], value);
break;

View File

@ -47,7 +47,8 @@ class Base
F_16_4, // base 16: 4 bytes wide
F_16_8, // base 16: 8 bytes wide
F_10, // base 10: 3 or 5 bytes (depending on value)
F_10_2, // base 10: 2 digits
F_10_02, // base 10: 02 digits
F_10_4, // base 10: 4 digits
F_2, // base 2: 8 or 16 bits (depending on value)
F_2_8, // base 2: 1 byte (8 bits) wide
F_2_16, // base 2: 2 bytes (16 bits) wide

View File

@ -48,11 +48,11 @@ class FrameBufferSDL2 : public FrameBuffer
//////////////////////////////////////////////////////////////////////
/**
Updates window title
Updates window title.
@param title The title of the application / window
@param title The title of the application / window
*/
void setTitle(const string& title);
void setTitle(const string& title) override;
/**
Shows or hides the cursor based on the given boolean value.

View File

@ -129,6 +129,12 @@ class LinkedObjectPool
*/
const_iter next(const_iter i) const { return std::next(i, 1); }
/**
Canonical iterators from C++ STL.
*/
const_iter cbegin() const { return myList.cbegin(); }
const_iter cend() const { return myList.cend(); }
/**
Answer whether 'current' is at the specified iterator.
*/

View File

@ -42,7 +42,7 @@ void RewindManager::setup()
mySize = myOSystem.settings().getInt(prefix + "tm.size");
if(mySize != myStateList.capacity())
myStateList.resize(mySize);
resize(mySize);
myUncompressed = myOSystem.settings().getInt(prefix + "tm.uncompressed");
@ -56,7 +56,7 @@ void RewindManager::setup()
if(HOR_SETTINGS[i] == myOSystem.settings().getString(prefix + "tm.horizon"))
myHorizon = HORIZON_CYCLES[i];
// calc interval growth factor
// calc interval growth factor for compression
// this factor defines the backward horizon
const double MAX_FACTOR = 1E8;
double minFactor = 0, maxFactor = MAX_FACTOR;
@ -71,8 +71,8 @@ void RewindManager::setup()
// horizon not reachable?
if(myFactor == MAX_FACTOR)
break;
// sum up interval cycles (first and last state are not compressed)
for(uInt32 i = myUncompressed + 1; i < mySize - 1; ++i)
// sum up interval cycles (first state is not compressed)
for(uInt32 i = myUncompressed + 1; i < mySize; ++i)
{
interval *= myFactor;
cycleSum += interval;
@ -88,7 +88,6 @@ void RewindManager::setup()
else
maxFactor = myFactor;
}
//cerr << "factor " << myFactor << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -138,7 +137,7 @@ bool RewindManager::addState(const string& message, bool timeMachine)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::rewindState(uInt32 numStates)
uInt32 RewindManager::rewindStates(uInt32 numStates)
{
uInt64 startCycles = myOSystem.console().tia().cycles();
uInt32 i;
@ -146,7 +145,7 @@ uInt32 RewindManager::rewindState(uInt32 numStates)
for(i = 0; i < numStates; ++i)
{
if(!atFirst())
if(!atFirst())
{
if(!myLastTimeMachineAdd)
// Set internal current iterator to previous state (back in time),
@ -177,7 +176,7 @@ uInt32 RewindManager::rewindState(uInt32 numStates)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::unwindState(uInt32 numStates)
uInt32 RewindManager::unwindStates(uInt32 numStates)
{
uInt64 startCycles = myOSystem.console().tia().cycles();
uInt32 i;
@ -210,44 +209,48 @@ uInt32 RewindManager::unwindState(uInt32 numStates)
return i;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::windStates(uInt32 numStates, bool unwind)
{
if(unwind)
return unwindStates(numStates);
else
return rewindStates(numStates);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RewindManager::compressStates()
{
double expectedCycles = myInterval * myFactor * (1 + myFactor);
double maxError = 1.5;
uInt32 idx = myStateList.size() - 2;
//uInt32 removeIdx = 0;
// in case maxError is <= 1.5 remove first state by default:
Common::LinkedObjectPool<RewindState>::const_iter removeIter = myStateList.first();
if(myUncompressed < mySize)
/*if(myUncompressed < mySize)
// if compression is enabled, the first but one state is removed by default:
removeIter++;
removeIter++;*/
//cerr << "idx: " << idx << endl;
// iterate from last but one to first but one
for(auto it = myStateList.previous(myStateList.last()); it != myStateList.first(); --it)
{
if(idx < mySize - myUncompressed)
{
//cerr << *it << endl << endl; // debug code
expectedCycles *= myFactor;
uInt64 prevCycles = myStateList.previous(it)->cycles;
uInt64 nextCycles = myStateList.next(it)->cycles;
double error = expectedCycles / (nextCycles - prevCycles);
//cerr << "prevCycles: " << prevCycles << ", nextCycles: " << nextCycles << ", error: " << error << endl;
if(error > maxError)
{
maxError = error;
removeIter = it;
//removeIdx = idx;
}
}
--idx;
}
myStateList.remove(removeIter); // remove
//cerr << "remove " << removeIdx << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -295,7 +298,7 @@ string RewindManager::getUnitString(Int64 cycles)
{
// use the lower unit up to twice the nextCycles unit, except for an exact match of the nextCycles unit
// TODO: does the latter make sense, e.g. for ROMs with changing scanlines?
if(cycles < UNIT_CYCLES[i + 1] * 2 && cycles % UNIT_CYCLES[i + 1] != 0)
if(cycles == 0 || cycles < UNIT_CYCLES[i + 1] * 2 && cycles % UNIT_CYCLES[i + 1] != 0)
break;
}
result << cycles / UNIT_CYCLES[i] << " " << UNIT_NAMES[i];
@ -306,14 +309,14 @@ string RewindManager::getUnitString(Int64 cycles)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getFirstCycles()
uInt32 RewindManager::getFirstCycles() const
{
// TODO: check if valid
return Common::LinkedObjectPool<RewindState>::const_iter(myStateList.first())->cycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getCurrentCycles()
uInt32 RewindManager::getCurrentCycles() const
{
if(myStateList.currentIsValid())
return myStateList.current().cycles;
@ -322,9 +325,20 @@ uInt32 RewindManager::getCurrentCycles()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getLastCycles()
uInt32 RewindManager::getLastCycles() const
{
// TODO: check if valid
return Common::LinkedObjectPool<RewindState>::const_iter(myStateList.last())->cycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IntArray RewindManager::cyclesList() const
{
IntArray arr;
uInt64 firstCycle = getFirstCycles();
for(auto it = myStateList.cbegin(); it != myStateList.cend(); ++it)
arr.push_back(uInt32(it->cycles - firstCycle));
return arr;
}

View File

@ -38,6 +38,9 @@ class StateManager;
to the end of the list (aka, all future states) are removed, and the internal
iterator moves to the insertion point of the data (the end of the list).
If the list is full, states are either removed at the beginning (compression
off) or at selective positions (compression on).
@author Stephen Anthony
*/
class RewindManager
@ -106,22 +109,32 @@ class RewindManager
bool addState(const string& message, bool timeMachine = false);
/**
Rewind one level of the state list, and display the message associated
Rewind numStates levels of the state list, and display the message associated
with that state.
@param numStates Number of states to rewind
@return Number of states to rewinded
*/
uInt32 rewindState(uInt32 numStates = 1);
uInt32 rewindStates(uInt32 numStates = 1);
/**
Unwind one level of the state list, and display the message associated
Unwind numStates levels of the state list, and display the message associated
with that state.
@param numStates Number of states to unwind
@return Number of states to unwinded
*/
uInt32 unwindState(uInt32 numStates = 1);
uInt32 unwindStates(uInt32 numStates = 1);
/**
Rewind/unwind numStates levels of the state list, and display the message associated
with that state.
@param numStates Number of states to wind
@param unwind unwind or rewind
@return Number of states to winded
*/
uInt32 windStates(uInt32 numStates, bool unwind);
bool atFirst() const { return myStateList.atFirst(); }
bool atLast() const { return myStateList.atLast(); }
@ -136,9 +149,15 @@ class RewindManager
uInt32 getCurrentIdx() { return myStateList.currentIdx(); }
uInt32 getLastIdx() { return myStateList.size(); }
uInt32 getFirstCycles();
uInt32 getCurrentCycles();
uInt32 getLastCycles();
uInt32 getFirstCycles() const;
uInt32 getCurrentCycles() const;
uInt32 getLastCycles() const;
/**
Get a collection of cycle timestamps, offset from the first one in
the list. This also determines the number of states in the list.
*/
IntArray cyclesList() const;
private:
OSystem& myOSystem;

View File

@ -44,6 +44,7 @@ class FixedStack
bool full() const { return _size >= CAPACITY; }
T top() const { return _stack[_size - 1]; }
T get(uInt32 pos) { return _stack[pos]; };
void push(const T& x) { _stack[_size++] = x; }
T pop() { return std::move(_stack[--_size]); }
uInt32 size() const { return _size; }

View File

@ -142,17 +142,35 @@ void StateManager::toggleTimeMachine()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::rewindState(uInt32 numStates)
bool StateManager::addExtraState(const string& message)
{
RewindManager& r = myOSystem.state().rewindManager();
return r.rewindState(numStates);
if(myActiveMode == Mode::TimeMachine)
{
RewindManager& r = myOSystem.state().rewindManager();
return r.addState(message);
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::unwindState(uInt32 numStates)
bool StateManager::rewindStates(uInt32 numStates)
{
RewindManager& r = myOSystem.state().rewindManager();
return r.unwindState(numStates);
return r.rewindStates(numStates);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::unwindStates(uInt32 numStates)
{
RewindManager& r = myOSystem.state().rewindManager();
return r.unwindStates(numStates);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::windStates(uInt32 numStates, bool unwind)
{
RewindManager& r = myOSystem.state().rewindManager();
return r.windStates(numStates, unwind);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -72,14 +72,25 @@ class StateManager
void setRewindMode(Mode mode) { myActiveMode = mode; }
/**
Rewinds one state; this uses the RewindManager for its functionality.
Optionally adds one extra state when entering the Time Machine dialog;
this uses the RewindManager for its functionality.
*/
bool rewindState(uInt32 numStates = 1);
bool addExtraState(const string& message);
/**
Unwinds one state; this uses the RewindManager for its functionality.
Rewinds states; this uses the RewindManager for its functionality.
*/
bool unwindState(uInt32 numStates = 1);
bool rewindStates(uInt32 numStates = 1);
/**
Unwinds states; this uses the RewindManager for its functionality.
*/
bool unwindStates(uInt32 numStates = 1);
/**
Rewinds/unwinds states; this uses the RewindManager for its functionality.
*/
bool windStates(uInt32 numStates, bool unwind);
/**
Updates the state of the system based on the currently active mode.

View File

@ -18,7 +18,7 @@
#ifndef VERSION_HXX
#define VERSION_HXX
#define STELLA_VERSION "5.1_a2"
#define STELLA_VERSION "5.1_b1"
#define STELLA_BUILD "3826"
#endif

View File

@ -538,7 +538,7 @@ uInt16 Debugger::windStates(uInt16 numStates, bool unwind, string& message)
unlockBankswitchState();
uInt64 startCycles = myOSystem.console().tia().cycles();
uInt16 winds = unwind ? r.unwindState(numStates) : r.rewindState(numStates);
uInt16 winds = r.windStates(numStates, unwind);
message = r.getUnitString(myOSystem.console().tia().cycles() - startCycles);
lockBankswitchState();
@ -620,7 +620,8 @@ void Debugger::setStartState()
// Save initial state and add it to the rewind list (except when in currently rewinding)
RewindManager& r = myOSystem.state().rewindManager();
// avoid invalidating future states when entering the debugger e.g. during rewind
if(myOSystem.eventHandler().state() == EventHandlerState::EMULATION)
if(r.atLast() && (myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|| myOSystem.state().mode() == StateManager::Mode::Off))
addState("enter debugger");
else
updateRewindbuttons(r);
@ -783,6 +784,12 @@ void Debugger::unlockBankswitchState()
myConsole.cartridge().unlockBank();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::canExit() const
{
return myDialogStack.top() == baseDialog();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Debugger::BuiltinFunction Debugger::ourBuiltinFunctions[NUM_BUILTIN_FUNCS] = {
// left joystick:

View File

@ -240,6 +240,12 @@ class Debugger : public DialogContainer
void lockBankswitchState();
void unlockBankswitchState();
/**
Answers whether the debugger can be exited. Currently this only
happens when no other dialogs are active.
*/
bool canExit() const;
private:
/**
Save state of each debugger subsystem and, by default, mark all

View File

@ -66,6 +66,7 @@ const DebuggerState& RiotDebug::getState()
myState.TIMINT = timint();
myState.TIMCLKS = timClocks();
myState.INTIMCLKS = intimClocks();
myState.TIMDIV = timDivider();
return myState;
}
@ -107,6 +108,7 @@ void RiotDebug::saveOldState()
myOldState.TIMINT = timint();
myOldState.TIMCLKS = timClocks();
myOldState.INTIMCLKS = intimClocks();
myOldState.TIMDIV = timDivider();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -223,6 +225,12 @@ Int32 RiotDebug::intimClocks() const
return mySystem.m6532().intimClocks();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 RiotDebug::timDivider() const
{
return mySystem.m6532().myDivider;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller& RiotDebug::controller(Controller::Jack jack) const
{
@ -362,6 +370,7 @@ string RiotDebug::toString()
<< " 285/TIMINT=" << myDebugger.invIfChanged(state.TIMINT, oldstate.TIMINT)
<< " Timer_Clocks=" << myDebugger.invIfChanged(state.TIMCLKS, oldstate.TIMCLKS)
<< " INTIM_Clocks=" << myDebugger.invIfChanged(state.INTIMCLKS, oldstate.INTIMCLKS)
<< " Divider=" << myDebugger.invIfChanged(state.TIMDIV, oldstate.TIMDIV)
<< endl
<< "Left/P0diff: " << diffP0String() << " Right/P1diff: " << diffP0String()

View File

@ -36,7 +36,7 @@ class RiotState : public DebuggerState
BoolArray swbcntBits;
uInt8 TIM1T, TIM8T, TIM64T, T1024T, INTIM, TIMINT;
Int32 TIMCLKS, INTIMCLKS;
Int32 TIMCLKS, INTIMCLKS, TIMDIV;
// These are actually from the TIA, but are I/O related
uInt8 INPT0, INPT1, INPT2, INPT3, INPT4, INPT5;
@ -74,6 +74,7 @@ class RiotDebug : public DebuggerSystem
uInt8 timint() const;
Int32 timClocks() const;
Int32 intimClocks() const;
Int32 timDivider() const;
/* Controller ports */
Controller& controller(Controller::Jack jack) const;

View File

@ -78,7 +78,7 @@ int CartDebugWidget::addBaseInformation(int bytes, const string& manufacturer,
fwidth, lines * myLineHeight, false);
myDesc->setEditable(false);
myDesc->setList(sl);
addFocusWidget(myDesc);
y += myDesc->getHeight() + 4;
return y;

View File

@ -50,8 +50,7 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
_opsWidget(nullptr),
_scrollBar(nullptr)
{
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS |
WIDGET_WANTS_RAWDATA;
_flags = WIDGET_ENABLED | WIDGET_RETAIN_FOCUS | WIDGET_WANTS_RAWDATA;
_editMode = false;
// The item is selected, thus _bgcolor is used to draw the caret and
@ -250,6 +249,20 @@ void DataGridWidget::setRange(int lower, int upper)
_upperBound = std::min(1 << _bits, upper);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
{
@ -582,25 +595,16 @@ void DataGridWidget::drawWidget(bool hilite)
FBSurface& s = _boss->dialog().surface();
int row, col;
s.fillRect(_x, _y, _w, _h, hilite && isEnabled() && isEditable() ? _bgcolorhi : _bgcolor);
// Draw the internal grid and labels
int linewidth = _cols * _colWidth;
#ifndef FLAT_UI
for (row = 0; row <= _rows; row++)
s.hLine(_x, _y + (row * _rowHeight), _x + linewidth, kColor);
int lineheight = _rows * _rowHeight;
for (col = 0; col <= _cols; col++)
s.vLine(_x + (col * _colWidth), _y, _y + lineheight, kColor);
#else
s.frameRect(_x, _y, _w, _h, kColor);
s.frameRect(_x, _y, _w, _h, hilite && isEnabled() && isEditable() ? kWidColorHi : kColor);
for(row = 1; row <= _rows-1; row++)
s.hLine(_x+1, _y + (row * _rowHeight), _x + linewidth-1, kBGColorLo);
int lineheight = _rows * _rowHeight;
for(col = 1; col <= _cols-1; col++)
s.vLine(_x + (col * _colWidth), _y+1, _y + lineheight-1, kBGColorLo);
#endif
// Draw the list items
for (row = 0; row < _rows; row++)

View File

@ -100,6 +100,8 @@ class DataGridWidget : public EditableWidget
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
bool handleText(char text) override;
bool handleKeyDown(StellaKey key, StellaMod mod) override;
bool handleKeyUp(StellaKey key, StellaMod mod) override;

View File

@ -93,11 +93,39 @@ void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod)
else if(key == KBDK_F12)
{
instance().debugger().parser().run("savesnap");
return;
}
else if(StellaModTest::isAlt(mod) && !StellaModTest::isControl(mod))
{
switch(key)
{
case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states
if(StellaModTest::isShift(mod))
doRewind10();
else
doRewind();
return;
case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states
if(StellaModTest::isShift(mod))
doUnwind10();
else
doUnwind();
return;
case KBDK_DOWN: // Alt-down rewinds to start of list
doRewindAll();
return;
case KBDK_UP: // Alt-up rewinds to end of list
doUnwindAll();
return;
default:
break;
}
}
else if(StellaModTest::isControl(mod))
{
switch(key)
{
#if 0
case KBDK_R:
if(StellaModTest::isAlt(mod))
doRewindAll();
@ -105,7 +133,7 @@ void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod)
doRewind10();
else
doRewind();
break;
return;
case KBDK_Y:
if(StellaModTest::isAlt(mod))
doUnwindAll();
@ -113,19 +141,20 @@ void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod)
doUnwind10();
else
doUnwind();
break;
return;
#endif
case KBDK_S:
doStep();
break;
return;
case KBDK_T:
doTrace();
break;
return;
case KBDK_L:
doScanlineAdvance();
break;
return;
case KBDK_F:
doAdvance();
break;
return;
default:
break;
}
@ -322,7 +351,7 @@ void DebuggerDialog::createFont()
void DebuggerDialog::showFatalMessage(const string& msg)
{
myFatalError = make_unique<GUI::MessageBox>(this, *myLFont, msg, _w/2, _h/2,
kDDExitFatalCmd, "Exit ROM", "Continue");
kDDExitFatalCmd, "Exit ROM", "Continue", "Fatal error");
myFatalError->show();
}
@ -353,15 +382,9 @@ void DebuggerDialog::addTabArea()
int tabID;
// The Prompt/console tab
#ifndef FLAT_UI
tabID = myTab->addTab(" Prompt ");
myPrompt = new PromptWidget(myTab, *myNFont,
2, 2, widWidth, widHeight);
#else
tabID = myTab->addTab("Prompt");
myPrompt = new PromptWidget(myTab, *myNFont,
2, 2, widWidth - 4, widHeight);
#endif
myTab->setParentWidget(tabID, myPrompt);
addToFocusList(myPrompt->getFocusList(), myTab, tabID);
@ -448,24 +471,32 @@ void DebuggerDialog::addRomArea()
const GUI::Rect& r = getRomBounds();
const int VBORDER = 4;
const string ELLIPSIS = "\x1d";
WidgetArray wid1, wid2;
ButtonWidget* b;
int bwidth = myLFont->getStringWidth("Frame +1 "),
bheight = myLFont->getLineHeight() + 2;
int buttonX = r.right - bwidth - 5, buttonY = r.top + 5;
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Step", kDDStepCmd);
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Step", kDDStepCmd);
wid2.push_back(b);
buttonY += bheight + 4;
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Trace", kDDTraceCmd);
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Trace", kDDTraceCmd);
wid2.push_back(b);
buttonY += bheight + 4;
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Scan +1", kDDSAdvCmd);
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Scan +1", kDDSAdvCmd);
wid2.push_back(b);
buttonY += bheight + 4;
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Frame +1", kDDAdvCmd);
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Frame +1", kDDAdvCmd);
wid2.push_back(b);
buttonY += bheight + 4;
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Exit", kDDExitCmd);
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Exit", kDDExitCmd);
wid2.push_back(b);
bwidth = bheight; // 7 + 12;
bheight = bheight * 3 + 4 * 2;
@ -475,7 +506,6 @@ void DebuggerDialog::addRomArea()
myRewindButton =
new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, LEFT_ARROW, 7, 11, kDDRewindCmd);
myRewindButton->clearFlags(WIDGET_ENABLED);
buttonY += bheight + 4;
@ -491,7 +521,11 @@ void DebuggerDialog::addRomArea()
bwidth = myLFont->getStringWidth("Options " + ELLIPSIS);
bheight = myLFont->getLineHeight() + 2;
new ButtonWidget(this, *myLFont, xpos, r.top + 5, bwidth, bheight, "Options" + ELLIPSIS, kDDOptionsCmd);
b = new ButtonWidget(this, *myLFont, xpos, r.top + 5, bwidth, bheight,
"Options" + ELLIPSIS, kDDOptionsCmd);
wid1.push_back(b);
wid1.push_back(myRewindButton);
wid1.push_back(myUnwindButton);
DataGridOpsWidget* ops = new DataGridOpsWidget(this, *myLFont, xpos, ypos);
@ -500,6 +534,9 @@ void DebuggerDialog::addRomArea()
myCpu = new CpuWidget(this, *myLFont, *myNFont, xpos, ypos, max_w);
addToFocusList(myCpu->getFocusList());
addToFocusList(wid1);
addToFocusList(wid2);
xpos = r.left + 10; ypos += myCpu->getHeight() + 10;
myRam = new RiotRamWidget(this, *myLFont, *myNFont, xpos, ypos, r.width() - 10);
addToFocusList(myRam->getFocusList());

View File

@ -96,12 +96,12 @@ void DelayQueueWidget::drawWidget(bool hilite)
w = _w,
lineHeight = _font.getLineHeight();
surface.frameRect(x, y, w, _h, kShadowColor);
surface.frameRect(x, y, w, _h, kColor);
y += 1;
x += 1;
w -= 1;
surface.fillRect(x, y, w - 1, _h - 2, kBGColorHi);
surface.fillRect(x, y, w - 1, _h - 2, kDlgColor);
y += 2;
x += 2;

View File

@ -32,15 +32,14 @@ PaddleWidget::PaddleWidget(GuiObject* boss, const GUI::Font& font,
int xpos = x, ypos = y, lwidth = font.getStringWidth("Right (Paddles)");
new StaticTextWidget(boss, font, xpos, ypos+2, lwidth,
fontHeight, label, TextAlign::Left);
fontHeight, label);
ypos += lineHeight + 20;
const string& p0string = leftport ? "P0 pot " : "P2 pot ";
const string& p1string = leftport ? "P1 pot " : "P3 pot ";
lwidth = font.getStringWidth("P3 pot: ");
myP0Resistance =
new SliderWidget(boss, font, xpos, ypos, 10*fontWidth, lineHeight,
p0string, lwidth, kP0Changed);
new SliderWidget(boss, font, xpos, ypos,
p0string, 0, kP0Changed);
myP0Resistance->setMinValue(0);
myP0Resistance->setMaxValue(uInt32(Paddles::MAX_RESISTANCE));
myP0Resistance->setStepValue(uInt32(Paddles::MAX_RESISTANCE/100));
@ -53,8 +52,8 @@ PaddleWidget::PaddleWidget(GuiObject* boss, const GUI::Font& font,
xpos = x; ypos += 2*lineHeight;
myP1Resistance =
new SliderWidget(boss, font, xpos, ypos, 10*fontWidth, lineHeight,
p1string, lwidth, kP1Changed);
new SliderWidget(boss, font, xpos, ypos,
p1string, 0, kP1Changed);
myP1Resistance->setMinValue(0);
myP1Resistance->setMaxValue(uInt32(Paddles::MAX_RESISTANCE));
myP1Resistance->setStepValue(uInt32(Paddles::MAX_RESISTANCE/100));

View File

@ -46,6 +46,7 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n
const int bwidth = lfont.getStringWidth("Compare " + ELLIPSIS),
bheight = myLineHeight + 2;
const int VGAP = 4;
WidgetArray wid;
int ypos = y + myLineHeight;
@ -63,28 +64,35 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n
myUndoButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight,
"Undo", kUndoCmd);
wid.push_back(myUndoButton);
myUndoButton->setTarget(this);
by += bheight + VGAP;
myRevertButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight,
"Revert", kRevertCmd);
wid.push_back(myRevertButton);
myRevertButton->setTarget(this);
by += bheight + VGAP * 6;
mySearchButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight,
"Search" + ELLIPSIS, kSearchCmd);
wid.push_back(mySearchButton);
mySearchButton->setTarget(this);
by += bheight + VGAP;
myCompareButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight,
"Compare" + ELLIPSIS, kCmpCmd);
wid.push_back(myCompareButton);
myCompareButton->setTarget(this);
by += bheight + VGAP;
myRestartButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight,
"Reset", kRestartCmd);
wid.push_back(myRestartButton);
myRestartButton->setTarget(this);
addToFocusList(wid);
// Labels for RAM grid
myRamStart =
new StaticTextWidget(_boss, lfont, xpos - _font.getStringWidth("xxxx"),
@ -146,8 +154,8 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n
myLabel->setEditable(false, true);
// Inputbox which will pop up when searching RAM
StringList labels = { "Search " };
myInputBox = make_unique<InputTextDialog>(boss, lfont, nfont, labels);
StringList labels = { "Value" };
myInputBox = make_unique<InputTextDialog>(boss, lfont, nfont, labels, " ");
myInputBox->setTarget(this);
// Start with these buttons disabled
@ -247,7 +255,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
{
const string& result = doSearch(myInputBox->getResult());
if(result != "")
myInputBox->setTitle(result);
myInputBox->setMessage(result);
else
myInputBox->close();
break;
@ -257,7 +265,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
{
const string& result = doCompare(myInputBox->getResult());
if(result != "")
myInputBox->setTitle(result);
myInputBox->setMessage(result);
else
myInputBox->close();
break;
@ -322,11 +330,13 @@ void RamWidget::showInputBox(int cmd)
// Add inputbox in the middle of the RAM widget
uInt32 x = getAbsX() + ((getWidth() - myInputBox->getWidth()) >> 1);
uInt32 y = getAbsY() + ((getHeight() - myInputBox->getHeight()) >> 1);
myInputBox->show(x, y);
myInputBox->setText("");
myInputBox->setTitle("");
myInputBox->setMessage("");
myInputBox->setFocus(0);
myInputBox->setEmitSignal(cmd);
myInputBox->setTitle(cmd == kSValEntered ? "Search" : "Compare");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -115,9 +115,9 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
addFocusWidget(myTimWrite);
// Timer registers (RO)
const char* const readNames[] = { "INTIM", "TIMINT", "Total Clks", "INTIM Clks" };
xpos = 10; ypos += myTimWrite->getHeight() + lineHeight;
for(int row = 0; row < 4; ++row)
const char* const readNames[] = { "INTIM", "TIMINT", "Total Clks", "INTIM Clks", "Divider" };
xpos = 10; ypos += myTimWrite->getHeight() + lineHeight / 2;
for(int row = 0; row < 5; ++row)
{
t = new StaticTextWidget(boss, lfont, xpos, ypos + row*lineHeight + 2,
10*fontWidth, fontHeight, readNames[row], TextAlign::Left);
@ -127,6 +127,11 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
myTimRead->setTarget(this);
myTimRead->setEditable(false);
ypos += myTimRead->getHeight() - 1;
myTimDivider = new DataGridWidget(boss, nfont, xpos, ypos, 1, 1, 4, 32, Common::Base::F_10_4);
myTimDivider->setTarget(this);
myTimDivider->setEditable(false);
// Controller ports
const RiotDebug& riot = instance().debugger().riotDebug();
xpos = col; ypos = 10;
@ -315,6 +320,11 @@ void RiotWidget::loadConfig()
changed.push_back(state.INTIMCLKS != oldstate.INTIMCLKS);
myTimRead->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear();
alist.push_back(0); vlist.push_back(state.TIMDIV);
changed.push_back(state.TIMDIV != oldstate.TIMDIV);
myTimDivider->setList(alist, vlist, changed);
// Console switches (inverted, since 'selected' in the UI
// means 'grounded' in the system)
myP0Diff->setSelectedIndex(riot.diffP0(), state.swchbReadBits[1] != oldstate.swchbReadBits[1]);

View File

@ -59,6 +59,7 @@ class RiotWidget : public Widget, public CommandSender
DataGridWidget* myTimWrite;
DataGridWidget* myTimRead;
DataGridWidget* myTimDivider;
ControllerWidget *myLeftControl, *myRightControl;
PopUpWidget *myP0Diff, *myP1Diff;

View File

@ -288,6 +288,20 @@ void RomListWidget::handleMouseWheel(int x, int y, int direction)
myScrollBar->handleMouseWheel(x, y, direction);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RomListWidget::handleText(char text)
{
@ -458,9 +472,7 @@ void RomListWidget::drawWidget(bool hilite)
const GUI::Rect& l = getLineRect();
// Draw a thin frame around the list and to separate columns
s.hLine(_x, _y, _x + _w - 1, kColor);
s.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
s.vLine(_x, _y, _y + _h - 1, kColor);
s.frameRect(_x, _y, _w + 1, _h, hilite ? kWidColorHi : kColor);
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
// Draw the list items
@ -484,7 +496,7 @@ void RomListWidget::drawWidget(bool hilite)
// Draw highlighted item in a frame
if (_highlightedItem == pos)
s.frameRect(_x + l.x() - 3, ypos - 1, _w - l.x(), _fontHeight, kTextColorHi);
s.frameRect(_x + l.x() - 3, ypos - 1, _w - l.x(), _fontHeight, kWidColorHi);
// Draw the selected item inverted, on a highlighted background.
if(_selectedItem == pos && _hasFocus)
@ -495,7 +507,7 @@ void RomListWidget::drawWidget(bool hilite)
bytesColor = kTextColorInv;
}
else
s.frameRect(_x + r.x() - 3, ypos - 1, r.width(), _fontHeight, kTextColorHi);
s.frameRect(_x + r.x() - 3, ypos - 1, r.width(), _fontHeight, kWidColorHi);
}
// Draw labels

View File

@ -61,6 +61,8 @@ class RomListWidget : public EditableWidget
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
bool handleText(char text) override;
bool handleKeyDown(StellaKey key, StellaMod mod) override;
bool handleKeyUp(StellaKey key, StellaMod mod) override;

View File

@ -164,9 +164,18 @@ void TiaZoomWidget::handleMouseMoved(int x, int y)
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaZoomWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaZoomWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
myMouseMoving = false;
}
@ -242,11 +251,7 @@ void TiaZoomWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
s.fillRect(_x+1, _y+1, _w-2, _h-2, kBGColor);
#ifndef FLAT_UI
s.box(_x, _y, _w, _h, kColor, kShadowColor);
#else
s.frameRect(_x, _y, _w, _h, kColor);
#endif
s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor);
// Draw the zoomed image
// This probably isn't as efficient as it can be, but it's a small area
@ -269,11 +274,7 @@ void TiaZoomWidget::drawWidget(bool hilite)
{
uInt32 idx = y*width + x;
uInt32 color = currentFrame[idx] | (idx > scanoffset ? 1 : 0);
#ifndef FLAT_UI
s.fillRect(_x + col + 2, _y + row + 2, wzoom, hzoom, color);
#else
s.fillRect(_x + col + 1, _y + row + 1, wzoom, hzoom, color);
#endif
}
}
}

View File

@ -35,6 +35,9 @@ class TiaZoomWidget : public Widget, public CommandSender
void loadConfig() override;
void setPos(int x, int y);
protected:
void handleMouseEntered() override;
private:
void zoom(int level);
void recalc();

View File

@ -76,23 +76,16 @@ void ToggleBitWidget::drawWidget(bool hilite)
int row, col;
string buffer;
s.frameRect(_x, _y, _w, _h, hilite && isEnabled() && isEditable() ? kWidColorHi : kColor);
// Draw the internal grid and labels
int linewidth = _cols * _colWidth;
#ifndef FLAT_UI
for (row = 0; row <= _rows; row++)
s.hLine(_x, _y + (row * _rowHeight), _x + linewidth, kColor);
int lineheight = _rows * _rowHeight;
for (col = 0; col <= _cols; col++)
s.vLine(_x + (col * _colWidth), _y, _y + lineheight, kColor);
#else
s.frameRect(_x, _y, _w, _h, kColor);
for(row = 1; row <= _rows - 1; row++)
s.hLine(_x + 1, _y + (row * _rowHeight), _x + linewidth - 1, kBGColorLo);
int lineheight = _rows * _rowHeight;
for(col = 1; col <= _cols - 1; col++)
s.vLine(_x + (col * _colWidth), _y + 1, _y + lineheight - 1, kBGColorLo);
#endif
// Draw the list items
for (row = 0; row < _rows; row++)

View File

@ -123,12 +123,14 @@ void TogglePixelWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
int row, col;
s.frameRect(_x, _y, _w, _h, hilite && isEnabled() && isEditable() ? kWidColorHi : kColor);
// Draw the internal grid and labels
int linewidth = _cols * _colWidth;
for (row = 0; row <= _rows; row++)
for (row = 1; row <= _rows - 1; row++)
s.hLine(_x, _y + (row * _rowHeight), _x + linewidth, kColor);
int lineheight = _rows * _rowHeight;
for (col = 0; col <= _cols; col++)
for (col = 1; col <= _cols - 1; col++)
s.vLine(_x + (col * _colWidth), _y, _y + lineheight, kColor);
// Draw the pixels
@ -155,10 +157,6 @@ void TogglePixelWidget::drawWidget(bool hilite)
// Cross out the bits?
if(_crossBits)
{
#ifndef FLAT_UI
for(row = 1; row < 4; ++row)
s.hLine(_x, _y + (row * lineheight / 4), _x + linewidth, kColor);
#else
for(col = 0; col < _cols; ++col)
{
int x = _x + col * _colWidth;
@ -166,6 +164,5 @@ void TogglePixelWidget::drawWidget(bool hilite)
s.line(x + 1, _y + 1, x + _colWidth - 1, _y + lineheight - 1, kColor);
s.line(x + _colWidth - 1, _y + 1, x + 1, _y + lineheight - 1, kColor);
}
#endif
}
}

View File

@ -40,6 +40,20 @@ ToggleWidget::ToggleWidget(GuiObject* boss, const GUI::Font& font,
WIDGET_WANTS_RAWDATA;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ToggleWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ToggleWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ToggleWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
{

View File

@ -68,6 +68,8 @@ class ToggleWidget : public Widget, public CommandSender
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
bool handleKeyDown(StellaKey key, StellaMod mod) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;

View File

@ -294,33 +294,25 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
{
myOSystem.frameBuffer().toggleFullscreen();
}
// state rewinding must work in pause mode too
// State rewinding must work in pause mode too
else if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
{
switch(key)
{
case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states
myOSystem.frameBuffer().setPauseDelay();
setEventState(EventHandlerState::PAUSE);
myOSystem.state().rewindState((StellaModTest::isShift(mod) && state) ? 10 : 1);
enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, false);
break;
case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states
myOSystem.frameBuffer().setPauseDelay();
setEventState(EventHandlerState::PAUSE);
myOSystem.state().unwindState((StellaModTest::isShift(mod) && state) ? 10 : 1);
enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, true);
break;
case KBDK_DOWN: // Alt-down rewinds to start of list
myOSystem.frameBuffer().setPauseDelay();
setEventState(EventHandlerState::PAUSE);
myOSystem.state().rewindState(1000);
enterTimeMachineMenuMode(1000, false);
break;
case KBDK_UP: // Alt-up rewinds to end of list
myOSystem.frameBuffer().setPauseDelay();
setEventState(EventHandlerState::PAUSE);
myOSystem.state().unwindState(1000);
enterTimeMachineMenuMode(1000, true);
break;
default:
@ -329,7 +321,7 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
}
}
// These only work when in emulation mode
if(!handled && myState == EventHandlerState::EMULATION)
if(!handled && (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE))
{
handled = true;
switch(key)
@ -539,7 +531,7 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
handleEvent(Event::Quit, 1);
}
// These only work when in emulation mode
else if(myState == EventHandlerState::EMULATION)
else if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
{
switch(key)
{
@ -614,11 +606,34 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
// Don't pass the key on if we've already taken care of it
if(handled) return;
// Handle keys which switch eventhandler state
// Arrange the logic to take advantage of short-circuit evaluation
if(!(StellaModTest::isControl(mod) || StellaModTest::isShift(mod) || StellaModTest::isAlt(mod)) &&
!state && eventStateChange(myKeyTable[key][kEmulationMode]))
return;
if(!(StellaModTest::isControl(mod) || StellaModTest::isShift(mod) || StellaModTest::isAlt(mod)))
{
// special handling for Escape key
if(state && key == KBDK_ESCAPE)
{
if(myState == EventHandlerState::PAUSE)
{
setEventState(EventHandlerState::EMULATION);
return;
}
else if(myState == EventHandlerState::CMDMENU ||
myState == EventHandlerState::TIMEMACHINE)
{
leaveMenuMode();
return;
}
else if(myState == EventHandlerState::DEBUGGER && myOSystem.debugger().canExit())
{
leaveDebugMode();
return;
}
}
// Handle keys which switch eventhandler state
if(!state && eventStateChange(myKeyTable[key][kEmulationMode]))
return;
}
// Otherwise, let the event handler deal with it
switch(myState)
@ -919,7 +934,7 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleEvent(Event::Type event, int state)
void EventHandler::handleEvent(Event::Type event, Int32 state)
{
// Take care of special events that aren't part of the emulation core
// or need to be preprocessed before passing them on
@ -1223,14 +1238,14 @@ bool EventHandler::eventStateChange(Event::Type type)
break;
case Event::OptionsMenuMode:
if(myState == EventHandlerState::EMULATION)
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
enterMenuMode(EventHandlerState::OPTIONSMENU);
else
handled = false;
break;
case Event::CmdMenuMode:
if(myState == EventHandlerState::EMULATION)
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
enterMenuMode(EventHandlerState::CMDMENU);
else if(myState == EventHandlerState::CMDMENU)
leaveMenuMode();
@ -1239,8 +1254,8 @@ bool EventHandler::eventStateChange(Event::Type type)
break;
case Event::TimeMachineMode:
if(myState == EventHandlerState::EMULATION)
enterMenuMode(EventHandlerState::TIMEMACHINE);
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
enterTimeMachineMenuMode(0, false);
else if(myState == EventHandlerState::TIMEMACHINE)
leaveMenuMode();
else
@ -1248,9 +1263,10 @@ bool EventHandler::eventStateChange(Event::Type type)
break;
case Event::DebuggerMode:
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE)
if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE
|| myState == EventHandlerState::TIMEMACHINE)
enterDebugMode();
else if(myState == EventHandlerState::DEBUGGER)
else if(myState == EventHandlerState::DEBUGGER && myOSystem.debugger().canExit())
leaveDebugMode();
else
handled = false;
@ -2139,6 +2155,17 @@ void EventHandler::leaveDebugMode()
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::enterTimeMachineMenuMode(uInt32 numWinds, bool unwind)
{
// add one extra state if we are in Time Machine mode
// TODO: maybe remove this state if we leave the menu at this new state
myOSystem.state().addExtraState("enter Time Machine dialog"); // force new state
// TODO: display last wind message (numWinds != 0) in time machine dialog
enterMenuMode(EventHandlerState::TIMEMACHINE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setEventState(EventHandlerState state)
{

View File

@ -24,7 +24,6 @@ class Console;
class OSystem;
class MouseControl;
class DialogContainer;
class EventMappingWidget;
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
@ -137,6 +136,7 @@ class EventHandler
void leaveMenuMode();
bool enterDebugMode();
void leaveDebugMode();
void enterTimeMachineMenuMode(uInt32 numWinds, bool unwind);
void takeSnapshot(uInt32 number = 0);
/**
@ -473,7 +473,6 @@ class EventHandler
The following methods take care of assigning action mappings.
*/
void setActionMappings(EventMode mode);
void setKeyNames();
void setKeymap();
void setDefaultKeymap(Event::Type, EventMode mode);
void setDefaultJoymap(Event::Type, EventMode mode);

View File

@ -154,8 +154,15 @@ void FBSurface::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 color)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurface::drawChar(const GUI::Font& font, uInt8 chr,
uInt32 tx, uInt32 ty, uInt32 color)
uInt32 tx, uInt32 ty, uInt32 color, uInt32 shadowColor)
{
if(shadowColor != 0)
{
drawChar(font, chr, tx + 1, ty + 0, shadowColor);
drawChar(font, chr, tx + 0, ty + 1, shadowColor);
drawChar(font, chr, tx + 1, ty + 1, shadowColor);
}
const FontDesc& desc = font.desc();
// If this character is not included in the font, use the default char.
@ -263,24 +270,6 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
case FrameStyle::Dashed:
uInt32 i, skip, lwidth = 1;
#ifndef FLAT_UI
for(i = x, skip = 1; i < x+w-1; i=i+lwidth+1, ++skip)
{
if(skip % 2)
{
hLine(i, y, i + lwidth, color);
hLine(i, y + h - 1, i + lwidth, color);
}
}
for(i = y, skip = 1; i < y+h-1; i=i+lwidth+1, ++skip)
{
if(skip % 2)
{
vLine(x, i, i + lwidth, color);
vLine(x + w - 1, i, i + lwidth, color);
}
}
#else
for(i = x; i < x + w; i += 2)
{
hLine(i, y, i, color);
@ -291,7 +280,6 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
vLine(x, i, i, color);
vLine(x + w - 1, i, i, color);
}
#endif
break;
}
}
@ -300,7 +288,7 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
void FBSurface::drawString(const GUI::Font& font, const string& s,
int x, int y, int w,
uInt32 color, TextAlign align,
int deltax, bool useEllipsis)
int deltax, bool useEllipsis, uInt32 shadowColor)
{
const string ELLIPSIS = "\x1d"; // "..."
const int leftX = x, rightX = x + w;
@ -313,43 +301,22 @@ void FBSurface::drawString(const GUI::Font& font, const string& s,
// String is too wide. So we shorten it "intelligently", by replacing
// parts of it by an ellipsis ("..."). There are three possibilities
// for this: replace the start, the end, or the middle of the string.
// What is best really depends on the context; but unless we want to
// make this configurable, replacing the middle probably is a good
// compromise.
const int ellipsisWidth = font.getStringWidth(ELLIPSIS);
// SLOW algorithm to remove enough of the middle. But it is good enough for now.
const int halfWidth = (w - ellipsisWidth) / 2;
int w2 = 0;
// What is best really depends on the context; but most applications
// replace the end. So we use that too.
int w2 = font.getStringWidth(ELLIPSIS);
// SLOW algorithm to find the acceptable length. But it is good enough for now.
for(i = 0; i < s.size(); ++i)
{
int charWidth = font.getCharWidth(s[i]);
if(w2 + charWidth > halfWidth)
if(w2 + charWidth > w)
break;
w2 += charWidth;
str += s[i];
}
// At this point we know that the first 'i' chars are together 'w2'
// pixels wide. We took the first i-1, and add "..." to them.
str += ELLIPSIS;
// The original string is width wide. Of those we already skipped past
// w2 pixels, which means (width - w2) remain.
// The new str is (w2+ellipsisWidth) wide, so we can accomodate about
// (w - (w2+ellipsisWidth)) more pixels.
// Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) =
// (width + ellipsisWidth - w)
int skip = width + ellipsisWidth - w;
for(; i < s.size() && skip > 0; ++i)
skip -= font.getCharWidth(s[i]);
// Append the remaining chars, if any
for(; i < s.size(); ++i)
str += s[i];
width = font.getStringWidth(str);
}
else
@ -367,7 +334,7 @@ void FBSurface::drawString(const GUI::Font& font, const string& s,
if(x+w > rightX)
break;
if(x >= leftX)
drawChar(font, str[i], x, y, color);
drawChar(font, str[i], x, y, color, shadowColor);
x += w;
}

View File

@ -134,7 +134,7 @@ class FBSurface
@param color The color of the character
*/
virtual void drawChar(const GUI::Font& font, uInt8 c, uInt32 x, uInt32 y,
uInt32 color);
uInt32 color, uInt32 shadowColor = 0);
/**
This method should be called to draw the bitmap image.
@ -217,7 +217,7 @@ class FBSurface
virtual void drawString(
const GUI::Font& font, const string& s, int x, int y, int w,
uInt32 color, TextAlign align = TextAlign::Left,
int deltax = 0, bool useEllipsis = true);
int deltax = 0, bool useEllipsis = true, uInt32 shadowColor = 0);
/**
This method should be called to indicate that the surface has been

View File

@ -46,10 +46,12 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
: myOSystem(osystem),
myInitializedCount(0),
myPausedCount(0),
myCurrentModeList(nullptr)
myStatsEnabled(false),
myLastFrameRate(60),
myCurrentModeList(nullptr),
myTotalTime(0),
myTotalFrames(0)
{
myMsg.surface = myStatsMsg.surface = nullptr;
myStatsEnabled = myMsg.enabled = myStatsMsg.enabled = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -229,8 +231,8 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
// Create surfaces for TIA statistics and general messages
myStatsMsg.color = kColorInfo;
myStatsMsg.w = infoFont().getMaxCharWidth() * 24 + 2;
myStatsMsg.h = (infoFont().getFontHeight() + 2) * 2;
myStatsMsg.w = font().getMaxCharWidth() * 30 + 3;
myStatsMsg.h = (font().getFontHeight() + 2) * 2;
if(!myStatsMsg.surface)
{
@ -285,36 +287,10 @@ void FrameBuffer::update()
// Show frame statistics
if(myStatsMsg.enabled)
{
const ConsoleInfo& info = myOSystem.console().about();
char msg[30];
std::snprintf(msg, 30, "%3u @ %3.2ffps => %s",
myOSystem.console().tia().scanlinesLastFrame(),
myOSystem.console().getFramerate(), info.DisplayFormat.c_str());
myStatsMsg.surface->invalidate();
string bsinfo = info.BankSwitch +
(myOSystem.settings().getBool("dev.settings") ? "| Developer" : "| Player");
// draw shadowed text
myStatsMsg.surface->drawString(infoFont(), msg, 1 + 1, 1 + 0,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), msg, 1 + 0, 1 + 1,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), msg, 1 + 1, 1 + 1,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), msg, 1, 1,
myStatsMsg.w, myStatsMsg.color);
myStatsMsg.surface->drawString(infoFont(), bsinfo, 1 + 1, 15 + 0,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), bsinfo, 1 + 0, 15 + 1,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), bsinfo, 1 + 1, 15 + 1,
myStatsMsg.w, kBGColor);
myStatsMsg.surface->drawString(infoFont(), bsinfo, 1, 15,
myStatsMsg.w, myStatsMsg.color);
myStatsMsg.surface->setDirty();
myStatsMsg.surface->setDstPos(myImageRect.x() + 1, myImageRect.y() + 1);
myStatsMsg.surface->render();
}
drawFrameStats();
else
myLastFrameRate = myOSystem.console().getFramerate();
myLastScanlines = myOSystem.console().tia().scanlinesLastFrame();
myPausedCount = 0;
break; // EventHandlerState::EMULATION
}
@ -400,6 +376,66 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
myMsg.enabled = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::drawFrameStats()
{
const ConsoleInfo& info = myOSystem.console().about();
char msg[30];
uInt32 color;
const int XPOS = 2, YPOS = 0;
int xPos = XPOS;
myStatsMsg.surface->invalidate();
string bsinfo = info.BankSwitch +
(myOSystem.settings().getBool("dev.settings") ? "| Developer" : "| Player");
// draw shadowed text
color = myOSystem.console().tia().scanlinesLastFrame() != myLastScanlines ? kDbgColorRed : myStatsMsg.color;
std::snprintf(msg, 30, "%3u", myOSystem.console().tia().scanlinesLastFrame());
myStatsMsg.surface->drawString(font(), msg, xPos, YPOS,
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
xPos += font().getStringWidth(msg);
std::snprintf(msg, 30, " => %s", info.DisplayFormat.c_str());
myStatsMsg.surface->drawString(font(), msg, xPos, YPOS,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
xPos += font().getStringWidth(msg);
// draw framerate
float frameRate;
/*if(myOSystem.settings().getInt("framerate") == 0)
{
// if 'Auto' is selected, draw the calculated framerate
frameRate = myOSystem.console().getFramerate();
}
else*/
{
// if 'Auto' is not selected, draw the effective framerate
const TimingInfo& ti = myOSystem.timingInfo();
if(ti.totalFrames - myTotalFrames >= myLastFrameRate)
{
frameRate = 1000000.0 * (ti.totalFrames - myTotalFrames) / (ti.totalTime - myTotalTime);
if(frameRate > myOSystem.console().getFramerate() + 1)
frameRate = 1;
myTotalFrames = ti.totalFrames;
myTotalTime = ti.totalTime;
}
else
frameRate = myLastFrameRate;
}
myLastFrameRate = frameRate;
std::snprintf(msg, 30, " @ %5.2ffps", frameRate);
myStatsMsg.surface->drawString(font(), msg, xPos, YPOS,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(),
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
myStatsMsg.surface->setDirty();
myStatsMsg.surface->setDstPos(myImageRect.x() + 1, myImageRect.y() + 1);
myStatsMsg.surface->render();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFrameStats()
{
@ -490,11 +526,7 @@ inline void FrameBuffer::drawMessage()
myMsg.surface->setDstPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y());
myMsg.surface->fillRect(1, 1, myMsg.w-2, myMsg.h-2, kBtnColor);
#ifndef FLAT_UI
myMsg.surface->box(0, 0, myMsg.w, myMsg.h, kColor, kShadowColor);
#else
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
#endif
myMsg.surface->drawString(font(), myMsg.text, 5, 4,
myMsg.w, myMsg.color, TextAlign::Left);
@ -957,14 +989,17 @@ void FrameBuffer::VideoModeList::setZoom(uInt32 zoom)
kTextColor Normal text color
kTextColorHi Highlighted text color
kTextColorEm Emphasized text color
kTextColorSel Color for selected text
kTextColorInv Color for selected text
*** UI elements (dialog and widgets) ***
kDlgColor Dialog background
kWidColor Widget background
kWidColorHi Widget highlight color
kWidFrameColor Border for currently selected widget
*** Button colors ***
kBtnColor Normal button background
kBtnColorHi Highlighted button background
kBtnBorderColor,
kBtnBorderColorHi,
kBtnTextColor Normal button font color
kBtnTextColorHi Highlighted button font color
*** Checkbox colors ***
@ -975,47 +1010,53 @@ void FrameBuffer::VideoModeList::setZoom(uInt32 zoom)
*** Slider colors ***
kSliderColor,
kSliderColorHi
kSliderBGColor
kSliderBGColorHi
kSliderBGColorLo,
*** Debugger colors ***
kDbgChangedColor Background color for changed cells
kDbgChangedTextColor Text color for changed cells
kDbgColorHi Highlighted color in debugger data cells
kDbgColorRed Red color in debugger
*** Info color ***
kColorinfo
*** Other colors ***
kColorInfo TIA output position color
kColorTitleBar Title bar color
kColorTitleText Title text color
kColorTitleBarLo Disabled title bar color
kColorTitleTextLo Disabled title text color
*/
uInt32 FrameBuffer::ourGUIColors[3][kNumColors-256] = {
// Standard
{ 0x686868, 0x000000, 0xa38c61, 0xdccfa5, 0x404040,
0x000000, 0x62a108, 0x9f0000, 0x000000,
0xc9af7c, 0xf0f0cf, 0xc80000,
0xac3410, 0xd55941, 0xffffff, 0xffd652,
0xac3410,
0xac3410, 0xd55941,
0xac3410, 0xd55941,
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000,
0xffffff
{ 0x686868, 0x000000, 0xa38c61, 0xdccfa5, 0x404040, // base
0x000000, 0xac3410, 0x9f0000, 0xf0f0cf, // text
0xc9af7c, 0xf0f0cf, 0xd55941, 0xc80000, // UI elements
0xac3410, 0xd55941, 0x686868, 0xdccfa5, 0xf0f0cf, 0xf0f0cf, // buttons
0xac3410, // checkbox
0xac3410, 0xd55941, // scrollbar
0xac3410, 0xd55941, 0xdccfa5, 0xf0f0cf, 0xa38c61, // slider
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000, // debugger
0xffffff, 0xac3410, 0xf0f0cf, 0x686868, 0xdccfa5 // other
},
// Classic
{ 0x686868, 0x000000, 0x404040, 0x404040, 0x404040,
0x20a020, 0x00ff00, 0xc80000, 0x20a020,
0x000000, 0x000000, 0xc80000,
0x000000, 0x000000, 0x20a020, 0x00ff00,
0x20a020,
0x20a020, 0x00ff00,
0x20a020, 0x00ff00,
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000,
0x20a020
{ 0x686868, 0x000000, 0x404040, 0x404040, 0x404040, // base
0x20a020, 0x00ff00, 0xc80000, 0x000000, // text
0x000000, 0x000000, 0x00ff00, 0xc80000, // UI elements
0x000000, 0x000000, 0x686868, 0x00ff00, 0x20a020, 0x00ff00, // buttons
0x20a020, // checkbox
0x20a020, 0x00ff00, // scrollbar
0x20a020, 0x00ff00, 0x404040, 0x686868, 0x404040, // slider
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000, // debugger
0x20a020, 0x20a020, 0x000000, 0x686868, 0x404040 // other
},
// Light
{
0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base
0x000000, 0x0078d7, 0x0078d7, 0xffffff, // text
0xf0f0f0, 0xffffff, 0x0f0f0f, // elements
0xe1e1e1, 0xe5f1fb, 0x000000, 0x000000, // buttons
0x333333, // checkbox
0x808080, 0x0078d7, // scrollbar
0x333333, 0x0078d7, // slider
0xffc0c0, 0x000000, 0xe00000, 0xc00000, // debugger
0xffffff // info
{ 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base
0x000000, 0xBDDEF9, 0x0078d7, 0x000000, // text
0xf0f0f0, 0xffffff, 0x0078d7, 0x0f0f0f, // UI elements
0xe1e1e1, 0xe5f1fb, 0x808080, 0x0078d7, 0x000000, 0x000000, // buttons
0x333333, // checkbox
0xc0c0c0, 0x808080, // scrollbar
0x333333, 0x0078d7, 0xc0c0c0, 0x808080, 0xe1e1e1, // slider
0xffc0c0, 0x000000, 0xe00000, 0xc00000, // debugger
0xffffff, 0x333333, 0xf0f0f0, 0x808080, 0xc0c0c0 // other
}
};

View File

@ -458,6 +458,9 @@ class FrameBuffer
string myScreenTitle;
private:
// Draws the frame stats overlay
void drawFrameStats();
// Indicates the number of times the framebuffer was initialized
uInt32 myInitializedCount;
@ -506,10 +509,14 @@ class FrameBuffer
uInt32 color;
shared_ptr<FBSurface> surface;
bool enabled;
Message() : counter(0), x(0), y(0), w(0), h(0), color(0), enabled(false) { }
};
Message myMsg;
Message myStatsMsg;
bool myStatsEnabled;
uInt32 myLastScanlines;
float myLastFrameRate;
bool myGrabMouse;
@ -530,6 +537,9 @@ class FrameBuffer
// Holds UI palette data (standard and classic colours)
static uInt32 ourGUIColors[3][kNumColors-256];
uInt64 myTotalTime;
uInt64 myTotalFrames;
private:
// Following constructors and assignment operators not supported
FrameBuffer() = delete;

View File

@ -53,9 +53,12 @@ enum {
kTextColorInv,
kDlgColor,
kWidColor,
kWidColorHi,
kWidFrameColor,
kBtnColor,
kBtnColorHi,
kBtnBorderColor,
kBtnBorderColorHi,
kBtnTextColor,
kBtnTextColorHi,
kCheckColor,
@ -63,11 +66,18 @@ enum {
kScrollColorHi,
kSliderColor,
kSliderColorHi,
kSliderBGColor,
kSliderBGColorHi,
kSliderBGColorLo,
kDbgChangedColor,
kDbgChangedTextColor,
kDbgColorHi,
kDbgColorRed,
kColorInfo,
kColorTitleBar,
kColorTitleText,
kColorTitleBarLo,
kColorTitleTextLo,
kNumColors
};

View File

@ -18,6 +18,9 @@
#include <cstdio>
#include "System.hxx"
#include "Settings.hxx"
#include "MT24LC256.hxx"
#define DEBUG_EEPROM 0
@ -250,6 +253,9 @@ void MT24LC256::jpee_data_stop()
{
myDataChanged = true;
myPageHit[jpee_address / PAGE_SIZE] = true;
bool devSettings = mySystem.oSystem().settings().getBool("dev.settings");
if(mySystem.oSystem().settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
mySystem.oSystem().frameBuffer().showMessage("AtariVox/SaveKey EEPROM write");
myData[(jpee_address++) & jpee_sizemask] = jpee_packet[i];
if (!(jpee_address & jpee_pagemask))
break; /* Writes can't cross page boundary! */
@ -347,6 +353,12 @@ void MT24LC256::jpee_clock_fall()
}
jpee_state=3;
myPageHit[jpee_address / PAGE_SIZE] = true;
{
bool devSettings = mySystem.oSystem().settings().getBool("dev.settings");
if(mySystem.oSystem().settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
mySystem.oSystem().frameBuffer().showMessage("AtariVox/SaveKey EEPROM read");
}
jpee_nb = (myData[jpee_address & jpee_sizemask] << 1) | 1; /* Fall through */
JPEE_LOG2("I2C_READ(%04X=%02X)",jpee_address,jpee_nb/2);
[[fallthrough]];

View File

@ -633,7 +633,7 @@ void OSystem::mainLoop()
// for that and reset the timers when appropriate
if((myTimingInfo.virt - myTimingInfo.current) > (myTimePerFrame << 1))
{
myTimingInfo.start = myTimingInfo.current = myTimingInfo.virt = getTicks();
myTimingInfo.current = myTimingInfo.virt = getTicks();
}
if(myTimingInfo.current < myTimingInfo.virt)

View File

@ -164,6 +164,7 @@ Settings::Settings(OSystem& osystem)
setInternal("plr.tm.horizon", "10m"); // = ~10 minutes
// Thumb ARM emulation options
setInternal("plr.thumb.trapfatal", "false");
setInternal("plr.eepromaccess", "false");
// developer settings
setInternal("dev.settings", "false");
@ -184,6 +185,7 @@ Settings::Settings(OSystem& osystem)
setInternal("dev.tm.horizon", "10s"); // = ~10 seconds
// Thumb ARM emulation options
setInternal("dev.thumb.trapfatal", "true");
setInternal("dev.eepromaccess", "true");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -574,6 +576,7 @@ void Settings::usage() const
<< " -plr.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -plr.tiadriven <1|0> Drive unused TIA pins randomly on a read/peek\n"
<< " -plr.thumb.trapfatal <1|0> Determines whether errors in ARM emulation throw an exception\n"
<< " -plr.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access messages\n"
<< endl
<< " The same parameters but for developer settings mode\n"
<< " -dev.stats <1|0> Overlay console info during emulation\n"
@ -587,6 +590,7 @@ void Settings::usage() const
<< " -dev.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a read/peek\n"
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation throw an exception\n"
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access messages\n"
<< endl << std::flush;
}

View File

@ -88,6 +88,13 @@ class System : public Serializable
void reset(bool autodetect = false);
public:
/**
Answer the OSystem attached to the system.
@return The attached OSystem
*/
const OSystem& oSystem() const { return myOSystem; }
/**
Answer the 6502 microprocessor attached to the system. If a
processor has not been attached calling this function will fail.

View File

@ -815,10 +815,9 @@ void TIA::update()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIA::enableColorLoss(bool enabled)
{
if (consoleTiming() != ConsoleTiming::pal)
return false;
bool allowColorLoss = consoleTiming() == ConsoleTiming::pal;
if(enabled)
if(allowColorLoss && enabled)
{
myColorLossEnabled = true;
myColorLossActive = myFrameManager->scanlinesLastFrame() & 0x1;
@ -836,7 +835,7 @@ bool TIA::enableColorLoss(bool enabled)
myBackground.applyColorLoss();
}
return true;
return allowColorLoss;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -25,7 +25,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "About Stella"),
myPage(1),
myNumPages(4),
myLinesPerPage(13)
@ -40,7 +40,7 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = 55 * fontWidth + 8;
_h = 15 * lineHeight + 20;
_h = 15 * lineHeight + 20 + _th;
// Add Previous, Next and Close buttons
xpos = 10; ypos = _h - buttonHeight - 10;
@ -50,7 +50,7 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
myPrevButton->clearFlags(WIDGET_ENABLED);
wid.push_back(myPrevButton);
xpos += buttonWidth + 7;
xpos += buttonWidth + 8;
myNextButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Next", GuiObject::kNextCmd);
@ -61,17 +61,17 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Close", GuiObject::kCloseCmd);
wid.push_back(b);
addOKWidget(b); addCancelWidget(b);
addCancelWidget(b);
xpos = 5; ypos = 5;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - 10, fontHeight,
xpos = 5; ypos = 5 + _th;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2, fontHeight,
"", TextAlign::Center);
myTitle->setTextColor(kTextColorEm);
xpos = 10; ypos += lineHeight + 4;
xpos = 16; ypos += lineHeight + 4;
for(int i = 0; i < myLinesPerPage; i++)
{
myDesc.push_back(new StaticTextWidget(this, font, xpos, ypos, _w - 20,
myDesc.push_back(new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2,
fontHeight, "", TextAlign::Left));
myDescStr.push_back("");
ypos += fontHeight;
@ -116,30 +116,30 @@ void AboutDialog::updateStrings(int page, int lines, string& title)
case 2:
title = "The Stella Team";
ADD_ATEXT("\\L\\c0"" Stephen Anthony");
ADD_ATEXT("\\L\\c2"" Lead developer, current maintainer for the");
ADD_ATEXT("\\L\\c2"" Linux/OSX and Windows ports ");
ADD_ATEXT("\\L\\c0"" Christian Speckner");
ADD_ATEXT("\\L\\c2"" Emulation core development, TIA core");
ADD_ATEXT("\\L\\c0"" Eckhard Stolberg");
ADD_ATEXT("\\L\\c2"" Emulation core development");
ADD_ATEXT("\\L\\c0"" Thomas Jentzsch");
ADD_ATEXT("\\L\\c2"" Emulation core development, jack-of-all-trades");
ADD_ATEXT("\\L\\c0"" Brian Watson");
ADD_ATEXT("\\L\\c2"" Emulation core enhancement, debugger support");
ADD_ATEXT("\\L\\c0"" Bradford W. Mott");
ADD_ATEXT("\\L\\c2"" Original author of Stella");
ADD_ATEXT("\\L\\c0""Stephen Anthony");
ADD_ATEXT("\\L\\c2"" Lead developer, current maintainer for the");
ADD_ATEXT("\\L\\c2"" Linux/OSX and Windows ports ");
ADD_ATEXT("\\L\\c0""Christian Speckner");
ADD_ATEXT("\\L\\c2"" Emulation core development, TIA core");
ADD_ATEXT("\\L\\c0""Eckhard Stolberg");
ADD_ATEXT("\\L\\c2"" Emulation core development");
ADD_ATEXT("\\L\\c0""Thomas Jentzsch");
ADD_ATEXT("\\L\\c2"" Emulation core development, jack-of-all-trades");
ADD_ATEXT("\\L\\c0""Brian Watson");
ADD_ATEXT("\\L\\c2"" Emulation core enhancement, debugger support");
ADD_ATEXT("\\L\\c0""Bradford W. Mott");
ADD_ATEXT("\\L\\c2"" Original author of Stella");
break;
case 3:
title = "Contributors";
ADD_ATEXT("\\L\\c0"" See https://stella-emu.github.io/credits.html for");
ADD_ATEXT("\\L\\c0"" people that have contributed to Stella.");
ADD_ATEXT("\\L\\c0""See https://stella-emu.github.io/credits.html for");
ADD_ATEXT("\\L\\c0""people that have contributed to Stella.");
ADD_ALINE();
ADD_ATEXT("\\L\\c0"" Thanks to the ScummVM project for the GUI code.");
ADD_ATEXT("\\L\\c0""Thanks to the ScummVM project for the GUI code.");
ADD_ALINE();
ADD_ATEXT("\\L\\c0"" Thanks to Ian Bogost and the Georgia Tech");
ADD_ATEXT("\\L\\c0"" Atari Team for the CRT Simulation effects.");
ADD_ATEXT("\\L\\c0""Thanks to Ian Bogost and the Georgia Tech Atari Team");
ADD_ATEXT("\\L\\c0""for the CRT Simulation effects.");
break;
case 4:

View File

@ -35,8 +35,11 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent)
: Dialog(osystem, parent, font, "Audio settings")
{
const int VBORDER = 10;
const int HBORDER = 10;
const int INDENT = 20;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
@ -49,22 +52,24 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
VariantList items;
// Set real dimensions
_w = 35 * fontWidth + 10;
_h = 7 * (lineHeight + 4) + 10;
_w = 35 * fontWidth + HBORDER * 2;
_h = 7 * (lineHeight + 4) + VBORDER + _th;
xpos = HBORDER; ypos = VBORDER + _th;
// Enable sound
xpos = HBORDER;
mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos,
"Enable sound", kSoundEnableChanged);
wid.push_back(mySoundEnableCheckbox);
ypos += lineHeight + 4;
xpos += INDENT;
// Volume
xpos = 3 * fontWidth; ypos = 10;
myVolumeSlider = new SliderWidget(this, font, xpos, ypos, 6*fontWidth, lineHeight,
"Volume ", lwidth, kVolumeChanged);
myVolumeSlider = new SliderWidget(this, font, xpos, ypos, 11 * fontWidth + 5, lineHeight,
"Volume ", lwidth, 0, 4 * fontWidth, "%");
myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100);
wid.push_back(myVolumeSlider);
myVolumeLabel = new StaticTextWidget(this, font,
xpos + myVolumeSlider->getWidth() + 4,
ypos + 1,
3*fontWidth, fontHeight, "", TextAlign::Left);
myVolumeLabel->setFlags(WIDGET_CLEARBG);
ypos += lineHeight + 4;
// Fragment size
@ -75,7 +80,7 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
VarList::push_back(items, "2 KB", "2048");
VarList::push_back(items, "4 KB", "4096");
myFragsizePopup = new PopUpWidget(this, font, xpos, ypos,
pwidth + myVolumeLabel->getWidth() - 4, lineHeight,
pwidth, lineHeight,
items, "Sample size (*) ", lwidth);
wid.push_back(myFragsizePopup);
ypos += lineHeight + 4;
@ -88,31 +93,19 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
VarList::push_back(items, "44100 Hz", "44100");
VarList::push_back(items, "48000 Hz", "48000");
myFreqPopup = new PopUpWidget(this, font, xpos, ypos,
pwidth + myVolumeLabel->getWidth() - 4, lineHeight,
pwidth, lineHeight,
items, "Frequency (*) ", lwidth);
wid.push_back(myFreqPopup);
ypos += lineHeight + 4;
// Enable sound
xpos = (_w - (font.getStringWidth("Enable sound") + 10)) / 2;
ypos += 4;
mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos,
"Enable sound", kSoundEnableChanged);
wid.push_back(mySoundEnableCheckbox);
// Add message concerning usage
ypos += lineHeight + 12;
ypos = _h - fontHeight * 2 - 24;
const GUI::Font& infofont = instance().frameBuffer().infoFont();
new StaticTextWidget(this, infofont, 10, ypos,
new StaticTextWidget(this, infofont, HBORDER, ypos,
font.getStringWidth("(*) Requires application restart"), fontHeight,
"(*) Requires application restart", TextAlign::Left);
// Add Defaults, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addToFocusList(wid);
}
@ -122,7 +115,6 @@ void AudioDialog::loadConfig()
{
// Volume
myVolumeSlider->setValue(instance().settings().getInt("volume"));
myVolumeLabel->setLabel(instance().settings().getString("volume"));
// Fragsize
myFragsizePopup->setSelected(instance().settings().getString("fragsize"), "512");
@ -166,7 +158,6 @@ void AudioDialog::saveConfig()
void AudioDialog::setDefaults()
{
myVolumeSlider->setValue(100);
myVolumeLabel->setLabel("100");
myFragsizePopup->setSelected("512", "");
myFreqPopup->setSelected("31400", "");
@ -183,7 +174,6 @@ void AudioDialog::setDefaults()
void AudioDialog::handleSoundEnableChange(bool active)
{
myVolumeSlider->setEnabled(active);
myVolumeLabel->setEnabled(active);
myFragsizePopup->setEnabled(active);
myFreqPopup->setEnabled(active);
}
@ -203,10 +193,6 @@ void AudioDialog::handleCommand(CommandSender* sender, int cmd,
setDefaults();
break;
case kVolumeChanged:
myVolumeLabel->setValue(myVolumeSlider->getValue());
break;
case kSoundEnableChanged:
handleSoundEnableChange(data == 1);
break;

View File

@ -45,12 +45,10 @@ class AudioDialog : public Dialog
private:
enum {
kVolumeChanged = 'ADvc',
kSoundEnableChanged = 'ADse'
};
SliderWidget* myVolumeSlider;
StaticTextWidget* myVolumeLabel;
PopUpWidget* myFragsizePopup;
PopUpWidget* myFreqPopup;
CheckboxWidget* mySoundEnableCheckbox;

View File

@ -33,8 +33,8 @@
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
int max_w, int max_h)
: Dialog(boss->instance(), boss->parent()),
int max_w, int max_h, const string& title)
: Dialog(boss->instance(), boss->parent(), font, title),
CommandSender(boss),
_cmd(0),
_mode(FileSave)
@ -46,38 +46,31 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
const int lineHeight = font.getLineHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4,
selectHeight = lineHeight + 8;
selectHeight = lineHeight + 12;
int xpos, ypos;
ButtonWidget* b;
xpos = 10; ypos = 4;
_title = new StaticTextWidget(this, font, xpos, ypos,
_w - 2 * xpos, lineHeight,
"", TextAlign::Center);
xpos = 10; ypos = 4 + _th;
// Current path - TODO: handle long paths ?
ypos += lineHeight + 4;
_currentPath = new StaticTextWidget(this, font, xpos, ypos,
_w - 2 * xpos, lineHeight,
"", TextAlign::Left);
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Pfad ");
_currentPath = new EditTextWidget(this, font, xpos + t->getWidth(), ypos,
_w - t->getWidth() - 2 * xpos, lineHeight);
_currentPath->setEditable(false);
// Add file list
ypos += lineHeight + 4;
ypos += lineHeight + 8;
_fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos,
_h - selectHeight - buttonHeight - ypos - 20);
_fileList->setEditable(false);
addFocusWidget(_fileList);
// Add currently selected item
ypos += _fileList->getHeight() + 4;
ypos += _fileList->getHeight() + 8;
_type = new StaticTextWidget(this, font, xpos, ypos+2,
font.getStringWidth("Name "), lineHeight,
"Name", TextAlign::Center);
_type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name ");
_selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos,
_w - _type->getWidth() - 2 * xpos, lineHeight, "");
_selected->setEditable(false);
addFocusWidget(_selected);
// Buttons
_goUpButton = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
@ -111,11 +104,10 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::show(const string& title, const string& startpath,
void BrowserDialog::show(const string& startpath,
BrowserDialog::ListMode mode, int cmd,
const string& ext)
{
_title->setLabel(title);
_cmd = cmd;
_mode = mode;
@ -125,17 +117,23 @@ void BrowserDialog::show(const string& title, const string& startpath,
_fileList->setFileListMode(FilesystemNode::kListAll);
_fileList->setFileExtension(ext);
_selected->setEditable(false);
_selected->clearFlags(WIDGET_INVISIBLE);
_type->clearFlags(WIDGET_INVISIBLE);
break;
case FileSave:
_fileList->setFileListMode(FilesystemNode::kListAll);
_fileList->setFileExtension(ext);
_selected->setEditable(false); // FIXME - disable user input for now
_selected->clearFlags(WIDGET_INVISIBLE);
_type->clearFlags(WIDGET_INVISIBLE);
break;
case Directories:
_fileList->setFileListMode(FilesystemNode::kListDirectoriesOnly);
_selected->setEditable(false);
_selected->setFlags(WIDGET_INVISIBLE);
_type->setFlags(WIDGET_INVISIBLE);
break;
}
@ -164,7 +162,7 @@ void BrowserDialog::updateUI()
_goUpButton->setEnabled(_fileList->currentDir().hasParent());
// Update the path display
_currentPath->setLabel(_fileList->currentDir().getShortPath());
_currentPath->setText(_fileList->currentDir().getShortPath());
// Enable/disable OK button based on current mode
bool enable = _mode == Directories || !_fileList->selected().isDirectory();

View File

@ -39,11 +39,12 @@ class BrowserDialog : public Dialog, public CommandSender
};
public:
BrowserDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h);
BrowserDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h,
const string& title = "");
virtual ~BrowserDialog() = default;
/** Place the browser window onscreen, using the given attributes */
void show(const string& title, const string& startpath,
void show(const string& startpath,
BrowserDialog::ListMode mode, int cmd, const string& ext = "");
/** Get resulting file node (called after receiving kChooseCmd) */
@ -63,8 +64,7 @@ class BrowserDialog : public Dialog, public CommandSender
int _cmd;
FileListWidget* _fileList;
StaticTextWidget* _currentPath;
StaticTextWidget* _title;
EditTextWidget* _currentPath;
StaticTextWidget* _type;
EditTextWidget* _selected;
ButtonWidget* _goUpButton;

View File

@ -47,6 +47,20 @@ CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font,
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::setList(const StringList& list, const BoolArray& state)
{
@ -85,10 +99,7 @@ void CheckListWidget::drawWidget(bool hilite)
int i, pos, len = int(_list.size());
// Draw a thin frame around the list and to separate columns
s.hLine(_x, _y, _x + _w - 1, kColor);
s.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
s.vLine(_x, _y, _y + _h - 1, kColor);
s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor);
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
// Draw the list items

View File

@ -37,13 +37,16 @@ class CheckListWidget : public ListWidget
int x, int y, int w, int h);
virtual ~CheckListWidget() = default;
void setStyle(CheckStyle style);
void setList(const StringList& list, const BoolArray& state);
void setLine(int line, const string& str, const bool& state);
bool getState(int line);
bool getSelectedState() { return getState(_selectedItem); }
protected:
void handleMouseEntered() override;
void handleMouseLeft() override;
private:
bool handleEvent(Event::Type e) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;

View File

@ -48,14 +48,7 @@ void ColorWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
// Draw a thin frame around us.
#ifndef FLAT_UI
s.hLine(_x, _y, _x + _w - 1, kColor);
s.hLine(_x, _y +_h, _x + _w - 1, kShadowColor);
s.vLine(_x, _y, _y+_h, kColor);
s.vLine(_x + _w - 1, _y, _y +_h - 1, kShadowColor);
#else
s.frameRect(_x, _y, _w, _h + 1, kColor);
#endif
// Show the currently selected color
s.fillRect(_x+1, _y+1, _w-2, _h-1, isEnabled() ? _color : kWidColor);
@ -63,12 +56,7 @@ void ColorWidget::drawWidget(bool hilite)
// Cross out the grid?
if(_crossGrid)
{
#ifndef FLAT_UI
for(uInt32 row = 1; row < 4; ++row)
s.hLine(_x, _y + (row * _h/4), _x + _w - 2, kColor);
#else
s.line(_x + 1, _y + 1, _x + _w - 2, _y + _h - 1, kColor);
s.line(_x + _w - 2, _y + 1, _x + 1, _y + _h - 1, kColor);
#endif
}
}

View File

@ -29,7 +29,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
const VariantList& combolist)
: Dialog(boss->instance(), boss->parent()),
: Dialog(boss->instance(), boss->parent(), font, ""),
myComboEvent(Event::NoType)
{
const int lineHeight = font.getLineHeight(),
@ -42,19 +42,15 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
// Set real dimensions
_w = 35 * fontWidth + 10;
_h = 11 * (lineHeight + 4) + 10;
xpos = ypos = 5;
_h = 10 * (lineHeight + 4) + 10 + _th;
xpos = 10;
ypos = 10 + _th;
// Get maximum width of popupwidget
int pwidth = 0;
for(const auto& s: combolist)
pwidth = std::max(font.getStringWidth(s.first), pwidth);
// Label for dialog, indicating which combo is being changed
myComboName = new StaticTextWidget(this, font, xpos, ypos, _w - xpos - 10,
fontHeight, "", TextAlign::Center);
ypos += (lineHeight + 4) + 5;
// Add event popup for 8 events
auto ADD_EVENT_POPUP = [&](int idx, const string& label)
{
@ -75,11 +71,7 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
myEvents[7] = nullptr; ADD_EVENT_POPUP(7, "Event 8 ");
// Add Defaults, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addToFocusList(wid);
}
@ -91,7 +83,7 @@ void ComboDialog::show(Event::Type event, const string& name)
if(event >= Event::Combo1 && event <= Event::Combo16)
{
myComboEvent = event;
myComboName->setLabel("Add events for " + name);
setTitle("Add events for " + name);
open();
}
else

View File

@ -45,7 +45,6 @@ class ComboDialog : public Dialog
private:
Event::Type myComboEvent;
StaticTextWidget* myComboName;
PopUpWidget* myEvents[8];
private:

View File

@ -30,23 +30,25 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
: Dialog(osystem, parent)
{
const GUI::Font& font = instance().frameBuffer().font();
initTitle(font, "Commands");
const int buttonWidth = font.getStringWidth("Right Diff B") + 20,
buttonHeight = font.getLineHeight() + 6,
rowHeight = font.getLineHeight() + 10;
rowHeight = buttonHeight + 8;
// Set real dimensions
_w = 3 * (buttonWidth + 5) + 20;
_h = 6 * rowHeight + 15;
_h = 6 * rowHeight + 8 + _th;
WidgetArray wid;
ButtonWidget* b[16];
int xoffset = 10, yoffset = 10;
int xoffset = 10, yoffset = 8 + _th;
auto ADD_CD_BUTTON = [&](const string& label, int cmd)
{
ButtonWidget* bw = new ButtonWidget(this, font, xoffset, yoffset,
buttonWidth, buttonHeight, label, cmd);
xoffset += buttonWidth + 6;
xoffset += buttonWidth + 8;
return bw;
};
@ -56,31 +58,31 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
b[8] = ADD_CD_BUTTON("Save State", kSaveStateCmd);
// Row 2
xoffset = 10; yoffset += buttonHeight + 3;
xoffset = 10; yoffset += buttonHeight + 8;
b[1] = ADD_CD_BUTTON("Reset", kResetCmd);
b[5] = ADD_CD_BUTTON("Left Diff B", kLeftDiffBCmd);
b[9] = ADD_CD_BUTTON("State Slot", kStateSlotCmd);
// Row 3
xoffset = 10; yoffset += buttonHeight + 3;
xoffset = 10; yoffset += buttonHeight + 8;
b[2] = ADD_CD_BUTTON("Color TV", kColorCmd);
b[6] = ADD_CD_BUTTON("Right Diff A", kRightDiffACmd);
b[10] = ADD_CD_BUTTON("Load State", kLoadStateCmd);
// Row 4
xoffset = 10; yoffset += buttonHeight + 3;
xoffset = 10; yoffset += buttonHeight + 8;
b[3] = ADD_CD_BUTTON("B/W TV", kBWCmd);
b[7] = ADD_CD_BUTTON("Right Diff B", kRightDiffBCmd);
b[11] = ADD_CD_BUTTON("Snapshot", kSnapshotCmd);
// Row 5
xoffset = 10; yoffset += buttonHeight + 3;
b[12] = ADD_CD_BUTTON("NTSC/PAL", kFormatCmd);
xoffset = 10; yoffset += buttonHeight + 8;
b[12] = ADD_CD_BUTTON("TV Format", kFormatCmd);
b[13] = ADD_CD_BUTTON("Palette", kPaletteCmd);
b[14] = ADD_CD_BUTTON("Reload ROM", kReloadRomCmd);
// Row 6
xoffset = 10 + buttonWidth + 6; yoffset += buttonHeight + 3;
xoffset = 10 + buttonWidth + 8; yoffset += buttonHeight + 8;
b[15] = ADD_CD_BUTTON("Exit Game", kExitCmd);
for(int i = 0; i < 16; ++i)

View File

@ -29,94 +29,92 @@
ConfigPathDialog::ConfigPathDialog(
OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, GuiObject* boss)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Configure paths"),
CommandSender(boss),
myFont(font),
myBrowser(nullptr),
myIsGlobal(boss != nullptr)
{
const int VBORDER = 10 + _th;
const int HBORDER = 10;
const int V_GAP = 4;
const int H_GAP = 8;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Properties file") + 20,
buttonHeight = font.getLineHeight() + 4;
const int vBorder = 8;
const int hBorder = 10;
int xpos, ypos;
WidgetArray wid;
ButtonWidget* b;
// Set real dimensions
_w = 56 * fontWidth + 8;
_h = 9 * (lineHeight + 4) + 10;
_w = 64 * fontWidth + HBORDER*2;
_h = 9 * (lineHeight + V_GAP) + VBORDER;
xpos = hBorder; ypos = vBorder;
xpos = HBORDER; ypos = VBORDER;
// ROM path
ButtonWidget* romButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"ROM path" + ELLIPSIS, kChooseRomDirCmd);
wid.push_back(romButton);
xpos += buttonWidth + 10;
myRomPath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myRomPath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myRomPath);
// Cheat file
xpos = hBorder; ypos += romButton->getHeight() + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Cheat file" + ELLIPSIS, kChooseCheatFileCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
myCheatFile = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myCheatFile = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myCheatFile);
// Palette file
xpos = hBorder; ypos += b->getHeight() + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Palette file" + ELLIPSIS, kChoosePaletteFileCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
myPaletteFile = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myPaletteFile = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myPaletteFile);
// Properties file
xpos = hBorder; ypos += b->getHeight() + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Properties file" + ELLIPSIS, kChoosePropsFileCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
myPropsFile = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myPropsFile = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myPropsFile);
// State directory
xpos = hBorder; ypos += b->getHeight() + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"State path" + ELLIPSIS, kChooseStateDirCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
myStatePath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myStatePath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myStatePath);
// NVRAM directory
xpos = hBorder; ypos += b->getHeight() + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"NVRAM path" + ELLIPSIS, kChooseNVRamDirCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
myNVRamPath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + H_GAP;
myNVRamPath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myNVRamPath);
// Add Defaults, OK and Cancel buttons
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
font.getStringWidth("Defaults") + 20, buttonHeight,
"Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addToFocusList(wid);
@ -210,48 +208,48 @@ void ConfigPathDialog::handleCommand(CommandSender* sender, int cmd,
case kChooseRomDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select ROM directory", myRomPath->getText(),
createBrowser("Select ROM directory");
myBrowser->show(myRomPath->getText(),
BrowserDialog::Directories, LauncherDialog::kRomDirChosenCmd);
break;
case kChooseCheatFileCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select cheat file", myCheatFile->getText(),
createBrowser("Select cheat file");
myBrowser->show(myCheatFile->getText(),
BrowserDialog::FileLoad, kCheatFileChosenCmd);
break;
case kChoosePaletteFileCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select palette file", myPaletteFile->getText(),
createBrowser("Select palette file");
myBrowser->show(myPaletteFile->getText(),
BrowserDialog::FileLoad, kPaletteFileChosenCmd);
break;
case kChoosePropsFileCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select properties file", myPropsFile->getText(),
createBrowser("Select properties file");
myBrowser->show(myPropsFile->getText(),
BrowserDialog::FileLoad, kPropsFileChosenCmd);
break;
case kChooseNVRamDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select NVRAM directory", myNVRamPath->getText(),
createBrowser("Select NVRAM directory");
myBrowser->show(myNVRamPath->getText(),
BrowserDialog::Directories, kNVRamDirChosenCmd);
break;
case kChooseStateDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select state directory", myStatePath->getText(),
createBrowser("Select state directory");
myBrowser->show(myStatePath->getText(),
BrowserDialog::Directories, kStateDirChosenCmd);
break;
@ -290,13 +288,15 @@ void ConfigPathDialog::handleCommand(CommandSender* sender, int cmd,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ConfigPathDialog::createBrowser()
void ConfigPathDialog::createBrowser(const string& title)
{
uInt32 w = 0, h = 0;
getResizableBounds(w, h);
// Create file browser dialog
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h);
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
else
myBrowser->setTitle(title);
}

View File

@ -40,7 +40,7 @@ class ConfigPathDialog : public Dialog, public CommandSender
private:
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void createBrowser();
void createBrowser(const string& title);
void loadConfig() override;
void saveConfig() override;

View File

@ -60,11 +60,7 @@ void ContextMenu::addItems(const VariantList& items)
maxwidth = std::max(maxwidth, _font.getStringWidth(e.first));
_x = _y = 0;
#ifndef FLAT_UI
_w = maxwidth + 15;
#else
_w = maxwidth + 23;
#endif
_h = 1; // recalculate this in ::recalc()
_scrollUpColor = _firstEntry > 0 ? kScrollColor : kColor;
@ -106,18 +102,18 @@ void ContextMenu::recalc(const GUI::Rect& image)
{
// Now is the time to adjust the height
// If it's higher than the screen, we need to scroll through
uInt32 maxentries = std::min(18u, (image.height() - 4) / _rowHeight);
uInt32 maxentries = std::min(18u, (image.height() - 2) / _rowHeight);
if(_entries.size() > maxentries)
{
// We show two less than the max, so we have room for two scroll buttons
_numEntries = maxentries - 2;
_h = maxentries * _rowHeight + 4;
_h = maxentries * _rowHeight + 2;
_showScroll = true;
}
else
{
_numEntries = int(_entries.size());
_h = int(_entries.size()) * _rowHeight + 4;
_h = int(_entries.size()) * _rowHeight + 2;
_showScroll = false;
}
_isScrolling = false;
@ -555,23 +551,16 @@ void ContextMenu::drawDialog()
{
// Draw menu border and background
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
#ifndef FLAT_UI
s.box(_x, _y, _w, _h, kColor, kShadowColor);
// Draw the entries, taking scroll buttons into account
int x = _x + 2, y = _y + 2, w = _w - 4;
#else
s.frameRect(_x, _y, _w, _h, kTextColor);
// Draw the entries, taking scroll buttons into account
int x = _x + 1, y = _y + 1, w = _w - 2;
#endif
// Show top scroll area
int offset = _selectedOffset;
if(_showScroll)
{
s.hLine(x, y+_rowHeight-1, w+2, kShadowColor);
s.hLine(x, y+_rowHeight-1, w+2, kColor);
s.drawBitmap(up_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
y += _rowHeight;
offset--;
@ -582,14 +571,14 @@ void ContextMenu::drawDialog()
bool hilite = offset == current;
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
!hilite ? kTextColor : kWidColor);
!hilite ? kTextColor : kTextColorInv);
y += _rowHeight;
}
// Show bottom scroll area
if(_showScroll)
{
s.hLine(x, y, w+2, kShadowColor);
s.hLine(x, y, w+2, kColor);
s.drawBitmap(down_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
}

View File

@ -23,7 +23,6 @@
#include "SaveKey.hxx"
#include "AtariVox.hxx"
#include "Settings.hxx"
#include "EventMappingWidget.hxx"
#include "EditTextWidget.hxx"
#include "PopUpWidget.hxx"
#include "RadioButtonWidget.hxx"
@ -45,7 +44,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent)
: Dialog(osystem, parent, font, "Developer settings")
{
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
@ -55,18 +54,21 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = std::min(53 * fontWidth + 10, max_w);
_h = std::min(15 * (lineHeight + VGAP) + 14, max_h);
_h = std::min(15 * (lineHeight + VGAP) + 14 + _th, max_h);
// The tab widget
xpos = 2; ypos = 4;
myTab = new TabWidget(this, font, xpos, ypos, _w - 2 * xpos, _h - buttonHeight - 16 - ypos);
myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2 * xpos, _h - _th - buttonHeight - 16 - ypos);
addTabWidget(myTab);
addEmulationTab(font);
addVideoTab(font);
addTimeMachineTab(font);
addDebuggerTab(font);
addDefaultOKCancelButtons(font);
WidgetArray wid;
addDefaultsOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
// Activate the first tab
myTab->setActiveTab(0);
@ -83,7 +85,7 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
int lineHeight = font.getLineHeight();
WidgetArray wid;
VariantList items;
int tabID = myTab->addTab(" Emulation ");
int tabID = myTab->addTab("Emulation");
// settings set
mySettingsGroup0 = new RadioButtonGroup();
@ -154,6 +156,12 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
myThumbExceptionWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"Fatal ARM emulation error throws exception");
wid.push_back(myThumbExceptionWidget);
ypos += lineHeight + VGAP;
// AtariVox/SaveKey EEPROM access
myEEPROMAccessWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"Display AtariVox/SaveKey EEPROM R/W access");
wid.push_back(myEEPROMAccessWidget);
// Add items for tab 0
addToFocusList(wid, myTab, tabID);
@ -195,15 +203,13 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
wid.push_back(myTVJitterWidget);
myTVJitterRecWidget = new SliderWidget(myTab, font,
myTVJitterWidget->getRight() + fontWidth * 3, ypos - 1,
8 * fontWidth, lineHeight, "Recovery ",
font.getStringWidth("Recovery "), kTVJitterChanged);
"Recovery ", 0, kTVJitterChanged);
myTVJitterRecWidget->setMinValue(1); myTVJitterRecWidget->setMaxValue(20);
wid.push_back(myTVJitterRecWidget);
myTVJitterRecLabelWidget = new StaticTextWidget(myTab, font,
myTVJitterRecWidget->getRight() + 4,
myTVJitterRecWidget->getTop() + 2,
5 * fontWidth, fontHeight, "", TextAlign::Left);
wid.push_back(myTVJitterRecLabelWidget);
5 * fontWidth, fontHeight, "");
ypos += lineHeight + VGAP;
myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
@ -304,8 +310,10 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
const int VBORDER = 8;
const int VGAP = 4;
int ypos = VBORDER;
int lineHeight = font.getLineHeight();
int fontHeight = font.getFontHeight();
int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
lwidth = fontWidth * 11;
WidgetArray wid;
VariantList items;
int tabID = myTab->addTab("Time Machine");
@ -326,25 +334,21 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
wid.push_back(myTimeMachineWidget);
ypos += lineHeight + VGAP;
int sWidth = font.getMaxCharWidth() * 8;
myStateSizeWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, sWidth, lineHeight,
"Buffer size (*) ", 0, kSizeChanged);
int swidth = fontWidth * 12 + 5; // width of PopUpWidgets below
myStateSizeWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight,
"Buffer size (*) ", 0, kSizeChanged, lwidth, " states");
myStateSizeWidget->setMinValue(20);
myStateSizeWidget->setMaxValue(1000);
myStateSizeWidget->setStepValue(20);
wid.push_back(myStateSizeWidget);
myStateSizeLabelWidget = new StaticTextWidget(myTab, font, myStateSizeWidget->getRight() + 4,
myStateSizeWidget->getTop() + 2, "100 ");
ypos += lineHeight + VGAP;
myUncompressedWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, sWidth, lineHeight,
"Uncompressed size ", 0, kUncompressedChanged);
myUncompressedWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight,
"Uncompressed size ", 0, kUncompressedChanged, lwidth, " states");
myUncompressedWidget->setMinValue(0);
myUncompressedWidget->setMaxValue(1000);
myUncompressedWidget->setStepValue(20);
wid.push_back(myUncompressedWidget);
myUncompressedLabelWidget = new StaticTextWidget(myTab, font, myUncompressedWidget->getRight() + 4,
myUncompressedWidget->getTop() + 2, "50 ");
ypos += lineHeight + VGAP;
items.clear();
@ -418,36 +422,26 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
ypos += lineHeight + VGAP * 4;
pwidth = font.getMaxCharWidth() * 8;
// Debugger width and height
myDebuggerWidthSlider = new SliderWidget(myTab, font, xpos, ypos-1, pwidth,
lineHeight, "Debugger width (*) ",
0, kDWidthChanged);
myDebuggerWidthSlider = new SliderWidget(myTab, font, xpos, ypos-1, "Debugger width (*) ",
0, 0, 6 * fontWidth, "px");
myDebuggerWidthSlider->setMinValue(DebuggerDialog::kSmallFontMinW);
myDebuggerWidthSlider->setMaxValue(ds.w);
myDebuggerWidthSlider->setStepValue(10);
wid.push_back(myDebuggerWidthSlider);
myDebuggerWidthLabel =
new StaticTextWidget(myTab, font,
xpos + myDebuggerWidthSlider->getWidth() + 4,
ypos + 1, 4 * fontWidth, fontHeight, "", TextAlign::Left);
ypos += lineHeight + VGAP;
myDebuggerHeightSlider = new SliderWidget(myTab, font, xpos, ypos-1, pwidth,
lineHeight, "Debugger height (*) ",
0, kDHeightChanged);
myDebuggerHeightSlider = new SliderWidget(myTab, font, xpos, ypos-1, "Debugger height (*) ",
0, 0, 6 * fontWidth, "px");
myDebuggerHeightSlider->setMinValue(DebuggerDialog::kSmallFontMinH);
myDebuggerHeightSlider->setMaxValue(ds.h);
myDebuggerHeightSlider->setStepValue(10);
wid.push_back(myDebuggerHeightSlider);
myDebuggerHeightLabel =
new StaticTextWidget(myTab, font,
xpos + myDebuggerHeightSlider->getWidth() + 4,
ypos + 1, 4 * fontWidth, fontHeight, "", TextAlign::Left);
ypos += lineHeight + VGAP * 4;
myGhostReadsTrapWidget = new CheckboxWidget(myTab, font, HBORDER, ypos + 1,
"Trap on 'ghost' reads", kGhostReads);
wid.push_back(myGhostReadsTrapWidget);
// Add message concerning usage
const GUI::Font& infofont = instance().frameBuffer().infoFont();
@ -465,13 +459,8 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
if(!debuggerAvailable)
{
myDebuggerWidthSlider->clearFlags(WIDGET_ENABLED);
myDebuggerWidthLabel->clearFlags(WIDGET_ENABLED);
myDebuggerHeightSlider->clearFlags(WIDGET_ENABLED);
myDebuggerHeightLabel->clearFlags(WIDGET_ENABLED);
}
// Add items for tab 1
addToFocusList(wid, myTab, tabID);
#else
new StaticTextWidget(myTab, font, 0, 20, _w - 20, font.getFontHeight(),
"Debugger support not included", TextAlign::Center);
@ -480,21 +469,6 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
addToFocusList(wid, myTab, tabID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addDefaultOKCancelButtons(const GUI::Font& font)
{
const int buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
WidgetArray wid;
wid.clear();
ButtonWidget* btn = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(btn);
addOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::loadSettings(SettingsSet set)
{
@ -510,6 +484,8 @@ void DeveloperDialog::loadSettings(SettingsSet set)
myUndrivenPins[set] = instance().settings().getBool(prefix + "tiadriven");
// Thumb ARM emulation exception
myThumbException[set] = instance().settings().getBool(prefix + "thumb.trapfatal");
// AtariVox/SaveKey EEPROM access
myEEPROMAccess[set] = instance().settings().getBool(prefix + "eepromaccess");
// Debug colors
myDebugColors[set] = instance().settings().getBool(prefix + "debugcolors");
@ -542,6 +518,8 @@ void DeveloperDialog::saveSettings(SettingsSet set)
instance().settings().setValue(prefix + "tiadriven", myUndrivenPins[set]);
// Thumb ARM emulation exception
instance().settings().setValue(prefix + "thumb.trapfatal", myThumbException[set]);
// AtariVox/SaveKey EEPROM access
instance().settings().setValue(prefix + "eepromaccess", myEEPROMAccess[set]);
// Debug colors
instance().settings().setValue(prefix + "debugcolors", myDebugColors[set]);
@ -577,6 +555,8 @@ void DeveloperDialog::getWidgetStates(SettingsSet set)
myUndrivenPins[set] = myUndrivenPinsWidget->getState();
// Thumb ARM emulation exception
myThumbException[set] = myThumbExceptionWidget->getState();
// AtariVox/SaveKey EEPROM access
myEEPROMAccess[set] = myEEPROMAccessWidget->getState();
// Debug colors
myDebugColors[set] = myDebugColorsWidget->getState();
@ -612,6 +592,8 @@ void DeveloperDialog::setWidgetStates(SettingsSet set)
myUndrivenPinsWidget->setState(myUndrivenPins[set]);
// Thumb ARM emulation exception
myThumbExceptionWidget->setState(myThumbException[set]);
// AtariVox/SaveKey EEPROM access
myEEPROMAccessWidget->setState(myEEPROMAccess[set]);
handleConsole();
@ -666,9 +648,7 @@ void DeveloperDialog::loadConfig()
w = ds.w; h = ds.h;
myDebuggerWidthSlider->setValue(w);
myDebuggerWidthLabel->setValue(w);
myDebuggerHeightSlider->setValue(h);
myDebuggerHeightLabel->setValue(h);
// Debugger font size
string size = instance().settings().getString("dbg.fontsize");
@ -760,6 +740,8 @@ void DeveloperDialog::setDefaults()
myUndrivenPins[set] = devSettings ? true : false;
// Thumb ARM emulation exception
myThumbException[set] = devSettings ? true : false;
// AtariVox/SaveKey EEPROM access
myEEPROMAccess[set] = devSettings ? true : false;
setWidgetStates(set);
break;
@ -793,9 +775,7 @@ void DeveloperDialog::setDefaults()
uInt32 w = std::min(instance().frameBuffer().desktopSize().w, uInt32(DebuggerDialog::kMediumFontMinW));
uInt32 h = std::min(instance().frameBuffer().desktopSize().h, uInt32(DebuggerDialog::kMediumFontMinH));
myDebuggerWidthSlider->setValue(w);
myDebuggerWidthLabel->setValue(w);
myDebuggerHeightSlider->setValue(h);
myDebuggerHeightLabel->setValue(h);
myDebuggerFontSize->setSelected("medium");
myDebuggerFontStyle->setSelected("0");
@ -885,14 +865,6 @@ void DeveloperDialog::handleCommand(CommandSender* sender, int cmd, int data, in
break;
#ifdef DEBUGGER_SUPPORT
case kDWidthChanged:
myDebuggerWidthLabel->setValue(myDebuggerWidthSlider->getValue());
break;
case kDHeightChanged:
myDebuggerHeightLabel->setValue(myDebuggerHeightSlider->getValue());
break;
case kDFontSizeChanged:
handleFontSize();
break;
@ -965,11 +937,7 @@ void DeveloperDialog::handleTimeMachine()
bool enable = myTimeMachineWidget->getState();
myStateSizeWidget->setEnabled(enable);
myStateSizeLabelWidget->setEnabled(enable);
myUncompressedWidget->setEnabled(enable);
myUncompressedLabelWidget->setEnabled(enable);
myStateIntervalWidget->setEnabled(enable);
uInt32 size = myStateSizeWidget->getValue();
@ -994,7 +962,6 @@ void DeveloperDialog::handleSize()
if(horizon == -1)
horizon = 0;
myStateSizeLabelWidget->setValue(size);
// adapt horizon and interval
do
{
@ -1024,8 +991,6 @@ void DeveloperDialog::handleUncompressed()
uInt32 size = myStateSizeWidget->getValue();
uInt32 uncompressed = myUncompressedWidget->getValue();
myUncompressedLabelWidget->setValue(myUncompressedWidget->getValue());
if(size < uncompressed)
myStateSizeWidget->setValue(uncompressed);
myStateHorizonWidget->setEnabled(myTimeMachineWidget->getState() && size > uncompressed);
@ -1223,16 +1188,10 @@ void DeveloperDialog::handleFontSize()
myDebuggerWidthSlider->setMinValue(minW);
if(minW > uInt32(myDebuggerWidthSlider->getValue()))
{
myDebuggerWidthSlider->setValue(minW);
myDebuggerWidthLabel->setValue(minW);
}
myDebuggerHeightSlider->setMinValue(minH);
if(minH > uInt32(myDebuggerHeightSlider->getValue()))
{
myDebuggerHeightSlider->setValue(minH);
myDebuggerHeightLabel->setValue(minH);
}
#endif
}

View File

@ -21,7 +21,6 @@
class OSystem;
class GuiObject;
class TabWidget;
class EventMappingWidget;
class CheckboxWidget;
class EditTextWidget;
class PopUpWidget;
@ -75,8 +74,6 @@ class DeveloperDialog : public Dialog
kPFColourChangedCmd = 'GOpf',
kBLColourChangedCmd = 'GObl',
#ifdef DEBUGGER_SUPPORT
kDWidthChanged = 'UIdw',
kDHeightChanged = 'UIdh',
kDFontSizeChanged = 'UIfs',
kGhostReads = 'Dbgh'
#endif
@ -105,6 +102,7 @@ class DeveloperDialog : public Dialog
CheckboxWidget* myRandomizeCPUWidget[5];
CheckboxWidget* myUndrivenPinsWidget;
CheckboxWidget* myThumbExceptionWidget;
CheckboxWidget* myEEPROMAccessWidget;
// Video widgets
RadioButtonGroup* mySettingsGroup1;
@ -120,18 +118,14 @@ class DeveloperDialog : public Dialog
RadioButtonGroup* mySettingsGroup2;
CheckboxWidget* myTimeMachineWidget;
SliderWidget* myStateSizeWidget;
StaticTextWidget* myStateSizeLabelWidget;
SliderWidget* myUncompressedWidget;
StaticTextWidget* myUncompressedLabelWidget;
PopUpWidget* myStateIntervalWidget;
PopUpWidget* myStateHorizonWidget;
#ifdef DEBUGGER_SUPPORT
// Debugger UI widgets
SliderWidget* myDebuggerWidthSlider;
StaticTextWidget* myDebuggerWidthLabel;
SliderWidget* myDebuggerHeightSlider;
StaticTextWidget* myDebuggerHeightLabel;
PopUpWidget* myDebuggerFontSize;
PopUpWidget* myDebuggerFontStyle;
CheckboxWidget* myGhostReadsTrapWidget;
@ -150,6 +144,7 @@ class DeveloperDialog : public Dialog
bool myDebugColors[2];
bool myUndrivenPins[2];
bool myThumbException[2];
bool myEEPROMAccess[2];
// States sets
bool myTimeMachine[2];
int myStateSize[2];
@ -162,8 +157,6 @@ class DeveloperDialog : public Dialog
void addTimeMachineTab(const GUI::Font& font);
void addVideoTab(const GUI::Font& font);
void addDebuggerTab(const GUI::Font& font);
// Add Defaults, OK and Cancel buttons
void addDefaultOKCancelButtons(const GUI::Font& font);
void loadSettings(SettingsSet set);
void saveSettings(SettingsSet set);

View File

@ -27,6 +27,10 @@
#include "Dialog.hxx"
#include "Widget.hxx"
#include "TabWidget.hxx"
#include "ContextMenu.hxx"
#include "PopUpWidget.hxx"
#include "Vec.hxx"
/*
@ -38,9 +42,34 @@
* ...
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font, const string& title,
int x, int y, int w, int h)
: GuiObject(instance, parent, *this, x, y, w, h),
_font(&font),
_title(title),
_th(0),
_mouseWidget(nullptr),
_focusedWidget(nullptr),
_dragWidget(nullptr),
_okWidget(nullptr),
_cancelWidget(nullptr),
_visible(false),
_processCancel(false),
_surface(nullptr),
_tabID(0),
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
{
initTitle(font, title);
}
Dialog::Dialog(OSystem& instance, DialogContainer& parent,
int x, int y, int w, int h)
: GuiObject(instance, parent, *this, x, y, w, h),
_font(nullptr),
_title(""),
_th(0),
_fh(0),
_mouseWidget(nullptr),
_focusedWidget(nullptr),
_dragWidget(nullptr),
@ -102,6 +131,29 @@ void Dialog::close(bool refresh)
parent().removeDialog();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::initTitle(const GUI::Font& font, const string& title)
{
_font = &font;
_fh = font.getLineHeight();
setTitle(title);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::setTitle(const string& title)
{
if(_font != nullptr)
{
_title = title;
_h -= _th;
if(title.empty())
_th = 0;
else
_th = _fh + 4;
_h += _th;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::center()
{
@ -270,15 +322,26 @@ void Dialog::drawDialog()
if(_dirty)
{
// dialog is still on top if e.g a ContextMenu is opened
bool onTop = parent().myDialogStack.top() == this
|| parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
&& !parent().myDialogStack.top()->hasTitle();
if(_flags & WIDGET_CLEARBG)
{
// cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl;
s.fillRect(_x, _y, _w, _h, kDlgColor);
s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo);
if(_th)
{
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
s.drawString(*_font, _title, _x + 10, _y + 2 + 1, _font->getStringWidth(_title),
onTop ? kColorTitleText : kColorTitleTextLo);
}
}
else
s.invalidate();
if(_flags & WIDGET_BORDER)
#ifndef FLAT_UI
s.box(_x, _y, _w, _h, kColor, kShadowColor);
#else
s.frameRect(_x, _y, _w, _h, kColor);
#endif // !FLAT_UI
s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor);
// Make all child widget dirty
Widget* w = _firstWidget;
@ -662,23 +725,28 @@ Widget* Dialog::findWidget(int x, int y) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText, const string& cancelText,
bool focusOKButton)
bool focusOKButton, int buttonWidth)
{
int buttonWidth = std::max(font.getStringWidth("Cancel"),
std::max(font.getStringWidth(okText),
font.getStringWidth(okText))) + 15;
const int HBORDER = 10;
const int VBORDER = 10;
const int BTN_BORDER = 20;
const int BUTTON_GAP = 8;
buttonWidth = std::max(buttonWidth,
std::max(font.getStringWidth("Defaults"),
std::max(font.getStringWidth(okText),
font.getStringWidth(cancelText))) + BTN_BORDER);
int buttonHeight = font.getLineHeight() + 4;
#ifndef BSPF_MAC_OSX
addOKWidget(new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7),
_h - buttonHeight - 10, buttonWidth, buttonHeight, okText, GuiObject::kOKCmd));
addCancelWidget(new ButtonWidget(this, font, _w - (buttonWidth + 10),
_h - buttonHeight - 10, buttonWidth, buttonHeight, cancelText, GuiObject::kCloseCmd));
addOKWidget(new ButtonWidget(this, font, _w - 2 * buttonWidth - HBORDER - BUTTON_GAP,
_h - buttonHeight - VBORDER, buttonWidth, buttonHeight, okText, GuiObject::kOKCmd));
addCancelWidget(new ButtonWidget(this, font, _w - (buttonWidth + HBORDER),
_h - buttonHeight - VBORDER, buttonWidth, buttonHeight, cancelText, GuiObject::kCloseCmd));
#else
addCancelWidget(new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7),
_h - buttonHeight - 10, buttonWidth, buttonHeight, cancelText, GuiObject::kCloseCmd));
addOKWidget(new ButtonWidget(this, font, _w - (buttonWidth + 10),
_h - buttonHeight - 10, buttonWidth, buttonHeight, okText, GuiObject::kOKCmd));
addCancelWidget(new ButtonWidget(this, font, _w - 2 * buttonWidth - HBORDER - BUTTON_GAP,
_h - buttonHeight - VBORDER, buttonWidth, buttonHeight, cancelText, GuiObject::kCloseCmd));
addOKWidget(new ButtonWidget(this, font, _w - (buttonWidth + HBORDER),
_h - buttonHeight - VBORDER, buttonWidth, buttonHeight, okText, GuiObject::kOKCmd));
#endif
// Note that 'focusOKButton' only takes effect when there are no other UI
@ -697,6 +765,25 @@ void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText, const string& cancelText,
const string& defaultsText,
bool focusOKButton)
{
const int HBORDER = 10;
const int VBORDER = 10;
const int BTN_BORDER = 20;
int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER;
int buttonHeight = font.getLineHeight() + 4;
addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd));
wid.push_back(_defaultWidget);
addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::TabFocus::appendFocusList(WidgetArray& list)
{

View File

@ -46,6 +46,8 @@ class Dialog : public GuiObject
public:
Dialog(OSystem& instance, DialogContainer& parent,
int x = 0, int y = 0, int w = 0, int h = 0);
Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font, const string& title,
int x = 0, int y = 0, int w = 0, int h = 0);
virtual ~Dialog();
@ -65,6 +67,7 @@ class Dialog : public GuiObject
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; }
void addTabWidget(TabWidget* w);
void addDefaultWidget(Widget* w) { _defaultWidget = w; }
void addOKWidget(Widget* w) { _okWidget = w; }
void addCancelWidget(Widget* w) { _cancelWidget = w; }
void setFocus(Widget* w);
@ -83,6 +86,9 @@ class Dialog : public GuiObject
void clearFlags(int flags) { _flags &= ~flags; setDirty(); }
int getFlags() const { return _flags; }
void setTitle(const string& title);
bool hasTitle() { return !_title.empty(); }
protected:
virtual void draw() override { }
void releaseFocus() override;
@ -106,7 +112,14 @@ class Dialog : public GuiObject
void addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText = "OK",
const string& cancelText = "Cancel",
bool focusOKButton = true);
bool focusOKButton = true,
int buttonWidth = 0);
void addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText = "OK",
const string& cancelText = "Cancel",
const string& defaultsText = "Defaults",
bool focusOKButton = true);
void processCancelWithoutWidget(bool state) { _processCancel = state; }
@ -115,6 +128,8 @@ class Dialog : public GuiObject
*/
bool getResizableBounds(uInt32& w, uInt32& h) const;
void initTitle(const GUI::Font& font, const string& title);
private:
void buildCurrentFocusList(int tabID = -1);
bool handleNavEvent(Event::Type e);
@ -125,10 +140,15 @@ class Dialog : public GuiObject
Widget* _mouseWidget;
Widget* _focusedWidget;
Widget* _dragWidget;
Widget* _defaultWidget;
Widget* _okWidget;
Widget* _cancelWidget;
bool _visible;
bool _processCancel;
string _title;
int _th;
const GUI::Font* _font;
int _fh;
Common::FixedStack<shared_ptr<FBSurface>> mySurfaceStack;

View File

@ -40,6 +40,20 @@ void EditTextWidget::setText(const string& str, bool changed)
_changed = changed;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
{
@ -71,21 +85,10 @@ void EditTextWidget::drawWidget(bool hilite)
if(_changed)
s.fillRect(_x, _y, _w, _h, kDbgChangedColor);
else if(!isEditable())
#ifndef FLAT_UI
s.fillRect(_x, _y, _w, _h, kBGColorHi);
#else
s.fillRect(_x, _y, _w, _h, kDlgColor);
#endif
// Draw a thin frame around us.
#ifndef FLAT_UI
s.hLine(_x, _y, _x + _w - 1, kColor);
s.hLine(_x, _y + _h - 1, _x +_w - 1, kShadowColor);
s.vLine(_x, _y, _y + _h - 1, kColor);
s.vLine(_x + _w - 1, _y, _y + _h - 1, kShadowColor);
#else
s.frameRect(_x, _y, _w, _h, kColor);
#endif
s.frameRect(_x, _y, _w, _h, hilite && isEditable() && isEnabled() ? kWidColorHi : kColor);
// Draw the text
adjustOffset();

View File

@ -43,6 +43,8 @@ class EditTextWidget : public EditableWidget
GUI::Rect getEditRect() const override;
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
protected:
string _backupString;

View File

@ -50,17 +50,19 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
lineHeight = font.getLineHeight(),
buttonWidth = font.getStringWidth("Defaults") + 10,
buttonHeight = font.getLineHeight() + 4;
int xpos = 5, ypos = 5;
const int HBORDER = 8;
const int VBORDER = 8;
int xpos = HBORDER, ypos = VBORDER;
myActionsList = new StringListWidget(boss, font, xpos, ypos,
_w - buttonWidth - 20, _h - 3*lineHeight);
_w - buttonWidth - HBORDER * 2 - 8, _h - 3*lineHeight - VBORDER);
myActionsList->setTarget(this);
myActionsList->setEditable(false);
myActionsList->setList(actions);
addFocusWidget(myActionsList);
// Add remap, erase, cancel and default buttons
xpos += myActionsList->getWidth() + 5; ypos += 5;
xpos = _w - HBORDER - buttonWidth;
myMapButton = new ButtonWidget(boss, font, xpos, ypos,
buttonWidth, buttonHeight,
"Map" + ELLIPSIS, kStartMapCmd);
@ -105,13 +107,13 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
myComboButton = nullptr;
// Show message for currently selected event
xpos = 10; ypos = 5 + myActionsList->getHeight() + 5;
xpos = HBORDER; ypos = VBORDER + myActionsList->getHeight() + 8;
StaticTextWidget* t;
t = new StaticTextWidget(boss, font, xpos, ypos+2, font.getStringWidth("Action"),
fontHeight, "Action", TextAlign::Left);
myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + 8, ypos,
_w - xpos - t->getWidth() - 15, lineHeight, "");
_w - xpos - t->getWidth() - 8 - HBORDER, lineHeight, "");
myKeyMapping->setEditable(false, true);
myKeyMapping->clearFlags(WIDGET_RETAIN_FOCUS);
}

View File

@ -21,6 +21,7 @@
#include "SaveKey.hxx"
#include "Dialog.hxx"
#include "EditTextWidget.hxx"
#include "RadioButtonWidget.hxx"
#include "Launcher.hxx"
#include "OSystem.hxx"
#include "PopUpWidget.hxx"
@ -37,7 +38,7 @@
GameInfoDialog::GameInfoDialog(
OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
GuiObject* boss)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Game properties"),
CommandSender(boss),
myPropertiesLoaded(false),
myDefaultsSelected(false)
@ -48,146 +49,136 @@ GameInfoDialog::GameInfoDialog(
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
const int vBorder = 4;
const int hBorder = 2;
const int vBorder = 8;
const int hBorder = 8;
const int hSpace = 10;
const int vGap = 4;
const int VGAP = 4;
int xpos, ypos, lwidth, fwidth, pwidth, tabID;
int xpos, ypos, lwidth, fwidth, pwidth, swidth, tabID;
WidgetArray wid;
VariantList items, ports, ctrls;
StaticTextWidget* t;
// Set real dimensions
_w = 52 * fontWidth + 8;
_h = 9 * (lineHeight + vGap) + vBorder * 2 + buttonHeight + fontHeight + ifont.getLineHeight() + 20;
_w = 53 * fontWidth + 8;
_h = 9 * (lineHeight + VGAP) + vBorder * 2 + _th + buttonHeight + fontHeight + ifont.getLineHeight() + 20;
// The tab widget
xpos = hBorder; ypos = vBorder;
myTab = new TabWidget(this, font, xpos, ypos, _w - 2 * hBorder,
_h - (buttonHeight + fontHeight + ifont.getLineHeight() + 20));
myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2 * 2,
_h - (_th + buttonHeight + fontHeight + ifont.getLineHeight() + 20));
addTabWidget(myTab);
//////////////////////////////////////////////////////////////////////////////
// 1) Cartridge properties
tabID = myTab->addTab("Cartridge");
xpos = hSpace;
lwidth = font.getStringWidth("Manufacturer ");
fwidth = _w - xpos - lwidth - hSpace - hBorder * 2;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Name", TextAlign::Left);
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "Name");
myName = new EditTextWidget(myTab, font, xpos+lwidth, ypos-1,
fwidth, lineHeight, "");
wid.push_back(myName);
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"MD5", TextAlign::Left);
ypos += lineHeight + VGAP;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "MD5");
myMD5 = new EditTextWidget(myTab, font, xpos + lwidth, ypos-1,
fwidth, lineHeight, "");
myMD5->setEditable(false);
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Manufacturer", TextAlign::Left);
ypos += lineHeight + VGAP;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "Manufacturer");
myManufacturer = new EditTextWidget(myTab, font, xpos+lwidth, ypos-1,
fwidth, lineHeight, "");
wid.push_back(myManufacturer);
ypos += lineHeight + vGap;
ypos += lineHeight + VGAP;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Model", TextAlign::Left);
myModelNo = new EditTextWidget(myTab, font, xpos+lwidth, ypos-1,
fwidth, lineHeight, "");
wid.push_back(myModelNo);
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Rarity", TextAlign::Left);
ypos += lineHeight + VGAP;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "Rarity");
myRarity = new EditTextWidget(myTab, font, xpos+lwidth, ypos-1,
fwidth, lineHeight, "");
wid.push_back(myRarity);
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Note", TextAlign::Left);
ypos += lineHeight + VGAP;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "Note");
myNote = new EditTextWidget(myTab, font, xpos+lwidth, ypos-1,
fwidth, lineHeight, "");
wid.push_back(myNote);
ypos += lineHeight + VGAP;
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Sound", TextAlign::Left);
pwidth = font.getStringWidth("Stereo");
items.clear();
VarList::push_back(items, "Mono", "MONO");
VarList::push_back(items, "Stereo", "STEREO");
mySound = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(mySound);
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Type", TextAlign::Left);
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight, "Type");
pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)");
items.clear();
for(int i = 0; i < int(BSType::NumSchemes); ++i)
VarList::push_back(items, BSList[i].desc, BSList[i].name);
myType = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
pwidth, lineHeight, items, "");
wid.push_back(myType);
ypos += lineHeight + VGAP;
mySound = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Stereo sound");
wid.push_back(mySound);
// Add items for tab 0
addToFocusList(wid, myTab, tabID);
//////////////////////////////////////////////////////////////////////////////
// 2) Console properties
wid.clear();
tabID = myTab->addTab("Console");
xpos = hSpace; ypos = vBorder;
lwidth = font.getStringWidth("Right Difficulty ");
pwidth = font.getStringWidth("B & W");
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Left Difficulty", TextAlign::Left);
items.clear();
VarList::push_back(items, "B", "B");
VarList::push_back(items, "A", "A");
myLeftDiff = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myLeftDiff);
StaticTextWidget* s = new StaticTextWidget(myTab, font, xpos, ypos+1, "Left difficulty ");
myLeftDiffGroup = new RadioButtonGroup();
RadioButtonWidget* r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"A", myLeftDiffGroup);
wid.push_back(r);
ypos += lineHeight;
r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"B", myLeftDiffGroup);
wid.push_back(r);
ypos += lineHeight + VGAP * 2;
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Right Difficulty", TextAlign::Left);
// ... use same items as above
myRightDiff = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myRightDiff);
s = new StaticTextWidget(myTab, font, xpos, ypos+1, "Right difficulty ");
myRightDiffGroup = new RadioButtonGroup();
r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"A", myRightDiffGroup);
wid.push_back(r);
ypos += lineHeight;
r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"B", myRightDiffGroup);
wid.push_back(r);
ypos += lineHeight + VGAP * 2;
ypos += lineHeight + vGap;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"TV Type", TextAlign::Left);
items.clear();
VarList::push_back(items, "Color", "COLOR");
VarList::push_back(items, "B & W", "BW");
myTVType = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myTVType);
s = new StaticTextWidget(myTab, font, xpos, ypos+1, "TV type ");
myTVTypeGroup = new RadioButtonGroup();
r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"Color", myTVTypeGroup);
wid.push_back(r);
ypos += lineHeight;
r = new RadioButtonWidget(myTab, font, s->getRight(), ypos + 1,
"B/W", myTVTypeGroup);
wid.push_back(r);
// Add items for tab 1
addToFocusList(wid, myTab, tabID);
//////////////////////////////////////////////////////////////////////////////
// 3) Controller properties
wid.clear();
tabID = myTab->addTab("Controller");
ypos = vBorder;
pwidth = font.getStringWidth("Paddles_IAxis");
myP0Label = new StaticTextWidget(myTab, font, hSpace, ypos+1,
"P0 Controller ", TextAlign::Left);
myP0Label = new StaticTextWidget(myTab, font, hSpace, ypos+1, "P0 controller ");
ctrls.clear();
VarList::push_back(ctrls, "Joystick", "JOYSTICK" );
VarList::push_back(ctrls, "Paddles", "PADDLES" );
@ -210,40 +201,34 @@ GameInfoDialog::GameInfoDialog(
pwidth, lineHeight, ctrls, "", 0, kLeftCChanged);
wid.push_back(myP0Controller);
ypos += lineHeight + vGap;
ypos += lineHeight + VGAP;
pwidth = font.getStringWidth("Paddles_IAxis");
myP1Label = new StaticTextWidget(myTab, font, hSpace, ypos+1,
"P1 Controller ", TextAlign::Left);
myP1Label = new StaticTextWidget(myTab, font, hSpace, ypos+1, "P1 controller ");
myP1Controller = new PopUpWidget(myTab, font, myP1Label->getRight(), myP1Label->getTop()-1,
pwidth, lineHeight, ctrls, "", 0, kRightCChanged);
wid.push_back(myP1Controller);
//ypos += lineHeight + vGap;
mySwapPorts = new CheckboxWidget(myTab, font, myP0Controller->getRight() + fontWidth*5, myP0Controller->getTop()+1,
"Swap Ports");
//ypos += lineHeight + VGAP;
mySwapPorts = new CheckboxWidget(myTab, font, myP0Controller->getRight() + fontWidth*4, myP0Controller->getTop()+1,
"Swap ports");
wid.push_back(mySwapPorts);
//ypos += lineHeight + vGap;
mySwapPaddles = new CheckboxWidget(myTab, font, myP1Controller->getRight() + fontWidth*5, myP1Controller->getTop()+1,
"Swap Paddles");
//ypos += lineHeight + VGAP;
mySwapPaddles = new CheckboxWidget(myTab, font, myP1Controller->getRight() + fontWidth*4, myP1Controller->getTop()+1,
"Swap paddles");
wid.push_back(mySwapPaddles);
// EEPROM erase button for P0
ypos += lineHeight + vGap + 4;
// EEPROM erase button for P0/P1
ypos += lineHeight + VGAP + 4;
pwidth = myP1Controller->getWidth(); //font.getStringWidth("Erase EEPROM ") + 23;
myEraseEEPROMLabel = new StaticTextWidget(myTab, font, hSpace, ypos, "AtariVox/SaveKey ");
myEraseEEPROMButton = new ButtonWidget(myTab, font, myEraseEEPROMLabel->getRight(), ypos - 4,
"Erase EEPROM", kEEButtonPressed);
myEraseEEPROMInfo = new StaticTextWidget(myTab, ifont, myEraseEEPROMButton->getRight() + 4, myEraseEEPROMLabel->getTop() + 3,
"(for this game only)");
pwidth, buttonHeight, "Erase EEPROM", kEEButtonPressed);
wid.push_back(myEraseEEPROMButton);
myEraseEEPROMInfo = new StaticTextWidget(myTab, ifont, myEraseEEPROMButton->getRight() + 4,
myEraseEEPROMLabel->getTop() + 3, "(for this game only)");
ypos += lineHeight + vGap * 4;
lwidth = font.getStringWidth("Mouse axis mode ");
pwidth = font.getStringWidth("Specific axis");
items.clear();
VarList::push_back(items, "Automatic", "AUTO");
VarList::push_back(items, "Specific axis", "specific");
myMouseControl =
new PopUpWidget(myTab, font, hSpace, ypos, pwidth, lineHeight, items,
"Mouse axis mode ", lwidth, kMCtrlChanged);
ypos += lineHeight + VGAP * 4;
myMouseControl = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Specific mouse axes", kMCtrlChanged);
wid.push_back(myMouseControl);
// Mouse controller specific axis
@ -259,41 +244,36 @@ GameInfoDialog::GameInfoDialog(
VarList::push_back(items, "MindLink 0", MouseControl::MindLink0);
VarList::push_back(items, "MindLink 1", MouseControl::MindLink1);
xpos = hSpace + lwidth;
lwidth = font.getStringWidth("X-Axis is ");
xpos -= lwidth;
ypos += lineHeight + vGap;
xpos += 20;
ypos += lineHeight + VGAP;
myMouseX = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
"X-Axis is ");
wid.push_back(myMouseX);
ypos += lineHeight + vGap;
ypos += lineHeight + VGAP;
myMouseY = new PopUpWidget(myTab, font, myMouseX->getLeft(), ypos, pwidth, lineHeight, items,
"Y-Axis is ");
wid.push_back(myMouseY);
xpos = hSpace; ypos += lineHeight + vGap;
xpos = hSpace; ypos += lineHeight + VGAP;
lwidth = font.getStringWidth("Mouse axis range ");
myMouseRange = new SliderWidget(myTab, font, hSpace, ypos, 8*fontWidth, lineHeight,
"Mouse axis range ", lwidth, kMRangeChanged);
myMouseRange = new SliderWidget(myTab, font, hSpace, ypos,
"Mouse axis range ", lwidth, 0, fontWidth * 4, "%");
myMouseRange->setMinValue(1); myMouseRange->setMaxValue(100);
wid.push_back(myMouseRange);
myMouseRangeLabel = new StaticTextWidget(myTab, font,
myMouseRange->getRight() + 4, myMouseRange->getTop()+1,
" ", TextAlign::Left);
// Add items for tab 2
addToFocusList(wid, myTab, tabID);
//////////////////////////////////////////////////////////////////////////////
// 4) Display properties
wid.clear();
tabID = myTab->addTab("Display");
ypos = vBorder;
pwidth = font.getStringWidth("Auto-detect");
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Format ", TextAlign::Left);
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Format ");
items.clear();
VarList::push_back(items, "Auto-detect", "AUTO");
VarList::push_back(items, "NTSC", "NTSC");
@ -306,43 +286,34 @@ GameInfoDialog::GameInfoDialog(
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myFormat);
ypos += lineHeight + vGap;
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "YStart ", TextAlign::Left);
myYStart = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
"", 0, kYStartChanged);
ypos += lineHeight + VGAP;
swidth = myFormat->getWidth();
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Y-Start ");
myYStart = new SliderWidget(myTab, font, t->getRight(), ypos, swidth, lineHeight,
"", 0, kYStartChanged, 4 * fontWidth, "px");
myYStart->setMinValue(TIAConstants::minYStart-1);
myYStart->setMaxValue(TIAConstants::maxYStart);
wid.push_back(myYStart);
myYStartLabel = new StaticTextWidget(myTab, font, myYStart->getRight() + 4,
ypos+1, 5*fontWidth, fontHeight, "", TextAlign::Left);
ypos += lineHeight + vGap;
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Height ", TextAlign::Left);
myHeight = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
"", 0, kHeightChanged);
ypos += lineHeight + VGAP;
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Height ");
myHeight = new SliderWidget(myTab, font, t->getRight(), ypos, swidth, lineHeight,
"", 0, kHeightChanged, 5 * fontWidth, "px");
myHeight->setMinValue(TIAConstants::minViewableHeight-1);
myHeight->setMaxValue(TIAConstants::maxViewableHeight);
wid.push_back(myHeight);
myHeightLabel = new StaticTextWidget(myTab, font, myHeight->getRight() + 4,
ypos+1, 5*fontWidth, fontHeight, "", TextAlign::Left);
// Phosphor
ypos += lineHeight + vGap*4;
myPhosphor = new CheckboxWidget(myTab, font, hSpace, ypos+1, "Use Phosphor", kPhosphorChanged);
ypos += lineHeight + VGAP*4;
myPhosphor = new CheckboxWidget(myTab, font, hSpace, ypos+1, "Phosphor", kPhosphorChanged);
wid.push_back(myPhosphor);
myPPBlend = new SliderWidget(myTab, font,
myPhosphor->getRight() + 16, myPhosphor->getTop()-2,
8*fontWidth, lineHeight, "Blend ",
font.getStringWidth("Blend "),
kPPBlendChanged);
myPhosphor->getRight() + fontWidth * 3, myPhosphor->getTop()-2,
"Blend ", 0, kPPBlendChanged, 7 * fontWidth, "%");
myPPBlend->setMinValue(0); myPPBlend->setMaxValue(100);
wid.push_back(myPPBlend);
myPPBlendLabel = new StaticTextWidget(myTab, font,
myPPBlend->getRight() + 4, myPhosphor->getTop(),
5*fontWidth, fontHeight, "", TextAlign::Left);
// Add items for tab 3
addToFocusList(wid, myTab, tabID);
@ -353,17 +324,11 @@ GameInfoDialog::GameInfoDialog(
// Add message concerning usage
lwidth = ifont.getStringWidth("(*) Changes to properties require a ROM reload");
new StaticTextWidget(this, ifont, hSpace, _h - (buttonHeight + fontHeight + 20),
lwidth, fontHeight,
"(*) Changes to properties require a ROM reload",
TextAlign::Left);
"(*) Changes to properties require a ROM reload");
// Add Defaults, OK and Cancel buttons
wid.clear();
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
}
@ -406,13 +371,13 @@ void GameInfoDialog::loadView()
myModelNo->setText(myGameProperties.get(Cartridge_ModelNo));
myRarity->setText(myGameProperties.get(Cartridge_Rarity));
myNote->setText(myGameProperties.get(Cartridge_Note));
mySound->setSelected(myGameProperties.get(Cartridge_Sound), "MONO");
mySound->setState(myGameProperties.get(Cartridge_Sound) == "STEREO");
myType->setSelected(myGameProperties.get(Cartridge_Type), "AUTO");
// Console properties
myLeftDiff->setSelected(myGameProperties.get(Console_LeftDifficulty), "B");
myRightDiff->setSelected(myGameProperties.get(Console_RightDifficulty), "B");
myTVType->setSelected(myGameProperties.get(Console_TelevisionType), "COLOR");
myLeftDiffGroup->setSelected(myGameProperties.get(Console_LeftDifficulty) == "A" ? 0 : 1);
myRightDiffGroup->setSelected(myGameProperties.get(Console_RightDifficulty) == "A" ? 0 : 1);
myTVTypeGroup->setSelected(myGameProperties.get(Console_TelevisionType) == "BW" ? 1 : 0);
// Controller properties
myP0Controller->setSelected(myGameProperties.get(Controller_Left), "JOYSTICK");
@ -425,15 +390,16 @@ void GameInfoDialog::loadView()
string m_control, m_range;
m_axis >> m_control;
bool autoAxis = BSPF::equalsIgnoreCase(m_control, "AUTO");
myMouseControl->setState(!autoAxis);
if(autoAxis)
{
myMouseControl->setSelectedIndex(0);
//myMouseControl->setSelectedIndex(0);
myMouseX->setSelectedIndex(0);
myMouseY->setSelectedIndex(0);
}
else
{
myMouseControl->setSelectedIndex(1);
//myMouseControl->setSelectedIndex(1);
myMouseX->setSelected(m_control[0] - '0');
myMouseY->setSelected(m_control[1] - '0');
}
@ -442,12 +408,10 @@ void GameInfoDialog::loadView()
if(m_axis >> m_range)
{
myMouseRange->setValue(atoi(m_range.c_str()));
myMouseRangeLabel->setLabel(m_range);
}
else
{
myMouseRange->setValue(100);
myMouseRangeLabel->setLabel("100");
}
// Display properties
@ -455,20 +419,22 @@ void GameInfoDialog::loadView()
const string& ystart = myGameProperties.get(Display_YStart);
myYStart->setValue(atoi(ystart.c_str()));
myYStartLabel->setLabel(ystart == "0" ? "Auto" : ystart);
myYStart->setValueLabel(ystart == "0" ? "Auto" : ystart);
myYStart->setValueUnit(ystart == "0" ? "" : "px");
const string& height = myGameProperties.get(Display_Height);
myHeight->setValue(atoi(height.c_str()));
myHeightLabel->setLabel(height == "0" ? "Auto" : height);
myHeight->setValueLabel(height == "0" ? "Auto" : height);
myHeight->setValueUnit(height == "0" ? "" : "px");
bool usePhosphor = myGameProperties.get(Display_Phosphor) == "YES";
myPhosphor->setState(usePhosphor);
myPPBlend->setEnabled(usePhosphor);
myPPBlendLabel->setEnabled(usePhosphor);
const string& blend = myGameProperties.get(Display_PPBlend);
myPPBlend->setValue(atoi(blend.c_str()));
myPPBlendLabel->setLabel(blend == "0" ? "Auto" : blend);
myPPBlend->setValueLabel(blend == "0" ? "Default" : blend);
myPPBlend->setValueUnit(blend == "0" ? "" : "%");
myTab->loadConfig();
}
@ -485,13 +451,13 @@ void GameInfoDialog::saveConfig()
myGameProperties.set(Cartridge_ModelNo, myModelNo->getText());
myGameProperties.set(Cartridge_Rarity, myRarity->getText());
myGameProperties.set(Cartridge_Note, myNote->getText());
myGameProperties.set(Cartridge_Sound, mySound->getSelectedTag().toString());
myGameProperties.set(Cartridge_Sound, mySound->getState() ? "STEREO" : "MONO");
myGameProperties.set(Cartridge_Type, myType->getSelectedTag().toString());
// Console properties
myGameProperties.set(Console_LeftDifficulty, myLeftDiff->getSelectedTag().toString());
myGameProperties.set(Console_RightDifficulty, myRightDiff->getSelectedTag().toString());
myGameProperties.set(Console_TelevisionType, myTVType->getSelectedTag().toString());
myGameProperties.set(Console_LeftDifficulty, myLeftDiffGroup->getSelected() ? "B" : "A");
myGameProperties.set(Console_RightDifficulty, myRightDiffGroup->getSelected() ? "B" : "A");
myGameProperties.set(Console_TelevisionType, myTVTypeGroup->getSelected() ? "BW" : "COLOR");
// Controller properties
myGameProperties.set(Controller_Left, myP0Controller->getSelectedTag().toString());
@ -500,25 +466,25 @@ void GameInfoDialog::saveConfig()
myGameProperties.set(Controller_SwapPaddles, (mySwapPaddles->isEnabled() && mySwapPaddles->getState()) ? "YES" : "NO");
// MouseAxis property (potentially contains 'range' information)
string mcontrol = myMouseControl->getSelectedTag().toString();
if(mcontrol != "AUTO")
string mcontrol = "AUTO";
if(myMouseControl->getState())
mcontrol = myMouseX->getSelectedTag().toString() +
myMouseY->getSelectedTag().toString();
string range = myMouseRangeLabel->getLabel();
string range = myMouseRange->getValueLabel();
if(range != "100")
mcontrol += " " + range;
myGameProperties.set(Controller_MouseAxis, mcontrol);
// Display properties
myGameProperties.set(Display_Format, myFormat->getSelectedTag().toString());
myGameProperties.set(Display_YStart, myYStartLabel->getLabel() == "Auto" ? "0" :
myYStartLabel->getLabel());
myGameProperties.set(Display_Height, myHeightLabel->getLabel() == "Auto" ? "0" :
myHeightLabel->getLabel());
myGameProperties.set(Display_YStart, myYStart->getValueLabel() == "Auto" ? "0" :
myYStart->getValueLabel());
myGameProperties.set(Display_Height, myHeight->getValueLabel() == "Auto" ? "0" :
myHeight->getValueLabel());
myGameProperties.set(Display_Phosphor, myPhosphor->getState() ? "YES" : "NO");
myGameProperties.set(Display_PPBlend, myPPBlendLabel->getLabel() == "Auto" ? "0" :
myPPBlendLabel->getLabel());
myGameProperties.set(Display_PPBlend, myPPBlend->getValueLabel() == "Default" ? "0" :
myPPBlend->getValueLabel());
// Determine whether to add or remove an entry from the properties set
if(myDefaultsSelected)
@ -639,38 +605,44 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
{
bool status = myPhosphor->getState();
myPPBlend->setEnabled(status);
myPPBlendLabel->setEnabled(status);
break;
}
case kYStartChanged:
if(myYStart->getValue() == TIAConstants::minYStart-1)
myYStartLabel->setLabel("Auto");
{
myYStart->setValueLabel("Auto");
myYStart->setValueUnit("");
}
else
myYStartLabel->setValue(myYStart->getValue());
myYStart->setValueUnit("px");
break;
case kHeightChanged:
if(myHeight->getValue() == TIAConstants::minViewableHeight-1)
myHeightLabel->setLabel("Auto");
{
myHeight->setValueLabel("Auto");
myHeight->setValueUnit("");
}
else
myHeightLabel->setValue(myHeight->getValue());
myHeight->setValueUnit("px");
break;
case kPPBlendChanged:
if(myPPBlend->getValue() == 0)
myPPBlendLabel->setLabel("Auto");
{
myPPBlend->setValueLabel("Default");
myPPBlend->setValueUnit("");
}
else
myPPBlendLabel->setValue(myPPBlend->getValue());
break;
case kMRangeChanged:
myMouseRangeLabel->setValue(myMouseRange->getValue());
myPPBlend->setValueUnit("%");
break;
case kMCtrlChanged:
{
bool state = myMouseControl->getSelectedTag() != "AUTO";
//bool state = myMouseControl->getSelectedTag() != "AUTO";
bool state = myMouseControl->getState();
myMouseX->setEnabled(state);
myMouseY->setEnabled(state);
break;

View File

@ -23,6 +23,7 @@ class GuiObject;
class EditTextWidget;
class PopUpWidget;
class StaticTextWidget;
class RadioButtonGroup;
class TabWidget;
class SliderWidget;
@ -58,13 +59,13 @@ class GameInfoDialog : public Dialog, public CommandSender
EditTextWidget* myModelNo;
EditTextWidget* myRarity;
EditTextWidget* myNote;
PopUpWidget* mySound;
PopUpWidget* myType;
CheckboxWidget* mySound;
// Console properties
PopUpWidget* myLeftDiff;
PopUpWidget* myRightDiff;
PopUpWidget* myTVType;
RadioButtonGroup* myLeftDiffGroup;
RadioButtonGroup* myRightDiffGroup;
RadioButtonGroup* myTVTypeGroup;
// Controller properties
StaticTextWidget* myP0Label;
@ -76,26 +77,21 @@ class GameInfoDialog : public Dialog, public CommandSender
StaticTextWidget* myEraseEEPROMLabel;
ButtonWidget* myEraseEEPROMButton;
StaticTextWidget* myEraseEEPROMInfo;
PopUpWidget* myMouseControl;
CheckboxWidget* myMouseControl;
PopUpWidget* myMouseX;
PopUpWidget* myMouseY;
SliderWidget* myMouseRange;
StaticTextWidget* myMouseRangeLabel;
// Display properties
PopUpWidget* myFormat;
SliderWidget* myYStart;
StaticTextWidget* myYStartLabel;
SliderWidget* myHeight;
StaticTextWidget* myHeightLabel;
CheckboxWidget* myPhosphor;
SliderWidget* myPPBlend;
StaticTextWidget* myPPBlendLabel;
enum {
kLeftCChanged = 'LCch',
kRightCChanged = 'RCch',
kMRangeChanged = 'MRch',
kYStartChanged = 'YSch',
kHeightChanged = 'HTch',
kPhosphorChanged = 'PPch',

View File

@ -30,7 +30,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
: Dialog(boss->instance(), boss->parent()),
: Dialog(boss->instance(), boss->parent(), font, "Power-on options"),
CommandSender(boss)
{
const int lineHeight = font.getLineHeight(),
@ -47,9 +47,9 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
// Set real dimensions
_w = lwidth + pwidth + fontWidth*3 + 15;
_h = 17 * (lineHeight + 4) + buttonHeight + 20;
_h = 17 * (lineHeight + 4) + buttonHeight + 20 + _th;
xpos = 10; ypos = 10;
xpos = 10; ypos = 10 + _th;
// Bankswitch type
new StaticTextWidget(this, font, xpos, ypos+1, lwidth, fontHeight,
@ -133,11 +133,7 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
" further ROMs until clicking 'Defaults'", TextAlign::Left);
// Add Defaults, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font, "Load ROM", "Close");
addDefaultsOKCancelBGroup(wid, font, "Load ROM", "Close");
addToFocusList(wid);
}

View File

@ -24,7 +24,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Help"),
myPage(1),
myNumPages(5)
{
@ -39,7 +39,7 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = 46 * fontWidth + 10;
_h = 12 * lineHeight + 20;
_h = 12 * lineHeight + 20 + _th;
// Add Previous, Next and Close buttons
xpos = 10; ypos = _h - buttonHeight - 10;
@ -49,7 +49,7 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
myPrevButton->clearFlags(WIDGET_ENABLED);
wid.push_back(myPrevButton);
xpos += buttonWidth + 7;
xpos += buttonWidth + 8;
myNextButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Next", GuiObject::kNextCmd);
@ -60,9 +60,9 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Close", GuiObject::kCloseCmd);
wid.push_back(b);
addOKWidget(b); addCancelWidget(b);
addCancelWidget(b);
xpos = 5; ypos = 5;
xpos = 5; ypos = 5 + _th;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - 10, fontHeight,
"", TextAlign::Center);

View File

@ -38,11 +38,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Input settings"),
myConfirmMsg(nullptr),
myMaxWidth(max_w),
myMaxHeight(max_h)
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
@ -54,11 +53,11 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = std::min(50 * fontWidth + 10, max_w);
_h = std::min(16 * (lineHeight + 4) + 14, max_h);
_h = std::min(16 * (lineHeight + 4) + 16 + _th, max_h);
// The tab widget
xpos = 2; ypos = vBorder;
myTab = new TabWidget(this, font, xpos, ypos, _w - 2*xpos, _h - buttonHeight - 20);
xpos = 2; ypos = vBorder + _th;
myTab = new TabWidget(this, font, xpos, ypos, _w - 2*xpos, _h -_th - buttonHeight - 20);
addTabWidget(myTab);
// 1) Event mapper for emulation actions
@ -66,7 +65,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
actions = instance().eventHandler().getActionList(kEmulationMode);
myEmulEventMapper = new EventMappingWidget(myTab, font, 2, 2,
myTab->getWidth(),
myTab->getHeight() - ypos,
myTab->getHeight() - 4,
actions, kEmulationMode);
myTab->setParentWidget(tabID, myEmulEventMapper);
addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID);
@ -76,7 +75,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
actions = instance().eventHandler().getActionList(kMenuMode);
myMenuEventMapper = new EventMappingWidget(myTab, font, 2, 2,
myTab->getWidth(),
myTab->getHeight() - ypos,
myTab->getHeight() - 4,
actions, kMenuMode);
myTab->setParentWidget(tabID, myMenuEventMapper);
addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID);
@ -90,11 +89,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
// Add Defaults, OK and Cancel buttons
WidgetArray wid;
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
}
@ -112,42 +107,35 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
int xpos, ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
const int vGap = 4;
const int hSpace = 8;
const int VGAP = 4;
const int VBORDER = 9;
const int HBORDER = 8;
// Devices/ports
tabID = myTab->addTab("Devices & Ports");
// Stelladaptor mappings
ypos = vGap+2;
ypos = VBORDER;
lwidth = font.getStringWidth("Digital paddle sensitivity "); // was: "Use mouse as a controller "
pwidth = font.getStringWidth("-UI, -Emulation");
VarList::push_back(items, "Left / Right", "lr");
VarList::push_back(items, "Right / Left", "rl");
mySAPort = new PopUpWidget(myTab, font, hSpace, ypos, pwidth, lineHeight, items,
"Stelladaptor port order ", lwidth);
wid.push_back(mySAPort);
// Use mouse as controller
ypos += lineHeight + vGap;
items.clear();
VarList::push_back(items, "Always", "always");
VarList::push_back(items, "Analog devices", "analog");
VarList::push_back(items, "Never", "never");
myMouseControl = new PopUpWidget(myTab, font, hSpace, ypos, pwidth, lineHeight, items,
"Use mouse as a controller ", lwidth);
myMouseControl = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items,
"Use mouse as a controller ", lwidth);
wid.push_back(myMouseControl);
// Mouse cursor state
ypos += lineHeight + vGap;
ypos += lineHeight + VGAP;
items.clear();
VarList::push_back(items, "-UI, -Emulation", "0");
VarList::push_back(items, "-UI, +Emulation", "1");
VarList::push_back(items, "+UI, -Emulation", "2");
VarList::push_back(items, "+UI, +Emulation", "3");
myCursorState = new PopUpWidget(myTab, font, hSpace, ypos, pwidth, lineHeight, items,
"Mouse cursor visibility ", lwidth);
myCursorState = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items,
"Mouse cursor visibility ", lwidth);
wid.push_back(myCursorState);
#ifndef WINDOWED_SUPPORT
myCursorState->clearFlags(WIDGET_ENABLED);
@ -157,57 +145,53 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
pwidth = font.getMaxCharWidth() * 8;
// Add joystick deadzone setting
ypos += lineHeight + vGap*3;
myDeadzone = new SliderWidget(myTab, font, hSpace, ypos, pwidth, lineHeight,
ypos += lineHeight + VGAP*3;
myDeadzone = new SliderWidget(myTab, font, HBORDER, ypos,
"Joystick deadzone size ", lwidth, kDeadzoneChanged);
myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29);
xpos = hSpace + myDeadzone->getWidth() + 5;
myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth,
lineHeight, "", TextAlign::Left);
xpos = HBORDER + myDeadzone->getWidth() + 5;
myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth, lineHeight, "");
wid.push_back(myDeadzone);
// Add paddle speed (digital emulation)
ypos += lineHeight + vGap;
myDPaddleSpeed = new SliderWidget(myTab, font, hSpace, ypos, pwidth, lineHeight,
ypos += lineHeight + VGAP;
myDPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos,
"Digital paddle sensitivity ",
lwidth, kDPSpeedChanged);
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20);
xpos = hSpace + myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", TextAlign::Left);
xpos = HBORDER + myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myDPaddleSpeed);
// Add paddle speed (mouse emulation)
ypos += lineHeight + vGap;
myMPaddleSpeed = new SliderWidget(myTab, font, hSpace, ypos, pwidth, lineHeight,
ypos += lineHeight + VGAP;
myMPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos,
"Mouse paddle sensitivity ",
lwidth, kMPSpeedChanged);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
xpos = hSpace + myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", TextAlign::Left);
xpos = HBORDER + myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myMPaddleSpeed);
// Add trackball speed
ypos += lineHeight + vGap;
myTrackBallSpeed = new SliderWidget(myTab, font, hSpace, ypos, pwidth, lineHeight,
ypos += lineHeight + VGAP;
myTrackBallSpeed = new SliderWidget(myTab, font, HBORDER, ypos,
"Trackball sensitivity ",
lwidth, kTBSpeedChanged);
myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20);
xpos = hSpace + myTrackBallSpeed->getWidth() + 5;
myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", TextAlign::Left);
xpos = HBORDER + myTrackBallSpeed->getWidth() + 5;
myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myTrackBallSpeed);
// Add 'allow all 4 directions' for joystick
ypos += lineHeight + vGap*3;
myAllowAll4 = new CheckboxWidget(myTab, font, hSpace, ypos,
ypos += lineHeight + VGAP*3;
myAllowAll4 = new CheckboxWidget(myTab, font, HBORDER, ypos,
"Allow all 4 directions on joystick");
wid.push_back(myAllowAll4);
// Grab mouse (in windowed mode)
ypos += lineHeight + vGap;
myGrabMouse = new CheckboxWidget(myTab, font, hSpace, ypos,
ypos += lineHeight + VGAP;
myGrabMouse = new CheckboxWidget(myTab, font, HBORDER, ypos,
"Grab mouse in emulation mode");
wid.push_back(myGrabMouse);
#ifndef WINDOWED_SUPPORT
@ -215,38 +199,45 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
#endif
// Enable/disable control key-combos
ypos += lineHeight + vGap;
myCtrlCombo = new CheckboxWidget(myTab, font, hSpace, ypos,
ypos += lineHeight + VGAP;
myCtrlCombo = new CheckboxWidget(myTab, font, HBORDER, ypos,
"Use Control key combos");
wid.push_back(myCtrlCombo);
ypos += lineHeight + VGAP;
// Stelladaptor mappings
mySAPort = new CheckboxWidget(myTab, font, HBORDER, ypos,
"Swap Stelladaptor ports");
wid.push_back(mySAPort);
int fwidth;
// Add EEPROM erase (part 1/2)
ypos += vGap*4;
ypos += VGAP*4;
fwidth = font.getStringWidth("AtariVox/SaveKey");
lwidth = font.getStringWidth("AtariVox/SaveKey");
new StaticTextWidget(myTab, font, _w - 14 - (fwidth + lwidth) / 2, ypos,
new StaticTextWidget(myTab, font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos,
"AtariVox/SaveKey");
// Show joystick database
ypos += lineHeight;
myJoyDlgButton = new ButtonWidget(myTab, font, hSpace, ypos, 20,
"Joystick database" + ELLIPSIS, kDBButtonPressed);
myJoyDlgButton = new ButtonWidget(myTab, font, HBORDER, ypos, 20,
"Joystick Database" + ELLIPSIS, kDBButtonPressed);
wid.push_back(myJoyDlgButton);
// Add EEPROM erase (part 1/2)
myEraseEEPROMButton = new ButtonWidget(myTab, font, _w - 14 - fwidth, ypos,
myEraseEEPROMButton = new ButtonWidget(myTab, font, _w - HBORDER - 4 - fwidth, ypos,
fwidth, lineHeight+4,
"Erase EEPROM", kEEButtonPressed);
wid.push_back(myEraseEEPROMButton);
// Add AtariVox serial port
ypos += lineHeight + vGap*2;
ypos += lineHeight + VGAP*2;
lwidth = font.getStringWidth("AVox serial port ");
fwidth = _w - 14 - hSpace - lwidth;
new StaticTextWidget(myTab, font, hSpace, ypos, "AVox serial port ");
myAVoxPort = new EditTextWidget(myTab, font, hSpace + lwidth, ypos,
fwidth, fontHeight, "");
fwidth = _w - HBORDER * 2 - 4 - lwidth;
new StaticTextWidget(myTab, font, HBORDER, ypos + 2, "AVox serial port ");
myAVoxPort = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos,
fwidth, fontHeight);
wid.push_back(myAVoxPort);
@ -258,7 +249,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
void InputDialog::loadConfig()
{
// Left & right ports
mySAPort->setSelected(instance().settings().getString("saport"), "lr");
mySAPort->setState(instance().settings().getString("saport") == "rl");
// Use mouse as a controller
myMouseControl->setSelected(
@ -312,7 +303,7 @@ void InputDialog::loadConfig()
void InputDialog::saveConfig()
{
// Left & right ports
instance().eventHandler().mapStelladaptors(mySAPort->getSelectedTag().toString());
instance().eventHandler().mapStelladaptors(mySAPort->getState() ? "rl": "lr");
// Use mouse as a controller
const string& usemouse = myMouseControl->getSelectedTag().toString();
@ -371,7 +362,7 @@ void InputDialog::setDefaults()
case 2: // Virtual devices
{
// Left & right ports
mySAPort->setSelected("lr");
mySAPort->setState(false);
// Use mouse as a controller
myMouseControl->setSelected("analog");
@ -520,8 +511,11 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
case kDBButtonPressed:
if(!myJoyDialog)
{
const GUI::Font& font = instance().frameBuffer().font();
myJoyDialog = make_unique<JoystickDialog>
(this, instance().frameBuffer().font(), _w-60, _h-60);
(this, font, font.getMaxCharWidth() * 56 + 20, font.getFontHeight() * 18 + 20);
}
myJoyDialog->show();
break;
@ -539,7 +533,7 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
myConfirmMsg = make_unique<GUI::MessageBox>
(this, instance().frameBuffer().font(), msg,
myMaxWidth, myMaxHeight, kConfirmEEEraseCmd,
"OK", "Cancel", false);
"OK", "Cancel", "Erase EEPROM", false);
}
myConfirmMsg->show();
break;

View File

@ -73,7 +73,7 @@ class InputDialog : public Dialog
EventMappingWidget* myEmulEventMapper;
EventMappingWidget* myMenuEventMapper;
PopUpWidget* mySAPort;
CheckboxWidget* mySAPort;
PopUpWidget* myMouseControl;
PopUpWidget* myCursorState;

View File

@ -29,8 +29,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& font,
const StringList& labels)
: Dialog(boss->instance(), boss->parent()),
const StringList& labels, const string& title)
: Dialog(boss->instance(), boss->parent(), font, title),
CommandSender(boss),
myEnableCenter(false),
myErrorFlag(false),
@ -43,8 +43,8 @@ InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont,
const StringList& labels)
: Dialog(boss->instance(), boss->parent()),
const StringList& labels, const string& title)
: Dialog(boss->instance(), boss->parent(), lfont, title),
CommandSender(boss),
myEnableCenter(false),
myErrorFlag(false),
@ -66,7 +66,7 @@ void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
// Calculate real dimensions
_w = fontWidth * 41;
_h = lineHeight * 4 + int(labels.size()) * (lineHeight + 5);
_h = lineHeight * 4 + int(labels.size()) * (lineHeight + 5) + _th;
// Determine longest label
for(i = 0; i < labels.size(); ++i)
@ -80,7 +80,7 @@ void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
lwidth = lfont.getStringWidth(labels[maxIdx]);
// Create editboxes for all labels
ypos = lineHeight;
ypos = lineHeight + _th;
for(i = 0; i < labels.size(); ++i)
{
xpos = 10;
@ -98,9 +98,9 @@ void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
}
xpos = 10;
myTitle = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2*xpos, fontHeight,
myMessage = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2*xpos, fontHeight,
"", TextAlign::Left);
myTitle->setTextColor(kTextColorEm);
myMessage->setTextColor(kTextColorEm);
addToFocusList(wid);
@ -148,9 +148,9 @@ void InputTextDialog::center()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputTextDialog::setTitle(const string& title)
void InputTextDialog::setMessage(const string& title)
{
myTitle->setLabel(title);
myMessage->setLabel(title);
myErrorFlag = true;
}
@ -207,7 +207,7 @@ void InputTextDialog::handleCommand(CommandSender* sender, int cmd,
// Erase the invalid message once editing is restarted
if(myErrorFlag)
{
myTitle->setLabel("");
myMessage->setLabel("");
myErrorFlag = false;
}
break;
@ -216,7 +216,6 @@ void InputTextDialog::handleCommand(CommandSender* sender, int cmd,
Dialog::handleCommand(sender, GuiObject::kCloseCmd, data, id);
break;
default:
Dialog::handleCommand(sender, cmd, data, id);
break;

View File

@ -30,9 +30,9 @@ class InputTextDialog : public Dialog, public CommandSender
{
public:
InputTextDialog(GuiObject* boss, const GUI::Font& font,
const StringList& labels);
const StringList& labels, const string& title = "");
InputTextDialog(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, const StringList& labels);
const GUI::Font& nfont, const StringList& labels, const string& title = "");
virtual ~InputTextDialog() = default;
/** Place the input dialog onscreen and center it */
@ -47,7 +47,7 @@ class InputTextDialog : public Dialog, public CommandSender
void setTextFilter(const EditableWidget::TextFilter& f, int idx = 0);
void setEmitSignal(int cmd) { myCmd = cmd; }
void setTitle(const string& title);
void setMessage(const string& title);
void setFocus(int idx = 0);
@ -61,7 +61,7 @@ class InputTextDialog : public Dialog, public CommandSender
private:
vector<EditTextWidget*> myInput;
StaticTextWidget* myTitle;
StaticTextWidget* myMessage;
bool myEnableCenter;
bool myErrorFlag;

View File

@ -27,16 +27,16 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
int max_w, int max_h)
: Dialog(boss->instance(), boss->parent(), 0, 0, max_w, max_h)
: Dialog(boss->instance(), boss->parent(), font, "Joystick database", 0, 0, max_w, max_h)
{
int xpos, ypos;
WidgetArray wid;
int buttonWidth = font.getStringWidth("Close") + 20,
int buttonWidth = font.getStringWidth("Remove ") + 20,
buttonHeight = font.getLineHeight() + 4;
// Joystick list
xpos = 10; ypos = 10;
xpos = 10; ypos = 10 + _th;
int w = _w - 2 * xpos;
int h = _h - buttonHeight - ypos - 20;
myJoyList = new StringListWidget(this, font, xpos, ypos, w, h);
@ -45,11 +45,9 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
// Joystick ID
ypos = _h - buttonHeight - 10;
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos,
font.getStringWidth("Joystick ID "), font.getFontHeight(),
"Joystick ID ", TextAlign::Left);
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Joystick ID ");
xpos += t->getWidth() + 4;
myJoyText = new EditTextWidget(this, font, xpos, ypos-2,
myJoyText = new EditTextWidget(this, font, xpos, ypos,
font.getStringWidth("Unplugged")+8, font.getLineHeight(), "");
myJoyText->setEditable(false);
@ -60,7 +58,7 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
addOKWidget(myCloseBtn); addCancelWidget(myCloseBtn);
buttonWidth = font.getStringWidth("Remove") + 20;
xpos -= buttonWidth + 5;
xpos -= buttonWidth + 8;
myRemoveBtn = new ButtonWidget(this, font, xpos, ypos,
buttonWidth, buttonHeight, "Remove", kRemoveCmd);
myRemoveBtn->clearFlags(WIDGET_ENABLED);

View File

@ -54,21 +54,22 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
myRomInfoWidget(nullptr),
mySelectedItem(0)
{
const string ELLIPSIS = "\x1d";
const GUI::Font& font = instance().frameBuffer().launcherFont();
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
bwidth = (_w - 2 * 10 - 8 * (4 - 1)) / 4,
bheight = font.getLineHeight() + 4;
bheight = lineHeight + 4;
int xpos = 0, ypos = 0, lwidth = 0, lwidth2 = 0;
WidgetArray wid;
// Show game name
lwidth = font.getStringWidth("Select an item from the list ...");
lwidth = font.getStringWidth("Select a ROM from the list" + ELLIPSIS);
xpos += 10; ypos += 8;
new StaticTextWidget(this, font, xpos, ypos, lwidth, fontHeight,
"Select an item from the list ...", TextAlign::Left);
"Select a ROM from the list" + ELLIPSIS);
lwidth2 = font.getStringWidth("XXXX items found");
xpos = _w - lwidth2 - 10;
@ -81,14 +82,17 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
if(w >= 640)
{
int fwidth = std::min(15 * fontWidth, xpos - 20 - lwidth);
new StaticTextWidget(this, font, xpos - fwidth - 5 - font.getStringWidth("Filter "),
ypos, "Filter ");
xpos -= fwidth + 5;
myPattern = new EditTextWidget(this, font, xpos, ypos,
fwidth, fontHeight, "");
myPattern = new EditTextWidget(this, font, xpos, ypos - 2,
fwidth, lineHeight, "");
}
// Add list with game titles
// Before we add the list, we need to know the size of the RomInfoWidget
xpos = 10; ypos += fontHeight + 5;
xpos = 10; ypos += lineHeight + 4;
int romWidth = 0;
int romSize = instance().settings().getInt("romviewer");
if(romSize > 1 && w >= 1000 && h >= 760)
@ -96,9 +100,9 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
else if(romSize > 0 && w >= 640 && h >= 480)
romWidth = 365;
int listWidth = _w - (romWidth > 0 ? romWidth+5 : 0) - 20;
int listWidth = _w - (romWidth > 0 ? romWidth+8 : 0) - 20;
myList = new StringListWidget(this, font, xpos, ypos,
listWidth, _h - 35 - bheight - 2*fontHeight);
listWidth, _h - 43 - bheight - fontHeight - lineHeight);
myList->setEditable(false);
wid.push_back(myList);
if(myPattern) wid.push_back(myPattern); // Add after the list for tab order
@ -106,7 +110,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add ROM info area (if enabled)
if(romWidth > 0)
{
xpos += myList->getWidth() + 5;
xpos += myList->getWidth() + 8;
myRomInfoWidget = new RomInfoWidget(this,
romWidth < 660 ? instance().frameBuffer().smallFont() :
instance().frameBuffer().infoFont(),
@ -115,17 +119,17 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add textfield to show current directory
xpos = 10;
xpos += 5; ypos += myList->getHeight() + 4;
lwidth = font.getStringWidth("Dir ");
ypos += myList->getHeight() + 8;
lwidth = font.getStringWidth("Path ");
myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwidth, fontHeight,
"Dir", TextAlign::Left);
xpos += lwidth + 5;
"Path", TextAlign::Left);
xpos += lwidth;
myDir = new EditTextWidget(this, font, xpos, ypos, _w - xpos - 10, lineHeight, "");
myDir->setEditable(false, true);
myDir->clearFlags(WIDGET_RETAIN_FOCUS);
// Add four buttons at the bottom
xpos = 10; ypos += myDir->getHeight() + 4;
xpos = 10; ypos += myDir->getHeight() + 8;
#ifndef BSPF_MAC_OSX
myStartButton = new ButtonWidget(this, font, xpos, ypos, bwidth, bheight,
"Select", kLoadROMCmd);
@ -225,11 +229,12 @@ void LauncherDialog::loadConfig()
msg.push_back("Before you can start a game, you need to");
msg.push_back("specify where your ROMs are located.");
msg.push_back("");
msg.push_back("Click 'OK' to select a default ROM directory,");
msg.push_back("or 'Cancel' to browse the filesystem manually.");
msg.push_back("Click 'Default' to select a default ROM directory,");
msg.push_back("or 'Browse' to browse the filesystem manually.");
myFirstRunMsg = make_unique<GUI::MessageBox>
(this, instance().frameBuffer().font(),
msg, _w, _h, kFirstRunMsgChosenCmd);
msg, _w, _h, kFirstRunMsgChosenCmd,
"Default", "Browse", "ROM directory");
}
myFirstRunMsg->show();
}
@ -511,10 +516,9 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
case kFirstRunMsgChosenCmd:
// Show a file browser, starting from the users' home directory
if(!myRomDir)
myRomDir = make_unique<BrowserDialog>(this, instance().frameBuffer().font(), _w, _h);
myRomDir->show("Select ROM directory", "~",
BrowserDialog::Directories, kStartupRomDirChosenCmd);
myRomDir = make_unique<BrowserDialog>(this, instance().frameBuffer().font(),
_w, _h, "Select ROM directory");
myRomDir->show("~", BrowserDialog::Directories, kStartupRomDirChosenCmd);
break;
case kStartupRomDirChosenCmd:

View File

@ -28,7 +28,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LauncherFilterDialog::LauncherFilterDialog(GuiObject* boss, const GUI::Font& font)
: Dialog(boss->instance(), boss->parent()),
: Dialog(boss->instance(), boss->parent(), font, "Filter file list"),
CommandSender(boss)
{
const int lineHeight = font.getLineHeight(),
@ -41,9 +41,9 @@ LauncherFilterDialog::LauncherFilterDialog(GuiObject* boss, const GUI::Font& fon
VariantList items;
// Set real dimensions
_w = 3 * buttonWidth;//lwidth + pwidth + fontWidth*5 + 10;
_w = 3 * buttonWidth + 20 + 4 * 8;
xpos = 10; ypos = 10;
xpos = 10; ypos = 10 + _th;
// Types of files to show
VarList::push_back(items, "All files", "allfiles");
@ -56,13 +56,13 @@ LauncherFilterDialog::LauncherFilterDialog(GuiObject* boss, const GUI::Font& fon
ypos += lineHeight + 10;
// Different types of ROM extensions
xpos = 40;
xpos += font.getStringWidth("Show ");
myRomType[0] = new CheckboxWidget(this, font, xpos, ypos, ourRomTypes[0][0]);
int rightcol = xpos + myRomType[0]->getWidth() + 10;
myRomType[3] = new CheckboxWidget(this, font, xpos+rightcol, ypos, ourRomTypes[0][3]);
int rightcol = xpos + myRomType[0]->getWidth() + 8 * 3;
myRomType[3] = new CheckboxWidget(this, font, rightcol, ypos, ourRomTypes[0][3]);
ypos += lineHeight + 4;
myRomType[1] = new CheckboxWidget(this, font, xpos, ypos, ourRomTypes[0][1]);
myRomType[4] = new CheckboxWidget(this, font, xpos+rightcol, ypos, ourRomTypes[0][4]);
myRomType[4] = new CheckboxWidget(this, font, rightcol, ypos, ourRomTypes[0][4]);
ypos += lineHeight + 4;
myRomType[2] = new CheckboxWidget(this, font, xpos, ypos, ourRomTypes[0][2]);
ypos += lineHeight + 10;
@ -70,11 +70,7 @@ LauncherFilterDialog::LauncherFilterDialog(GuiObject* boss, const GUI::Font& fon
_h = ypos + buttonHeight + 20;
// Add Defaults, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addToFocusList(wid);
}
@ -181,7 +177,7 @@ void LauncherFilterDialog::saveConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherFilterDialog::setDefaults()
{
handleFileTypeChange("allfiles");
handleFileTypeChange("allroms");
_dirty = true;
}

View File

@ -33,7 +33,7 @@
LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h,
bool uselargefont)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "System logs"),
myLogInfo(nullptr)
{
const int lineHeight = font.getLineHeight(),
@ -48,7 +48,7 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
_h = max_h;
// Test listing of the log output
xpos = 10; ypos = 10;
xpos = 10; ypos = 10 + _th;
myLogInfo = new StringListWidget(this, uselargefont ? font :
instance().frameBuffer().infoFont(), xpos, ypos, _w - 2 * xpos,
_h - buttonHeight - ypos - 20 - 2 * lineHeight, false);
@ -57,7 +57,6 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
ypos += myLogInfo->getHeight() + 8;
// Level of logging (how much info to print)
xpos += 20;
VariantList items;
VarList::push_back(items, "None", "0");
VarList::push_back(items, "Basic", "1");
@ -69,11 +68,11 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myLogLevel);
// Should log output also be shown on the console?
xpos += myLogLevel->getWidth() + 30;
myLogToConsole = new CheckboxWidget(this, font, xpos, ypos, "Print to console");
xpos += myLogLevel->getWidth() + 32;
myLogToConsole = new CheckboxWidget(this, font, xpos, ypos + 1, "Print to console");
wid.push_back(myLogToConsole);
// Add Defaults, OK and Cancel buttons
// Add Save, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
buttonWidth, buttonHeight, "Save log to disk",

View File

@ -29,8 +29,9 @@ namespace GUI {
MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font,
const StringList& text, int max_w, int max_h, int cmd,
const string& okText, const string& cancelText,
const string& title,
bool focusOKButton)
: Dialog(boss->instance(), boss->parent(), 0, 0, max_w, max_h),
: Dialog(boss->instance(), boss->parent(), font, title, 0, 0, max_w, max_h),
CommandSender(boss),
myCmd(cmd)
{
@ -45,9 +46,10 @@ MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font,
MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font,
const string& text, int max_w, int max_h, int cmd,
const string& okText, const string& cancelText,
const string& title,
bool focusOKButton)
: MessageBox(boss, font, StringParser(text).stringList(), max_w, max_h,
cmd, okText, cancelText, focusOKButton)
cmd, okText, cancelText, title, focusOKButton)
{
}
@ -64,9 +66,9 @@ void MessageBox::addText(const GUI::Font& font, const StringList& text)
for(const auto& s: text)
str_w = std::max(int(s.length()), str_w);
_w = std::min(str_w * fontWidth + 20, _w);
_h = std::min(uInt32((text.size() + 2) * lineHeight + 20), uInt32(_h));
_h = std::min(uInt32((text.size() + 2) * lineHeight + 20 + _th), uInt32(_h));
xpos = 10; ypos = 10;
xpos = 10; ypos = 10 + _th;
for(const auto& s: text)
{
new StaticTextWidget(this, font, xpos, ypos, _w - 20,

View File

@ -37,10 +37,12 @@ class MessageBox : public Dialog, public CommandSender
MessageBox(GuiObject* boss, const GUI::Font& font, const StringList& text,
int max_w, int max_h, int cmd = 0,
const string& okText = "OK", const string& cancelText = "Cancel",
const string& title = "",
bool focusOKButton = true);
MessageBox(GuiObject* boss, const GUI::Font& font, const string& text,
int max_w, int max_h, int cmd = 0,
const string& okText = "OK", const string& cancelText = "Cancel",
const string& title = "",
bool focusOKButton = true);
virtual ~MessageBox() = default;

View File

@ -51,14 +51,17 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
myMode(mode)
{
const GUI::Font& font = instance().frameBuffer().font();
const int buttonWidth = font.getStringWidth("Developer Settings" + ELLIPSIS) + 20,
initTitle(font, "Options");
const int buttonWidth = font.getStringWidth("Game Properties" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 6,
rowHeight = font.getLineHeight() + 10;
const int VBORDER = 10 + _th;
_w = 2 * buttonWidth + 30;
_h = 7 * rowHeight + 15;
_h = 7 * rowHeight + 15 + _th;
int xoffset = 10, yoffset = 10;
int xoffset = 10, yoffset = VBORDER;
WidgetArray wid;
ButtonWidget* b = nullptr;
@ -70,46 +73,47 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
return bw;
};
b = ADD_OD_BUTTON("Video Settings" + ELLIPSIS, kVidCmd);
b = ADD_OD_BUTTON("Video" + ELLIPSIS, kVidCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Audio Settings" + ELLIPSIS, kAudCmd);
b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd);
#ifndef SOUND_SUPPORT
b->clearFlags(WIDGET_ENABLED);
#endif
wid.push_back(b);
b = ADD_OD_BUTTON("Input Settings" + ELLIPSIS, kInptCmd);
b = ADD_OD_BUTTON("Input" + ELLIPSIS, kInptCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("UI Settings" + ELLIPSIS, kUsrIfaceCmd);
b = ADD_OD_BUTTON("User Interface" + ELLIPSIS, kUsrIfaceCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Snapshot Settings" + ELLIPSIS, kSnapCmd);
b = ADD_OD_BUTTON("Snapshots" + ELLIPSIS, kSnapCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Config Paths" + ELLIPSIS, kCfgPathsCmd);
b = ADD_OD_BUTTON("Paths" + ELLIPSIS, kCfgPathsCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Developer" + ELLIPSIS, kDevelopCmd);
wid.push_back(b);
myRomAuditButton = ADD_OD_BUTTON("Audit ROMs" + ELLIPSIS, kAuditCmd);
wid.push_back(myRomAuditButton);
// Move to second column
xoffset += buttonWidth + 10; yoffset = 10;
xoffset += buttonWidth + 10; yoffset = VBORDER;
myGameInfoButton = ADD_OD_BUTTON("Game Properties" + ELLIPSIS, kInfoCmd);
wid.push_back(myGameInfoButton);
myCheatCodeButton = ADD_OD_BUTTON("Cheat Code" + ELLIPSIS, kCheatCmd);
myCheatCodeButton = ADD_OD_BUTTON("Cheat Codes" + ELLIPSIS, kCheatCmd);
#ifndef CHEATCODE_SUPPORT
myCheatCodeButton->clearFlags(WIDGET_ENABLED);
#endif
wid.push_back(myCheatCodeButton);
b = ADD_OD_BUTTON("System Logs" + ELLIPSIS, kLoggerCmd);
wid.push_back(b);
myRomAuditButton = ADD_OD_BUTTON("Audit ROMs" + ELLIPSIS, kAuditCmd);
wid.push_back(myRomAuditButton);
b = ADD_OD_BUTTON("Developer Settings" + ELLIPSIS, kDevelopCmd);
b = ADD_OD_BUTTON("System Logs" + ELLIPSIS, kLoggerCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Help" + ELLIPSIS, kHelpCmd);
@ -118,7 +122,7 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Exit Menu", kExitCmd);
b = ADD_OD_BUTTON("Close", kExitCmd);
wid.push_back(b);
addCancelWidget(b);

View File

@ -23,19 +23,7 @@
#include "DialogContainer.hxx"
#include "PopUpWidget.hxx"
// Little up/down arrow
#ifndef FLAT_UI
static uInt32 up_down_arrows[8] = {
0b00000000,
0b00001000,
0b00011100,
0b00111110,
0b00000000,
0b00111110,
0b00011100,
0b00001000,
};
#else
// Little down arrow
static uInt32 down_arrow[8] = {
0b100000001,
0b110000011,
@ -46,7 +34,6 @@ static uInt32 down_arrow[8] = {
0b000010000,
0b000000000
};
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font,
@ -67,11 +54,7 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font,
if(!_label.empty() && _labelWidth == 0)
_labelWidth = _font.getStringWidth(_label);
#ifndef FLAT_UI
_w = w + _labelWidth + 15;
#else
_w = w + _labelWidth + 23;
#endif
// vertically center the arrows and text
myTextY = (_h - _font.getFontHeight()) / 2;
@ -157,7 +140,6 @@ void PopUpWidget::handleMouseWheel(int x, int y, int direction)
}
}
#ifdef FLAT_UI
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PopUpWidget::handleMouseEntered()
{
@ -171,7 +153,6 @@ void PopUpWidget::handleMouseLeft()
clearFlags(WIDGET_HILITED);
setDirty();
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PopUpWidget::handleEvent(Event::Type e)
@ -221,32 +202,14 @@ void PopUpWidget::drawWidget(bool hilite)
int x = _x + _labelWidth;
int w = _w - _labelWidth;
#ifndef FLAT_UI
// Draw the label, if any
if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + myTextY, _labelWidth,
isEnabled() ? _textcolor : uInt32(kColor), TextAlign::Right);
// Draw a thin frame around us.
s.hLine(x, _y, x + w - 1, kColor);
s.hLine(x, _y +_h-1, x + w - 1, kShadowColor);
s.vLine(x, _y, _y+_h-1, kColor);
s.vLine(x + w - 1, _y, _y +_h - 1, kShadowColor);
// Fill the background
s.fillRect(x + 1, _y + 1, w - 2, _h - 2, _changed ? kDbgChangedColor : kWidColor);
// Draw an arrow pointing down at the right end to signal this is a dropdown/popup
s.drawBitmap(up_down_arrows, x + w - 10, _y + myArrowsY,
!isEnabled() ? kColor : hilite ? kTextColorHi : kTextColor);
#else
// Draw the label, if any
if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + myTextY, _labelWidth,
isEnabled() ? _textcolor : uInt32(kColor), TextAlign::Left);
// Draw a thin frame around us.
s.frameRect(x, _y, w, _h, kColor);
s.frameRect(x + w - 16, _y + 1, 15, _h - 2, isEnabled() && hilite ? kTextColorHi : kBGColorLo);
s.frameRect(x, _y, w, _h, isEnabled() && hilite ? kWidColorHi : kColor);
s.frameRect(x + w - 16, _y + 1, 15, _h - 2, isEnabled() && hilite ? kWidColorHi : kBGColorLo);
// Fill the background
s.fillRect(x + 1, _y + 1, w - 17, _h - 2, _changed ? kDbgChangedColor : kWidColor);
@ -254,7 +217,6 @@ void PopUpWidget::drawWidget(bool hilite)
// Draw an arrow pointing down at the right end to signal this is a dropdown/popup
s.drawBitmap(down_arrow, x + w - 13, _y + myArrowsY + 1,
!isEnabled() ? kColor : kTextColor, 9u, 8u);
#endif
// Draw the selected entry, if any
const string& name = myMenu->getSelectedName();

View File

@ -64,10 +64,8 @@ class PopUpWidget : public Widget, public CommandSender
protected:
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override;
#ifdef FLAT_UI
void handleMouseEntered() override;
void handleMouseLeft() override;
#endif
bool handleEvent(Event::Type e) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void drawWidget(bool hilite) override;

View File

@ -21,63 +21,6 @@
#include "RadioButtonWidget.hxx"
/* Radiobutton bitmaps */
#ifndef FLAT_UI
static uInt32 radio_img_outercircle[14] =
{
0b00001111110000,
0b00111111111100,
0b01110000001110,
0b01100000000110,
0b11000000000011,
0b11000000000011,
0b11000000000011,
0b11000000000011,
0b11000000000011,
0b11000000000011,
0b01100000000110,
0b01110000001110,
0b00111111111100,
0b00001111110000
};
static uInt32 radio_img_innercircle[10] =
{
0b0011111100,
0b0111111110,
0b1111111111,
0b1111111111,
0b1111111111,
0b1111111111,
0b1111111111,
0b1111111111,
0b0111111110,
0b0011111100
};
static uInt32 radio_img_active[8] =
{
0b00111100,
0b01111110,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b01111110,
0b00111100
};
static uInt32 radio_img_inactive[8] =
{
0b00111100,
0b01111110,
0b11100111,
0b11000011,
0b11000011,
0b11100111,
0b01111110,
0b00111100
};
#else
static uInt32 radio_img_outercircle[14] =
{
0b00001111110000,
@ -139,7 +82,6 @@ static uInt32 radio_img_inactive[10] =
0b0111111110,
0b0011111100
};
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font,
@ -217,19 +159,8 @@ void RadioButtonWidget::drawWidget(bool hilite)
{
FBSurface& s = _boss->dialog().surface();
#ifndef FLAT_UI
// Draw the outer bounding circle
s.drawBitmap(radio_img_outercircle, _x, _y + _boxY, kShadowColor, 14, 14);
// Draw the inner bounding circle with enabled color
s.drawBitmap(radio_img_innercircle, _x + 2, _y + _boxY + 2, isEnabled() ? _bgcolor : kColor, 10, 10);
// draw state
if(_state)
s.drawBitmap(_img, _x + 3, _y + _boxY + 3, isEnabled() ? kCheckColor : kShadowColor);
#else
// Draw the outer bounding circle
s.drawBitmap(radio_img_outercircle, _x, _y + _boxY, hilite ? kScrollColorHi : kShadowColor, 14, 14);
s.drawBitmap(radio_img_outercircle, _x, _y + _boxY, hilite ? kWidColorHi : kColor, 14, 14);
// Draw the inner bounding circle with enabled color
s.drawBitmap(radio_img_innercircle, _x + 1, _y + _boxY + 1, isEnabled()
@ -238,9 +169,8 @@ void RadioButtonWidget::drawWidget(bool hilite)
// draw state
if(_state)
s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled()
? hilite ? kScrollColorHi : kCheckColor
: kShadowColor, 10);
#endif
? hilite ? kWidColorHi : kCheckColor
: kColor, 10);
// Finally draw the label
s.drawString(_font, _label, _x + 20, _y + _textY, _w,

View File

@ -35,13 +35,13 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Audit ROMs"),
myConfirmMsg(nullptr),
myMaxWidth(max_w),
myMaxHeight(max_h)
{
const int vBorder = 10;
const int hBorder = 10;
const int VBORDER = 10 + _th;
const int HBORDER = 10;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
@ -49,48 +49,48 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent,
buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 4,
lwidth = font.getStringWidth("ROMs without properties (skipped) ");
int xpos, ypos = vBorder;
int xpos, ypos = VBORDER;
WidgetArray wid;
// Set real dimensions
_w = 54 * fontWidth + 10;
_h = 7 * (lineHeight + 4) + 10;
_w = 64 * fontWidth + HBORDER * 2;
_h = 7 * (lineHeight + 4) + VBORDER;
// Audit path
ButtonWidget* romButton =
new ButtonWidget(this, font, hBorder, ypos, buttonWidth, buttonHeight,
new ButtonWidget(this, font, HBORDER, ypos, buttonWidth, buttonHeight,
"Audit path" + ELLIPSIS, kChooseAuditDirCmd);
wid.push_back(romButton);
xpos = hBorder + buttonWidth + 10;
myRomPath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - hBorder, lineHeight, "");
xpos = HBORDER + buttonWidth + 8;
myRomPath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(myRomPath);
// Show results of ROM audit
ypos += buttonHeight + 16;
new StaticTextWidget(this, font, hBorder, ypos, lwidth, fontHeight,
new StaticTextWidget(this, font, HBORDER, ypos, lwidth, fontHeight,
"ROMs with properties (renamed) ", TextAlign::Left);
myResults1 = new EditTextWidget(this, font, hBorder + lwidth, ypos - 2,
_w - hBorder*2 - lwidth, lineHeight, "");
myResults1 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2,
fontWidth * 6, lineHeight, "");
myResults1->setEditable(false, true);
ypos += buttonHeight;
new StaticTextWidget(this, font, hBorder, ypos, lwidth, fontHeight,
new StaticTextWidget(this, font, HBORDER, ypos, lwidth, fontHeight,
"ROMs without properties (skipped) ", TextAlign::Left);
myResults2 = new EditTextWidget(this, font, hBorder + lwidth, ypos - 2,
_w - hBorder*2 - lwidth, lineHeight, "");
myResults2 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2,
fontWidth * 6, lineHeight, "");
myResults2->setEditable(false, true);
ypos += buttonHeight + 8;
new StaticTextWidget(this, font, hBorder, ypos, _w - 20, fontHeight,
"(*) WARNING: operation cannot be undone!",
new StaticTextWidget(this, font, HBORDER, ypos, _w - 20, fontHeight,
"(*) WARNING: Operation cannot be undone!",
TextAlign::Left);
// Add OK and Cancel buttons
addOKCancelBGroup(wid, font, "Audit", "Done");
addOKCancelBGroup(wid, font, "Audit", "Close");
addBGroupToFocusList(wid);
// Create file browser dialog
myBrowser = make_unique<BrowserDialog>(this, font, myMaxWidth, myMaxHeight);
myBrowser = make_unique<BrowserDialog>(this, font, myMaxWidth, myMaxHeight, "Select ROM directory to audit");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -189,7 +189,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd,
myConfirmMsg = make_unique<GUI::MessageBox>
(this, instance().frameBuffer().font(), msg,
myMaxWidth, myMaxHeight, kConfirmAuditCmd,
"OK", "Cancel", false);
"OK", "Cancel", "ROM Audit", false);
}
myConfirmMsg->show();
break;
@ -200,7 +200,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kChooseAuditDirCmd:
myBrowser->show("Select ROM directory to audit", myRomPath->getText(),
myBrowser->show(myRomPath->getText(),
BrowserDialog::Directories, kAuditDirChosenCmd);
break;

View File

@ -118,17 +118,17 @@ void RomInfoWidget::parseProperties()
mySurface->setVisible(mySurfaceIsValid);
// Now add some info for the message box below the image
myRomInfo.push_back("Name: " + myProperties.get(Cartridge_Name));
myRomInfo.push_back("Manufacturer: " + myProperties.get(Cartridge_Manufacturer));
myRomInfo.push_back("Model: " + myProperties.get(Cartridge_ModelNo));
myRomInfo.push_back("Rarity: " + myProperties.get(Cartridge_Rarity));
myRomInfo.push_back("Note: " + myProperties.get(Cartridge_Note));
myRomInfo.push_back("Name: " + myProperties.get(Cartridge_Name));
myRomInfo.push_back("Manufacturer: " + myProperties.get(Cartridge_Manufacturer));
myRomInfo.push_back("Model: " + myProperties.get(Cartridge_ModelNo));
myRomInfo.push_back("Rarity: " + myProperties.get(Cartridge_Rarity));
myRomInfo.push_back("Note: " + myProperties.get(Cartridge_Note));
bool swappedPorts = myProperties.get(Console_SwapPorts) == "YES";
myRomInfo.push_back("Controllers: " + (!swappedPorts
myRomInfo.push_back("Controllers: " + (!swappedPorts
? myProperties.get(Controller_Left) + " (left), " + myProperties.get(Controller_Right) + " (right)"
: myProperties.get(Controller_Right) + " (left), " + myProperties.get(Controller_Left) + " (right)"));
#if 0
myRomInfo.push_back("YStart/Height: " + myProperties.get(Display_YStart) +
myRomInfo.push_back("YStart/Height: " + myProperties.get(Display_YStart) +
" " + myProperties.get(Display_Height));
#endif
@ -142,9 +142,9 @@ void RomInfoWidget::drawWidget(bool hilite)
const int yoff = myAvail.h + 10;
s.fillRect(_x+2, _y+2, _w-4, _h-4, kWidColor);
s.box(_x, _y, _w, _h, kColor, kShadowColor);
s.box(_x, _y+yoff, _w, _h-yoff, kColor, kShadowColor);
s.fillRect(_x+2, _y+2, _w-4, _h-4, kDlgColor);
s.frameRect(_x, _y, _w, _h, kColor);
s.frameRect(_x, _y+yoff, _w, _h-yoff, kColor);
if(!myHaveProperties) return;
@ -167,10 +167,10 @@ void RomInfoWidget::drawWidget(bool hilite)
s.drawString(font, mySurfaceErrorMsg, x, y, _w - 10, _textcolor);
}
int xpos = _x + 5, ypos = _y + yoff + 10;
int xpos = _x + 8, ypos = _y + yoff + 10;
for(const auto& info: myRomInfo)
{
s.drawString(_font, info, xpos, ypos, _w - 10, _textcolor);
s.drawString(_font, info, xpos, ypos, _w - 16, _textcolor);
ypos += _font.getLineHeight();
}
}

View File

@ -32,26 +32,26 @@
// Up arrow
static uInt32 up_arrow[8] = {
0b00011000,
0b00011000,
0b00111100,
0b00111100,
0b01111110,
0b01111110,
0b11111111,
0b11111111
0b00000000,
0b00010000,
0b00111000,
0b01111100,
0b11101110,
0b11000110,
0b10000010,
0b00000000
};
// Down arrow
static uInt32 down_arrow[8] = {
0b11111111,
0b11111111,
0b01111110,
0b01111110,
0b00111100,
0b00111100,
0b00011000,
0b00011000
0b00000000,
0b10000010,
0b11000110,
0b11101110,
0b01111100,
0b00111000,
0b00010000,
0b00000000
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -101,11 +101,11 @@ void ScrollBarWidget::handleMouseDown(int x, int y, MouseButton b,
}
else if(y < _sliderPos)
{
_currentPos -= _entriesPerPage;
_currentPos -= _entriesPerPage - 1;
}
else if(y >= _sliderPos + _sliderHeight)
{
_currentPos += _entriesPerPage;
_currentPos += _entriesPerPage - 1;
}
else
{
@ -209,6 +209,7 @@ void ScrollBarWidget::checkBounds(int old_pos)
void ScrollBarWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -216,6 +217,7 @@ void ScrollBarWidget::handleMouseLeft()
{
_part = kNoPart;
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -250,31 +252,28 @@ void ScrollBarWidget::drawWidget(bool hilite)
int bottomY = _y + _h;
bool isSinglePage = (_numEntries <= _entriesPerPage);
s.frameRect(_x, _y, _w, _h, kShadowColor);
s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor);
if(_draggingPart != kNoPart)
_part = _draggingPart;
// Up arrow
s.frameRect(_x, _y, _w, UP_DOWN_BOX_HEIGHT, kColor);
s.drawBitmap(up_arrow, _x+3, _y+5, isSinglePage ? kColor :
(hilite && _part == kUpArrowPart) ? kScrollColorHi : kScrollColor, 8);
if(hilite && _part == kUpArrowPart)
s.fillRect(_x + 1, _y + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor);
s.drawBitmap(up_arrow, _x+4, _y+5, isSinglePage ? kColor :
(hilite && _part == kUpArrowPart) ? kWidColor : kTextColor, 8);
// Down arrow
s.frameRect(_x, bottomY - UP_DOWN_BOX_HEIGHT, _w, UP_DOWN_BOX_HEIGHT, kColor);
s.drawBitmap(down_arrow, _x+3, bottomY - UP_DOWN_BOX_HEIGHT + 5, isSinglePage ? kColor :
(hilite && _part == kDownArrowPart) ? kScrollColorHi : kScrollColor, 8);
if(hilite && _part == kDownArrowPart)
s.fillRect(_x + 1, bottomY - UP_DOWN_BOX_HEIGHT + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor);
s.drawBitmap(down_arrow, _x+4, bottomY - UP_DOWN_BOX_HEIGHT + 5, isSinglePage ? kColor :
(hilite && _part == kDownArrowPart) ? kWidColor : kTextColor, 8);
// Slider
if(!isSinglePage)
{
s.fillRect(_x, _y + _sliderPos, _w, _sliderHeight,
s.fillRect(_x + 1, _y + _sliderPos - 1, _w - 2, _sliderHeight + 2,
(hilite && _part == kSliderPart) ? kScrollColorHi : kScrollColor);
s.frameRect(_x, _y + _sliderPos, _w, _sliderHeight, kColor);
int y = _y + _sliderPos + _sliderHeight / 2;
s.hLine(_x + 2, y - 2, _x + _w - 3, kWidColor);
s.hLine(_x + 2, y, _x + _w - 3, kWidColor);
s.hLine(_x + 2, y + 2, _x + _w - 3, kWidColor);
}
}

View File

@ -25,7 +25,7 @@ class GuiObject;
#include "bspf.hxx"
enum {
kScrollBarWidth = 14
kScrollBarWidth = 15
};
class ScrollBarWidget : public Widget, public CommandSender

View File

@ -21,104 +21,87 @@
#include "FSNode.hxx"
#include "Font.hxx"
#include "LauncherDialog.hxx"
#include "PopUpWidget.hxx"
#include "Settings.hxx"
#include "SnapshotDialog.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent),
: Dialog(osystem, parent, font, "Snapshot settings"),
myFont(font)
{
const int VBORDER = 10;
const int HBORDER = 10;
const int INDENT = 16;
const int V_GAP = 4;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 4;
const int vBorder = 10;
int xpos, ypos, lwidth, fwidth;
int xpos, ypos, fwidth;
WidgetArray wid;
ButtonWidget* b;
// Set real dimensions
_w = 53 * fontWidth + 8;
_h = 10 * (lineHeight + 4) + 10;
_w = 64 * fontWidth + HBORDER * 2;
_h = 10 * (lineHeight + 4) + VBORDER + _th;
xpos = vBorder; ypos = vBorder;
xpos = HBORDER; ypos = VBORDER + _th;
// Snapshot path (save files)
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Save path" + ELLIPSIS, kChooseSnapSaveDirCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + 8;
mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(mySnapSavePath);
// Snapshot path (load files)
xpos = vBorder; ypos += buttonHeight + 3;
xpos = HBORDER; ypos += buttonHeight + V_GAP;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Load path" + ELLIPSIS, kChooseSnapLoadDirCmd);
wid.push_back(b);
xpos += buttonWidth + 10;
mySnapLoadPath = new EditTextWidget(this, font, xpos, ypos + 2,
_w - xpos - 10, lineHeight, "");
xpos += buttonWidth + 8;
mySnapLoadPath = new EditTextWidget(this, font, xpos, ypos + 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(mySnapLoadPath);
// Snapshot naming
lwidth = font.getStringWidth("Continuous snapshot interval ");
fwidth = font.getStringWidth("internal database");
VariantList items;
VarList::push_back(items, "actual ROM name", "rom");
VarList::push_back(items, "internal database", "int");
xpos = vBorder+10; ypos += buttonHeight + 8;
mySnapName =
new PopUpWidget(this, font, xpos, ypos, fwidth, lineHeight, items,
"Save snapshots according to ", lwidth);
wid.push_back(mySnapName);
xpos = HBORDER; ypos += buttonHeight + V_GAP * 4;
fwidth = font.getStringWidth("10 seconds");
// Snapshot interval (continuous mode)
items.clear();
VarList::push_back(items, "1 second", "1");
VarList::push_back(items, "2 seconds", "2");
VarList::push_back(items, "3 seconds", "3");
VarList::push_back(items, "4 seconds", "4");
VarList::push_back(items, "5 seconds", "5");
VarList::push_back(items, "6 seconds", "6");
VarList::push_back(items, "7 seconds", "7");
VarList::push_back(items, "8 seconds", "8");
VarList::push_back(items, "9 seconds", "9");
VarList::push_back(items, "10 seconds", "10");
ypos += buttonHeight;
mySnapInterval =
new PopUpWidget(this, font, xpos, ypos, fwidth, lineHeight, items,
"Continuous snapshot interval ", lwidth);
mySnapInterval = new SliderWidget(this, font, xpos, ypos,
"Continuous snapshot interval ", 0, kSnapshotInterval,
font.getStringWidth("10 seconds"));
mySnapInterval->setMinValue(1);
mySnapInterval->setMaxValue(10);
wid.push_back(mySnapInterval);
// Booleans for saving snapshots
fwidth = font.getStringWidth("When saving snapshots:");
xpos = vBorder; ypos += buttonHeight + 5;
xpos = HBORDER; ypos += lineHeight + V_GAP * 3;
new StaticTextWidget(this, font, xpos, ypos, fwidth, lineHeight,
"When saving snapshots:", TextAlign::Left);
// Snapshot single or multiple saves
xpos += 30; ypos += lineHeight + 3;
mySnapSingle = new CheckboxWidget(this, font, xpos, ypos,
"Overwrite existing files");
xpos += INDENT; ypos += lineHeight + V_GAP;
mySnapName = new CheckboxWidget(this, font, xpos, ypos, "Use actual ROM name");
wid.push_back(mySnapName);
ypos += lineHeight + V_GAP;
mySnapSingle = new CheckboxWidget(this, font, xpos, ypos, "Overwrite existing files");
wid.push_back(mySnapSingle);
// Snapshot in 1x mode (ignore scaling)
ypos += mySnapSingle->getHeight() + 4;
ypos += lineHeight + V_GAP;
mySnap1x = new CheckboxWidget(this, font, xpos, ypos,
"Ignore scaling (1x mode)");
wid.push_back(mySnap1x);
// Add Defaults, OK and Cancel buttons
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
font.getStringWidth("Defaults") + 20, buttonHeight,
"Defaults", GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
addDefaultsOKCancelBGroup(wid, font);
addToFocusList(wid);
}
@ -134,8 +117,8 @@ void SnapshotDialog::loadConfig()
const Settings& settings = instance().settings();
mySnapSavePath->setText(settings.getString("snapsavedir"));
mySnapLoadPath->setText(settings.getString("snaploaddir"));
mySnapName->setSelected(instance().settings().getString("snapname"), "int");
mySnapInterval->setSelected(instance().settings().getString("ssinterval"), "2");
mySnapInterval->setValue(instance().settings().getInt("ssinterval"));
mySnapName->setState(instance().settings().getString("snapname") == "rom");
mySnapSingle->setState(settings.getBool("sssingle"));
mySnap1x->setState(settings.getBool("ss1x"));
}
@ -145,12 +128,10 @@ void SnapshotDialog::saveConfig()
{
instance().settings().setValue("snapsavedir", mySnapSavePath->getText());
instance().settings().setValue("snaploaddir", mySnapLoadPath->getText());
instance().settings().setValue("snapname",
mySnapName->getSelectedTag().toString());
instance().settings().setValue("ssinterval", mySnapInterval->getValue());
instance().settings().setValue("snapname", mySnapName->getState() ? "rom" : "int");
instance().settings().setValue("sssingle", mySnapSingle->getState());
instance().settings().setValue("ss1x", mySnap1x->getState());
instance().settings().setValue("ssinterval",
mySnapInterval->getSelectedTag().toString());
// Flush changes to disk and inform the OSystem
instance().saveConfig();
@ -162,10 +143,10 @@ void SnapshotDialog::setDefaults()
{
mySnapSavePath->setText(instance().defaultSaveDir());
mySnapLoadPath->setText(instance().defaultLoadDir());
mySnapInterval->setValue(2);
mySnapName->setState(false);
mySnapSingle->setState(false);
mySnap1x->setState(false);
mySnapInterval->setSelected("2", "2");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -186,16 +167,16 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd,
case kChooseSnapSaveDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select snapshot save directory", mySnapSavePath->getText(),
createBrowser("Select snapshot save directory");
myBrowser->show(mySnapSavePath->getText(),
BrowserDialog::Directories, kSnapSaveDirChosenCmd);
break;
case kChooseSnapLoadDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser();
myBrowser->show("Select snapshot load directory", mySnapLoadPath->getText(),
createBrowser("Select snapshot load directory");
myBrowser->show(mySnapLoadPath->getText(),
BrowserDialog::Directories, kSnapLoadDirChosenCmd);
break;
@ -207,6 +188,13 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd,
mySnapLoadPath->setText(myBrowser->getResult().getShortPath());
break;
case kSnapshotInterval:
if(mySnapInterval->getValue() == 1)
mySnapInterval->setValueUnit(" second");
else
mySnapInterval->setValueUnit(" seconds");
break;
default:
Dialog::handleCommand(sender, cmd, data, 0);
break;
@ -214,13 +202,15 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SnapshotDialog::createBrowser()
void SnapshotDialog::createBrowser(const string& title)
{
uInt32 w = 0, h = 0;
getResizableBounds(w, h);
// Create file browser dialog
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h);
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
else
myBrowser->setTitle(title);
}

View File

@ -22,7 +22,6 @@ class OSystem;
class GuiObject;
class DialogContainer;
class CheckboxWidget;
class PopUpWidget;
class EditTextWidget;
class SliderWidget;
class StaticTextWidget;
@ -44,14 +43,15 @@ class SnapshotDialog : public Dialog
void setDefaults() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void createBrowser();
void createBrowser(const string& title);
private:
enum {
kChooseSnapSaveDirCmd = 'LOss', // snapshot dir (save files)
kChooseSnapLoadDirCmd = 'LOsl', // snapshot dir (load files)
kSnapSaveDirChosenCmd = 'snsc', // snap chosen (save files)
kSnapLoadDirChosenCmd = 'snlc' // snap chosen (load files)
kSnapLoadDirChosenCmd = 'snlc', // snap chosen (load files)
kSnapshotInterval = 'SnIn' // snap chosen (load files)
};
const GUI::Font& myFont;
@ -60,8 +60,8 @@ class SnapshotDialog : public Dialog
EditTextWidget* mySnapSavePath;
EditTextWidget* mySnapLoadPath;
PopUpWidget* mySnapName;
PopUpWidget* mySnapInterval;
CheckboxWidget* mySnapName;
SliderWidget* mySnapInterval;
CheckboxWidget* mySnapSingle;
CheckboxWidget* mySnap1x;

View File

@ -30,7 +30,7 @@
size: 95
ascent: 8
descent: 2
first char: 32 (0x20)
first char: 29 (0x1d)
last char: 126 (0x7e)
default char: 32 (0x20)
proportional: no
@ -42,6 +42,90 @@ namespace GUI {
// Font character bitmap data.
static const uInt16 stella_font_bits[] = {
/* Character 29 (0x1d):
width 6
bbx ( 6, 10, 0, -2 )
+------+
| |
| |
| |
| |
| |
| |
| |
|* * * |
| |
| |
+------+
*/
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0b1010100000000000,
0x0000,
0x0000,
/* Character 30 (0x1e):
width 6
bbx ( 6, 10, 0, -2 )
+------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+------+
*/
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
/* Character 31 (0x1f):
width 6
bbx ( 6, 10, 0, -2 )
+------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+------+
*/
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
/* Character 32 (0x20):
width 6
bbx ( 6, 10, 0, -2 )
@ -445,9 +529,9 @@ static const uInt16 stella_font_bits[] = {
| |
| |
| |
| * |
| *** |
| * |
| |
| ** |
| |
| |
+------+
*/
@ -457,9 +541,9 @@ static const uInt16 stella_font_bits[] = {
0x0000,
0x0000,
0x0000,
0x2000,
0x7000,
0x2000,
0x0000,
0x6000,
0x0000,
0x0000,
/* Character 47 (0x2f):
@ -777,25 +861,25 @@ static const uInt16 stella_font_bits[] = {
+------+
| |
| |
| * |
| *** |
| * |
| |
| * |
| *** |
| * |
| ** |
| |
| |
| |
| ** |
| |
| |
+------+
*/
0x0000,
0x0000,
0x2000,
0x7000,
0x2000,
0x0000,
0x2000,
0x7000,
0x2000,
0x6000,
0x0000,
0x0000,
0x0000,
0x6000,
0x0000,
0x0000,
/* Character 59 (0x3b):
@ -805,9 +889,9 @@ static const uInt16 stella_font_bits[] = {
+------+
| |
| |
| * |
| *** |
| * |
| |
| ** |
| |
| |
| ** |
| * |
@ -817,9 +901,9 @@ static const uInt16 stella_font_bits[] = {
*/
0x0000,
0x0000,
0x2000,
0x7000,
0x2000,
0x0000,
0x3000,
0x0000,
0x0000,
0x3000,
0x2000,
@ -2710,8 +2794,8 @@ static const FontDesc stellaDesc = {
10,
6, 10, 0, -2,
8,
32,
95,
29,
98,
stella_font_bits,
nullptr, /* no encode table*/
nullptr, /* fixed width*/

View File

@ -30,9 +30,9 @@
size: 95
ascent: 14
descent: 4
first char: 30 (0x1e)
first char: 29 (0x1d)
last char: 126 (0x7e)
default char: 30 (0x1e)
default char: 32 (0x20)
proportional: no
Public domain font. Share and enjoy.
*/

View File

@ -39,6 +39,20 @@ void StringListWidget::setList(const StringList& list)
ListWidget::recalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StringListWidget::handleMouseEntered()
{
setFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StringListWidget::handleMouseLeft()
{
clearFlags(WIDGET_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StringListWidget::drawWidget(bool hilite)
{
@ -46,9 +60,7 @@ void StringListWidget::drawWidget(bool hilite)
int i, pos, len = int(_list.size());
// Draw a thin frame around the list.
s.hLine(_x, _y, _x + _w - 1, kColor);
s.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
s.vLine(_x, _y, _y + _h - 1, kColor);
s.frameRect(_x, _y, _w + 1, _h, hilite && _hilite ? kWidColorHi : kColor);
// Draw the list items
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++)
@ -65,7 +77,7 @@ void StringListWidget::drawWidget(bool hilite)
textColor = kTextColorInv;
}
else
s.frameRect(_x + 1, _y + 1 + _fontHeight * i, _w - 1, _fontHeight, kTextColorHi);
s.frameRect(_x + 1, _y + 1 + _fontHeight * i, _w - 1, _fontHeight, kWidColorHi);
}
GUI::Rect r(getEditRect());

View File

@ -32,6 +32,8 @@ class StringListWidget : public ListWidget
bool wantsFocus() const override { return true; }
protected:
void handleMouseEntered() override;
void handleMouseLeft() override;
void drawWidget(bool hilite) override;
GUI::Rect getEditRect() const override;

View File

@ -253,29 +253,6 @@ void TabWidget::loadConfig()
updateActiveTab();
}
#ifndef FLAT_UI
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TabWidget::box(int x, int y, int width, int height,
uInt32 colorA, uInt32 colorB, bool omitBottom)
{
//cerr << "TabWidget::box\n";
FBSurface& s = _boss->dialog().surface();
s.hLine(x + 1, y, x + width - 2, colorA);
s.hLine(x, y + 1, x + width - 1, colorA);
s.vLine(x, y + 1, y + height - (omitBottom ? 1 : 2), colorA);
s.vLine(x + 1, y, y + height - (omitBottom ? 2 : 1), colorA);
if (!omitBottom)
{
s.hLine(x + 1, y + height - 2, x + width - 1, colorB);
s.hLine(x + 1, y + height - 1, x + width - 2, colorB);
}
s.vLine(x + width - 1, y + 1, y + height - (omitBottom ? 1 : 2), colorB);
s.vLine(x + width - 2, y + 1, y + height - (omitBottom ? 2 : 1), colorB);
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TabWidget::drawWidget(bool hilite)
{
@ -291,25 +268,11 @@ void TabWidget::drawWidget(bool hilite)
const int left2 = right1 + _tabWidth;
const int right2 = _x + _w - 2;
#ifndef FLAT_UI
// Draw horizontal line
s.hLine(left1, _y + _tabHeight - 2, right1, kShadowColor);
s.hLine(left2, _y + _tabHeight - 2, right2, kShadowColor);
#endif
// Iterate over all tabs and draw them
int i, x = _x + kTabLeftOffset;
for (i = 0; i < int(_tabs.size()); ++i)
{
uInt32 fontcolor = _tabs[i].enabled ? kTextColor : kColor;
#ifndef FLAT_UI
uInt32 boxcolor = (i == _activeTab) ? kColor : kShadowColor;
int yOffset = (i == _activeTab) ? 0 : 2;
box(x, _y + yOffset, _tabWidth, _tabHeight - yOffset, boxcolor, boxcolor, (i == _activeTab));
s.drawString(_font, _tabs[i].title, x + kTabPadding,
_y + yOffset / 2 + (_tabHeight - _fontHeight - 1),
_tabWidth - 2 * kTabPadding, fontcolor, TextAlign::Center);
#else
int yOffset = (i == _activeTab) ? 0 : 1;
s.fillRect(x, _y + 1, _tabWidth, _tabHeight - 1, (i == _activeTab)
? kDlgColor : kBGColorHi); // ? kWidColor : kDlgColor
@ -323,23 +286,13 @@ void TabWidget::drawWidget(bool hilite)
}
else
s.hLine(x, _y + _tabHeight, x + _tabWidth, kWidColor);
#endif
x += _tabWidth + kTabSpacing;
}
#ifndef FLAT_UI
// Draw a frame around the widget area (belows the tabs)
s.hLine(left1, _y + _tabHeight - 1, right1, kColor);
s.hLine(left2, _y + _tabHeight - 1, right2, kColor);
s.hLine(_x+1, _y + _h - 2, _x + _w - 2, kShadowColor);
s.hLine(_x+1, _y + _h - 1, _x + _w - 2, kColor);
s.vLine(_x + _w - 2, _y + _tabHeight - 1, _y + _h - 2, kColor);
s.vLine(_x + _w - 1, _y + _tabHeight - 1, _y + _h - 2, kShadowColor);
#else
// fill empty right space
s.hLine(x - kTabSpacing + 1, _y + _tabHeight, _x + _w - 1, kWidColor);
s.hLine(_x, _y + _h - 1, _x + _w - 1, kBGColorLo);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -90,22 +90,12 @@ class TabWidget : public Widget, public CommandSender
bool _firstTime;
enum {
#ifndef FLAT_UI
kTabLeftOffset = 4,
kTabSpacing = 2,
kTabPadding = 3
#else
kTabLeftOffset = 0,
kTabSpacing = 1,
kTabPadding = 4
#endif
};
private:
#ifndef FLAT_UI
void box(int x, int y, int width, int height,
uInt32 colorA, uInt32 colorB, bool omitBottom);
#endif
void updateActiveTab();
private:

232
src/gui/TimeLineWidget.cxx Normal file
View File

@ -0,0 +1,232 @@
//============================================================================
//
// 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-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "bspf.hxx"
#include "Command.hxx"
#include "Dialog.hxx"
#include "Font.hxx"
#include "FBSurface.hxx"
#include "GuiObject.hxx"
#include "OSystem.hxx"
#include "TimeLineWidget.hxx"
// TODO - remove all references to _stepValue__
// - fix posToValue to use _stepValue
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h,
const string& label, int labelWidth, int cmd)
: ButtonWidget(boss, font, x, y, w, h, label, cmd),
_value(0),
_stepValue__(1),
_valueMin(0),
_valueMax(100),
_isDragging(false),
_labelWidth(labelWidth)
{
_flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE;
_bgcolor = kDlgColor;
_bgcolorhi = kDlgColor;
if(!_label.empty() && _labelWidth == 0)
_labelWidth = _font.getStringWidth(_label);
_w = w + _labelWidth;
_stepValue.reserve(100);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::setValue(int value)
{
if(value < _valueMin) value = _valueMin;
else if(value > _valueMax) value = _valueMax;
if(value != _value)
{
_value = value;
setDirty();
sendCommand(_cmd, _value, _id);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::setMinValue(int value)
{
_valueMin = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::setMaxValue(int value)
{
_valueMax = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::setStepValues(const IntArray& steps)
{
// Try to allocate as infrequently as possible
if(steps.size() > _stepValue.capacity())
_stepValue.reserve(2 * steps.size());
_stepValue.clear();
double scale = (_w - _labelWidth - 4) / double(steps.back());
// Skip the very last value; we take care of it outside the end of the loop
for(uInt32 i = 0; i < steps.size() - 1; ++i)
_stepValue.push_back(int(steps[i] * scale));
// Due to integer <-> double conversion, the last value is sometimes
// slightly less than the maximum value; we assign it manually to fix this
_stepValue.push_back(_w - _labelWidth - 4);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::handleMouseMoved(int x, int y)
{
// TODO: when the mouse is dragged outside the widget, the slider should
// snap back to the old value.
if(isEnabled() && _isDragging && x >= int(_labelWidth))
setValue(posToValue(x - _labelWidth));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
{
if(isEnabled() && b == MouseButton::LEFT)
{
_isDragging = true;
handleMouseMoved(x, y);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
{
if(isEnabled() && _isDragging)
sendCommand(_cmd, _value, _id);
_isDragging = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::handleMouseWheel(int x, int y, int direction)
{
if(isEnabled())
{
if(direction < 0)
handleEvent(Event::UIUp);
else if(direction > 0)
handleEvent(Event::UIDown);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TimeLineWidget::handleEvent(Event::Type e)
{
if(!isEnabled())
return false;
switch(e)
{
case Event::UIDown:
case Event::UILeft:
case Event::UIPgDown:
setValue(_value - _stepValue__);
break;
case Event::UIUp:
case Event::UIRight:
case Event::UIPgUp:
setValue(_value + _stepValue__);
break;
case Event::UIHome:
setValue(_valueMin);
break;
case Event::UIEnd:
setValue(_valueMax);
break;
default:
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeLineWidget::drawWidget(bool hilite)
{
FBSurface& s = _boss->dialog().surface();
#ifndef FLAT_UI
// Draw the label, if any
if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + 2, _labelWidth,
isEnabled() ? kTextColor : kColor, TextAlign::Right);
// Draw the box
s.box(_x + _labelWidth, _y, _w - _labelWidth, _h, kColor, kShadowColor);
// Fill the box
s.fillRect(_x + _labelWidth + 2, _y + 2, _w - _labelWidth - 4, _h - 4,
!isEnabled() ? kBGColorHi : kWidColor);
// Draw the 'bar'
s.fillRect(_x + _labelWidth + 2, _y + 2, valueToPos(_value), _h - 4,
!isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor);
#else
// Draw the label, if any
if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + 2, _labelWidth,
isEnabled() ? kTextColor : kColor, TextAlign::Left);
// Draw the box
s.frameRect(_x + _labelWidth, _y, _w - _labelWidth, _h, isEnabled() && hilite ? kSliderColorHi : kShadowColor);
// Fill the box
s.fillRect(_x + _labelWidth + 1, _y + 1, _w - _labelWidth - 2, _h - 2,
!isEnabled() ? kBGColorHi : kWidColor);
// Draw the 'bar'
s.fillRect(_x + _labelWidth + 2, _y + 2, valueToPos(_value), _h - 4,
!isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int TimeLineWidget::valueToPos(int value)
{
if(value < _valueMin) value = _valueMin;
else if(value > _valueMax) value = _valueMax;
int real = _stepValue[BSPF::clamp(value, _valueMin, _valueMax)];
#if 0
int range = std::max(_valueMax - _valueMin, 1); // don't divide by zero
int actual = ((_w - _labelWidth - 4) * (value - _valueMin) / range);
cerr << "i=" << value << " real=" << real << endl << "actual=" << actual << endl << endl;
#endif
return real;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int TimeLineWidget::posToValue(int pos)
{
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
// Scale the position to the correct interval (according to step value)
return value - (value % _stepValue__);
}

View File

@ -0,0 +1,73 @@
//============================================================================
//
// 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-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef TIMELINE_WIDGET_HXX
#define TIMELINE_WIDGET_HXX
#include "Widget.hxx"
class TimeLineWidget : public ButtonWidget
{
public:
TimeLineWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h, const string& label = "",
int labelWidth = 0, int cmd = 0);
void setValue(int value);
int getValue() const { return _value; }
void setMinValue(int value);
int getMinValue() const { return _valueMin; }
void setMaxValue(int value);
int getMaxValue() const { return _valueMax; }
/**
Steps are not necessarily linear in a timeline, so we need info
on each interval instead.
*/
void setStepValues(const IntArray& steps);
protected:
void handleMouseMoved(int x, int y) override;
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override;
bool handleEvent(Event::Type event) override;
void drawWidget(bool hilite) override;
int valueToPos(int value);
int posToValue(int pos);
protected:
int _value, _stepValue__;
int _valueMin, _valueMax;
bool _isDragging;
int _labelWidth;
IntArray _stepValue;
private:
// Following constructors and assignment operators not supported
TimeLineWidget() = delete;
TimeLineWidget(const TimeLineWidget&) = delete;
TimeLineWidget(TimeLineWidget&&) = delete;
TimeLineWidget& operator=(const TimeLineWidget&) = delete;
TimeLineWidget& operator=(TimeLineWidget&&) = delete;
};
#endif

Some files were not shown because too many files have changed in this diff Show More