mirror of https://github.com/stella-emu/stella.git
initial commit
This commit is contained in:
parent
859f33f54c
commit
00841dc6ec
|
@ -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
|
||||
|
@ -294,7 +294,7 @@ more convenient.
|
|||
<li>
|
||||
"<rom_filename>.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>
|
||||
|
@ -917,7 +917,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
|
||||
|
@ -954,11 +954,11 @@ clearsavestateifs - Clear all savestate points
|
|||
joy1fire - Set joystick 1 fire button to value <x> (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)
|
||||
|
@ -979,12 +979,12 @@ clearsavestateifs - Clear all savestate points
|
|||
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)
|
||||
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)
|
||||
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 <condition>
|
||||
scanline - Advance emulation by <xx> scanlines (default=1)
|
||||
|
@ -1333,11 +1333,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,
|
||||
|
@ -1363,7 +1363,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>
|
||||
|
@ -1377,7 +1377,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>
|
||||
|
@ -1504,7 +1504,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>
|
||||
|
@ -1512,7 +1512,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>
|
||||
|
||||
|
@ -1587,7 +1587,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
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "PromptWidget.hxx"
|
||||
#include "RomWidget.hxx"
|
||||
#include "ProgressDialog.hxx"
|
||||
#include "BrowserDialog.hxx"
|
||||
#include "TimerManager.hxx"
|
||||
#include "Vec.hxx"
|
||||
|
||||
|
@ -1828,14 +1829,20 @@ void DebuggerParser::executeS()
|
|||
// "save"
|
||||
void DebuggerParser::executeSave()
|
||||
{
|
||||
commandResult << saveScriptFile(argStrings[0]);
|
||||
if(argCount && argStrings[0] == "?")
|
||||
debugger.myDialog->showBrowser(DebuggerDialog::svScript);
|
||||
else
|
||||
commandResult << saveScriptFile(argStrings[0]);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "saveaccess"
|
||||
void DebuggerParser::executeSaveAccess()
|
||||
{
|
||||
commandResult << debugger.cartDebug().saveAccessFile();
|
||||
if(argCount && argStrings[0] == "?")
|
||||
debugger.myDialog->showBrowser(DebuggerDialog::svAccess);
|
||||
else
|
||||
commandResult << debugger.cartDebug().saveAccessFile();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -37,19 +37,20 @@
|
|||
#include "DataGridOpsWidget.hxx"
|
||||
#include "EditTextWidget.hxx"
|
||||
#include "MessageBox.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "DebuggerParser.hxx"
|
||||
#include "debugger.hxx"
|
||||
#include "debuggerParser.hxx"
|
||||
#include "ConsoleFont.hxx"
|
||||
#include "ConsoleBFont.hxx"
|
||||
#include "ConsoleMediumFont.hxx"
|
||||
#include "ConsoleMediumBFont.hxx"
|
||||
#include "StellaMediumFont.hxx"
|
||||
#include "OptionsDialog.hxx"
|
||||
#include "BrowserDialog.hxx"
|
||||
#include "StateManager.hxx"
|
||||
#include "FrameManager.hxx"
|
||||
#include "OSystem.hxx"
|
||||
#include "Console.hxx"
|
||||
#include "DebuggerDialog.hxx"
|
||||
#include "debuggerDialog.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent,
|
||||
|
@ -256,6 +257,43 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
loadConfig();
|
||||
break;
|
||||
|
||||
case kSvScriptCmd:
|
||||
execSave("save");
|
||||
break;
|
||||
|
||||
case kSvSessionCmd:
|
||||
execSave("saveses");
|
||||
break;
|
||||
|
||||
case kSvConfigCmd:
|
||||
execSave("saveconfig");
|
||||
break;
|
||||
|
||||
case kSvDisCmd:
|
||||
execSave("savedis");
|
||||
break;
|
||||
|
||||
case kSvAccessCmd:
|
||||
execSave("saveaccess");
|
||||
break;
|
||||
|
||||
case kSvRomCmd:
|
||||
execSave("saverom");
|
||||
break;
|
||||
|
||||
case kSvStateCmd:
|
||||
execSave("savestate");
|
||||
break;
|
||||
|
||||
|
||||
case kSvAllStatesCmd:
|
||||
execSave("saveallstates");
|
||||
break;
|
||||
|
||||
case kSvSnapCmd:
|
||||
execSave("savesnap"); // TODO: param
|
||||
break;
|
||||
|
||||
case RomWidget::kInvalidateListing:
|
||||
// Only do a full redraw if the disassembly tab is actually showing
|
||||
myRom->invalidate(myRomTab->getActiveTab() == 0);
|
||||
|
@ -408,6 +446,114 @@ void DebuggerDialog::createFont()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::showBrowser(BrowserType type)
|
||||
{
|
||||
int cmd;
|
||||
string title;
|
||||
string key;
|
||||
string defaultPath;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case BrowserType::svScript:
|
||||
cmd = kSvScriptCmd;
|
||||
title = "workbench";
|
||||
key = "dbg.savepath";
|
||||
defaultPath = instance().defaultSaveDir().getPath() + "commands.script";
|
||||
break;
|
||||
|
||||
case BrowserType::svSession:
|
||||
cmd = kSvSessionCmd;
|
||||
title = "session";
|
||||
key = "dbg.savesessionpath";
|
||||
break;
|
||||
|
||||
case BrowserType::svConfig:
|
||||
cmd = kSvConfigCmd;
|
||||
title = "DiStella config";
|
||||
key = "dbg.saveconfigpath";
|
||||
break;
|
||||
|
||||
case BrowserType::svDis:
|
||||
cmd = kSvDisCmd;
|
||||
title = "disassembly";
|
||||
key = "dbg.savedispath";
|
||||
break;
|
||||
|
||||
case BrowserType::svAccess:
|
||||
cmd = kSvAccessCmd;
|
||||
title = "access counters";
|
||||
key = "dbg.saveaccesspath";
|
||||
break;
|
||||
|
||||
case BrowserType::svRom:
|
||||
cmd = kSvRomCmd;
|
||||
title = "ROM";
|
||||
key = "dbg.saverompath";
|
||||
break;
|
||||
|
||||
case BrowserType::svState:
|
||||
cmd = kSvStateCmd;
|
||||
title = "state";
|
||||
key = "dbg.savestatepath";
|
||||
break;
|
||||
|
||||
case BrowserType::svAllStates:
|
||||
cmd = kSvAllStatesCmd;
|
||||
title = "all states";
|
||||
key = "dbg.savestatepath";
|
||||
break;
|
||||
|
||||
case BrowserType::svSnap:
|
||||
cmd = kSvSnapCmd;
|
||||
title = "snapshot";
|
||||
key = "snapsavedir";
|
||||
break;
|
||||
|
||||
default:
|
||||
cmd = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(cmd)
|
||||
{
|
||||
//TODO: default path (path and filename)
|
||||
string path = instance().settings().getString(key);
|
||||
|
||||
createBrowser("Save " + title + " as");
|
||||
|
||||
if(path.empty())
|
||||
path = defaultPath;
|
||||
|
||||
//myBrowser->show(instance().defaultSaveDir().getPath(),
|
||||
// BrowserDialog::FileSave, cmd);
|
||||
myBrowser->show(path, BrowserDialog::FileSave, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::execSave(const string& command)
|
||||
{
|
||||
FilesystemNode dir(myBrowser->getResult());
|
||||
|
||||
instance().debugger().parser().run(command + " " + dir.getShortPath());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::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, instance().frameBuffer().font(), w, h, title);
|
||||
else
|
||||
myBrowser->setTitle(title);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::showFatalMessage(const string& msg)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ class TiaZoomWidget;
|
|||
class CartDebugWidget;
|
||||
class CartRamWidget;
|
||||
class OptionsDialog;
|
||||
class BrowserDialog;
|
||||
|
||||
namespace GUI {
|
||||
class MessageBox;
|
||||
|
@ -54,6 +55,17 @@ class DebuggerDialog : public Dialog
|
|||
kMediumFontMinW = 1160, kMediumFontMinH = 770,
|
||||
kLargeFontMinW = 1160, kLargeFontMinH = 870
|
||||
};
|
||||
enum BrowserType {
|
||||
svScript, // save
|
||||
svSession, // saveses
|
||||
svConfig, // saveconfig
|
||||
svDis, // savedis
|
||||
svAccess, // saveaccess
|
||||
svRom, // saverom
|
||||
svState, // savestate
|
||||
svAllStates, // saveallstates
|
||||
svSnap // savesnap
|
||||
};
|
||||
|
||||
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
|
||||
int x, int y, int w, int h);
|
||||
|
@ -74,6 +86,7 @@ class DebuggerDialog : public Dialog
|
|||
|
||||
void showFatalMessage(const string& msg);
|
||||
void saveConfig() override;
|
||||
void showBrowser(BrowserType type);
|
||||
|
||||
private:
|
||||
void center() override { positionAt(0); }
|
||||
|
@ -113,11 +126,23 @@ class DebuggerDialog : public Dialog
|
|||
kDDSAdvCmd = 'DDsv',
|
||||
kDDRewindCmd = 'DDrw',
|
||||
kDDUnwindCmd = 'DDuw',
|
||||
kDDRunCmd = 'DDex',
|
||||
kDDRunCmd = 'DDex',
|
||||
kDDExitFatalCmd = 'DDer',
|
||||
kDDOptionsCmd = 'DDop'
|
||||
kDDOptionsCmd = 'DDop',
|
||||
kSvScriptCmd = 'SvSc',
|
||||
kSvSessionCmd = 'SvSs',
|
||||
kSvConfigCmd = 'SvCn',
|
||||
kSvDisCmd = 'SvDs',
|
||||
kSvAccessCmd = 'SvAc',
|
||||
kSvRomCmd = 'SvRm',
|
||||
kSvStateCmd = 'SvSt',
|
||||
kSvAllStatesCmd = 'SvAs',
|
||||
kSvSnapCmd = 'SvSn'
|
||||
};
|
||||
|
||||
void execSave(const string& command);
|
||||
void createBrowser(const string& title);
|
||||
|
||||
TabWidget *myTab{nullptr}, *myRomTab{nullptr};
|
||||
|
||||
PromptWidget* myPrompt{nullptr};
|
||||
|
@ -135,7 +160,8 @@ class DebuggerDialog : public Dialog
|
|||
ButtonWidget* myUnwindButton{nullptr};
|
||||
|
||||
unique_ptr<GUI::MessageBox> myFatalError;
|
||||
unique_ptr<OptionsDialog> myOptions;
|
||||
unique_ptr<OptionsDialog> myOptions;
|
||||
unique_ptr<BrowserDialog> myBrowser;
|
||||
|
||||
unique_ptr<GUI::Font> myLFont; // used for labels
|
||||
unique_ptr<GUI::Font> myNFont; // used for normal text
|
||||
|
|
|
@ -74,7 +74,7 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
|
|||
_type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name ");
|
||||
_selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos,
|
||||
_w - _type->getWidth() - 2 * xpos, lineHeight, "");
|
||||
_selected->setEditable(false);
|
||||
addFocusWidget(_selected);
|
||||
|
||||
// Buttons
|
||||
_goUpButton = new ButtonWidget(this, font, xpos, _h - buttonHeight - VBORDER,
|
||||
|
@ -112,45 +112,71 @@ void BrowserDialog::show(const string& startpath,
|
|||
BrowserDialog::ListMode mode, int cmd,
|
||||
const string& ext)
|
||||
{
|
||||
#ifdef BSPF_WINDOWS
|
||||
#define PATH_SEPARATOR '\\'
|
||||
#else
|
||||
#define PATH_SEPARATOR '/'
|
||||
#endif
|
||||
_cmd = cmd;
|
||||
_mode = mode;
|
||||
string fileName;
|
||||
|
||||
// Set start path
|
||||
if(_mode != Directories)
|
||||
{
|
||||
// split startpath into path and filename
|
||||
FilesystemNode fs = FilesystemNode(startpath);
|
||||
fileName = fs.getName();
|
||||
string directory = fs.isDirectory() ? "" : fs.getParent().getPath();
|
||||
|
||||
_fileList->setDirectory(FilesystemNode(directory), fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileList->setDirectory(FilesystemNode(startpath));
|
||||
}
|
||||
|
||||
switch(_mode)
|
||||
{
|
||||
case FileLoad:
|
||||
_fileList->setListMode(FilesystemNode::ListMode::All);
|
||||
_fileList->setNameFilter([&ext](const FilesystemNode& node) {
|
||||
_fileList->setNameFilter([ext](const FilesystemNode& node) {
|
||||
return BSPF::endsWithIgnoreCase(node.getName(), ext);
|
||||
});
|
||||
_selected->setEditable(false);
|
||||
_selected->setEnabled(false);
|
||||
_selected->clearFlags(Widget::FLAG_INVISIBLE);
|
||||
_type->clearFlags(Widget::FLAG_INVISIBLE);
|
||||
_okWidget->setLabel("Load");
|
||||
updateUI(true);
|
||||
break;
|
||||
|
||||
case FileSave:
|
||||
_fileList->setListMode(FilesystemNode::ListMode::All);
|
||||
_fileList->setNameFilter([&ext](const FilesystemNode& node) {
|
||||
_fileList->setNameFilter([ext](const FilesystemNode& node) {
|
||||
return BSPF::endsWithIgnoreCase(node.getName(), ext);
|
||||
});
|
||||
_selected->setEditable(false); // FIXME - disable user input for now
|
||||
_selected->setEditable(true);
|
||||
_selected->setEnabled(true);
|
||||
_selected->clearFlags(Widget::FLAG_INVISIBLE);
|
||||
_type->clearFlags(Widget::FLAG_INVISIBLE);
|
||||
_okWidget->setLabel("Save");
|
||||
_selected->setText(fileName);
|
||||
updateUI(false);
|
||||
break;
|
||||
|
||||
case Directories:
|
||||
_fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly);
|
||||
_fileList->setNameFilter([](const FilesystemNode&) { return true; });
|
||||
_selected->setEditable(false);
|
||||
_selected->setEnabled(false);
|
||||
_selected->setFlags(Widget::FLAG_INVISIBLE);
|
||||
_type->setFlags(Widget::FLAG_INVISIBLE);
|
||||
_okWidget->setLabel("Choose");
|
||||
updateUI(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set start path
|
||||
_fileList->setDirectory(FilesystemNode(startpath));
|
||||
|
||||
updateUI();
|
||||
|
||||
// Finally, open the dialog after it has been fully updated
|
||||
open();
|
||||
}
|
||||
|
@ -159,13 +185,17 @@ void BrowserDialog::show(const string& startpath,
|
|||
const FilesystemNode& BrowserDialog::getResult() const
|
||||
{
|
||||
if(_mode == FileLoad || _mode == FileSave)
|
||||
return _fileList->selected();
|
||||
{
|
||||
static FilesystemNode node(_fileList->currentDir().getShortPath() + _selected->getText());
|
||||
|
||||
return node;
|
||||
}
|
||||
else
|
||||
return _fileList->currentDir();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BrowserDialog::updateUI()
|
||||
void BrowserDialog::updateUI(bool fileSelected)
|
||||
{
|
||||
// Only hilite the 'up' button if there's a parent directory
|
||||
_goUpButton->setEnabled(_fileList->currentDir().hasParent());
|
||||
|
@ -174,13 +204,56 @@ void BrowserDialog::updateUI()
|
|||
_currentPath->setText(_fileList->currentDir().getShortPath());
|
||||
|
||||
// Enable/disable OK button based on current mode
|
||||
bool enable = _mode == Directories || !_fileList->selected().isDirectory();
|
||||
//bool enable = true;
|
||||
//switch(_mode)
|
||||
//{
|
||||
// case Directories:
|
||||
// enable = true;
|
||||
// break;
|
||||
|
||||
// case FileLoad:
|
||||
// if(_fileList->selected().isDirectory())
|
||||
// {
|
||||
// enable = false;
|
||||
// _selected->setText("");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// enable = fileSelected && !_selected->getText().empty();
|
||||
// _selected->setText(_fileList->getSelectedString());
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case FileSave:
|
||||
// if(_fileList->selected().isDirectory())
|
||||
// {
|
||||
// enable = false;
|
||||
// _selected->setText("");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// enable = fileSelected && !_selected->getText().empty(); // TODO
|
||||
// _selected->setText(_fileList->getSelectedString());
|
||||
// }
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// break;
|
||||
//}
|
||||
//_okWidget->setEnabled(enable);
|
||||
|
||||
bool enable = _mode == Directories
|
||||
|| (!_fileList->selected().isDirectory() && fileSelected)
|
||||
|| (!_selected->getText().empty() && !fileSelected);
|
||||
_okWidget->setEnabled(enable);
|
||||
|
||||
if(!_fileList->selected().isDirectory())
|
||||
_selected->setText(_fileList->getSelectedString());
|
||||
else
|
||||
_selected->setText("");
|
||||
if(fileSelected)
|
||||
{
|
||||
if(!_fileList->selected().isDirectory())
|
||||
_selected->setText(_fileList->getSelectedString());
|
||||
else
|
||||
_selected->setText("");
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -205,8 +278,13 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
_fileList->setDirectory(FilesystemNode(instance().baseDir()));
|
||||
break;
|
||||
|
||||
case EditableWidget::kChangedCmd:
|
||||
Dialog::handleCommand(sender, cmd, data, 0);
|
||||
updateUI(false);
|
||||
break;
|
||||
|
||||
case FileListWidget::ItemChanged:
|
||||
updateUI();
|
||||
updateUI(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -52,7 +52,7 @@ class BrowserDialog : public Dialog, public CommandSender
|
|||
|
||||
private:
|
||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||
void updateUI();
|
||||
void updateUI(bool fileSelected);
|
||||
|
||||
private:
|
||||
enum {
|
||||
|
|
|
@ -684,7 +684,7 @@ bool Dialog::handleNavEvent(Event::Type e, bool repeated)
|
|||
if(_okWidget && _okWidget->isEnabled() && !repeated)
|
||||
{
|
||||
// Receiving 'OK' is the same as getting the 'Select' event
|
||||
_okWidget->handleEvent(Event::UISelect);
|
||||
//_okWidget->handleEvent(Event::UISelect);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -693,7 +693,7 @@ bool Dialog::handleNavEvent(Event::Type e, bool repeated)
|
|||
if(_cancelWidget && _cancelWidget->isEnabled() && !repeated)
|
||||
{
|
||||
// Receiving 'Cancel' is the same as getting the 'Select' event
|
||||
_cancelWidget->handleEvent(Event::UISelect);
|
||||
//_cancelWidget->handleEvent(Event::UISelect);
|
||||
return true;
|
||||
}
|
||||
else if(_processCancel)
|
||||
|
|
|
@ -73,9 +73,9 @@ class Dialog : public GuiObject
|
|||
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
||||
void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; }
|
||||
void addTabWidget(TabWidget* w);
|
||||
void addDefaultWidget(Widget* w) { _defaultWidget = w; }
|
||||
void addOKWidget(Widget* w) { _okWidget = w; }
|
||||
void addCancelWidget(Widget* w) { _cancelWidget = w; }
|
||||
void addDefaultWidget(ButtonWidget* w) { _defaultWidget = 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. */
|
||||
|
@ -192,9 +192,9 @@ 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* _okWidget{nullptr};
|
||||
ButtonWidget* _cancelWidget{nullptr};
|
||||
|
||||
bool _visible{false};
|
||||
bool _onTop{true};
|
||||
|
|
Loading…
Reference in New Issue