diff --git a/Changes.txt b/Changes.txt index 4600e6451..fbd594b57 100644 --- a/Changes.txt +++ b/Changes.txt @@ -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 diff --git a/Makefile b/Makefile index 2b0c212c8..35a1e3606 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/docs/index.html b/docs/index.html index dbc1313c9..a89ca6d67 100644 --- a/docs/index.html +++ b/docs/index.html @@ -268,7 +268,7 @@ joysticks or mouse
  • Emulates the Sega Genesis Controller using your computer's keyboard, joysticks or mouse
  • -
  • Emulates CX22/CX80 style trakballs and Amiga/Atari Mouse using your +
  • Emulates CX22/CX80 style trackballs and Amiga/Atari Mouse using your computer's mouse
  • Emulates Spectravideo CompuMate system using your computer's keyboard, including mapping of CompuMate 'Backspace', 'Space' and 'Enter' functionality to @@ -645,8 +645,8 @@ Enter/exit options mode - Tab - Tab + Tab/Escape + Tab/Escape @@ -1745,12 +1745,12 @@ ✓ - Trakball/Mouse + Trackball/Mouse ✕ ✕ ✓ ✓ (axis ignored) - ✕ + ✓ CompuMate @@ -2103,7 +2103,7 @@
    -usemouse <always|analog|never>
    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.). + (paddles, trackball, etc.). @@ -2995,8 +2995,9 @@

    Stelladaptor/2600-daptor Support

    -

    Stella supports real Atari 2600 joysticks, paddles and driving controllers - using the Stelladaptor and +

    Stella supports real Atari 2600 joysticks, paddles, driving controllers + and trackballs (CX22/CX80 'Trak-Ball', Atari and Amiga mouse) using the + Stelladaptor and 2600-daptor devices.

    Stella can use up to two 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.
    + becomes larger the further they are back in time.
    (*) Compresion only works if 'Uncompressed size' is smaller than 'Buffer size'. diff --git a/src/cheat/CheatCodeDialog.cxx b/src/cheat/CheatCodeDialog.cxx index 4b5495080..6fbb3b110 100644 --- a/src/cheat/CheatCodeDialog.cxx +++ b/src/cheat/CheatCodeDialog.cxx @@ -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(this, font, labels); + myCheatInput = make_unique(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; } diff --git a/src/common/Base.cxx b/src/common/Base.cxx index f3d668b33..1347300f3 100644 --- a/src/common/Base.cxx +++ b/src/common/Base.cxx @@ -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; diff --git a/src/common/Base.hxx b/src/common/Base.hxx index 3c4916abe..8ccd739e2 100644 --- a/src/common/Base.hxx +++ b/src/common/Base.hxx @@ -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 diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index 3944849ce..74969ed55 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -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. diff --git a/src/common/LinkedObjectPool.hxx b/src/common/LinkedObjectPool.hxx index 3bbabfb9f..1b434cea8 100644 --- a/src/common/LinkedObjectPool.hxx +++ b/src/common/LinkedObjectPool.hxx @@ -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. */ diff --git a/src/common/RewindManager.cxx b/src/common/RewindManager.cxx index f6d6d0b62..165eb1e19 100644 --- a/src/common/RewindManager.cxx +++ b/src/common/RewindManager.cxx @@ -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::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::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::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; +} diff --git a/src/common/RewindManager.hxx b/src/common/RewindManager.hxx index 8749aa109..6066beadf 100644 --- a/src/common/RewindManager.hxx +++ b/src/common/RewindManager.hxx @@ -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; diff --git a/src/common/Stack.hxx b/src/common/Stack.hxx index f1ae48ae4..ef267e7e2 100644 --- a/src/common/Stack.hxx +++ b/src/common/Stack.hxx @@ -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; } diff --git a/src/common/StateManager.cxx b/src/common/StateManager.cxx index 706f8f019..5ab51fb8f 100644 --- a/src/common/StateManager.cxx +++ b/src/common/StateManager.cxx @@ -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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/StateManager.hxx b/src/common/StateManager.hxx index 0e322f8dd..851694299 100644 --- a/src/common/StateManager.hxx +++ b/src/common/StateManager.hxx @@ -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. diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 44ab97567..c8a5972f8 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -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 diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 95da6a018..c840e9a78 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -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: diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index 0324cbdc0..76b32e9e5 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -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 diff --git a/src/debugger/RiotDebug.cxx b/src/debugger/RiotDebug.cxx index bc8a89b99..e218a6c58 100644 --- a/src/debugger/RiotDebug.cxx +++ b/src/debugger/RiotDebug.cxx @@ -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() diff --git a/src/debugger/RiotDebug.hxx b/src/debugger/RiotDebug.hxx index d6425d8a0..fc871d722 100644 --- a/src/debugger/RiotDebug.hxx +++ b/src/debugger/RiotDebug.hxx @@ -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; diff --git a/src/debugger/gui/CartDebugWidget.cxx b/src/debugger/gui/CartDebugWidget.cxx index 82cbb6f34..c6b2f664a 100644 --- a/src/debugger/gui/CartDebugWidget.cxx +++ b/src/debugger/gui/CartDebugWidget.cxx @@ -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; diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index e2b39ecaa..ab12fd5c2 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -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++) diff --git a/src/debugger/gui/DataGridWidget.hxx b/src/debugger/gui/DataGridWidget.hxx index 4b931a6d2..bd84168d2 100644 --- a/src/debugger/gui/DataGridWidget.hxx +++ b/src/debugger/gui/DataGridWidget.hxx @@ -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; diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 9c81fcfdf..861deff3f 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -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(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()); diff --git a/src/debugger/gui/DelayQueueWidget.cxx b/src/debugger/gui/DelayQueueWidget.cxx index 5bf6b0b1b..281947e22 100644 --- a/src/debugger/gui/DelayQueueWidget.cxx +++ b/src/debugger/gui/DelayQueueWidget.cxx @@ -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; diff --git a/src/debugger/gui/PaddleWidget.cxx b/src/debugger/gui/PaddleWidget.cxx index 81d596bca..42f6fe0a4 100644 --- a/src/debugger/gui/PaddleWidget.cxx +++ b/src/debugger/gui/PaddleWidget.cxx @@ -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)); diff --git a/src/debugger/gui/RamWidget.cxx b/src/debugger/gui/RamWidget.cxx index 5b1493471..9002313dd 100644 --- a/src/debugger/gui/RamWidget.cxx +++ b/src/debugger/gui/RamWidget.cxx @@ -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(boss, lfont, nfont, labels); + StringList labels = { "Value" }; + myInputBox = make_unique(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"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/RiotWidget.cxx b/src/debugger/gui/RiotWidget.cxx index 091abf935..39dd3b21f 100644 --- a/src/debugger/gui/RiotWidget.cxx +++ b/src/debugger/gui/RiotWidget.cxx @@ -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]); diff --git a/src/debugger/gui/RiotWidget.hxx b/src/debugger/gui/RiotWidget.hxx index e5f03ed13..1582872d6 100644 --- a/src/debugger/gui/RiotWidget.hxx +++ b/src/debugger/gui/RiotWidget.hxx @@ -59,6 +59,7 @@ class RiotWidget : public Widget, public CommandSender DataGridWidget* myTimWrite; DataGridWidget* myTimRead; + DataGridWidget* myTimDivider; ControllerWidget *myLeftControl, *myRightControl; PopUpWidget *myP0Diff, *myP1Diff; diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 86108950e..bc077e94b 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -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 diff --git a/src/debugger/gui/RomListWidget.hxx b/src/debugger/gui/RomListWidget.hxx index 312d9dbfc..3f55d991b 100644 --- a/src/debugger/gui/RomListWidget.hxx +++ b/src/debugger/gui/RomListWidget.hxx @@ -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; diff --git a/src/debugger/gui/TiaZoomWidget.cxx b/src/debugger/gui/TiaZoomWidget.cxx index a52df7a5d..195ae4514 100644 --- a/src/debugger/gui/TiaZoomWidget.cxx +++ b/src/debugger/gui/TiaZoomWidget.cxx @@ -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 } } } diff --git a/src/debugger/gui/TiaZoomWidget.hxx b/src/debugger/gui/TiaZoomWidget.hxx index 890e4af64..3e3cfaa2b 100644 --- a/src/debugger/gui/TiaZoomWidget.hxx +++ b/src/debugger/gui/TiaZoomWidget.hxx @@ -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(); diff --git a/src/debugger/gui/ToggleBitWidget.cxx b/src/debugger/gui/ToggleBitWidget.cxx index 05579f9d4..ebd6c1898 100644 --- a/src/debugger/gui/ToggleBitWidget.cxx +++ b/src/debugger/gui/ToggleBitWidget.cxx @@ -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++) diff --git a/src/debugger/gui/TogglePixelWidget.cxx b/src/debugger/gui/TogglePixelWidget.cxx index 40845c4df..929c43200 100644 --- a/src/debugger/gui/TogglePixelWidget.cxx +++ b/src/debugger/gui/TogglePixelWidget.cxx @@ -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 } } diff --git a/src/debugger/gui/ToggleWidget.cxx b/src/debugger/gui/ToggleWidget.cxx index aa05632b2..062eb58e0 100644 --- a/src/debugger/gui/ToggleWidget.cxx +++ b/src/debugger/gui/ToggleWidget.cxx @@ -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) { diff --git a/src/debugger/gui/ToggleWidget.hxx b/src/debugger/gui/ToggleWidget.hxx index dbdecb1f1..e91f7fcba 100644 --- a/src/debugger/gui/ToggleWidget.hxx +++ b/src/debugger/gui/ToggleWidget.hxx @@ -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; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index f55308007..ac36877ab 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -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) { diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 0564c5d2e..4821f4ca2 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -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); diff --git a/src/emucore/FBSurface.cxx b/src/emucore/FBSurface.cxx index 2b0362857..ef93e0dfc 100644 --- a/src/emucore/FBSurface.cxx +++ b/src/emucore/FBSurface.cxx @@ -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; } diff --git a/src/emucore/FBSurface.hxx b/src/emucore/FBSurface.hxx index 87757078b..21d06306f 100644 --- a/src/emucore/FBSurface.hxx +++ b/src/emucore/FBSurface.hxx @@ -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 diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 456175997..1554ddd94 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -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 } }; diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 975ecbf4e..eb834815e 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -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 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; diff --git a/src/emucore/FrameBufferConstants.hxx b/src/emucore/FrameBufferConstants.hxx index 1af98a6ae..081d7cd68 100644 --- a/src/emucore/FrameBufferConstants.hxx +++ b/src/emucore/FrameBufferConstants.hxx @@ -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 }; diff --git a/src/emucore/MT24LC256.cxx b/src/emucore/MT24LC256.cxx index 62d7e4446..80fe2f4e3 100644 --- a/src/emucore/MT24LC256.cxx +++ b/src/emucore/MT24LC256.cxx @@ -18,6 +18,9 @@ #include #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]]; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 95175dc67..2a5704382 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -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) diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index ac09c2478..b54c366ed 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -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; } diff --git a/src/emucore/System.hxx b/src/emucore/System.hxx index b9dd5ee3b..de6e354df 100644 --- a/src/emucore/System.hxx +++ b/src/emucore/System.hxx @@ -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. diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index f7cbe949a..bc79b5ede 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -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; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index d574b40ef..76410d349 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -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: diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx index 6873f41eb..54fc3f241 100644 --- a/src/gui/AudioDialog.cxx +++ b/src/gui/AudioDialog.cxx @@ -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; diff --git a/src/gui/AudioDialog.hxx b/src/gui/AudioDialog.hxx index 617399123..1ca83be00 100644 --- a/src/gui/AudioDialog.hxx +++ b/src/gui/AudioDialog.hxx @@ -45,12 +45,10 @@ class AudioDialog : public Dialog private: enum { - kVolumeChanged = 'ADvc', kSoundEnableChanged = 'ADse' }; SliderWidget* myVolumeSlider; - StaticTextWidget* myVolumeLabel; PopUpWidget* myFragsizePopup; PopUpWidget* myFreqPopup; CheckboxWidget* mySoundEnableCheckbox; diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 9d31527a8..911c38af0 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -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(); diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index 80597c7d3..e928b683e 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -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; diff --git a/src/gui/CheckListWidget.cxx b/src/gui/CheckListWidget.cxx index 10950a09d..53c747794 100644 --- a/src/gui/CheckListWidget.cxx +++ b/src/gui/CheckListWidget.cxx @@ -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 diff --git a/src/gui/CheckListWidget.hxx b/src/gui/CheckListWidget.hxx index 3626a954b..a48f35385 100644 --- a/src/gui/CheckListWidget.hxx +++ b/src/gui/CheckListWidget.hxx @@ -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; diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 27b632b03..9abcf2d91 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -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 } } diff --git a/src/gui/ComboDialog.cxx b/src/gui/ComboDialog.cxx index 377bab487..3ac85213c 100644 --- a/src/gui/ComboDialog.cxx +++ b/src/gui/ComboDialog.cxx @@ -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 diff --git a/src/gui/ComboDialog.hxx b/src/gui/ComboDialog.hxx index 8585e9399..f6ad4db57 100644 --- a/src/gui/ComboDialog.hxx +++ b/src/gui/ComboDialog.hxx @@ -45,7 +45,6 @@ class ComboDialog : public Dialog private: Event::Type myComboEvent; - StaticTextWidget* myComboName; PopUpWidget* myEvents[8]; private: diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 84e9ee698..ad6735cc1 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -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) diff --git a/src/gui/ConfigPathDialog.cxx b/src/gui/ConfigPathDialog.cxx index 6c27a8525..07caff59e 100644 --- a/src/gui/ConfigPathDialog.cxx +++ b/src/gui/ConfigPathDialog.cxx @@ -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(this, myFont, w, h); + uInt32(myBrowser->getHeight()) != h) + myBrowser = make_unique(this, myFont, w, h, title); + else + myBrowser->setTitle(title); } diff --git a/src/gui/ConfigPathDialog.hxx b/src/gui/ConfigPathDialog.hxx index def491369..9195debb4 100644 --- a/src/gui/ConfigPathDialog.hxx +++ b/src/gui/ConfigPathDialog.hxx @@ -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; diff --git a/src/gui/ContextMenu.cxx b/src/gui/ContextMenu.cxx index 5880db8ba..ba1ff7761 100644 --- a/src/gui/ContextMenu.cxx +++ b/src/gui/ContextMenu.cxx @@ -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); } diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index b19a7ebcb..b1f2b4883 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -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 } diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx index 27577b89f..eb0b39eaa 100644 --- a/src/gui/DeveloperDialog.hxx +++ b/src/gui/DeveloperDialog.hxx @@ -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); diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 8caceff55..6a3f71907 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -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) { diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 73804a0c6..8773a40d0 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -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> mySurfaceStack; diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index e23f37cbb..7223bc834 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -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(); diff --git a/src/gui/EditTextWidget.hxx b/src/gui/EditTextWidget.hxx index 0e2548f3a..e5252ea3a 100644 --- a/src/gui/EditTextWidget.hxx +++ b/src/gui/EditTextWidget.hxx @@ -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; diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index 1c83a055b..67cfefec1 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -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); } diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 368eaf0cf..519a3acfb 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -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; diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index 2ffd7b053..f95ecea1f 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -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', diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index 5fe9c7367..23de11795 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -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); } diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index 15bb77497..5235c09d8 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -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); diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 62be23f58..d3a6549fb 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -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 - (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 (this, instance().frameBuffer().font(), msg, myMaxWidth, myMaxHeight, kConfirmEEEraseCmd, - "OK", "Cancel", false); + "OK", "Cancel", "Erase EEPROM", false); } myConfirmMsg->show(); break; diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 7cee52005..44ea8c6c9 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -73,7 +73,7 @@ class InputDialog : public Dialog EventMappingWidget* myEmulEventMapper; EventMappingWidget* myMenuEventMapper; - PopUpWidget* mySAPort; + CheckboxWidget* mySAPort; PopUpWidget* myMouseControl; PopUpWidget* myCursorState; diff --git a/src/gui/InputTextDialog.cxx b/src/gui/InputTextDialog.cxx index a23a70422..771cd707a 100644 --- a/src/gui/InputTextDialog.cxx +++ b/src/gui/InputTextDialog.cxx @@ -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; diff --git a/src/gui/InputTextDialog.hxx b/src/gui/InputTextDialog.hxx index 5e691556e..8706bee15 100644 --- a/src/gui/InputTextDialog.hxx +++ b/src/gui/InputTextDialog.hxx @@ -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 myInput; - StaticTextWidget* myTitle; + StaticTextWidget* myMessage; bool myEnableCenter; bool myErrorFlag; diff --git a/src/gui/JoystickDialog.cxx b/src/gui/JoystickDialog.cxx index 68153c57d..791f80597 100644 --- a/src/gui/JoystickDialog.cxx +++ b/src/gui/JoystickDialog.cxx @@ -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); diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 941d9ce8e..69d20b00c 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -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 (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(this, instance().frameBuffer().font(), _w, _h); - - myRomDir->show("Select ROM directory", "~", - BrowserDialog::Directories, kStartupRomDirChosenCmd); + myRomDir = make_unique(this, instance().frameBuffer().font(), + _w, _h, "Select ROM directory"); + myRomDir->show("~", BrowserDialog::Directories, kStartupRomDirChosenCmd); break; case kStartupRomDirChosenCmd: diff --git a/src/gui/LauncherFilterDialog.cxx b/src/gui/LauncherFilterDialog.cxx index 789630ec7..704c9f5e2 100644 --- a/src/gui/LauncherFilterDialog.cxx +++ b/src/gui/LauncherFilterDialog.cxx @@ -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; } diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 67e0b3a39..18fb3b913 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -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", diff --git a/src/gui/MessageBox.cxx b/src/gui/MessageBox.cxx index 0812831b4..32c2e9c60 100644 --- a/src/gui/MessageBox.cxx +++ b/src/gui/MessageBox.cxx @@ -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, diff --git a/src/gui/MessageBox.hxx b/src/gui/MessageBox.hxx index f80512a52..b983b2124 100644 --- a/src/gui/MessageBox.hxx +++ b/src/gui/MessageBox.hxx @@ -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; diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index c3c42dfc3..30c291387 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -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); diff --git a/src/gui/PopUpWidget.cxx b/src/gui/PopUpWidget.cxx index 1cedb56fc..aaf9d810c 100644 --- a/src/gui/PopUpWidget.cxx +++ b/src/gui/PopUpWidget.cxx @@ -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(); diff --git a/src/gui/PopUpWidget.hxx b/src/gui/PopUpWidget.hxx index a3da6dd36..aecdfe00d 100644 --- a/src/gui/PopUpWidget.hxx +++ b/src/gui/PopUpWidget.hxx @@ -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; diff --git a/src/gui/RadioButtonWidget.cxx b/src/gui/RadioButtonWidget.cxx index ddd69d564..e0549ee1d 100644 --- a/src/gui/RadioButtonWidget.cxx +++ b/src/gui/RadioButtonWidget.cxx @@ -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, diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 3b0cc7b07..26de177b0 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -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(this, font, myMaxWidth, myMaxHeight); + myBrowser = make_unique(this, font, myMaxWidth, myMaxHeight, "Select ROM directory to audit"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -189,7 +189,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, myConfirmMsg = make_unique (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; diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index 53f402a24..bdd6278ef 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -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(); } } diff --git a/src/gui/ScrollBarWidget.cxx b/src/gui/ScrollBarWidget.cxx index b74d0e23d..8e3960965 100644 --- a/src/gui/ScrollBarWidget.cxx +++ b/src/gui/ScrollBarWidget.cxx @@ -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); } } diff --git a/src/gui/ScrollBarWidget.hxx b/src/gui/ScrollBarWidget.hxx index 3e40a6fc3..0756d635c 100644 --- a/src/gui/ScrollBarWidget.hxx +++ b/src/gui/ScrollBarWidget.hxx @@ -25,7 +25,7 @@ class GuiObject; #include "bspf.hxx" enum { - kScrollBarWidth = 14 + kScrollBarWidth = 15 }; class ScrollBarWidget : public Widget, public CommandSender diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index d8671a991..b8e6a1efc 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -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(this, myFont, w, h); + uInt32(myBrowser->getHeight()) != h) + myBrowser = make_unique(this, myFont, w, h, title); + else + myBrowser->setTitle(title); } diff --git a/src/gui/SnapshotDialog.hxx b/src/gui/SnapshotDialog.hxx index 8d1cbbd88..9eaa01b04 100644 --- a/src/gui/SnapshotDialog.hxx +++ b/src/gui/SnapshotDialog.hxx @@ -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; diff --git a/src/gui/StellaFont.hxx b/src/gui/StellaFont.hxx index 96fe715d4..968afad49 100644 --- a/src/gui/StellaFont.hxx +++ b/src/gui/StellaFont.hxx @@ -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*/ diff --git a/src/gui/StellaMediumFont.hxx b/src/gui/StellaMediumFont.hxx index c3c892b01..48ed6d7ae 100644 --- a/src/gui/StellaMediumFont.hxx +++ b/src/gui/StellaMediumFont.hxx @@ -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. */ diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index 544416a13..cd5a6fe9b 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -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()); diff --git a/src/gui/StringListWidget.hxx b/src/gui/StringListWidget.hxx index 5cd89c3a6..1894bca9a 100644 --- a/src/gui/StringListWidget.hxx +++ b/src/gui/StringListWidget.hxx @@ -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; diff --git a/src/gui/TabWidget.cxx b/src/gui/TabWidget.cxx index d30cb320e..d456c35d4 100644 --- a/src/gui/TabWidget.cxx +++ b/src/gui/TabWidget.cxx @@ -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 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/TabWidget.hxx b/src/gui/TabWidget.hxx index 5adb99f61..132502685 100644 --- a/src/gui/TabWidget.hxx +++ b/src/gui/TabWidget.hxx @@ -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: diff --git a/src/gui/TimeLineWidget.cxx b/src/gui/TimeLineWidget.cxx new file mode 100644 index 000000000..d99c7d58a --- /dev/null +++ b/src/gui/TimeLineWidget.cxx @@ -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__); +} diff --git a/src/gui/TimeLineWidget.hxx b/src/gui/TimeLineWidget.hxx new file mode 100644 index 000000000..397ee241e --- /dev/null +++ b/src/gui/TimeLineWidget.hxx @@ -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 diff --git a/src/gui/TimeMachineDialog.cxx b/src/gui/TimeMachineDialog.cxx index bd38faf45..9641adfed 100644 --- a/src/gui/TimeMachineDialog.cxx +++ b/src/gui/TimeMachineDialog.cxx @@ -24,18 +24,16 @@ #include "Widget.hxx" #include "StateManager.hxx" #include "RewindManager.hxx" - +#include "TimeLineWidget.hxx" #include "Console.hxx" #include "TIA.hxx" #include "System.hxx" - #include "TimeMachineDialog.hxx" #include "Base.hxx" using Common::Base; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, int max_w, int max_h) @@ -43,23 +41,6 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, { const int BUTTON_W = 16, BUTTON_H = 14; - /*static uInt32 PAUSE[BUTTON_H] = - { - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000, - 0b0001111001111000 - };*/ static uInt32 PLAY[BUTTON_H] = { 0b0110000000000000, @@ -181,79 +162,80 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, }; const GUI::Font& font = instance().frameBuffer().font(); - const int H_BORDER = 6, BUTTON_GAP = 4, V_BORDER = 4, V_GAP = 4; + const int H_BORDER = 6, BUTTON_GAP = 4, V_BORDER = 4; const int buttonWidth = BUTTON_W + 8, buttonHeight = BUTTON_H + 10, rowHeight = font.getLineHeight(); - WidgetArray wid; int xpos, ypos; // Set real dimensions _w = 20 * (buttonWidth + BUTTON_GAP) + 20; _h = V_BORDER * 2 + rowHeight + buttonHeight + 2; - //this->clearFlags(WIDGET_CLEARBG); // does only work combined with blending! - //this->clearFlags(WIDGET_BORDER); + this->clearFlags(WIDGET_CLEARBG); // does only work combined with blending (0..100)! + this->clearFlags(WIDGET_BORDER); xpos = H_BORDER; ypos = V_BORDER; // Add index info - myCurrentIdxWidget = new StaticTextWidget(this, font, xpos, ypos, " "); + myCurrentIdxWidget = new StaticTextWidget(this, font, xpos, ypos, " ", TextAlign::Left, kBGColor); + myCurrentIdxWidget->setTextColor(kColorInfo); myLastIdxWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("8888"), ypos, - " ", TextAlign::Right); + " ", TextAlign::Right, kBGColor); + myLastIdxWidget->setTextColor(kColorInfo); + + // Add timeline + const uInt32 tl_h = myCurrentIdxWidget->getHeight() / 2, + tl_x = xpos + myCurrentIdxWidget->getWidth() + 8, + tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2, + tl_w = myLastIdxWidget->getAbsX() - tl_x - 8; + myTimeline = new TimeLineWidget(this, font, tl_x, tl_y, tl_w, tl_h, "", 0, kTimeline); + myTimeline->setMinValue(0); ypos += rowHeight; // Add time info - myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "04:32 59"); - //myCurrentTimeWidget->setFlags(WIDGET_CLEARBG); + myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "04:32 59", TextAlign::Left, kBGColor); + myCurrentTimeWidget->setTextColor(kColorInfo); myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("XX:XX XX"), ypos + 3, - "12:25 59"); + "12:25 59", TextAlign::Right, kBGColor); + myLastTimeWidget->setTextColor(kColorInfo); xpos = myCurrentTimeWidget->getRight() + BUTTON_GAP * 4; // Add buttons myRewindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_ALL, BUTTON_W, BUTTON_H, kRewindAll); - wid.push_back(myRewindAllWidget); xpos += buttonWidth + BUTTON_GAP; myRewind10Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_10, BUTTON_W, BUTTON_H, kRewind10); - wid.push_back(myRewind10Widget); xpos += buttonWidth + BUTTON_GAP; myRewind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_1, BUTTON_W, BUTTON_H, kRewind1); - wid.push_back(myRewind1Widget); xpos += buttonWidth + BUTTON_GAP*2; - /*myPauseWidget = new ButtonWidget(this, font, xpos, ypos - 2, buttonWidth + 4, buttonHeight + 4, PAUSE, - BUTTON_W, BUTTON_H, kPause); - wid.push_back(myPauseWidget); - myPauseWidget->clearFlags(WIDGET_ENABLED);*/ myPlayWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, PLAY, BUTTON_W, BUTTON_H, kPlay); - wid.push_back(myPlayWidget); xpos += buttonWidth + BUTTON_GAP*2; myUnwind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_1, BUTTON_W, BUTTON_H, kUnwind1); - wid.push_back(myUnwind1Widget); xpos += buttonWidth + BUTTON_GAP; myUnwind10Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_10, BUTTON_W, BUTTON_H, kUnwind10); - wid.push_back(myUnwind10Widget); xpos += buttonWidth + BUTTON_GAP; myUnwindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_ALL, BUTTON_W, BUTTON_H, kUnwindAll); - wid.push_back(myUnwindAllWidget); xpos = myUnwindAllWidget->getRight() + BUTTON_GAP * 3; // Add message - myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " "); + myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " ", + TextAlign::Left, kBGColor); + myMessageWidget->setTextColor(kColorInfo); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -268,21 +250,75 @@ void TimeMachineDialog::center() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TimeMachineDialog::loadConfig() { - surface().attributes().blending = true; - surface().attributes().blendalpha = 80; - surface().applyAttributes(); + RewindManager& r = instance().state().rewindManager(); + IntArray cycles = r.cyclesList(); + + // Set range and intervals for timeline + myTimeline->setMaxValue(cycles.size() - 1); + myTimeline->setStepValues(cycles); + + // Enable blending (only once is necessary) + if(!surface().attributes().blending) + { + surface().attributes().blending = true; + surface().attributes().blendalpha = 80; + surface().applyAttributes(); + } handleWinds(); myMessageWidget->setLabel(""); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TimeMachineDialog::handleKeyDown(StellaKey key, StellaMod mod) +{ + // The following 'Alt' shortcuts duplicate the shortcuts in EventHandler + // It is best to keep them the same, so changes in EventHandler mean we + // need to update the logic here too + if(StellaModTest::isAlt(mod)) + { + switch(key) + { + case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states + handleCommand(nullptr, StellaModTest::isShift(mod) ? kRewind10 : kRewind1, 0, 0); + break; + + case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states + handleCommand(nullptr, StellaModTest::isShift(mod) ? kUnwind10 : kUnwind1, 0, 0); + break; + + case KBDK_DOWN: // Alt-down rewinds to start of list + handleCommand(nullptr, kRewindAll, 0, 0); + break; + + case KBDK_UP: // Alt-up rewinds to end of list + handleCommand(nullptr, kUnwindAll, 0, 0); + break; + + default: + Dialog::handleKeyDown(key, mod); + } + } + else if(key == KBDK_SPACE || key == KBDK_ESCAPE) + handleCommand(nullptr, kPlay, 0, 0); + else + Dialog::handleKeyDown(key, mod); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) { -//cerr << cmd << endl; switch(cmd) { + case kTimeline: + { + Int32 winds = myTimeline->getValue() - + instance().state().rewindManager().getCurrentIdx() + 1; + handleWinds(winds); + break; + } + case kPlay: instance().eventHandler().leaveMenuMode(); break; @@ -316,12 +352,13 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd, } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string TimeMachineDialog::getTimeString(uInt64 cycles) { const Int32 scanlines = std::max(instance().console().tia().scanlinesLastFrame(), 240u); const bool isNTSC = scanlines <= 287; const Int32 NTSC_FREQ = 1193182; // ~76*262*60 - const Int32 PAL_FREQ = 1182298; // ~76*312*50 + const Int32 PAL_FREQ = 1182298; // ~76*312*50 const Int32 freq = isNTSC ? NTSC_FREQ : PAL_FREQ; // = cycles/second uInt32 minutes = cycles / (freq * 60); @@ -331,9 +368,9 @@ string TimeMachineDialog::getTimeString(uInt64 cycles) uInt32 frames = cycles / (scanlines * 76); stringstream time; - time << Common::Base::toString(minutes, Common::Base::F_10_2) << ":"; - time << Common::Base::toString(seconds, Common::Base::F_10_2) << "."; - time << Common::Base::toString(frames, Common::Base::F_10_2); + time << Common::Base::toString(minutes, Common::Base::F_10_02) << ":"; + time << Common::Base::toString(seconds, Common::Base::F_10_02) << "."; + time << Common::Base::toString(frames, Common::Base::F_10_02); return time.str(); } @@ -346,18 +383,26 @@ void TimeMachineDialog::handleWinds(Int32 numWinds) if(numWinds) { uInt64 startCycles = instance().console().tia().cycles(); - uInt32 winds = numWinds < 0 ? r.rewindState(-numWinds) : r.unwindState(numWinds); - string message = r.getUnitString(instance().console().tia().cycles() - startCycles); + if(numWinds < 0) r.rewindStates(-numWinds); + else if(numWinds > 0) r.unwindStates(numWinds); - myMessageWidget->setLabel((numWinds < 0 ? "(-" : "(+") + message + ")"); + uInt64 elapsed = instance().console().tia().cycles() - startCycles; + if(elapsed > 0) + { + string message = r.getUnitString(elapsed); + + // TODO: add message text from addState() + myMessageWidget->setLabel((numWinds < 0 ? "(-" : "(+") + message + ")"); + } } // Update time myCurrentTimeWidget->setLabel(getTimeString(r.getCurrentCycles() - r.getFirstCycles())); myLastTimeWidget->setLabel(getTimeString(r.getLastCycles() - r.getFirstCycles())); + myTimeline->setValue(r.getCurrentIdx()-1); // Update index myCurrentIdxWidget->setValue(r.getCurrentIdx()); myLastIdxWidget->setValue(r.getLastIdx()); - // enable/disable buttons + // Enable/disable buttons myRewindAllWidget->setEnabled(!r.atFirst()); myRewind10Widget->setEnabled(!r.atFirst()); myRewind1Widget->setEnabled(!r.atFirst()); diff --git a/src/gui/TimeMachineDialog.hxx b/src/gui/TimeMachineDialog.hxx index 06a1e36e9..e842386d5 100644 --- a/src/gui/TimeMachineDialog.hxx +++ b/src/gui/TimeMachineDialog.hxx @@ -21,6 +21,7 @@ class CommandSender; class DialogContainer; class OSystem; +class TimeLineWidget; #include "Dialog.hxx" @@ -32,6 +33,7 @@ class TimeMachineDialog : public Dialog private: void loadConfig() override; + void handleKeyDown(StellaKey key, StellaMod mod) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; /** This dialog uses its own positioning, so we override Dialog::center() */ @@ -45,7 +47,7 @@ class TimeMachineDialog : public Dialog private: enum { - kPause = 'TMps', + kTimeline = 'TMtl', kPlay = 'TMpl', kRewindAll = 'TMra', kRewind10 = 'TMr1', @@ -55,7 +57,8 @@ class TimeMachineDialog : public Dialog kUnwind1 = 'TMun', }; - ButtonWidget* myPauseWidget; + TimeLineWidget* myTimeline; + ButtonWidget* myPlayWidget; ButtonWidget* myRewindAllWidget; ButtonWidget* myRewind10Widget; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 8628d25d5..4b11a9f8a 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -35,7 +35,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) - : Dialog(osystem, parent) + : Dialog(osystem, parent, font, "User interface settings") { const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = font.getLineHeight(), @@ -43,7 +43,8 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, fontHeight = font.getFontHeight(), buttonWidth = font.getStringWidth("Defaults") + 20, buttonHeight = font.getLineHeight() + 4; - const int vBorder = 5; + const int VBORDER = 8; + const int HBORDER = 10; int xpos, ypos, tabID; int lwidth, pwidth = font.getStringWidth("Standard"); WidgetArray wid; @@ -52,54 +53,95 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Size& ds = instance().frameBuffer().desktopSize(); // Set real dimensions - _w = 37 * fontWidth + 10; - _h = 11 * (lineHeight + 4) + 10; + _w = 39 * fontWidth + 10 * 2; + _h = 10 * (lineHeight + 4) + VBORDER + _th; // The tab widget - xpos = ypos = vBorder; - myTab = new TabWidget(this, font, xpos, ypos, _w - 2*xpos, _h - buttonHeight - 20); + xpos = HBORDER; ypos = VBORDER; + myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2*2, _h - _th - buttonHeight - 20); addTabWidget(myTab); ////////////////////////////////////////////////////////// - // 1) Launcher options + // 1) Misc. options + wid.clear(); + tabID = myTab->addTab(" Look & Feel "); + lwidth = font.getStringWidth("Mouse wheel scroll "); + pwidth = font.getStringWidth("Standard"); + xpos = HBORDER; ypos = VBORDER; + + // UI Palette + ypos += 1; + items.clear(); + VarList::push_back(items, "Standard", "standard"); + VarList::push_back(items, "Classic", "classic"); + VarList::push_back(items, "Light", "light"); + myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, + items, "Theme (*) ", lwidth); + wid.push_back(myPalettePopup); + ypos += lineHeight + 4 * 4; + + // Delay between quick-selecting characters in ListWidget + int swidth = myPalettePopup->getWidth() - lwidth; + myListDelayPopup = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, + "List input delay ", 0, kListDelay, + font.getStringWidth("1 second")); + myListDelayPopup->setMinValue(0); + myListDelayPopup->setMaxValue(1000); + myListDelayPopup->setStepValue(50); + wid.push_back(myListDelayPopup); + ypos += lineHeight + 4; + + // Number of lines a mouse wheel will scroll + myWheelLinesPopup = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, + "Mouse wheel scroll ", 0, kMouseWheel, + font.getStringWidth("10 lines")); + myWheelLinesPopup->setMinValue(1); + myWheelLinesPopup->setMaxValue(10); + wid.push_back(myWheelLinesPopup); + + // Add message concerning usage + xpos = HBORDER; + ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10; + lwidth = ifont.getStringWidth("(*) Requires application restart"); + new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w-20), fontHeight, + "(*) Requires application restart", + TextAlign::Left); + + // Add items for tab 0 + addToFocusList(wid, myTab, tabID); + + ////////////////////////////////////////////////////////// + // 2) Launcher options + wid.clear(); tabID = myTab->addTab(" Launcher "); - lwidth = font.getStringWidth("Exit to Launcher "); + lwidth = font.getStringWidth("Launcher Height "); + xpos = HBORDER; ypos = VBORDER; // Launcher width and height - myLauncherWidthSlider = new SliderWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, "Launcher Width ", - lwidth, kLWidthChanged); + myLauncherWidthSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher Width ", + lwidth, 0, 6 * fontWidth, "px"); myLauncherWidthSlider->setMinValue(FrameBuffer::kFBMinW); myLauncherWidthSlider->setMaxValue(ds.w); myLauncherWidthSlider->setStepValue(10); wid.push_back(myLauncherWidthSlider); - myLauncherWidthLabel = - new StaticTextWidget(myTab, font, - xpos + myLauncherWidthSlider->getWidth() + 4, - ypos + 1, 4*fontWidth, fontHeight, "", TextAlign::Left); ypos += lineHeight + 4; - myLauncherHeightSlider = new SliderWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, "Launcher Height ", - lwidth, kLHeightChanged); + myLauncherHeightSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher Height ", + lwidth, 0, 6 * fontWidth, "px"); myLauncherHeightSlider->setMinValue(FrameBuffer::kFBMinH); myLauncherHeightSlider->setMaxValue(ds.h); myLauncherHeightSlider->setStepValue(10); wid.push_back(myLauncherHeightSlider); - myLauncherHeightLabel = - new StaticTextWidget(myTab, font, - xpos + myLauncherHeightSlider->getWidth() + 4, - ypos + 1, 4*fontWidth, fontHeight, "", TextAlign::Left); ypos += lineHeight + 4; // Launcher font pwidth = font.getStringWidth("2x (1000x760)"); items.clear(); - VarList::push_back(items, "Small", "small"); + VarList::push_back(items, "Small", "small"); VarList::push_back(items, "Medium", "medium"); - VarList::push_back(items, "Large", "large"); + VarList::push_back(items, "Large", "large"); myLauncherFontPopup = - new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items, + new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items, "Launcher Font ", lwidth); wid.push_back(myLauncherFontPopup); ypos += lineHeight + 4; @@ -110,92 +152,24 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, VarList::push_back(items, "1x (640x480) ", "1"); VarList::push_back(items, "2x (1000x760)", "2"); myRomViewerPopup = - new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items, + new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items, "ROM Info viewer ", lwidth); wid.push_back(myRomViewerPopup); - ypos += lineHeight + 4; + ypos += lineHeight + 4*4; // Exit to Launcher - pwidth = font.getStringWidth("If in use"); - items.clear(); - VarList::push_back(items, "If in use", "0"); - VarList::push_back(items, "Always", "1"); - myLauncherExitPopup = - new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items, - "Exit to Launcher ", lwidth); - wid.push_back(myLauncherExitPopup); - ypos += lineHeight + 4; + myLauncherExitWidget = new CheckboxWidget(myTab, font, xpos + 1, ypos, "Always exit to Launcher"); + wid.push_back(myLauncherExitWidget); // Add message concerning usage - xpos = vBorder; ypos += 1*(lineHeight + 4); + xpos = HBORDER; + ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10; lwidth = ifont.getStringWidth("(*) Changes require application restart"); - new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w-20), fontHeight, + new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight, "(*) Changes require application restart", TextAlign::Left); - // Add items for tab 0 - addToFocusList(wid, myTab, tabID); - - ////////////////////////////////////////////////////////// - // 3) Misc. options - wid.clear(); - tabID = myTab->addTab(" Misc. "); - lwidth = font.getStringWidth("Interface Palette (*) "); - pwidth = font.getStringWidth("Standard"); - xpos = ypos = vBorder; - - // UI Palette - ypos += 1; - items.clear(); - VarList::push_back(items, "Standard", "standard"); - VarList::push_back(items, "Classic", "classic"); - VarList::push_back(items, "Light", "light"); - myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "Interface Palette (*) ", lwidth); - wid.push_back(myPalettePopup); - ypos += lineHeight + 4; - - // Delay between quick-selecting characters in ListWidget - items.clear(); - VarList::push_back(items, "Disabled", "0"); - VarList::push_back(items, "300 ms", "300"); - VarList::push_back(items, "400 ms", "400"); - VarList::push_back(items, "500 ms", "500"); - VarList::push_back(items, "600 ms", "600"); - VarList::push_back(items, "700 ms", "700"); - VarList::push_back(items, "800 ms", "800"); - VarList::push_back(items, "900 ms", "900"); - VarList::push_back(items, "1 second", "1000"); - myListDelayPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "List quick delay ", lwidth); - wid.push_back(myListDelayPopup); - ypos += lineHeight + 4; - - // Number of lines a mouse wheel will scroll - items.clear(); - VarList::push_back(items, "1 line", "1"); - VarList::push_back(items, "2 lines", "2"); - VarList::push_back(items, "3 lines", "3"); - VarList::push_back(items, "4 lines", "4"); - VarList::push_back(items, "5 lines", "5"); - VarList::push_back(items, "6 lines", "6"); - VarList::push_back(items, "7 lines", "7"); - VarList::push_back(items, "8 lines", "8"); - VarList::push_back(items, "9 lines", "9"); - VarList::push_back(items, "10 lines", "10"); - myWheelLinesPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "Mouse wheel scroll ", lwidth); - wid.push_back(myWheelLinesPopup); - ypos += lineHeight + 4; - - // Add message concerning usage - xpos = vBorder; ypos += 1*(lineHeight + 4); - lwidth = ifont.getStringWidth("(*) Requires application restart"); - new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w-20), fontHeight, - "(*) Requires application restart", - TextAlign::Left); - - // Add items for tab 2 + // Add items for tab 1 addToFocusList(wid, myTab, tabID); // Activate the first tab @@ -203,10 +177,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, // Add Defaults, OK and Cancel buttons wid.clear(); - 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); } @@ -223,9 +194,7 @@ void UIDialog::loadConfig() h = std::min(h, instance().frameBuffer().desktopSize().h); myLauncherWidthSlider->setValue(w); - myLauncherWidthLabel->setValue(w); myLauncherHeightSlider->setValue(h); - myLauncherHeightLabel->setValue(h); // Launcher font const string& font = instance().settings().getString("launcherfont"); @@ -237,19 +206,19 @@ void UIDialog::loadConfig() // Exit to launcher bool exitlauncher = instance().settings().getBool("exitlauncher"); - myLauncherExitPopup->setSelected(exitlauncher ? "1" : "0", "0"); + myLauncherExitWidget->setState(exitlauncher); // UI palette const string& pal = instance().settings().getString("uipalette"); myPalettePopup->setSelected(pal, "standard"); // Listwidget quick delay - const string& delay = instance().settings().getString("listdelay"); - myListDelayPopup->setSelected(delay, "300"); + int delay = instance().settings().getInt("listdelay"); + myListDelayPopup->setValue(delay); // Mouse wheel lines - const string& mw = instance().settings().getString("mwheel"); - myWheelLinesPopup->setSelected(mw, "1"); + int mw = instance().settings().getInt("mwheel"); + myWheelLinesPopup->setValue(mw); myTab->loadConfig(); } @@ -271,22 +240,19 @@ void UIDialog::saveConfig() myRomViewerPopup->getSelectedTag().toString()); // Exit to Launcher - instance().settings().setValue("exitlauncher", - myLauncherExitPopup->getSelectedTag().toString()); + instance().settings().setValue("exitlauncher", myLauncherExitWidget->getState()); // UI palette instance().settings().setValue("uipalette", myPalettePopup->getSelectedTag().toString()); // Listwidget quick delay - instance().settings().setValue("listdelay", - myListDelayPopup->getSelectedTag().toString()); - ListWidget::setQuickSelectDelay(myListDelayPopup->getSelectedTag().toInt()); + instance().settings().setValue("listdelay", myListDelayPopup->getValue()); + ListWidget::setQuickSelectDelay(myListDelayPopup->getValue()); // Mouse wheel lines - instance().settings().setValue("mwheel", - myWheelLinesPopup->getSelectedTag().toString()); - ScrollBarWidget::setWheelLines(myWheelLinesPopup->getSelectedTag().toInt()); + instance().settings().setValue("mwheel", myWheelLinesPopup->getValue()); + ScrollBarWidget::setWheelLines(myWheelLinesPopup->getValue()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -299,19 +265,17 @@ void UIDialog::setDefaults() uInt32 w = std::min(instance().frameBuffer().desktopSize().w, 900u); uInt32 h = std::min(instance().frameBuffer().desktopSize().h, 600u); myLauncherWidthSlider->setValue(w); - myLauncherWidthLabel->setValue(w); myLauncherHeightSlider->setValue(h); - myLauncherHeightLabel->setValue(h); myLauncherFontPopup->setSelected("medium", ""); myRomViewerPopup->setSelected("1", ""); - myLauncherExitPopup->setSelected("0", ""); + myLauncherExitWidget->setState(false); break; } case 1: // Misc. options myPalettePopup->setSelected("standard"); - myListDelayPopup->setSelected("300"); - myWheelLinesPopup->setSelected("4"); + myListDelayPopup->setValue(300); + myWheelLinesPopup->setValue(4); break; default: @@ -326,14 +290,6 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) { switch(cmd) { - case kLWidthChanged: - myLauncherWidthLabel->setValue(myLauncherWidthSlider->getValue()); - break; - - case kLHeightChanged: - myLauncherHeightLabel->setValue(myLauncherHeightSlider->getValue()); - break; - case GuiObject::kOKCmd: saveConfig(); close(); @@ -343,6 +299,29 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) setDefaults(); break; + case kListDelay: + if(myListDelayPopup->getValue() == 0) + { + myListDelayPopup->setValueLabel("Off"); + myListDelayPopup->setValueUnit(""); + } + else if(myListDelayPopup->getValue() == 1000) + { + myListDelayPopup->setValueLabel("1"); + myListDelayPopup->setValueUnit(" second"); + } + else + { + myListDelayPopup->setValueUnit(" ms"); + } + break; + case kMouseWheel: + if(myWheelLinesPopup->getValue() == 1) + myWheelLinesPopup->setValueUnit(" line"); + else + myWheelLinesPopup->setValueUnit(" lines"); + break; + default: Dialog::handleCommand(sender, cmd, data, 0); break; diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 3efada9a6..e0811b23e 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -44,26 +44,25 @@ class UIDialog : public Dialog void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: + enum + { + kListDelay = 'UILd', + kMouseWheel = 'UIMw', + }; + TabWidget* myTab; // Launcher options SliderWidget* myLauncherWidthSlider; - StaticTextWidget* myLauncherWidthLabel; SliderWidget* myLauncherHeightSlider; - StaticTextWidget* myLauncherHeightLabel; - PopUpWidget* myLauncherExitPopup; + CheckboxWidget* myLauncherExitWidget; PopUpWidget* myLauncherFontPopup; PopUpWidget* myRomViewerPopup; // Misc options PopUpWidget* myPalettePopup; - PopUpWidget* myListDelayPopup; - PopUpWidget* myWheelLinesPopup; - - enum { - kLWidthChanged = 'UIlw', - kLHeightChanged = 'UIlh', - }; + SliderWidget* myListDelayPopup; + SliderWidget* myWheelLinesPopup; private: // Following constructors and assignment operators not supported diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 6569260d7..007e663ec 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -35,31 +35,32 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent) + : Dialog(osystem, parent, font, "Video settings") { const int VGAP = 4; const int VBORDER = 8; - const int HBORDER = 8; + const int HBORDER = 10; + const int INDENT = 20; const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), buttonWidth = font.getStringWidth("Defaults") + 20, buttonHeight = font.getLineHeight() + 4; int xpos, ypos, tabID; - int lwidth = font.getStringWidth("NTSC Aspect "), + int lwidth = font.getStringWidth("TIA Palette "), pwidth = font.getStringWidth("XXXXxXXXX"), - swidth = 69; + swidth = font.getMaxCharWidth() * 10 - 2; WidgetArray wid; VariantList items; // Set real dimensions - _w = std::min(52 * fontWidth + 10, max_w); - _h = std::min(16 * (lineHeight + VGAP) + 14, max_h); + _w = std::min(57 * fontWidth + HBORDER * 2, max_w); + _h = std::min((16-2) * (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 - 20); + myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2*xpos, _h - _th - buttonHeight - 20); addTabWidget(myTab); xpos = HBORDER; ypos = VBORDER; @@ -74,117 +75,114 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myRenderer); ypos += lineHeight + VGAP; - // TIA filters (will be dynamically filled later) - myTIAZoom = new PopUpWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, items, "TIA Zoom ", lwidth); - wid.push_back(myTIAZoom); - ypos += lineHeight + VGAP; - // TIA Palette items.clear(); VarList::push_back(items, "Standard", "standard"); VarList::push_back(items, "Z26", "z26"); VarList::push_back(items, "User", "user"); myTIAPalette = new PopUpWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, items, "TIA Palette ", lwidth); + lineHeight, items, "TIA palette ", lwidth); wid.push_back(myTIAPalette); ypos += lineHeight + VGAP; - // TIA interpolation - items.clear(); - VarList::push_back(items, "Linear", "linear"); - VarList::push_back(items, "Nearest", "nearest"); - myTIAInterpolate = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "TIA Inter ", lwidth); - wid.push_back(myTIAInterpolate); + // TIA filters (will be dynamically filled later) + myTIAZoom = new PopUpWidget(myTab, font, xpos, ypos, pwidth, + lineHeight, items, "TIA zoom ", lwidth); + wid.push_back(myTIAZoom); ypos += lineHeight + VGAP; - // Timing to use between frames - items.clear(); - VarList::push_back(items, "Sleep", "sleep"); - VarList::push_back(items, "Busy-wait", "busy"); - myFrameTiming = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "Timing (*) ", lwidth); - wid.push_back(myFrameTiming); + SliderWidget* s = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, + "TIA zoom", lwidth, 0, fontWidth * 4, "%"); + s->setMinValue(200); s->setMaxValue(500); + wid.push_back(s); + ypos += lineHeight + VGAP; + + + // TIA interpolation + myTIAInterpolate = new CheckboxWidget(myTab, font, xpos, ypos + 1, "TIA interpolation "); + wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP; // Aspect ratio (NTSC mode) myNAspectRatio = - new SliderWidget(myTab, font, xpos, ypos-1, pwidth, lineHeight, - "NTSC Aspect ", lwidth, kNAspectRatioChanged); + new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, + "NTSC aspect ", lwidth, 0, + fontWidth * 4, "%"); myNAspectRatio->setMinValue(80); myNAspectRatio->setMaxValue(120); wid.push_back(myNAspectRatio); - myNAspectRatioLabel = - new StaticTextWidget(myTab, font, xpos + myNAspectRatio->getWidth() + 4, - ypos + 1, fontWidth * 3, fontHeight, "", TextAlign::Left); ypos += lineHeight + VGAP; // Aspect ratio (PAL mode) myPAspectRatio = - new SliderWidget(myTab, font, xpos, ypos-1, pwidth, lineHeight, - "PAL Aspect ", lwidth, kPAspectRatioChanged); + new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, + "PAL aspect ", lwidth, 0, + fontWidth * 4, "%"); myPAspectRatio->setMinValue(80); myPAspectRatio->setMaxValue(120); wid.push_back(myPAspectRatio); - myPAspectRatioLabel = - new StaticTextWidget(myTab, font, xpos + myPAspectRatio->getWidth() + 4, - ypos + 1, fontWidth * 3, fontHeight, "", TextAlign::Left); ypos += lineHeight + VGAP; // Framerate myFrameRate = - new SliderWidget(myTab, font, xpos, ypos-1, pwidth, lineHeight, - "Framerate ", lwidth, kFrameRateChanged); + new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, + "Frame rate ", lwidth, kFrameRateChanged, fontWidth * 6, "fps"); myFrameRate->setMinValue(0); myFrameRate->setMaxValue(900); myFrameRate->setStepValue(10); wid.push_back(myFrameRate); - myFrameRateLabel = - new StaticTextWidget(myTab, font, xpos + myFrameRate->getWidth() + 4, - ypos + 1, fontWidth * 4, fontHeight, "", TextAlign::Left); + ypos += lineHeight + VGAP; + + // Use sync to vblank + myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync"); + wid.push_back(myUseVSync); // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10; new StaticTextWidget(myTab, infofont, 10, ypos, - font.getStringWidth("(*) Requires application restart"), fontHeight, - "(*) Requires application restart", TextAlign::Left); + "(*) Requires application restart"); // Move over to the next column - xpos += myNAspectRatio->getWidth() + myNAspectRatioLabel->getWidth() + 30; + xpos += myFrameRate->getWidth() + 28; ypos = VBORDER; // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos, "Fullscreen"); + myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen"); wid.push_back(myFullscreen); ypos += lineHeight + VGAP; - // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos, ypos, "Fullscreen Fill"); - wid.push_back(myUseStretch); - ypos += lineHeight + VGAP; + /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); + myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedScreenModes(), "Mode "); + wid.push_back(myFullScreenMode); + ypos += lineHeight + VGAP;*/ - // Use sync to vblank - myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos, "VSync"); - wid.push_back(myUseVSync); + // FS stretch + myUseStretch = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen fill"); + wid.push_back(myUseStretch); ypos += (lineHeight + VGAP) * 2; // Skip progress load bars for SuperCharger ROMs // Doesn't really belong here, but I couldn't find a better place for it - myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos, "Fast SC/AR BIOS"); + myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fast SuperCharger load"); wid.push_back(myFastSCBios); ypos += lineHeight + VGAP; // Show UI messages onscreen - myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos, "Show UI messages"); + myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Show UI messages"); wid.push_back(myUIMessages); ypos += lineHeight + VGAP; // Center window (in windowed mode) - myCenter = new CheckboxWidget(myTab, font, xpos, ypos, "Center window"); + myCenter = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Center window"); wid.push_back(myCenter); + ypos += (lineHeight + VGAP) * 2; + + // Timing to use between frames + myFrameTiming = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Idle between frames (*)"); + wid.push_back(myFrameTiming); ypos += lineHeight + VGAP; // Use multi-threading - myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos, "Use multi-threading"); + myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Multi-threading"); wid.push_back(myUseThreads); // Add items for tab 0 @@ -196,6 +194,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, tabID = myTab->addTab(" TV Effects "); xpos = HBORDER; ypos = VBORDER; + swidth = font.getMaxCharWidth() * 8 - 4; // TV Mode items.clear(); @@ -209,27 +208,23 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, pwidth = font.getStringWidth("Bad adjust"); myTVMode = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "TV Mode ", lwidth, kTVModeChanged); + items, "TV mode ", lwidth, kTVModeChanged); wid.push_back(myTVMode); ypos += lineHeight + VGAP; // Custom adjustables (using macro voodoo) - xpos += 8+1; ypos += 0; + xpos += INDENT - 2; ypos += 0; pwidth = lwidth; lwidth = font.getStringWidth("Saturation "); #define CREATE_CUSTOM_SLIDERS(obj, desc) \ myTV ## obj = \ - new SliderWidget(myTab, font, xpos, ypos-1, pwidth, lineHeight, \ - desc, lwidth, kTV ## obj ##Changed); \ + new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \ + desc, lwidth, 0, fontWidth*4, "%"); \ myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ wid.push_back(myTV ## obj); \ - myTV ## obj ## Label = \ - new StaticTextWidget(myTab, font, xpos+myTV ## obj->getWidth()+4, \ - ypos+1, fontWidth*3, fontHeight, "", TextAlign::Left);\ ypos += lineHeight + VGAP; - pwidth = swidth; CREATE_CUSTOM_SLIDERS(Contrast, "Contrast "); CREATE_CUSTOM_SLIDERS(Bright, "Brightness "); CREATE_CUSTOM_SLIDERS(Hue, "Hue "); @@ -241,44 +236,37 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, CREATE_CUSTOM_SLIDERS(Fringe, "Fringing "); CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding "); - xpos += myTVContrast->getWidth() + myTVContrastLabel->getWidth() + 36; + xpos += myTVContrast->getWidth() + 40; ypos = VBORDER; lwidth = font.getStringWidth("Intensity "); pwidth = font.getMaxCharWidth() * 6; // TV Phosphor effect - items.clear(); - VarList::push_back(items, "Always", "always"); - VarList::push_back(items, "Per-ROM", "byrom"); - myTVPhosphor = new PopUpWidget(myTab, font, xpos, ypos, - font.getStringWidth("Per-ROM"), lineHeight, items, - "TV Phosphor ", font.getStringWidth("TV Phosphor ")); + myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs"); + wid.push_back(myTVPhosphor); ypos += lineHeight + VGAP; // TV Phosphor default level - xpos += 8-8+16; - pwidth = swidth; + xpos += INDENT; + swidth = font.getMaxCharWidth() * 10; CREATE_CUSTOM_SLIDERS(PhosLevel, "Default "); ypos += 6; // Scanline intensity and interpolation - xpos -= 8+8; - myTVScanLabel = - new StaticTextWidget(myTab, font, xpos, ypos, font.getStringWidth("Scanline settings"), - fontHeight, "Scanline settings", TextAlign::Left); + xpos -= INDENT; + myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanline settings"); ypos += lineHeight; - xpos += 8+8; + xpos += INDENT; CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity "); - myTVScanInterpolate = new CheckboxWidget(myTab, font, xpos, ypos, - "Interpolation"); + myTVScanInterpolate = new CheckboxWidget(myTab, font, xpos, ypos, "Interpolation"); wid.push_back(myTVScanInterpolate); ypos += lineHeight + 6; // Adjustable presets - xpos -= 8+8; + xpos -= INDENT; int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20; #define CREATE_CLONE_BUTTON(obj, desc) \ myClone ## obj = \ @@ -302,11 +290,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // 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); // Disable certain functions when we know they aren't present @@ -334,28 +318,26 @@ void VideoDialog::loadConfig() instance().settings().getString("palette"), "standard"); // TIA interpolation - const string& tia_inter = instance().settings().getBool("tia.inter") ? - "linear" : "nearest"; - myTIAInterpolate->setSelected(tia_inter, "nearest"); + myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); // Wait between frames - myFrameTiming->setSelected( - instance().settings().getString("timing"), "sleep"); + myFrameTiming->setState(instance().settings().getString("timing") == "sleep"); // Aspect ratio setting (NTSC and PAL) myNAspectRatio->setValue(instance().settings().getInt("tia.aspectn")); - myNAspectRatioLabel->setLabel(instance().settings().getString("tia.aspectn")); myPAspectRatio->setValue(instance().settings().getInt("tia.aspectp")); - myPAspectRatioLabel->setLabel(instance().settings().getString("tia.aspectp")); // Framerate (0 or -1 means automatic framerate calculation) int rate = instance().settings().getInt("framerate"); myFrameRate->setValue(rate < 0 ? 0 : rate); - myFrameRateLabel->setLabel(rate <= 0 ? "Auto" : - instance().settings().getString("framerate")); + myFrameRate->setValueLabel(rate <= 0 ? "Auto" : + instance().settings().getString("framerate")); + myFrameRate->setValueUnit(rate <= 0 ? "" : "fps"); // Fullscreen myFullscreen->setState(instance().settings().getBool("fullscreen")); + /*string mode = instance().settings().getString("fullscreenmode"); + myFullScreenMode->setSelected(mode);*/ // Fullscreen stretch setting myUseStretch->setState(instance().settings().getBool("tia.fsfill")); @@ -385,16 +367,13 @@ void VideoDialog::loadConfig() loadTVAdjustables(NTSCFilter::PRESET_CUSTOM); // TV phosphor mode - myTVPhosphor->setSelected( - instance().settings().getString("tv.phosphor"), "byrom"); + myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); // TV phosphor blend myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); - myTVPhosLevelLabel->setLabel(instance().settings().getString("tv.phosblend")); // TV scanline intensity and interpolation myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); - myTVScanIntenseLabel->setLabel(instance().settings().getString("tv.scanlines")); myTVScanInterpolate->setState(instance().settings().getBool("tv.scaninter")); myTab->loadConfig(); @@ -417,16 +396,14 @@ void VideoDialog::saveConfig() myTIAPalette->getSelectedTag().toString()); // Wait between frames - instance().settings().setValue("timing", - myFrameTiming->getSelectedTag().toString()); + instance().settings().setValue("timing", myFrameTiming->getState() ? "sleep" : "busy"); // TIA interpolation - instance().settings().setValue("tia.inter", - myTIAInterpolate->getSelectedTag().toString() == "linear" ? true : false); + instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); // Aspect ratio setting (NTSC and PAL) - instance().settings().setValue("tia.aspectn", myNAspectRatioLabel->getLabel()); - instance().settings().setValue("tia.aspectp", myPAspectRatioLabel->getLabel()); + instance().settings().setValue("tia.aspectn", myNAspectRatio->getValueLabel()); + instance().settings().setValue("tia.aspectp", myPAspectRatio->getValueLabel()); // Framerate int f = myFrameRate->getValue(); @@ -440,7 +417,8 @@ void VideoDialog::saveConfig() // Fullscreen instance().settings().setValue("fullscreen", myFullscreen->getState()); - + /*instance().settings().setValue("fullscreenmode", + myFullScreenMode->getSelectedTag().toString());*/ // Fullscreen stretch setting instance().settings().setValue("tia.fsfill", myUseStretch->getState()); @@ -481,14 +459,14 @@ void VideoDialog::saveConfig() // TV phosphor mode instance().settings().setValue("tv.phosphor", - myTVPhosphor->getSelectedTag().toString()); + myTVPhosphor->getState() ? "always" : "byrom"); // TV phosphor blend - instance().settings().setValue("tv.phosblend", myTVPhosLevelLabel->getLabel()); - Properties::setDefault(Display_PPBlend, myTVPhosLevelLabel->getLabel()); + instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel()); + Properties::setDefault(Display_PPBlend, myTVPhosLevel->getValueLabel()); // TV scanline intensity and interpolation - instance().settings().setValue("tv.scanlines", myTVScanIntenseLabel->getLabel()); + instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); instance().settings().setValue("tv.scaninter", myTVScanInterpolate->getState()); // Finally, issue a complete framebuffer re-initialization @@ -505,16 +483,14 @@ void VideoDialog::setDefaults() myRenderer->setSelectedIndex(0); myTIAZoom->setSelected("3", ""); myTIAPalette->setSelected("standard", ""); - myFrameTiming->setSelected("sleep", ""); - myTIAInterpolate->setSelected("nearest", ""); - myNAspectRatio->setValue(90); - myNAspectRatioLabel->setLabel("91"); - myPAspectRatio->setValue(100); - myPAspectRatioLabel->setLabel("109"); + myFrameTiming->setState(true); + myTIAInterpolate->setState(false); + myNAspectRatio->setValue(91); + myPAspectRatio->setValue(109); myFrameRate->setValue(0); - myFrameRateLabel->setLabel("Auto"); myFullscreen->setState(false); + //myFullScreenMode->setSelectedIndex(0); myUseStretch->setState(true); myUseVSync->setState(true); myUIMessages->setState(true); @@ -529,15 +505,13 @@ void VideoDialog::setDefaults() myTVMode->setSelected("0", "0"); // TV phosphor mode - myTVPhosphor->setSelected("byrom", "byrom"); + myTVPhosphor->setState(false); // TV phosphor blend myTVPhosLevel->setValue(50); - myTVPhosLevelLabel->setLabel("50"); // TV scanline intensity and interpolation myTVScanIntense->setValue(25); - myTVScanIntenseLabel->setLabel("25"); myTVScanInterpolate->setState(true); // Make sure that mutually-exclusive items are not enabled at the same time @@ -557,25 +531,15 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) bool scanenable = preset != NTSCFilter::PRESET_OFF; myTVSharp->setEnabled(enable); - myTVSharpLabel->setEnabled(enable); myTVHue->setEnabled(enable); - myTVHueLabel->setEnabled(enable); myTVRes->setEnabled(enable); - myTVResLabel->setEnabled(enable); myTVArtifacts->setEnabled(enable); - myTVArtifactsLabel->setEnabled(enable); myTVFringe->setEnabled(enable); - myTVFringeLabel->setEnabled(enable); myTVBleed->setEnabled(enable); - myTVBleedLabel->setEnabled(enable); myTVBright->setEnabled(enable); - myTVBrightLabel->setEnabled(enable); myTVContrast->setEnabled(enable); - myTVContrastLabel->setEnabled(enable); myTVSatur->setEnabled(enable); - myTVSaturLabel->setEnabled(enable); myTVGamma->setEnabled(enable); - myTVGammaLabel->setEnabled(enable); myCloneComposite->setEnabled(enable); myCloneSvideo->setEnabled(enable); myCloneRGB->setEnabled(enable); @@ -584,7 +548,6 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) myTVScanLabel->setEnabled(scanenable); myTVScanIntense->setEnabled(scanenable); - myTVScanIntenseLabel->setEnabled(scanenable); myTVScanInterpolate->setEnabled(scanenable); _dirty = true; @@ -597,25 +560,15 @@ void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) instance().frameBuffer().tiaSurface().ntsc().getAdjustables( adj, NTSCFilter::Preset(preset)); myTVSharp->setValue(adj.sharpness); - myTVSharpLabel->setValue(adj.sharpness); myTVHue->setValue(adj.hue); - myTVHueLabel->setValue(adj.hue); myTVRes->setValue(adj.resolution); - myTVResLabel->setValue(adj.resolution); myTVArtifacts->setValue(adj.artifacts); - myTVArtifactsLabel->setValue(adj.artifacts); myTVFringe->setValue(adj.fringing); - myTVFringeLabel->setValue(adj.fringing); myTVBleed->setValue(adj.bleed); - myTVBleedLabel->setValue(adj.bleed); myTVBright->setValue(adj.brightness); - myTVBrightLabel->setValue(adj.brightness); myTVContrast->setValue(adj.contrast); - myTVContrastLabel->setValue(adj.contrast); myTVSatur->setValue(adj.saturation); - myTVSaturLabel->setValue(adj.saturation); myTVGamma->setValue(adj.gamma); - myTVGammaLabel->setValue(adj.gamma); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -633,48 +586,16 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; - case kNAspectRatioChanged: - myNAspectRatioLabel->setValue(myNAspectRatio->getValue()); - break; - - case kPAspectRatioChanged: - myPAspectRatioLabel->setValue(myPAspectRatio->getValue()); - break; - case kFrameRateChanged: if(myFrameRate->getValue() == 0) - myFrameRateLabel->setLabel("Auto"); - else - myFrameRateLabel->setValue(myFrameRate->getValue()); + myFrameRate->setValueLabel("Auto"); + myFrameRate->setValueUnit(myFrameRate->getValue() == 0 ? "" : "fps"); break; case kTVModeChanged: handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); break; - case kTVSharpChanged: myTVSharpLabel->setValue(myTVSharp->getValue()); - break; - case kTVHueChanged: myTVHueLabel->setValue(myTVHue->getValue()); - break; - case kTVResChanged: myTVResLabel->setValue(myTVRes->getValue()); - break; - case kTVArtifactsChanged: myTVArtifactsLabel->setValue(myTVArtifacts->getValue()); - break; - case kTVFringeChanged: myTVFringeLabel->setValue(myTVFringe->getValue()); - break; - case kTVBleedChanged: myTVBleedLabel->setValue(myTVBleed->getValue()); - break; - case kTVBrightChanged: myTVBrightLabel->setValue(myTVBright->getValue()); - break; - case kTVContrastChanged: myTVContrastLabel->setValue(myTVContrast->getValue()); - break; - case kTVSaturChanged: myTVSaturLabel->setValue(myTVSatur->getValue()); - break; - case kTVGammaChanged: myTVGammaLabel->setValue(myTVGamma->getValue()); - break; - case kTVPhosLevelChanged: myTVPhosLevelLabel->setValue(myTVPhosLevel->getValue()); - break; - case kTVScanIntenseChanged: myTVScanIntenseLabel->setValue(myTVScanIntense->getValue()); - break; + case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::PRESET_COMPOSITE); break; case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::PRESET_SVIDEO); diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index 0029cb6e0..bec208387 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -52,18 +52,16 @@ class VideoDialog : public Dialog // General options PopUpWidget* myRenderer; - PopUpWidget* myTIAZoom; + PopUpWidget* myTIAZoom; // TODO: SliderWidget PopUpWidget* myTIAPalette; - PopUpWidget* myFrameTiming; - PopUpWidget* myTIAInterpolate; + CheckboxWidget* myFrameTiming; + CheckboxWidget* myTIAInterpolate; SliderWidget* myNAspectRatio; - StaticTextWidget* myNAspectRatioLabel; SliderWidget* myPAspectRatio; - StaticTextWidget* myPAspectRatioLabel; - SliderWidget* myFrameRate; - StaticTextWidget* myFrameRateLabel; + CheckboxWidget* myFullscreen; + //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch; CheckboxWidget* myUseVSync; CheckboxWidget* myUIMessages; @@ -74,35 +72,23 @@ class VideoDialog : public Dialog // TV effects adjustables (custom mode) PopUpWidget* myTVMode; SliderWidget* myTVSharp; - StaticTextWidget* myTVSharpLabel; SliderWidget* myTVHue; - StaticTextWidget* myTVHueLabel; SliderWidget* myTVRes; - StaticTextWidget* myTVResLabel; SliderWidget* myTVArtifacts; - StaticTextWidget* myTVArtifactsLabel; SliderWidget* myTVFringe; - StaticTextWidget* myTVFringeLabel; SliderWidget* myTVBleed; - StaticTextWidget* myTVBleedLabel; SliderWidget* myTVBright; - StaticTextWidget* myTVBrightLabel; SliderWidget* myTVContrast; - StaticTextWidget* myTVContrastLabel; SliderWidget* myTVSatur; - StaticTextWidget* myTVSaturLabel; SliderWidget* myTVGamma; - StaticTextWidget* myTVGammaLabel; // TV phosphor effect - PopUpWidget* myTVPhosphor; + CheckboxWidget* myTVPhosphor; SliderWidget* myTVPhosLevel; - StaticTextWidget* myTVPhosLevelLabel; // TV scanline intensity and interpolation StaticTextWidget* myTVScanLabel; SliderWidget* myTVScanIntense; - StaticTextWidget* myTVScanIntenseLabel; CheckboxWidget* myTVScanInterpolate; // TV effects adjustables presets (custom mode) @@ -113,24 +99,9 @@ class VideoDialog : public Dialog ButtonWidget* myCloneCustom; enum { - kNAspectRatioChanged = 'VDan', - kPAspectRatioChanged = 'VDap', kFrameRateChanged = 'VDfr', kTVModeChanged = 'VDtv', - kTVSharpChanged = 'TVsh', - kTVHueChanged = 'TVhu', - kTVResChanged = 'TVrs', - kTVArtifactsChanged = 'TVar', - kTVFringeChanged = 'TVfr', - kTVBleedChanged = 'TVbl', - kTVBrightChanged = 'TVbr', - kTVContrastChanged = 'TVct', - kTVSaturChanged = 'TVsa', - kTVGammaChanged = 'TVga', - kTVScanIntenseChanged= 'TVsc', - - kTVPhosLevelChanged = 'TVpl', kCloneCompositeCmd = 'CLcp', kCloneSvideoCmd = 'CLsv', diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index c432c7506..d8501bf32 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -21,7 +21,6 @@ #include "bspf.hxx" #include "Command.hxx" #include "Dialog.hxx" -#include "Font.hxx" #include "FBSurface.hxx" #include "GuiObject.hxx" #include "OSystem.hxx" @@ -84,21 +83,13 @@ void Widget::draw() { x++; y++; w-=2; h-=2; } -#ifndef FLAT_UI s.fillRect(x, y, w, h, (_flags & WIDGET_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); -#else - s.fillRect(x, y, w, h, (_flags & WIDGET_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); -#endif } // Draw border if(hasBorder) { -#ifndef FLAT_UI - s.box(_x, _y, _w, _h, kColor, kShadowColor); -#else - s.frameRect(_x, _y, _w, _h, (_flags & WIDGET_HILITED) && isEnabled() ? kScrollColorHi : kColor); -#endif // !FLAT_UI + s.frameRect(_x, _y, _w, _h, (_flags & WIDGET_HILITED) && isEnabled() ? kWidColorHi : kColor); _x += 4; _y += 4; _w -= 8; @@ -304,7 +295,8 @@ void Widget::setDirtyInChain(Widget* start) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StaticTextWidget::StaticTextWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, - const string& text, TextAlign align) + const string& text, TextAlign align, + uInt32 shadowColor) : Widget(boss, font, x, y, w, h), _align(align) { @@ -313,6 +305,7 @@ StaticTextWidget::StaticTextWidget(GuiObject* boss, const GUI::Font& font, _bgcolorhi = kDlgColor; _textcolor = kTextColor; _textcolorhi = kTextColor; + _shadowcolor = shadowColor; _label = text; _editable = false; @@ -321,8 +314,10 @@ StaticTextWidget::StaticTextWidget(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StaticTextWidget::StaticTextWidget(GuiObject* boss, const GUI::Font& font, int x, int y, - const string& text, TextAlign align) - : StaticTextWidget(boss, font, x, y, font.getStringWidth(text), font.getLineHeight(), text, align) + const string& text, TextAlign align, + uInt32 shadowColor) + : StaticTextWidget(boss, font, x, y, font.getStringWidth(text), font.getLineHeight(), + text, align, shadowColor) { } @@ -349,7 +344,7 @@ void StaticTextWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); s.drawString(_font, _label, _x, _y, _w, - isEnabled() ? _textcolor : uInt32(kColor), _align); + isEnabled() ? _textcolor : uInt32(kColor), _align, 0, true, _shadowcolor); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -361,7 +356,7 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font, _cmd(cmd), _useBitmap(false) { - _flags = WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG; + _flags = WIDGET_ENABLED | WIDGET_CLEARBG; _bgcolor = kBtnColor; _bgcolorhi = kBtnColorHi; _textcolor = kBtnTextColor; @@ -444,56 +439,22 @@ void ButtonWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount) void ButtonWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); + + s.frameRect(_x, _y, _w, _h, hilite && isEnabled() ? kBtnBorderColorHi : kBtnBorderColor); + if (!_useBitmap) s.drawString(_font, _label, _x, _y + (_h - _fontHeight)/2 + 1, _w, - !isEnabled() ? hilite ? uInt32(kColor) : uInt32(kBGColorLo) : + !isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) : hilite ? _textcolorhi : _textcolor, _align); else s.drawBitmap(_bitmap, _x + (_w - _bmw) / 2, _y + (_h - _bmh) / 2, - !isEnabled() ? hilite ? uInt32(kColor) : uInt32(kBGColorLo) : + !isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) : hilite ? _textcolorhi : _textcolor, _bmw, _bmh); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* 8x8 checkbox bitmap */ -#ifndef FLAT_UI -static uInt32 checked_img_active[8] = -{ - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111, - 0b11111111 -}; - -static uInt32 checked_img_inactive[8] = -{ - 0b11111111, - 0b11111111, - 0b11100111, - 0b11000011, - 0b11000011, - 0b11100111, - 0b11111111, - 0b11111111 -}; - -static uInt32 checked_img_circle[8] = -{ - 0b00011000, - 0b01111110, - 0b01111110, - 0b11111111, - 0b11111111, - 0b01111110, - 0b01111110, - 0b00011000 -}; -#else static uInt32 checked_img_active[10] = { 0b1111111111, @@ -535,7 +496,7 @@ static uInt32 checked_img_circle[10] = 0b0111111110, 0b0001111000 }; -#endif // !FLAT_UI + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CheckboxWidget::CheckboxWidget(GuiObject* boss, const GUI::Font& font, int x, int y, const string& label, @@ -648,25 +609,14 @@ void CheckboxWidget::drawWidget(bool hilite) { FBSurface& s = _boss->dialog().surface(); -#ifndef FLAT_UI - // Draw the box if(_drawBox) - s.box(_x, _y + _boxY, 14, 14, kColor, kShadowColor); - // Do we draw a square or cross? - s.fillRect(_x + 2, _y + _boxY + 2, 10, 10, _changed ? kDbgChangedColor - : isEnabled() ? _bgcolor : kColor); - if(_state) - s.drawBitmap(_img, _x + 3, _y + _boxY + 3, isEnabled() ? kCheckColor : kShadowColor); -#else - if(_drawBox) - s.frameRect(_x, _y + _boxY, 14, 14, hilite ? kScrollColorHi : kShadowColor); + s.frameRect(_x, _y + _boxY, 14, 14, hilite && isEnabled() && isEditable() ? kWidColorHi : kColor); // Do we draw a square or cross? s.fillRect(_x + 1, _y + _boxY + 1, 12, 12, _changed ? kDbgChangedColor : isEnabled() ? _bgcolor : kColor); if(_state) - s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled() ? hilite ? kScrollColorHi : kCheckColor - : kShadowColor, 10); -#endif + s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled() ? hilite && isEditable() ? kWidColorHi : kCheckColor + : kColor, 10); // Finally draw the label s.drawString(_font, _label, _x + 20, _y + _textY, _w, @@ -676,14 +626,19 @@ void CheckboxWidget::drawWidget(bool hilite) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, - const string& label, int labelWidth, int cmd) + const string& label, int labelWidth, int cmd, + int valueLabelWidth, const string& valueUnit, int valueLabelGap) : ButtonWidget(boss, font, x, y, w, h, label, cmd), - _value(0), + _value(-1), _stepValue(1), _valueMin(0), _valueMax(100), _isDragging(false), - _labelWidth(labelWidth) + _labelWidth(labelWidth), + _valueLabelGap(valueLabelGap), + _valueLabelWidth(valueLabelWidth), + _valueLabel(""), + _valueUnit(valueUnit) { _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE; _bgcolor = kDlgColor; @@ -692,7 +647,20 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font, if(!_label.empty() && _labelWidth == 0) _labelWidth = _font.getStringWidth(_label); - _w = w + _labelWidth; + if(_valueLabelWidth == 0) + _valueLabelGap = 0; + + _w = w + _labelWidth + _valueLabelGap + _valueLabelWidth; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font, + int x, int y, + const string& label, int labelWidth, int cmd, + int valueLabelWidth, const string& valueUnit, int valueLabelGap) + : SliderWidget(boss, font, x, y, font.getMaxCharWidth() * 10, font.getLineHeight(), + label, labelWidth, cmd, valueLabelWidth, valueUnit, valueLabelGap) +{ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -705,6 +673,8 @@ void SliderWidget::setValue(int value) { _value = value; setDirty(); + if (_valueLabelWidth) + setValueLabel(_value); // update label sendCommand(_cmd, _value, _id); } } @@ -727,12 +697,37 @@ void SliderWidget::setStepValue(int value) _stepValue = value; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SliderWidget::setValueLabel(const string& valueLabel) +{ + _valueLabel = valueLabel; + setDirty(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SliderWidget::setValueLabel(int value) +{ + char buf[256]; + std::snprintf(buf, 255, "%d", value); + _valueLabel = buf; + + setDirty(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SliderWidget::setValueUnit(const string& valueUnit) +{ + _valueUnit = valueUnit; + setDirty(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SliderWidget::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)) + if(isEnabled() && _isDragging && + x >= int(_labelWidth - 4) && x <= int(_w - _valueLabelGap - _valueLabelWidth + 4)) setValue(posToValue(x - _labelWidth)); } @@ -806,35 +801,28 @@ void SliderWidget::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); + s.drawString(_font, _label, _x, _y + 2, _labelWidth, isEnabled() ? kTextColor : kColor); - // 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); + int p = valueToPos(_value), + h = _h - 10, + x = _x + _labelWidth, + y = _y + (_h - h) / 2 + 1; - // 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); + s.fillRect(x, y, _w - _labelWidth - _valueLabelGap - _valueLabelWidth, h, + !isEnabled() ? kSliderBGColorLo : hilite ? kSliderBGColorHi : kSliderBGColor); // Draw the 'bar' - s.fillRect(_x + _labelWidth + 2, _y + 2, valueToPos(_value), _h - 4, + s.fillRect(x, y, p, h, !isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor); -#endif + // Draw the 'handle' + s.fillRect(x + p, y - 2, 2, h + 4, + !isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor); + + if(_valueLabelWidth > 0) + s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2, + _valueLabelWidth, isEnabled() ? kTextColor : kColor); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -844,13 +832,13 @@ int SliderWidget::valueToPos(int value) else if(value > _valueMax) value = _valueMax; int range = std::max(_valueMax - _valueMin, 1); // don't divide by zero - return ((_w - _labelWidth - 4) * (value - _valueMin) / range); + return ((_w - _labelWidth - _valueLabelGap - _valueLabelWidth - 2) * (value - _valueMin) / range); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int SliderWidget::posToValue(int pos) { - int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin; + int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - _valueLabelGap - _valueLabelWidth - 4) + _valueMin; // Scale the position to the correct interval (according to step value) return value - (value % _stepValue); diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 21baeccb3..06de06337 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -32,6 +32,7 @@ namespace GUI { #include "bspf.hxx" #include "Event.hxx" #include "GuiObject.hxx" +#include "Font.hxx" enum { WIDGET_ENABLED = 1 << 0, @@ -111,6 +112,7 @@ class Widget : public GuiObject void setTextColorHi(uInt32 color) { _textcolorhi = color; } void setBGColor(uInt32 color) { _bgcolor = color; } void setBGColorHi(uInt32 color) { _bgcolorhi = color; } + void setShadowColor(uInt32 color) { _shadowcolor = color; } virtual void loadConfig() { } @@ -141,6 +143,7 @@ class Widget : public GuiObject uInt32 _bgcolorhi; uInt32 _textcolor; uInt32 _textcolorhi; + uInt32 _shadowcolor; public: static Widget* findWidgetInChain(Widget* start, int x, int y); @@ -176,10 +179,12 @@ class StaticTextWidget : public Widget public: StaticTextWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, - const string& text, TextAlign align = TextAlign::Left); + const string& text = "", TextAlign align = TextAlign::Left, + uInt32 shadowColor = 0); StaticTextWidget(GuiObject* boss, const GUI::Font& font, int x, int y, - const string& text, TextAlign align = TextAlign::Left); + const string& text = "", TextAlign align = TextAlign::Left, + uInt32 shadowColor = 0); void setValue(int value); void setLabel(const string& label); void setAlign(TextAlign align) { _align = align; } @@ -301,18 +306,27 @@ class SliderWidget : public ButtonWidget { public: SliderWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, const string& label = "", - int labelWidth = 0, int cmd = 0); + int x, int y, int w, int h, + const string& label = "", int labelWidth = 0, int cmd = 0, + int valueLabelWidth = 0, const string& valueUnit = "", int valueLabelGap = 4); + SliderWidget(GuiObject* boss, const GUI::Font& font, + int x, int y, + const string& label = "", int labelWidth = 0, int cmd = 0, + int valueLabelWidth = 0, const string& valueUnit = "", int valueLabelGap = 4); void setValue(int value); - int getValue() const { return _value; } + int getValue() const { return _value; } void setMinValue(int value); - int getMinValue() const { return _valueMin; } + int getMinValue() const { return _valueMin; } void setMaxValue(int value); - int getMaxValue() const { return _valueMax; } + int getMaxValue() const { return _valueMax; } void setStepValue(int value); - int getStepValue() const { return _stepValue; } + int getStepValue() const { return _stepValue; } + void setValueLabel(const string& valueLabel); + void setValueLabel(int value); + const string& getValueLabel() const { return _valueLabel; } + void setValueUnit(const string& valueUnit); protected: void handleMouseMoved(int x, int y) override; @@ -327,10 +341,14 @@ class SliderWidget : public ButtonWidget int posToValue(int pos); protected: - int _value, _stepValue; - int _valueMin, _valueMax; - bool _isDragging; - int _labelWidth; + int _value, _stepValue; + int _valueMin, _valueMax; + bool _isDragging; + int _labelWidth; + string _valueLabel; + string _valueUnit; + int _valueLabelWidth; + int _valueLabelGap; private: // Following constructors and assignment operators not supported diff --git a/src/gui/module.mk b/src/gui/module.mk index 3058ac9c8..b598334c7 100644 --- a/src/gui/module.mk +++ b/src/gui/module.mk @@ -43,6 +43,7 @@ MODULE_OBJS := \ src/gui/SnapshotDialog.o \ src/gui/StringListWidget.o \ src/gui/TabWidget.o \ + src/gui/TimeLineWidget.o \ src/gui/TimeMachineDialog.o \ src/gui/TimeMachine.o \ src/gui/UIDialog.o \ diff --git a/src/macosx/stella.xcodeproj/project.pbxproj b/src/macosx/stella.xcodeproj/project.pbxproj index 4df9ee437..459b7ba78 100644 --- a/src/macosx/stella.xcodeproj/project.pbxproj +++ b/src/macosx/stella.xcodeproj/project.pbxproj @@ -568,6 +568,8 @@ DCE5CDE31BA10024005CD08A /* RiotRamWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCE5CDE11BA10024005CD08A /* RiotRamWidget.cxx */; }; DCE5CDE41BA10024005CD08A /* RiotRamWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCE5CDE21BA10024005CD08A /* RiotRamWidget.hxx */; }; DCE8B1871E7E03B300189864 /* FrameLayout.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCE8B1861E7E03B300189864 /* FrameLayout.hxx */; }; + DCE9158B201543B900960CC0 /* TimeLineWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCE91589201543B900960CC0 /* TimeLineWidget.cxx */; }; + DCE9158C201543B900960CC0 /* TimeLineWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCE9158A201543B900960CC0 /* TimeLineWidget.hxx */; }; DCEC58581E945125002F0246 /* DelayQueueWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCEC58561E945125002F0246 /* DelayQueueWidget.cxx */; }; DCEC58591E945125002F0246 /* DelayQueueWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCEC58571E945125002F0246 /* DelayQueueWidget.hxx */; }; DCEC585E1E945175002F0246 /* DelayQueueIterator.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCEC585B1E945175002F0246 /* DelayQueueIterator.hxx */; }; @@ -1240,6 +1242,8 @@ DCE5CDE11BA10024005CD08A /* RiotRamWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RiotRamWidget.cxx; sourceTree = ""; }; DCE5CDE21BA10024005CD08A /* RiotRamWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RiotRamWidget.hxx; sourceTree = ""; }; DCE8B1861E7E03B300189864 /* FrameLayout.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FrameLayout.hxx; sourceTree = ""; }; + DCE91589201543B900960CC0 /* TimeLineWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeLineWidget.cxx; sourceTree = ""; }; + DCE9158A201543B900960CC0 /* TimeLineWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimeLineWidget.hxx; sourceTree = ""; }; DCEC58561E945125002F0246 /* DelayQueueWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DelayQueueWidget.cxx; sourceTree = ""; }; DCEC58571E945125002F0246 /* DelayQueueWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DelayQueueWidget.hxx; sourceTree = ""; }; DCEC585B1E945175002F0246 /* DelayQueueIterator.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DelayQueueIterator.hxx; sourceTree = ""; }; @@ -1908,6 +1912,8 @@ 2DEF21FB08BC033500B246B4 /* StringListWidget.hxx */, 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */, 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */, + DCE91589201543B900960CC0 /* TimeLineWidget.cxx */, + DCE9158A201543B900960CC0 /* TimeLineWidget.hxx */, DCA82C6D1FEB4E780059340F /* TimeMachine.cxx */, DCA82C6E1FEB4E780059340F /* TimeMachine.hxx */, DCA82C6F1FEB4E780059340F /* TimeMachineDialog.cxx */, @@ -2180,6 +2186,7 @@ 2D91740509BA90380026E9FF /* DialogContainer.hxx in Headers */, DC6D39881A3CE65000171E71 /* CartWDWidget.hxx in Headers */, 2D91740609BA90380026E9FF /* GameInfoDialog.hxx in Headers */, + DCE9158C201543B900960CC0 /* TimeLineWidget.hxx in Headers */, 2D91740709BA90380026E9FF /* GameList.hxx in Headers */, 2D91740809BA90380026E9FF /* GuiObject.hxx in Headers */, DC73BD861915E5B1003FAFAD /* FBSurfaceSDL2.hxx in Headers */, @@ -2592,6 +2599,7 @@ 2D9174B709BA90380026E9FF /* OptionsDialog.cxx in Sources */, 2D9174B809BA90380026E9FF /* PopUpWidget.cxx in Sources */, DCBDDE9A1D6A5F0E009DF1E9 /* Cart3EPlusWidget.cxx in Sources */, + DCE9158B201543B900960CC0 /* TimeLineWidget.cxx in Sources */, DCE5CDE31BA10024005CD08A /* RiotRamWidget.cxx in Sources */, 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */, 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */, diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 021ec6dcb..15ea0f4a4 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -349,6 +349,7 @@ + @@ -656,6 +657,7 @@ + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index f43f77d34..1cbe3f7bb 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -888,6 +888,7 @@ Source Files\emucore\tia +<<<<<<< HEAD Source Files\emucore @@ -896,6 +897,10 @@ Source Files\emucore\tia +======= + + Source Files\gui +>>>>>>> master @@ -1826,6 +1831,7 @@ Header Files\emucore\tia +<<<<<<< HEAD Header Files\emucore @@ -1834,6 +1840,10 @@ Header Files\emucore\tia +======= + + Header Files\gui +>>>>>>> master