added subdirectory search to launcher

enhanced ProgressDialog
This commit is contained in:
thrust26 2020-11-22 12:39:17 +01:00
parent 4c97ec89c9
commit 1219fe0d2c
13 changed files with 330 additions and 67 deletions

View File

@ -76,9 +76,62 @@ bool FilesystemNode::exists() const
return _realNode ? _realNode->exists() : false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNode::getAllChildren(FSList& fslist, ListMode mode,
const NameFilter& filter,
bool includeParentDirectory) const
{
if(getChildren(fslist, mode, filter, includeParentDirectory))
{
// Sort only once at the end
#if defined(ZIP_SUPPORT)
// before sorting, replace single file ZIP archive names with contained file names
// because they are displayed using their contained file names
for(auto& i : fslist)
{
if(BSPF::endsWithIgnoreCase(i.getPath(), ".zip"))
{
FilesystemNodeZIP zipNode(i.getPath());
i.setName(zipNode.getName());
}
}
#endif
std::sort(fslist.begin(), fslist.end(),
[](const FilesystemNode& node1, const FilesystemNode& node2)
{
if(node1.isDirectory() != node2.isDirectory())
return node1.isDirectory();
else
return BSPF::compareIgnoreCase(node1.getName(), node2.getName()) < 0;
}
);
#if defined(ZIP_SUPPORT)
// After sorting replace zip files with zip nodes
for(auto& i : fslist)
{
if(BSPF::endsWithIgnoreCase(i.getPath(), ".zip"))
{
// Force ZIP c'tor to be called
AbstractFSNodePtr ptr = FilesystemNodeFactory::create(i.getPath(),
FilesystemNodeFactory::Type::ZIP);
FilesystemNode zipNode(ptr);
i = zipNode;
}
}
#endif
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
const NameFilter& filter,
bool includeChildDirectories,
bool includeParentDirectory) const
{
if (!_realNode || !_realNode->isDirectory())
@ -90,12 +143,15 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
if (!_realNode->getChildren(tmp, mode))
return false;
// when incuding child directories, everything must be sorted once at the end
if(!includeChildDirectories)
{
#if defined(ZIP_SUPPORT)
// before sorting, replace single file ZIP archive names with contained file names
// because they are displayed using their contained file names
for (auto& i : tmp)
for(auto& i : tmp)
{
if (BSPF::endsWithIgnoreCase(i->getPath(), ".zip"))
if(BSPF::endsWithIgnoreCase(i->getPath(), ".zip"))
{
FilesystemNodeZIP node(i->getPath());
@ -104,15 +160,16 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
}
#endif
std::sort(tmp.begin(), tmp.end(),
[](const AbstractFSNodePtr& node1, const AbstractFSNodePtr& node2)
std::sort(tmp.begin(), tmp.end(),
[](const AbstractFSNodePtr& node1, const AbstractFSNodePtr& node2)
{
if (node1->isDirectory() != node2->isDirectory())
if(node1->isDirectory() != node2->isDirectory())
return node1->isDirectory();
else
return BSPF::compareIgnoreCase(node1->getName(), node2->getName()) < 0;
}
);
);
}
// Add parent node, if it is valid to do so
if (includeParentDirectory && hasParent())
@ -130,21 +187,44 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
{
// Force ZIP c'tor to be called
AbstractFSNodePtr ptr = FilesystemNodeFactory::create(i->getPath(),
FilesystemNodeFactory::Type::ZIP);
FilesystemNode node(ptr);
if (filter(node))
fslist.emplace_back(node);
FilesystemNodeFactory::Type::ZIP);
FilesystemNode zipNode(ptr);
if(filter(zipNode))
{
if(!includeChildDirectories)
fslist.emplace_back(zipNode);
else
{
// filter by zip node but add file node
FilesystemNode node(i);
fslist.emplace_back(node);
}
}
}
else
#endif
{
// Make directories stand out
if (i->isDirectory())
if(i->isDirectory())
i->setName(" [" + i->getName() + "]");
FilesystemNode node(i);
if (filter(node))
fslist.emplace_back(node);
if(includeChildDirectories)
{
if(i->isDirectory())
node.getChildren(fslist, mode, filter, includeChildDirectories, false);
else
// do not add directories in this mode
if(filter(node))
fslist.emplace_back(node);
}
else
{
if(filter(node))
fslist.emplace_back(node);
}
}
}

View File

@ -114,6 +114,17 @@ class FilesystemNode
*/
bool exists() const;
/**
* Return a list of child nodes of this and all sub-directories. If called on a node
* that does not represent a directory, false is returned.
*
* @return true if successful, false otherwise (e.g. when the directory
* does not exist).
*/
bool getAllChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly,
const NameFilter& filter = [](const FilesystemNode&) { return true; },
bool includeParentDirectory = true) const;
/**
* Return a list of child nodes of this directory node. If called on a node
* that does not represent a directory, false is returned.
@ -123,6 +134,7 @@ class FilesystemNode
*/
bool getChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly,
const NameFilter& filter = [](const FilesystemNode&){ return true; },
bool includeChildDirectories = false,
bool includeParentDirectory = true) const;
/**
@ -273,8 +285,8 @@ class FilesystemNode
string getPathWithExt(const string& ext) const;
private:
AbstractFSNodePtr _realNode;
explicit FilesystemNode(const AbstractFSNodePtr& realNode);
AbstractFSNodePtr _realNode;
void setPath(const string& path);
};

View File

@ -45,6 +45,8 @@ class ContextMenu : public Dialog, public CommandSender
const VariantList& items, int cmd = 0, int width = 0);
~ContextMenu() override = default;
bool isShading() const override { return false; }
/** Set the parent widget's ID */
void setID(uInt32 id) { _id = id; }

View File

@ -255,12 +255,11 @@ void Dialog::render()
});
}
// Dialog is still on top if e.g a dialog without title is opened
// (e.g. ContextMenu)
// A dialog is still on top if a non-shading dialog (e.g. ContextMenu)
// is opended above it.
bool onTop = parent().myDialogStack.top() == this
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
&& !parent().myDialogStack.top()->hasTitle());
//&& typeid(*parent().myDialogStack.top()) == typeid(ContextMenu))
&& !parent().myDialogStack.top()->isShading());
if(!onTop)
{

View File

@ -94,6 +94,8 @@ class Dialog : public GuiObject
void setTitle(const string& title);
bool hasTitle() { return !_title.empty(); }
virtual bool isShading() const { return true; }
/**
Determine the maximum width/height of a dialog based on the minimum
allowable bounds, also taking into account the current window size.

View File

@ -171,7 +171,7 @@ void DialogContainer::removeDialog()
{
if(!myDialogStack.empty())
{
cerr << "remove dialog " << typeid(*myDialogStack.top()).name() << endl;
//cerr << "remove dialog " << typeid(*myDialogStack.top()).name() << endl;
myDialogStack.pop();
// Inform the frame buffer that it has to render all surfaces

View File

@ -20,6 +20,7 @@
#include "ScrollBarWidget.hxx"
#include "FileListWidget.hxx"
#include "TimerManager.hxx"
#include "ProgressDialog.hxx"
#include "bspf.hxx"
@ -72,22 +73,37 @@ void FileListWidget::setDirectory(const FilesystemNode& node,
void FileListWidget::setLocation(const FilesystemNode& node,
const string& select)
{
progress().resetProgress();
progress().open();
_node = node;
// Read in the data from the file system (start with an empty list)
_fileList.clear();
_fileList.reserve(512);
_node.getChildren(_fileList, _fsmode, _filter);
if(_includeSubDirs)
{
// Actually this could become HUGE
_fileList.reserve(0x2000);
_node.getAllChildren(_fileList, _fsmode, _filter);
}
else
{
_fileList.reserve(0x200);
_node.getChildren(_fileList, _fsmode, _filter);
}
// Now fill the list widget with the names from the file list
StringList l;
for(const auto& file: _fileList)
for(const auto& file : _fileList)
l.push_back(file.getName());
setList(l);
setSelected(select);
ListWidget::recalc();
progress().close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -114,6 +130,21 @@ void FileListWidget::reload()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProgressDialog& FileListWidget::progress()
{
if(myProgressDialog == nullptr)
myProgressDialog = make_unique<ProgressDialog>(this, _font, "", false);
return *myProgressDialog;
}
void FileListWidget::incProgress()
{
if(_includeSubDirs)
progress().incProgress();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FileListWidget::handleText(char text)
{
@ -202,3 +233,5 @@ void FileListWidget::handleCommand(CommandSender* sender, int cmd, int data, int
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt64 FileListWidget::_QUICK_SELECT_DELAY = 300;
unique_ptr<ProgressDialog> FileListWidget::myProgressDialog{nullptr};

View File

@ -19,6 +19,7 @@
#define FILE_LIST_WIDGET_HXX
class CommandSender;
class ProgressDialog;
#include "FSNode.hxx"
#include "Stack.hxx"
@ -59,12 +60,16 @@ class FileListWidget : public StringListWidget
_filter = filter;
}
// When enabled, all subdirectories will be searched too.
void setIncludeSubDirs(bool enable) { _includeSubDirs = enable; }
/**
Set initial directory, and optionally select the given item.
@param node The directory to display. If this is a file, its parent
will instead be used, and the file will be selected
@param select An optional entry to select (if applicable)
@param node The directory to display. If this is a file, its parent
will instead be used, and the file will be selected
@param select An optional entry to select (if applicable)
@param recursive Recursively list sub-directories too
*/
void setDirectory(const FilesystemNode& node,
const string& select = EmptyString);
@ -84,6 +89,12 @@ class FileListWidget : public StringListWidget
static void setQuickSelectDelay(uInt64 time) { _QUICK_SELECT_DELAY = time; }
ProgressDialog& progress();
void incProgress();
protected:
static unique_ptr<ProgressDialog> myProgressDialog;
private:
/** Very similar to setDirectory(), but also updates the history */
void setLocation(const FilesystemNode& node, const string& select);
@ -99,6 +110,7 @@ class FileListWidget : public StringListWidget
FilesystemNode::NameFilter _filter;
FilesystemNode _node;
FSList _fileList;
bool _includeSubDirs{false};
Common::FixedStack<string> _history;
uInt32 _selected{0};

View File

@ -15,6 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
// TODO:
// - abort current file list reload when typing
#include "bspf.hxx"
#include "Bankswitch.hxx"
#include "BrowserDialog.hxx"
@ -29,6 +32,7 @@
#include "GlobalPropsDialog.hxx"
#include "StellaSettingsDialog.hxx"
#include "WhatsNewDialog.hxx"
#include "ProgressDialog.hxx"
#include "MessageBox.hxx"
#include "ToolTip.hxx"
#include "OSystem.hxx"
@ -73,25 +77,71 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: lineHeight * 1.25,
buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1));
int xpos = HBORDER, ypos = VBORDER, lwidth = 0, lwidth2 = 0;
int xpos = HBORDER, ypos = VBORDER;
WidgetArray wid;
string lblRom = "Select a ROM from the list" + ELLIPSIS;
string lblSelect = "Select a ROM from the list" + ELLIPSIS;
string lblAllFiles = "Show all files";
const string& lblFilter = "Filter";
const string& lblAllFiles = "Show all files";
const string& lblFound = "XXXX items found";
string lblSubDirs = "Incl. subdirectories";
string lblFound = "12345 items found";
tooltip().setFont(font);
lwidth = font.getStringWidth(lblRom);
lwidth2 = font.getStringWidth(lblAllFiles) + CheckboxWidget::boxSize(font);
int lwidth3 = font.getStringWidth(lblFilter);
int lwidth4 = font.getStringWidth(lblFound);
int lwSelect = font.getStringWidth(lblSelect);
int cwAllFiles = font.getStringWidth(lblAllFiles) + CheckboxWidget::prefixSize(font);
int lwFilter = font.getStringWidth(lblFilter);
int cwSubDirs = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font);
int lwFound = font.getStringWidth(lblFound);
int wTotal = HBORDER * 2 + lwSelect + cwAllFiles + lwFilter + cwSubDirs + lwFound
+ EditTextWidget::calcWidth(font, "123456") + LBL_GAP * 7;
bool noSelect = false;
if(w < HBORDER * 2 + lwidth + lwidth2 + lwidth3 + lwidth4 + fontWidth * 6 + LBL_GAP * 8)
if(w < wTotal)
{
// make sure there is space for at least 6 characters in the filter field
lblRom = "Select a ROM" + ELLIPSIS;
lwidth = font.getStringWidth(lblRom);
lblSelect = "Select a ROM" + ELLIPSIS;
int lwSelectShort = font.getStringWidth(lblSelect);
wTotal -= lwSelect - lwSelectShort;
lwSelect = lwSelectShort;
}
if(w < wTotal)
{
// make sure there is space for at least 6 characters in the filter field
lblSubDirs = "Subdir.";
int cwSubDirsShort = font.getStringWidth(lblSubDirs) + CheckboxWidget::prefixSize(font);
wTotal -= cwSubDirs - cwSubDirsShort;
cwSubDirs = cwSubDirsShort;
}
if(w < wTotal)
{
// 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);
wTotal -= cwAllFiles - cwAllFilesShort;
cwAllFiles = cwAllFilesShort;
}
if(w < wTotal)
{
// make sure there is space for at least 6 characters in the filter field
lblFound = "12345 found";
int lwFoundShort = font.getStringWidth(lblFound);
wTotal -= lwFound - lwFoundShort;
lwFound = lwFoundShort;
myShortCount = true;
}
if(w < wTotal)
{
// make sure there is space for at least 6 characters in the filter field
lblSelect = "";
int lwSelectShort = font.getStringWidth(lblSelect);
wTotal -= lwSelect - lwSelectShort;
lwSelect = lwSelectShort;
noSelect = true;
}
if(myUseMinimalUI)
@ -108,31 +158,51 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
}
// Show the header
new StaticTextWidget(this, font, xpos, ypos, lblRom);
new StaticTextWidget(this, font, xpos, ypos, lblSelect);
// Shop the files counter
xpos = _w - HBORDER - lwidth4;
xpos = _w - HBORDER - lwFound;
myRomCount = new StaticTextWidget(this, font, xpos, ypos,
lwidth4, fontHeight,
lwFound, fontHeight,
"", TextAlign::Right);
// Add filter that can narrow the results shown in the listing
// It has to fit between both labels
if(!myUseMinimalUI && w >= 640)
{
int fwidth = std::min(15 * fontWidth, xpos - lwidth3 - lwidth2 - lwidth - HBORDER - LBL_GAP * 8);
int fwFilter = std::min(EditTextWidget::calcWidth(font, "123456789012345"),
xpos - cwSubDirs - lwFilter - cwAllFiles
- lwSelect - HBORDER - LBL_GAP * (noSelect ? 5 : 7));
// Show the subdirectories checkbox
xpos -= cwSubDirs + LBL_GAP;
mySubDirs = new CheckboxWidget(this, font, xpos, ypos, lblSubDirs, kSubDirsCmd);
mySubDirs->setEnabled(false);
ostringstream tip;
tip << "Search files in subdirectories too.\n"
<< "Filter must have at least " << MIN_SUBDIRS_CHARS << " chars.";
mySubDirs->setToolTip(tip.str());
// Show the filter input field
xpos -= fwidth + LBL_GAP;
myPattern = new EditTextWidget(this, font, xpos, ypos - 2, fwidth, lineHeight, "");
myPattern->setToolTip("Enter filter text to reduce file list.");
xpos -= fwFilter + LBL_GAP;
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 -= lwidth3 + LBL_GAP;
xpos -= lwFilter + LBL_GAP;
new StaticTextWidget(this, font, xpos, ypos, lblFilter);
// Show the checkbox for all files
xpos -= lwidth2 + LBL_GAP * 3;
if(noSelect)
xpos = HBORDER;
else
xpos -= cwAllFiles + LBL_GAP * 2;
myAllFiles = new CheckboxWidget(this, font, xpos, ypos, lblAllFiles, kAllfilesCmd);
myAllFiles->setToolTip("Uncheck to show ROM files only.");
wid.push_back(myAllFiles);
wid.push_back(myPattern);
wid.push_back(mySubDirs);
}
// Add list with game titles
@ -167,11 +237,11 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
// Add textfield to show current directory
xpos = HBORDER;
ypos += myList->getHeight() + VGAP * 2;
lwidth = font.getStringWidth("Path") + LBL_GAP;
myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwidth, fontHeight,
ypos += myList->getHeight() + VGAP;
lwSelect = font.getStringWidth("Path") + LBL_GAP;
myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwSelect, fontHeight,
"Path", TextAlign::Left);
xpos += lwidth;
xpos += lwSelect;
myDir = new EditTextWidget(this, font, xpos, ypos, _w - xpos - HBORDER, lineHeight, "");
myDir->setEditable(false, true);
myDir->clearFlags(Widget::FLAG_RETAIN_FOCUS);
@ -236,9 +306,13 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent,
myGlobalProps = make_unique<GlobalPropsDialog>(this,
myUseMinimalUI ? osystem.frameBuffer().launcherFont() : osystem.frameBuffer().font());
// since we cannot know how many files there are, use are really high value here
myList->progress().setRange(0, 50000, 5);
myList->progress().setMessage(" Filtering files" + ELLIPSIS + " ");
// Do we show only ROMs or all files?
bool onlyROMs = instance().settings().getBool("launcherroms");
showOnlyROMs(onlyROMs);
if(myAllFiles)
myAllFiles->setState(!onlyROMs);
}
@ -341,7 +415,7 @@ void LauncherDialog::updateUI()
// Indicate how many files were found
ostringstream buf;
buf << (myList->getList().size() - 1) << " items found";
buf << (myList->getList().size() - 1) << (myShortCount ? " found" : " items found");
myRomCount->setLabel(buf.str());
// Update ROM info UI item
@ -422,6 +496,7 @@ void LauncherDialog::applyFiltering()
{
myList->setNameFilter(
[&](const FilesystemNode& node) {
myList->incProgress();
if(!node.isDirectory())
{
// Do we want to show only ROMs or all files?
@ -664,6 +739,11 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
reload();
break;
case kSubDirsCmd:
myList->setIncludeSubDirs(mySubDirs->getState());
reload();
break;
case kLoadROMCmd:
case FileListWidget::ItemActivated:
saveConfig();
@ -689,9 +769,15 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
break;
case EditableWidget::kChangedCmd:
{
bool subAllowed = myPattern->getText().length() >= MIN_SUBDIRS_CHARS;
mySubDirs->setEnabled(subAllowed);
myList->setIncludeSubDirs(mySubDirs->getState() && subAllowed);
applyFiltering(); // pattern matching taken care of directly in this method
reload();
break;
}
case kQuitCmd:
saveConfig();

View File

@ -100,6 +100,7 @@ class LauncherDialog : public Dialog
static constexpr int MIN_ROMINFO_CHARS = 30;
static constexpr int MIN_ROMINFO_ROWS = 7; // full lines
static constexpr int MIN_ROMINFO_LINES = 4; // extra lines
static constexpr int MIN_SUBDIRS_CHARS = 3; // minimum filter chars for subdirectory search
void setPosition() override { positionAt(0); }
void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override;
@ -169,19 +170,22 @@ class LauncherDialog : public Dialog
// automatically sized font for ROM info viewer
unique_ptr<GUI::Font> myROMInfoFont;
ButtonWidget* myStartButton{nullptr};
ButtonWidget* myPrevDirButton{nullptr};
ButtonWidget* myOptionsButton{nullptr};
ButtonWidget* myQuitButton{nullptr};
CheckboxWidget* myAllFiles{nullptr};
EditTextWidget* myPattern{nullptr};
CheckboxWidget* mySubDirs{nullptr};
StaticTextWidget* myRomCount{nullptr};
FileListWidget* myList{nullptr};
StaticTextWidget* myDirLabel{nullptr};
EditTextWidget* myDir{nullptr};
StaticTextWidget* myRomCount{nullptr};
EditTextWidget* myPattern{nullptr};
CheckboxWidget* myAllFiles{nullptr};
RomInfoWidget* myRomInfoWidget{nullptr};
ButtonWidget* myStartButton{nullptr};
ButtonWidget* myPrevDirButton{nullptr};
ButtonWidget* myOptionsButton{nullptr};
ButtonWidget* myQuitButton{nullptr};
RomInfoWidget* myRomInfoWidget{nullptr};
std::unordered_map<string,string> myMD5List;
int mySelectedItem{0};
@ -189,9 +193,11 @@ class LauncherDialog : public Dialog
bool myShowOnlyROMs{false};
bool myUseMinimalUI{false};
bool myEventHandled{false};
bool myShortCount{false};
enum {
kAllfilesCmd = 'lalf', // show all files (or ROMs only)
kSubDirsCmd = 'lred',
kPrevDirCmd = 'PRVD',
kOptionsCmd = 'OPTI',
kQuitCmd = 'QUIT'

View File

@ -26,8 +26,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font,
const string& message)
: Dialog(boss->instance(), boss->parent())
const string& message, bool openDialog)
: Dialog(boss->instance(), boss->parent()),
myFont(font)
{
const int fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(),
@ -52,13 +53,23 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font,
mySlider->setMinValue(1);
mySlider->setMaxValue(100);
open();
if(openDialog)
open();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ProgressDialog::setMessage(const string& message)
{
const int fontWidth = myFont.getMaxCharWidth(),
HBORDER = fontWidth * 1.25;
const int lwidth = myFont.getStringWidth(message);
// Recalculate real dimensions
_w = HBORDER * 2 + lwidth;
myMessage->setWidth(lwidth);
myMessage->setLabel(message);
mySlider->setWidth(lwidth);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -68,17 +79,25 @@ void ProgressDialog::setRange(int start, int finish, int step)
myFinish = finish;
myStep = int((step / 100.0) * (myFinish - myStart + 1));
mySlider->setMinValue(myStart);
mySlider->setMinValue(myStart + myStep);
mySlider->setMaxValue(myFinish);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ProgressDialog::resetProgress()
{
myProgress = myStepProgress = 0;
mySlider->setValue(0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ProgressDialog::setProgress(int progress)
{
// Only increase the progress bar if we have arrived at a new step
if(progress - mySlider->getValue() > myStep)
if(progress - myStepProgress >= myStep)
{
mySlider->setValue(progress);
myStepProgress = progress;
mySlider->setValue(progress % (myFinish - myStart + 1));
// Since this dialog is usually called in a tight loop that doesn't
// yield, we need to manually tell the framebuffer that a redraw is
@ -88,3 +107,9 @@ void ProgressDialog::setProgress(int progress)
instance().frameBuffer().update();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ProgressDialog::incProgress()
{
setProgress(++myProgress);
}

View File

@ -23,23 +23,29 @@ class StaticTextWidget;
class SliderWidget;
#include "bspf.hxx"
#include "Dialog.hxx"
class ProgressDialog : public Dialog
{
public:
ProgressDialog(GuiObject* boss, const GUI::Font& font,
const string& message);
const string& message, bool openDialog = true);
~ProgressDialog() override = default;
void setMessage(const string& message);
void setRange(int begin, int end, int step);
void resetProgress();
void setProgress(int progress);
void incProgress();
private:
const GUI::Font& myFont;
StaticTextWidget* myMessage{nullptr};
SliderWidget* mySlider{nullptr};
int myStart{0}, myFinish{0}, myStep{0};
int myProgress{0};
int myStepProgress{0};
private:
// Following constructors and assignment operators not supported

View File

@ -179,5 +179,5 @@ void ToolTip::show(const string& tip)
void ToolTip::render()
{
if(myTipShown)
mySurface->render(), cerr << " render tooltip" << endl;
mySurface->render(); // , cerr << " render tooltip" << endl;
}