Merge branch 'master' into feature/full-on-sqlite

This commit is contained in:
Stephen Anthony 2020-12-27 20:21:51 -03:30
commit c4b93c346d
90 changed files with 1184 additions and 1136 deletions

View File

@ -32,12 +32,17 @@
* Added sound to Time Machine playback.
* Added browser dialogs for user saved files.
* Extended global hotkeys for input devices & ports settings.
* Increased sample size for CDFJ+.
* Fixed autofire bug for trackball controllers.
* Fixed bug in TV autodetection in filenames; a filename containing
'PAL' would sometimes misdetect as a PAL ROM.
* Fixed Stelladaptor/2600'daptor devices sometimes not being assigned
correct default mappings.

View File

@ -74,7 +74,7 @@
<li><a href="#CartridgeRAMInformation">Detailed Cartridge Extended RAM Information</a></li>
</ul>
</li>
<li><a href="#DistellaConfiguration">Distella Configuration Files</a></li>
<li><a href="#DistellaConfiguration">DiStella Configuration Files</a></li>
<li><a href="#Howtohack">Tutorial: How to hack a ROM</a></li>
</li>
</ul>
@ -119,14 +119,14 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
<li>Rewind previous advance operations and undo rewinds.</li>
<li>Supports Distella 'configuration directives', which may be used to
<li>Supports DiStella 'configuration directives', which may be used to
override automatic code/data determination in the disassembly. For now,
the following directives are supported: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW.
These directives can be entered at the debugger prompt, or be (automatically)
loaded and saved in configuration files.</li>
<li>Extensive disassembly support, both from the emulation core and with help
from Distella. Where possible, the disassembly differentiates between code,
from DiStella. Where possible, the disassembly differentiates between code,
player and playfield graphics, colors and audio (ie, addresses stored in
GRPx, PFx, COLUxx, AUDxx)
and data (addresses used as an operand of a command). Code sections are also
@ -302,7 +302,7 @@ more convenient.
<li>
"&lt;rom_filename&gt;.cfg"</br>
This file is described in <a href="#DistellaConfiguration">
<b>Distella Configuration Files</b></a>.
<b>DiStella Configuration Files</b></a>.
</br></br>
</li>
<li>
@ -929,7 +929,7 @@ Type "help 'cmd'" to see extended information about the given command.</p>
c - Carry Flag: set (0 or 1), or toggle (no arg)
cheat - Use a cheat code (see manual for cheat types)
clearbreaks - Clear all breakpoints
clearconfig - Clear Distella config directives [bank xx]
clearconfig - Clear DiStella config directives [bank xx]
clearsavestateifs - Clear all savestate points
cleartraps - Clear all traps
clearwatches - Clear all watches
@ -966,11 +966,11 @@ clearsavestateifs - Clear all savestate points
joy1fire - Set joystick 1 fire button to value &lt;x&gt; (0 or 1), or toggle (no arg)
jump - Scroll disassembly to address xx
listbreaks - List breakpoints
listconfig - List Distella config directives [bank xx]
listconfig - List DiStella config directives [bank xx]
listfunctions - List user-defined functions
listsavestateifs - List savestate points
listtraps - List traps
loadconfig - Load Distella config file
loadconfig - Load DiStella config file
loadallstates - Load all emulator states
loadstate - Load emulator state xx (0-9)
n - Negative Flag: set (0 or 1), or toggle (no arg)
@ -989,14 +989,14 @@ clearsavestateifs - Clear all savestate points
runto - Run until string xx in disassembly
runtopc - Run until PC is set to value xx
s - Set Stack Pointer to value xx
save - Save breaks, watches, traps and functions to file xx
saveaccess - Save access counters to CSV file
saveconfig - Save Distella config file (with default name)
savedis - Save Distella disassembly (with default name)
saverom - Save (possibly patched) ROM (with default name)
saveses - Save console session (with default name)
save - Save breaks, watches, traps and functions to file xx (use ? for file dialog)
saveaccess - Save access counters to CSV file (use ? for file dialog)
saveconfig - Save DiStella config file (with default name)
savedis - Save DiStella disassembly (use ? for file dialog)
saverom - Save (possibly patched) ROM (use ? for file dialog)
saveses - Save console session (use ? for file dialog)
savesnap - Save current TIA image to PNG file
saveallstatea - Save all emulator states
saveallstates - Save all emulator states
savestate - Save emulator state xx (valid args 0-9)
savestateif - Create savestate on &lt;condition&gt;
scanline - Advance emulation by &lt;xx&gt; scanlines (default=1)
@ -1349,11 +1349,11 @@ file is loaded, the disassembly will have labels. Even without a symbol file, th
differentiate between code, graphics, data and unused bytes. There are actually two
levels of disassembly in Stella. First, the emulation core tracks accesses as a game
is running, making for very accurate results. This is known as a <b>dynamic</b> analysis.
Second, the built-in Distella code does a <b>static</b> analysis, which tentatively fills
Second, the built-in DiStella code does a <b>static</b> analysis, which tentatively fills
in sections that the dynamic disassembler missed (usually because the addresses haven't
been accessed at runtime yet).</p>
<p>As such, code can be marked in two ways (absolute, when done by the emulation core),
and tentative (when done by Distella, and the emulation core hasn't accessed it yet).
and tentative (when done by DiStella, and the emulation core hasn't accessed it yet).
Such 'tentative' code is marked with the '*' symbol, indicating that it has the potential
to be accessed as code sometime during the program run. This gives very useful information,
since it can indicate areas toggled by an option in the game (ie, when a player dies,
@ -1379,7 +1379,7 @@ by the <a href="#Breakpoints">break</a> command, <b>not</b> the conditional "bre
(which makes sense: conditional breaks can break on any condition, the Program
Counter isn't necessarily involved).</li>
<li><b>Labels</b>: Any labels assigned to the given address, either generated
automatically by Distella, read from a DASM symbol file or custom
automatically by DiStella, read from a DASM symbol file or custom
labels created by the user. If 'Show PC addresses'
(see <a href="#DisassemblySettings"><b>ROM Disassembly Settings</b></a>) is enabled,
the address will be shown in grey.</li>
@ -1393,7 +1393,7 @@ Note that only code, graphics or data will show bytes and can be edited.</li>
<p>At this point, we should explain the various 'types' that the disassembler
can use. These are known as 'directives', and partly correspond to configuration
options from the standalone Distella program. They are listed in order of
options from the standalone DiStella program. They are listed in order of
decreasing hierarchy:</p>
<table border="1" cellpadding=4>
<tr>
@ -1520,7 +1520,7 @@ matches the address of the disassembly line where the mouse was clicked.</li>
<li><b>Disassemble @ current line</b>: Disassemble from the disassembly line where the mouse was clicked.
This allows to fill gaps in the disassembly and is most useful for bankswitched ROMs.</li>
<li><b>Show tentative code</b>: Allow Distella to do a static analysis/disassembly.</li>
<li><b>Show tentative code</b>: Allow DiStella to do a static analysis/disassembly.</li>
<li><b>Show PC addresses</b>: Show Program Counter addresses as labels (where there
isn't already a defined label).</li>
@ -1528,7 +1528,7 @@ isn't already a defined label).</li>
<li><b>Show GFX as binary</b>: Switch between displaying/editing GFX and PGFX sections
in either binary or hexidecimal.</li>
<li><b>Use address relocation</b>: Corresponds to the Distella '-r' option
<li><b>Use address relocation</b>: Corresponds to the DiStella '-r' option
(Relocate calls out of address range).</br>
Note: The code will continue to run fine, but the ROM image will be altered.</li>
@ -1603,7 +1603,7 @@ the RAM in the DPC scheme is not viewable by the 6507, so its addresses start fr
<!-- ///////////////////////////////////////////////////////////////////////// -->
<br>
<h1><a name="DistellaConfiguration">Distella Configuration Files</a></h1>
<h1><a name="DistellaConfiguration">DiStella Configuration Files</a></h1>
<p>As mentioned in <a href="#Disassembly"><b>ROM Disassembly</b></a>, Stella supports the following directives:
CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. While the debugger will try to automatically mark address
space with the appropriate directive, there are times when it will fail. There are

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1375,10 +1375,9 @@
</tr>
<tr>
<td>Toggle adapting display refresh rate to game frame rate
</br>
Note: Not available for macOS.</td>
</br>Note: Not available for macOS</td>
<td>Alt + R</td>
<td>Cmd + R</td>
<td>-</td>
</tr>
<tr>
<td><i>Decrease</i> overscan in fullscreen mode</td>
@ -2813,8 +2812,8 @@
<tr>
<td><pre>-tia.fs_refresh &lt;1|0&gt;</pre></td>
<td>While in fullscreen mode, adapt the display's refresh rate to the game's frame rate
to minimize judder.</br>
Note: Not available for macOS.</td>
to minimize judder.
</br>Note: Not available for macOS</td>
</tr>
<tr>
@ -2897,7 +2896,8 @@
<tr>
<td><pre>-tv.scanlines &lt;0 - 100&gt;</pre></td>
<td>Set TV effects scanline intensity, where 0 means completely off. Note: No scanlines in 1x mode snapshots.</td>
<td>Set TV effects scanline intensity, where 0 means completely off.
</br>Note: No scanlines in 1x mode snapshots</td>
</tr>
<tr>
@ -3073,7 +3073,8 @@
<tr>
<td><pre>-ssinterval &lt;number&gt;</pre></td>
<td>Set the interval in seconds between taking snapshots in continuous snapshot mode (currently 1 - 10).</td>
<td>Set the interval in seconds between taking snapshots in continuous
snapshot mode (currently 1 - 10).</td>
</tr>
<tr>
@ -3123,8 +3124,8 @@
<tr>
<td><pre>-romviewer &lt;float&gt;</pre></td>
<td>Hide ROM Info Viewer in ROM launcher mode (0) or use the
given zoom level.</br>
Note: The zoom level is converted into a percentage in the UI.</td>
given zoom level.
</br>Note: The zoom level is converted into a percentage in the UI.</td>
</tr>
<tr>
@ -3189,6 +3190,16 @@
<td>Make the start path follow ROM launcher navigation.</td>
</tr>
<tr>
<td><pre>-userdir &lt;dir&gt;</pre></td>
<td>Set the path to save user files (property exports, debugger saves) to.</td>
</tr>
<tr>
<td><pre>-saveuserdir &lt;0|1&gt;</pre></td>
<td>Update the user path when navigating in browser.</td>
</tr>
<tr>
<td><pre>-maxres &lt;WxH&gt;</pre></td>
<td>Useful for developers, this sets the maximum size of window that
@ -3197,17 +3208,20 @@
<tr>
<td><pre>-basedir &lt;dir&gt;</pre></td>
<td>Override the base directory for all config files.</td>
<td>Override the base directory for all config files.
<br>Note: Not available for macOS</td>
</tr>
<tr>
<td><pre>-baseinappdir</pre></td>
<td>Override the base directory for all config files by attempting to use the application directory. For now this is only supported in Windows.</td>
<td>Override the base directory for all config files by attempting to use
the application directory.
<br>Note: Only available for Windows</td>
</tr>
<tr>
<td><pre>-help</pre></td>
<td>Prints a help message describing these options, and then
<td>Print a help message describing these options, and then
exit Stella.</td>
</tr>
</table>
@ -3602,7 +3616,7 @@
This depends on the OS and renderer used.</td><td>-fullscreen</td></tr>
<tr><td>Stretch</td><td>In fullscreen mode, completely fill screen with the TIA image.</td><td>-tia.fs_stretch</td></tr>
<tr><td>Adapt display...</td><td>In fullscreen mode, adapt the display's refresh rate to the game's frame rate to minimize judder.
</br>Note: Not available for macOS.</td><td>-tia.fs_refresh</td></tr>
</br>Note: Not available for macOS</td><td>-tia.fs_refresh</td></tr>
<tr><td>Overscan</td><td>In fullscreen mode, add overscan to the TIA image.</td><td>-tia.fs_overscan</td></tr>
<tr><td>Correct aspect ratio</td><td>Enable aspect ratio correct scaling.
</br>Note: Creates a cleaner looking TIA image when disabled (like z26 and old versions of Stella) vs. a correctly emulated aspect ratio when enabled.</td><td>-tia.correct_aspect</td></tr>
@ -3652,7 +3666,7 @@
<tr><td>Blend (phosphor)</td><td>Blend level to use in phosphor mode for all ROMs
(needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>
<tr><td>Scanline intensity</td><td>Sets scanline black-level intensity.</br>
Note: No scanlines in 1x mode snapshots.</td><td>-tv.scanlines</td></tr>
Note: No scanlines in 1x mode snapshots</td><td>-tv.scanlines</td></tr>
<tr><td>Clone RGB</td><td>Copy 'RGB' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone S-Video</td><td>Copy 'S-Video' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Composite</td><td>Copy 'Composite' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
@ -3930,7 +3944,7 @@
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>
<tr><td>Joystick database</td><td>Show all joysticks that Stella knows about, with the option to remove them</td><td>&nbsp;</td></tr>
<tr><td>Joystick Database</td><td>Show all joysticks that Stella knows about, with the option to remove them</td><td>&nbsp;</td></tr>
<tr><td>Erase EEPROM</td><td>Erase the whole AtariVox/SaveKey flash memory</td><td>&nbsp;</td></tr>
<tr><td>AtariVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr>
</table>
@ -5003,11 +5017,11 @@ Ms Pac-Man (Stella extended codes):
<p>The buttons at the bottom of the dialogs work as follows:
<ul>
<li><b>Defaults</b>: Reset the properties to those built into Stella.</li>
<li><b>Save</b>: Save the properties for the <i>currently selected ROM only</i>
to a properties file in the users default save directory.</li>
<li><b>Export</b>: Export the properties for the <i>currently selected ROM only</i>
to a properties file in the user's default save directory.</li>
<li><b>OK</b>: Merge/commit any changes into the ROM properties database, which
contains info on all ROMs.</li>
<li><b>Cancel</b>: Revert any changes in the dialog, and cancel the operation.</li>
contains info of all ROMs.</li>
<li><b>Cancel</b>: Revert any changes in the dialog and cancel the operation.</li>
</ul>
<p>The name of the properties file will depend on the version of Stella, as follows:</p>

View File

@ -35,15 +35,14 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent, font, "Cheat codes")
{
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
//fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("One shot "),
VGAP = Dialog::vGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
int xpos, ypos;
WidgetArray wid;
ButtonWidget* b;

View File

@ -106,21 +106,6 @@ class FilesystemNodeZIP : public AbstractFSNode
// ZipHandler static reference variable responsible for accessing ZIP files
static unique_ptr<ZipHandler> myZipHandler;
// Get last component of path
static const char* lastPathComponent(const string& str)
{
if(str.empty())
return "";
const char* start = str.c_str();
const char* cur = start + str.size() - 2;
while (cur >= start && !(*cur == '/' || *cur == '\\'))
--cur;
return cur + 1;
}
};
#endif

View File

@ -49,7 +49,7 @@ class PhysicalJoystickHandler
private:
struct StickInfo
{
StickInfo(nlohmann::json map, PhysicalJoystickPtr stick = nullptr)
explicit StickInfo(nlohmann::json map, PhysicalJoystickPtr stick = nullptr)
: mapping(map), joy{std::move(stick)} {}
nlohmann::json mapping;

View File

@ -242,7 +242,7 @@ namespace BSPF
// Find location (if any) of the second string within the first,
// starting from 'startpos' in the first string
static size_t findIgnoreCase(const string& s1, const string& s2, size_t startpos = 0)
static size_t findIgnoreCase(string_view s1, string_view s2, size_t startpos = 0)
{
auto pos = std::search(s1.cbegin()+startpos, s1.cend(),
s2.cbegin(), s2.cend(), [](char ch1, char ch2) {
@ -252,7 +252,7 @@ namespace BSPF
}
// Test whether the first string contains the second one (case insensitive)
inline bool containsIgnoreCase(const string& s1, const string& s2)
inline bool containsIgnoreCase(string_view s1, string_view s2)
{
return findIgnoreCase(s1, s2) != string::npos;
}
@ -260,7 +260,7 @@ namespace BSPF
// Test whether the first string matches the second one (case insensitive)
// - the first character must match
// - the following characters must appear in the order of the first string
inline bool matches(const string& s1, const string& s2)
inline bool matches(string_view s1, string_view s2)
{
if(startsWithIgnoreCase(s1, s2.substr(0, 1)))
{
@ -336,6 +336,17 @@ namespace BSPF
}
#endif
}
inline bool isWhiteSpace(const char s)
{
const string WHITESPACES = " ,.;:+-*&/\\'";
for(size_t i = 0; i < WHITESPACES.length(); ++i)
if(s == WHITESPACES[i])
return true;
return false;
}
} // namespace BSPF
#endif

View File

@ -57,15 +57,9 @@ void AtariNTSC::generateKernels()
const uInt8* ptr = myRGBPalette.data();
for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry)
{
#ifdef BLARGG_PALETTE
float r = myImpl.to_float[*ptr++],
g = myImpl.to_float[*ptr++],
b = myImpl.to_float[*ptr++];
#else
float r = (*ptr++) / 255.F * rgb_unit + rgb_offset,
g = (*ptr++) / 255.F * rgb_unit + rgb_offset,
b = (*ptr++) / 255.F * rgb_unit + rgb_offset;
#endif
float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q );
// Generate kernel
@ -325,11 +319,6 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariNTSC::init(init_t& impl, const Setup& setup)
{
#ifdef BLARGG_PALETTE
impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset;
impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit;
#endif
impl.artifacts = setup.artifacts;
if ( impl.artifacts > 0 )
impl.artifacts *= artifacts_max - artifacts_mid;
@ -342,30 +331,8 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
initFilters(impl, setup);
#ifdef BLARGG_PALETTE
/* generate gamma table */
if (true) /* was (gamma_size > 1) */
{
float const to_float = 1.F / (gamma_size - 1/*(gamma_size > 1)*/);
float const gamma = 1.1333F - setup.gamma * 0.5F;
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
int i;
for(i = 0; i < gamma_size; i++)
impl.to_float[i] =
powf(i * to_float, gamma) * impl.contrast + impl.brightness;
}
#endif
/* setup decoder matricies */
{
#ifdef BLARGG_PALETTE
float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue;
float sat = setup.saturation + 1;
hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue);
float s = sinf(hue)*sat;
float c = cosf(hue)*sat;
#endif
float* out = impl.to_rgb.data();
int n;
@ -378,13 +345,8 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
{
float i = *in++;
float q = *in++;
#ifdef BLARGG_PALETTE
*out++ = i * c - q * s;
*out++ = i * s + q * c;
#else
*out++ = i ;
*out++ = i;
*out++ = q;
#endif
}
while ( --n2 );
#if 0 // burst_count is always 0
@ -561,32 +523,16 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const AtariNTSC::Setup AtariNTSC::TV_Composite = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F
#else
0.0F, 0.15F, 0.0F, 0.0F, 0.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_SVideo = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F
#else
0.0F, 0.45F, -1.0F, -1.0F, 0.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_RGB = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F
#else
0.2F, 0.70F, -1.0F, -1.0F, -1.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_Bad = {
#ifdef BLARGG_PALETTE
0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F
#else
0.2F, 0.1F, 0.5F, 0.5F, 0.5F
#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -46,8 +46,6 @@
#include "FrameBufferConstants.hxx"
#include "bspf.hxx"
//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined
class AtariNTSC
{
public:
@ -59,18 +57,9 @@ class AtariNTSC
struct Setup
{
// Basic parameters
#ifdef BLARGG_PALETTE
float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees
float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5)
float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5)
#endif
float sharpness{0.F}; // edge contrast enhancement/blurring
// Advanced parameters
#ifdef BLARGG_PALETTE
float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5)
#endif
float resolution{0.F}; // image resolution
float artifacts{0.F}; // artifacts caused by color changes
float fringing{0.F}; // color artifacts caused by brightness changes
@ -133,9 +122,6 @@ class AtariNTSC
burst_size = entry_size / burst_count,
kernel_half = 16,
kernel_size = kernel_half * 2 + 1,
#ifdef BLARGG_PALETTE
gamma_size = 256,
#endif
rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)),
rgb_kernel_size = burst_size / alignment_count,
@ -170,20 +156,12 @@ class AtariNTSC
struct init_t
{
std::array<float, burst_count * 6> to_rgb{0.F};
#ifdef BLARGG_PALETTE
std::array<float, gamma_size> to_float{0.F};
float contrast{0.F};
float brightness{0.F};
#endif
float artifacts{0.F};
float fringing{0.F};
std::array<float, rescale_out * kernel_size * 2> kernel{0.F};
init_t() {
to_rgb.fill(0.0);
#ifdef BLARGG_PALETTE
to_float.fill(0.0);
#endif
kernel.fill(0.0);
}
};

View File

@ -77,19 +77,11 @@ void NTSCFilter::selectAdjustable(int direction,
{
if(direction == +1)
{
#ifdef BLARGG_PALETTE
myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
#else
myCurrentAdjustable = (myCurrentAdjustable + 1) % 5;
#endif
}
else if(direction == -1)
{
#ifdef BLARGG_PALETTE
if(myCurrentAdjustable == 0) myCurrentAdjustable = 9;
#else
if(myCurrentAdjustable == 0) myCurrentAdjustable = 4;
#endif
else --myCurrentAdjustable;
}
@ -139,13 +131,6 @@ void NTSCFilter::loadConfig(const Settings& settings)
{
// Load adjustables for custom mode
#ifdef BLARGG_PALETTE
myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F);
myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F);
myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F);
myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F);
myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F);
#endif
myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F);
myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F);
myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F);
@ -157,13 +142,6 @@ void NTSCFilter::loadConfig(const Settings& settings)
void NTSCFilter::saveConfig(Settings& settings) const
{
// Save adjustables for custom mode
#ifdef BLARGG_PALETTE
settings.setValue("tv.hue", myCustomSetup.hue);
settings.setValue("tv.saturation", myCustomSetup.saturation);
settings.setValue("tv.contrast", myCustomSetup.contrast);
settings.setValue("tv.brightness", myCustomSetup.brightness);
settings.setValue("tv.gamma", myCustomSetup.gamma);
#endif
settings.setValue("tv.sharpness", myCustomSetup.sharpness);
settings.setValue("tv.resolution", myCustomSetup.resolution);
settings.setValue("tv.artifacts", myCustomSetup.artifacts);
@ -194,13 +172,6 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::setCustomAdjustables(const Adjustable& adjustable)
{
#ifdef BLARGG_PALETTE
//myCustomSetup.hue = scaleFrom100(adjustable.hue);
//myCustomSetup.saturation = scaleFrom100(adjustable.saturation);
//myCustomSetup.contrast = scaleFrom100(adjustable.contrast);
//myCustomSetup.brightness = scaleFrom100(adjustable.brightness);
//myCustomSetup.gamma = scaleFrom100(adjustable.gamma);
#endif
myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness);
myCustomSetup.resolution = scaleFrom100(adjustable.resolution);
myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts);
@ -212,13 +183,6 @@ void NTSCFilter::setCustomAdjustables(const Adjustable& adjustable)
void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
const AtariNTSC::Setup& setup) const
{
#ifdef BLARGG_PALETTE
//adjustable.hue = scaleTo100(setup.hue);
//adjustable.saturation = scaleTo100(setup.saturation);
//adjustable.contrast = scaleTo100(setup.contrast);
//adjustable.brightness = scaleTo100(setup.brightness);
//adjustable.gamma = scaleTo100(setup.gamma);
#endif
adjustable.sharpness = scaleTo100(setup.sharpness);
adjustable.resolution = scaleTo100(setup.resolution);
adjustable.artifacts = scaleTo100(setup.artifacts);
@ -230,16 +194,7 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ifdef BLARGG_PALETTE
const std::array<NTSCFilter::AdjustableTag, 10> NTSCFilter::ourCustomAdjustables = { {
{ "contrast", &myCustomSetup.contrast },
{ "brightness", &myCustomSetup.brightness },
{ "hue", &myCustomSetup.hue },
{ "saturation", &myCustomSetup.saturation },
{ "gamma", &myCustomSetup.gamma },
#else
const std::array<NTSCFilter::AdjustableTag, int(NTSCFilter::Adjustables::NUM_ADJUSTABLES)> NTSCFilter::ourCustomAdjustables = { {
#endif
{ "sharpness", &myCustomSetup.sharpness },
{ "resolution", &myCustomSetup.resolution },
{ "artifacts", &myCustomSetup.artifacts },

View File

@ -59,12 +59,7 @@ class NTSCFilter
/* Normally used in conjunction with custom mode, contains all
aspects currently adjustable in NTSC TV emulation. */
struct Adjustable {
#ifdef BLARGG_PALETTE
uInt32 hue, saturation, contrast, brightness, gamma,
sharpness, resolution, artifacts, fringing, bleed;
#else
uInt32 sharpness, resolution, artifacts, fringing, bleed;
#endif
uInt32 sharpness{0}, resolution{0}, artifacts{0}, fringing{0}, bleed{0};
};
public:
@ -153,11 +148,7 @@ class NTSCFilter
float* value{nullptr};
};
uInt32 myCurrentAdjustable{0};
#ifdef BLARGG_PALETTE
static const std::array<AdjustableTag, 10> ourCustomAdjustables;
#else
static const std::array<AdjustableTag, 5> ourCustomAdjustables;
#endif
private:
// Following constructors and assignment operators not supported

View File

@ -1041,7 +1041,7 @@ string CartDebug::saveConfigFile()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::saveDisassembly()
string CartDebug::saveDisassembly(string path)
{
string NTSC_COLOR[16] = {
"BLACK", "YELLOW", "BROWN", "ORANGE",
@ -1350,9 +1350,16 @@ string CartDebug::saveDisassembly()
// And finally, output the disassembly
out << buf.str();
const string& propsname =
myConsole.properties().get(PropType::Cart_Name) + ".asm";
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + propsname);
if(path.empty())
path = myOSystem.userDir().getPath()
+ myConsole.properties().get(PropType::Cart_Name) + ".asm";
else
// Append default extension when missing
if(path.find_last_of('.') == string::npos)
path += ".asm";
FilesystemNode node(path);
stringstream retVal;
try
{
@ -1370,11 +1377,18 @@ string CartDebug::saveDisassembly()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::saveRom()
string CartDebug::saveRom(string path)
{
const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".a26";
if(path.empty())
path = myOSystem.userDir().getPath()
+ myConsole.properties().get(PropType::Cart_Name) + ".a26";
else
// Append default extension when missing
if(path.find_last_of('.') == string::npos)
path += ".a26";
FilesystemNode node(path);
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom);
if(myConsole.cartridge().saveROM(node))
return "saved ROM as " + node.getShortPath();
else
@ -1382,7 +1396,7 @@ string CartDebug::saveRom()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::saveAccessFile()
string CartDebug::saveAccessFile(string path)
{
stringstream out;
out << myConsole.tia().getAccessCounters();
@ -1391,8 +1405,15 @@ string CartDebug::saveAccessFile()
try
{
const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".csv";
FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom);
if(path.empty())
path = myOSystem.userDir().getPath()
+ myConsole.properties().get(PropType::Cart_Name) + ".csv";
else
// Append default extension when missing
if(path.find_last_of('.') == string::npos)
path += ".csv";
FilesystemNode node(path);
node.write(out);
return "saved access counters as " + node.getShortPath();

View File

@ -236,13 +236,13 @@ class CartDebug : public DebuggerSystem
/**
Save disassembly and ROM file
*/
string saveDisassembly();
string saveRom();
string saveDisassembly(string path);
string saveRom(string path);
/**
Save access counters file
*/
string saveAccessFile();
string saveAccessFile(string path);
/**
Show Distella directives (both set by the user and determined by Distella)

View File

@ -35,6 +35,7 @@
#include "PromptWidget.hxx"
#include "RomWidget.hxx"
#include "ProgressDialog.hxx"
#include "BrowserDialog.hxx"
#include "TimerManager.hxx"
#include "Vec.hxx"
@ -564,6 +565,12 @@ string DebuggerParser::eval()
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& DebuggerParser::cartName() const
{
return debugger.myOSystem.console().properties().get(PropType::Cart_Name);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerParser::listTraps(bool listCond)
{
@ -629,10 +636,6 @@ string DebuggerParser::trapStatus(const Trap& trap)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string DebuggerParser::saveScriptFile(string file)
{
// Append 'script' extension when necessary
if(file.find_last_of('.') == string::npos)
file += ".script";
stringstream out;
Debugger::FunctionDefMap funcs = debugger.getFunctionDefMap();
for(const auto& [name, cmd]: funcs)
@ -674,7 +677,16 @@ string DebuggerParser::saveScriptFile(string file)
out << endl;
}
FilesystemNode node(debugger.myOSystem.defaultSaveDir().getPath() + file);
// Append 'script' extension when necessary
if(file.find_last_of('.') == string::npos)
file += ".script";
// Use user dir if no path is provided
if(file.find_first_of(FilesystemNode::PATH_SEPARATOR) == string::npos)
file = debugger.myOSystem.userDir().getPath() + file;
FilesystemNode node(file);
try
{
node.write(out);
@ -1132,8 +1144,7 @@ void DebuggerParser::executeDump()
else
{
ostringstream file;
file << debugger.myOSystem.defaultSaveDir()
<< debugger.myOSystem.console().properties().get(PropType::Cart_Name) << "_dbg_";
file << debugger.myOSystem.userDir() << cartName() << "_dbg_";
if(execDepth > 0)
{
file << execPrefix;
@ -1228,7 +1239,7 @@ void DebuggerParser::executeExec()
file += ".script";
FilesystemNode node(file);
if (!node.exists())
node = FilesystemNode(debugger.myOSystem.defaultSaveDir().getPath() + file);
node = FilesystemNode(debugger.myOSystem.userDir().getPath() + file);
if (argCount == 2) {
execPrefix = argStrings[1];
@ -1833,14 +1844,28 @@ void DebuggerParser::executeS()
// "save"
void DebuggerParser::executeSave()
{
commandResult << saveScriptFile(argStrings[0]);
if(argCount && argStrings[0] == "?")
{
debugger.myDialog->showBrowser(DebuggerDialog::svScript, cartName() + ".script");
// avoid printing a new prompt
commandResult << "_EXIT_DEBUGGER";
}
else
commandResult << saveScriptFile(argStrings[0]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "saveaccess"
void DebuggerParser::executeSaveAccess()
{
commandResult << debugger.cartDebug().saveAccessFile();
if(argCount && argStrings[0] == "?")
{
debugger.myDialog->showBrowser(DebuggerDialog::svAccess, cartName() + ".csv");
// avoid printing a new prompt
commandResult << "_EXIT_DEBUGGER";
}
else
commandResult << debugger.cartDebug().saveAccessFile(argCount ? argStrings[0] : EmptyString);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1854,14 +1879,28 @@ void DebuggerParser::executeSaveconfig()
// "savedis"
void DebuggerParser::executeSavedisassembly()
{
commandResult << debugger.cartDebug().saveDisassembly();
if(argCount && argStrings[0] == "?")
{
debugger.myDialog->showBrowser(DebuggerDialog::svDis, cartName() + ".asm");
// avoid printing a new prompt
commandResult << "_EXIT_DEBUGGER";
}
else
commandResult << debugger.cartDebug().saveDisassembly(argCount ? argStrings[0] : EmptyString);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "saverom"
void DebuggerParser::executeSaverom()
{
commandResult << debugger.cartDebug().saveRom();
if(argCount && argStrings[0] == "?")
{
debugger.myDialog->showBrowser(DebuggerDialog::svRom, cartName() + ".a26");
// avoid printing a new prompt
commandResult << "_EXIT_DEBUGGER";
}
else
commandResult << debugger.cartDebug().saveRom(argCount ? argStrings[0] : EmptyString);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1870,13 +1909,27 @@ void DebuggerParser::executeSaveses()
{
ostringstream filename;
auto timeinfo = BSPF::localTime();
filename << debugger.myOSystem.defaultSaveDir()
<< std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt");
FilesystemNode file(filename.str());
if(debugger.prompt().saveBuffer(file))
commandResult << "saved " + file.getShortPath() + " OK";
filename << std::put_time(&timeinfo, "session_%F_%H-%M-%S.txt");
if(argCount && argStrings[0] == "?")
{
debugger.myDialog->showBrowser(DebuggerDialog::svSession, filename.str());
commandResult << "_EXIT_DEBUGGER";
}
else
commandResult << "unable to save session";
{
ostringstream path;
if(argCount)
path << argStrings[0];
else
path << debugger.myOSystem.userDir() << filename.str();
FilesystemNode file(path.str());
if(debugger.prompt().saveBuffer(file))
commandResult << "saved " + file.getShortPath() + " OK";
else
commandResult << "unable to save session";
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2616,9 +2669,10 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
"dump",
"Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs]",
"Example:\n"
" dump f000 - dumps 128 bytes @ f000\n"
" dump f000 - dumps 128 bytes from f000\n"
" dump f000 f0ff - dumps all bytes from f000 to f0ff\n"
" dump f000 f0ff 7 - dumps all bytes from f000 to f0ff, CPU state and input registers into a file",
" dump f000 f0ff 7 - dumps all bytes from f000 to f0ff,\n"
" CPU state and input registers into a file in user dir",
true,
false,
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
@ -3042,7 +3096,8 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
{
"save",
"Save breaks, watches, traps and functions to file xx",
"Example: save commands.script",
"Example: save commands.script, save ?\n"
"NOTE: saves to user dir by default",
true,
false,
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
@ -3052,10 +3107,11 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
{
"saveaccess",
"Save the access counters to CSV file",
"Example: saveaccess (no parameters)",
"Example: saveaccess, saveaccess ?\n"
"NOTE: saves to user dir by default",
false,
false,
{ Parameters::ARG_END_ARGS },
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
std::mem_fn(&DebuggerParser::executeSaveAccess)
},
@ -3071,34 +3127,34 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
{
"savedis",
"Save Distella disassembly (with default name)",
"Example: savedis\n"
"NOTE: saves to default save location",
"Save Distella disassembly",
"Example: savedis, savedis ?\n"
"NOTE: saves to user dir by default",
false,
false,
{ Parameters::ARG_END_ARGS },
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
std::mem_fn(&DebuggerParser::executeSavedisassembly)
},
{
"saverom",
"Save (possibly patched) ROM (with default name)",
"Example: saverom\n"
"NOTE: saves to default save location",
"Save (possibly patched) ROM",
"Example: saverom, saverom ?\n"
"NOTE: saves to user dir by default",
false,
false,
{ Parameters::ARG_END_ARGS },
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
std::mem_fn(&DebuggerParser::executeSaverom)
},
{
"saveses",
"Save console session (with default name)",
"Example: saveses\n"
"NOTE: saves to default save location",
"Save console session",
"Example: saveses, saveses ?\n"
"NOTE: saves to user dir by default",
false,
false,
{ Parameters::ARG_END_ARGS },
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
std::mem_fn(&DebuggerParser::executeSaveses)
},

View File

@ -65,6 +65,7 @@ class DebuggerParser
bool validateArgs(int cmd);
string eval();
string saveScriptFile(string file);
const string& cartName() const;
private:
// Constants for argument processing

View File

@ -34,7 +34,7 @@ DataGridOpsWidget::DataGridOpsWidget(GuiObject* boss, const GUI::Font& font,
_zeroButton = new ButtonWidget(boss, font, xpos, ypos, bwidth, bheight,
"0", kDGZeroCmd);
_zeroButton->setToolTip("Zero currently selected value");
ypos += bheight + space;
_invButton = new ButtonWidget(boss, font, xpos, ypos, bwidth, bheight,
"Inv", kDGInvertCmd);

View File

@ -46,6 +46,7 @@
#include "ConsoleMediumBFont.hxx"
#include "StellaMediumFont.hxx"
#include "OptionsDialog.hxx"
#include "BrowserDialog.hxx"
#include "StateManager.hxx"
#include "FrameManager.hxx"
#include "OSystem.hxx"
@ -399,6 +400,66 @@ void DebuggerDialog::createFont()
tooltip().setFont(*myNFont);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName)
{
string title, command;
switch(type)
{
case BrowserType::svAccess:
title = "Access Counters";
command = "saveaccess";
break;
case BrowserType::svDis:
title = "Disassembly";
command = "savedis";
break;
case BrowserType::svRom:
title = "ROM";
command = "saverom";
break;
case BrowserType::svScript:
title = "Workbench";
command = "save";
break;
case BrowserType::svSession:
title = "Session";
command = "saveses";
break;
default:
break;
}
if(command != EmptyString)
{
BrowserDialog::show(this, instance().frameBuffer().font(), "Save " + title + " as",
instance().userDir().getPath() + defaultName,
BrowserDialog::Mode::FileSave,
[this, command](bool OK, const FilesystemNode& node) {
if(OK) runCommand(node, command);
else runCommand(node);
});
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::runCommand(const FilesystemNode& node, const string& command)
{
if(command != EmptyString)
{
string result = instance().debugger().parser().run(command + " {" +
node.getPath() + "}");
prompt().print(result + '\n');
}
prompt().printPrompt();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::showFatalMessage(const string& msg)
{

View File

@ -21,6 +21,7 @@
class Debugger;
class OSystem;
class DialogContainer;
class FilesystemNode;
class ButtonWidget;
class CpuWidget;
class PromptWidget;
@ -54,6 +55,13 @@ class DebuggerDialog : public Dialog
kMediumFontMinW = 1160, kMediumFontMinH = 770,
kLargeFontMinW = 1160, kLargeFontMinH = 870
};
enum BrowserType {
svAccess, // saveaccess
svDis, // savedis
svRom, // saverom
svScript, // save
svSession // saveses
};
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
int x, int y, int w, int h);
@ -74,6 +82,7 @@ class DebuggerDialog : public Dialog
void showFatalMessage(const string& msg);
void saveConfig() override;
void showBrowser(BrowserType type, const string& defaultName);
private:
void setPosition() override { positionAt(0); }
@ -113,11 +122,14 @@ class DebuggerDialog : public Dialog
kDDSAdvCmd = 'DDsv',
kDDRewindCmd = 'DDrw',
kDDUnwindCmd = 'DDuw',
kDDRunCmd = 'DDex',
kDDRunCmd = 'DDex',
kDDExitFatalCmd = 'DDer',
kDDOptionsCmd = 'DDop'
};
void runCommand(const FilesystemNode& node,
const string& command = EmptyString);
TabWidget *myTab{nullptr}, *myRomTab{nullptr};
PromptWidget* myPrompt{nullptr};
@ -135,7 +147,7 @@ class DebuggerDialog : public Dialog
ButtonWidget* myUnwindButton{nullptr};
unique_ptr<GUI::MessageBox> myFatalError;
unique_ptr<OptionsDialog> myOptions;
unique_ptr<OptionsDialog> myOptions;
unique_ptr<GUI::Font> myLFont; // used for labels
unique_ptr<GUI::Font> myNFont; // used for normal text

View File

@ -76,13 +76,12 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
bits->setTarget(this); \
bits->setID(bitsID); \
if(editable) addFocusWidget(bits); else bits->setEditable(false); \
xpos += bits->getWidth() + 5; \
bits->setList(off, on);
// SWCHA bits in 'poke' mode
labels.clear();
CREATE_IO_REGS("SWCHA(W)", mySWCHAWriteBits, kSWCHABitsID, true)
col = xpos + 20; // remember this for adding widgets to the second column
col = xpos + mySWCHAWriteBits->getWidth() + 25; // remember this for adding widgets to the second column
// SWACNT bits
xpos = 10; ypos += lineHeight + 5;

View File

@ -232,7 +232,7 @@ class CartridgeCM : public Cartridge
/**
Inform the cartridge about the parent CompuMate controller
*/
void setCompuMate(shared_ptr<CompuMate>& cmate) { myCompuMate = cmate; }
void setCompuMate(const shared_ptr<CompuMate>& cmate) { myCompuMate = cmate; }
/**
Get the current keyboard column

View File

@ -316,13 +316,13 @@ string Console::formatFromFilename() const
{ R"([ _\-(\[<]+NTSC[ _-]?50)", "NTSC50" },
{ R"([ _\-(\[<]+PAL[ _-]?60)", "PAL60" },
{ R"([ _\-(\[<]+SECAM[ _-]?60)", "SECAM60" },
{ R"([ _\-(\[<]+NTSC[ _\-)\]>]?)", "NTSC" },
{ R"([ _\-(\[<]+PAL[ _\-)\]>]?)", "PAL" },
{ R"([ _\-(\[<]+SECAM[ _\-)\]>]?)", "SECAM" }
{ R"([ _\-(\[<]+NTSC[ _\-)\]>.])", "NTSC" },
{ R"([ _\-(\[<]+PAL[ _\-)\]>.])", "PAL" },
{ R"([ _\-(\[<]+SECAM[ _\-)\]>.])", "SECAM" }
}};
// Get filename *without* extension, and search using regex's above
const string& filename = myOSystem.romFile().getNameWithExt("");
// Get filename, and search using regex's above
const string& filename = myOSystem.romFile().getName();
for(size_t i = 0; i < Pattern.size(); ++i)
{
try

View File

@ -49,14 +49,6 @@ void FilesystemNode::setPath(const string& path)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode& FilesystemNode::operator/=(const string& path)
{
// This part could probably be put in a virtual function, but it seems like
// a waste since almost every system uses the same separator, except Windows
#ifdef BSPF_WINDOWS
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
if (path != EmptyString)
{
string newPath = getPath();
@ -67,7 +59,6 @@ FilesystemNode& FilesystemNode::operator/=(const string& path)
}
return *this;
#undef PATH_SEPARATOR
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -48,6 +48,13 @@ class FSList : public vector<FilesystemNode> { };
*/
class FilesystemNode
{
public:
#ifdef BSPF_WINDOWS
static constexpr char PATH_SEPARATOR = '\\';
#else
static constexpr char PATH_SEPARATOR = '/';
#endif
public:
/**
* Flag to tell listDir() which kind of files to list.
@ -471,6 +478,26 @@ class AbstractFSNode
* a try-catch block.
*/
virtual size_t write(const stringstream& buffer) const { return 0; }
/**
* Returns the last component of a given path.
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
static const char* lastPathComponent(const string& str)
{
if(str.empty())
return "";
const char* start = str.c_str();
const char* cur = start + str.size() - 2;
while (cur >= start && !(*cur == '/' || *cur == '\\'))
--cur;
return cur + 1;
}
};
#endif

View File

@ -211,8 +211,8 @@ void OSystem::loadConfig(const Settings::Options& options)
{
// Get base directory and config file from derived class
// It will decide whether it can override its default location
string baseDir, defSaveDir, defLoadDir;
getBaseDirAndConfig(baseDir, defSaveDir, defLoadDir,
string baseDir, homeDir;
getBaseDirAndConfig(baseDir, homeDir,
ourOverrideBaseDirWithApp, ourOverrideBaseDir);
// Get fully-qualified pathnames, and make directories when needed
@ -220,13 +220,9 @@ void OSystem::loadConfig(const Settings::Options& options)
if(!myBaseDir.isDirectory())
myBaseDir.makeDir();
myDefaultSaveDir = FilesystemNode(defSaveDir);
if(!myDefaultSaveDir.isDirectory())
myDefaultSaveDir.makeDir();
myDefaultLoadDir = FilesystemNode(defLoadDir);
if(!myDefaultLoadDir.isDirectory())
myDefaultLoadDir.makeDir();
myHomeDir = FilesystemNode(homeDir);
if(!myHomeDir.isDirectory())
myHomeDir.makeDir();
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "settings");
if(!mySettingsDb->initialize())
@ -234,9 +230,16 @@ void OSystem::loadConfig(const Settings::Options& options)
myConfigFile = FilesystemNode(mySettingsDb->databaseFileName());
mySettings->setRepository(createSettingsRepository());
mySettings->load(options);
// userDir is NOT affected by '-baseDir'and '-basedirinapp' params
string userDir = mySettings->getString("userdir");
if(userDir.empty())
userDir = homeDir;
myUserDir = FilesystemNode(userDir);
if(!myUserDir.isDirectory())
myUserDir.makeDir();
Logger::instance().setLogParameters(mySettings->getInt("loglevel"),
mySettings->getBool("logtoconsole"));
Logger::debug("Loading config options ...");
@ -286,7 +289,7 @@ void OSystem::setConfigPaths()
#ifdef PNG_SUPPORT
const string& ssSaveDir = mySettings->getString("snapsavedir");
if(ssSaveDir == EmptyString)
mySnapshotSaveDir = defaultSaveDir();
mySnapshotSaveDir = userDir();
else
mySnapshotSaveDir = FilesystemNode(ssSaveDir);
if(!mySnapshotSaveDir.isDirectory())
@ -294,7 +297,7 @@ void OSystem::setConfigPaths()
const string& ssLoadDir = mySettings->getString("snaploaddir");
if(ssLoadDir == EmptyString)
mySnapshotLoadDir = defaultLoadDir();
mySnapshotLoadDir = userDir();
else
mySnapshotLoadDir = FilesystemNode(ssLoadDir);
if(!mySnapshotLoadDir.isDirectory())
@ -324,6 +327,14 @@ void OSystem::setConfigPaths()
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setUserDir(const string& path)
{
mySettings->setValue("userdir", path);
myUserDir = FilesystemNode(path);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool OSystem::checkUserPalette(bool outputError) const
{

View File

@ -316,11 +316,11 @@ class OSystem
const FilesystemNode& romFile() const { return myRomFile; }
/**
The default locations for saving and loading various files that
don't already have a specific location.
The default and user defined locations for saving and loading various
files that don't already have a specific location.
*/
const FilesystemNode& defaultSaveDir() const { return myDefaultSaveDir; }
const FilesystemNode& defaultLoadDir() const { return myDefaultLoadDir; }
const FilesystemNode& homeDir() const { return myHomeDir; }
const FilesystemNode& userDir() const { return myUserDir; }
/**
Open the given ROM and return an array containing its contents.
@ -425,6 +425,9 @@ class OSystem
static void overrideBaseDir(const string& path) { ourOverrideBaseDir = path; }
static void overrideBaseDirWithApp() { ourOverrideBaseDirWithApp = true; }
// Update the path of the user directory
void setUserDir(const string& path);
public:
//////////////////////////////////////////////////////////////////////
// The following methods are system-specific and can be overrided in
@ -456,8 +459,7 @@ class OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -465,9 +467,8 @@ class OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
virtual void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) = 0;
virtual void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) = 0;
protected:
// Pointer to the EventHandler object
@ -548,10 +549,9 @@ class OSystem
private:
FilesystemNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir,
myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir;
FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile;
FilesystemNode myRomFile;
string myRomMD5;
myNVRamDir, myCfgDir, myHomeDir, myUserDir;
FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile;
FilesystemNode myRomFile; string myRomMD5;
string myFeatures;
string myBuildInfo;

View File

@ -135,6 +135,8 @@ Settings::Settings()
// Config files and paths
setPermanent("romdir", "");
setPermanent("userdir", "");
setPermanent("saveuserdir", "false");
// ROM browser options
setPermanent("exitlauncher", "false");
@ -526,14 +528,14 @@ void Settings::usage() const
<< endl
<< " -saveonexit <none|current| Automatically save state(s) when exiting\n"
<< " all> emulation\n"
<< " -autoslot <1|0> Automatically change to next save slot when\n"
<< " -autoslot <0|1> Automatically change to next save slot when\n"
<< " state saving\n"
<< endl
<< " -rominfo <rom> Display detailed information for the given ROM\n"
<< " -listrominfo Display contents of stella.pro, one line per ROM\n"
<< " entry\n"
<< endl
<< " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n"
<< " -exitlauncher <0|1> On exiting a ROM, go back to the ROM launcher\n"
<< " -launcherpos <XxY> Sets the window position in windowed EOM launcher mode\n"
<< " -launcherdisplay <number> Sets the display for the ROM launcher\n"
<< " -launcherres <WxH> The resolution to use in ROM launcher mode\n"
@ -542,11 +544,14 @@ void Settings::usage() const
<< " medium|large|\n"
<< " large12|large14|\n"
<< " large16>\n"
<< " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n"
<< " -launchersubdirs <1|0> Show files from subdirectories too\n"
<< " -romviewer <float> Show ROM info viewer at given zoom level in ROM\n"
<< " launcher (use 0 for off)\n"
<< " -followlauncher <0|1> Default ROM path follows launcher navigation\n"
<< " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n"
<< " -launchersubdirs <0|1> Show files from subdirectories too\n"
<< " -romdir <dir> Set the path where the ROM launcher will start\n"
<< " -followlauncher <0|1> Default ROM path follows launcher navigation\n"
<< " -userdir <dir> Set the path to save user files to\n"
<< " -saveuserdir <0|1> Update user path when navigating in browser\n"
<< " -lastrom <name> Last played ROM, automatically selected in\n"
<< " launcher\n"
<< " -romloadcount <number> Number of ROM to load next from multicard\n"
@ -570,8 +575,6 @@ void Settings::usage() const
<< " -ctrlrate <rate> Rate per second of repeated controller input in\n"
<< " UI\n"
<< " -basic_settings <0|1> Display only a basic settings dialog\n"
<< " -romdir <dir> Set the directory where the ROM launcher will\n"
<< " start\n"
<< " -avoxport <name> The name of the serial port where an AtariVox is\n"
<< " connected\n"
<< " -holdreset Start the emulator with the Game Reset switch\n"

View File

@ -29,15 +29,14 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent, font, "About Stella")
{
const int lineHeight = font.getLineHeight(),
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Previous"),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
WidgetArray wid;
@ -274,7 +273,7 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id
case kWhatsNew:
if(myWhatsNewDialog == nullptr)
myWhatsNewDialog = make_unique<WhatsNewDialog>(instance(), parent(), _font,
myWhatsNewDialog = make_unique<WhatsNewDialog>(instance(), parent(),
640 * 0.95, 480 * 0.95);
myWhatsNewDialog->open();
break;

View File

@ -26,30 +26,23 @@
#include "Font.hxx"
#include "BrowserDialog.hxx"
/* We want to use this as a general directory selector at some point... possible uses
* - to select the data dir for a game
* - to select the place where save games are stored
* - others???
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
int max_w, int max_h, const string& title)
: Dialog(boss->instance(), boss->parent(), font, title),
CommandSender(boss)
: Dialog(boss->instance(), boss->parent(), font, title)
{
// Set real dimensions
_w = max_w;
_h = max_h;
const int lineHeight = font.getLineHeight(),
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 lineHeight = Dialog::lineHeight(),
//fontHeight = Dialog::fontHeight(),
//fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Base Dir"),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int selectHeight = lineHeight + VGAP * 3;
int xpos, ypos;
ButtonWidget* b;
@ -61,8 +54,13 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
_currentPath = new EditTextWidget(this, font, xpos + t->getWidth(), ypos,
_w - t->getWidth() - 2 * xpos, lineHeight);
_currentPath->setEditable(false);
xpos = _w - (HBORDER + _font.getStringWidth("Save") + CheckboxWidget::prefixSize(_font));
_savePathBox = new CheckboxWidget(this, font, xpos, ypos + 2, "Save");
_savePathBox->setToolTip("Check to save current path as default.");
// Add file list
ypos += lineHeight + VGAP * 2;
xpos = HBORDER; ypos += lineHeight + VGAP * 2;
_fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos,
_h - selectHeight - buttonHeight - ypos - VBORDER * 2);
_fileList->setEditable(false);
@ -71,24 +69,29 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
// Add currently selected item
ypos += _fileList->getHeight() + VGAP * 2;
_type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name ");
_selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos,
_w - _type->getWidth() - 2 * xpos, lineHeight, "");
_selected->setEditable(false);
_name = new StaticTextWidget(this, font, xpos, ypos + 2, "Name ");
_selected = new EditTextWidget(this, font, xpos + _name->getWidth(), ypos,
_w - _name->getWidth() - 2 * xpos, lineHeight, "");
addFocusWidget(_selected);
// Buttons
_goUpButton = new ButtonWidget(this, font, xpos, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Go up", kGoUpCmd);
addFocusWidget(_goUpButton);
_basedirButton =
new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd);
addFocusWidget(_basedirButton);
b = new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd);
b->setToolTip("Go to Stella's base directory.");
addFocusWidget(b);
b = new ButtonWidget(this, font, b->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Home Dir", kHomeDirCmd);
b->setToolTip("Go to user's home directory.");
addFocusWidget(b);
#ifndef BSPF_MACOS
b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Choose", kChooseCmd);
buttonWidth, buttonHeight, "OK", kChooseCmd);
addFocusWidget(b);
addOKWidget(b);
b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER,
@ -101,55 +104,119 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
addFocusWidget(b);
addCancelWidget(b);
b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Choose", kChooseCmd);
buttonWidth, buttonHeight, "OK", kChooseCmd);
addFocusWidget(b);
addOKWidget(b);
#endif
// add last to avoid focus problems
addFocusWidget(_savePathBox);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::show(GuiObject* parent, const GUI::Font& font,
const string& title, const string& startpath,
BrowserDialog::Mode mode,
const Command& command,
const FilesystemNode::NameFilter& namefilter)
{
uInt32 w = 0, h = 0;
static_cast<Dialog*>(parent)->getDynamicBounds(w, h);
if(w > uInt32(font.getMaxCharWidth() * 80))
w = font.getMaxCharWidth() * 80;
static unique_ptr<BrowserDialog> ourBrowser =
make_unique<BrowserDialog>(parent, font, w, h, title);
ourBrowser->show(startpath, mode, command, namefilter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::show(const string& startpath,
BrowserDialog::ListMode mode, int cmd,
const string& ext)
BrowserDialog::Mode mode,
const Command& command,
const FilesystemNode::NameFilter& namefilter)
{
_cmd = cmd;
const int fontWidth = Dialog::fontWidth(),
VGAP = Dialog::vGap();
_mode = mode;
_command = command;
string directory;
string fileName;
bool fileSelected = true;
// Set start path
if(_mode != Mode::Directories)
{
// split startpath into path and filename
FilesystemNode fs = FilesystemNode(startpath);
fileName = fs.getName();
directory = fs.isDirectory() ? "" : fs.getParent().getPath();
}
switch(_mode)
{
case FileLoad:
case Mode::FileLoad:
_fileList->setListMode(FilesystemNode::ListMode::All);
_fileList->setNameFilter([&ext](const FilesystemNode& node) {
return BSPF::endsWithIgnoreCase(node.getName(), ext);
});
_fileList->setNameFilter(namefilter);
_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop());
_currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth);
_savePathBox->setEnabled(true);
_savePathBox->clearFlags(Widget::FLAG_INVISIBLE);
_savePathBox->setState(instance().settings().getBool("saveuserdir"));
_name->clearFlags(Widget::FLAG_INVISIBLE);
_selected->clearFlags(Widget::FLAG_INVISIBLE);
_selected->setEditable(false);
_selected->clearFlags(Widget::FLAG_INVISIBLE);
_type->clearFlags(Widget::FLAG_INVISIBLE);
_selected->setEnabled(false);
_okWidget->setLabel("Load");
break;
case FileSave:
case Mode::FileSave:
_fileList->setListMode(FilesystemNode::ListMode::All);
_fileList->setNameFilter([&ext](const FilesystemNode& node) {
return BSPF::endsWithIgnoreCase(node.getName(), ext);
});
_selected->setEditable(false); // FIXME - disable user input for now
_fileList->setNameFilter(namefilter);
_fileList->setHeight(_selected->getTop() - VGAP * 2 - _fileList->getTop());
_currentPath->setWidth(_savePathBox->getLeft() - _currentPath->getLeft() - fontWidth);
_savePathBox->setEnabled(true);
_savePathBox->clearFlags(Widget::FLAG_INVISIBLE);
_savePathBox->setState(instance().settings().getBool("saveuserdir"));
_name->clearFlags(Widget::FLAG_INVISIBLE);
_selected->clearFlags(Widget::FLAG_INVISIBLE);
_type->clearFlags(Widget::FLAG_INVISIBLE);
_selected->setEditable(true);
_selected->setEnabled(true);
_selected->setText(fileName);
_okWidget->setLabel("Save");
fileSelected = false;
break;
case Directories:
case Mode::Directories:
_fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly);
_fileList->setNameFilter([](const FilesystemNode&) { return true; });
_selected->setEditable(false);
// TODO: scrollbar affected too!
_fileList->setHeight(_selected->getBottom() - _fileList->getTop());
_currentPath->setWidth(_savePathBox->getRight() - _currentPath->getLeft());
_savePathBox->setEnabled(false);
_savePathBox->setFlags(Widget::FLAG_INVISIBLE);
_name->setFlags(Widget::FLAG_INVISIBLE);
_selected->setFlags(Widget::FLAG_INVISIBLE);
_type->setFlags(Widget::FLAG_INVISIBLE);
_selected->setEditable(false);
_selected->setEnabled(false);
_okWidget->setLabel("OK");
break;
}
// Set start path
_fileList->setDirectory(FilesystemNode(startpath));
if(_mode != Mode::Directories)
_fileList->setDirectory(FilesystemNode(directory), fileName);
else
_fileList->setDirectory(FilesystemNode(startpath));
updateUI();
updateUI(fileSelected);
// Finally, open the dialog after it has been fully updated
open();
@ -158,31 +225,17 @@ void BrowserDialog::show(const string& startpath,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FilesystemNode& BrowserDialog::getResult() const
{
if(_mode == FileLoad || _mode == FileSave)
return _fileList->selected();
if(_mode == Mode::FileLoad || _mode == Mode::FileSave)
{
static FilesystemNode node;
return node
= FilesystemNode(_fileList->currentDir().getPath() + _selected->getText());
}
else
return _fileList->currentDir();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::updateUI()
{
// Only hilite the 'up' button if there's a parent directory
_goUpButton->setEnabled(_fileList->currentDir().hasParent());
// Update the path display
_currentPath->setText(_fileList->currentDir().getShortPath());
// Enable/disable OK button based on current mode
bool enable = _mode == Directories || !_fileList->selected().isDirectory();
_okWidget->setEnabled(enable);
if(!_fileList->selected().isDirectory())
_selected->setText(_fileList->getSelectedString());
else
_selected->setText("");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
int data, int id)
@ -192,8 +245,22 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
case kChooseCmd:
case FileListWidget::ItemActivated:
// Send a signal to the calling class that a selection has been made
// Since we aren't derived from a widget, we don't have a 'data' or 'id'
if(_cmd) sendCommand(_cmd, -1, -1);
if(_mode != Mode::Directories)
{
// TODO: check if affected by '-baseDir'and 'basedirinapp' params
bool savePath = _savePathBox->getState();
instance().settings().setValue("saveuserdir", savePath);
if(savePath)
instance().setUserDir(_fileList->currentDir().getShortPath());
}
_command(true, getResult());
close();
break;
case kCloseCmd:
// Send a signal to the calling class that the dialog was closed without selection
_command(false, getResult());
close();
break;
@ -205,8 +272,17 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
_fileList->setDirectory(FilesystemNode(instance().baseDir()));
break;
case kHomeDirCmd:
_fileList->setDirectory(FilesystemNode(instance().homeDir()));
break;
case EditableWidget::kChangedCmd:
Dialog::handleCommand(sender, cmd, data, 0);
updateUI(false);
break;
case FileListWidget::ItemChanged:
updateUI();
updateUI(true);
break;
default:
@ -214,3 +290,23 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BrowserDialog::updateUI(bool fileSelected)
{
// Only hilite the 'up' button if there's a parent directory
_goUpButton->setEnabled(_fileList->currentDir().hasParent());
// Update the path display
_currentPath->setText(_fileList->currentDir().getShortPath());
// Enable/disable OK button based on current mode and status
bool enable = true;
if(_mode != Mode::Directories)
enable = !_selected->getText().empty();
_okWidget->setEnabled(enable);
if(fileSelected && !_fileList->selected().isDirectory())
_selected->setText(_fileList->getSelectedString());
}

View File

@ -23,54 +23,85 @@ class ButtonWidget;
class EditTextWidget;
class FileListWidget;
class StaticTextWidget;
class FilesystemNode;
#include "Dialog.hxx"
#include "Command.hxx"
#include "FSNode.hxx"
#include "bspf.hxx"
class BrowserDialog : public Dialog, public CommandSender
class BrowserDialog : public Dialog
{
public:
enum ListMode {
enum class Mode {
FileLoad, // File selector, no input from user
FileSave, // File selector, filename changable by user
Directories // Directories only, no input from user
};
/** Function which is run when the user clicks OK or Cancel.
Boolean parameter is passed as 'true' when OK is clicked, else 'false'.
FilesystemNode parameter is what is currently selected in the browser.
*/
using Command = std::function<void(bool, const FilesystemNode&)>;
public:
// NOTE: Do not call this c'tor directly! Use the static show method below
// There is no point in doing so, since the result can't be returned
BrowserDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h,
const string& title = "");
const string& title);
~BrowserDialog() override = default;
/**
Place the browser window onscreen, using the given attributes.
@param parent The parent object of the browser (cannot be nullptr)
@param font The font to use in the browser
@param title The title of the browser window
@param startpath The initial path to select in the browser
@param mode The functionality to use (load/save/display)
@param command The command to run when 'OK' or 'Cancel' is clicked
@param namefilter Filter files/directories in browser display
*/
static void show(GuiObject* parent, const GUI::Font& font,
const string& title, const string& startpath,
BrowserDialog::Mode mode,
const Command& command,
const FilesystemNode::NameFilter& namefilter = {
[](const FilesystemNode&) { return true; }});
private:
/** Place the browser window onscreen, using the given attributes */
void show(const string& startpath,
BrowserDialog::ListMode mode, int cmd, const string& ext = "");
BrowserDialog::Mode mode,
const Command& command,
const FilesystemNode::NameFilter& namefilter);
/** Get resulting file node (called after receiving kChooseCmd) */
const FilesystemNode& getResult() const;
private:
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void updateUI();
void updateUI(bool fileSelected);
private:
enum {
kChooseCmd = 'CHOS',
kGoUpCmd = 'GOUP',
kBaseDirCmd = 'BADR'
kBaseDirCmd = 'BADR',
kHomeDirCmd = 'HODR'
};
int _cmd{0};
// Called when the user selects OK (bool is true) or Cancel (bool is false)
// FSNode will be set to whatever is active (basically, getResult())
Command _command{[](bool, const FilesystemNode&){}};
FileListWidget* _fileList{nullptr};
EditTextWidget* _currentPath{nullptr};
StaticTextWidget* _type{nullptr};
StaticTextWidget* _name{nullptr};
EditTextWidget* _selected{nullptr};
ButtonWidget* _goUpButton{nullptr};
ButtonWidget* _basedirButton{nullptr};
CheckboxWidget* _savePathBox{nullptr};
BrowserDialog::ListMode _mode{Directories};
BrowserDialog::Mode _mode{Mode::Directories};
private:
// Following constructors and assignment operators not supported

View File

@ -31,14 +31,12 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
const VariantList& combolist)
: Dialog(boss->instance(), boss->parent(), font, "Add...")
{
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
WidgetArray wid;

View File

@ -34,16 +34,14 @@
CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
: Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands")
{
const int 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;
const int buttonHeight = Dialog::buttonHeight(),
buttonWidth = _font.getStringWidth("Time Machine On") + Dialog::fontWidth() * 2,
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
//INDENT = Dialog::indent();
const int HGAP = Dialog::buttonGap(),
rowHeight = buttonHeight + VGAP;
// Set real dimensions
_w = 3 * (buttonWidth + HGAP) - HGAP + HBORDER * 2;
_h = 6 * rowHeight - VGAP + VBORDER * 2 + _th;

View File

@ -48,14 +48,12 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Developer settings")
{
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
// Set real dimensions
@ -87,14 +85,12 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addEmulationTab(const GUI::Font& font)
{
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;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int ypos = VBORDER;
WidgetArray wid;
VariantList items;
@ -216,14 +212,11 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addTiaTab(const GUI::Font& font)
{
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;
const int lineHeight = Dialog::lineHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int ypos = VBORDER;
int pwidth = font.getStringWidth("Faulty Cosmic Ark stars");
WidgetArray wid;
@ -323,17 +316,16 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DeveloperDialog::addVideoTab(const GUI::Font& font)
{
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;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int ypos = VBORDER;
int lwidth = font.getStringWidth("Intensity ");
int pwidth = font.getMaxCharWidth() * 6;
int pwidth = fontWidth * 6;
WidgetArray wid;
VariantList items;
int tabID = myTab->addTab(" Video ", TabWidget::AUTO_WIDTH);
@ -366,7 +358,7 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
myTVJitterRecLabelWidget = new StaticTextWidget(myTab, font,
myTVJitterRecWidget->getRight() + 4,
myTVJitterRecWidget->getTop() + 2,
5 * fontWidth, fontHeight, "");
5 * fontWidth, fontHeight);
ypos += lineHeight + VGAP;
myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
@ -467,14 +459,13 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
"30m",
"60m"
};
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;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos = HBORDER,
ypos = VBORDER,
lwidth = fontWidth * 11;
@ -568,13 +559,12 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
WidgetArray wid;
#ifdef DEBUGGER_SUPPORT
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
VariantList items;
int xpos, ypos, pwidth;
const Common::Size& ds = instance().frameBuffer().desktopSize();
@ -725,21 +715,21 @@ void DeveloperDialog::saveSettings(SettingsSet set)
instance().settings().setValue(prefix + "bankrandom", myRandomBank[set]);
instance().settings().setValue(prefix + "ramrandom", myRandomizeRAM[set]);
instance().settings().setValue(prefix + "cpurandom", myRandomizeCPU[set]);
// Undriven TIA pins
if(devSettings)
instance().settings().setValue("dev.tiadriven", myUndrivenPins[set]);
#ifdef DEBUGGER_SUPPORT
if (devSettings)
{
// Undriven TIA pins
instance().settings().setValue("dev.tiadriven", myUndrivenPins[set]);
#ifdef DEBUGGER_SUPPORT
// Read from write ports break
instance().settings().setValue("dev.rwportbreak", myRWPortBreak[set]);
// Write to read ports break
instance().settings().setValue("dev.wrportbreak", myWRPortBreak[set]);
}
#endif
if(devSettings)
#endif
// Thumb ARM emulation exception
instance().settings().setValue("dev.thumb.trapfatal", myThumbException[set]);
}
// AtariVox/SaveKey EEPROM access
instance().settings().setValue(prefix + "eepromaccess", myEEPROMAccess[set]);

View File

@ -449,7 +449,7 @@ void Dialog::drawDialog()
if(_th)
{
s.fillRect(_x, _y, _w, _th, kColorTitleBar);
s.drawString(_font, _title, _x + _font.getMaxCharWidth() * 1.25, _y + _font.getFontHeight() / 6,
s.drawString(_font, _title, _x + hBorder(), _y + _font.getFontHeight() / 6,
_font.getStringWidth(_title), kColorTitleText);
}
}
@ -865,17 +865,14 @@ Widget* Dialog::findWidget(int x, int y) const
void Dialog::addOKBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText, int buttonWidth)
{
const int 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 = fontWidth * 6 + BTN_BORDER;
buttonWidth = std::max(buttonWidth, font.getStringWidth(okText) + BTN_BORDER);
const int buttonHeight = Dialog::buttonHeight(),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
buttonWidth = std::max(buttonWidth,
std::max(Dialog::buttonWidth(okText),
Dialog::buttonWidth("Cancel")));
_w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w);
addOKWidget(new ButtonWidget(this, font, (_w - buttonWidth) / 2,
@ -888,17 +885,15 @@ void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& okText, const string& cancelText,
bool focusOKButton, int buttonWidth)
{
const int 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;
const int buttonHeight = Dialog::buttonHeight(),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
buttonWidth = std::max(buttonWidth,
std::max(font.getStringWidth("Defaults"),
std::max(font.getStringWidth(okText),
font.getStringWidth(cancelText))) + BTN_BORDER);
std::max(Dialog::buttonWidth("Defaults"),
std::max(Dialog::buttonWidth(okText),
Dialog::buttonWidth(cancelText))));
_w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w);
@ -936,13 +931,10 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
const string& defaultsText,
bool focusOKButton)
{
const int 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;
const int buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth(defaultsText),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd));
@ -958,23 +950,21 @@ void Dialog::addDefaultsExtraOKCancelBGroup(
const string& okText, const string& cancelText, const string& defaultsText,
bool focusOKButton)
{
const int 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;
const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER;
const int buttonHeight = Dialog::buttonHeight(),
buttonWidth = std::max(Dialog::buttonWidth(defaultsText),
Dialog::buttonWidth(extraText)),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd));
wid.push_back(_defaultWidget);
wid.push_back(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP,
_h - buttonHeight - VBORDER, buttonWidth, buttonHeight,
extraText, extraCmd)
);
addExtraWidget(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP,
_h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, extraText, extraCmd));
wid.push_back(_extraWidget);
addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth);
}

View File

@ -75,9 +75,10 @@ class Dialog : public GuiObject
void addToFocusList(const WidgetArray& list, TabWidget* w, int tabId);
void addBGroupToFocusList(const WidgetArray& list) { _buttonGroup = list; }
void addTabWidget(TabWidget* w);
void addDefaultWidget(Widget* w) { _defaultWidget = w; }
void addOKWidget(Widget* w) { _okWidget = w; }
void addCancelWidget(Widget* w) { _cancelWidget = w; }
void addDefaultWidget(ButtonWidget* w) { _defaultWidget = w; }
void addExtraWidget(ButtonWidget* w) { _extraWidget = w; }
void addOKWidget(ButtonWidget* w) { _okWidget = w; }
void addCancelWidget(ButtonWidget* w) { _cancelWidget = w; }
void setFocus(Widget* w);
/** Returns the base surface associated with this dialog. */
@ -126,6 +127,19 @@ class Dialog : public GuiObject
ToolTip& tooltip() { return *_toolTip; }
int lineHeight() const { return _font.getLineHeight(); }
int fontHeight() const { return _font.getFontHeight(); }
int fontWidth() const { return _font.getMaxCharWidth(); }
int buttonHeight() const { return lineHeight() * 1.25; }
int buttonWidth(const string& label) const {
return _font.getStringWidth(label) + fontWidth() * 2.5;
}
int buttonGap() const { return fontWidth(); }
int hBorder() const { return fontWidth() * 1.25; }
int vBorder() const { return fontHeight() / 2; }
int vGap() const { return fontHeight() / 4; }
int indent() const { return fontWidth() * 2; }
protected:
void draw() override { }
void releaseFocus() override;
@ -163,7 +177,6 @@ class Dialog : public GuiObject
const string& cancelText = "Cancel",
const string& defaultsText = "Defaults",
bool focusOKButton = true);
int buttonHeight(const GUI::Font& font) const;
// NOTE: This method, and the three above it, are due to be refactored at some
// point, since the parameter list is kind of getting ridiculous
@ -195,9 +208,10 @@ class Dialog : public GuiObject
Widget* _mouseWidget{nullptr};
Widget* _focusedWidget{nullptr};
Widget* _dragWidget{nullptr};
Widget* _defaultWidget{nullptr};
Widget* _okWidget{nullptr};
Widget* _cancelWidget{nullptr};
ButtonWidget* _defaultWidget{nullptr};
ButtonWidget* _extraWidget{nullptr};
ButtonWidget* _okWidget{nullptr};
ButtonWidget* _cancelWidget{nullptr};
bool _visible{false};
bool _processCancel{false};

View File

@ -477,13 +477,13 @@ void EditableWidget::drawCaretSelection()
int y = editRect.y();
int w = editRect.w();
int h = editRect.h();
int wt = int(text.length()) * _font.getMaxCharWidth() + 1;
int dx = selectStartPos() * _font.getMaxCharWidth() - _editScrollOffset;
int wt = int(text.length()) * _boss->dialog().fontWidth() + 1;
int dx = selectStartPos() * _boss->dialog().fontWidth() - _editScrollOffset;
if(dx < 0)
{
// selected text starts left of displayed rect
text = text.substr(-(dx - 1) / _font.getMaxCharWidth());
text = text.substr(-(dx - 1) / _boss->dialog().fontWidth());
wt += dx;
dx = 0;
}
@ -657,7 +657,7 @@ bool EditableWidget::killWord(int direction)
{
while(currentPos > 0)
{
if(_editString[currentPos - 1] == ' ')
if(BSPF::isWhiteSpace(_editString[currentPos - 1]))
{
if(!space)
break;
@ -673,7 +673,7 @@ bool EditableWidget::killWord(int direction)
{
while(currentPos < int(_editString.size()))
{
if(currentPos && _editString[currentPos - 1] == ' ')
if(currentPos && BSPF::isWhiteSpace(_editString[currentPos - 1]))
{
if(!space)
break;
@ -709,7 +709,7 @@ bool EditableWidget::moveWord(int direction, bool select)
{
while (currentPos > 0)
{
if (_editString[currentPos - 1] == ' ')
if (BSPF::isWhiteSpace(_editString[currentPos - 1]))
{
if (!space)
break;
@ -728,7 +728,7 @@ bool EditableWidget::moveWord(int direction, bool select)
{
while (currentPos < int(_editString.size()))
{
if (currentPos && _editString[currentPos - 1] == ' ')
if (currentPos && BSPF::isWhiteSpace(_editString[currentPos - 1]))
{
if (!space)
break;
@ -754,14 +754,14 @@ bool EditableWidget::markWord()
while(_caretPos + _selectSize < int(_editString.size()))
{
if(_editString[_caretPos + _selectSize] == ' ')
if(BSPF::isWhiteSpace(_editString[_caretPos + _selectSize]))
break;
_selectSize++;
}
while(_caretPos > 0)
{
if(_editString[_caretPos - 1] == ' ')
if(BSPF::isWhiteSpace(_editString[_caretPos - 1]))
break;
_caretPos--;
_selectSize++;

View File

@ -66,15 +66,13 @@ EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Emulation settings")
{
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;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos;
int lwidth = font.getStringWidth("Emulation speed ");
WidgetArray wid;

View File

@ -42,14 +42,13 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
CommandSender(boss),
myEventMode{mode}
{
const int fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
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 lineHeight = boss->dialog().lineHeight(),
fontWidth = boss->dialog().fontWidth(),
buttonHeight = boss->dialog().buttonHeight(),
buttonWidth = boss->dialog().buttonWidth("Defaults"),
VBORDER = boss->dialog().vBorder(),
HBORDER = boss->dialog().hBorder(),
VGAP = boss->dialog().vGap();
const int ACTION_LINES = 2;
int xpos = HBORDER, ypos = VBORDER;
const int listWidth = _w - buttonWidth - HBORDER * 2 - fontWidth;
@ -136,8 +135,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
xpos = HBORDER;
ypos = myActionsList->getBottom() + VGAP * 2;
StaticTextWidget* t;
t = new StaticTextWidget(boss, font, xpos, ypos+2, font.getStringWidth("Action"),
fontHeight, "Action", TextAlign::Left);
t = new StaticTextWidget(boss, font, xpos, ypos+2, "Action");
myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + fontWidth, ypos,
_w - xpos - t->getWidth() - fontWidth - HBORDER + 2,

View File

@ -54,7 +54,7 @@ void FileListWidget::setDirectory(const FilesystemNode& node,
while(tmp.hasParent() && !_history.full())
{
string name = tmp.getName();
if(name.back() == '/' || name.back() == '\\')
if(name.back() == FilesystemNode::PATH_SEPARATOR)
name.pop_back();
if(!BSPF::startsWithIgnoreCase(name, " ["))
name = " [" + name.append("]");

View File

@ -29,6 +29,7 @@
#include "Paddles.hxx"
#include "PopUpWidget.hxx"
#include "PropsSet.hxx"
#include "BrowserDialog.hxx"
#include "QuadTariDialog.hxx"
#include "TabWidget.hxx"
#include "TIAConstants.hxx"
@ -55,16 +56,13 @@ GameInfoDialog::GameInfoDialog(
CommandSender(boss)
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25,
infoLineHeight = ifont.getLineHeight();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int infoLineHeight = ifont.getLineHeight();
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
WidgetArray wid;
// Set real dimensions
@ -92,7 +90,9 @@ GameInfoDialog::GameInfoDialog(
myTab->setActiveTab(0);
// Add Defaults, OK and Cancel buttons
addDefaultsExtraOKCancelBGroup(wid, font, "Save", kSavePressed);
addDefaultsExtraOKCancelBGroup(wid, font, "Export" + ELLIPSIS, kExportPressed);
_extraWidget->setToolTip("Export the current ROM's properties\n"
"into the default directory.");
addBGroupToFocusList(wid);
}
@ -100,13 +100,12 @@ GameInfoDialog::GameInfoDialog(
void GameInfoDialog::addEmulationTab()
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int ypos, pwidth, tabID;
WidgetArray wid;
VariantList items;
@ -197,13 +196,10 @@ void GameInfoDialog::addEmulationTab()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::addConsoleTab()
{
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos, lwidth, tabID;
WidgetArray wid;
@ -253,15 +249,13 @@ void GameInfoDialog::addConsoleTab()
void GameInfoDialog::addControllersTab()
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
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;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos, pwidth, tabID;
VariantList items, ctrls;
WidgetArray wid;
@ -405,13 +399,11 @@ void GameInfoDialog::addControllersTab()
void GameInfoDialog::addCartridgeTab()
{
// 4) Cartridge properties
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos, lwidth, fwidth, tabID;
WidgetArray wid;
VariantList items;
@ -466,14 +458,13 @@ void GameInfoDialog::addCartridgeTab()
void GameInfoDialog::addHighScoresTab()
{
// 4) High Scores properties
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;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
@ -658,7 +649,6 @@ void GameInfoDialog::addHighScoresTab()
addToFocusList(wid, myTab, tabID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GameInfoDialog::~GameInfoDialog()
{
@ -1339,7 +1329,8 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget
valWidget->setText("");
}
void GameInfoDialog::saveCurrentPropertiesToDisk()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::exportCurrentPropertiesToDisk(const FilesystemNode& node)
{
saveProperties();
stringstream out;
@ -1347,16 +1338,12 @@ void GameInfoDialog::saveCurrentPropertiesToDisk()
try
{
FilesystemNode propfile = instance().defaultSaveDir();
propfile /= myGameFile.getNameWithExt(".pro");
propfile.write(out);
instance().frameBuffer().showTextMessage("Properties saved to " +
propfile.getShortPath());
node.write(out);
instance().frameBuffer().showTextMessage("ROM properties exported");
}
catch(...)
{
instance().frameBuffer().showTextMessage("Error saving properties");
instance().frameBuffer().showTextMessage("Error exporting ROM properties");
}
}
@ -1375,8 +1362,14 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
setDefaults();
break;
case kSavePressed:
saveCurrentPropertiesToDisk();
case kExportPressed:
BrowserDialog::show(this, _font, "Export Properties as",
instance().userDir().getPath() +
myGameFile.getNameWithExt(".pro"),
BrowserDialog::Mode::FileSave,
[this](bool OK, const FilesystemNode& node) {
if(OK) exportCurrentPropertiesToDisk(node);
});
break;
case TabWidget::kTabChangedCmd:

View File

@ -77,7 +77,7 @@ class GameInfoDialog : public Dialog, public CommandSender
// set formatted memory value for given address field
void setAddressVal(EditTextWidget* address, EditTextWidget* val,
bool isBCD = true, bool zeroBased = false, uInt8 maxVal = 255);
void saveCurrentPropertiesToDisk();
void exportCurrentPropertiesToDisk(const FilesystemNode& node);
private:
TabWidget* myTab{nullptr};
@ -180,7 +180,7 @@ class GameInfoDialog : public Dialog, public CommandSender
kHiScoresChanged = 'HSch',
kPXCenterChanged = 'Pxch',
kPYCenterChanged = 'Pych',
kSavePressed = 'GIsp'
kExportPressed = 'Expr'
};
// Game properties for currently loaded ROM

View File

@ -33,14 +33,12 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
: Dialog(boss->instance(), boss->parent(), font, "Power-on options"),
CommandSender(boss)
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonHeight = lineHeight * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
int lwidth = font.getStringWidth("Right difficulty "),
pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)");
@ -138,10 +136,9 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y,
WidgetArray& wid)
{
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight();
const int VGAP = fontHeight / 4;
const int fontWidth = Dialog::fontWidth(),
//fontHeight = Dialog::fontHeight(),
VGAP = Dialog::vGap();
int xpos = x, ypos = y, xdiff = CheckboxWidget::boxSize(font) - 9;
// Left joystick

View File

@ -28,15 +28,14 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent, font, "Help")
{
const int lineHeight = font.getLineHeight(),
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Previous"),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
WidgetArray wid;
@ -76,10 +75,10 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent,
{
myKey[i] =
new StaticTextWidget(this, font, xpos, ypos, lwidth,
fontHeight, "", TextAlign::Left);
fontHeight);
myDesc[i] =
new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - HBORDER,
fontHeight, "", TextAlign::Left);
fontHeight);
ypos += fontHeight;
}

View File

@ -107,23 +107,22 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
myScores.variation = HSM::DEFAULT_VARIATION;
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth(),
infoLineHeight = ifont.getLineHeight(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int BUTTON_GAP = fontWidth;
const int infoLineHeight = ifont.getLineHeight();
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xposRank = HBORDER;
int xposScore = xposRank + _font.getStringWidth("Rank");
int xposSpecial = xposScore + _font.getStringWidth(" Score ");
int xposName = xposSpecial + _font.getStringWidth("Round ");
int xposDate = xposName + _font.getStringWidth("Name ");
int xposDelete = xposDate + _font.getStringWidth("YY-MM-DD HH:MM ");
int nWidth = _font.getStringWidth("ABC") + _font.getMaxCharWidth() * 0.75;
int nWidth = _font.getStringWidth("ABC") + fontWidth * 0.75;
bool smallFont = _font.getFontHeight() < 24;
int buttonSize = smallFont ? BUTTON_GFX_H : BUTTON_GFX_H_LARGE;
int xpos, ypos;

View File

@ -44,13 +44,12 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
myMaxWidth{max_w},
myMaxHeight{max_h}
{
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int VGAP = fontHeight / 4;
const int HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos, tabID;
// Set real dimensions
@ -107,13 +106,12 @@ InputDialog::~InputDialog()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::addDevicePortTab()
{
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos, lwidth, tabID;
WidgetArray wid;
@ -213,7 +211,7 @@ void InputDialog::addDevicePortTab()
// Show joystick database
ypos += lineHeight;
lwidth = _font.getStringWidth("Joystick Database" + ELLIPSIS) + fontWidth * 2.5;
lwidth = Dialog::buttonWidth("Joystick Database" + ELLIPSIS);
myJoyDlgButton = new ButtonWidget(myTab, _font, HBORDER, ypos, lwidth, buttonHeight,
"Joystick Database" + ELLIPSIS, kDBButtonPressed);
wid.push_back(myJoyDlgButton);
@ -240,13 +238,12 @@ void InputDialog::addDevicePortTab()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::addMouseTab()
{
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;
const int INDENT = fontWidth * 2;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos = HBORDER, ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
@ -713,7 +710,7 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
{
const GUI::Font& font = instance().frameBuffer().font();
myJoyDialog = make_unique<JoystickDialog>
(this, font, font.getMaxCharWidth() * 56 + 20, font.getFontHeight() * 18 + 20);
(this, font, fontWidth() * 56 + 20, fontHeight() * 18 + 20);
}
myJoyDialog->show();
break;

View File

@ -50,14 +50,13 @@ InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& lfont,
void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont,
const StringList& labels)
{
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;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
uInt32 xpos, ypos, i, lwidth = 0, maxIdx = 0;
WidgetArray wid;

View File

@ -31,15 +31,13 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
{
int xpos, ypos;
WidgetArray wid;
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 lineHeight = Dialog::lineHeight(),
//fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Remove"),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
// Joystick list
xpos = HBORDER; ypos = VBORDER + _th;
int w = _w - 2 * xpos;

View File

@ -61,20 +61,19 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
int x, int y, int w, int h)
: Dialog(osystem, parent, x, y, w, h)
: Dialog(osystem, parent, osystem.frameBuffer().launcherFont(), "",
x, y, w, h)
{
myUseMinimalUI = instance().settings().getBool("minimal_ui");
const GUI::Font& font = instance().frameBuffer().launcherFont();
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
HBORDER = fontWidth * 1.25,
VBORDER = fontHeight / 2,
BUTTON_GAP = fontWidth,
LBL_GAP = fontWidth,
VGAP = fontHeight / 4,
buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: lineHeight * 1.25,
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int LBL_GAP = fontWidth,
buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: Dialog::buttonHeight(),
buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1));
int xpos = HBORDER, ypos = VBORDER;
@ -85,22 +84,22 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
string lblSubDirs = "Incl. subdirectories";
string lblFound = "12345 items found";
tooltip().setFont(font);
tooltip().setFont(_font);
int lwSelect = font.getStringWidth(lblSelect);
int cwAllFiles = font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(font);
int cwSubDirs = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font);
int lwFilter = font.getStringWidth(lblFilter);
int lwFound = font.getStringWidth(lblFound);
int lwSelect = _font.getStringWidth(lblSelect);
int cwAllFiles = _font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(_font);
int cwSubDirs = _font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(_font);
int lwFilter = _font.getStringWidth(lblFilter);
int lwFound = _font.getStringWidth(lblFound);
int wTotal = HBORDER * 2 + lwSelect + cwAllFiles + cwSubDirs + lwFilter + lwFound
+ EditTextWidget::calcWidth(font, "123456") + LBL_GAP * 7;
+ EditTextWidget::calcWidth(_font, "123456") + LBL_GAP * 7;
bool noSelect = false;
if(w < wTotal)
{
// make sure there is space for at least 6 characters in the filter field
lblSelect = "Select a ROM" + ELLIPSIS;
int lwSelectShort = font.getStringWidth(lblSelect);
int lwSelectShort = _font.getStringWidth(lblSelect);
wTotal -= lwSelect - lwSelectShort;
lwSelect = lwSelectShort;
@ -109,7 +108,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
{
// make sure there is space for at least 6 characters in the filter field
lblSubDirs = "Subdir.";
int cwSubDirsShort = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font);
int cwSubDirsShort = _font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(_font);
wTotal -= cwSubDirs - cwSubDirsShort;
cwSubDirs = cwSubDirsShort;
@ -118,7 +117,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
{
// make sure there is space for at least 6 characters in the filter field
lblAllFiles = "All files";
int cwAllFilesShort = font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(font);
int cwAllFilesShort = _font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(_font);
wTotal -= cwAllFiles - cwAllFilesShort;
cwAllFiles = cwAllFilesShort;
@ -127,7 +126,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
{
// make sure there is space for at least 6 characters in the filter field
lblFound = "12345 found";
int lwFoundShort = font.getStringWidth(lblFound);
int lwFoundShort = _font.getStringWidth(lblFound);
wTotal -= lwFound - lwFoundShort;
lwFound = lwFoundShort;
@ -137,7 +136,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
{
// make sure there is space for at least 6 characters in the filter field
lblSelect = "";
int lwSelectShort = font.getStringWidth(lblSelect);
int lwSelectShort = _font.getStringWidth(lblSelect);
// wTotal -= lwSelect - lwSelectShort; // dead code
lwSelect = lwSelectShort;
@ -152,16 +151,16 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
#if defined(RETRON77)
ver << " for RetroN 77";
#endif
new StaticTextWidget(this, font, 0, ypos, _w, fontHeight,
new StaticTextWidget(this, _font, 0, ypos, _w, fontHeight,
ver.str(), TextAlign::Center);
ypos += lineHeight;
}
// Show the header
new StaticTextWidget(this, font, xpos, ypos, lblSelect);
new StaticTextWidget(this, _font, xpos, ypos, lblSelect);
// Shop the files counter
xpos = _w - HBORDER - lwFound;
myRomCount = new StaticTextWidget(this, font, xpos, ypos,
myRomCount = new StaticTextWidget(this, _font, xpos, ypos,
lwFound, fontHeight,
"", TextAlign::Right);
@ -169,23 +168,23 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// It has to fit between both labels
if(!myUseMinimalUI && w >= 640)
{
int fwFilter = std::min(EditTextWidget::calcWidth(font, "123456789012345"),
int fwFilter = std::min(EditTextWidget::calcWidth(_font, "123456789012345"),
xpos - cwSubDirs - lwFilter - cwAllFiles
- lwSelect - HBORDER - LBL_GAP * (noSelect ? 5 : 7));
// Show the filter input field
xpos -= fwFilter + LBL_GAP;
myPattern = new EditTextWidget(this, font, xpos, ypos - 2, fwFilter, lineHeight, "");
myPattern = new EditTextWidget(this, _font, xpos, ypos - 2, fwFilter, lineHeight, "");
myPattern->setToolTip("Enter filter text to reduce file list.\n"
"Use '*' and '?' as wildcards.");
// Show the "Filter" label
xpos -= lwFilter + LBL_GAP;
new StaticTextWidget(this, font, xpos, ypos, lblFilter);
new StaticTextWidget(this, _font, xpos, ypos, lblFilter);
// Show the subdirectories checkbox
xpos -= cwSubDirs + LBL_GAP * 2;
mySubDirs = new CheckboxWidget(this, font, xpos, ypos, lblSubDirs, kSubDirsCmd);
mySubDirs = new CheckboxWidget(this, _font, xpos, ypos, lblSubDirs, kSubDirsCmd);
ostringstream tip;
tip << "Search files in subdirectories too.";
mySubDirs->setToolTip(tip.str());
@ -195,7 +194,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
xpos = HBORDER;
else
xpos -= cwAllFiles + LBL_GAP;
myAllFiles = new CheckboxWidget(this, font, xpos, ypos, lblAllFiles, kAllfilesCmd);
myAllFiles = new CheckboxWidget(this, _font, xpos, ypos, lblAllFiles, kAllfilesCmd);
myAllFiles->setToolTip("Uncheck to show ROM files only.");
wid.push_back(myAllFiles);
@ -211,7 +210,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
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 = new FileListWidget(this, _font, xpos, ypos, listWidth, listHeight);
myList->setEditable(false);
myList->setListMode(FilesystemNode::ListMode::All);
wid.push_back(myList);
@ -236,11 +235,11 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add textfield to show current directory
xpos = HBORDER;
ypos += myList->getHeight() + VGAP;
lwSelect = font.getStringWidth("Path") + LBL_GAP;
myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwSelect, fontHeight,
lwSelect = _font.getStringWidth("Path") + LBL_GAP;
myDirLabel = new StaticTextWidget(this, _font, xpos, ypos+2, lwSelect, fontHeight,
"Path", TextAlign::Left);
xpos += lwSelect;
myDir = new EditTextWidget(this, font, xpos, ypos, _w - xpos - HBORDER, lineHeight, "");
myDir = new EditTextWidget(this, _font, xpos, ypos, _w - xpos - HBORDER, lineHeight, "");
myDir->setEditable(false, true);
myDir->clearFlags(Widget::FLAG_RETAIN_FOCUS);
@ -249,41 +248,41 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add four buttons at the bottom
xpos = HBORDER; ypos = _h - VBORDER - buttonHeight;
#ifndef BSPF_MACOS
myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight,
myStartButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight,
"Select", kLoadROMCmd);
wid.push_back(myStartButton);
xpos += (buttonWidth + 0) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
myPrevDirButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
"Go Up", kPrevDirCmd);
wid.push_back(myPrevDirButton);
xpos += (buttonWidth + 1) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
myOptionsButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
"Options" + ELLIPSIS, kOptionsCmd);
wid.push_back(myOptionsButton);
xpos += (buttonWidth + 2) / 4 + BUTTON_GAP;
myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 4) / 4, buttonHeight,
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, (buttonWidth + 0) / 4, buttonHeight,
myQuitButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight,
"Quit", kQuitCmd);
wid.push_back(myQuitButton);
xpos += (buttonWidth + 0) / 4 + BUTTON_GAP;
myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
myOptionsButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight,
"Options" + ELLIPSIS, kOptionsCmd);
wid.push_back(myOptionsButton);
xpos += (buttonWidth + 1) / 4 + BUTTON_GAP;
myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight,
myPrevDirButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight,
"Go Up", kPrevDirCmd);
wid.push_back(myPrevDirButton);
xpos += (buttonWidth + 2) / 4 + BUTTON_GAP;
myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
myStartButton = new ButtonWidget(this, _font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight,
"Select", kLoadROMCmd);
wid.push_back(myStartButton);
#endif
@ -297,12 +296,12 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
addToFocusList(wid);
// Create (empty) context menu for ROM list options
myMenu = make_unique<ContextMenu>(this, osystem.frameBuffer().launcherFont(), EmptyVarList);
myMenu = make_unique<ContextMenu>(this, _font, EmptyVarList);
// Create global props dialog, which is used to temporarily override
// ROM properties
myGlobalProps = make_unique<GlobalPropsDialog>(this,
myUseMinimalUI ? osystem.frameBuffer().launcherFont() : osystem.frameBuffer().font());
myUseMinimalUI ? _font : osystem.frameBuffer().font());
// since we cannot know how many files there are, use are really high value here
myList->progress().setRange(0, 50000, 5);
@ -536,16 +535,15 @@ float LauncherDialog::getRomInfoZoom(int listHeight) const
if(zoom > 0.F)
{
const GUI::Font& font = instance().frameBuffer().launcherFont();
const GUI::Font& smallFont = instance().frameBuffer().smallFont();
const int fontWidth = font.getMaxCharWidth(),
HBORDER = fontWidth * 1.25;
const int fontWidth = Dialog::fontWidth(),
HBORDER = Dialog::hBorder();
// 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)
/ fontWidth < MIN_LAUNCHER_CHARS)
{
zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * font.getMaxCharWidth())
zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * fontWidth)
/ TIAConstants::viewableWidth;
}
if((listHeight - 12 - zoom * TIAConstants::viewableHeight) <
@ -584,7 +582,7 @@ void LauncherDialog::setRomInfoFont(const Common::Size& area)
for(size_t i = 0; i < sizeof(FONTS) / sizeof(FontDesc); ++i)
{
// only use fonts <= launcher fonts
if(instance().frameBuffer().launcherFont().getFontHeight() >= FONTS[i].height)
if(Dialog::fontHeight() >= FONTS[i].height)
{
if(area.h >= uInt32(MIN_ROMINFO_ROWS * FONTS[i].height + 2
+ MIN_ROMINFO_LINES * FONTS[i].height)
@ -916,7 +914,7 @@ void LauncherDialog::openHighScores()
void LauncherDialog::openWhatsNew()
{
if(myWhatsNewDialog == nullptr)
myWhatsNewDialog = make_unique<WhatsNewDialog>(instance(), parent(), _font, _w, _h);
myWhatsNewDialog = make_unique<WhatsNewDialog>(instance(), parent(), _w, _h);
myWhatsNewDialog->open();
}

View File

@ -22,7 +22,6 @@ class ButtonWidget;
class CommandSender;
class ContextMenu;
class DialogContainer;
class BrowserDialog;
class OptionsDialog;
class HighScoresDialog;
class GlobalPropsDialog;
@ -168,7 +167,6 @@ class LauncherDialog : public Dialog
unique_ptr<StellaSettingsDialog> myStellaSettingsDialog;
unique_ptr<ContextMenu> myMenu;
unique_ptr<GlobalPropsDialog> myGlobalProps;
unique_ptr<BrowserDialog> myRomDir;
unique_ptr<WhatsNewDialog> myWhatsNewDialog;
// automatically sized font for ROM info viewer

View File

@ -56,6 +56,17 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font,
_w = w - 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ListWidget::setHeight(int h)
{
Widget::setHeight(h);
if(_useScrollbar)
_scrollBar->setHeight(h);
_rows = (h - 2) / _lineHeight;
recalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ListWidget::setSelected(int item)
{
@ -161,7 +172,7 @@ void ListWidget::recalc()
{
int size = int(_list.size());
if(_currentPos >= size)
if(_currentPos >= size - _rows)
{
if(size <= _rows)
_currentPos = 0;
@ -171,7 +182,9 @@ void ListWidget::recalc()
if (_currentPos < 0)
_currentPos = 0;
if(_selectedItem < 0 || _selectedItem >= size)
if(_selectedItem >= size)
_selectedItem = size - 1;
if(_selectedItem < 0)
_selectedItem = 0;
_editMode = false;

View File

@ -47,6 +47,7 @@ class ListWidget : public EditableWidget
int rows() const { return _rows; }
int currentPos() const { return _currentPos; }
void setHeight(int h) override;
int getSelected() const { return _selectedItem; }
void setSelected(int item);

View File

@ -24,6 +24,7 @@
#include "Settings.hxx"
#include "PopUpWidget.hxx"
#include "StringListWidget.hxx"
#include "BrowserDialog.hxx"
#include "StringParser.hxx"
#include "Widget.hxx"
#include "Font.hxx"
@ -36,15 +37,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
bool uselargefont)
: Dialog(osystem, parent, font, "System logs")
{
const int lineHeight = font.getLineHeight(),
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 VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Save log to disk" + ELLIPSIS),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
WidgetArray wid;
@ -80,7 +79,7 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent,
// Add Save, OK and Cancel buttons
ButtonWidget* b;
b = new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
buttonWidth, buttonHeight, "Save log to disk",
buttonWidth, buttonHeight, "Save log to disk" + ELLIPSIS,
GuiObject::kDefaultsCmd);
wid.push_back(b);
addOKCancelBGroup(wid, font);
@ -114,21 +113,18 @@ void LoggerDialog::saveConfig()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LoggerDialog::saveLogFile()
void LoggerDialog::saveLogFile(const FilesystemNode& node)
{
FilesystemNode node = instance().defaultSaveDir();
node /= "stella.log";
try
{
stringstream out;
out << Logger::instance().logMessages();
instance().frameBuffer().showTextMessage("Saving log file to " + node.getShortPath());
node.write(out);
instance().frameBuffer().showTextMessage("System log saved");
}
catch(...)
{
instance().frameBuffer().showTextMessage("Error saving log file to " + node.getShortPath());
instance().frameBuffer().showTextMessage("Error saving system log");
}
}
@ -144,7 +140,12 @@ void LoggerDialog::handleCommand(CommandSender* sender, int cmd,
break;
case GuiObject::kDefaultsCmd:
saveLogFile();
BrowserDialog::show(this, _font, "Save Log as",
instance().userDir().getPath() + "stella.log",
BrowserDialog::Mode::FileSave,
[this](bool OK, const FilesystemNode& node) {
if(OK) saveLogFile(node);
});
break;
default:

View File

@ -37,7 +37,7 @@ class LoggerDialog : public Dialog
private:
void loadConfig() override;
void saveConfig() override;
void saveLogFile();
void saveLogFile(const FilesystemNode& node);
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;

View File

@ -79,11 +79,10 @@ 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();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int fontWidth = Dialog::fontWidth(),
fontHeight = Dialog::fontHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
int xpos, ypos;
// Set real dimensions
int str_w = 0;

View File

@ -54,17 +54,13 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
{
// do not show basic settings options in debugger
bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger;
const int
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;
const int buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int HGAP = Dialog::buttonGap(),
rowHeight = buttonHeight + VGAP;
int buttonWidth = Dialog::buttonWidth("Game Properties" + ELLIPSIS);
_w = 2 * buttonWidth + HBORDER * 2 + HGAP;
_h = 7 * rowHeight + VBORDER * 2 - VGAP + _th;
@ -133,7 +129,7 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd);
wid.push_back(b);
buttonWidth = _font.getStringWidth(" Close ") + fontWidth * 2.5;
buttonWidth = Dialog::buttonWidth(" Close ");
xoffset -= (buttonWidth + HGAP) / 2;
b = ADD_OD_BUTTON("Close", kExitCmd);
wid.push_back(b);

View File

@ -32,17 +32,14 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font,
: Dialog(boss->instance(), boss->parent()),
myFont{font}
{
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(),
VBORDER = fontHeight / 2,
HBORDER = fontWidth * 1.25,
VGAP = fontHeight / 4,
buttonHeight = font.getLineHeight() * 1.25,
BTN_BORDER = fontWidth * 2.5,
buttonWidth = font.getStringWidth("Cancel") + BTN_BORDER,
lwidth = font.getStringWidth(message);
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Cancel"),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int lwidth = font.getStringWidth(message);
int xpos, ypos;
WidgetArray wid;
@ -73,12 +70,9 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ProgressDialog::setMessage(const string& message)
{
const int fontWidth = myFont.getMaxCharWidth(),
HBORDER = fontWidth * 1.25,
lwidth = myFont.getStringWidth(message),
BTN_BORDER = fontWidth * 2.5,
buttonWidth = myFont.getStringWidth("Cancel") + BTN_BORDER;
const int buttonWidth = Dialog::buttonWidth("Cancel"),
HBORDER = Dialog::hBorder();
const int lwidth = myFont.getStringWidth(message);
// Recalculate real dimensions
_w = HBORDER * 2 + std::max(lwidth, buttonWidth);

View File

@ -31,13 +31,10 @@ QuadTariDialog::QuadTariDialog(GuiObject* boss, const GUI::Font& font, int max_w
: Dialog(boss->instance(), boss->parent(), font, "QuadTari controllers", 0, 0, max_w, max_h),
myGameProperties{properties}
{
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
WidgetArray wid;
VariantList ctrls;

View File

@ -27,28 +27,30 @@ R77HelpDialog::R77HelpDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font)
: Dialog(osystem, parent, font, "RetroN 77 help")
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Previous") + 20,
buttonHeight = font.getLineHeight() + 4;
const int HBORDER = 10;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Previous"),
BUTTON_GAP = Dialog::buttonGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
int xpos, ypos;
WidgetArray wid;
// Set real dimensions
_w = 47 * fontWidth + HBORDER * 2;
_h = (LINES_PER_PAGE + 2) * lineHeight + 12 + _th;
_h = (LINES_PER_PAGE + 2) * lineHeight + VBORDER * 2 + _th;
// Add Previous, Next and Close buttons
xpos = HBORDER; 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 + BUTTON_GAP;
myNextButton =
new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight,
"Next", GuiObject::kNextCmd);
@ -61,7 +63,7 @@ R77HelpDialog::R77HelpDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(b);
addCancelWidget(b);
xpos = HBORDER; ypos = 5 + _th;
xpos = HBORDER; ypos = VBORDER + _th;
myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2, fontHeight,
"", TextAlign::Center);

View File

@ -37,49 +37,47 @@
RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Audit ROMs"),
myFont{font},
myMaxWidth{max_w},
myMaxHeight{max_h}
{
const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
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;
int xpos, ypos = VBORDER;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Audit path" + ELLIPSIS),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int lwidth = font.getStringWidth("ROMs without properties (skipped) ");
int xpos, ypos = _th + VBORDER;
WidgetArray wid;
// Set real dimensions
_w = 64 * fontWidth + HBORDER * 2;
_h = 7 * (lineHeight + 4) + VBORDER;
_h = _th + VBORDER * 2 + buttonHeight * 2 + lineHeight * 3 + VGAP * 10;
// Audit path
ButtonWidget* romButton =
new ButtonWidget(this, font, HBORDER, ypos, buttonWidth, buttonHeight,
"Audit path" + ELLIPSIS, kChooseAuditDirCmd);
wid.push_back(romButton);
xpos = HBORDER + buttonWidth + 8;
xpos = HBORDER + buttonWidth + fontWidth;
myRomPath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1,
_w - xpos - HBORDER, lineHeight, "");
_w - xpos - HBORDER, lineHeight);
wid.push_back(myRomPath);
// Show results of ROM audit
ypos += buttonHeight + 16;
ypos += buttonHeight + VGAP * 4;
new StaticTextWidget(this, font, HBORDER, ypos, "ROMs with properties (renamed) ");
myResults1 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2,
fontWidth * 6, lineHeight, "");
fontWidth * 6, lineHeight);
myResults1->setEditable(false, true);
ypos += buttonHeight;
new StaticTextWidget(this, font, HBORDER, ypos, "ROMs without properties (skipped) ");
myResults2 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2,
fontWidth * 6, lineHeight, "");
fontWidth * 6, lineHeight);
myResults2->setEditable(false, true);
ypos += buttonHeight + 8;
ypos += buttonHeight + VGAP * 2;
new StaticTextWidget(this, font, HBORDER, ypos, "(*) WARNING: Operation cannot be undone!");
// Add OK and Cancel buttons
@ -186,7 +184,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd,
msg.push_back("If you're sure you want to proceed with the");
msg.push_back("audit, click 'OK', otherwise click 'Cancel'.");
myConfirmMsg = make_unique<GUI::MessageBox>
(this, myFont, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd,
(this, _font, msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd,
"OK", "Cancel", "ROM Audit", false);
}
myConfirmMsg->show();
@ -198,36 +196,20 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kChooseAuditDirCmd:
createBrowser("Select ROM directory to audit");
myBrowser->show(myRomPath->getText(),
BrowserDialog::Directories, kAuditDirChosenCmd);
BrowserDialog::show(this, _font, "Select ROM Directory to Audit",
myRomPath->getText(),
BrowserDialog::Mode::Directories,
[this](bool OK, const FilesystemNode& node) {
if(OK) {
myRomPath->setText(node.getShortPath());
myResults1->setText("");
myResults2->setText("");
}
});
break;
case kAuditDirChosenCmd:
{
FilesystemNode dir(myBrowser->getResult());
myRomPath->setText(dir.getShortPath());
myResults1->setText("");
myResults2->setText("");
break;
}
default:
Dialog::handleCommand(sender, cmd, data, 0);
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomAuditDialog::createBrowser(const string& title)
{
uInt32 w = 0, h = 0;
getDynamicBounds(w, h);
// Create file browser dialog
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
else
myBrowser->setTitle(title);
}

View File

@ -23,7 +23,6 @@ class GuiObject;
class DialogContainer;
class EditTextWidget;
class StaticTextWidget;
class BrowserDialog;
namespace GUI {
class MessageBox;
}
@ -42,20 +41,14 @@ class RomAuditDialog : public Dialog
private:
void loadConfig() override;
void auditRoms();
void createBrowser(const string& title);
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
private:
enum {
kChooseAuditDirCmd = 'RAsl', // audit dir select
kAuditDirChosenCmd = 'RAch', // audit dir changed
kConfirmAuditCmd = 'RAcf' // confirm rom audit
};
// Select a new ROM audit path
unique_ptr<BrowserDialog> myBrowser;
const GUI::Font& myFont;
// ROM audit path
EditTextWidget* myRomPath{nullptr};

View File

@ -236,6 +236,7 @@ void ScrollBarWidget::checkBounds(int old_pos)
if (old_pos != _currentPos)
{
recalc();
setDirty();
sendCommand(GuiObject::kSetPositionCmd, _currentPos, _id);
}
}
@ -308,7 +309,13 @@ void ScrollBarWidget::drawWidget(bool hilite)
// Slider
if(!isSinglePage)
{
s.fillRect(_x + 1, _y + _sliderPos - 1, _w - 2, _sliderHeight + 2,
// align slider to scroll intervals
int alignedPos = _upDownBoxHeight + (_h - 2 * _upDownBoxHeight - _sliderHeight) *
_currentPos / (_numEntries - _entriesPerPage);
if(alignedPos < 0)
alignedPos = 0;
s.fillRect(_x + 1, _y + alignedPos - 1, _w - 2, _sliderHeight + 2,
(hilite && _part == Part::Slider) ? kScrollColorHi : kScrollColor);
}
clearDirty();
@ -316,4 +323,3 @@ void ScrollBarWidget::drawWidget(bool hilite)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int ScrollBarWidget::_WHEEL_LINES = 4;

View File

@ -28,19 +28,16 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Snapshot settings"),
myFont{font}
: Dialog(osystem, parent, font, "Snapshot settings")
{
const int lineHeight = font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
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;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Save path" + ELLIPSIS),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos, fwidth;
WidgetArray wid;
ButtonWidget* b;
@ -98,11 +95,6 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
addToFocusList(wid);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SnapshotDialog::~SnapshotDialog()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SnapshotDialog::loadConfig()
{
@ -131,7 +123,7 @@ void SnapshotDialog::saveConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SnapshotDialog::setDefaults()
{
mySnapSavePath->setText(instance().defaultSaveDir().getShortPath());
mySnapSavePath->setText(instance().userDir().getShortPath());
mySnapInterval->setValue(2);
mySnapName->setState(false);
mySnapSingle->setState(false);
@ -154,15 +146,12 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kChooseSnapSaveDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser("Select snapshot save directory");
myBrowser->show(mySnapSavePath->getText(),
BrowserDialog::Directories, kSnapSaveDirChosenCmd);
break;
case kSnapSaveDirChosenCmd:
mySnapSavePath->setText(myBrowser->getResult().getShortPath());
BrowserDialog::show(this, _font, "Select Snapshot Save Directory",
mySnapSavePath->getText(),
BrowserDialog::Mode::Directories,
[this](bool OK, const FilesystemNode& node) {
if(OK) mySnapSavePath->setText(node.getShortPath());
});
break;
case kSnapshotInterval:
@ -177,17 +166,3 @@ void SnapshotDialog::handleCommand(CommandSender* sender, int cmd,
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SnapshotDialog::createBrowser(const string& title)
{
uInt32 w = 0, h = 0;
getDynamicBounds(w, h);
// Create file browser dialog
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
else
myBrowser->setTitle(title);
}

View File

@ -25,7 +25,6 @@ class CheckboxWidget;
class EditTextWidget;
class SliderWidget;
class StaticTextWidget;
class BrowserDialog;
#include "Dialog.hxx"
#include "Command.hxx"
@ -35,7 +34,7 @@ class SnapshotDialog : public Dialog
public:
SnapshotDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h);
~SnapshotDialog() override;
~SnapshotDialog() override = default;
private:
void loadConfig() override;
@ -43,17 +42,13 @@ class SnapshotDialog : public Dialog
void setDefaults() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void createBrowser(const string& title);
private:
enum {
kChooseSnapSaveDirCmd = 'LOss', // snapshot dir (save files)
kSnapSaveDirChosenCmd = 'snsc', // snap chosen (save files)
kSnapshotInterval = 'SnIn' // snap chosen (load files)
};
const GUI::Font& myFont;
// Config paths
EditTextWidget* mySnapSavePath{nullptr};
@ -63,8 +58,6 @@ class SnapshotDialog : public Dialog
CheckboxWidget* mySnapSingle{nullptr};
CheckboxWidget* mySnap1x{nullptr};
unique_ptr<BrowserDialog> myBrowser;
private:
// Following constructors and assignment operators not supported
SnapshotDialog() = delete;

View File

@ -34,16 +34,15 @@ StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& pa
: Dialog(osystem, parent, osystem.frameBuffer().font(), "Basic settings"),
myMode{mode}
{
const int buttonHeight = _font.getLineHeight() + _font.getLineHeight() / 5,
lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
buttonWidth = _font.getStringWidth(" Help " + ELLIPSIS),
iLineHeight = instance().frameBuffer().infoFont().getLineHeight();
const int VBORDER = _font.getFontHeight() / 2;
const int HBORDER = fontWidth;
const int INDENT = fontWidth * 2;
const int VGAP = _font.getFontHeight() / 4;
const int iLineHeight = instance().frameBuffer().infoFont().getLineHeight();
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth(" Help " + ELLIPSIS),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos;
ButtonWidget* bw = nullptr;
@ -97,8 +96,8 @@ StellaSettingsDialog::~StellaSettingsDialog()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos)
{
const int VGAP = _font.getFontHeight() / 4;
const int lineHeight = _font.getLineHeight();
const int lineHeight = Dialog::lineHeight(),
VGAP = Dialog::vGap();
VariantList items;
int pwidth = _font.getStringWidth("Right bottom"); // align width with other popup
@ -126,10 +125,10 @@ void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypos)
{
const int VGAP = _font.getFontHeight() / 4;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
VGAP = Dialog::vGap();
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth();
VariantList items;
// TV effects options
@ -180,8 +179,8 @@ void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypo
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos)
{
const int VGAP = _font.getFontHeight() / 4;
const int lineHeight = _font.getLineHeight();
const int lineHeight = Dialog::lineHeight(),
VGAP = Dialog::vGap();
const GUI::Font& ifont = instance().frameBuffer().infoFont();
VariantList ctrls;

View File

@ -42,18 +42,17 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, GuiObject* boss, int max_w, int max_h)
: Dialog(osystem, parent, font, "User interface settings"),
CommandSender(boss),
myFont{font},
myIsGlobal{boss != nullptr}
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
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 INDENT = fontWidth * 2;
const int VGAP = fontHeight / 4;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
int xpos, ypos, tabID;
int lwidth, pwidth, bwidth;
WidgetArray wid;
@ -91,7 +90,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myPalettePopup);
ypos += lineHeight + VGAP;
// Dialog font
items.clear();
VarList::push_back(items, "Small", "small"); // 8x13
@ -318,11 +316,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UIDialog::~UIDialog()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UIDialog::loadConfig()
{
@ -515,7 +508,7 @@ void UIDialog::setDefaults()
myLauncherHeightSlider->setValue(h);
myLauncherFontPopup->setSelected("medium", "");
myRomViewerSize->setValue(35);
mySnapLoadPath->setText(instance().defaultLoadDir().getShortPath());
mySnapLoadPath->setText(instance().userDir().getShortPath());
myLauncherExitWidget->setState(false);
break;
}
@ -584,15 +577,12 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
break;
case kChooseRomDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser("Select ROM directory");
myBrowser->show(myRomPath->getText(),
BrowserDialog::Directories, LauncherDialog::kRomDirChosenCmd);
break;
case LauncherDialog::kRomDirChosenCmd:
myRomPath->setText(myBrowser->getResult().getShortPath());
BrowserDialog::show(this, _font, "Select ROM Directory",
myRomPath->getText(),
BrowserDialog::Mode::Directories,
[this](bool OK, const FilesystemNode& node) {
if(OK) myRomPath->setText(node.getShortPath());
});
break;
case kRomViewer:
@ -600,15 +590,12 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
break;
case kChooseSnapLoadDirCmd:
// This dialog is resizable under certain conditions, so we need
// to re-create it as necessary
createBrowser("Select snapshot load directory");
myBrowser->show(mySnapLoadPath->getText(),
BrowserDialog::Directories, kSnapLoadDirChosenCmd);
break;
case kSnapLoadDirChosenCmd:
mySnapLoadPath->setText(myBrowser->getResult().getShortPath());
BrowserDialog::show(this, _font, "Select ROM Info Viewer Image Directory",
mySnapLoadPath->getText(),
BrowserDialog::Mode::Directories,
[this](bool OK, const FilesystemNode& node) {
if(OK) mySnapLoadPath->setText(node.getShortPath());
});
break;
default:
@ -700,17 +687,3 @@ void UIDialog::handleRomViewer()
myOpenBrowserButton->setEnabled(enable);
mySnapLoadPath->setEnabled(enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UIDialog::createBrowser(const string& title)
{
uInt32 w = 0, h = 0;
getDynamicBounds(w, h);
// Create file browser dialog
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
uInt32(myBrowser->getHeight()) != h)
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
else
myBrowser->setTitle(title);
}

View File

@ -18,14 +18,15 @@
#ifndef UI_DIALOG_HXX
#define UI_DIALOG_HXX
class BrowserDialog;
#include "Dialog.hxx"
#include "bspf.hxx"
class UIDialog : public Dialog, public CommandSender
{
public:
UIDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
GuiObject* boss, int max_w, int max_h);
~UIDialog() override;
~UIDialog() override = default;
private:
void loadConfig() override;
@ -35,7 +36,6 @@ class UIDialog : public Dialog, public CommandSender
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void handleLauncherSize();
void handleRomViewer();
void createBrowser(const string& title);
private:
enum
@ -46,11 +46,9 @@ class UIDialog : public Dialog, public CommandSender
kControllerDelay = 'UIcd',
kChooseRomDirCmd = 'LOrm', // rom select
kRomViewer = 'UIRv',
kChooseSnapLoadDirCmd = 'UIsl', // snapshot dir (load files)
kSnapLoadDirChosenCmd = 'UIsc' // snap chosen (load files)
kChooseSnapLoadDirCmd = 'UIsl' // snapshot dir (load files)
};
const GUI::Font& myFont;
TabWidget* myTab{nullptr};
// Launcher options
@ -76,8 +74,6 @@ class UIDialog : public Dialog, public CommandSender
SliderWidget* myControllerDelaySlider{nullptr};
SliderWidget* myDoubleClickSlider{nullptr};
unique_ptr<BrowserDialog> myBrowser;
// Indicates if this dialog is used for global (vs. in-game) settings
bool myIsGlobal{false};

View File

@ -57,13 +57,12 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent,
const GUI::Font& font, int max_w, int max_h)
: Dialog(osystem, parent, font, "Video & Audio settings")
{
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int xpos, ypos;
// Set real dimensions
@ -103,12 +102,12 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent,
void VideoAudioDialog::addDisplayTab()
{
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth();
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int INDENT = CheckboxWidget::prefixSize(_font);
const int lwidth = _font.getStringWidth("V-Size adjust "),
pwidth = _font.getStringWidth("OpenGLES2");
@ -199,13 +198,12 @@ void VideoAudioDialog::addDisplayTab()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoAudioDialog::addPaletteTab()
{
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;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap(),
INDENT = Dialog::indent();
const int lwidth = _font.getStringWidth(" NTSC phase ");
const int pwidth = _font.getStringWidth("Standard");
int xpos = HBORDER,
@ -331,14 +329,14 @@ void VideoAudioDialog::addPaletteTab()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoAudioDialog::addTVEffectsTab()
{
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 lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
buttonWidth = Dialog::buttonWidth("Clone Bad Adjust"),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2;
const int VGAP = fontHeight / 4;
int xpos = HBORDER,
ypos = VBORDER;
const int lwidth = _font.getStringWidth("Saturation ");
@ -392,14 +390,13 @@ void VideoAudioDialog::addTVEffectsTab()
CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged)
// Create buttons in 2nd column
int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5;
xpos = _w - HBORDER - 2 * 2 - cloneWidth;
xpos = _w - HBORDER - 2 * 2 - buttonWidth;
ypos = VBORDER - VGAP / 2;
// Adjustable presets
#define CREATE_CLONE_BUTTON(obj, desc) \
myClone ## obj = \
new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\
new ButtonWidget(myTab, _font, xpos, ypos, buttonWidth, buttonHeight,\
desc, kClone ## obj ##Cmd); \
wid.push_back(myClone ## obj); \
ypos += buttonHeight + VGAP;
@ -418,14 +415,12 @@ void VideoAudioDialog::addTVEffectsTab()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoAudioDialog::addAudioTab()
{
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth();
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontWidth = Dialog::fontWidth(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
const int INDENT = CheckboxWidget::prefixSize(_font);
const int VGAP = fontHeight / 4;
int xpos, ypos;
int lwidth = _font.getStringWidth("Volume "),
pwidth;

View File

@ -15,6 +15,8 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "Version.hxx"
#include "WhatsNewDialog.hxx"
@ -22,20 +24,21 @@
constexpr int MAX_CHARS = 64; // maximum number of chars per line
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent,
int max_w, int max_h)
#if defined(RETRON77)
: Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + " for RetroN 77?")
: Dialog(osystem, parent, osystem.frameBuffer().font(),
"What's New in Stella " + string(STELLA_VERSION) + " for RetroN 77?")
#else
: Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + "?")
: Dialog(osystem, parent, osystem.frameBuffer().font(),
"What's New in Stella " + string(STELLA_VERSION) + "?")
#endif
{
const int fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth(),
buttonHeight = _font.getLineHeight() * 1.25;
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int fontWidth = Dialog::fontWidth(),
buttonHeight = Dialog::buttonHeight(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder(),
VGAP = Dialog::vGap();
int ypos = _th + VBORDER;
// Set preliminary dimensions
@ -75,10 +78,9 @@ WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void WhatsNewDialog::add(int& ypos, const string& text)
{
const int lineHeight = _font.getLineHeight(),
fontHeight = _font.getFontHeight(),
fontWidth = _font.getMaxCharWidth(),
HBORDER = fontWidth * 1.25;
const int lineHeight = Dialog::lineHeight(),
fontHeight = Dialog::fontHeight(),
HBORDER = Dialog::hBorder();
const string DOT = "\x1f";
string txt = DOT + " " + text;

View File

@ -23,7 +23,7 @@
class WhatsNewDialog : public Dialog
{
public:
WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
WhatsNewDialog(OSystem& osystem, DialogContainer& parent,
int max_w, int max_h);
~WhatsNewDialog() override = default;

View File

@ -203,6 +203,36 @@ void Widget::setPos(const Common::Point& pos)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::setWidth(int w)
{
setSize(w, _h);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::setHeight(int h)
{
setSize(_w, h);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::setSize(int w, int h)
{
setSize(Common::Point(w, h));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::setSize(const Common::Point& pos)
{
if(pos != Common::Point(_w, _h))
{
_w = pos.x;
_h = pos.y;
// we have to redraw the whole dialog!
dialog().setDirty();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::handleMouseEntered()
{

View File

@ -57,6 +57,10 @@ class Widget : public GuiObject
virtual void setPosY(int y);
virtual void setPos(int x, int y);
virtual void setPos(const Common::Point& pos);
void setWidth(int w) override;
void setHeight(int h) override;
virtual void setSize(int w, int h);
virtual void setSize(const Common::Point& pos);
virtual bool handleText(char text) { return false; }
virtual bool handleKeyDown(StellaKey key, StellaMod mod) { return false; }
@ -236,6 +240,8 @@ class ButtonWidget : public StaticTextWidget, public CommandSender
int cmd = 0, bool repeat = false);
~ButtonWidget() override = default;
bool handleEvent(Event::Type event) override;
void setCmd(int cmd) { _cmd = cmd; }
int getCmd() const { return _cmd; }
/* Sets/changes the button's bitmap **/
@ -247,7 +253,6 @@ class ButtonWidget : public StaticTextWidget, public CommandSender
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
void handleMouseEntered() override;
void handleMouseLeft() override;
bool handleEvent(Event::Type event) override;
void drawWidget(bool hilite) override;

View File

@ -25,9 +25,8 @@
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystemLIBRETRO::getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
void OSystemLIBRETRO::getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir)
{
loaddir = savedir = basedir = "." + slash;
basedir = homedir = "." + slash;
}

View File

@ -38,8 +38,7 @@ class OSystemLIBRETRO : public OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -47,9 +46,8 @@ class OSystemLIBRETRO : public OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) override;
};
#endif

View File

@ -95,6 +95,11 @@ static AboutBox *sharedInstance = nil;
withRTF:[creditsString RTFFromRange:
NSMakeRange( 0, [creditsString length] )
documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]];
if (@available(macOS 10.14, *)) {
creditsField.usesAdaptiveColorMappingForDarkAppearance = true;
} else {
// Fallback on earlier versions
}
// Prepare some scroll info
creditsBounds = [creditsField bounds];

View File

@ -19,9 +19,8 @@
#include "OSystemMACOS.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystemMACOS::getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
void OSystemMACOS::getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir)
{
basedir = "~/Library/Application Support/Stella/";
@ -30,12 +29,9 @@ void OSystemMACOS::getBaseDirAndConfig(string& basedir,
if(useappdir)
cout << "ERROR: base dir in app folder not supported" << endl;
else if(usedir != "")
{
basedir = FilesystemNode(usedir).getPath();
savedir = loaddir = basedir;
}
#endif
FilesystemNode desktop("~/Desktop/");
savedir = loaddir = desktop.isDirectory() ? desktop.getShortPath() : "~/";
homedir = desktop.isDirectory() ? desktop.getShortPath() : "~/";
}

View File

@ -38,8 +38,7 @@ class OSystemMACOS : public OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -47,9 +46,9 @@ class OSystemMACOS : public OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported
OSystemMACOS(const OSystemMACOS&) = delete;

View File

@ -89,30 +89,6 @@ class FilesystemNodePOSIX : public AbstractFSNode
* using the stat() function.
*/
void setFlags();
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
static const char* lastPathComponent(const string& str)
{
if(str.empty())
return "";
const char* start = str.c_str();
const char* cur = start + str.size() - 2;
while (cur >= start && *cur != '/')
--cur;
return cur + 1;
}
};
#endif

View File

@ -22,22 +22,18 @@
#include "OSystemUNIX.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystemUNIX::getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
void OSystemUNIX::getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir)
{
// Use XDG_CONFIG_HOME if defined, otherwise use the default
string configDir = BSPF::getenv("XDG_CONFIG_HOME");
if(configDir == EmptyString) configDir = "~/.config";
basedir = configDir + "/stella";
savedir = loaddir = "~/";
homedir = "~/";
// Check to see if basedir overrides are active
if(useappdir)
cout << "ERROR: base dir in app folder not supported" << endl;
else if(usedir != "")
{
basedir = FilesystemNode(usedir).getPath();
savedir = loaddir = basedir;
}
}

View File

@ -38,8 +38,7 @@ class OSystemUNIX : public OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -47,9 +46,8 @@ class OSystemUNIX : public OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported

View File

@ -18,8 +18,8 @@
#include "OSystemR77.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystemR77::getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir, bool, const string&)
void OSystemR77::getBaseDirAndConfig(string& basedir, string& homeDir,
bool, const string&)
{
basedir = savedir = loaddir = "/mnt/stella";
basedir = homeDir = "/mnt/stella";
}

View File

@ -40,8 +40,7 @@ class OSystemR77 : public OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -49,9 +48,8 @@ class OSystemR77 : public OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported

View File

@ -39,31 +39,6 @@
#include "Windows.hxx"
#include "FSNodeWINDOWS.hxx"
/**
* Returns the last component of a given path.
*
* Examples:
* c:\foo\bar.txt would return "\bar.txt"
* c:\foo\bar\ would return "\bar\"
*
* @param str Path to obtain the last component from.
* @return Pointer to the first char of the last component inside str.
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* lastPathComponent(const string& str)
{
if(str.empty())
return "";
const char* start = str.c_str();
const char* cur = start + str.size() - 2;
while(cur >= start && *cur != '\\')
--cur;
return cur + 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNodeWINDOWS::exists() const
{

View File

@ -22,12 +22,12 @@
#include "OSystemWINDOWS.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystemWINDOWS::getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
void OSystemWINDOWS::getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir)
{
HomeFinder homefinder;
FilesystemNode appdata(homefinder.getAppDataPath());
if(appdata.isDirectory())
{
basedir = appdata.getShortPath();
@ -35,8 +35,9 @@ void OSystemWINDOWS::getBaseDirAndConfig(string& basedir,
basedir += '\\';
basedir += "Stella\\";
}
FilesystemNode defaultLoadSaveDir(homefinder.getDesktopPath());
savedir = loaddir = defaultLoadSaveDir.getShortPath();
FilesystemNode defaultHomeDir(homefinder.getDesktopPath());
homedir = defaultHomeDir.getShortPath();
// Check to see if basedir overrides are active
if(useappdir)
@ -44,10 +45,11 @@ void OSystemWINDOWS::getBaseDirAndConfig(string& basedir,
char filename[MAX_PATH];
GetModuleFileNameA(NULL, filename, sizeof(filename));
FilesystemNode appdir(filename);
appdir = appdir.getParent();
if(appdir.isDirectory())
savedir = loaddir = basedir = appdir.getPath();
basedir = appdir.getPath();
}
else if(usedir != "")
savedir = loaddir = basedir = FilesystemNode(usedir).getPath();
basedir = FilesystemNode(usedir).getPath();
}

View File

@ -38,8 +38,7 @@ class OSystemWINDOWS : public OSystem
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param homedir The default directory to store various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@ -47,9 +46,8 @@ class OSystemWINDOWS : public OSystem
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
void getBaseDirAndConfig(string& basedir, string& homedir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported