new file picker, part 1
prototype
This commit is contained in:
parent
134cdde1e5
commit
6aca12184f
5 changed files with 208 additions and 3 deletions
|
|
@ -894,6 +894,7 @@ src/gui/image.cpp
|
|||
|
||||
src/gui/debug.cpp
|
||||
src/gui/fileDialog.cpp
|
||||
src/gui/newFilePicker.cpp
|
||||
|
||||
src/gui/intConst.cpp
|
||||
src/gui/guiConst.cpp
|
||||
|
|
|
|||
|
|
@ -4987,6 +4987,8 @@ bool FurnaceGUI::loop() {
|
|||
MEASURE(log,drawLog());
|
||||
MEASURE(effectList,drawEffectList());
|
||||
MEASURE(userPresets,drawUserPresets());
|
||||
|
||||
newFilePicker->draw();
|
||||
}
|
||||
|
||||
// release selection if mouse released
|
||||
|
|
@ -7867,6 +7869,9 @@ bool FurnaceGUI::init() {
|
|||
|
||||
userEvents=SDL_RegisterEvents(1);
|
||||
|
||||
newFilePicker=new FurnaceFilePicker;
|
||||
newFilePicker->open("New File Picker","/home",false);
|
||||
|
||||
e->setMidiCallback([this](const TAMidiMessage& msg) -> int {
|
||||
if (introPos<11.0) return -3;
|
||||
midiLock.lock();
|
||||
|
|
@ -8511,6 +8516,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
postWarnAction(GUI_WARN_GENERIC),
|
||||
mobScene(GUI_SCENE_PATTERN),
|
||||
fileDialog(NULL),
|
||||
newFilePicker(NULL),
|
||||
scrW(GUI_WIDTH_DEFAULT),
|
||||
scrH(GUI_HEIGHT_DEFAULT),
|
||||
scrConfW(GUI_WIDTH_DEFAULT),
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "../pch.h"
|
||||
|
||||
#include "fileDialog.h"
|
||||
#include "newFilePicker.h"
|
||||
|
||||
#define FURNACE_APP_ID "org.tildearrow.furnace"
|
||||
|
||||
|
|
@ -1765,6 +1766,7 @@ class FurnaceGUI {
|
|||
FurnaceGUIMobileScenes mobScene;
|
||||
|
||||
FurnaceGUIFileDialog* fileDialog;
|
||||
FurnaceFilePicker* newFilePicker;
|
||||
|
||||
int scrW, scrH, scrConfW, scrConfH, canvasW, canvasH;
|
||||
int scrX, scrY, scrConfX, scrConfY;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,183 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// this is the code to a new file picker using Dear ImGui.
|
||||
// this will eventually replace ImGuiFileDialog as the built-in file picker.
|
||||
// this is the code to a new file picker using Dear ImGui.
|
||||
// this will eventually replace ImGuiFileDialog as the built-in file picker.
|
||||
|
||||
|
||||
#include "newFilePicker.h"
|
||||
#include "imgui.h"
|
||||
#include <IconsFontAwesome4.h>
|
||||
#include <dirent.h>
|
||||
|
||||
static void _fileThread(void* item) {
|
||||
((FurnaceFilePicker*)item)->readDirectorySub();
|
||||
}
|
||||
|
||||
void FurnaceFilePicker::readDirectorySub() {
|
||||
/// STAGE 1: get file list
|
||||
DIR* dir=opendir(path.c_str());
|
||||
|
||||
if (dir==NULL) {
|
||||
failMessage=strerror(errno);
|
||||
haveFiles=true;
|
||||
haveStat=true;
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent* entry=NULL;
|
||||
while (true) {
|
||||
entry=readdir(dir);
|
||||
if (entry==NULL) break;
|
||||
if (strcmp(entry->d_name,".")==0) continue;
|
||||
if (strcmp(entry->d_name,"..")==0) continue;
|
||||
|
||||
FileEntry* newEntry=new FileEntry;
|
||||
newEntry->name=entry->d_name;
|
||||
switch (entry->d_type) {
|
||||
case DT_REG:
|
||||
newEntry->type=FP_TYPE_NORMAL;
|
||||
break;
|
||||
case DT_DIR:
|
||||
newEntry->type=FP_TYPE_DIR;
|
||||
break;
|
||||
case DT_LNK:
|
||||
newEntry->type=FP_TYPE_LINK;
|
||||
break;
|
||||
case DT_SOCK:
|
||||
newEntry->type=FP_TYPE_SOCKET;
|
||||
break;
|
||||
default:
|
||||
newEntry->type=FP_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
entries.push_back(newEntry);
|
||||
}
|
||||
if (closedir(dir)!=0) {
|
||||
// ?!
|
||||
}
|
||||
|
||||
// we're done - this is sufficient to show a file list (and sort by name)
|
||||
haveFiles=true;
|
||||
|
||||
/// STAGE 2: retrieve file information
|
||||
|
||||
haveStat=true;
|
||||
}
|
||||
|
||||
void FurnaceFilePicker::readDirectory(String path) {
|
||||
if (fileThread!=NULL) {
|
||||
// stop current file thread
|
||||
stopReading=true;
|
||||
fileThread->join();
|
||||
delete fileThread;
|
||||
fileThread=NULL;
|
||||
}
|
||||
|
||||
// clear all entries
|
||||
sortedEntries.clear();
|
||||
for (FileEntry* i: entries) {
|
||||
delete i;
|
||||
}
|
||||
entries.clear();
|
||||
|
||||
// start new file thread
|
||||
this->path=path;
|
||||
failMessage="";
|
||||
haveFiles=false;
|
||||
haveStat=false;
|
||||
stopReading=false;
|
||||
fileThread=new std::thread(_fileThread,this);
|
||||
}
|
||||
|
||||
bool FurnaceFilePicker::draw() {
|
||||
if (!isOpen) return false;
|
||||
|
||||
String newDir;
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(800.0,600.0),ImVec2(8000.0,6000.0));
|
||||
if (ImGui::Begin(windowName.c_str(),NULL,ImGuiWindowFlags_NoSavedSettings)) {
|
||||
if (ImGui::Button(ICON_FA_CHEVRON_UP "##ParentDir")) {
|
||||
size_t pos=path.rfind('/');
|
||||
if (pos!=String::npos && path!="/") {
|
||||
newDir=path.substr(0,pos);
|
||||
if (newDir.empty()) newDir="/";
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (!haveFiles) {
|
||||
ImGui::Text("Loading... (%s)",path.c_str());
|
||||
} else {
|
||||
if (haveStat) {
|
||||
ImGui::Text("Hiya! (%s)",path.c_str());
|
||||
} else {
|
||||
ImGui::Text("Loading... (%s)",path.c_str());
|
||||
}
|
||||
|
||||
if (entries.empty()) {
|
||||
if (failMessage.empty()) {
|
||||
ImGui::Text("This directory is empty!");
|
||||
} else {
|
||||
ImGui::Text("Could not load this directory!\n(%s)",failMessage.c_str());
|
||||
}
|
||||
} else {
|
||||
if (ImGui::BeginTable("FileList",3,ImGuiTableFlags_Borders)) {
|
||||
entryLock.lock();
|
||||
int index=0;
|
||||
for (FileEntry* i: entries) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (i->type==FP_TYPE_DIR) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,0xff00ffff);
|
||||
}
|
||||
ImGui::PushID(index++);
|
||||
if (ImGui::Selectable("##File",false)) {
|
||||
if (i->type==FP_TYPE_DIR || i->type==FP_TYPE_LINK) {
|
||||
if (*path.rbegin()=='/') {
|
||||
newDir=path+i->name;
|
||||
} else {
|
||||
newDir=path+'/'+i->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(i->name.c_str());
|
||||
|
||||
if (i->type==FP_TYPE_DIR) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
entryLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!newDir.empty()) {
|
||||
// change directory
|
||||
readDirectory(newDir);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FurnaceFilePicker::open(String name, String path, bool modal) {
|
||||
if (isOpen) return false;
|
||||
|
||||
readDirectory(path);
|
||||
windowName=name;
|
||||
isOpen=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
FurnaceFilePicker::FurnaceFilePicker():
|
||||
fileThread(NULL),
|
||||
haveFiles(false),
|
||||
haveStat(false),
|
||||
stopReading(false),
|
||||
isOpen(false) {
|
||||
|
||||
}
|
||||
|
|
@ -18,20 +18,40 @@
|
|||
*/
|
||||
|
||||
#include "../ta-utils.h"
|
||||
#include <thread>
|
||||
|
||||
class FurnaceFilePicker {
|
||||
enum FileType {
|
||||
FP_TYPE_UNKNOWN=0,
|
||||
FP_TYPE_NORMAL,
|
||||
FP_TYPE_DIR,
|
||||
FP_TYPE_LINK,
|
||||
FP_TYPE_PIPE,
|
||||
FP_TYPE_SOCKET,
|
||||
};
|
||||
struct FileEntry {
|
||||
String path;
|
||||
String name;
|
||||
String ext;
|
||||
uint64_t size;
|
||||
struct tm time;
|
||||
FileType type;
|
||||
};
|
||||
std::vector<FileEntry*> entries;
|
||||
std::vector<FileEntry*> sortedEntries;
|
||||
std::thread* fileThread;
|
||||
std::mutex entryLock;
|
||||
String windowName;
|
||||
String path;
|
||||
String failMessage;
|
||||
bool haveFiles, haveStat, stopReading, isOpen;
|
||||
|
||||
void clearAllFiles();
|
||||
void readDirectory(String path);
|
||||
|
||||
public:
|
||||
void readDirectorySub();
|
||||
bool draw();
|
||||
bool open(String name, String path, bool modal);
|
||||
FurnaceFilePicker();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue