mirror of https://github.com/stella-emu/stella.git
202 lines
5.5 KiB
C++
202 lines
5.5 KiB
C++
//============================================================================
|
|
//
|
|
// SSSS tt lll lll
|
|
// SS SS tt ll ll
|
|
// SS tttttt eeee ll ll aaaa
|
|
// SSSS tt ee ee ll ll aa
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
// SS SS tt ee ll ll aa aa
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
//
|
|
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
|
// and the Stella Team
|
|
//
|
|
// See the file "License.txt" for information on usage and redistribution of
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
//============================================================================
|
|
|
|
#include <cctype>
|
|
|
|
#include "ScrollBarWidget.hxx"
|
|
#include "FileListWidget.hxx"
|
|
#include "TimerManager.hxx"
|
|
|
|
#include "bspf.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
FileListWidget::FileListWidget(GuiObject* boss, const GUI::Font& font,
|
|
int x, int y, int w, int h)
|
|
: StringListWidget(boss, font, x, y, w, h),
|
|
_filter([](const FilesystemNode& node) { return true; })
|
|
{
|
|
// This widget is special, in that it catches signals and redirects them
|
|
setTarget(this);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::setDirectory(const FilesystemNode& node,
|
|
const string& select)
|
|
{
|
|
_node = node;
|
|
|
|
// We always want a directory listing
|
|
if(!_node.isDirectory() && _node.hasParent())
|
|
{
|
|
_selectedFile = _node.getName();
|
|
_node = _node.getParent();
|
|
}
|
|
else
|
|
_selectedFile = select;
|
|
|
|
// Initialize history
|
|
FilesystemNode tmp = _node;
|
|
while(tmp.hasParent())
|
|
{
|
|
string name = tmp.getName();
|
|
if(name.back() == '/' || name.back() == '\\')
|
|
name.pop_back();
|
|
if(!BSPF::startsWithIgnoreCase(name, " ["))
|
|
name = " [" + name.append("]");
|
|
|
|
_history.push(name);
|
|
tmp = tmp.getParent();
|
|
}
|
|
// History is in reverse order; we need to fix that
|
|
_history.reverse();
|
|
|
|
// Finally, go to this location
|
|
setLocation(_node, _selectedFile);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::setLocation(const FilesystemNode& node,
|
|
const string& select)
|
|
{
|
|
_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);
|
|
|
|
// Now fill the list widget with the names from the file list
|
|
StringList l;
|
|
for(const auto& file: _fileList)
|
|
l.push_back(file.getName());
|
|
|
|
setList(l);
|
|
setSelected(select);
|
|
|
|
ListWidget::recalc();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::selectDirectory()
|
|
{
|
|
_history.push(selected().getName());
|
|
setLocation(selected(), _selectedFile);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::selectParent()
|
|
{
|
|
if(_node.hasParent())
|
|
setLocation(_node.getParent(), !_history.empty() ? _history.pop() : EmptyString);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::reload()
|
|
{
|
|
if(_node.exists())
|
|
{
|
|
_selectedFile = selected().getName();
|
|
setLocation(_node, _selectedFile);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool FileListWidget::handleText(char text)
|
|
{
|
|
// Quick selection mode: Go to first list item starting with this key
|
|
// (or a substring accumulated from the last couple key presses).
|
|
// Only works in a useful fashion if the list entries are sorted.
|
|
uInt64 time = TimerManager::getTicks() / 1000;
|
|
if(_quickSelectTime < time)
|
|
{
|
|
if(std::isupper(text))
|
|
{
|
|
// Select directories when the first character is uppercase
|
|
_quickSelectStr = " [";
|
|
_quickSelectStr.push_back(text);
|
|
}
|
|
else
|
|
_quickSelectStr = text;
|
|
}
|
|
else
|
|
_quickSelectStr += text;
|
|
_quickSelectTime = time + _QUICK_SELECT_DELAY;
|
|
|
|
int selectedItem = 0;
|
|
for(const auto& i: _list)
|
|
{
|
|
if(BSPF::startsWithIgnoreCase(i, _quickSelectStr))
|
|
break;
|
|
selectedItem++;
|
|
}
|
|
|
|
if(selectedItem > 0)
|
|
setSelected(selectedItem);
|
|
|
|
return true;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void FileListWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case ListWidget::kPrevDirCmd:
|
|
selectParent();
|
|
break;
|
|
|
|
case ListWidget::kSelectionChangedCmd:
|
|
_selected = data;
|
|
cmd = ItemChanged;
|
|
break;
|
|
|
|
case ListWidget::kActivatedCmd:
|
|
case ListWidget::kDoubleClickedCmd:
|
|
_selected = data;
|
|
if(selected().isDirectory())
|
|
{
|
|
if(selected().getName() == " [..]")
|
|
selectParent();
|
|
else
|
|
{
|
|
cmd = ItemChanged;
|
|
selectDirectory();
|
|
}
|
|
}
|
|
else
|
|
cmd = ItemActivated;
|
|
break;
|
|
|
|
case ListWidget::kLongButtonPressCmd:
|
|
// do nothing, let boss handle this one
|
|
break;
|
|
|
|
default:
|
|
// If we don't know about the command, send it to the parent and exit
|
|
StringListWidget::handleCommand(sender, cmd, data, id);
|
|
return;
|
|
}
|
|
|
|
// Send command to boss, then revert to target 'this'
|
|
setTarget(_boss);
|
|
sendCommand(cmd, data, id);
|
|
setTarget(this);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
uInt64 FileListWidget::_QUICK_SELECT_DELAY = 300;
|