mirror of
https://github.com/joel16/NX-Shell.git
synced 2024-11-23 11:49:46 +00:00
options: Reimplement options popup in filebrowser tab
This commit is contained in:
parent
ee4fbc8a31
commit
c602482f70
@ -12,7 +12,7 @@ extern dk::ImageDescriptor *s_imageDescriptors;
|
|||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
bool Init(void);
|
bool Init(void);
|
||||||
bool Loop(void);
|
bool Loop(u64 &key);
|
||||||
void Render(void);
|
void Render(void);
|
||||||
void Exit(void);
|
void Exit(void);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#ifndef NX_SHELL_POPUPS_H
|
#ifndef NX_SHELL_POPUPS_H
|
||||||
#define NX_SHELL_POPUPS_H
|
#define NX_SHELL_POPUPS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
namespace Popups {
|
namespace Popups {
|
||||||
inline void SetupPopup(const char *id) {
|
inline void SetupPopup(const char *id) {
|
||||||
@ -19,7 +22,7 @@ namespace Popups {
|
|||||||
void DeletePopup(void);
|
void DeletePopup(void);
|
||||||
void FilePropertiesPopup(void);
|
void FilePropertiesPopup(void);
|
||||||
void ImageProperties(bool *state);
|
void ImageProperties(bool *state);
|
||||||
void OptionsPopup(void);
|
void OptionsPopup(WindowData &data);
|
||||||
void ProgressPopup(float offset, float size, const std::string &title, const std::string &text);
|
void ProgressPopup(float offset, float size, const std::string &title, const std::string &text);
|
||||||
void UpdatePopup(bool *state, bool *connection_status, bool *available, const std::string &tag);
|
void UpdatePopup(bool *state, bool *connection_status, bool *available, const std::string &tag);
|
||||||
}
|
}
|
||||||
|
@ -6,28 +6,36 @@
|
|||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
|
enum WINDOW_STATES {
|
||||||
|
WINDOW_STATE_FILEBROWSER,
|
||||||
|
WINDOW_STATE_SETTINGS,
|
||||||
|
WINDOW_STATE_OPTIONS,
|
||||||
|
WINDOW_STATE_DELETE,
|
||||||
|
WINDOW_STATE_PROPERTIES,
|
||||||
|
WINDOW_STATE_IMAGEVIEWER,
|
||||||
|
WINDOW_STATE_ARCHIVEEXTRACT,
|
||||||
|
WINDOW_STATE_TEXTREADER
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::vector<FsDirectoryEntry> entries;
|
|
||||||
std::vector<bool> checked;
|
std::vector<bool> checked;
|
||||||
std::vector<bool> checked_copy;
|
std::vector<bool> checked_copy;
|
||||||
int checked_count = 0;
|
std::string cwd;
|
||||||
|
int count = 0;
|
||||||
|
} WindowCheckboxData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WINDOW_STATES state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
int selected = 0;
|
||||||
|
std::vector<FsDirectoryEntry> entries;
|
||||||
|
WindowCheckboxData checkbox_data;
|
||||||
s64 used_storage = 0;
|
s64 used_storage = 0;
|
||||||
s64 total_storage = 0;
|
s64 total_storage = 0;
|
||||||
} WindowData;
|
} WindowData;
|
||||||
|
|
||||||
namespace Windows {
|
namespace Windows {
|
||||||
inline void SetupWindow(void) {
|
void ResetCheckbox(WindowData &data);
|
||||||
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_Once);
|
void MainWindow(WindowData &data, u64 &key);
|
||||||
ImGui::SetNextWindowSize(ImVec2(1280.0f, 720.0f), ImGuiCond_Once);
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void ExitWindow(void) {
|
|
||||||
ImGui::End();
|
|
||||||
ImGui::PopStyleVar();
|
|
||||||
};
|
|
||||||
|
|
||||||
void MainWindow(WindowData &data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
285
source/fs.cpp
285
source/fs.cpp
@ -12,6 +12,16 @@ FsFileSystem *fs;
|
|||||||
FsFileSystem devices[4];
|
FsFileSystem devices[4];
|
||||||
|
|
||||||
namespace FS {
|
namespace FS {
|
||||||
|
static int PREVIOUS_BROWSE_STATE = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char copy_path[FS_MAX_PATH];
|
||||||
|
char copy_filename[FS_MAX_PATH];
|
||||||
|
bool is_dir = false;
|
||||||
|
} FS_Copy_Struct;
|
||||||
|
|
||||||
|
FS_Copy_Struct fs_copy_struct;
|
||||||
|
|
||||||
bool FileExists(const char path[FS_MAX_PATH]) {
|
bool FileExists(const char path[FS_MAX_PATH]) {
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (R_SUCCEEDED(fsFsOpenFile(fs, path, FsOpenMode_Read, &file))) {
|
if (R_SUCCEEDED(fsFsOpenFile(fs, path, FsOpenMode_Read, &file))) {
|
||||||
@ -31,6 +41,25 @@ namespace FS {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GetFileSize(const char path[FS_MAX_PATH], s64 *size) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
FsFile file;
|
||||||
|
if (R_FAILED(ret = fsFsOpenFile(fs, path, FsOpenMode_Read, &file))) {
|
||||||
|
Log::Error("fsFsOpenFile(%s) failed: 0x%x\n", path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFileGetSize(&file, size))) {
|
||||||
|
Log::Error("fsFileGetSize(%s) failed: 0x%x\n", path, ret);
|
||||||
|
fsFileClose(&file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsFileClose(&file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetFileExt(const std::string &filename) {
|
std::string GetFileExt(const std::string &filename) {
|
||||||
std::string ext = std::filesystem::path(filename).extension();
|
std::string ext = std::filesystem::path(filename).extension();
|
||||||
@ -178,6 +207,262 @@ namespace FS {
|
|||||||
|
|
||||||
return FS::ChangeDir(new_cwd, entries);
|
return FS::ChangeDir(new_cwd, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ConstructPath(FsDirectoryEntry *entry, char path[FS_MAX_PATH + 1], const char filename[FS_MAX_PATH]) {
|
||||||
|
if (entry) {
|
||||||
|
if ((std::snprintf(path, FS_MAX_PATH, "%s%s%s", cfg.cwd, !std::strncmp(cfg.cwd, "/", 2) ? "" : "/", entry? entry->name : "")) > 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((std::snprintf(path, FS_MAX_PATH, "%s%s%s", cfg.cwd, !std::strncmp(cfg.cwd, "/", 2) ? "" : "/", filename[0] != '\0'? filename : "")) > 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetTimeStamp(FsDirectoryEntry *entry, FsTimeStampRaw *timestamp) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
if (FS::ConstructPath(entry, path, "") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFsGetFileTimeStampRaw(fs, path, timestamp))) {
|
||||||
|
Log::Error("fsFsGetFileTimeStampRaw(%s) failed: 0x%x\n", path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Rename(FsDirectoryEntry *entry, const char filename[FS_MAX_PATH]) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
if (FS::ConstructPath(entry, path, "") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char new_path[FS_MAX_PATH];
|
||||||
|
if (FS::ConstructPath(nullptr, new_path, filename) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (entry->type == FsDirEntryType_Dir) {
|
||||||
|
if (R_FAILED(ret = fsFsRenameDirectory(fs, path, new_path))) {
|
||||||
|
Log::Error("fsFsRenameDirectory(%s, %s) failed: 0x%x\n", path, new_path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (R_FAILED(ret = fsFsRenameFile(fs, path, new_path))) {
|
||||||
|
Log::Error("fsFsRenameFile(%s, %s) failed: 0x%x\n", path, new_path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Delete(FsDirectoryEntry *entry) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
if (FS::ConstructPath(entry, path, "") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (entry->type == FsDirEntryType_Dir) {
|
||||||
|
if (R_FAILED(ret = fsFsDeleteDirectoryRecursively(fs, path))) {
|
||||||
|
Log::Error("fsFsDeleteDirectoryRecursively(%s) failed: 0x%x\n", path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (R_FAILED(ret = fsFsDeleteFile(fs, path))) {
|
||||||
|
Log::Error("fsFsDeleteFile(%s) failed: 0x%x\n", path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetArchiveBit(FsDirectoryEntry *entry) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
if (FS::ConstructPath(entry, path, "") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFsSetConcatenationFileAttribute(fs, path))) {
|
||||||
|
Log::Error("fsFsSetConcatenationFileAttribute(%s) failed: 0x%x\n", path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result CopyFile(const char src_path[FS_MAX_PATH], const char dest_path[FS_MAX_PATH]) {
|
||||||
|
Result ret = 0;
|
||||||
|
FsFile src_handle, dest_handle;
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFsOpenFile(&devices[PREVIOUS_BROWSE_STATE], src_path, FsOpenMode_Read, &src_handle))) {
|
||||||
|
Log::Error("fsFsOpenFile(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 size = 0;
|
||||||
|
if (R_FAILED(ret = fsFileGetSize(&src_handle, &size))) {
|
||||||
|
Log::Error("fsFileGetSize(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
fsFileClose(&src_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This may fail or not, but we don't care -> create the file if it doesn't exist, otherwise continue.
|
||||||
|
fsFsCreateFile(fs, dest_path, size, 0);
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFsOpenFile(fs, dest_path, FsOpenMode_Write, &dest_handle))) {
|
||||||
|
Log::Error("fsFsOpenFile(%s) failed: 0x%x\n", dest_path, ret);
|
||||||
|
fsFileClose(&src_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 bytes_read = 0;
|
||||||
|
const u64 buf_size = 0x10000;
|
||||||
|
s64 offset = 0;
|
||||||
|
unsigned char *buf = new unsigned char[buf_size];
|
||||||
|
std::string filename = std::filesystem::path(src_path).filename();
|
||||||
|
|
||||||
|
do {
|
||||||
|
std::memset(buf, 0, buf_size);
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFileRead(&src_handle, offset, buf, buf_size, FsReadOption_None, &bytes_read))) {
|
||||||
|
Log::Error("fsFileRead(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
delete[] buf;
|
||||||
|
fsFileClose(&src_handle);
|
||||||
|
fsFileClose(&dest_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFileWrite(&dest_handle, offset, buf, bytes_read, FsWriteOption_Flush))) {
|
||||||
|
Log::Error("fsFileWrite(%s) failed: 0x%x\n", dest_path, ret);
|
||||||
|
delete[] buf;
|
||||||
|
fsFileClose(&src_handle);
|
||||||
|
fsFileClose(&dest_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += bytes_read;
|
||||||
|
//Popups::ProgressPopup(static_cast<float>(offset), static_cast<float>(size), strings[cfg.lang][Lang::OptionsCopying], filename.c_str());
|
||||||
|
} while(offset < size);
|
||||||
|
|
||||||
|
delete[] buf;
|
||||||
|
fsFileClose(&src_handle);
|
||||||
|
fsFileClose(&dest_handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result CopyDir(const char src_path[FS_MAX_PATH], const char dest_path[FS_MAX_PATH]) {
|
||||||
|
Result ret = 0;
|
||||||
|
FsDir dir;
|
||||||
|
|
||||||
|
if (R_FAILED(ret = fsFsOpenDirectory(&devices[PREVIOUS_BROWSE_STATE], src_path, FsDirOpenMode_ReadDirs | FsDirOpenMode_ReadFiles, &dir))) {
|
||||||
|
Log::Error("fsFsOpenDirectory(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This may fail or not, but we don't care -> make the dir if it doesn't exist, otherwise continue.
|
||||||
|
fsFsCreateDirectory(fs, dest_path);
|
||||||
|
|
||||||
|
s64 entry_count = 0;
|
||||||
|
if (R_FAILED(ret = fsDirGetEntryCount(&dir, &entry_count))) {
|
||||||
|
Log::Error("fsDirGetEntryCount(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
FsDirectoryEntry *entries = new FsDirectoryEntry[entry_count * sizeof(*entries)];
|
||||||
|
if (R_FAILED(ret = fsDirRead(&dir, nullptr, static_cast<size_t>(entry_count), entries))) {
|
||||||
|
Log::Error("fsDirRead(%s) failed: 0x%x\n", src_path, ret);
|
||||||
|
delete[] entries;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s64 i = 0; i < entry_count; i++) {
|
||||||
|
std::string filename = entries[i].name;
|
||||||
|
if (!filename.empty()) {
|
||||||
|
if ((!filename.compare(".")) || (!filename.compare("..")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string src = src_path;
|
||||||
|
src.append("/");
|
||||||
|
src.append(filename);
|
||||||
|
|
||||||
|
std::string dest = dest_path;
|
||||||
|
dest.append("/");
|
||||||
|
dest.append(filename);
|
||||||
|
|
||||||
|
if (entries[i].type == FsDirEntryType_Dir)
|
||||||
|
FS::CopyDir(src.c_str(), dest.c_str()); // Copy Folder (via recursion)
|
||||||
|
else
|
||||||
|
FS::CopyFile(src.c_str(), dest.c_str()); // Copy File
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] entries;
|
||||||
|
fsDirClose(&dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Copy(FsDirectoryEntry *entry, const std::string &path) {
|
||||||
|
std::string full_path = path;
|
||||||
|
full_path.append("/");
|
||||||
|
full_path.append(entry->name);
|
||||||
|
std::strcpy(fs_copy_struct.copy_path, full_path.c_str());
|
||||||
|
std::strcpy(fs_copy_struct.copy_filename, entry->name);
|
||||||
|
if (entry->type == FsDirEntryType_Dir)
|
||||||
|
fs_copy_struct.is_dir = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Paste(void) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
FS::ConstructPath(nullptr, path, fs_copy_struct.copy_filename);
|
||||||
|
|
||||||
|
if (fs_copy_struct.is_dir) // Copy folder recursively
|
||||||
|
ret = FS::CopyDir(fs_copy_struct.copy_path, path);
|
||||||
|
else // Copy file
|
||||||
|
ret = FS::CopyFile(fs_copy_struct.copy_path, path);
|
||||||
|
|
||||||
|
std::memset(fs_copy_struct.copy_path, 0, FS_MAX_PATH);
|
||||||
|
std::memset(fs_copy_struct.copy_filename, 0, FS_MAX_PATH);
|
||||||
|
fs_copy_struct.is_dir = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Move(void) {
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
FS::ConstructPath(nullptr, path, fs_copy_struct.copy_filename);
|
||||||
|
|
||||||
|
if (fs_copy_struct.is_dir) {
|
||||||
|
if (R_FAILED(ret = fsFsRenameDirectory(fs, fs_copy_struct.copy_path, path))) {
|
||||||
|
Log::Error("fsFsRenameDirectory(%s, %s) failed: 0x%x\n", path, fs_copy_struct.copy_filename, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (R_FAILED(ret = fsFsRenameFile(fs, fs_copy_struct.copy_path, path))) {
|
||||||
|
Log::Error("fsFsRenameFile(%s, %s) failed: 0x%x\n", path, fs_copy_struct.copy_filename, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memset(fs_copy_struct.copy_path, 0, FS_MAX_PATH);
|
||||||
|
std::memset(fs_copy_struct.copy_filename, 0, FS_MAX_PATH);
|
||||||
|
fs_copy_struct.is_dir = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Result GetFreeStorageSpace(s64 &size) {
|
Result GetFreeStorageSpace(s64 &size) {
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
|
@ -153,14 +153,14 @@ namespace GUI {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Loop(void) {
|
bool Loop(u64 &key) {
|
||||||
if (!appletMainLoop())
|
if (!appletMainLoop())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u64 down = imgui::nx::newFrame();
|
key = imgui::nx::newFrame();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
return !(down & HidNpadButton_Plus);
|
return !(key & HidNpadButton_Plus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render(void) {
|
void Render(void) {
|
||||||
|
@ -102,6 +102,8 @@ namespace Services {
|
|||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
Result ret = 0;
|
Result ret = 0;
|
||||||
WindowData data;
|
WindowData data;
|
||||||
|
u64 key = 0;
|
||||||
|
|
||||||
Services::Init();
|
Services::Init();
|
||||||
|
|
||||||
if (R_FAILED(ret = FS::GetDirList(cfg.cwd, data.entries))) {
|
if (R_FAILED(ret = FS::GetDirList(cfg.cwd, data.entries))) {
|
||||||
@ -109,12 +111,12 @@ int main(int argc, char* argv[]) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.checked.resize(data.entries.size());
|
data.checkbox_data.checked.resize(data.entries.size());
|
||||||
FS::GetUsedStorageSpace(data.used_storage);
|
FS::GetUsedStorageSpace(data.used_storage);
|
||||||
FS::GetTotalStorageSpace(data.total_storage);
|
FS::GetTotalStorageSpace(data.total_storage);
|
||||||
|
|
||||||
while (GUI::Loop()) {
|
while (GUI::Loop(key)) {
|
||||||
Windows::MainWindow(data);
|
Windows::MainWindow(data, key);
|
||||||
GUI::Render();
|
GUI::Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
185
source/popups/options.cpp
Normal file
185
source/popups/options.cpp
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_internal.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "language.h"
|
||||||
|
#include "popups.h"
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
namespace Popups {
|
||||||
|
static bool copy = false, move = false;
|
||||||
|
static void HandleMultipleCopy(WindowData &data, Result (*func)()) {
|
||||||
|
Result ret = 0;
|
||||||
|
std::vector<FsDirectoryEntry> entries;
|
||||||
|
|
||||||
|
if (R_FAILED(ret = FS::GetDirList(data.checkbox_data.cwd.data(), entries)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (long unsigned int i = 0; i < data.checkbox_data.checked_copy.size(); i++) {
|
||||||
|
if (data.checkbox_data.checked_copy.at(i)) {
|
||||||
|
FS::Copy(&entries[i], data.checkbox_data.cwd);
|
||||||
|
if (R_FAILED((*func)())) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsPopup(WindowData &data) {
|
||||||
|
Popups::SetupPopup(strings[cfg.lang][Lang::OptionsTitle]);
|
||||||
|
|
||||||
|
if (ImGui::BeginPopupModal(strings[cfg.lang][Lang::OptionsTitle], nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsSelectAll], ImVec2(200, 50))) {
|
||||||
|
if ((!data.checkbox_data.cwd.empty()) && (data.checkbox_data.cwd.compare(cfg.cwd) != 0))
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
|
||||||
|
data.checkbox_data.cwd = cfg.cwd;
|
||||||
|
std::fill(data.checkbox_data.checked.begin(), data.checkbox_data.checked.end(), true);
|
||||||
|
data.checkbox_data.count = data.checkbox_data.checked.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine(0.0f, 15.0f);
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsClearAll], ImVec2(200, 50))) {
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
copy = false;
|
||||||
|
move = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsProperties], ImVec2(200, 50))) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_PROPERTIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine(0.0f, 15.0f);
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsRename], ImVec2(200, 50))) {
|
||||||
|
std::string path = Keyboard::GetText(strings[cfg.lang][Lang::OptionsRenamePrompt], data.entries[data.selected].name);
|
||||||
|
if (R_SUCCEEDED(FS::Rename(&data.entries[data.selected], path.c_str())))
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsNewFolder], ImVec2(200, 50))) {
|
||||||
|
std::string path = cfg.cwd;
|
||||||
|
path.append("/");
|
||||||
|
std::string name = Keyboard::GetText(strings[cfg.lang][Lang::OptionsFolderPrompt], strings[cfg.lang][Lang::OptionsNewFolder]);
|
||||||
|
path.append(name);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsCreateDirectory(fs, path.c_str()))) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine(0.0f, 15.0f);
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsNewFile], ImVec2(200, 50))) {
|
||||||
|
std::string path = cfg.cwd;
|
||||||
|
path.append("/");
|
||||||
|
std::string name = Keyboard::GetText(strings[cfg.lang][Lang::OptionsFilePrompt], strings[cfg.lang][Lang::OptionsNewFile]);
|
||||||
|
path.append(name);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(fsFsCreateFile(fs, path.c_str(), 0, 0))) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::Button(!copy? strings[cfg.lang][Lang::OptionsCopy] : strings[cfg.lang][Lang::OptionsPaste], ImVec2(200, 50))) {
|
||||||
|
if (!copy) {
|
||||||
|
if ((data.checkbox_data.count >= 1) && (data.checkbox_data.cwd.compare(cfg.cwd) != 0))
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
if (data.checkbox_data.count <= 1)
|
||||||
|
FS::Copy(&data.entries[data.selected], cfg.cwd);
|
||||||
|
|
||||||
|
copy = !copy;
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImGui::EndPopup();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
ImGui::Render();
|
||||||
|
|
||||||
|
if ((data.checkbox_data.count > 1) && (data.checkbox_data.cwd.compare(cfg.cwd) != 0))
|
||||||
|
Popups::HandleMultipleCopy(data, &FS::Paste);
|
||||||
|
else {
|
||||||
|
if (R_SUCCEEDED(FS::Paste())) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy = !copy;
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine(0.0f, 15.0f);
|
||||||
|
|
||||||
|
if (ImGui::Button(!move? strings[cfg.lang][Lang::OptionsMove] : strings[cfg.lang][Lang::OptionsPaste], ImVec2(200, 50))) {
|
||||||
|
if (!move) {
|
||||||
|
if ((data.checkbox_data.count >= 1) && (data.checkbox_data.cwd.compare(cfg.cwd) != 0))
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
if (data.checkbox_data.count <= 1)
|
||||||
|
FS::Copy(&data.entries[data.selected], cfg.cwd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((data.checkbox_data.count > 1) && (data.checkbox_data.cwd.compare(cfg.cwd) != 0))
|
||||||
|
Popups::HandleMultipleCopy(data, &FS::Move);
|
||||||
|
else if (R_SUCCEEDED(FS::Move())) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
move = !move;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, 5.0f)); // Spacing
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsDelete], ImVec2(200, 50))) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine(0.0f, 15.0f);
|
||||||
|
|
||||||
|
if (ImGui::Button(strings[cfg.lang][Lang::OptionsSetArchiveBit], ImVec2(200, 50))) {
|
||||||
|
if (R_SUCCEEDED(FS::SetArchiveBit(&data.entries[data.selected]))) {
|
||||||
|
FS::GetDirList(cfg.cwd, data.entries);
|
||||||
|
Windows::ResetCheckbox(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Popups::ExitPopup();
|
||||||
|
}
|
||||||
|
}
|
@ -36,9 +36,9 @@ namespace Tabs {
|
|||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
if (ImGui::ImageButton(imgui::deko3d::makeTextureID(
|
if (ImGui::ImageButton(imgui::deko3d::makeTextureID(
|
||||||
data.checked.at(i)? dkMakeTextureHandle(check_icon.image_id, check_icon.sampler_id) : dkMakeTextureHandle(uncheck_icon.image_id, uncheck_icon.sampler_id)),
|
data.checkbox_data.checked.at(i)? dkMakeTextureHandle(check_icon.image_id, check_icon.sampler_id) : dkMakeTextureHandle(uncheck_icon.image_id, uncheck_icon.sampler_id)),
|
||||||
tex_size, ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
tex_size, ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||||
data.checked.at(i) = !data.checked.at(i);
|
data.checkbox_data.checked.at(i) = !data.checkbox_data.checked.at(i);
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
|
||||||
@ -57,17 +57,17 @@ namespace Tabs {
|
|||||||
if (!strncmp(data.entries[i].name, "..", sizeof(data.entries[i].name))) {
|
if (!strncmp(data.entries[i].name, "..", sizeof(data.entries[i].name))) {
|
||||||
if (R_SUCCEEDED(FS::ChangeDirPrev(data.entries))) {
|
if (R_SUCCEEDED(FS::ChangeDirPrev(data.entries))) {
|
||||||
// Make a copy before resizing our vector.
|
// Make a copy before resizing our vector.
|
||||||
if (data.checked_count > 1)
|
if (data.checkbox_data.count > 1)
|
||||||
data.checked_copy = data.checked;
|
data.checkbox_data.checked_copy = data.checkbox_data.checked;
|
||||||
|
|
||||||
data.checked.resize(data.entries.size());
|
data.checkbox_data.checked.resize(data.entries.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (R_SUCCEEDED(FS::ChangeDirNext(data.entries[i].name, data.entries))) {
|
else if (R_SUCCEEDED(FS::ChangeDirNext(data.entries[i].name, data.entries))) {
|
||||||
if ((data.checked_count > 1) && (data.checked_copy.empty()))
|
if ((data.checkbox_data.count > 1) && (data.checkbox_data.checked_copy.empty()))
|
||||||
data.checked_copy = data.checked;
|
data.checkbox_data.checked_copy = data.checkbox_data.checked;
|
||||||
|
|
||||||
data.checked.resize(data.entries.size());
|
data.checkbox_data.checked.resize(data.entries.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset navigation ID -- TODO: Scroll to top
|
// Reset navigation ID -- TODO: Scroll to top
|
||||||
|
@ -1,9 +1,30 @@
|
|||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "popups.h"
|
||||||
#include "tabs.h"
|
#include "tabs.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
namespace Windows {
|
namespace Windows {
|
||||||
void MainWindow(WindowData &data) {
|
static void SetupWindow(void) {
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_Once);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(1280.0f, 720.0f), ImGuiCond_Once);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ExitWindow(void) {
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
};
|
||||||
|
|
||||||
|
void ResetCheckbox(WindowData &data) {
|
||||||
|
data.checkbox_data.checked.clear();
|
||||||
|
data.checkbox_data.checked_copy.clear();
|
||||||
|
data.checkbox_data.checked.resize(data.entries.size());
|
||||||
|
data.checkbox_data.checked.assign(data.checkbox_data.checked.size(), false);
|
||||||
|
data.checkbox_data.cwd.clear();
|
||||||
|
data.checkbox_data.count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MainWindow(WindowData &data, u64 &key) {
|
||||||
Windows::SetupWindow();
|
Windows::SetupWindow();
|
||||||
if (ImGui::Begin("NX-Shell", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) {
|
if (ImGui::Begin("NX-Shell", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse)) {
|
||||||
if (ImGui::BeginTabBar("NX-Shell-tabs")) {
|
if (ImGui::BeginTabBar("NX-Shell-tabs")) {
|
||||||
@ -13,5 +34,22 @@ namespace Windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Windows::ExitWindow();
|
Windows::ExitWindow();
|
||||||
|
|
||||||
|
switch (data.state) {
|
||||||
|
case WINDOW_STATE_OPTIONS:
|
||||||
|
Popups::OptionsPopup(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key & HidNpadButton_X) && (data.state == WINDOW_STATE_FILEBROWSER))
|
||||||
|
data.state = WINDOW_STATE_OPTIONS;
|
||||||
|
|
||||||
|
if (key & HidNpadButton_B) {
|
||||||
|
if (data.state == WINDOW_STATE_OPTIONS)
|
||||||
|
data.state = WINDOW_STATE_FILEBROWSER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user