Merge branch 'master' into refactor/cart

This commit is contained in:
thrust26 2020-05-02 10:20:25 +02:00
commit 31f9613825
86 changed files with 1484 additions and 734 deletions

View File

@ -12,7 +12,7 @@
Release History
===========================================================================
6.1 to 6.2: (??? ??, 2020)
6.1.2 to 6.2: (??? ??, 2020)
* Added that paddle centering and sensitivity can be adjusted (TODO: Doc)
@ -24,7 +24,9 @@
* Added 'Turbo' mode, runs the game as fast as the computer allows.
* Added option which lets default ROM path follow launcher navigation (TODO: Doc)
* Added selectable dialog fonts
* Added option which lets default ROM path follow launcher navigation
* Added displaying last write address in the debugger.
@ -39,6 +41,16 @@
-Have fun!
6.1.1 to 6.1.2: (April 25, 2020)
* Fixed bug with remapped events not being reloaded in certain cases.
* Fixed bug in debugger for 3E scheme when displaying active RAM bank.
* Fixed bug in "Dragon Defender" ROM being misconfigured for Mindlink
controller.
6.1 to 6.1.1: (April 4, 2020)
* Fixed crash in 3E bankswitching scheme when writing to ROM addresses.

View File

@ -8,14 +8,11 @@
## SS SS tt ee ll ll aa aa
## SSSS ttt eeeee llll llll aaaaa
##
## Copyright (c) 1995-2016 by Bradford W. Mott, Stephen Anthony
## Copyright (c) 1995-2020 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.
##
## Based on code from ScummVM - Scumm Interpreter
## Copyright (C) 2002-2004 The ScummVM project
##============================================================================
#######################################################################

View File

@ -7,15 +7,15 @@ environment:
matrix:
- Platform: x64
- Platform: Win32
Configuration: Release
SDL2_version: 2.0.10
SDL2_version: 2.0.12
install:
- cmd: |
curl -o "C:\SDL2-devel.zip" https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip
curl -o "C:\SDL2-devel.zip" "https://www.libsdl.org/release/SDL2-devel-%SDL2_version%-VC.zip"
7z x "C:\SDL2-devel.zip" -o"C:\"
xcopy /S "C:\SDL2-%SDL2_version%\include" src\common

7
debian/changelog vendored
View File

@ -1,3 +1,10 @@
stella (6.1.2-1) stable; urgency=high
* Version 6.1.2 release
-- Stephen Anthony <sa666666@gmail.com> Sat, 25 Apr 2020 17:09:59 -0230
stella (6.1.1-1) stable; urgency=high
* Version 6.1.1 release

View File

@ -331,7 +331,7 @@ previous rewind operation. The rewind buffer is 100 levels deep by default, the
size can be configured e.g. in the
<b><a href="index.html#Debugger">Developer Settings</a> - Time Machine</b> dialog.<p>
<p>The other operations are Step, Trace, Scan+1, Frame+1 and Exit (debugger).</p>
<p>The other operations are Step, Trace, Scan+1, Frame+1 and Run.</p>
<p>You can also use the buttons from anywhere in the GUI via hotkeys.</p>
<p>
@ -382,12 +382,12 @@ size can be configured e.g. in the
</tr>
<tr>
<td>Backquote (`)</td>
<td>Exit</td>
<td>Run</td>
</tr>
</table>
</p>
For MacOS use 'Cmd' instead of &nbsp;'Alt' key.
<p>To the left of the global buttons, you find the "Options..." button.</p>
<p>To the left of the global buttons, you find the 'Options...' button.</p>
<ul>
<p><img src="graphics/debugger_options.png"></p>
</ul>
@ -608,7 +608,7 @@ created a symbol file, you can use labels for the expression.</p>
<p>Example: You have got a label called "kernel". To break there,
the command is "break kernel". After you've set the breakpoint,
exit the debugger ("quit" or click the Exit button). The emulator
exit the debugger (enter "run" or click the 'Run' button). The emulator
will run until it gets to the breakpoint, then it will enter the
debugger with the Program Counter pointing to the instruction
at the breakpoint.</p>
@ -1027,8 +1027,8 @@ graphics and positions, and the playfield.</p>
of the displays are editable. You can even toggle individual bits in
the GRP0/1 and playfield registers (remember to double-click).</p>
<p>The group of buttons labelled "Strobes" allows you to write to any
of the strobe registers at any time.</p>
<p>The buttons allow you to write to any of the strobe registers at
any time.</p>
<p>The collision registers are displayed in decoded format, in a table.
You can see exactly which objects have hit what. These are read-only
@ -1103,7 +1103,7 @@ or TV effects are enabled, you won't see the effects here; this shows the
<b>raw</b> TIA image only.</p>
<p>To e.g. watch the TIA draw the frame one scanline at a time, you can
use the "Scan+1" button, the prompt "scan" command or the Control-L key.</p>
use the 'Scan+1' button, the prompt "scan" command or the Control-L key.</p>
<p>You can also right-click anywhere in this window to show a context menu,
as illustrated:</p>
@ -1213,7 +1213,7 @@ section for details.</p>
<p><img src="graphics/debugger_cpuregs.png"></p>
<p>All the registers and flags are displayed, and can be changed by
double-clicking on them (to the left). Flags are toggled on double-click.
Selected registers here can also be changed by using the "Data Operations" buttons,
Selected registers here can also be changed by using the 'Data Operations' buttons,
further described in (J). All items are shown in hex. Any label defined for the
current PC value is shown to the right. Decimal and binary equivalents
are shown for SP/A/X/Y to the right (first decimal, then binary).</p>
@ -1631,7 +1631,7 @@ but it helps to know at least a little about 6502 programming.</p>
<li>Enter the debugger by pressing the ` (backquote) key. Don't get
killed before you do this, though. You should still have all 5 lives.</li>
<li>In the RAM display, click the "Search" button and enter "5" for input.
<li>In the RAM display, click the 'Search' button and enter "5" for input.
This searches RAM for your value and highlights all addresses that match
the input. You should see two addresses highlighted: "00a5" and "00ba".
These are the only two addresses that currently have the value 5, so they're
@ -1647,7 +1647,7 @@ but it helps to know at least a little about 6502 programming.</p>
<li>Get killed! Ram an enemy tank, or let him shoot you. Wait for
the explosion to finish. You will now have 4 lives.</li>
<li>Enter the debugger again. Click the "Compare" button in RAM widget and enter
<li>Enter the debugger again. Click the 'Compare...' button in RAM widget and enter
a value of 4. Now the RAM widget should only show one highlighted address:
"00ba". What we did was search within our previous results (the ones that
were 5 before) for the new value 4. Address $00ba used to have the value 5,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -2404,6 +2404,11 @@
<td>Use the specified palette for UI elements.</td>
</tr>
<tr>
<td><pre>-dialogfont &lt;small|low_medium|medium|large|large12|large14|large16&gt;</pre></td>
<td>Set the size of the font in the dialogs.</td>
</tr>
<tr>
<td><pre>-dialogpos &lt;0 - 4&gt;</pre></td>
<td>Set the position of dialogs within Stella windows (0 = center).</td>
@ -2448,7 +2453,12 @@
<tr>
<td><pre>-romdir &lt;dir&gt;</pre></td>
<td>Set the directory where the ROM launcher will start.</td>
<td>Set the path where the ROM launcher will start.</td>
</tr>
<tr>
<td><pre>-followlauncher &lt;0|1&gt;</pre></td>
<td>Make the start path follow ROM launcher navigation.</td>
</tr>
<tr>
@ -2914,8 +2924,9 @@
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Theme</td><td>Theme to use for UI elements (see examples)</td><td>-uipalette</td></tr>
<tr><td>Dialogs position</td><td>Position of dialogs with Stella window</td><td>-dialogpos</td></tr>
<tr><td>Dialogs font</td><td>The font used in the dialogs</td><td>-dialogfont</td></tr>
<tr><td>HiDPI mode</td><td>Scales the UI by a factor of two when enabled</td><td>-hidpi</td></tr>
<tr><td>Dialogs position</td><td>Position of dialogs with Stella window</td><td>-dialogpos</td></tr>
<tr><td>Confirm exiting...</td><td>Display a popup when emulation is exited</td><td>-confirmexit</td></tr>
<tr><td>List input delay</td><td>Maximum delay between keypresses in filelist-widgets before a search string resets. </td><td>-listdelay</td></tr>
<tr><td>Mouse wheel scroll</td><td>Number of lines a mouse scroll will move in list-widgets</td><td>-mwheel</td></tr>

View File

@ -35,46 +35,50 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: 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;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("One shot ") + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
ButtonWidget* b;
// Set real dimensions
_w = 45 * fontWidth + HBORDER * 2;
_h = 11 * (lineHeight + 4) + VBORDER;
_h = _th + 11 * (lineHeight + 4) + VBORDER * 2;
// List of cheats, with checkboxes to enable/disable
xpos = HBORDER; ypos = VBORDER;
xpos = HBORDER; ypos = _th + VBORDER;
myCheatList =
new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - 8,
_h - 2*buttonHeight - VBORDER);
new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - fontWidth,
_h - _th - buttonHeight - VBORDER * 3);
myCheatList->setEditable(false);
wid.push_back(myCheatList);
xpos += myCheatList->getWidth() + 8; ypos = VBORDER;
xpos += myCheatList->getWidth() + fontWidth; ypos = _th + VBORDER;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Add" + ELLIPSIS, kAddCheatCmd);
wid.push_back(b);
ypos += lineHeight + 8;
ypos += lineHeight + VGAP * 2;
myEditButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Edit" + ELLIPSIS, kEditCheatCmd);
wid.push_back(myEditButton);
ypos += lineHeight + 8;
ypos += lineHeight + VGAP * 2;
myRemoveButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Remove", kRemCheatCmd);
wid.push_back(myRemoveButton);
ypos += lineHeight + 8 * 3;
ypos += lineHeight + VGAP * 2 * 3;
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"One shot" + ELLIPSIS, kAddOneShotCmd);

View File

@ -49,7 +49,7 @@
*/
namespace Common {
template <class T, uInt32 CAPACITY = 100>
template <typename T, uInt32 CAPACITY = 100>
class LinkedObjectPool
{
public:

View File

@ -66,6 +66,31 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
setDefaultMapping(Event::NoType, EventMode::kMenuMode, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isMappingUsed(EventMode mode, const EventMapping& map) const
{
// Menu events can only interfere with
// - other menu events
if(mode == EventMode::kMenuMode)
return myKeyMap.check(EventMode::kMenuMode, map.key, map.mod);
// Controller events can interfere with
// - other events of the same controller
// - and common emulation events
if(mode != EventMode::kCommonMode)
return myKeyMap.check(mode, map.key, map.mod)
|| myKeyMap.check(EventMode::kCommonMode, map.key, map.mod);
// Common emulation events can interfere with
// - other common emulation events
// - and all controller events
return myKeyMap.check(EventMode::kCommonMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kJoystickMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kPaddlesMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kKeypadMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kCompuMateMode, map.key, map.mod);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Depending on parameters, this method does the following:
// 1. update all events with default (event == Event::NoType, updateDefault == true)
@ -83,7 +108,7 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
// if there is no existing mapping for the event and
// the default mapping for the event is unused, set default key for event
if (myKeyMap.getEventMapping(map.event, mode).size() == 0 &&
!myKeyMap.check(mode, map.key, map.mod))
!isMappingUsed(mode, map))
{
addMapping(map.event, mode, map.key, StellaMod(map.mod));
}

View File

@ -87,6 +87,9 @@ class PhysicalKeyboardHandler
};
using EventMappingArray = std::vector<EventMapping>;
// Checks if the given mapping is used by any event mode
bool isMappingUsed(EventMode mode, const EventMapping& map) const;
void setDefaultKey(EventMapping map, Event::Type event = Event::NoType,
EventMode mode = EventMode::kEmulationMode, bool updateDefaults = false);

View File

@ -27,7 +27,7 @@
*/
namespace Common {
template <class T, uInt32 CAPACITY = 50>
template <typename T, uInt32 CAPACITY = 50>
class FixedStack
{
private:

View File

@ -22,19 +22,19 @@
namespace Vec {
template<class T>
template<typename T>
void append(vector<T>& dst, const vector<T>& src)
{
dst.insert(dst.cend(), src.cbegin(), src.cend());
}
template<class T>
template<typename T>
void insertAt(vector<T>& dst, uInt32 idx, const T& element)
{
dst.insert(dst.cbegin()+idx, element);
}
template<class T>
template<typename T>
void removeAt(vector<T>& dst, uInt32 idx)
{
dst.erase(dst.cbegin()+idx);

View File

@ -120,16 +120,16 @@ namespace BSPF
#endif
// Make 2D-arrays using std::array less verbose
template<class T, size_t ROW, size_t COL>
template<typename T, size_t ROW, size_t COL>
using array2D = std::array<std::array<T, COL>, ROW>;
// Combines 'max' and 'min', and clamps value to the upper/lower value
// if it is outside the specified range
template<class T> inline T clamp(T val, T lower, T upper)
template<typename T> inline T clamp(T val, T lower, T upper)
{
return (val < lower) ? lower : (val > upper) ? upper : val;
}
template<class T> inline void clamp(T& val, T lower, T upper, T setVal)
template<typename T> inline void clamp(T& val, T lower, T upper, T setVal)
{
if(val < lower || val > upper) val = setVal;
}

View File

@ -736,7 +736,7 @@ string CartDebug::loadListFile()
if(myListFile == "")
{
FilesystemNode lst(myOSystem.romFile().getPathWithExt("") + ".lst");
FilesystemNode lst(myOSystem.romFile().getPathWithExt(".lst"));
if(lst.isFile() && lst.isReadable())
myListFile = lst.getPath();
else
@ -796,7 +796,7 @@ string CartDebug::loadSymbolFile()
if(mySymbolFile == "")
{
FilesystemNode sym(myOSystem.romFile().getPathWithExt("") + ".sym");
FilesystemNode sym(myOSystem.romFile().getPathWithExt(".sym"));
if(sym.isFile() && sym.isReadable())
mySymbolFile = sym.getPath();
else
@ -856,7 +856,7 @@ string CartDebug::loadConfigFile()
if(myCfgFile == "")
{
FilesystemNode romNode(myOSystem.romFile().getPathWithExt("") + ".cfg");
FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg"));
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
if(cfg.isFile() && cfg.isReadable())
myCfgFile = cfg.getPath();
@ -978,7 +978,7 @@ string CartDebug::saveConfigFile()
if(myCfgFile == "")
{
FilesystemNode romNode(myOSystem.romFile().getPathWithExt("") + ".cfg");
FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg"));
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
if(cfg.getParent().isWritable())
myCfgFile = cfg.getPath();

View File

@ -688,6 +688,7 @@ void Debugger::setStartState()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setQuitState()
{
myDialog->saveConfig();
saveOldState();
// Bus must be unlocked for normal operation when leaving debugger mode

View File

@ -65,7 +65,7 @@ int CartDebugWidget::addBaseInformation(size_t bytes, const string& manufacturer
w->setEditable(false);
y += myLineHeight + 4;
StringParser bs(desc, (fwidth - kScrollBarWidth - 4) / myFontWidth);
StringParser bs(desc, (fwidth - ScrollBarWidget::scrollBarWidth(_font)) / myFontWidth - 4);
const StringList& sl = bs.stringList();
uInt32 lines = uInt32(sl.size());
if(lines < 3) lines = 3;

View File

@ -62,7 +62,7 @@ CartRamWidget::CartRamWidget(
// Add Description
const string& desc = cartDebug.internalRamDescription();
const uInt16 maxlines = 6;
StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth);
StringParser bs(desc, (fwidth - ScrollBarWidget::scrollBarWidth(_font)) / myFontWidth);
const StringList& sl = bs.stringList();
uInt32 lines = uInt32(sl.size());
if(lines < 2) lines = 2;

View File

@ -67,7 +67,8 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
// Add a scrollbar if necessary
if(useScrollbar)
{
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h);
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y,
ScrollBarWidget::scrollBarWidth(_font), _h);
_scrollBar->setTarget(this);
_scrollBar->_numEntries = 1;
_scrollBar->_currentPos = 0;
@ -675,7 +676,7 @@ Common::Rect DataGridWidget::getEditRect() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DataGridWidget::getWidth() const
{
return _w + (_scrollBar ? kScrollBarWidth : 0);
return _w + (_scrollBar ? ScrollBarWidget::scrollBarWidth(_font) : 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -71,12 +71,11 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::loadConfig()
{
// set initial focus to myPrompt
if (myFirstLoad)
{
setFocus(myPrompt);
myFirstLoad = false;
}
if(myFocusedWidget == nullptr)
// Set initial focus to prompt tab
myFocusedWidget = myPrompt;
// Restore focus
setFocus(myFocusedWidget);
myTab->loadConfig();
myTiaInfo->loadConfig();
@ -89,6 +88,11 @@ void DebuggerDialog::loadConfig()
myMessageBox->setText("");
}
void DebuggerDialog::saveConfig()
{
myFocusedWidget = _focusedWidget;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
{
@ -231,7 +235,7 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
doUnwind();
break;
case kDDExitCmd:
case kDDRunCmd:
doExitDebugger();
break;
@ -541,7 +545,7 @@ void DebuggerDialog::addRomArea()
wid2.push_back(b);
buttonY += bheight + 4;
b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
bwidth, bheight, "Exit", kDDExitCmd);
bwidth, bheight, "Run", kDDRunCmd);
wid2.push_back(b);
addCancelWidget(b);

View File

@ -71,6 +71,7 @@ class DebuggerDialog : public Dialog
ButtonWidget& unwindButton() const { return *myUnwindButton; }
void showFatalMessage(const string& msg);
void saveConfig();
private:
void center() override { positionAt(0); }
@ -110,7 +111,7 @@ class DebuggerDialog : public Dialog
kDDSAdvCmd = 'DDsv',
kDDRewindCmd = 'DDrw',
kDDUnwindCmd = 'DDuw',
kDDExitCmd = 'DDex',
kDDRunCmd = 'DDex',
kDDExitFatalCmd = 'DDer',
kDDOptionsCmd = 'DDop'
};
@ -136,7 +137,8 @@ class DebuggerDialog : public Dialog
unique_ptr<GUI::Font> myLFont; // used for labels
unique_ptr<GUI::Font> myNFont; // used for normal text
bool myFirstLoad{true};
Widget* myFocusedWidget{nullptr};
private:
// Following constructors and assignment operators not supported

View File

@ -30,7 +30,6 @@ FlashWidget::FlashWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FlashWidget::init(GuiObject* boss, const GUI::Font& font, int x, int y)
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = font.getLineHeight();
int xpos = x, ypos = y;
@ -38,14 +37,14 @@ void FlashWidget::init(GuiObject* boss, const GUI::Font& font, int x, int y)
ypos += lineHeight + 6;
new StaticTextWidget(boss, ifont, xpos, ypos, "Pages/Ranges used:");
new StaticTextWidget(boss, font, xpos, ypos, "Pages/Ranges used:");
ypos += lineHeight + 2;
xpos += 8;
for(uInt32 page = 0; page < MAX_PAGES; ++page)
{
myPage[page] = new StaticTextWidget(boss, ifont, xpos, ypos,
myPage[page] = new StaticTextWidget(boss, font, xpos, ypos,
page ? " " : "none ");
ypos += lineHeight;
}

View File

@ -33,7 +33,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h)
: Widget(boss, font, x, y, w - kScrollBarWidth, h),
: Widget(boss, font, x, y, w - ScrollBarWidget::scrollBarWidth(font), h),
CommandSender(boss),
_historySize(0),
_historyIndex(0),
@ -53,12 +53,13 @@ PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font,
_kConsoleLineHeight = _kConsoleCharHeight + 2;
// Calculate depending values
_lineWidth = (_w - kScrollBarWidth - 2) / _kConsoleCharWidth;
_lineWidth = (_w - ScrollBarWidget::scrollBarWidth(_font) - 2) / _kConsoleCharWidth;
_linesPerPage = (_h - 2) / _kConsoleLineHeight;
_linesInBuffer = kBufferSize / _lineWidth;
// Add scrollbar
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h);
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y,
ScrollBarWidget::scrollBarWidth(_font), _h);
_scrollBar->setTarget(this);
// Init colors
@ -546,7 +547,7 @@ void PromptWidget::loadConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int PromptWidget::getWidth() const
{
return _w + kScrollBarWidth;
return _w + ScrollBarWidget::scrollBarWidth(_font);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -214,7 +214,7 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
// 2600/7800 mode
lwidth = lfont.getStringWidth("Console") + 29;
pwidth = lfont.getStringWidth("Atari 2600") + 4;
pwidth = lfont.getStringWidth("Atari 2600") + 6;
new StaticTextWidget(boss, lfont, 10, ypos+1, "Console");
myConsole = new EditTextWidget(boss, lfont, 10 + lwidth, ypos - 1, pwidth, lineHeight);
myConsole->setEditable(false, true);

View File

@ -42,11 +42,12 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
_rows = h / _fontHeight;
// Set real dimensions
_w = w - kScrollBarWidth;
_w = w - ScrollBarWidget::scrollBarWidth(_font);
_h = h + 2;
// Create scrollbar and attach to the list
myScrollBar = new ScrollBarWidget(boss, lfont, _x + _w, _y, kScrollBarWidth, _h);
myScrollBar = new ScrollBarWidget(boss, lfont, _x + _w, _y,
ScrollBarWidget::scrollBarWidth(_font), _h);
myScrollBar->setTarget(this);
// Add settings menu
@ -65,7 +66,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
// rowheight is determined by largest item on a line,
// possibly meaning that number of rows will change
_fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize());
_fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize(_font));
_rows = h / _fontHeight;
// Create a CheckboxWidget for each row in the list
@ -465,7 +466,7 @@ void RomListWidget::drawWidget(bool hilite)
// Draw a thin frame around the list and to separate columns
s.frameRect(_x, _y, _w + 1, _h, hilite ? kWidColorHi : kColor);
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
s.vLine(_x + CheckboxWidget::boxSize(_font) + 5, _y, _y + _h - 1, kColor);
// Draw the list items
int cycleCountW = _fontWidth * 8,
@ -476,7 +477,7 @@ void RomListWidget::drawWidget(bool hilite)
if(actualWidth < codeDisasmW)
codeDisasmW = actualWidth;
xpos = _x + CheckboxWidget::boxSize() + 10; ypos = _y + 2;
xpos = _x + CheckboxWidget::boxSize(_font) + 10; ypos = _y + 2;
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++, ypos += _fontHeight)
{
ColorId bytesColor = textColor;
@ -566,7 +567,7 @@ void RomListWidget::drawWidget(bool hilite)
Common::Rect RomListWidget::getLineRect() const
{
const int yoffset = std::max(0, (_selectedItem - _currentPos) * _fontHeight),
xoffset = CheckboxWidget::boxSize() + 10;
xoffset = CheckboxWidget::boxSize(_font) + 10;
return Common::Rect(2 + xoffset, 1 + yoffset,
_w - (xoffset - 15), _fontHeight + yoffset);

View File

@ -34,15 +34,16 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont,
: Widget(boss, lfont, x, y, 16, 16),
CommandSender(boss)
{
bool longstr = 34 * lfont.getMaxCharWidth() <= max_w;
bool longstr = 11 + 32 * lfont.getMaxCharWidth() + 9
+ EditTextWidget::calcWidth(lfont) * 3 <= max_w;
const int VGAP = 5;
x += 11;
const int lineHeight = lfont.getLineHeight();
int xpos = x, ypos = y + 10;
int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle " : "F. Cycle ");
int fwidth = 5 * lfont.getMaxCharWidth() + 4;
int twidth = 8 * lfont.getMaxCharWidth() + 4;
int fwidth = EditTextWidget::calcWidth(lfont, 5);
int twidth = EditTextWidget::calcWidth(lfont, 8);
// Add frame info
// 1st column
@ -78,11 +79,9 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont,
// 2nd column
xpos = x + lwidth + myFrameCycles->getWidth() + 9; ypos = y + 10;
lwidth = lfont.getStringWidth(longstr ? "Color Clock " : "Pixel Pos ");
fwidth = 3 * lfont.getMaxCharWidth() + 4;
fwidth = EditTextWidget::calcWidth(lfont, 3);
new StaticTextWidget(boss, lfont, xpos, ypos,
lfont.getStringWidth(longstr ? "Scanline" : "Scn Ln"), lineHeight,
longstr ? "Scanline" : "Scn Ln", TextAlign::Left);
new StaticTextWidget(boss, lfont, xpos, ypos, longstr ? "Scanline" : "Scn Ln");
myScanlineCountLast = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth,
lineHeight, "");
myScanlineCountLast->setEditable(false, true);

View File

@ -2092,7 +2092,7 @@ static const BSPF::array2D<const char*, DEF_PROPS_SIZE, 23> DefProps = {{
{ "95a69cf8c08ef1522b050529464f0bca", "", "", "Grid Pattern Demo 1 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "95a89d1bf767d7cc9d0d5093d579ba61", "PlayAround - J.H.M.", "204", "Lady in Wading (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },
{ "95e1d834c57cdd525dd0bd6048a57f7b", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "95e542a7467c94b1e4ab24a3ebe907f1", "Suntek", "SS-021", "Dragon Defender (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "YES", "" },
{ "95e542a7467c94b1e4ab24a3ebe907f1", "Suntek", "SS-021", "Dragon Defender (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },
{ "95fd6097dc27c20666f039cfe34f7c69", "", "", "Oh No! (Version 1) (17-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "961112b74a920a5242e233480326c356", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "962ffd3eaf865230a7a312b80e6c5cfd", "Imagic, Wilfredo 'Willy' Aguilar, Michael Becker, Rob Fulop", "13205", "Fathom (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },

View File

@ -55,7 +55,7 @@ class DispatchResult
if (myStatus != status) throw runtime_error("invalid status for operation");
}
template<class ...Ts> void assertStatus(Status status, Ts... more) const
template<typename ...Ts> void assertStatus(Status status, Ts... more) const
{
if (myStatus == status) return;

View File

@ -82,7 +82,8 @@ enum class EventMode {
kPaddlesMode,
kKeypadMode,
kCompuMateMode, // cannot be remapped
kCommonMode // mapping common between controllers
kCommonMode, // mapping common between controllers
kNumModes
};
namespace GUI

View File

@ -36,6 +36,7 @@
#ifdef GUI_SUPPORT
#include "Font.hxx"
#include "StellaFont.hxx"
#include "ConsoleMediumFont.hxx"
#include "ConsoleMediumBFont.hxx"
#include "StellaMediumFont.hxx"
#include "StellaLargeFont.hxx"
@ -97,56 +98,7 @@ bool FrameBuffer::initialize()
}
#ifdef GUI_SUPPORT
////////////////////////////////////////////////////////////////////
// Create fonts to draw text
// NOTE: the logic determining appropriate font sizes is done here,
// so that the UI classes can just use the font they expect,
// and not worry about it
// This logic should also take into account the size of the
// framebuffer, and try to be intelligent about font sizes
// We can probably add ifdefs to take care of corner cases,
// but that means we've failed to abstract it enough ...
////////////////////////////////////////////////////////////////////
// This font is used in a variety of situations when a really small
// font is needed; we let the specific widget/dialog decide when to
// use it
mySmallFont = make_unique<GUI::Font>(GUI::stellaDesc); // 6x10
// The general font used in all UI elements
// This is determined by the size of the framebuffer
if(myOSystem.settings().getBool("minimal_ui"))
{
myFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
// The info font used in all UI elements
// This is determined by the size of the framebuffer
myInfoFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
}
else
{
myFont = make_unique<GUI::Font>(GUI::stellaMediumDesc); // 9x18
// The info font used in all UI elements
// This is determined by the size of the framebuffer
myInfoFont = make_unique<GUI::Font>(GUI::consoleDesc); // 8x13
}
// The font used by the ROM launcher
const string& lf = myOSystem.settings().getString("launcherfont");
if(lf == "small")
myLauncherFont = make_unique<GUI::Font>(GUI::consoleBDesc); // 8x13
else if(lf == "low_medium")
myLauncherFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc); // 9x15
else if(lf == "medium")
myLauncherFont = make_unique<GUI::Font>(GUI::stellaMediumDesc); // 9x18
else if(lf == "large" || lf == "large10")
myLauncherFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
else if(lf == "large12")
myLauncherFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
else if(lf == "large14")
myLauncherFont = make_unique<GUI::Font>(GUI::stella14x28tDesc); // 14x28
else // "large16"
myLauncherFont = make_unique<GUI::Font>(GUI::stella16x32tDesc); // 16x32
setupFonts();
#endif
// Determine possible TIA windowed zoom levels
@ -164,6 +116,92 @@ bool FrameBuffer::initialize()
return true;
}
#ifdef GUI_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setupFonts()
{
////////////////////////////////////////////////////////////////////
// Create fonts to draw text
// NOTE: the logic determining appropriate font sizes is done here,
// so that the UI classes can just use the font they expect,
// and not worry about it
// This logic should also take into account the size of the
// framebuffer, and try to be intelligent about font sizes
// We can probably add ifdefs to take care of corner cases,
// but that means we've failed to abstract it enough ...
////////////////////////////////////////////////////////////////////
// This font is used in a variety of situations when a really small
// font is needed; we let the specific widget/dialog decide when to
// use it
mySmallFont = make_unique<GUI::Font>(GUI::stellaDesc); // 6x10
if(myOSystem.settings().getBool("minimal_ui"))
{
// The general font used in all UI elements
myFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
// The info font used in all UI elements
myInfoFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
}
else
{
const int NUM_FONTS = 7;
FontDesc FONT_DESC[NUM_FONTS] = {GUI::consoleDesc, GUI::consoleMediumDesc, GUI::stellaMediumDesc,
GUI::stellaLargeDesc, GUI::stella12x24tDesc, GUI::stella14x28tDesc, GUI::stella16x32tDesc};
const string& dialogFont = myOSystem.settings().getString("dialogfont");
FontDesc fd = getFontDesc(dialogFont);
// The general font used in all UI elements
myFont = make_unique<GUI::Font>(fd); // default: 9x18
// The info font used in all UI elements,
// automatically determined aiming for 1 / 1.4 (~= 18 / 13) size
int fontIdx = 0;
for(int i = 0; i < NUM_FONTS; ++i)
{
if(fd.height <= FONT_DESC[i].height * 1.4)
{
fontIdx = i;
break;
}
}
myInfoFont = make_unique<GUI::Font>(FONT_DESC[fontIdx]); // default 8x13
// Determine minimal zoom level based on the default font
// So what fits with default font should fit for any font.
// However, we have to make sure all Dialogs are sized using the fontsize.
int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height;
int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth;
myTIAMinZoom = std::max(zoom_w, zoom_h) / 4.F; // round to 25% steps
}
// The font used by the ROM launcher
const string& lf = myOSystem.settings().getString("launcherfont");
myLauncherFont = make_unique<GUI::Font>(getFontDesc(lf)); // 8x13
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FontDesc FrameBuffer::getFontDesc(const string& name) const
{
if(name == "small")
return GUI::consoleBDesc; // 8x13
else if(name == "low_medium")
return GUI::consoleMediumBDesc; // 9x15
else if(name == "medium")
return GUI::stellaMediumDesc; // 9x18
else if(name == "large" || name == "large10")
return GUI::stellaLargeDesc; // 10x20
else if(name == "large12")
return GUI::stella12x24tDesc; // 12x24
else if(name == "large14")
return GUI::stella14x28tDesc; // 14x28
else // "large16"
return GUI::stella16x32tDesc; // 16x32
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBInitStatus FrameBuffer::createDisplay(const string& title,
uInt32 width, uInt32 height,
@ -268,7 +306,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
}
if(!myMsg.surface)
myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight()+10);
myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight() * 1.5);
#endif
// Print initial usage message, but only print it later if the status has changed
@ -454,14 +492,20 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
if(myMsg.surface == nullptr || !(force || myOSystem.settings().getBool("uimessages")))
return;
const int fontWidth = font().getMaxCharWidth(),
fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
// Precompute the message coordinates
myMsg.text = message;
myMsg.counter = uInt32(myOSystem.frameRate()) << 1; // Show message for 2 seconds
if(myMsg.counter == 0) myMsg.counter = 60;
myMsg.color = kBtnTextColor;
myMsg.w = font().getStringWidth(myMsg.text) + 10;
myMsg.h = font().getFontHeight() + 8;
myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
myMsg.h = fontHeight + VBORDER * 2;
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
myMsg.position = position;
@ -580,6 +624,10 @@ inline bool FrameBuffer::drawMessage()
// Draw the bounded box and text
const Common::Rect& dst = myMsg.surface->dstRect();
const int fontWidth = font().getMaxCharWidth(),
fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
switch(myMsg.position)
{
@ -630,10 +678,10 @@ inline bool 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);
myMsg.surface->fillRect(1, 1, myMsg.w - 2, myMsg.h - 2, kBtnColor);
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
myMsg.surface->drawString(font(), myMsg.text, 5, 4,
myMsg.w, myMsg.color, TextAlign::Left);
myMsg.surface->drawString(font(), myMsg.text, HBORDER, VBORDER,
myMsg.w, myMsg.color);
myMsg.surface->render();
myMsg.counter--;
#endif
@ -965,7 +1013,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
if(tiaMode)
{
// TIA windowed modes
uInt32 minZoom = supportedTIAMinZoom();
float minZoom = supportedTIAMinZoom();
myTIAMaxZoom = maxZoomForScreen(baseWidth, baseHeight,
myAbsDesktopSize.w, myAbsDesktopSize.h);
// Determine all zoom levels

View File

@ -26,9 +26,9 @@ class Settings;
class FBSurface;
class TIASurface;
namespace GUI {
class Font;
}
#ifdef GUI_SUPPORT
#include "Font.hxx"
#endif
#include "Rect.hxx"
#include "Variant.hxx"
@ -223,7 +223,7 @@ class FrameBuffer
Get the minimum/maximum supported TIA zoom level (windowed mode)
for the framebuffer.
*/
float supportedTIAMinZoom() const { return 2 * hidpiScaleFactor(); }
float supportedTIAMinZoom() const { return myTIAMinZoom * hidpiScaleFactor(); }
float supportedTIAMaxZoom() const { return myTIAMaxZoom; }
/**
@ -307,6 +307,15 @@ class FrameBuffer
const GUI::Font& infoFont() const { return *myInfoFont; }
const GUI::Font& smallFont() const { return *mySmallFont; }
const GUI::Font& launcherFont() const { return *myLauncherFont; }
/**
Get the font description from the font name
@param name The settings name of the font
@return The description of the font
*/
FontDesc getFontDesc(const string& name) const;
#endif
//////////////////////////////////////////////////////////////////////
@ -480,6 +489,13 @@ class FrameBuffer
*/
void resetSurfaces();
#ifdef GUI_SUPPORT
/**
Setup the UI fonts
*/
void setupFonts();
#endif
/**
Calculate the maximum level by which the base window can be zoomed and
still fit in the given screen dimensions.
@ -619,6 +635,8 @@ class FrameBuffer
VideoModeList myWindowedModeList;
vector<VideoModeList> myFullscreenModeLists;
// Minimum TIA zoom level that can be used for this framebuffer
float myTIAMinZoom{2.F};
// Maximum TIA zoom level that can be used for this framebuffer
float myTIAMaxZoom{1.F};

View File

@ -646,11 +646,35 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size
if(md5 == "")
md5 = MD5::hash(image, size);
// Some games may not have a name, since there may not
// be an entry in stella.pro. In that case, we use the rom name
// and reinsert the properties object
// Handle ROM properties, do some error checking
// Only add to the database when necessary
bool toInsert = false;
// First, does this ROM have a per-ROM properties entry?
// If so, load it into the database
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
if(propsNode.exists() && propsNode.isFile())
{
Logger::info("Loading per-ROM properties: " + propsNode.getShortPath());
myPropSet->load(propsNode.getPath(), false);
}
// Next, make sure we have a valid md5 and name
Properties props;
myPropSet->getMD5WithInsert(rom, md5, props);
if(!myPropSet->getMD5(md5, props))
{
props.set(PropType::Cart_MD5, md5);
toInsert = true;
}
if(toInsert || props.get(PropType::Cart_Name) == EmptyString)
{
props.set(PropType::Cart_Name, rom.getNameWithExt(""));
toInsert = true;
}
// Finally, insert properties if any info was missing
if(toInsert)
myPropSet->insert(props, false);
return image;
}

View File

@ -24,13 +24,13 @@
#include "PropsSet.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::load(const string& filename)
void PropertiesSet::load(const string& filename, bool save)
{
ifstream in(filename);
Properties prop;
while(in >> prop)
insert(prop);
insert(prop, save);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -117,26 +117,6 @@ bool PropertiesSet::getMD5(const string& md5, Properties& properties,
return found;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::getMD5WithInsert(const FilesystemNode& rom,
const string& md5, Properties& properties)
{
bool toInsert = false;
if(!getMD5(md5, properties))
{
properties.set(PropType::Cart_MD5, md5);
toInsert = true;
}
if(toInsert || properties.get(PropType::Cart_Name) == EmptyString)
{
properties.set(PropType::Cart_Name, rom.getNameWithExt(""));
toInsert = true;
}
if(toInsert)
insert(properties, false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::insert(const Properties& properties, bool save)
{

View File

@ -49,8 +49,10 @@ class PropertiesSet
searchable list.
@param filename Full pathname of input file to use
@param save Indicates whether the properties should be saved
when the program exits
*/
void load(const string& filename);
void load(const string& filename, bool save = true);
/**
Save properties to the specified file.
@ -78,19 +80,6 @@ class PropertiesSet
bool getMD5(const string& md5, Properties& properties,
bool useDefaults = false) const;
/**
Get the property from the set with the given MD5, at the same time
checking if it exists. If it doesn't, insert a temporary copy into
the set.
@param rom The ROM file used to calculate the MD5
@param md5 The md5 of the property to get
@param properties The properties with the given MD5, or the default
properties if not found
*/
void getMD5WithInsert(const FilesystemNode& rom, const string& md5,
Properties& properties);
/**
Insert the properties into the set. If a duplicate is inserted
the old properties are overwritten with the new ones.

View File

@ -146,6 +146,7 @@ Settings::Settings()
setPermanent("ctrldelay", "400");
setPermanent("ctrlrate", "20");
setPermanent("basic_settings", false);
setPermanent("dialogfont", "medium");
setPermanent("dialogpos", 0);
setPermanent("confirmexit", false);
@ -510,6 +511,11 @@ void Settings::usage() const
<< " -uipalette <standard| Selects GUI theme\n"
<< " classic|light>\n"
<< " -hidpi <0|1> Enable HiDPI mode\n"
<< " -dialogfont <small| Use the specified font in the dialogs\n"
<< " low_medium|\n"
<< " medium|large|\n"
<< " large12|large14|\n"
<< " large16>\n"
<< " -dialogpos <0..4> Display all dialogs at given positions\n"
<< " -confirmexit <0|1> Display a confirm dialog when exiting emulation\n"
<< " -listdelay <delay> Time to wait between keypresses in list widgets\n"

View File

@ -12574,7 +12574,6 @@
"Cart.Manufacturer" "Suntek"
"Cart.ModelNo" "SS-021"
"Cart.Name" "Dragon Defender (1983) (Suntek) (PAL)"
"Controller.Left" "MINDLINK"
"Display.Phosphor" "YES"
""

View File

@ -41,7 +41,7 @@ class DelayQueue : public Serializable
void reset();
template<class T> void execute(T executor);
template<typename T> void execute(T executor);
/**
Serializable methods (see that class for more information).
@ -103,7 +103,7 @@ void DelayQueue<length, capacity>::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<unsigned length, unsigned capacity>
template<class T>
template<typename T>
void DelayQueue<length, capacity>::execute(T executor)
{
DelayQueueMember<capacity>& currentMember = myMembers[myIndex];

View File

@ -28,44 +28,49 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
: Dialog(osystem, parent, font, "About Stella")
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
// Set real dimensions
_w = 55 * fontWidth + 8;
_h = 15 * lineHeight + 20 + _th;
_w = 55 * fontWidth + HBORDER * 2;
_h = _th + 14 * lineHeight + VGAP * 3 + buttonHeight + VBORDER * 2;
// Add Previous, Next and Close buttons
xpos = 10; ypos = _h - buttonHeight - 10;
xpos = HBORDER; ypos = _h - buttonHeight - VBORDER;
myPrevButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Previous", GuiObject::kPrevCmd);
myPrevButton->clearFlags(Widget::FLAG_ENABLED);
wid.push_back(myPrevButton);
xpos += buttonWidth + 8;
xpos += buttonWidth + fontWidth;
myNextButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Next", GuiObject::kNextCmd);
wid.push_back(myNextButton);
xpos = _w - buttonWidth - 10;
xpos = _w - buttonWidth - HBORDER;
ButtonWidget* b =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Close", GuiObject::kCloseCmd);
wid.push_back(b);
addCancelWidget(b);
xpos = 5; ypos = 5 + _th;
xpos = HBORDER; ypos = _th + VBORDER;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2, fontHeight,
"", TextAlign::Center);
myTitle->setTextColor(kTextColorEm);
xpos = 16; ypos += lineHeight + 4;
xpos = HBORDER * 2; ypos += lineHeight + VGAP * 2;
for(int i = 0; i < myLinesPerPage; i++)
{
myDesc.push_back(new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2,

View File

@ -40,12 +40,14 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent, font, "Audio settings")
{
const int VBORDER = 10;
const int HBORDER = 10;
const int INDENT = 20;
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
int lwidth = font.getStringWidth("Volume "),
pwidth;
@ -64,7 +66,7 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
"Enable sound", kSoundEnableChanged);
wid.push_back(mySoundEnableCheckbox);
ypos += lineHeight + VGAP;
xpos += INDENT;
xpos += CheckboxWidget::prefixSize(font);
// Volume
myVolumeSlider = new SliderWidget(this, font, xpos, ypos,

View File

@ -42,13 +42,19 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
_h = max_h;
const int lineHeight = font.getLineHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4,
selectHeight = lineHeight + 12;
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() * 1.25,
buttonWidth = font.getStringWidth("Base Dir") + fontWidth * 2.5;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int BUTTON_GAP = fontWidth;
const int selectHeight = lineHeight + VGAP * 3;
int xpos, ypos;
ButtonWidget* b;
xpos = 10; ypos = 4 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
// Current path - TODO: handle long paths ?
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Path ");
@ -56,14 +62,14 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
_w - t->getWidth() - 2 * xpos, lineHeight);
_currentPath->setEditable(false);
// Add file list
ypos += lineHeight + 8;
ypos += lineHeight + VGAP * 2;
_fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos,
_h - selectHeight - buttonHeight - ypos - 20);
_h - selectHeight - buttonHeight - ypos - VBORDER * 2);
_fileList->setEditable(false);
addFocusWidget(_fileList);
// Add currently selected item
ypos += _fileList->getHeight() + 8;
ypos += _fileList->getHeight() + VGAP * 2;
_type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name ");
_selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos,
@ -71,30 +77,30 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
_selected->setEditable(false);
// Buttons
_goUpButton = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
_goUpButton = new ButtonWidget(this, font, xpos, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Go up", kGoUpCmd);
addFocusWidget(_goUpButton);
_basedirButton =
new ButtonWidget(this, font, 15 + buttonWidth, _h - buttonHeight - 10,
new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd);
addFocusWidget(_basedirButton);
#ifndef BSPF_MACOS
b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10,
b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Choose", kChooseCmd);
addFocusWidget(b);
addOKWidget(b);
b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10,
b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Cancel", GuiObject::kCloseCmd);
addFocusWidget(b);
addCancelWidget(b);
#else
b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10,
b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Cancel", GuiObject::kCloseCmd);
addFocusWidget(b);
addCancelWidget(b);
b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10,
b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Choose", kChooseCmd);
addFocusWidget(b);
addOKWidget(b);

View File

@ -29,7 +29,7 @@ CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font,
// rowheight is determined by largest item on a line,
// possibly meaning that number of rows will change
_fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize());
_fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize(_font));
_rows = h / _fontHeight;
// Create a CheckboxWidget for each row in the list
@ -100,7 +100,7 @@ void CheckListWidget::drawWidget(bool hilite)
// Draw a thin frame around the list and to separate columns
s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor);
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
s.vLine(_x + CheckboxWidget::boxSize(_font) + 5, _y, _y + _h - 1, kColor);
// Draw the list items
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++)
@ -150,7 +150,7 @@ void CheckListWidget::drawWidget(bool hilite)
Common::Rect CheckListWidget::getEditRect() const
{
const int yoffset = (_selectedItem - _currentPos) * _fontHeight,
xoffset = CheckboxWidget::boxSize() + 10;
xoffset = CheckboxWidget::boxSize(_font) + 10;
return Common::Rect(2 + xoffset, 1 + yoffset,
_w - (xoffset - 15), _fontHeight + yoffset);

View File

@ -32,7 +32,14 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
: Dialog(boss->instance(), boss->parent(), font, "Add...")
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth();
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
@ -42,10 +49,10 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
pwidth = std::max(font.getStringWidth(s.first), pwidth);
// Set real dimensions
_w = 11 * fontWidth + pwidth-4 + 10 * 2;
_h = 10 * (lineHeight + 4) + 10 + _th;
xpos = 10;
ypos = 10 + _th;
_w = 8 * fontWidth + pwidth + PopUpWidget::dropDownWidth(font) + HBORDER * 2;
_h = 8 * (lineHeight + VGAP) + VGAP + buttonHeight + VBORDER * 2 + _th;
xpos = HBORDER;
ypos = VBORDER + _th;
// Add event popup for 8 events
myEvents.fill(nullptr);
@ -54,7 +61,7 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
myEvents[idx] = new PopUpWidget(this, font, xpos, ypos,
pwidth, lineHeight, combolist, label);
wid.push_back(myEvents[idx]);
ypos += lineHeight + 4;
ypos += lineHeight + VGAP;
};
ADD_EVENT_POPUP(0, "Event 1 ");
ADD_EVENT_POPUP(1, "Event 2 ");

View File

@ -33,16 +33,19 @@
CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
: Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands")
{
const int HBORDER = 10;
const int VBORDER = 10;
const int HGAP = 8;
const int VGAP = 4;
const int buttonWidth = _font.getStringWidth("Time Machine On") + 16,
buttonHeight = _font.getLineHeight() + 6,
rowHeight = buttonHeight + VGAP;
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth(),
buttonHeight = _font.getLineHeight() * 1.25,
buttonWidth = _font.getStringWidth("Time Machine On") + fontWidth * 2;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int HGAP = fontWidth;
const int rowHeight = buttonHeight + VGAP;
// Set real dimensions
_w = 3 * (buttonWidth + 5) + HBORDER * 2;
_w = 3 * (buttonWidth + HGAP) - HGAP + HBORDER * 2;
_h = 6 * rowHeight - VGAP + VBORDER * 2 + _th;
ButtonWidget* bw = nullptr;
WidgetArray wid;

View File

@ -23,6 +23,7 @@
#include "Dialog.hxx"
#include "DialogContainer.hxx"
#include "ScrollBarWidget.hxx"
#include "PopUpWidget.hxx"
#include "ContextMenu.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -35,6 +36,7 @@ ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font,
_maxWidth(width)
{
addItems(items);
setArrows();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -49,7 +51,7 @@ void ContextMenu::addItems(const VariantList& items)
maxwidth = std::max(maxwidth, _font.getStringWidth(e.first));
_x = _y = 0;
_w = maxwidth + 23;
_w = maxwidth + PopUpWidget::dropDownWidth(_font); // 23;
_h = 1; // recalculate this in ::recalc()
_scrollUpColor = _firstEntry > 0 ? kScrollColor : kColor;
@ -509,7 +511,7 @@ void ContextMenu::scrollDown(int distance)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::drawDialog()
void ContextMenu::setArrows()
{
static constexpr std::array<uInt32, 8> up_arrow = {
0b00011000,
@ -532,6 +534,55 @@ void ContextMenu::drawDialog()
0b00011000
};
static constexpr std::array<uInt32, 12> up_arrow_large = {
0b000001100000,
0b000001100000,
0b000011110000,
0b000011110000,
0b000111111000,
0b000111111000,
0b001111111100,
0b001111111100,
0b011111111110,
0b011111111110,
0b111111111111,
0b111111111111
};
static constexpr std::array<uInt32, 12> down_arrow_large = {
0b111111111111,
0b111111111111,
0b011111111110,
0b011111111110,
0b001111111100,
0b001111111100,
0b000111111000,
0b000111111000,
0b000011110000,
0b000011110000,
0b000001100000,
0b000001100000
};
if(_font.getFontHeight() < 24)
{
_textOfs = 2;
_arrowSize = 8;
_upImg = up_arrow.data();
_downImg = down_arrow.data();
}
else
{
_textOfs = 4;
_arrowSize = 12;
_upImg = up_arrow_large.data();
_downImg = down_arrow_large.data();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::drawDialog()
{
// Normally we add widgets and let Dialog::draw() take care of this
// logic. But for some reason, this Dialog was written differently
// by the ScummVM guys, so I'm not going to mess with it.
@ -549,7 +600,7 @@ void ContextMenu::drawDialog()
if(_showScroll)
{
s.hLine(x, y+_rowHeight-1, w+2, kColor);
s.drawBitmap(up_arrow.data(), ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
s.drawBitmap(_upImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, _arrowSize);
y += _rowHeight;
offset--;
}
@ -558,7 +609,7 @@ 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,
s.drawString(_font, _entries[i].first, x + _textOfs, y + 2, w,
!hilite ? kTextColor : kTextColorInv);
y += _rowHeight;
}
@ -567,7 +618,7 @@ void ContextMenu::drawDialog()
if(_showScroll)
{
s.hLine(x, y, w+2, kColor);
s.drawBitmap(down_arrow.data(), ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
s.drawBitmap(_downImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, _arrowSize);
}
setDirty();

View File

@ -95,6 +95,7 @@ class ContextMenu : public Dialog, public CommandSender
bool handleJoyHat(int stick, int hat, JoyHatDir vahdirlue, int button) override;
void handleEvent(Event::Type e);
void setArrows();
void drawDialog() override;
void recalc(const Common::Rect& image);
@ -129,6 +130,11 @@ class ContextMenu : public Dialog, public CommandSender
uInt32 _xorig{0}, _yorig{0};
uInt32 _maxWidth{0};
int _textOfs{0};
int _arrowSize{0};
const uInt32* _upImg{nullptr};
const uInt32* _downImg{nullptr};
private:
// Following constructors and assignment operators not supported
ContextMenu() = delete;

View File

@ -48,18 +48,27 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Developer settings")
{
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() + 4;
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
// Set real dimensions
setSize(54 * fontWidth + 10, 16 * (lineHeight + VGAP) + 14 + _th, max_w, max_h);
setSize(53 * fontWidth + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
max_w, max_h);
// The tab widget
xpos = 2; ypos = 4;
myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2 * xpos, _h - _th - buttonHeight - 16 - ypos);
xpos = 2; ypos = VGAP;
myTab = new TabWidget(this, font, xpos, ypos + _th,
_w - 2 * xpos,
_h - _th - VGAP - buttonHeight - VBORDER * 2);
addTabWidget(myTab);
addEmulationTab(font);
@ -79,12 +88,16 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addEmulationTab(const GUI::Font& font)
{
const int HBORDER = 10;
const int INDENT = 16+4;
const int VBORDER = 8;
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int ypos = VBORDER;
int lineHeight = font.getLineHeight();
WidgetArray wid;
VariantList items;
int tabID = myTab->addTab(" Emulation ", TabWidget::AUTO_WIDTH);
@ -136,13 +149,13 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
myRandomizeCPULabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, "Randomize CPU ");
wid.push_back(myRandomizeCPULabel);
int xpos = myRandomizeCPULabel->getRight() + 10;
int xpos = myRandomizeCPULabel->getRight() + fontWidth * 1.25;
for(int i = 0; i < 5; ++i)
{
myRandomizeCPUWidget[i] = new CheckboxWidget(myTab, font, xpos, ypos + 1,
ourCPUregs[i], kRandCPUID);
wid.push_back(myRandomizeCPUWidget[i]);
xpos += CheckboxWidget::boxSize() + font.getStringWidth("XX") + 20;
xpos += CheckboxWidget::boxSize(font) + font.getStringWidth("XX") + fontWidth * 2.5;
}
ypos += lineHeight + VGAP;
@ -182,12 +195,16 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addTiaTab(const GUI::Font& font)
{
const int HBORDER = 10;
const int INDENT = 16 + 4;
const int VBORDER = 8;
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int ypos = VBORDER;
int lineHeight = font.getLineHeight();
int pwidth = font.getStringWidth("Faulty Cosmic Ark stars");
WidgetArray wid;
VariantList items;
@ -268,13 +285,16 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addVideoTab(const GUI::Font& font)
{
const int HBORDER = 10;
const int INDENT = 16 + 4;
const int VBORDER = 8;
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int ypos = VBORDER;
int lineHeight = font.getLineHeight();
int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight();
int lwidth = font.getStringWidth("Intensity ");
int pwidth = font.getMaxCharWidth() * 6;
WidgetArray wid;
@ -340,7 +360,7 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
myDbgColour[idx] = new PopUpWidget(myTab, font, x, ypos - 1,
pwidth, lineHeight, items, desc, lwidth, dbg_cmds[idx]);
wid.push_back(myDbgColour[idx]);
x += myDbgColour[idx]->getWidth() + 10;
x += myDbgColour[idx]->getWidth() + fontWidth * 1.25;
myDbgColourSwatch[idx] = new ColorWidget(myTab, font, x, ypos - 1,
uInt32(2 * lineHeight), lineHeight);
ypos += lineHeight + VGAP * 1;
@ -355,8 +375,11 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
// Add message concerning usage
const GUI::Font& infofont = instance().frameBuffer().infoFont();
ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10;
new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Colors identical for player and developer settings");
ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER;
lwidth = infofont.getStringWidth("(*) Colors identical for player and developer settings");
new StaticTextWidget(myTab, infofont, HBORDER, ypos,
std::min(lwidth, _w - HBORDER * 2), infofont.getFontHeight(),
"(*) Colors identical for player and developer settings");
// Add items for tab 2
addToFocusList(wid, myTab, tabID);
@ -403,37 +426,42 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
"30m",
"60m"
};
const int HBORDER = 10;
const int INDENT = 16+4;
const int VBORDER = 8;
const int VGAP = 4;
int ypos = VBORDER;
int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
lwidth = fontWidth * 11;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos = HBORDER,
ypos = VBORDER,
lwidth = fontWidth * 11;
WidgetArray wid;
VariantList items;
int tabID = myTab->addTab(" Time Machine ", TabWidget::AUTO_WIDTH);
// settings set
mySettingsGroupTM = new RadioButtonGroup();
RadioButtonWidget* r = new RadioButtonWidget(myTab, font, HBORDER, ypos + 1,
RadioButtonWidget* r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
"Player settings", mySettingsGroupTM, kPlrSettings);
wid.push_back(r);
ypos += lineHeight + VGAP;
r = new RadioButtonWidget(myTab, font, HBORDER, ypos + 1,
r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
"Developer settings", mySettingsGroupTM, kDevSettings);
wid.push_back(r);
xpos += INDENT;
ypos += lineHeight + VGAP * 1;
myTimeMachineWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT, ypos + 1,
myTimeMachineWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1,
"Time Machine", kTimeMachine);
wid.push_back(myTimeMachineWidget);
xpos += CheckboxWidget::prefixSize(font);
ypos += lineHeight + VGAP;
int swidth = fontWidth * 12 + 5; // width of PopUpWidgets below
myStateSizeWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight,
myStateSizeWidget = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight,
"Buffer size (*) ", 0, kSizeChanged, lwidth, " states");
myStateSizeWidget->setMinValue(20);
#ifdef RETRON77
@ -446,7 +474,7 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
wid.push_back(myStateSizeWidget);
ypos += lineHeight + VGAP;
myUncompressedWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight,
myUncompressedWidget = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight,
"Uncompressed size ", 0, kUncompressedChanged, lwidth, " states");
myUncompressedWidget->setMinValue(0);
#ifdef RETRON77
@ -463,7 +491,7 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
for(int i = 0; i < NUM_INTERVALS; ++i)
VarList::push_back(items, INTERVALS[i], INT_SETTINGS[i]);
int pwidth = font.getStringWidth("10 seconds");
myStateIntervalWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth,
myStateIntervalWidget = new PopUpWidget(myTab, font, xpos, ypos, pwidth,
lineHeight, items, "Interval ", 0, kIntervalChanged);
wid.push_back(myStateIntervalWidget);
ypos += lineHeight + VGAP;
@ -471,37 +499,42 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
items.clear();
for(int i = 0; i < NUM_HORIZONS; ++i)
VarList::push_back(items, HORIZONS[i], HOR_SETTINGS[i]);
myStateHorizonWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth,
myStateHorizonWidget = new PopUpWidget(myTab, font, xpos, ypos, pwidth,
lineHeight, items, "Horizon ~ ", 0, kHorizonChanged);
wid.push_back(myStateHorizonWidget);
xpos = HBORDER + INDENT;
ypos += lineHeight + VGAP * 2;
new StaticTextWidget(myTab, font, HBORDER, ypos + 1,
"When entering/exiting emulation:");
ypos += lineHeight + VGAP;
mySaveOnExitGroup = new RadioButtonGroup();
r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1,
r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
"Do nothing", mySaveOnExitGroup);
wid.push_back(r);
ypos += lineHeight + VGAP;
r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1,
r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
"Save current state in current slot", mySaveOnExitGroup);
wid.push_back(r);
ypos += lineHeight + VGAP;
r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1,
r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
"Load/save all Time Machine states", mySaveOnExitGroup);
wid.push_back(r);
ypos += lineHeight + VGAP;
xpos = HBORDER;
myAutoSlotWidget = new CheckboxWidget(myTab, font, HBORDER, ypos + 1, "Automatically change save state slots");
myAutoSlotWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Automatically change save state slots");
wid.push_back(myAutoSlotWidget);
ypos += lineHeight + VGAP;
// Add message concerning usage
const GUI::Font& infofont = instance().frameBuffer().infoFont();
ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10;
new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Any size change clears the buffer");
ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER;
lwidth = infofont.getStringWidth("(*) Any size change clears the buffer");
new StaticTextWidget(myTab, infofont, HBORDER, ypos,
std::min(lwidth, _w - HBORDER * 2), infofont.getFontHeight(),
"(*) Any size change clears the buffer");
addToFocusList(wid, myTab, tabID);
}
@ -513,14 +546,16 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
WidgetArray wid;
#ifdef DEBUGGER_SUPPORT
const int HBORDER = 10;
const int VBORDER = 8;
const int VGAP = 4;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
VariantList items;
int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight();
int xpos, ypos, pwidth;
const Common::Size& ds = instance().frameBuffer().desktopSize();
@ -537,7 +572,7 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
new PopUpWidget(myTab, font, HBORDER, ypos + 1, pwidth, lineHeight, items,
"Font size (*) ", 0, kDFontSizeChanged);
wid.push_back(myDebuggerFontSize);
ypos += lineHeight + 4;
ypos += lineHeight + VGAP;
// Font style (bold label vs. text, etc)
items.clear();
@ -580,8 +615,8 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
// Add message concerning usage
const GUI::Font& infofont = instance().frameBuffer().infoFont();
ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10;
new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Changes require a ROM reload");
ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER;
new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Change requires a ROM reload");
#if defined(DEBUGGER_SUPPORT) && defined(WINDOWED_SUPPORT)
// Debugger is only realistically available in windowed modes 800x600 or greater

View File

@ -139,7 +139,7 @@ void Dialog::setTitle(const string& title)
if(title.empty())
_th = 0;
else
_th = _font.getLineHeight() + 4;
_th = _font.getLineHeight() * 1.25;
_h += _th;
}
@ -383,7 +383,8 @@ void Dialog::drawDialog()
if(_th)
{
s.fillRect(_x, _y, _w, _th, _onTop ? kColorTitleBar : kColorTitleBarLo);
s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
s.drawString(_font, _title, _x + _font.getMaxCharWidth() * 1.25, _y + _font.getFontHeight() / 6,
_font.getStringWidth(_title),
_onTop ? kColorTitleText : kColorTitleTextLo);
}
}
@ -771,15 +772,18 @@ void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText, const string& cancelText,
bool focusOKButton, int buttonWidth)
{
const int HBORDER = 10;
const int VBORDER = 10;
const int BTN_BORDER = 20;
const int BUTTON_GAP = 8;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int BTN_BORDER = fontWidth * 2.5;
const int BUTTON_GAP = fontWidth;
buttonWidth = std::max(buttonWidth,
std::max(font.getStringWidth("Defaults"),
std::max(font.getStringWidth(okText),
font.getStringWidth(cancelText))) + BTN_BORDER);
int buttonHeight = font.getLineHeight() + 4;
_w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w);
@ -817,11 +821,14 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
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;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int BTN_BORDER = fontWidth * 2.5;
const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER;
addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd));

View File

@ -29,6 +29,15 @@ EditTextWidget::EditTextWidget(GuiObject* boss, const GUI::Font& font,
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
EditableWidget::startEditMode(); // We're always in edit mode
if(_font.getFontHeight() < 24)
{
_textOfs = 3;
}
else
{
_textOfs = 5;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -92,7 +101,7 @@ void EditTextWidget::drawWidget(bool hilite)
// Draw the text
adjustOffset();
s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().w(), getEditRect().h(),
s.drawString(_font, editString(), _x + _textOfs, _y + 2, getEditRect().w(), getEditRect().h(),
_changed && onTop && isEnabled()
? kDbgChangedTextColor
: onTop && isEnabled() ? _textcolor : kColor,
@ -105,7 +114,7 @@ void EditTextWidget::drawWidget(bool hilite)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Common::Rect EditTextWidget::getEditRect() const
{
return Common::Rect(2, 1, _w - 2, _h);
return Common::Rect(_textOfs, 1, _w - _textOfs, _h);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -32,6 +32,18 @@ class EditTextWidget : public EditableWidget
void setText(const string& str, bool changed = false) override;
// Get total width of widget
static int calcWidth(const GUI::Font& font, int length = 0)
{
return length * font.getMaxCharWidth()
+ (font.getFontHeight() < 24 ? 3 * 2 : 5 * 2);
}
// Get total width of widget
static int calcWidth(const GUI::Font& font, const string& str)
{
return calcWidth(font, int(str.length()));
}
protected:
void drawWidget(bool hilite) override;
void lostFocusWidget() override;
@ -49,6 +61,7 @@ class EditTextWidget : public EditableWidget
protected:
string _backupString;
bool _changed{false};
int _textOfs{0};
private:
// Following constructors and assignment operators not supported

View File

@ -44,13 +44,15 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
{
const int fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
buttonWidth = font.getStringWidth("Defaults") + 10,
buttonHeight = font.getLineHeight() + 4;
const int HBORDER = 8;
const int VBORDER = 8;
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Defaults") + fontWidth * 1.25,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int ACTION_LINES = 2;
int xpos = HBORDER, ypos = VBORDER;
const int listWidth = _w - buttonWidth - HBORDER * 2 - 8;
const int listWidth = _w - buttonWidth - HBORDER * 2 - fontWidth;
int listHeight = _h - (2 + ACTION_LINES) * lineHeight - VBORDER + 2;
if(mode == EventMode::kEmulationMode)
@ -70,12 +72,12 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
VarList::push_back(items, "Debug", Event::Group::Debug);
myFilterPopup = new PopUpWidget(boss, font, xpos, ypos,
listWidth - font.getStringWidth("Events ") - 23, lineHeight,
items, "Events ", 0, kFilterCmd);
listWidth - font.getStringWidth("Events ") - PopUpWidget::dropDownWidth(font),
lineHeight, items, "Events ", 0, kFilterCmd);
myFilterPopup->setTarget(this);
addFocusWidget(myFilterPopup);
ypos += lineHeight + 8;
listHeight -= lineHeight + 8;
ypos += lineHeight * 1.5;
listHeight -= lineHeight * 1.5;
}
myActionsList = new StringListWidget(boss, font, xpos, ypos, listWidth, listHeight);
@ -91,7 +93,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
myMapButton->setTarget(this);
addFocusWidget(myMapButton);
ypos += lineHeight + 10;
ypos += buttonHeight + VGAP;
myCancelMapButton = new ButtonWidget(boss, font, xpos, ypos,
buttonWidth, buttonHeight,
"Cancel", kStopMapCmd);
@ -99,14 +101,14 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
myCancelMapButton->clearFlags(Widget::FLAG_ENABLED);
addFocusWidget(myCancelMapButton);
ypos += lineHeight + 20;
ypos += buttonHeight + VGAP * 2;
myEraseButton = new ButtonWidget(boss, font, xpos, ypos,
buttonWidth, buttonHeight,
"Erase", kEraseCmd);
myEraseButton->setTarget(this);
addFocusWidget(myEraseButton);
ypos += lineHeight + 10;
ypos += buttonHeight + VGAP;
myResetButton = new ButtonWidget(boss, font, xpos, ypos,
buttonWidth, buttonHeight,
"Reset", kResetCmd);
@ -115,7 +117,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
if(mode == EventMode::kEmulationMode)
{
ypos += lineHeight + 20;
ypos += buttonHeight + VGAP * 2;
myComboButton = new ButtonWidget(boss, font, xpos, ypos,
buttonWidth, buttonHeight,
"Combo" + ELLIPSIS, kComboCmd);
@ -128,13 +130,13 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
// Show message for currently selected event
xpos = HBORDER;
ypos = myActionsList->getBottom() + 8;
ypos = myActionsList->getBottom() + VGAP * 2;
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() - 8 - HBORDER,
myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + fontWidth, ypos,
_w - xpos - t->getWidth() - fontWidth - HBORDER + 2,
lineHeight + font.getFontHeight() * (ACTION_LINES - 1), "");
myKeyMapping->setEditable(false, true);
myKeyMapping->clearFlags(Widget::FLAG_RETAIN_FOCUS);

View File

@ -52,14 +52,16 @@ GameInfoDialog::GameInfoDialog(
CommandSender(boss)
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() + 4,
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25,
infoLineHeight = ifont.getLineHeight();
const int VBORDER = 8;
const int HBORDER = 10;
const int VGAP = 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos, lwidth, fwidth, pwidth, tabID;
WidgetArray wid;
@ -67,19 +69,20 @@ GameInfoDialog::GameInfoDialog(
StaticTextWidget* t;
// Set real dimensions
setSize(55 * fontWidth + 8,
8 * (lineHeight + VGAP) + 1 * (infoLineHeight + VGAP) + VBORDER * 2 + _th +
buttonHeight + fontHeight + ifont.getLineHeight() + 20,
setSize(54 * fontWidth + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 8 * (lineHeight + VGAP) + 1 * (infoLineHeight + VGAP) +
ifont.getLineHeight() + VGAP + buttonHeight + VBORDER * 2,
max_w, max_h);
// The tab widget
myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2 * 2,
_h - (_th + buttonHeight + 20));
myTab = new TabWidget(this, font, 2, 4 + _th,
_w - 2 * 2,
_h - _th - VGAP - buttonHeight - VBORDER * 2);
addTabWidget(myTab);
//////////////////////////////////////////////////////////////////////////////
// 1) Emulation properties
tabID = myTab->addTab("Emulation");
tabID = myTab->addTab(" Emulation ", TabWidget::AUTO_WIDTH);
ypos = VBORDER;
@ -88,12 +91,12 @@ GameInfoDialog::GameInfoDialog(
items.clear();
for(uInt32 i = 0; i < uInt32(Bankswitch::Type::NumSchemes); ++i)
VarList::push_back(items, Bankswitch::BSList[i].desc, Bankswitch::BSList[i].name);
myBSType = new PopUpWidget(myTab, font, t->getRight() + 8, ypos,
myBSType = new PopUpWidget(myTab, font, t->getRight() + fontWidth, ypos,
pwidth, lineHeight, items, "");
wid.push_back(myBSType);
ypos += lineHeight + VGAP;
myTypeDetected = new StaticTextWidget(myTab, ifont, t->getRight() + 8, ypos,
myTypeDetected = new StaticTextWidget(myTab, ifont, t->getRight() + fontWidth, ypos,
"CM (SpectraVideo CompuMate) detected");
ypos += ifont.getLineHeight() + VGAP;
@ -119,7 +122,7 @@ GameInfoDialog::GameInfoDialog(
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myFormat);
myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + 8, ypos + 4,
myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + fontWidth, ypos + 4,
"SECAM60 detected");
// Phosphor
@ -130,7 +133,7 @@ GameInfoDialog::GameInfoDialog(
ypos += lineHeight + VGAP * 0;
myPPBlend = new SliderWidget(myTab, font,
HBORDER + 20, ypos,
HBORDER + fontWidth * 2, ypos,
"Blend ", 0, kPPBlendChanged, 4 * fontWidth, "%");
myPPBlend->setMinValue(0); myPPBlend->setMaxValue(100);
myPPBlend->setTickmarkIntervals(2);
@ -138,7 +141,7 @@ GameInfoDialog::GameInfoDialog(
ypos += lineHeight + VGAP;
t = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "V-Center ");
myVCenter = new SliderWidget(myTab, font, t->getRight() + 2, ypos, "",
myVCenter = new SliderWidget(myTab, font, t->getRight(), ypos, "",
0, kVCenterChanged, 7 * fontWidth, "px", 0, true);
myVCenter->setMinValue(TIAConstants::minVcenter);
@ -151,9 +154,9 @@ GameInfoDialog::GameInfoDialog(
wid.push_back(mySound);
// Add message concerning usage
ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10;
ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER;
new StaticTextWidget(myTab, ifont, HBORDER, ypos,
"(*) Changes require a ROM reload");
"(*) Change requires a ROM reload");
// Add items for tab 0
addToFocusList(wid, myTab, tabID);
@ -161,7 +164,7 @@ GameInfoDialog::GameInfoDialog(
//////////////////////////////////////////////////////////////////////////////
// 2) Console properties
wid.clear();
tabID = myTab->addTab("Console");
tabID = myTab->addTab(" Console ", TabWidget::AUTO_WIDTH);
xpos = HBORDER; ypos = VBORDER;
lwidth = font.getStringWidth(GUI::RIGHT_DIFFICULTY + " ");
@ -204,7 +207,7 @@ GameInfoDialog::GameInfoDialog(
//////////////////////////////////////////////////////////////////////////////
// 3) Controller properties
wid.clear();
tabID = myTab->addTab("Controllers");
tabID = myTab->addTab(" Controllers ", TabWidget::AUTO_WIDTH);
ctrls.clear();
VarList::push_back(ctrls, "Auto-detect", "AUTO");
@ -271,7 +274,7 @@ GameInfoDialog::GameInfoDialog(
myPaddlesCenter = new StaticTextWidget(myTab, font, xpos, ypos, "Paddles center:");
ypos += lineHeight + VGAP;
xpos += 20;
xpos += INDENT;
myPaddleXCenter = new SliderWidget(myTab, font, xpos, ypos - 1, "X ", 0, kPXCenterChanged,
fontWidth * 6, "px", 0 ,true);
myPaddleXCenter->setMinValue(Paddles::MIN_ANALOG_CENTER);
@ -288,7 +291,7 @@ GameInfoDialog::GameInfoDialog(
wid.push_back(myPaddleYCenter);
// Mouse
xpos = HBORDER + fontWidth * 24 - 20;
xpos = HBORDER + fontWidth * 24 - INDENT;
ypos = myPaddlesCenter->getTop();
myMouseControl = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Specific mouse axes",
kMCtrlChanged);
@ -307,7 +310,7 @@ GameInfoDialog::GameInfoDialog(
VarList::push_back(items, "MindLink 0", static_cast<uInt32>(MouseControl::Type::MindLink0));
VarList::push_back(items, "MindLink 1", static_cast<uInt32>(MouseControl::Type::MindLink1));
xpos += 20;
xpos += CheckboxWidget::prefixSize(font);
ypos += lineHeight + VGAP;
myMouseX = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
"X-Axis is ");
@ -318,7 +321,7 @@ GameInfoDialog::GameInfoDialog(
"Y-Axis is ");
wid.push_back(myMouseY);
xpos -= 20; ypos += lineHeight + VGAP;
xpos -= CheckboxWidget::prefixSize(font); ypos += lineHeight + VGAP;
myMouseRange = new SliderWidget(myTab, font, xpos, ypos,
"Mouse axes range ", 0, 0, fontWidth * 4, "%");
myMouseRange->setMinValue(1); myMouseRange->setMaxValue(100);
@ -331,7 +334,7 @@ GameInfoDialog::GameInfoDialog(
//////////////////////////////////////////////////////////////////////////////
// 4) Cartridge properties
wid.clear();
tabID = myTab->addTab("Cartridge");
tabID = myTab->addTab(" Cartridge ", TabWidget::AUTO_WIDTH);
xpos = HBORDER; ypos = VBORDER;
lwidth = font.getStringWidth("Manufacturer ");

View File

@ -36,20 +36,25 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() + 4;
buttonHeight = lineHeight * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
int lwidth = font.getStringWidth("Right difficulty "),
pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)");
const int VGAP = 4;
WidgetArray wid;
VariantList items;
const GUI::Font& infofont = instance().frameBuffer().infoFont();
// Set real dimensions
_w = lwidth + pwidth + fontWidth*3 + 15;
_h = 15 * (lineHeight + 4) + buttonHeight + 16 + _th;
_w = HBORDER * 2 + std::max(lwidth + pwidth + PopUpWidget::dropDownWidth(font),
49 * infofont.getMaxCharWidth());
_h = _th + 11 * (lineHeight + VGAP) + 3 * infofont.getLineHeight() + VGAP * 12 + buttonHeight + VBORDER * 2;
xpos = 10; ypos = 10 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
// Bankswitch type
new StaticTextWidget(this, font, xpos, ypos+1, "Bankswitch type");
@ -112,12 +117,12 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
"(automatically released shortly after start)");
// Start with console joystick direction/buttons held down
xpos = 32; ypos += infofont.getLineHeight() + VGAP * 2;
xpos = fontWidth * 4; ypos += infofont.getLineHeight() + VGAP * 2;
ypos = addHoldWidgets(font, xpos, ypos, wid);
// Add message concerning usage
xpos = 10; ypos += 2 * fontHeight;
ypos = _h - fontHeight * 2 - infofont.getLineHeight() - 24;
xpos = HBORDER;
ypos = _h - VBORDER - buttonHeight - VGAP * 3 - infofont.getLineHeight() * 2;
new StaticTextWidget(this, infofont, xpos, ypos,
"(*) These options are not saved, but apply to all");
ypos += infofont.getLineHeight();
@ -134,21 +139,24 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y,
WidgetArray& wid)
{
int xpos = x, ypos = y;
const int VGAP = 4;
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight();
const int VGAP = fontHeight / 4;
int xpos = x, ypos = y, xdiff = CheckboxWidget::boxSize(font) - 9;
// Left joystick
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Left joy");
xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP;
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Left joy");
xpos += t->getWidth()/2 - xdiff - 2; ypos += t->getHeight() + VGAP;
myJoy[kJ0Up] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Up);
ypos += myJoy[kJ0Up]->getHeight() * 2 + VGAP * 2;
myJoy[kJ0Down] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Down);
xpos -= myJoy[kJ0Up]->getWidth() + 5;
xpos -= myJoy[kJ0Up]->getWidth() + xdiff;
ypos -= myJoy[kJ0Up]->getHeight() + VGAP;
myJoy[kJ0Left] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Left);
xpos += (myJoy[kJ0Up]->getWidth() + 5) * 2;
xpos += (myJoy[kJ0Up]->getWidth() + xdiff) * 2;
myJoy[kJ0Right] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Right);
xpos -= (myJoy[kJ0Up]->getWidth() + 5) * 2;
xpos -= (myJoy[kJ0Up]->getWidth() + xdiff) * 2;
ypos += myJoy[kJ0Down]->getHeight() * 2 + VGAP * 2;
myJoy[kJ0Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire", kJ0Fire);
@ -157,20 +165,20 @@ int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y,
// Right joystick
t = new StaticTextWidget(this, font, xpos, ypos + 2, "Right joy");
xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP;
xpos += t->getWidth()/2 - xdiff - 2; ypos += t->getHeight() + VGAP;
myJoy[kJ1Up] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Up);
ypos += myJoy[kJ1Up]->getHeight() * 2 + VGAP * 2;
myJoy[kJ1Down] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Down);
xpos -= myJoy[kJ1Up]->getWidth() + 5;
xpos -= myJoy[kJ1Up]->getWidth() + xdiff;
ypos -= myJoy[kJ1Up]->getHeight() + VGAP;
myJoy[kJ1Left] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Left);
xpos += (myJoy[kJ1Up]->getWidth() + 5) * 2;
xpos += (myJoy[kJ1Up]->getWidth() + xdiff) * 2;
myJoy[kJ1Right] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Right);
xpos -= (myJoy[kJ1Up]->getWidth() + 5) * 2;
xpos -= (myJoy[kJ1Up]->getWidth() + xdiff) * 2;
ypos += myJoy[kJ1Down]->getHeight() * 2 + VGAP * 2;
myJoy[kJ1Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire", kJ1Fire);
xpos = 2 * _w / 3 + 8; ypos = y;
xpos = 2 * _w / 3 + fontWidth; ypos = y;
// Console Select/Reset
t = new StaticTextWidget(this, font, xpos, ypos+2, "Console");

View File

@ -31,49 +31,55 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
// Set real dimensions
_w = 46 * fontWidth + 10;
_h = 12 * lineHeight + 20 + _th;
_w = 46 * fontWidth + HBORDER * 2;
_h = _th + 11 * lineHeight + VGAP * 3 + buttonHeight + VBORDER * 2;
// Add Previous, Next and Close buttons
xpos = 10; ypos = _h - buttonHeight - 10;
xpos = HBORDER; ypos = _h - buttonHeight - VBORDER;
myPrevButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Previous", GuiObject::kPrevCmd);
myPrevButton->clearFlags(Widget::FLAG_ENABLED);
wid.push_back(myPrevButton);
xpos += buttonWidth + 8;
xpos += buttonWidth + fontWidth;
myNextButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Next", GuiObject::kNextCmd);
wid.push_back(myNextButton);
xpos = _w - buttonWidth - 10;
xpos = _w - buttonWidth - HBORDER;
ButtonWidget* b =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Close", GuiObject::kCloseCmd);
wid.push_back(b);
addCancelWidget(b);
xpos = 5; ypos = 5 + _th;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - 10, fontHeight,
xpos = HBORDER; ypos = VBORDER + _th;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2, fontHeight,
"", TextAlign::Center);
myTitle->setTextColor(kTextColorEm);
int lwidth = 13 * fontWidth;
xpos += 5; ypos += lineHeight + 4;
for(uInt8 i = 0; i < LINES_PER_PAGE; ++i)
int lwidth = 15 * fontWidth;
ypos += lineHeight + VGAP * 2;
for(int i = 0; i < LINES_PER_PAGE; ++i)
{
myKey[i] =
new StaticTextWidget(this, font, xpos, ypos, lwidth,
fontHeight, "", TextAlign::Left);
myDesc[i] =
new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - 5,
new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - HBORDER,
fontHeight, "", TextAlign::Left);
ypos += fontHeight;
}
@ -158,7 +164,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title)
case 5:
title = "All other commands";
ADD_LINE();
ADD_BIND("Remapped Even", "ts");
ADD_BIND("Remapped Events", "");
ADD_TEXT("Most other commands can be");
ADD_TEXT("remapped. Please consult the");
ADD_TEXT("'Options/Input" + ELLIPSIS + "' dialog for");

View File

@ -45,16 +45,23 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
{
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
buttonHeight = _font.getLineHeight() + 4;
const int vBorder = 4;
fontHeight = _font.getFontHeight(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int VGAP = fontHeight / 4;
const int HBORDER = fontWidth * 1.25;
int xpos, ypos, tabID;
// Set real dimensions
setSize(51 * fontWidth + 10, 17 * (lineHeight + 4) + 16 + _th, max_w, max_h);
setSize(50 * fontWidth + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + VGAP * 7 + buttonHeight + VBORDER * 3,
max_w, max_h);
// The tab widget
xpos = 2; ypos = vBorder + _th;
myTab = new TabWidget(this, _font, xpos, ypos, _w - 2*xpos, _h -_th - buttonHeight - 20);
xpos = 2; ypos = VGAP + _th;
myTab = new TabWidget(this, _font, xpos, ypos,
_w - 2*xpos,
_h -_th - VGAP - buttonHeight - VBORDER * 2);
addTabWidget(myTab);
// 1) Event mapper for emulation actions
@ -102,11 +109,11 @@ void InputDialog::addDevicePortTab()
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight();
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
int xpos, ypos, lwidth, tabID;
WidgetArray wid;
const int VGAP = 4;
const int VBORDER = 8;
const int HBORDER = 8;
// Devices/ports
tabID = myTab->addTab("Devices & Ports", TabWidget::AUTO_WIDTH);
@ -239,13 +246,14 @@ void InputDialog::addDevicePortTab()
void InputDialog::addMouseTab()
{
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth();
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight();
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
int ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
const int VGAP = 4;
const int VBORDER = 8;
const int HBORDER = 8;
// Mouse
tabID = myTab->addTab(" Mouse ", TabWidget::AUTO_WIDTH);

View File

@ -50,15 +50,20 @@ InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& lfont,
void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
const StringList& labels)
{
const int fontWidth = lfont.getMaxCharWidth(),
fontHeight = lfont.getFontHeight(),
lineHeight = lfont.getLineHeight();
const int lineHeight = lfont.getLineHeight(),
fontWidth = lfont.getMaxCharWidth(),
fontHeight = lfont.getFontHeight(),
buttonHeight = lfont.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
uInt32 xpos, ypos, i, lwidth = 0, maxIdx = 0;
WidgetArray wid;
// Calculate real dimensions
_w = fontWidth * 41;
_h = lineHeight * 4 + int(labels.size()) * (lineHeight + 5) + _th;
_w = HBORDER * 2 + fontWidth * 39;
_h = buttonHeight + lineHeight + VGAP + int(labels.size()) * (lineHeight + VGAP) + _th + VBORDER * 2;
// Determine longest label
for(i = 0; i < labels.size(); ++i)
@ -72,25 +77,25 @@ void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
lwidth = lfont.getStringWidth(labels[maxIdx]);
// Create editboxes for all labels
ypos = lineHeight + _th;
ypos = VBORDER + _th;
for(i = 0; i < labels.size(); ++i)
{
xpos = 10;
xpos = HBORDER;
new StaticTextWidget(this, lfont, xpos, ypos + 2,
lwidth, fontHeight,
labels[i], TextAlign::Left);
xpos += lwidth + fontWidth;
EditTextWidget* w = new EditTextWidget(this, nfont, xpos, ypos,
_w - xpos - 10, lineHeight, "");
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(w);
myInput.push_back(w);
ypos += lineHeight + 5;
ypos += lineHeight + VGAP;
}
xpos = 10;
myMessage = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2*xpos, fontHeight,
xpos = HBORDER; ypos += VGAP;
myMessage = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2 * xpos, fontHeight,
"", TextAlign::Left);
myMessage->setTextColor(kTextColorEm);

View File

@ -32,33 +32,40 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
int xpos, ypos;
WidgetArray wid;
int buttonWidth = font.getStringWidth("Remove ") + 20,
buttonHeight = font.getLineHeight() + 4;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Remove") + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
// Joystick list
xpos = 10; ypos = 10 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
int w = _w - 2 * xpos;
int h = _h - buttonHeight - ypos - 20;
int h = _h - buttonHeight - ypos - VBORDER * 2;
myJoyList = new StringListWidget(this, font, xpos, ypos, w, h);
myJoyList->setEditable(false);
wid.push_back(myJoyList);
// Joystick ID
ypos = _h - buttonHeight - 10;
ypos = _h - VBORDER - (buttonHeight + lineHeight) / 2;
StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Joystick ID ");
xpos += t->getWidth() + 4;
xpos += t->getWidth();
myJoyText = new EditTextWidget(this, font, xpos, ypos,
font.getStringWidth("Unplugged")+8, font.getLineHeight(), "");
font.getStringWidth("Unplugged "), font.getLineHeight(), "");
myJoyText->setEditable(false);
// Add buttons at bottom
xpos = _w - buttonWidth - 10;
xpos = _w - buttonWidth - HBORDER;
ypos = _h - VBORDER - buttonHeight;
myCloseBtn = new ButtonWidget(this, font, xpos, ypos,
buttonWidth, buttonHeight, "Close", GuiObject::kCloseCmd);
addOKWidget(myCloseBtn); addCancelWidget(myCloseBtn);
buttonWidth = font.getStringWidth("Remove") + 20;
xpos -= buttonWidth + 8;
xpos -= buttonWidth + fontWidth;
myRemoveBtn = new ButtonWidget(this, font, xpos, ypos,
buttonWidth, buttonHeight, "Remove", kRemoveCmd);
myRemoveBtn->clearFlags(Widget::FLAG_ENABLED);

View File

@ -60,25 +60,26 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
myUseMinimalUI = instance().settings().getBool("minimal_ui");
const GUI::Font& font = instance().frameBuffer().launcherFont();
const int HBORDER = 10;
const int BUTTON_GAP = 8;
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
bwidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)),
bheight = myUseMinimalUI ? lineHeight - 4 : lineHeight + 4,
LBL_GAP = fontWidth;
int xpos = 0, ypos = 0, lwidth = 0, lwidth2 = 0;
WidgetArray wid;
HBORDER = fontWidth * 1.25,
VBORDER = fontHeight / 2,
BUTTON_GAP = fontWidth,
LBL_GAP = fontWidth,
VGAP = fontHeight / 4,
buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: lineHeight * 1.25,
buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1));
int xpos = HBORDER, ypos = VBORDER, lwidth = 0, lwidth2 = 0;
WidgetArray wid;
string lblRom = "Select a ROM from the list" + ELLIPSIS;
const string& lblFilter = "Filter";
const string& lblAllFiles = "Show all files";
const string& lblFound = "XXXX items found";
lwidth = font.getStringWidth(lblRom);
lwidth2 = font.getStringWidth(lblAllFiles) + 20;
lwidth2 = font.getStringWidth(lblAllFiles) + CheckboxWidget::boxSize(font);
int lwidth3 = font.getStringWidth(lblFilter);
int lwidth4 = font.getStringWidth(lblFound);
@ -97,14 +98,12 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
#if defined(RETRON77)
ver << " for RetroN 77";
#endif
ypos += 8;
new StaticTextWidget(this, font, xpos, ypos, _w - 20, fontHeight,
new StaticTextWidget(this, font, 0, ypos, _w, fontHeight,
ver.str(), TextAlign::Center);
ypos += fontHeight - 4;
ypos += lineHeight;
}
// Show the header
xpos += HBORDER; ypos += 8;
new StaticTextWidget(this, font, xpos, ypos, lblRom);
// Shop the files counter
xpos = _w - HBORDER - lwidth4;
@ -132,12 +131,12 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add list with game titles
// Before we add the list, we need to know the size of the RomInfoWidget
int listHeight = _h - 43 - bheight - fontHeight - lineHeight;
int listHeight = _h - VBORDER * 2 - buttonHeight - lineHeight * 2 - VGAP * 6;
float imgZoom = getRomInfoZoom(listHeight);
int romWidth = imgZoom * TIAConstants::viewableWidth;
if(romWidth > 0) romWidth += 10;
int listWidth = _w - (romWidth > 0 ? romWidth+8 : 0) - 20;
xpos = HBORDER; ypos += lineHeight + 4;
if(romWidth > 0) romWidth += HBORDER;
int listWidth = _w - (romWidth > 0 ? romWidth + fontWidth : 0) - HBORDER * 2;
xpos = HBORDER; ypos += lineHeight + VGAP;
myList = new FileListWidget(this, font, xpos, ypos, listWidth, listHeight);
myList->setEditable(false);
myList->setListMode(FilesystemNode::ListMode::All);
@ -146,14 +145,14 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add ROM info area (if enabled)
if(romWidth > 0)
{
xpos += myList->getWidth() + 8;
xpos += myList->getWidth() + fontWidth;
// Initial surface size is the same as the viewable area
Common::Size imgSize(TIAConstants::viewableWidth*imgZoom,
TIAConstants::viewableHeight*imgZoom);
// Calculate font area, and in the process the font that can be used
Common::Size fontArea(romWidth - 16, myList->getHeight() - imgSize.h - 12);
Common::Size fontArea(romWidth - fontWidth * 2, myList->getHeight() - imgSize.h - VGAP * 3);
setRomInfoFont(fontArea);
myRomInfoWidget = new RomInfoWidget(this, *myROMInfoFont,
@ -162,7 +161,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add textfield to show current directory
xpos = HBORDER;
ypos += myList->getHeight() + 8;
ypos += myList->getHeight() + VGAP * 2;
lwidth = font.getStringWidth("Path") + LBL_GAP;
myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwidth, fontHeight,
"Path", TextAlign::Left);
@ -174,43 +173,43 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
if(!myUseMinimalUI)
{
// Add four buttons at the bottom
xpos = HBORDER; ypos += myDir->getHeight() + 8;
xpos = HBORDER; ypos = _h - VBORDER - buttonHeight;
#ifndef BSPF_MACOS
myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight,
myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight,
"Select", kLoadROMCmd);
wid.push_back(myStartButton);
xpos += (bwidth + 0) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight,
xpos += (buttonWidth + 0) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
"Go Up", kPrevDirCmd);
wid.push_back(myPrevDirButton);
xpos += (bwidth + 1) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight,
xpos += (buttonWidth + 1) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
"Options" + ELLIPSIS, kOptionsCmd);
wid.push_back(myOptionsButton);
xpos += (bwidth + 2) / 4 + BUTTON_GAP;
myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 4) / 4, bheight,
xpos += (buttonWidth + 2) / 4 + BUTTON_GAP;
myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 4) / 4, buttonHeight,
"Quit", kQuitCmd);
wid.push_back(myQuitButton);
#else
myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight,
myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight,
"Quit", kQuitCmd);
wid.push_back(myQuitButton);
xpos += (bwidth + 0) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight,
xpos += (buttonWidth + 0) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
"Options" + ELLIPSIS, kOptionsCmd);
wid.push_back(myOptionsButton);
xpos += (bwidth + 1) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 2) / 4, bheight,
xpos += (buttonWidth + 1) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight,
"Go Up", kPrevDirCmd);
wid.push_back(myPrevDirButton);
xpos += (bwidth + 2) / 4 + BUTTON_GAP;
myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight,
xpos += (buttonWidth + 2) / 4 + BUTTON_GAP;
myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
"Select", kLoadROMCmd);
wid.push_back(myStartButton);
#endif
@ -223,7 +222,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
addToFocusList(wid);
// Create (empty) context menu for ROM list options
myMenu = make_unique<ContextMenu>(this, osystem.frameBuffer().font(), EmptyVarList);
myMenu = make_unique<ContextMenu>(this, osystem.frameBuffer().launcherFont(), EmptyVarList);
// Create global props dialog, which is used to temporarily override
// ROM properties
@ -363,28 +362,33 @@ float LauncherDialog::getRomInfoZoom(int listHeight) const
if(zoom > 0.F)
{
// upper zoom limit - at least 24 launchers chars/line and 8 ROM info lines
if((_w - 58 - zoom * TIAConstants::viewableWidth)
/ instance().frameBuffer().launcherFont().getMaxCharWidth() < MIN_LAUNCHER_CHARS)
const GUI::Font& font = instance().frameBuffer().launcherFont();
const GUI::Font& smallFont = instance().frameBuffer().smallFont();
const int fontWidth = font.getMaxCharWidth(),
HBORDER = fontWidth * 1.25;
// upper zoom limit - at least 24 launchers chars/line and 7 + 4 ROM info lines
if((_w - (HBORDER * 2 + fontWidth + 30) - zoom * TIAConstants::viewableWidth)
/ font.getMaxCharWidth() < MIN_LAUNCHER_CHARS)
{
zoom = float(_w - 58 - MIN_LAUNCHER_CHARS * instance().frameBuffer().launcherFont().getMaxCharWidth())
zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * font.getMaxCharWidth())
/ TIAConstants::viewableWidth;
}
if((listHeight - 12 - zoom * TIAConstants::viewableHeight) <
MIN_ROMINFO_ROWS * instance().frameBuffer().smallFont().getLineHeight() +
MIN_ROMINFO_LINES * instance().frameBuffer().smallFont().getFontHeight())
MIN_ROMINFO_ROWS * smallFont.getLineHeight() +
MIN_ROMINFO_LINES * smallFont.getFontHeight())
{
zoom = float(listHeight - 12 -
MIN_ROMINFO_ROWS * instance().frameBuffer().smallFont().getLineHeight() -
MIN_ROMINFO_LINES * instance().frameBuffer().smallFont().getFontHeight())
MIN_ROMINFO_ROWS * smallFont.getLineHeight() -
MIN_ROMINFO_LINES * smallFont.getFontHeight())
/ TIAConstants::viewableHeight;
}
// lower zoom limit - at least 24 ROM info chars/line
// lower zoom limit - at least 30 ROM info chars/line
if((zoom * TIAConstants::viewableWidth)
/ instance().frameBuffer().smallFont().getMaxCharWidth() < MIN_ROMINFO_CHARS + 6)
/ smallFont.getMaxCharWidth() < MIN_ROMINFO_CHARS + 6)
{
zoom = float(MIN_ROMINFO_CHARS * instance().frameBuffer().smallFont().getMaxCharWidth() + 6)
zoom = float(MIN_ROMINFO_CHARS * smallFont.getMaxCharWidth() + 6)
/ TIAConstants::viewableWidth;
}
}
@ -428,13 +432,7 @@ void LauncherDialog::loadRomInfo()
const string& md5 = selectedRomMD5();
if(md5 != EmptyString)
{
// Get the properties for this entry
Properties props;
instance().propSet().getMD5WithInsert(currentNode(), md5, props);
myRomInfoWidget->setProperties(props, currentNode());
}
myRomInfoWidget->setProperties(currentNode(), md5);
else
myRomInfoWidget->clearProperties();
}

View File

@ -94,9 +94,9 @@ class LauncherDialog : public Dialog
private:
static constexpr int MIN_LAUNCHER_CHARS = 24;
static constexpr int MIN_ROMINFO_CHARS = 24;
static constexpr int MIN_ROMINFO_CHARS = 30;
static constexpr int MIN_ROMINFO_ROWS = 7; // full lines
static constexpr int MIN_ROMINFO_LINES = 2; // extra lines
static constexpr int MIN_ROMINFO_LINES = 4; // extra lines
void center() override { positionAt(0); }
void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override;
@ -132,7 +132,7 @@ class LauncherDialog : public Dialog
unique_ptr<GUI::Font> myROMInfoFont;
ButtonWidget* myStartButton{nullptr};
ButtonWidget* myPrevDirButton{nullptr};
ButtonWidget* myPrevDirButton{nullptr};
ButtonWidget* myOptionsButton{nullptr};
ButtonWidget* myQuitButton{nullptr};

View File

@ -39,11 +39,12 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font,
_rows = h / _fontHeight;
// Set real dimensions
_w = w - kScrollBarWidth;
_w = w - ScrollBarWidget::scrollBarWidth(_font);
_h = h + 2;
// Create scrollbar and attach to the list
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h);
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y,
ScrollBarWidget::scrollBarWidth(_font), _h);
_scrollBar->setTarget(this);
}
@ -144,7 +145,7 @@ void ListWidget::scrollTo(int item)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int ListWidget::getWidth() const
{
return _w + kScrollBarWidth;
return _w + ScrollBarWidget::scrollBarWidth(_font);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -37,8 +37,15 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
: Dialog(osystem, parent, font, "System logs")
{
const int lineHeight = font.getLineHeight(),
buttonWidth = font.getStringWidth("Save log to disk") + 20,
buttonHeight = font.getLineHeight() + 4;
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Save log to disk") + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
@ -47,13 +54,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
setSize(4000, 4000, max_w, max_h);
// Test listing of the log output
xpos = 10; ypos = 10 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
myLogInfo = new StringListWidget(this, uselargefont ? font :
instance().frameBuffer().infoFont(), xpos, ypos, _w - 2 * xpos,
_h - buttonHeight - ypos - 20 - 2 * lineHeight, false);
_h - buttonHeight - ypos - VBORDER - lineHeight - VGAP * 4, false);
myLogInfo->setEditable(false);
wid.push_back(myLogInfo);
ypos += myLogInfo->getHeight() + 8;
ypos += myLogInfo->getHeight() + VGAP * 2;
// Level of logging (how much info to print)
VariantList items;
@ -67,13 +74,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myLogLevel);
// Should log output also be shown on the console?
xpos += myLogLevel->getWidth() + 32;
xpos += myLogLevel->getWidth() + fontWidth * 4;
myLogToConsole = new CheckboxWidget(this, font, xpos, ypos + 1, "Print to console");
wid.push_back(myLogToConsole);
// Add Save, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10,
b = new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Save log to disk",
GuiObject::kDefaultsCmd);
wid.push_back(b);

View File

@ -79,21 +79,24 @@ MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MessageBox::addText(const GUI::Font& font, const StringList& text)
{
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight();
int xpos, ypos;
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
int xpos, ypos;
// Set real dimensions
int str_w = 0;
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) * fontHeight + 20 + _th), uInt32(_h));
_w = std::min(str_w * fontWidth + HBORDER * 2, _w);
_h = std::min(uInt32((text.size() + 2) * fontHeight + VBORDER * 2 + _th), uInt32(_h));
xpos = 10; ypos = 10 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
for(const auto& s: text)
{
new StaticTextWidget(this, font, xpos, ypos, _w - 20,
new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2,
fontHeight, s, TextAlign::Left);
ypos += fontHeight;
}

View File

@ -49,19 +49,24 @@
OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
GuiObject* boss, int max_w, int max_h, Menu::AppMode mode)
: Dialog(osystem, parent, osystem.frameBuffer().font(), "Options"),
myBoss(boss),
myMode(mode)
{
// do not show basic settings options in debugger
bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger;
const int buttonHeight = _font.getLineHeight() + 6,
GAP = buttonHeight > 26 ? 5 : 4,
rowHeight = buttonHeight + GAP;
const int VBORDER = GAP * 2 + 2;
const int HBORDER = GAP * 2 + 2;
int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + GAP * 5;
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight(),
buttonHeight = _font.getLineHeight() * 1.25,
VGAP = fontHeight / 4,
HGAP = fontWidth,
rowHeight = buttonHeight + VGAP;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + fontWidth * 2.5;
_w = 2 * buttonWidth + HBORDER * 3;
_h = 7 * rowHeight + VBORDER * 2 - GAP + _th;
_w = 2 * buttonWidth + HBORDER * 2 + HGAP;
_h = 7 * rowHeight + VBORDER * 2 - VGAP + _th;
int xoffset = HBORDER, yoffset = VBORDER + _th;
WidgetArray wid;
@ -72,8 +77,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset,
_w - HBORDER * 2, buttonHeight, "Use Basic Settings", kBasSetCmd);
wid.push_back(bw);
yoffset += rowHeight + GAP * 2;
_h += rowHeight + GAP * 2;
yoffset += rowHeight + VGAP * 2;
_h += rowHeight + VGAP * 2;
}
auto ADD_OD_BUTTON = [&](const string& label, int cmd)
@ -107,8 +112,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(b);
// Move to second column
xoffset += buttonWidth + HBORDER;
yoffset = minSettings ? VBORDER + _th + rowHeight + GAP * 2 : VBORDER + _th;
xoffset += buttonWidth + HGAP;
yoffset = minSettings ? VBORDER + _th + rowHeight + VGAP * 2 : VBORDER + _th;
myGameInfoButton = ADD_OD_BUTTON("Game Properties" + ELLIPSIS, kInfoCmd);
wid.push_back(myGameInfoButton);
@ -131,8 +136,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd);
wid.push_back(b);
buttonWidth = _font.getStringWidth(" Close ") + GAP * 5;
xoffset -= (buttonWidth + HBORDER) / 2;
buttonWidth = _font.getStringWidth(" Close ") + fontWidth * 2.5;
xoffset -= (buttonWidth + HGAP) / 2;
b = ADD_OD_BUTTON("Close", kExitCmd);
wid.push_back(b);
addCancelWidget(b);
@ -243,8 +248,20 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd,
}
case kUsrIfaceCmd:
{
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
uInt32 w = 0, h = 0;
if(myUIDialog == nullptr || myUIDialog->shouldResize(w, h))
{
myUIDialog = make_unique<UIDialog>(instance(), parent(),
instance().frameBuffer().font(), myBoss, w, h);
}
myUIDialog->open();
break;
}
case kSnapCmd:
{

View File

@ -71,6 +71,7 @@ class OptionsDialog : public Dialog
ButtonWidget* myGameInfoButton{nullptr};
ButtonWidget* myCheatCodeButton{nullptr};
GuiObject* myBoss;
// Indicates if this dialog is used for global (vs. in-game) settings
Menu::AppMode myMode{Menu::AppMode::emulator};

View File

@ -41,11 +41,13 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font,
if(!_label.empty() && _labelWidth == 0)
_labelWidth = _font.getStringWidth(_label);
_w = w + _labelWidth + 23;
setArrow();
_w = w + _labelWidth + dropDownWidth(font); // 23
// vertically center the arrows and text
myTextY = (_h - _font.getFontHeight()) / 2;
myArrowsY = (_h - 8) / 2;
myArrowsY = (_h - _arrowHeight) / 2;
myMenu = make_unique<ContextMenu>(this, font, list, cmd, w);
}
@ -185,10 +187,10 @@ void PopUpWidget::handleCommand(CommandSender* sender, int cmd, int data, int id
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PopUpWidget::drawWidget(bool hilite)
void PopUpWidget::setArrow()
{
// Little down arrow
static constexpr std::array<uInt32, 8> down_arrow = {
// Small down arrow
static constexpr std::array<uInt32, 7> down_arrow = {
0b100000001,
0b110000011,
0b111000111,
@ -196,9 +198,40 @@ void PopUpWidget::drawWidget(bool hilite)
0b001111100,
0b000111000,
0b000010000,
0b000000000
};
// Large down arrow
static constexpr std::array<uInt32, 10> down_arrow_large = {
0b1000000000001,
0b1100000000011,
0b1110000000111,
0b1111000001111,
0b0111100011110,
0b0011110111100,
0b0001111111000,
0b0000111110000,
0b0000011100000,
0b0000001000000
};
if(_font.getFontHeight() < 24)
{
_textOfs = 3;
_arrowWidth = 9;
_arrowHeight = 7;
_arrowImg = down_arrow.data();
}
else
{
_textOfs = 5;
_arrowWidth = 13;
_arrowHeight = 10;
_arrowImg = down_arrow_large.data();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PopUpWidget::drawWidget(bool hilite)
{
//cerr << "PopUpWidget::drawWidget\n";
FBSurface& s = dialog().surface();
bool onTop = _boss->dialog().isOnTop();
@ -213,19 +246,22 @@ void PopUpWidget::drawWidget(bool hilite)
// Draw a thin frame around us.
s.frameRect(x, _y, w, _h, isEnabled() && hilite ? kWidColorHi : kColor);
s.frameRect(x + w - 16, _y + 1, 15, _h - 2, isEnabled() && hilite ? kWidColorHi : kBGColorLo);
s.frameRect(x + w - (_arrowWidth * 2 - 2), _y + 1, (_arrowWidth * 2 - 3), _h - 2,
isEnabled() && hilite ? kWidColorHi : kBGColorLo);
// Fill the background
s.fillRect(x + 1, _y + 1, w - 17, _h - 2, onTop ? _changed ? kDbgChangedColor : kWidColor : kDlgColor);
s.fillRect(x + w - 15, _y + 2, 13, _h - 4, onTop ? isEnabled() && hilite ? kWidColor : kBGColorHi : kBGColorLo);
s.fillRect(x + 1, _y + 1, w - (_arrowWidth * 2 - 1), _h - 2,
onTop ? _changed ? kDbgChangedColor : kWidColor : kDlgColor);
s.fillRect(x + w - (_arrowWidth * 2 - 3), _y + 2, (_arrowWidth * 2 - 5), _h - 4,
onTop ? isEnabled() && hilite ? kWidColor : kBGColorHi : kBGColorLo);
// Draw an arrow pointing down at the right end to signal this is a dropdown/popup
s.drawBitmap(down_arrow.data(), x + w - 13, _y + myArrowsY + 1,
!(isEnabled() && onTop) ? kColor : kTextColor, 9U, 8U);
s.drawBitmap(_arrowImg, x + w - (_arrowWidth * 1.5 - 1), _y + myArrowsY + 1,
!(isEnabled() && onTop) ? kColor : kTextColor, _arrowWidth, _arrowHeight);
// Draw the selected entry, if any
const string& name = myMenu->getSelectedName();
TextAlign align = (_font.getStringWidth(name) > w-6) ?
TextAlign align = (_font.getStringWidth(name) > w - 6) ?
TextAlign::Right : TextAlign::Left;
s.drawString(_font, name, x+2, _y+myTextY, w-6,
s.drawString(_font, name, x + _textOfs, _y + myTextY, w - 6,
!(isEnabled() && onTop) ? kColor : _changed ? kDbgChangedTextColor : kTextColor, align);
}

View File

@ -62,6 +62,10 @@ class PopUpWidget : public Widget, public CommandSender
const Variant& getSelectedTag() const;
bool wantsFocus() const override { return true; }
static int dropDownWidth(const GUI::Font& font)
{
return font.getFontHeight() < 24 ? (9 * 2 + 3) : (13 * 2 + 7);
}
protected:
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
@ -70,6 +74,8 @@ class PopUpWidget : public Widget, public CommandSender
void handleMouseLeft() override;
bool handleEvent(Event::Type e) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void setArrow();
void drawWidget(bool hilite) override;
private:
@ -81,6 +87,11 @@ class PopUpWidget : public Widget, public CommandSender
int _labelWidth{0};
bool _changed{false};
int _textOfs{0};
int _arrowWidth{0};
int _arrowHeight{0};
const uInt32* _arrowImg{nullptr};
private:
// Following constructors and assignment operators not supported
PopUpWidget() = delete;

View File

@ -31,20 +31,23 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font,
{
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight();
lineHeight = font.getLineHeight(),
VBORDER = fontHeight / 2,
HBORDER = fontWidth * 1.25,
VGAP = fontHeight / 4;
int xpos, ypos, lwidth;
// Calculate real dimensions
lwidth = font.getStringWidth(message);
_w = lwidth + 2 * fontWidth;
_h = lineHeight * 5;
_w = HBORDER * 2 + lwidth;
_h = VBORDER * 2 + lineHeight * 2 + VGAP * 2;
xpos = fontWidth; ypos = lineHeight;
xpos = HBORDER; ypos = VBORDER;
myMessage = new StaticTextWidget(this, font, xpos, ypos, lwidth, fontHeight,
message, TextAlign::Center);
myMessage->setTextColor(kTextColorEm);
xpos = fontWidth; ypos += 2 * lineHeight;
xpos = HBORDER; ypos += lineHeight + VGAP * 2;
mySlider = new SliderWidget(this, font, xpos, ypos, lwidth, lineHeight, "", 0, 0);
mySlider->setMinValue(1);
mySlider->setMaxValue(100);

View File

@ -21,6 +21,7 @@
#include "RadioButtonWidget.hxx"
/* Radiobutton bitmaps */
// small versions
static constexpr std::array<uInt32, 14> radio_img_outercircle = {
0b00001111110000, 0b00110000001100, 0b01000000000010,
0b01000000000010, 0b10000000000001, 0b10000000000001,
@ -33,16 +34,188 @@ static constexpr std::array<uInt32, 12> radio_img_innercircle = {
0b111111111111, 0b111111111111, 0b111111111111, 0b111111111111,
0b111111111111, 0b011111111110, 0b011111111110, 0b000111111000
};
static constexpr uInt32 RADIO_IMG_FILL_SIZE = 10;
static constexpr std::array<uInt32, RADIO_IMG_FILL_SIZE> radio_img_active = {
static constexpr std::array<uInt32, 10> radio_img_active = {
0b0011111100, 0b0111111110, 0b1111111111, 0b1111111111, 0b1111111111,
0b1111111111, 0b1111111111, 0b1111111111, 0b0111111110, 0b0011111100,
};
static constexpr std::array<uInt32, RADIO_IMG_FILL_SIZE> radio_img_inactive = {
static constexpr std::array<uInt32, 10> radio_img_inactive = {
0b0011111100, 0b0111111110, 0b1111001111, 0b1110000111, 0b1100000011,
0b1100000011, 0b1110000111, 0b1111001111, 0b0111111110, 0b0011111100
};
// large versions
static constexpr std::array<uInt32, 22> radio_img_outercircle_large = {
// thinner version
//0b0000000011111100000000,
//0b0000001100000011000000,
//0b0000110000000000110000,
//0b0001000000000000001000,
//0b0010000000000000000100,
//0b0010000000000000000100,
//0b0100000000000000000010,
//0b0100000000000000000010,
//0b1000000000000000000001,
//0b1000000000000000000001,
//0b1000000000000000000001,
//0b1000000000000000000001,
//0b1000000000000000000001,
//0b1000000000000000000001,
//0b0100000000000000000010,
//0b0100000000000000000010,
//0b0010000000000000000100,
//0b0010000000000000000100,
//0b0001000000000000001000,
//0b0000110000000000110000,
//0b0000001100000011000000,
//0b0000000011111100000000
0b0000000011111100000000,
0b0000001110000111000000,
0b0000111000000001110000,
0b0001100000000000011000,
0b0011000000000000001100,
0b0010000000000000000100,
0b0110000000000000000110,
0b0100000000000000000010,
0b1100000000000000000011,
0b1000000000000000000001,
0b1000000000000000000001,
0b1000000000000000000001,
0b1000000000000000000001,
0b1100000000000000000011,
0b0100000000000000000010,
0b0110000000000000000110,
0b0010000000000000000100,
0b0011000000000000001100,
0b0001100000000000011000,
0b0000111000000001110000,
0b0000001110000111000000,
0b0000000011111100000000
};
static constexpr std::array<uInt32, 20> radio_img_innercircle_large = {
//0b00000001111110000000,
//0b00000111111111100000,
//0b00011111111111111000,
//0b00111111111111111100,
//0b00111111111111111100,
//0b01111111111111111110,
//0b01111111111111111110,
//0b11111111111111111111,
//0b11111111111111111111,
//0b11111111111111111111,
//0b11111111111111111111,
//0b11111111111111111111,
//0b11111111111111111111,
//0b01111111111111111110,
//0b01111111111111111110,
//0b00111111111111111100,
//0b00111111111111111100,
//0b00011111111111111000,
//0b00000111111111100000,
//0b00000001111110000000
0b00000000111100000000,
0b00000011111111000000,
0b00001111111111110000,
0b00011111111111111000,
0b00111111111111111100,
0b00111111111111111100,
0b01111111111111111110,
0b01111111111111111110,
0b11111111111111111111,
0b11111111111111111111,
0b11111111111111111111,
0b11111111111111111111,
0b01111111111111111110,
0b01111111111111111110,
0b00111111111111111100,
0b00111111111111111100,
0b00011111111111111000,
0b00001111111111110000,
0b00000011111111000000,
0b00000000111100000000
};
static constexpr std::array<uInt32, 18> radio_img_active_large = {
//0b000000111111000000,
//0b000011111111110000,
//0b000111111111111000,
//0b001111111111111100,
//0b011111111111111110,
//0b011111111111111110,
//0b111111111111111111,
//0b111111111111111111,
//0b111111111111111111,
//0b111111111111111111,
//0b111111111111111111,
//0b111111111111111111,
//0b011111111111111110,
//0b011111111111111110,
//0b001111111111111100,
//0b000111111111111000,
//0b000011111111110000,
//0b000000111111000000
0b000000000000000000,
0b000000111111000000,
0b000011111111110000,
0b000111111111111000,
0b001111111111111100,
0b001111111111111100,
0b011111111111111110,
0b011111111111111110,
0b011111111111111110,
0b011111111111111110,
0b011111111111111110,
0b011111111111111110,
0b001111111111111100,
0b001111111111111100,
0b000111111111111000,
0b000011111111110000,
0b000000111111000000,
0b000000000000000000
};
static constexpr std::array<uInt32, 18> radio_img_inactive_large = {
//0b000001111111100000,
//0b000111111111111000,
//0b001111111111111100,
//0b011111100001111110,
//0b011110000000011110,
//0b111100000000001111,
//0b111100000000001111,
//0b111000000000000111,
//0b111000000000000111,
//0b111000000000000111,
//0b111000000000000111,
//0b111100000000001111,
//0b111100000000001111,
//0b011110000000011110,
//0b011111100001111110,
//0b001111111111111100,
//0b010111111111111000,
//0b000001111111100000
0b000000000000000000,
0b000000111111000000,
0b000011111111110000,
0b000111111111111000,
0b001111100001111100,
0b001111000000111100,
0b011110000000011110,
0b011100000000001110,
0b011100000000001110,
0b011100000000001110,
0b011100000000001110,
0b011110000000011110,
0b001111000000111100,
0b001111100001111100,
0b000111111111111000,
0b000011111111110000,
0b000000111111000000,
0b000000000000000000
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, const string& label,
@ -54,19 +227,31 @@ RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font,
_bgcolor = _bgcolorhi = kWidColor;
_editable = true;
_buttonSize = buttonSize(font); // 14 | 22
if(_buttonSize == 14)
{
_outerCircle = radio_img_outercircle.data();
_innerCircle = radio_img_innercircle.data();
}
else
{
_outerCircle = radio_img_outercircle_large.data();
_innerCircle = radio_img_innercircle_large.data();
}
if(label == "")
_w = 14;
_w = _buttonSize;
else
_w = font.getStringWidth(label) + 20;
_h = font.getFontHeight() < 14 ? 14 : font.getFontHeight();
_w = font.getStringWidth(label) + _buttonSize + font.getMaxCharWidth() * 0.75;
_h = font.getFontHeight() < int(_buttonSize) ? _buttonSize : font.getFontHeight();
// Depending on font size, either the font or box will need to be
// centered vertically
if(_h > 14) // center box
_boxY = (_h - 14) / 2;
if(_h > int(_buttonSize)) // center box
_boxY = (_h - _buttonSize) / 2;
else // center text
_textY = (14 - _font.getFontHeight()) / 2;
_textY = (_buttonSize - _font.getFontHeight()) / 2;
setFill(CheckboxWidget::FillType::Normal);
myGroup->addWidget(this);
@ -102,10 +287,10 @@ void RadioButtonWidget::setFill(FillType type)
switch(type)
{
case CheckboxWidget::FillType::Normal:
_img = radio_img_active.data();
_img = _buttonSize == 14 ? radio_img_active.data() : radio_img_active_large.data();
break;
case CheckboxWidget::FillType::Inactive:
_img = radio_img_inactive.data();
_img = _buttonSize == 14 ? radio_img_inactive.data(): radio_img_inactive_large.data();
break;
default:
break;
@ -118,25 +303,23 @@ void RadioButtonWidget::drawWidget(bool hilite)
FBSurface& s = _boss->dialog().surface();
// Draw the outer bounding circle
s.drawBitmap(radio_img_outercircle.data(), _x, _y + _boxY,
s.drawBitmap(_outerCircle, _x, _y + _boxY,
hilite ? kWidColorHi : kColor,
static_cast<uInt32>(radio_img_outercircle.size()),
static_cast<uInt32>(radio_img_outercircle.size()));
_buttonSize);
// Draw the inner bounding circle with enabled color
s.drawBitmap(radio_img_innercircle.data(), _x + 1, _y + _boxY + 1,
s.drawBitmap(_innerCircle, _x + 1, _y + _boxY + 1,
isEnabled() ? _bgcolor : kColor,
static_cast<uInt32>(radio_img_innercircle.size()),
static_cast<uInt32>(radio_img_innercircle.size()));
_buttonSize - 2);
// draw state
if(_state)
s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled()
? hilite ? kWidColorHi : kCheckColor
: kColor, RADIO_IMG_FILL_SIZE);
: kColor, _buttonSize - 4);
// Finally draw the label
s.drawString(_font, _label, _x + 20, _y + _textY, _w,
s.drawString(_font, _label, _x + _buttonSize + _font.getMaxCharWidth() * 0.75, _y + _textY, _w,
isEnabled() ? kTextColor : kColor);
}

View File

@ -40,9 +40,14 @@ class RadioButtonWidget : public CheckboxWidget
protected:
void setFill(FillType type);
void drawWidget(bool hilite) override;
static int buttonSize(const GUI::Font& font)
{
return font.getFontHeight() < 24 ? 14 : 22; // box is square
}
private:
RadioButtonGroup* myGroup{nullptr};
uInt32 _buttonSize{14};
private:
// Following constructors and assignment operators not supported

View File

@ -40,15 +40,17 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent,
myMaxWidth(max_w),
myMaxHeight(max_h)
{
const int VBORDER = 10 + _th;
const int HBORDER = 10;
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 4,
buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25,
lwidth = font.getStringWidth("ROMs without properties (skipped) ");
const int VBORDER = _th + fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos = VBORDER;
WidgetArray wid;
@ -62,28 +64,24 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent,
"Audit path" + ELLIPSIS, kChooseAuditDirCmd);
wid.push_back(romButton);
xpos = HBORDER + buttonWidth + 8;
myRomPath = new EditTextWidget(this, font, xpos, ypos + 1,
myRomPath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 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,
"ROMs with properties (renamed) ", TextAlign::Left);
new StaticTextWidget(this, font, HBORDER, ypos, "ROMs with properties (renamed) ");
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,
"ROMs without properties (skipped) ", TextAlign::Left);
new StaticTextWidget(this, font, HBORDER, ypos, "ROMs without properties (skipped) ");
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!",
TextAlign::Left);
new StaticTextWidget(this, font, HBORDER, ypos, "(*) WARNING: Operation cannot be undone!");
// Add OK and Cancel buttons
addOKCancelBGroup(wid, font, "Audit", "Close");

View File

@ -27,6 +27,7 @@
#include "Logger.hxx"
#include "Props.hxx"
#include "PNGLibrary.hxx"
#include "PropsSet.hxx"
#include "Rect.hxx"
#include "Widget.hxx"
#include "RomInfoWidget.hxx"
@ -44,20 +45,10 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomInfoWidget::reloadProperties(const FilesystemNode& node)
{
// The ROM may have changed since we were last in the browser, either
// by saving a different image or through a change in video renderer,
// so we reload the properties
if(myHaveProperties)
parseProperties(node);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomInfoWidget::setProperties(const Properties& props, const FilesystemNode& node)
void RomInfoWidget::setProperties(const FilesystemNode& node, const string& md5)
{
myHaveProperties = true;
myProperties = props;
instance().propSet().getMD5(md5, myProperties);
// Decide whether the information should be shown immediately
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
@ -76,6 +67,16 @@ void RomInfoWidget::clearProperties()
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomInfoWidget::reloadProperties(const FilesystemNode& node)
{
// The ROM may have changed since we were last in the browser, either
// by saving a different image or through a change in video renderer,
// so we reload the properties
if(myHaveProperties)
parseProperties(node);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomInfoWidget::parseProperties(const FilesystemNode& node)
{
@ -140,8 +141,7 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
try
{
ByteBuffer image;
string md5 = myProperties.get(PropType::Cart_MD5);
size_t size = 0;
string md5 = ""; size_t size = 0;
if(node.exists() && !node.isDirectory() &&
(image = instance().openROM(node, md5, size)) != nullptr)
@ -203,11 +203,23 @@ void RomInfoWidget::drawWidget(bool hilite)
}
int xpos = _x + 8, ypos = _y + yoff + 5;
for(const auto& info: myRomInfo)
for(const auto& info : myRomInfo)
{
if(info.length() * _font.getMaxCharWidth() <= _w - 16)
{
// 1 line for next entry
if(ypos + _font.getFontHeight() > _h + _y)
break;
}
else
{
// assume 2 lines for next entry
if(ypos + _font.getLineHeight() + _font.getFontHeight() > _h + _y )
break;
}
int lines = s.drawString(_font, info, xpos, ypos, _w - 16, _font.getFontHeight() * 3,
onTop ? _textcolor : _shadowcolor);
if(ypos >= _h) break;
ypos += _font.getLineHeight() + (lines - 1) * _font.getFontHeight();
}
}

View File

@ -35,7 +35,7 @@ class RomInfoWidget : public Widget
const Common::Size& imgSize);
virtual ~RomInfoWidget() = default;
void setProperties(const Properties& props, const FilesystemNode& node);
void setProperties(const FilesystemNode& node, const string& md5);
void clearProperties();
void reloadProperties(const FilesystemNode& node);

View File

@ -28,8 +28,6 @@
* and we thus should not highlight the arrows/slider.
*/
#define UP_DOWN_BOX_HEIGHT 18
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h)
@ -38,6 +36,76 @@ ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font,
_flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE | Widget::FLAG_CLEARBG;
_bgcolor = kWidColor;
_bgcolorhi = kWidColor;
_scrollBarWidth = scrollBarWidth(font);
setArrows();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ScrollBarWidget::setArrows()
{
// Small up arrow
static constexpr std::array<uInt32, 6> up_arrow = {
0b0001000,
0b0011100,
0b0111110,
0b1110111,
0b1100011,
0b1000001,
};
// Small down arrow
static constexpr std::array<uInt32, 6> down_arrow = {
0b1000001,
0b1100011,
0b1110111,
0b0111110,
0b0011100,
0b0001000
};
// Large up arrow
static constexpr std::array<uInt32, 9> up_arrow_large = {
0b00000100000,
0b00001110000,
0b00011111000,
0b00111111100,
0b01111011110,
0b11110001111,
0b11100000111,
0b11000000011,
0b10000000001,
};
// Large down arrow
static constexpr std::array<uInt32, 9> down_arrow_large = {
0b10000000001,
0b11000000011,
0b11100000111,
0b11110001111,
0b01111011110,
0b00111111100,
0b00011111000,
0b00001110000,
0b00000100000
};
if(_font.getFontHeight() < 24)
{
_upDownWidth = 7;
_upDownHeight = 6;
_upDownBoxHeight = 18;
_upImg = up_arrow.data();
_downImg = down_arrow.data();
}
else
{
_upDownWidth = 11;
_upDownHeight = 9;
_upDownBoxHeight = 27;
_upImg = up_arrow_large.data();
_downImg = down_arrow_large.data();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -54,13 +122,13 @@ void ScrollBarWidget::handleMouseDown(int x, int y, MouseButton b,
if(_numEntries <= _entriesPerPage)
return;
if (y <= UP_DOWN_BOX_HEIGHT)
if (y <= _upDownBoxHeight)
{
// Up arrow
_currentPos--;
_draggingPart = Part::UpArrow;
}
else if(y >= _h - UP_DOWN_BOX_HEIGHT)
else if(y >= _h - _upDownBoxHeight)
{
// Down arrow
_currentPos++;
@ -120,23 +188,23 @@ void ScrollBarWidget::handleMouseMoved(int x, int y)
int old_pos = _currentPos;
_sliderPos = y - _sliderDeltaMouseDownPos;
if(_sliderPos < UP_DOWN_BOX_HEIGHT)
_sliderPos = UP_DOWN_BOX_HEIGHT;
if(_sliderPos < _upDownBoxHeight)
_sliderPos = _upDownBoxHeight;
if(_sliderPos > _h - UP_DOWN_BOX_HEIGHT - _sliderHeight)
_sliderPos = _h - UP_DOWN_BOX_HEIGHT - _sliderHeight;
if(_sliderPos > _h - _upDownBoxHeight - _sliderHeight)
_sliderPos = _h - _upDownBoxHeight - _sliderHeight;
_currentPos = (_sliderPos - UP_DOWN_BOX_HEIGHT) * (_numEntries - _entriesPerPage) /
(_h - 2 * UP_DOWN_BOX_HEIGHT - _sliderHeight);
_currentPos = (_sliderPos - _upDownBoxHeight) * (_numEntries - _entriesPerPage) /
(_h - 2 * _upDownBoxHeight - _sliderHeight);
checkBounds(old_pos);
}
else
{
Part old_part = _part;
if(y <= UP_DOWN_BOX_HEIGHT) // Up arrow
if(y <= _upDownBoxHeight) // Up arrow
_part = Part::UpArrow;
else if(y >= _h - UP_DOWN_BOX_HEIGHT) // Down arrow
else if(y >= _h - _upDownBoxHeight) // Down arrow
_part = Part::DownArrow;
else if(y < _sliderPos)
_part = Part::PageUp;
@ -193,19 +261,19 @@ void ScrollBarWidget::recalc()
//cerr << "ScrollBarWidget::recalc()\n";
if(_numEntries > _entriesPerPage)
{
_sliderHeight = (_h - 2 * UP_DOWN_BOX_HEIGHT) * _entriesPerPage / _numEntries;
if(_sliderHeight < UP_DOWN_BOX_HEIGHT)
_sliderHeight = UP_DOWN_BOX_HEIGHT;
_sliderHeight = (_h - 2 * _upDownBoxHeight) * _entriesPerPage / _numEntries;
if(_sliderHeight < _upDownBoxHeight)
_sliderHeight = _upDownBoxHeight;
_sliderPos = UP_DOWN_BOX_HEIGHT + (_h - 2 * UP_DOWN_BOX_HEIGHT - _sliderHeight) *
_sliderPos = _upDownBoxHeight + (_h - 2 * _upDownBoxHeight - _sliderHeight) *
_currentPos / (_numEntries - _entriesPerPage);
if(_sliderPos < 0)
_sliderPos = 0;
}
else
{
_sliderHeight = _h - 2 * UP_DOWN_BOX_HEIGHT;
_sliderPos = UP_DOWN_BOX_HEIGHT;
_sliderHeight = _h - 2 * _upDownBoxHeight;
_sliderPos = _upDownBoxHeight;
}
setDirty();
@ -214,30 +282,6 @@ void ScrollBarWidget::recalc()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ScrollBarWidget::drawWidget(bool hilite)
{
// Up arrow
static constexpr std::array<uInt32, 8> up_arrow = {
0b00000000,
0b00010000,
0b00111000,
0b01111100,
0b11101110,
0b11000110,
0b10000010,
0b00000000
};
// Down arrow
static constexpr std::array<uInt32, 8> down_arrow = {
0b00000000,
0b10000010,
0b11000110,
0b11101110,
0b01111100,
0b00111000,
0b00010000,
0b00000000
};
//cerr << "ScrollBarWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface();
bool onTop = _boss->dialog().isOnTop();
@ -251,17 +295,19 @@ void ScrollBarWidget::drawWidget(bool hilite)
// Up arrow
if(hilite && _part == Part::UpArrow)
s.fillRect(_x + 1, _y + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor);
s.drawBitmap(up_arrow.data(), _x+4, _y+5,
s.fillRect(_x + 1, _y + 1, _w - 2, _upDownBoxHeight - 2, kScrollColor);
s.drawBitmap(_upImg, _x + (_scrollBarWidth - _upDownWidth) / 2,
_y + (_upDownBoxHeight - _upDownHeight) / 2,
onTop ? isSinglePage ? kColor : (hilite && _part == Part::UpArrow) ? kWidColor
: kTextColor : kColor, 8);
: kTextColor : kColor, _upDownWidth, _upDownHeight);
// Down arrow
if(hilite && _part == Part::DownArrow)
s.fillRect(_x + 1, bottomY - UP_DOWN_BOX_HEIGHT + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor);
s.drawBitmap(down_arrow.data(), _x+4, bottomY - UP_DOWN_BOX_HEIGHT + 5,
s.fillRect(_x + 1, bottomY - _upDownBoxHeight + 1, _w - 2, _upDownBoxHeight - 2, kScrollColor);
s.drawBitmap(_downImg, _x + (_scrollBarWidth - _upDownWidth) / 2,
bottomY - _upDownBoxHeight + (_upDownBoxHeight - _upDownHeight) / 2,
onTop ? isSinglePage ? kColor : (hilite && _part == Part::DownArrow) ?
kWidColor : kTextColor : kColor, 8);
kWidColor : kTextColor : kColor, _upDownWidth, _upDownHeight);
// Slider
if(!isSinglePage)
@ -273,3 +319,4 @@ void ScrollBarWidget::drawWidget(bool hilite)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int ScrollBarWidget::_WHEEL_LINES = 4;

View File

@ -24,10 +24,6 @@ class GuiObject;
#include "Command.hxx"
#include "bspf.hxx"
enum {
kScrollBarWidth = 15
};
class ScrollBarWidget : public Widget, public CommandSender
{
public:
@ -40,6 +36,10 @@ class ScrollBarWidget : public Widget, public CommandSender
static void setWheelLines(int lines) { _WHEEL_LINES = lines; }
static int getWheelLines() { return _WHEEL_LINES; }
static int scrollBarWidth(const GUI::Font& font)
{
return font.getFontHeight() < 24 ? 15 : 23;
}
private:
void drawWidget(bool hilite) override;
@ -51,6 +51,7 @@ class ScrollBarWidget : public Widget, public CommandSender
bool handleMouseClicks(int x, int y, MouseButton b) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
void setArrows();
public:
int _numEntries{0};
@ -66,6 +67,12 @@ class ScrollBarWidget : public Widget, public CommandSender
int _sliderHeight{0};
int _sliderPos{0};
int _sliderDeltaMouseDownPos{0};
int _upDownWidth{0};
int _upDownHeight{0};
int _upDownBoxHeight{0};
int _scrollBarWidth{0};
const uInt32* _upImg{nullptr};
const uInt32* _downImg{nullptr};
static int _WHEEL_LINES;

View File

@ -30,20 +30,22 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& 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(),
fontHeight = _font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 4;
buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + fontWidth * 2.5,
buttonHeight = font.getLineHeight() * 1.25;
const int HBORDER = fontWidth * 1.25;
const int VBORDER = fontHeight / 4;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos, fwidth;
WidgetArray wid;
ButtonWidget* b;
// Set real dimensions
setSize(64 * fontWidth + HBORDER * 2, 9 * (lineHeight + 4) + VBORDER + _th, max_w, max_h);
setSize(64 * fontWidth + HBORDER * 2, 9 * (lineHeight + VGAP) + VBORDER + _th, max_w, max_h);
xpos = HBORDER; ypos = VBORDER + _th;
@ -51,13 +53,13 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Save path" + ELLIPSIS, kChooseSnapSaveDirCmd);
wid.push_back(b);
xpos += buttonWidth + 8;
mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + 1,
xpos += buttonWidth + fontWidth;
mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1,
_w - xpos - HBORDER, lineHeight, "");
wid.push_back(mySnapSavePath);
// Snapshot naming
xpos = HBORDER; ypos += buttonHeight + V_GAP * 4;
xpos = HBORDER; ypos += buttonHeight + VGAP * 4;
// Snapshot interval (continuous mode)
mySnapInterval = new SliderWidget(this, font, xpos, ypos,
@ -70,21 +72,21 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
// Booleans for saving snapshots
fwidth = font.getStringWidth("When saving snapshots:");
xpos = HBORDER; ypos += lineHeight + V_GAP * 3;
xpos = HBORDER; ypos += lineHeight + VGAP * 3;
new StaticTextWidget(this, font, xpos, ypos, fwidth, lineHeight,
"When saving snapshots:", TextAlign::Left);
// Snapshot single or multiple saves
xpos += INDENT; ypos += lineHeight + V_GAP;
xpos += INDENT; ypos += lineHeight + VGAP;
mySnapName = new CheckboxWidget(this, font, xpos, ypos, "Use actual ROM name");
wid.push_back(mySnapName);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
mySnapSingle = new CheckboxWidget(this, font, xpos, ypos, "Overwrite existing files");
wid.push_back(mySnapSingle);
// Snapshot in 1x mode (ignore scaling)
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
mySnap1x = new CheckboxWidget(this, font, xpos, ypos,
"Ignore scaling (1x mode)");
wid.push_back(mySnap1x);

View File

@ -29,6 +29,16 @@ StringListWidget::StringListWidget(GuiObject* boss, const GUI::Font& font,
_hilite(hilite)
{
_bgcolorlo = kDlgColor;
if(_font.getFontHeight() < 24)
{
_textOfs = 3;
}
else
{
_textOfs = 5;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -106,5 +116,5 @@ void StringListWidget::drawWidget(bool hilite)
Common::Rect StringListWidget::getEditRect() const
{
const int offset = std::max(0, (_selectedItem - _currentPos) * _fontHeight);
return Common::Rect(2, 1 + offset, _w - 2, _fontHeight + offset);
return Common::Rect(_textOfs, 1 + offset, _w - _textOfs, _fontHeight + offset);
}

View File

@ -39,6 +39,7 @@ class StringListWidget : public ListWidget
protected:
bool _hilite{false};
int _textOfs{0};
private:
// Following constructors and assignment operators not supported

View File

@ -196,7 +196,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = width; // Parent determines our width (based on window size)
_h = V_BORDER * 2 + rowHeight + buttonHeight + 2;
_h = V_BORDER * 2 + rowHeight + std::max(buttonHeight + 2, rowHeight);
this->clearFlags(Widget::FLAG_CLEARBG); // does only work combined with blending (0..100)!
this->clearFlags(Widget::FLAG_BORDER);
@ -221,9 +221,10 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
ypos += rowHeight;
// Add time info
myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "00:00.00", TextAlign::Left, kBGColor);
int ypos_s = ypos + (buttonHeight - font.getFontHeight() + 1) / 2; // align to button vertical center
myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos_s, "00:00.00", TextAlign::Left, kBGColor);
myCurrentTimeWidget->setTextColor(kColorInfo);
myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("00:00.00"), ypos + 3,
myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("00:00.00"), ypos_s,
"00:00.00", TextAlign::Right, kBGColor);
myLastTimeWidget->setTextColor(kColorInfo);
xpos = myCurrentTimeWidget->getRight() + BUTTON_GAP * 4;
@ -262,7 +263,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
xpos = myLoadAllWidget->getRight() + BUTTON_GAP * 4;
// Add message
myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3,
myMessageWidget = new StaticTextWidget(this, font, xpos, ypos_s,
" ", TextAlign::Left, kBGColor);
myMessageWidget->setTextColor(kColorInfo);
}

View File

@ -30,6 +30,7 @@
#include "TabWidget.hxx"
#include "Widget.hxx"
#include "Font.hxx"
#include "StellaMediumFont.hxx"
#include "LauncherDialog.hxx"
#ifdef DEBUGGER_SUPPORT
#include "DebuggerDialog.hxx"
@ -48,12 +49,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = font.getLineHeight() + 4;
const int VBORDER = 8;
const int HBORDER = 10;
const int INDENT = 16;
const int V_GAP = 4;
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos, ypos, tabID;
int lwidth, pwidth, bwidth;
WidgetArray wid;
@ -61,11 +61,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
const Common::Size& ds = instance().frameBuffer().desktopSize();
// Set real dimensions
setSize(64 * fontWidth + HBORDER * 2, 11 * (lineHeight + V_GAP) + V_GAP * 9 + VBORDER + _th,
setSize(64 * fontWidth + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 10 * (lineHeight + VGAP) + VGAP * 2 + buttonHeight + VBORDER * 3,
max_w, max_h);
// The tab widget
myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2*2, _h - _th - buttonHeight - 20);
myTab = new TabWidget(this, font, 2, VGAP + _th,
_w - 2*2,
_h - _th - VGAP - buttonHeight - VBORDER * 2);
addTabWidget(myTab);
//////////////////////////////////////////////////////////
@ -85,12 +88,27 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
items, "Theme ", lwidth);
wid.push_back(myPalettePopup);
ypos += lineHeight + VGAP;
// Dialog font
items.clear();
VarList::push_back(items, "Small", "small"); // 8x13
VarList::push_back(items, "Low Medium", "low_medium"); // 9x15
VarList::push_back(items, "Medium", "medium"); // 9x18
VarList::push_back(items, "Large (10pt)", "large"); // 10x20
VarList::push_back(items, "Large (12pt)", "large12"); // 12x24
VarList::push_back(items, "Large (14pt)", "large14"); // 14x28
VarList::push_back(items, "Large (16pt)", "large16"); // 16x32
myDialogFontPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
items, "Dialogs font (*)", lwidth, kDialogFont);
wid.push_back(myDialogFontPopup);
// Enable HiDPI mode
myHidpiWidget = new CheckboxWidget(myTab, font, myPalettePopup->getRight() + 40,
ypos, "HiDPI mode (*)");
myHidpiWidget = new CheckboxWidget(myTab, font, myDialogFontPopup->getRight() + fontWidth * 5,
ypos + 1, "HiDPI mode (*)");
wid.push_back(myHidpiWidget);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Dialog position
items.clear();
@ -100,14 +118,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
VarList::push_back(items, "Right bottom", 3);
VarList::push_back(items, "Left bottom", 4);
myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
items, "Dialogs position ", lwidth);
items, "Dialogs position", lwidth);
wid.push_back(myPositionPopup);
ypos += lineHeight + V_GAP * 2;
ypos += lineHeight + VGAP * 2;
// Confirm dialog when exiting emulation
myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation");
wid.push_back(myConfirmExitWidget);
ypos += lineHeight + V_GAP * 3;
ypos += lineHeight + VGAP * 3;
// Delay between quick-selecting characters in ListWidget
int swidth = myPalettePopup->getWidth() - lwidth;
@ -119,7 +137,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myListDelaySlider->setStepValue(50);
myListDelaySlider->setTickmarkIntervals(5);
wid.push_back(myListDelaySlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Number of lines a mouse wheel will scroll
myWheelLinesSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
@ -129,7 +147,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myWheelLinesSlider->setMaxValue(10);
myWheelLinesSlider->setTickmarkIntervals(3);
wid.push_back(myWheelLinesSlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Mouse double click speed
myDoubleClickSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
@ -140,7 +158,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myDoubleClickSlider->setStepValue(50);
myDoubleClickSlider->setTickmarkIntervals(8);
wid.push_back(myDoubleClickSlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Initial delay before controller input will start repeating
myControllerDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
@ -151,7 +169,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myControllerDelaySlider->setStepValue(100);
myControllerDelaySlider->setTickmarkIntervals(4);
wid.push_back(myControllerDelaySlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Controller repeat rate
myControllerRateSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
@ -164,10 +182,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myControllerRateSlider);
// Add message concerning usage
ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10;
lwidth = ifont.getStringWidth("(*) Change requires application restart");
new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight,
"(*) Change requires application restart");
ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER;
lwidth = ifont.getStringWidth("(*) Change requires an application restart");
new StaticTextWidget(myTab, ifont, xpos, ypos,
std::min(lwidth, _w - HBORDER * 2), ifont.getFontHeight(),
"(*) Change requires an application restart");
// Add items for tab 0
addToFocusList(wid, myTab, tabID);
@ -185,39 +204,33 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight,
"ROM path" + ELLIPSIS, kChooseRomDirCmd);
wid.push_back(romButton);
xpos = romButton->getRight() + 8;
myRomPath = new EditTextWidget(myTab, font, xpos, ypos + 1,
xpos = romButton->getRight() + fontWidth;
myRomPath = new EditTextWidget(myTab, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1,
_w - xpos - HBORDER - 2, lineHeight, "");
wid.push_back(myRomPath);
xpos = _w - HBORDER - font.getStringWidth("Follow Launcher path") - 24;
ypos += lineHeight + V_GAP * 2;
xpos = _w - HBORDER - font.getStringWidth("Follow Launcher path") - CheckboxWidget::prefixSize(font) - 1;
ypos += lineHeight + VGAP * 2;
myFollowLauncherWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Follow Launcher path");
wid.push_back(myFollowLauncherWidget);
xpos = HBORDER;
ypos += V_GAP * 2;
ypos += VGAP * 2;
// Launcher width and height
myLauncherWidthSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher width ",
lwidth, 0, 6 * fontWidth, "px");
myLauncherWidthSlider->setMinValue(FBMinimum::Width);
myLauncherWidthSlider->setMaxValue(ds.w);
myLauncherWidthSlider->setStepValue(10);
// one tickmark every ~100 pixel
myLauncherWidthSlider->setTickmarkIntervals((ds.w - FBMinimum::Width + 50) / 100);
wid.push_back(myLauncherWidthSlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
myLauncherHeightSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher height ",
lwidth, 0, 6 * fontWidth, "px");
myLauncherHeightSlider->setMinValue(FBMinimum::Height);
myLauncherHeightSlider->setMaxValue(ds.h);
myLauncherHeightSlider->setStepValue(10);
// one tickmark every ~100 pixel
myLauncherHeightSlider->setTickmarkIntervals((ds.h - FBMinimum::Height + 50) / 100);
wid.push_back(myLauncherHeightSlider);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Launcher font
pwidth = font.getStringWidth("2x (1000x760)");
@ -233,7 +246,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items,
"Launcher font ", lwidth);
wid.push_back(myLauncherFontPopup);
ypos += lineHeight + V_GAP * 4;
ypos += lineHeight + VGAP * 4;
// ROM launcher info/snapshot viewer
myRomViewerSize = new SliderWidget(myTab, font, xpos, ypos, "ROM info width ",
@ -245,19 +258,20 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myRomViewerSize->setTickmarkIntervals((myRomViewerSize->getMaxValue() - myRomViewerSize->getMinValue()) / 20);
wid.push_back(myRomViewerSize);
ypos += lineHeight + V_GAP;
ypos += lineHeight + VGAP;
// Snapshot path (load files)
xpos = HBORDER + INDENT;
bwidth = font.getStringWidth("Image path" + ELLIPSIS) + 20 + 1;
bwidth = font.getStringWidth("Image path" + ELLIPSIS) + fontWidth * 2 + 1;
myOpenBrowserButton = new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight,
"Image path" + ELLIPSIS, kChooseSnapLoadDirCmd);
wid.push_back(myOpenBrowserButton);
mySnapLoadPath = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos + 1,
mySnapLoadPath = new EditTextWidget(myTab, font, HBORDER + lwidth,
ypos + (buttonHeight - lineHeight) / 2 - 1,
_w - lwidth - HBORDER * 2 - 2, lineHeight, "");
wid.push_back(mySnapLoadPath);
ypos += lineHeight + V_GAP * 4;
ypos += lineHeight + VGAP * 4;
// Exit to Launcher
xpos = HBORDER;
@ -266,10 +280,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
// Add message concerning usage
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,
"(*) Changes require application restart");
ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER;
lwidth = ifont.getStringWidth("(*) Changes require an application restart");
new StaticTextWidget(myTab, ifont, xpos, ypos,
std::min(lwidth, _w - HBORDER * 2), ifont.getFontHeight(),
"(*) Changes require an application restart");
// Add items for tab 1
addToFocusList(wid, myTab, tabID);
@ -319,8 +334,8 @@ void UIDialog::loadConfig()
myFollowLauncherWidget->setState(settings.getBool("followlauncher"));
// Launcher font
const string& font = settings.getString("launcherfont");
myLauncherFontPopup->setSelected(font, "medium");
const string& launcherFont = settings.getString("launcherfont");
myLauncherFontPopup->setSelected(launcherFont, "medium");
// ROM launcher info viewer
float zoom = instance().settings().getFloat("romviewer");
@ -352,6 +367,10 @@ void UIDialog::loadConfig()
// Confirm dialog when exiting emulation
myConfirmExitWidget->setState(settings.getBool("confirmexit"));
// Dialog font
const string& dialogFont = settings.getString("dialogfont");
myDialogFontPopup->setSelected(dialogFont, "medium");
// Dialog position
myPositionPopup->setSelected(settings.getString("dialogpos"), "0");
@ -375,6 +394,7 @@ void UIDialog::loadConfig()
int cr = settings.getInt("ctrlrate");
myControllerRateSlider->setValue(cr);
handleLauncherSize();
handleRomViewer();
myTab->loadConfig();
@ -398,7 +418,7 @@ void UIDialog::saveConfig()
// Launcher font
settings.setValue("launcherfont",
myLauncherFontPopup->getSelectedTag().toString());
myLauncherFontPopup->getSelectedTag().toString());
// ROM launcher info viewer
int w = myLauncherWidthSlider->getValue();
@ -419,6 +439,10 @@ void UIDialog::saveConfig()
// Enable HiDPI mode
settings.setValue("hidpi", myHidpiWidget->getState());
// Dialog font
settings.setValue("dialogfont",
myDialogFontPopup->getSelectedTag().toString());
// Dialog position
settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString());
@ -458,6 +482,7 @@ void UIDialog::setDefaults()
case 0: // Misc. options
myPalettePopup->setSelected("standard");
myHidpiWidget->setState(false);
myDialogFontPopup->setSelected("medium", "");
myPositionPopup->setSelected("0");
myConfirmExitWidget->setState(false);
myListDelaySlider->setValue(300);
@ -501,6 +526,10 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
setDefaults();
break;
case kDialogFont:
handleLauncherSize();
break;
case kListDelay:
if(myListDelaySlider->getValue() == 0)
{
@ -571,6 +600,29 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UIDialog::handleLauncherSize()
{
// Determine minimal launcher sizebased on the default font
// So what fits with default font should fit for any font.
FontDesc fd = instance().frameBuffer().getFontDesc(myDialogFontPopup->getSelectedTag().toString());
int w = std::max(FBMinimum::Width, FBMinimum::Width * fd.maxwidth / GUI::stellaMediumDesc.maxwidth);
int h = std::max(FBMinimum::Height, FBMinimum::Height * fd.height / GUI::stellaMediumDesc.height);
const Common::Size& ds = instance().frameBuffer().desktopSize();
myLauncherWidthSlider->setMinValue(w);
if(myLauncherWidthSlider->getValue() < myLauncherWidthSlider->getMinValue())
myLauncherWidthSlider->setValue(w);
// one tickmark every ~100 pixel
myLauncherWidthSlider->setTickmarkIntervals((ds.w - w + 67) / 100);
myLauncherHeightSlider->setMinValue(h);
if(myLauncherHeightSlider->getValue() < myLauncherHeightSlider->getMinValue())
myLauncherHeightSlider->setValue(h);
// one tickmark every ~100 pixel
myLauncherHeightSlider->setTickmarkIntervals((ds.h - h + 67) / 100);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*void UIDialog::handleLauncherSize()
// an attempt to limit the minimal and maximal ROM info percentages

View File

@ -33,13 +33,14 @@ class UIDialog : public Dialog, public CommandSender
void setDefaults() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
//void handleLauncherSize();
void handleLauncherSize();
void handleRomViewer();
void createBrowser(const string& title);
private:
enum
{
kDialogFont = 'UIDf',
kListDelay = 'UILd',
kMouseWheel = 'UIMw',
kControllerDelay = 'UIcd',
@ -66,6 +67,7 @@ class UIDialog : public Dialog, public CommandSender
// Misc options
PopUpWidget* myPalettePopup{nullptr};
CheckboxWidget* myHidpiWidget{nullptr};
PopUpWidget* myDialogFontPopup{nullptr};
PopUpWidget* myPositionPopup{nullptr};
CheckboxWidget* myConfirmExitWidget{nullptr};
SliderWidget* myListDelaySlider{nullptr};

View File

@ -78,27 +78,33 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Video settings")
{
const int VGAP = 4;
const int VBORDER = 8;
const int HBORDER = 10;
const int INDENT = 20;
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() + 4;
buttonHeight = font.getLineHeight() * 1.25;
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int INDENT = fontWidth * 2;
int xpos, ypos, tabID;
int lwidth = font.getStringWidth("V-Size adjust "),
pwidth = font.getStringWidth("XXXXxXXXX"),
swidth = font.getMaxCharWidth() * 10 - 2;
pwidth = font.getStringWidth("XXXXxXXXX"),
swidth = font.getMaxCharWidth() * 10 - 2;
WidgetArray wid;
VariantList items;
// Set real dimensions
setSize(60 * fontWidth + HBORDER * 2, 14 * (lineHeight + VGAP) + 14 + _th, max_w, max_h);
setSize(60 * fontWidth + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
max_w, max_h);
// The tab widget
xpos = 2; ypos = 4;
myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2*xpos, _h - _th - buttonHeight - 20);
xpos = 2; ypos = VGAP;
myTab = new TabWidget(this, font, xpos, ypos + _th,
_w - 2*xpos,
_h - _th - VGAP - buttonHeight - VBORDER * 2);
addTabWidget(myTab);
xpos = HBORDER; ypos = VBORDER;
@ -160,7 +166,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myUseVSync);
// Move over to the next column
xpos += mySpeed->getWidth() + 44;
xpos = myVSizeAdjust->getRight() + fontWidth * 3;
ypos = VBORDER;
// Fullscreen
@ -216,7 +222,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
tabID = myTab->addTab(" TV Effects ");
xpos = HBORDER;
ypos = VBORDER;
swidth = font.getMaxCharWidth() * 8 - 4;
swidth = fontWidth * 8 - fontWidth / 2;
// TV Mode
items.clear();
@ -258,7 +264,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0)
CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0)
xpos += myTVContrast->getWidth() + 30;
xpos += myTVContrast->getWidth() + fontWidth * 4;
ypos = VBORDER;
lwidth = font.getStringWidth("Intensity ");
@ -272,7 +278,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
xpos += INDENT;
swidth = font.getMaxCharWidth() * 10;
CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged)
ypos += 8;
ypos += VGAP * 2;
// Scanline intensity and interpolation
xpos -= INDENT;
@ -291,7 +297,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\
desc, kClone ## obj ##Cmd); \
wid.push_back(myClone ## obj); \
ypos += lineHeight + 4 + VGAP;
ypos += buttonHeight + VGAP;
ypos += VGAP;
CREATE_CLONE_BUTTON(RGB, "Clone RGB")

View File

@ -482,26 +482,28 @@ void ButtonWidget::drawWidget(bool hilite)
CheckboxWidget::CheckboxWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, const string& label,
int cmd)
: ButtonWidget(boss, font, x, y, 16, 16, label, cmd)
: ButtonWidget(boss, font, x, y, font.getFontHeight() < 24 ? 16 : 24,
font.getFontHeight() < 24 ? 16 : 24, label, cmd)
{
_flags = Widget::FLAG_ENABLED;
_bgcolor = _bgcolorhi = kWidColor;
_bgcolorlo = kDlgColor;
_editable = true;
_boxSize = boxSize(font);
if(label == "")
_w = 14;
_w = _boxSize;
else
_w = font.getStringWidth(label) + 20;
_h = font.getFontHeight() < 14 ? 14 : font.getFontHeight();
_w = font.getStringWidth(label) + _boxSize + font.getMaxCharWidth() * 0.75;
_h = font.getFontHeight() < _boxSize ? _boxSize : font.getFontHeight();
// Depending on font size, either the font or box will need to be
// centered vertically
if(_h > 14) // center box
_boxY = (_h - 14) / 2;
if(_h > _boxSize) // center box
_boxY = (_h - _boxSize) / 2;
else // center text
_textY = (14 - _font.getFontHeight()) / 2;
_textY = (_boxSize - _font.getFontHeight()) / 2;
setFill(CheckboxWidget::FillType::Normal);
}
@ -549,7 +551,8 @@ void CheckboxWidget::setEditable(bool editable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckboxWidget::setFill(FillType type)
{
/* 8x8 checkbox bitmap */
/* 10x10 checkbox bitmap */
// small versions
static constexpr std::array<uInt32, 10> checked_img_active = {
0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111,
0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111
@ -565,17 +568,36 @@ void CheckboxWidget::setFill(FillType type)
0b1111111111, 0b1111111111, 0b0111111110, 0b0111111110, 0b0001111000
};
/* 18x18 checkbox bitmap */
// large versions
static constexpr std::array<uInt32, 18> checked_img_active_large = {
0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111,
0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111,
0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111,
0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111,
0b111111111111111111, 0b111111111111111111
};
static constexpr std::array<uInt32, 18> checked_img_inactive_large = {
0b111111111111111111, 0b111111111111111111, 0b111111111111111111,
0b111111110011111111, 0b111111100001111111, 0b111111000000111111, 0b111110000000011111,
0b111100000000001111, 0b111000000000000111, 0b111000000000000111, 0b111100000000001111,
0b111110000000011111, 0b111111000000111111, 0b111111100001111111, 0b111111110011111111,
0b111111111111111111, 0b111111111111111111, 0b111111111111111111
};
switch(type)
{
case CheckboxWidget::FillType::Normal:
_img = checked_img_active.data();
_img = _boxSize == 14 ? checked_img_active.data() : checked_img_active_large.data();
_drawBox = true;
break;
case CheckboxWidget::FillType::Inactive:
_img = checked_img_inactive.data();
_img = _boxSize == 14 ? checked_img_inactive.data() : checked_img_inactive_large.data();
_drawBox = true;
break;
case CheckboxWidget::FillType::Circle:
// only used in debugger which only has smaller fonts
_img = checked_img_circle.data();
_drawBox = false;
break;
@ -601,17 +623,17 @@ void CheckboxWidget::drawWidget(bool hilite)
bool onTop = _boss->dialog().isOnTop();
if(_drawBox)
s.frameRect(_x, _y + _boxY, 14, 14, onTop && hilite && isEnabled() && isEditable() ? kWidColorHi : kColor);
s.frameRect(_x, _y + _boxY, _boxSize, _boxSize, onTop && hilite && isEnabled() && isEditable() ? kWidColorHi : kColor);
// Do we draw a square or cross?
s.fillRect(_x + 1, _y + _boxY + 1, 12, 12,
s.fillRect(_x + 1, _y + _boxY + 1, _boxSize - 2, _boxSize - 2,
_changed ? onTop ? kDbgChangedColor : kDlgColor :
isEnabled() && onTop ? _bgcolor : kDlgColor);
if(_state)
s.drawBitmap(_img, _x + 2, _y + _boxY + 2, onTop && isEnabled() ? hilite && isEditable() ? kWidColorHi : kCheckColor
: kColor, 10);
: kColor, _boxSize - 4);
// Finally draw the label
s.drawString(_font, _label, _x + 20, _y + _textY, _w,
s.drawString(_font, _label, _x + prefixSize(_font), _y + _textY, _w,
onTop && isEnabled() ? kTextColor : kColor);
setDirty();
@ -640,7 +662,7 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font,
if(_valueLabelWidth == 0)
_valueLabelGap = 0;
if(_valueLabelGap == 0)
_valueLabelGap = DEF_LBL_GAP;
_valueLabelGap = font.getMaxCharWidth() / 2;
_w = w + _labelWidth + _valueLabelGap + _valueLabelWidth;
}
@ -807,9 +829,9 @@ void SliderWidget::drawWidget(bool hilite)
s.drawString(_font, _label, _x, _y + 2, _labelWidth, isEnabled() ? kTextColor : kColor);
int p = valueToPos(_value),
h = _h - 10,
h = _h - _font.getFontHeight() / 2 - 1,
x = _x + _labelWidth,
y = _y + (_h - h) / 2 + 1;
y = _y + 2 + _font.desc().ascent - (_font.getFontHeight() + 1) / 2 - 1; // align to bottom of font
// Fill the box
s.fillRect(x, y, _w - _labelWidth - _valueLabelGap - _valueLabelWidth, h,

View File

@ -285,7 +285,14 @@ class CheckboxWidget : public ButtonWidget
void handleMouseEntered() override;
void handleMouseLeft() override;
static int boxSize() { return 14; } // box is square
static int boxSize(const GUI::Font& font)
{
return font.getFontHeight() < 24 ? 14 : 22; // box is square
}
static int prefixSize(const GUI::Font& font)
{
return boxSize(font) + font.getMaxCharWidth() * 0.75;
}
protected:
void drawWidget(bool hilite) override;
@ -296,10 +303,13 @@ class CheckboxWidget : public ButtonWidget
bool _drawBox{true};
bool _changed{false};
const uInt32* _outerCircle{nullptr};
const uInt32* _innerCircle{nullptr};
const uInt32* _img{nullptr};
ColorId _fillColor{kColor};
int _boxY{0};
int _textY{0};
int _boxSize{14};
private:
// Following constructors and assignment operators not supported
@ -342,9 +352,6 @@ class SliderWidget : public ButtonWidget
void setTickmarkIntervals(int numIntervals);
protected:
const int DEF_LBL_GAP = 4;
protected:
void handleMouseMoved(int x, int y) override;
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;

View File

@ -1,5 +1,5 @@
%define name stella
%define version 6.1
%define version 6.1.2
%define rel 1
%define enable_sound 1
@ -100,6 +100,9 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version}
%_datadir/icons/large/%{name}.png
%changelog
* Sat Apr 25 2020 Stephen Anthony <sa666666@gmail.com> 6.1.2-1
- Version 6.1.2 release
* Sat Apr 04 2020 Stephen Anthony <sa666666@gmail.com> 6.1.1-1
- Version 6.1.1 release