mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-03-21 17:24:37 -05:00
Progress bars, split some ui classes, threaded confirm, better thread safety(I think)
This commit is contained in:
parent
d18204733d
commit
9227c7a3f1
4
Makefile
4
Makefile
|
|
@ -34,11 +34,11 @@ TARGET := JKSV
|
|||
BUILD := build
|
||||
SOURCES := src src/ui
|
||||
DATA := data
|
||||
INCLUDES := inc
|
||||
INCLUDES := inc inc/ui
|
||||
EXEFS_SRC := exefs_src
|
||||
APP_TITLE := JKSV
|
||||
APP_AUTHOR := JK
|
||||
APP_VERSION := 07.18.2021
|
||||
APP_VERSION := 07.22.2021
|
||||
ROMFS := romfs
|
||||
ICON := icon.jpg
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#define curData users[data::selUser].titleInfo[data::selData]
|
||||
|
||||
#define BLD_MON 7
|
||||
#define BLD_DAY 18
|
||||
#define BLD_DAY 22
|
||||
#define BLD_YEAR 2021
|
||||
|
||||
namespace data
|
||||
|
|
|
|||
37
inc/type.h
37
inc/type.h
|
|
@ -1,19 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <switch.h>
|
||||
|
||||
//Misc stuff for new menu code
|
||||
typedef void (*funcPtr)(void *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Mutex statusLock = 0;
|
||||
std::string status;
|
||||
void setStatus(const std::string& newStatus)
|
||||
{
|
||||
mutexLock(&statusLock);
|
||||
status = newStatus;
|
||||
mutexUnlock(&statusLock);
|
||||
}
|
||||
|
||||
void getStatus(std::string& statusOut)
|
||||
{
|
||||
mutexLock(&statusLock);
|
||||
statusOut = status;
|
||||
mutexUnlock(&statusLock);
|
||||
}
|
||||
|
||||
} threadStatus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool running = false, finished = false;
|
||||
Thread *thrdPtr = NULL;
|
||||
Thread thrd;
|
||||
void *argPtr = NULL;
|
||||
Mutex statusLock = 0;
|
||||
std::string *status;
|
||||
|
||||
void updateStatus(const std::string& newStatus)
|
||||
{
|
||||
mutexLock(&statusLock);
|
||||
*status = newStatus;
|
||||
mutexUnlock(&statusLock);
|
||||
}
|
||||
funcPtr drawFunc = NULL;//Draw func is passed threadInfo pointer too
|
||||
threadStatus *status;
|
||||
} threadInfo;
|
||||
|
|
|
|||
17
inc/ui.h
17
inc/ui.h
|
|
@ -8,12 +8,15 @@
|
|||
#include "gfx.h"
|
||||
|
||||
//ui headers - split up to keep a bit more organized
|
||||
#include "miscui.h"
|
||||
#include "uistr.h"
|
||||
#include "usr.h"
|
||||
#include "ttl.h"
|
||||
#include "sett.h"
|
||||
#include "fm.h"
|
||||
#include "ui/miscui.h"
|
||||
#include "ui/uistr.h"
|
||||
#include "ui/usr.h"
|
||||
#include "ui/ttl.h"
|
||||
#include "ui/sett.h"
|
||||
#include "ui/fm.h"
|
||||
#include "ui/ttlview.h"
|
||||
#include "ui/thrdProc.h"
|
||||
#include "ui/sldpanel.h"
|
||||
|
||||
enum menuState
|
||||
{
|
||||
|
|
@ -84,7 +87,7 @@ namespace ui
|
|||
//Adds a panel pointer to a vector since they need to be drawn over everything else
|
||||
int registerMenu(ui::menu *m);
|
||||
int registerPanel(ui::slideOutPanel *sop);
|
||||
int newThread(ThreadFunc func, void *args);
|
||||
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
|
||||
|
||||
//Just draws a screen and flips JIC boot takes long.
|
||||
void showLoadScreen();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,19 @@ typedef enum
|
|||
//For smaller classes that aren't easy to get lost in and general functions
|
||||
namespace ui
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
std::string text;
|
||||
bool hold;
|
||||
bool cleanup;
|
||||
funcPtr func;
|
||||
void *args;
|
||||
|
||||
//Stuff needed to keep track
|
||||
bool sel = 1;//1 = YES
|
||||
|
||||
} confirmArgs;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
funcPtr func = NULL;
|
||||
|
|
@ -103,86 +116,20 @@ namespace ui
|
|||
{
|
||||
public:
|
||||
//Constructor. _max is the maximum value
|
||||
progBar() = default;
|
||||
progBar(const uint64_t& _max) { max = _max; }
|
||||
|
||||
void setMax(const uint64_t& _max) { max = _max; };
|
||||
|
||||
//Updates progress
|
||||
void update(const uint64_t& _prog);
|
||||
|
||||
//Draws with text at top
|
||||
void draw(const std::string& text, const std::string& head);
|
||||
void draw(const std::string& text);
|
||||
|
||||
private:
|
||||
uint64_t max, prog;
|
||||
float width;
|
||||
};
|
||||
|
||||
//_draw is called and passed the panel texture/target when this.draw() is called.
|
||||
class slideOutPanel
|
||||
{
|
||||
public:
|
||||
slideOutPanel(int _w, int _h, int _y, funcPtr _draw);
|
||||
~slideOutPanel();
|
||||
|
||||
void update();
|
||||
void setCallback(funcPtr _cb, void *_args) { callback = _cb; cbArgs = _args; }
|
||||
void openPanel() { open = true; }
|
||||
void closePanel() { open = false; }
|
||||
bool isOpen() { return open; }
|
||||
void draw(const SDL_Color *backCol);
|
||||
|
||||
private:
|
||||
int w, h, x = 1280, y;
|
||||
bool open = false;
|
||||
SDL_Texture *panel;
|
||||
funcPtr drawFunc, callback = NULL;
|
||||
void *cbArgs = NULL;
|
||||
};
|
||||
|
||||
class titleTile
|
||||
{
|
||||
public:
|
||||
titleTile(unsigned _w, unsigned _h, bool _fav, SDL_Texture *_icon)
|
||||
{
|
||||
w = _w;
|
||||
h = _h;
|
||||
wS = _w;
|
||||
hS = _h;
|
||||
fav = _fav;
|
||||
icon = _icon;
|
||||
}
|
||||
|
||||
void draw(SDL_Texture *target, int x, int y, bool sel);
|
||||
|
||||
private:
|
||||
unsigned w, h, wS, hS;
|
||||
bool fav = false;
|
||||
SDL_Texture *icon;
|
||||
};
|
||||
|
||||
//Todo less hardcode etc
|
||||
class titleview
|
||||
{
|
||||
public:
|
||||
titleview(const data::user& _u, int _iconW, int _iconH, int _horGap, int _vertGap, int _rowCount, funcPtr _callback);
|
||||
~titleview();
|
||||
|
||||
void update();
|
||||
void refresh();
|
||||
|
||||
void setActive(bool _set, bool _showSel) { active = _set; showSel = _showSel; }
|
||||
bool getActive(){ return active; }
|
||||
void setSelected(int _set){ selected = _set; }
|
||||
int getSelected(){ return selected; }
|
||||
void draw(SDL_Texture *target);
|
||||
|
||||
private:
|
||||
const data::user *u;//Might not be safe. Users *shouldn't* be touched after initial load
|
||||
bool active = false, showSel = false, clrAdd = true;
|
||||
uint8_t clrShft = 0;
|
||||
funcPtr callback = NULL;
|
||||
int x = 34, y = 69, selected = 0, selRectX = 10, selRectY = 45;
|
||||
int iconW, iconH, horGap, vertGap, rowCount;
|
||||
std::vector<ui::titleTile *> tiles;
|
||||
uint64_t max = 0, prog = 0;
|
||||
float width = 0;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
|
@ -206,26 +153,10 @@ namespace ui
|
|||
std::vector<popMessage> message;
|
||||
};
|
||||
|
||||
class threadProcMngr
|
||||
{
|
||||
public:
|
||||
~threadProcMngr();
|
||||
void newThread(ThreadFunc func, void *args);
|
||||
void addThread(threadInfo *t);
|
||||
void update();
|
||||
void draw();
|
||||
bool empty(){ return threads.empty(); }
|
||||
|
||||
private:
|
||||
std::vector<threadInfo *> threads;
|
||||
uint8_t lgFrame = 0;
|
||||
unsigned frameCount = 0;
|
||||
Mutex threadLock = 0;
|
||||
};
|
||||
|
||||
//General use
|
||||
ui::confirmArgs *confirmArgsCreate(bool _hold, funcPtr _func, void *_funcArgs, bool _cleanup, const char *fmt, ...);
|
||||
void showMessage(const char *head, const char *fmt, ...);
|
||||
bool confirm(bool hold, const char *fmt, ...);
|
||||
void confirm(void *a);
|
||||
bool confirmTransfer(const std::string& f, const std::string& t);
|
||||
bool confirmDelete(const std::string& p);
|
||||
void drawBoundBox(SDL_Texture *target, int x, int y, int w, int h, uint8_t clrSh);
|
||||
26
inc/ui/sldpanel.h
Normal file
26
inc/ui/sldpanel.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
namespace ui
|
||||
{
|
||||
//_draw is called and passed the panel texture/target when this.draw() is called.
|
||||
class slideOutPanel
|
||||
{
|
||||
public:
|
||||
slideOutPanel(int _w, int _h, int _y, funcPtr _draw);
|
||||
~slideOutPanel();
|
||||
|
||||
void update();
|
||||
void setCallback(funcPtr _cb, void *_args) { callback = _cb; cbArgs = _args; }
|
||||
void openPanel() { open = true; }
|
||||
void closePanel() { open = false; }
|
||||
bool isOpen() { return open; }
|
||||
void draw(const SDL_Color *backCol);
|
||||
|
||||
private:
|
||||
int w, h, x = 1280, y;
|
||||
bool open = false;
|
||||
SDL_Texture *panel;
|
||||
funcPtr drawFunc, callback = NULL;
|
||||
void *cbArgs = NULL;
|
||||
};
|
||||
}
|
||||
23
inc/ui/thrdProc.h
Normal file
23
inc/ui/thrdProc.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "type.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class threadProcMngr
|
||||
{
|
||||
public:
|
||||
~threadProcMngr();
|
||||
//Draw function is used and called to draw on overlay
|
||||
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
|
||||
void update();
|
||||
void draw();
|
||||
bool empty() { return threads.empty(); }
|
||||
|
||||
private:
|
||||
std::vector<threadInfo *> threads;
|
||||
uint8_t lgFrame = 0;
|
||||
unsigned frameCount = 0;
|
||||
Mutex threadLock = 0;
|
||||
};
|
||||
}
|
||||
56
inc/ui/ttlview.h
Normal file
56
inc/ui/ttlview.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "type.h"
|
||||
#include "data.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class titleTile
|
||||
{
|
||||
public:
|
||||
titleTile(unsigned _w, unsigned _h, bool _fav, SDL_Texture *_icon)
|
||||
{
|
||||
w = _w;
|
||||
h = _h;
|
||||
wS = _w;
|
||||
hS = _h;
|
||||
fav = _fav;
|
||||
icon = _icon;
|
||||
}
|
||||
|
||||
void draw(SDL_Texture *target, int x, int y, bool sel);
|
||||
|
||||
private:
|
||||
unsigned w, h, wS, hS;
|
||||
bool fav = false;
|
||||
SDL_Texture *icon;
|
||||
};
|
||||
|
||||
//Todo less hardcode etc
|
||||
class titleview
|
||||
{
|
||||
public:
|
||||
titleview(const data::user& _u, int _iconW, int _iconH, int _horGap, int _vertGap, int _rowCount, funcPtr _callback);
|
||||
~titleview();
|
||||
|
||||
void update();
|
||||
void refresh();
|
||||
|
||||
void setActive(bool _set, bool _showSel) { active = _set; showSel = _showSel; }
|
||||
bool getActive() { return active; }
|
||||
void setSelected(int _set) { selected = _set; }
|
||||
int getSelected() { return selected; }
|
||||
void draw(SDL_Texture *target);
|
||||
|
||||
private:
|
||||
const data::user *u;//Might not be safe. Users *shouldn't* be touched after initial load
|
||||
bool active = false, showSel = false, clrAdd = true;
|
||||
uint8_t clrShft = 0;
|
||||
funcPtr callback = NULL;
|
||||
int x = 34, y = 69, selected = 0, selRectX = 10, selRectY = 45;
|
||||
int iconW, iconH, horGap, vertGap, rowCount;
|
||||
std::vector<ui::titleTile *> tiles;
|
||||
};
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ namespace util
|
|||
|
||||
std::string getInfoString(data::user& u, const uint64_t& tid);
|
||||
|
||||
std::string getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
|
||||
std::string getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
|
||||
|
||||
inline std::string getExtensionFromString(const std::string& get)
|
||||
{
|
||||
|
|
|
|||
283
src/file.cpp
283
src/file.cpp
|
|
@ -31,10 +31,16 @@ typedef struct
|
|||
std::string to, from, dev;
|
||||
zipFile z;
|
||||
unzFile unz;
|
||||
bool closeZip = false;
|
||||
bool cleanup = false;
|
||||
uint64_t offset = 0, fileSize = 0;
|
||||
ui::progBar *prog;
|
||||
threadStatus *thrdStatus;
|
||||
Mutex arglck = 0;
|
||||
void argLock() { mutexLock(&arglck); }
|
||||
void argUnlock() { mutexUnlock(&arglck); }
|
||||
} copyArgs;
|
||||
|
||||
static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _closeZip)
|
||||
static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _cleanup)
|
||||
{
|
||||
copyArgs *ret = new copyArgs;
|
||||
ret->to = to;
|
||||
|
|
@ -42,10 +48,20 @@ static copyArgs *copyArgsCreate(const std::string& from, const std::string& to,
|
|||
ret->dev = dev;
|
||||
ret->z = z;
|
||||
ret->unz = unz;
|
||||
ret->closeZip = _closeZip;
|
||||
ret->cleanup = _cleanup;
|
||||
ret->prog = new ui::progBar;
|
||||
ret->fileSize = 0.0f;
|
||||
ret->offset = 0.0f;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void copyArgsDestroy(copyArgs *c)
|
||||
{
|
||||
delete c->prog;
|
||||
delete c;
|
||||
c = NULL;
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
bool operator()(const fs::dirItem& a, const fs::dirItem& b)
|
||||
|
|
@ -349,19 +365,26 @@ int fs::dataFile::getNextValueInt()
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline std::string fileStatusString(const std::string& itm, float complete, float total)
|
||||
//Todo: Weird flickering?
|
||||
static void _fileDrawFunc(void *a)
|
||||
{
|
||||
char tmp[512];
|
||||
sprintf(tmp, "Copying \"%s\" : %.2f MB / %.2f MB", itm.c_str(), complete / 1024.0f / 1024.0f, total / 1024.0f / 1024.0f);
|
||||
return std::string(tmp);
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
if(!t->finished)
|
||||
{
|
||||
copyArgs *c = (copyArgs *)t->argPtr;
|
||||
std::string tmp;
|
||||
t->status->getStatus(tmp);
|
||||
c->argLock();
|
||||
c->prog->draw(tmp);
|
||||
c->argUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void copyfile_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
copyArgs *args = (copyArgs *)t->argPtr;
|
||||
|
||||
float srcSize = (float)fs::fsize(args->from);
|
||||
t->status->setStatus("Copying '" + args->from + "'...");
|
||||
|
||||
uint8_t *buff = new uint8_t[BUFF_SIZE];
|
||||
if(data::config["directFsCmd"])
|
||||
|
|
@ -380,7 +403,10 @@ static void copyfile_t(void *a)
|
|||
while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0)
|
||||
{
|
||||
fsfwrite(buff, 1, readIn, out);
|
||||
*t->status = fileStatusString(args->from, (float)in->offset, srcSize);
|
||||
args->argLock();
|
||||
args->offset = in->offset;
|
||||
args->prog->update(args->offset);
|
||||
args->argUnlock();
|
||||
}
|
||||
fsfclose(in);
|
||||
fsfclose(out);
|
||||
|
|
@ -401,20 +427,25 @@ static void copyfile_t(void *a)
|
|||
while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0)
|
||||
{
|
||||
fwrite(buff, 1, readIn, out);
|
||||
*t->status = fileStatusString(args->from, (float)ftell(in), srcSize);
|
||||
args->argLock();
|
||||
args->offset = ftell(in);
|
||||
args->prog->update(args->offset);
|
||||
args->argUnlock();
|
||||
}
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
}
|
||||
delete[] buff;
|
||||
delete args;
|
||||
copyArgsDestroy(args);
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::copyFile(const std::string& from, const std::string& to)
|
||||
{
|
||||
copyArgs *send = copyArgsCreate(from, to, "", NULL, NULL, false);
|
||||
ui::newThread(copyfile_t, send);
|
||||
send->fileSize = fs::fsize(from);
|
||||
send->prog->setMax(send->fileSize);
|
||||
ui::newThread(copyfile_t, send, _fileDrawFunc);
|
||||
}
|
||||
|
||||
void copyFileCommit_t(void *a)
|
||||
|
|
@ -422,8 +453,8 @@ void copyFileCommit_t(void *a)
|
|||
threadInfo *t = (threadInfo *)a;
|
||||
copyArgs *args = (copyArgs *)t->argPtr;
|
||||
data::titleInfo *info = data::getTitleInfoByTID(data::curData.saveID);
|
||||
t->status->setStatus("Copying '" + args->from + "'...");
|
||||
|
||||
float srcSize = (float)fs::fsize(args->from);
|
||||
uint64_t journalSize = getJournalSize(info), writeCount = 0;
|
||||
uint8_t *buff = new uint8_t[BUFF_SIZE];
|
||||
|
||||
|
|
@ -454,7 +485,10 @@ void copyFileCommit_t(void *a)
|
|||
|
||||
out = fsfopen(args->to.c_str(), FsOpenMode_Write | FsOpenMode_Append);
|
||||
}
|
||||
*t->status = fileStatusString(args->from, (float)out->offset, srcSize);
|
||||
args->argLock();
|
||||
args->offset = out->offset;
|
||||
args->prog->update(args->offset);
|
||||
args->argUnlock();
|
||||
}
|
||||
fsfclose(in);
|
||||
fsfclose(out);
|
||||
|
|
@ -486,7 +520,10 @@ void copyFileCommit_t(void *a)
|
|||
|
||||
out = fopen(args->to.c_str(), "ab");
|
||||
}
|
||||
*t->status = fileStatusString(args->from, (float)ftell(out), srcSize);
|
||||
args->argLock();
|
||||
args->offset = ftell(out);
|
||||
args->prog->update(args->offset);
|
||||
args->argUnlock();
|
||||
}
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
|
@ -494,15 +531,16 @@ void copyFileCommit_t(void *a)
|
|||
delete[] buff;
|
||||
|
||||
commitToDevice(args->dev.c_str());
|
||||
delete args;
|
||||
copyArgsDestroy(args);
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev)
|
||||
{
|
||||
ui::progBar prog(fsize(from));
|
||||
copyArgs *send = copyArgsCreate(from, to, dev, NULL, NULL, false);
|
||||
ui::newThread(copyFileCommit_t, send);
|
||||
send->fileSize = fs::fsize(from);
|
||||
send->prog->setMax(send->fileSize);
|
||||
ui::newThread(copyFileCommit_t, send, _fileDrawFunc);
|
||||
}
|
||||
|
||||
void fs::copyDirToDir(const std::string& from, const std::string& to)
|
||||
|
|
@ -539,30 +577,12 @@ void closeZip_t(void *a)
|
|||
t->finished = true;
|
||||
}
|
||||
|
||||
void copyFileToZip(const std::string& from, zipFile z, std::string *_status)
|
||||
{
|
||||
float srcSize = fs::fsize(from);
|
||||
FILE *cpy = fopen(from.c_str(), "rb");
|
||||
|
||||
size_t readIn = 0;
|
||||
uint8_t *buff = new uint8_t[BUFF_SIZE];
|
||||
while((readIn = fread(buff, 1, BUFF_SIZE, cpy)) > 0)
|
||||
{
|
||||
zipWriteInFileInZip(z, buff, readIn);
|
||||
*_status = (fileStatusString(from, (float)ftell(cpy), srcSize));
|
||||
}
|
||||
|
||||
delete[] buff;
|
||||
fclose(cpy);
|
||||
}
|
||||
|
||||
void copyDirToZip_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
copyArgs *args = (copyArgs *)t->argPtr;
|
||||
|
||||
t->updateStatus("Opening " + args->from + "...");
|
||||
//fs::logWrite(t->status->c_str());
|
||||
t->status->setStatus("Opening " + args->from + "...");
|
||||
fs::dirList *list = new fs::dirList(args->from);
|
||||
|
||||
unsigned listTotal = list->getCount();
|
||||
|
|
@ -575,11 +595,18 @@ void copyDirToZip_t(void *a)
|
|||
if(list->isDir(i))
|
||||
{
|
||||
std::string newFrom = args->from + itm + "/";
|
||||
//Fake thread and new args to point to src thread stuff
|
||||
//This wouldn't work spawning a new thread.
|
||||
threadInfo *tmpThread = new threadInfo;
|
||||
tmpThread->status = t->status;
|
||||
copyArgs *tmpArgs = copyArgsCreate(newFrom, "", "", args->z, NULL, false);
|
||||
copyArgs *tmpArgs = new copyArgs;
|
||||
tmpArgs->from = newFrom;
|
||||
tmpArgs->prog = args->prog;
|
||||
tmpArgs->z = args->z;
|
||||
tmpArgs->cleanup = false;
|
||||
tmpThread->argPtr = tmpArgs;
|
||||
copyDirToZip_t(tmpThread);
|
||||
delete tmpArgs;
|
||||
delete tmpThread;
|
||||
}
|
||||
else
|
||||
|
|
@ -587,67 +614,92 @@ void copyDirToZip_t(void *a)
|
|||
zip_fileinfo inf = {0};
|
||||
std::string filename = args->from + itm;
|
||||
size_t devPos = filename.find_first_of('/') + 1;
|
||||
t->updateStatus("Adding \"" + itm + "\" to ZIP.");
|
||||
if(zipOpenNewFileInZip(args->z, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == ZIP_OK)
|
||||
t->status->setStatus("Adding '" + itm + "' to ZIP.");
|
||||
int zOpenFile = zipOpenNewFileInZip64(args->z, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0);
|
||||
if(zOpenFile == ZIP_OK)
|
||||
{
|
||||
copyFileToZip(args->from +itm, args->z, t->status);
|
||||
std::string fullFrom = args->from + itm;
|
||||
args->offset = 0;
|
||||
args->fileSize = fs::fsize(fullFrom);
|
||||
args->prog->setMax(args->fileSize);
|
||||
args->prog->update(0);
|
||||
FILE *cpy = fopen(fullFrom.c_str(), "rb");
|
||||
size_t readIn = 0;
|
||||
uint8_t *buff = new uint8_t[BUFF_SIZE];
|
||||
while((readIn = fread(buff, 1, BUFF_SIZE, cpy)) > 0)
|
||||
{
|
||||
zipWriteInFileInZip(args->z, buff, readIn);
|
||||
args->offset += readIn;
|
||||
args->prog->update(args->offset);
|
||||
}
|
||||
delete[] buff;
|
||||
fclose(cpy);
|
||||
zipCloseFileInZip(args->z);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete list;
|
||||
if(args->closeZip)
|
||||
ui::newThread(closeZip_t, args->z);
|
||||
delete args;
|
||||
if(args->cleanup)
|
||||
{
|
||||
ui::newThread(closeZip_t, args->z, NULL);
|
||||
delete args->prog;
|
||||
delete args;
|
||||
}
|
||||
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::copyDirToZip(const std::string& from, zipFile to)
|
||||
{
|
||||
copyArgs *send = copyArgsCreate(from, "", "", to, NULL, true);
|
||||
ui::newThread(copyDirToZip_t, send);
|
||||
ui::newThread(copyDirToZip_t, send, _fileDrawFunc);
|
||||
}
|
||||
|
||||
void copyZipToDir_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
copyArgs *cpyArgs = (copyArgs *)t->argPtr;
|
||||
copyArgs *args = (copyArgs *)t->argPtr;
|
||||
|
||||
data::titleInfo *tinfo = data::getTitleInfoByTID(data::curData.saveID);
|
||||
uint64_t journalSize = getJournalSize(tinfo), writeCount = 0;
|
||||
char filename[FS_MAX_PATH];
|
||||
uint8_t *buff = new uint8_t[BUFF_SIZE];
|
||||
int readIn = 0;
|
||||
unz_file_info info;
|
||||
if(unzGoToFirstFile(cpyArgs->unz) == UNZ_OK)
|
||||
unz_file_info64 info;
|
||||
if(unzGoToFirstFile(args->unz) == UNZ_OK)
|
||||
{
|
||||
do
|
||||
{
|
||||
unzGetCurrentFileInfo(cpyArgs->unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0);
|
||||
if(unzOpenCurrentFile(cpyArgs->unz) == UNZ_OK)
|
||||
unzGetCurrentFileInfo64(args->unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0);
|
||||
if(unzOpenCurrentFile(args->unz) == UNZ_OK)
|
||||
{
|
||||
std::string path = cpyArgs->to + filename;
|
||||
t->status->setStatus("Copying '" + std::string(filename) + "'...");
|
||||
std::string path = args->to + filename;
|
||||
mkdirRec(path.substr(0, path.find_last_of('/') + 1));
|
||||
float srcSize = (float)info.uncompressed_size;
|
||||
|
||||
args->fileSize = info.uncompressed_size;
|
||||
args->offset = 0.0f;
|
||||
args->prog->setMax(args->fileSize);
|
||||
size_t done = 0;
|
||||
if(data::config["directFsCmd"])
|
||||
{
|
||||
FSFILE *out = fsfopen(path.c_str(), FsOpenMode_Write);
|
||||
while((readIn = unzReadCurrentFile(cpyArgs->unz, buff, BUFF_SIZE)) > 0)
|
||||
while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0)
|
||||
{
|
||||
done += readIn;
|
||||
writeCount += readIn;
|
||||
args->offset += readIn;
|
||||
args->prog->update(args->offset);
|
||||
fsfwrite(buff, 1, readIn, out);
|
||||
if(writeCount >= (journalSize - 0x100000))
|
||||
{
|
||||
writeCount = 0;
|
||||
fsfclose(out);
|
||||
if(!commitToDevice(cpyArgs->dev.c_str()))
|
||||
if(!commitToDevice(args->dev.c_str()))
|
||||
break;
|
||||
|
||||
out = fsfopen(path.c_str(), FsOpenMode_Write | FsOpenMode_Append);
|
||||
}
|
||||
t->updateStatus(fileStatusString(filename, (float)done, srcSize));
|
||||
}
|
||||
fsfclose(out);
|
||||
}
|
||||
|
|
@ -655,37 +707,39 @@ void copyZipToDir_t(void *a)
|
|||
{
|
||||
FILE *out = fopen(path.c_str(), "wb");
|
||||
|
||||
while((readIn = unzReadCurrentFile(cpyArgs->unz, buff, BUFF_SIZE)) > 0)
|
||||
while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0)
|
||||
{
|
||||
done += readIn;
|
||||
writeCount += readIn;
|
||||
args->offset += readIn;
|
||||
args->prog->update(args->offset);
|
||||
fwrite(buff, 1, readIn, out);
|
||||
if(writeCount >= (journalSize - 0x100000))
|
||||
{
|
||||
writeCount = 0;
|
||||
fclose(out);
|
||||
if(!commitToDevice(cpyArgs->dev.c_str()))
|
||||
if(!commitToDevice(args->dev.c_str()))
|
||||
break;
|
||||
|
||||
out = fopen(path.c_str(), "ab");
|
||||
}
|
||||
t->updateStatus(fileStatusString(filename, (float)done, srcSize));
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
unzCloseCurrentFile(cpyArgs->unz);
|
||||
commitToDevice(cpyArgs->dev.c_str());
|
||||
unzCloseCurrentFile(args->unz);
|
||||
commitToDevice(args->dev.c_str());
|
||||
}
|
||||
}
|
||||
while(unzGoToNextFile(cpyArgs->unz) != UNZ_END_OF_LIST_OF_FILE);
|
||||
while(unzGoToNextFile(args->unz) != UNZ_END_OF_LIST_OF_FILE);
|
||||
}
|
||||
else
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "ZIP file is empty!");
|
||||
|
||||
if(cpyArgs->closeZip)
|
||||
unzClose(cpyArgs->unz);
|
||||
|
||||
delete cpyArgs;
|
||||
if(args->cleanup)
|
||||
{
|
||||
unzClose(args->unz);
|
||||
copyArgsDestroy(args);
|
||||
}
|
||||
delete[] buff;
|
||||
t->finished = true;
|
||||
}
|
||||
|
|
@ -693,7 +747,7 @@ void copyZipToDir_t(void *a)
|
|||
void fs::copyZipToDir(unzFile unz, const std::string& to, const std::string& dev)
|
||||
{
|
||||
copyArgs *send = copyArgsCreate("", to, dev, NULL, unz, true);
|
||||
ui::newThread(copyZipToDir_t, send);
|
||||
ui::newThread(copyZipToDir_t, send, _fileDrawFunc);
|
||||
}
|
||||
|
||||
void fs::copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev)
|
||||
|
|
@ -939,7 +993,7 @@ void fs::createNewBackup(void *a)
|
|||
util::generateAbbrev(data::curData.saveID),
|
||||
".zip"
|
||||
};
|
||||
out = util::getStringInput("", "Enter a name", 64, 9, dict);
|
||||
out = util::getStringInput(SwkbdType_QWERTY, "", "Enter a name", 64, 9, dict);
|
||||
}
|
||||
|
||||
if(!out.empty())
|
||||
|
|
@ -951,7 +1005,7 @@ void fs::createNewBackup(void *a)
|
|||
if(ext != "zip")//data::zip is on but extension is not zip
|
||||
path += ".zip";
|
||||
|
||||
zipFile zip = zipOpen(path.c_str(), 0);
|
||||
zipFile zip = zipOpen64(path.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", zip);
|
||||
|
||||
}
|
||||
|
|
@ -967,49 +1021,49 @@ void fs::createNewBackup(void *a)
|
|||
|
||||
void fs::overwriteBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
fs::backupArgs *in = (fs::backupArgs *)t->argPtr;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;;//Skip new
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if(ui::confirm(data::config["holdOver"], ui::confOverwrite.c_str(), itemName.c_str()))
|
||||
if(d->isDir(ind))
|
||||
{
|
||||
if(d->isDir(ind))
|
||||
{
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
//Delete and recreate
|
||||
fs::delDir(toPath);
|
||||
mkdir(toPath.c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", toPath);
|
||||
}
|
||||
else if(!d->isDir(ind) && d->getItemExt(ind) == "zip")
|
||||
{
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(toPath);
|
||||
zipFile zip = zipOpen(toPath.c_str(), 0);
|
||||
if(zip)
|
||||
fs::copyDirToZip("sv:/", zip);
|
||||
}
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
//Delete and recreate
|
||||
fs::delDir(toPath);
|
||||
mkdir(toPath.c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", toPath);
|
||||
}
|
||||
else if(!d->isDir(ind) && d->getItemExt(ind) == "zip")
|
||||
{
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(toPath);
|
||||
zipFile zip = zipOpen64(toPath.c_str(), 0);
|
||||
if(zip)
|
||||
fs::copyDirToZip("sv:/", zip);
|
||||
}
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::restoreBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
fs::backupArgs *in = (fs::backupArgs *)t->argPtr;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if((data::curData.saveInfo.save_data_type != FsSaveDataType_System || data::config["sysSaveWrite"]) && m->getSelected() > 0 && ui::confirm(data::config["holdRest"], ui::confRestore.c_str(), itemName.c_str()))
|
||||
if((data::curData.saveInfo.save_data_type != FsSaveDataType_System || data::config["sysSaveWrite"]) && m->getSelected() > 0)
|
||||
{
|
||||
if(data::config["autoBack"] && data::config["zip"])
|
||||
{
|
||||
std::string autoZip = util::generatePathByTID(data::curData.saveID) + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
|
||||
zipFile zip = zipOpen(autoZip.c_str(), 0);
|
||||
zipFile zip = zipOpen64(autoZip.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", zip);
|
||||
}
|
||||
else if(data::config["autoBack"])
|
||||
|
|
@ -1029,7 +1083,7 @@ void fs::restoreBackup(void *a)
|
|||
{
|
||||
fs::wipeSave();
|
||||
std::string path = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
unzFile unz = unzOpen(path.c_str());
|
||||
unzFile unz = unzOpen64(path.c_str());
|
||||
fs::copyZipToDir(unz, "sv:/", "sv");
|
||||
}
|
||||
else
|
||||
|
|
@ -1043,40 +1097,43 @@ void fs::restoreBackup(void *a)
|
|||
|
||||
if(data::config["autoBack"])
|
||||
ui::populateFldMenu();
|
||||
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::deleteBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
fs::backupArgs *in = (fs::backupArgs *)t->argPtr;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if(ui::confirmDelete(itemName))
|
||||
t->status->setStatus("Deleting '" + itemName + "'...");
|
||||
|
||||
if(data::config["trashBin"])
|
||||
{
|
||||
if(data::config["trashBin"])
|
||||
{
|
||||
std::string oldPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
std::string trashPath = wd + "_TRASH_/" + itemName;
|
||||
rename(oldPath.c_str(), trashPath.c_str());
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s moved to trash.", itemName.c_str());
|
||||
}
|
||||
else if(d->isDir(ind))
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
fs::delDir(delPath);
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(delPath);
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str());
|
||||
}
|
||||
ui::populateFldMenu();
|
||||
std::string oldPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
std::string trashPath = wd + "_TRASH_/" + itemName;
|
||||
rename(oldPath.c_str(), trashPath.c_str());
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s moved to trash.", itemName.c_str());
|
||||
}
|
||||
else if(d->isDir(ind))
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
fs::delDir(delPath);
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(delPath);
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str());
|
||||
}
|
||||
ui::populateFldMenu();
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
void fs::logOpen()
|
||||
|
|
|
|||
38
src/ui.cpp
38
src/ui.cpp
|
|
@ -75,7 +75,7 @@ void ui::initTheme()
|
|||
txtDiag = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
rectLt = {0xDF, 0xDF, 0xDF, 0xFF};
|
||||
rectSh = {0xCA, 0xCA, 0xCA, 0xFF};
|
||||
tboxClr = {0x50, 0x50, 0x50, 0xFF};
|
||||
tboxClr = {0xEB, 0xEB, 0xEB, 0xFF};
|
||||
divClr = {0x00, 0x00, 0x00, 0xFF};
|
||||
slidePanelColor = {0xEE, 0xEE, 0xEE, 0xDD};
|
||||
break;
|
||||
|
|
@ -84,13 +84,12 @@ void ui::initTheme()
|
|||
case ColorSetId_Dark:
|
||||
//jic
|
||||
thmID = ColorSetId_Dark;
|
||||
|
||||
clearClr = {0x2D, 0x2D, 0x2D, 0xFF};
|
||||
txtCont = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
txtDiag = {0x00, 0x00, 0x00, 0xFF};
|
||||
rectLt = {0x50, 0x50, 0x50, 0xFF};
|
||||
rectSh = {0x20, 0x20, 0x20, 0xFF};
|
||||
tboxClr = {0xEB, 0xEB, 0xEB, 0xFF};
|
||||
tboxClr = {0x50, 0x50, 0x50, 0xFF};
|
||||
divClr = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
slidePanelColor = {0x00, 0x00, 0x00, 0xDD};
|
||||
break;
|
||||
|
|
@ -113,10 +112,10 @@ void ui::init()
|
|||
{
|
||||
case ColorSetId_Light:
|
||||
//Dark corners
|
||||
cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png");
|
||||
cornerTopRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopRight.png");
|
||||
cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png");
|
||||
cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotRight.png");
|
||||
cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopLeft.png");
|
||||
cornerTopRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopRight.png");
|
||||
cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotLeft.png");
|
||||
cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotRight.png");
|
||||
progCovLeft = gfx::loadImageFile("romfs:/img/tboxDrk/progBarCoverLeftDrk.png");
|
||||
progCovRight = gfx::loadImageFile("romfs:/img/tboxDrk/progBarCoverRightDrk.png");
|
||||
icn = gfx::loadImageFile("romfs:/img/icn/icnDrk.png");
|
||||
|
|
@ -125,10 +124,10 @@ void ui::init()
|
|||
|
||||
default:
|
||||
//Light corners
|
||||
cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopLeft.png");
|
||||
cornerTopRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerTopRight.png");
|
||||
cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotLeft.png");
|
||||
cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxLght/tboxCornerBotRight.png");
|
||||
cornerTopLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png");
|
||||
cornerTopRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerTopRight.png");
|
||||
cornerBottomLeft = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png");
|
||||
cornerBottomRight = gfx::loadImageFile("romfs:/img/tboxDrk/tboxCornerBotRight.png");
|
||||
progCovLeft = gfx::loadImageFile("romfs:/img/tboxLght/progBarCoverLeftLight.png");
|
||||
progCovRight = gfx::loadImageFile("romfs:/img/tboxLght/progBarCoverRightLight.png");
|
||||
icn = gfx::loadImageFile("romfs:/img/icn/icnLght.png");
|
||||
|
|
@ -205,10 +204,9 @@ int ui::registerPanel(slideOutPanel *sop)
|
|||
return panels.size() - 1;
|
||||
}
|
||||
|
||||
int ui::newThread(ThreadFunc func, void *args)
|
||||
threadInfo *ui::newThread(ThreadFunc func, void *args, funcPtr _drawFunc)
|
||||
{
|
||||
threadMngr->newThread(func, args);
|
||||
return 0;
|
||||
return threadMngr->newThread(func, args, _drawFunc);
|
||||
}
|
||||
|
||||
void ui::showLoadScreen()
|
||||
|
|
@ -243,7 +241,7 @@ void ui::drawUI()
|
|||
if(ui::usrMenu->getSelected() == settPos || ui::mstate == OPT_MNU)
|
||||
ui::settDraw(rightPanel);
|
||||
else if(usrMenu->getSelected() == extPos || ui::mstate == EX_MNU)
|
||||
gfx::drawTextf(rightPanel, 24, 32, 32, &ui::txtCont, "PLACE HOLDER SO COMPILER DOESN'T COMPLAIN");
|
||||
gfx::drawTextf(rightPanel, 24, 32, 32, &ui::txtCont, "PLACE HOLDER");
|
||||
else
|
||||
ui::ttlDraw(rightPanel);
|
||||
|
||||
|
|
@ -252,21 +250,21 @@ void ui::drawUI()
|
|||
for(slideOutPanel *s : panels)
|
||||
s->draw(&ui::slidePanelColor);
|
||||
|
||||
popMessages->draw();
|
||||
|
||||
if(!threadMngr->empty())
|
||||
threadMngr->draw();
|
||||
|
||||
popMessages->draw();
|
||||
}
|
||||
|
||||
static bool debugDisp = false;
|
||||
|
||||
bool ui::runApp()
|
||||
{
|
||||
ui::updateInput();
|
||||
uint64_t down = ui::padKeysDown();
|
||||
|
||||
if(threadMngr->empty())
|
||||
{
|
||||
ui::updateInput();
|
||||
uint64_t down = ui::padKeysDown();
|
||||
|
||||
if(down & HidNpadButton_StickL && down & HidNpadButton_StickR)
|
||||
debugDisp = true;
|
||||
else if(down & HidNpadButton_Plus)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "ui.h"
|
||||
#include "miscui.h"
|
||||
#include "util.h"
|
||||
#include "type.h"
|
||||
|
||||
static const char *okt = "OK \ue0e0";
|
||||
|
||||
|
|
@ -15,12 +16,10 @@ static const SDL_Color divDark = {0xCC, 0xCC, 0xCC, 0xFF};
|
|||
static const SDL_Color shadow = {0x66, 0x66, 0x66, 0xFF};
|
||||
|
||||
static const SDL_Color fillBack = {0x66, 0x66, 0x66, 0xFF};
|
||||
static const SDL_Color fillLight = {0x00, 0xFF, 0xC5, 0xFF};
|
||||
static const SDL_Color fillDark = {0x32, 0x50, 0xF0, 0xFF};
|
||||
static const SDL_Color fillBar = {0x00, 0xDD, 0x00, 0xFF};
|
||||
|
||||
static const SDL_Color menuColorLight = {0x32, 0x50, 0xF0, 0xFF};
|
||||
static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF};
|
||||
static const SDL_Color darkenBack = {0x00, 0x00, 0x00, 0xBB};
|
||||
|
||||
void ui::menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW, const unsigned& _fS, const unsigned& _mL)
|
||||
{
|
||||
|
|
@ -258,239 +257,21 @@ void ui::progBar::update(const uint64_t& _prog)
|
|||
{
|
||||
prog = _prog;
|
||||
|
||||
width = (float)(((float)prog / (float)max) * 576);
|
||||
if(max > 0)
|
||||
width = (float)((float)prog / (float)max) * 576.0f;
|
||||
}
|
||||
|
||||
void ui::progBar::draw(const std::string& text, const std::string& head)
|
||||
void ui::progBar::draw(const std::string& text)
|
||||
{
|
||||
size_t headWidth = gfx::getTextWidth(head.c_str(), 20);
|
||||
unsigned headX = (1280 / 2) - (headWidth / 2);
|
||||
char progStr[64];
|
||||
sprintf(progStr, "%.2fMB / %.2fMB", (float)prog / 1024.0f / 1024.0f, (float)max / 1024.0f / 1024.0f);
|
||||
int progX = 640 - (gfx::getTextWidth(progStr, 18) / 2);
|
||||
|
||||
ui::drawTextbox(NULL, 320, 150, 640, 420);
|
||||
gfx::drawLine(NULL, ui::thmID == ColorSetId_Light ? &divLight : &divDark, 320, 206, 959, 206);
|
||||
gfx::drawRect(NULL, &fillBack, 352, 530, 576, 12);
|
||||
gfx::drawRect(NULL, ui::thmID == ColorSetId_Light ? &fillLight : &fillDark, 352, 530, (int)width, 12);
|
||||
gfx::texDraw(NULL, ui::progCovLeft, 352, 530);
|
||||
gfx::texDraw(NULL, ui::progCovRight, 920, 530);
|
||||
|
||||
gfx::drawTextf(NULL, 20, headX, 168, &ui::txtDiag, head.c_str());
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 230, 576, &ui::txtDiag, text.c_str());
|
||||
}
|
||||
|
||||
ui::slideOutPanel::slideOutPanel(int _w, int _h, int _y, funcPtr _draw)
|
||||
{
|
||||
w = _w;
|
||||
h = _h;
|
||||
y = _y;
|
||||
drawFunc = _draw;
|
||||
panel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
SDL_SetTextureBlendMode(panel, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
ui::slideOutPanel::~slideOutPanel()
|
||||
{
|
||||
SDL_DestroyTexture(panel);
|
||||
}
|
||||
|
||||
void ui::slideOutPanel::update()
|
||||
{
|
||||
if(open && callback)
|
||||
(*callback)(cbArgs);
|
||||
}
|
||||
|
||||
void ui::slideOutPanel::draw(const SDL_Color *backCol)
|
||||
{
|
||||
gfx::clearTarget(panel, backCol);
|
||||
|
||||
if(open && x > 1280 - w)
|
||||
{
|
||||
float add = ((1280 - (float)w) - (float)x) / ui::animScale;
|
||||
x += ceil(add);
|
||||
}
|
||||
else if(!open && x < 1280)
|
||||
{
|
||||
float add = (1280 - (float)x) / ui::animScale;
|
||||
x += ceil(add);
|
||||
}
|
||||
|
||||
//don't waste time drawing if you can't even see it.
|
||||
if(x < 1280)
|
||||
{
|
||||
(*drawFunc)(panel);
|
||||
gfx::texDraw(NULL, panel, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//Todo make less hardcoded
|
||||
void ui::titleTile::draw(SDL_Texture *target, int x, int y, bool sel)
|
||||
{
|
||||
unsigned xScale = w * 1.28, yScale = h * 1.28;
|
||||
if(sel)
|
||||
{
|
||||
if(wS < xScale)
|
||||
wS += 18;
|
||||
if(hS < yScale)
|
||||
hS += 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(wS > w)
|
||||
wS -= 9;
|
||||
if(hS > h)
|
||||
hS -= 9;
|
||||
}
|
||||
|
||||
int dX = x - ((wS - w) / 2);
|
||||
int dY = y - ((hS - h) / 2);
|
||||
gfx::texDrawStretch(target, icon, dX, dY, wS, hS);
|
||||
if(fav)
|
||||
gfx::drawTextf(target, 20, dX + 8, dY + 8, &ui::heartColor, "♥");
|
||||
}
|
||||
|
||||
ui::titleview::titleview(const data::user& _u, int _iconW, int _iconH, int _horGap, int _vertGap, int _rowCount, funcPtr _callback)
|
||||
{
|
||||
iconW = _iconW;
|
||||
iconH = _iconH;
|
||||
horGap = _horGap;
|
||||
vertGap = _vertGap;
|
||||
rowCount = _rowCount;
|
||||
callback = _callback;
|
||||
u = &_u;
|
||||
|
||||
for(const data::userTitleInfo& t : u->titleInfo)
|
||||
tiles.emplace_back(new ui::titleTile(_iconW, _iconH, data::isFavorite(t.saveID), data::getTitleIconByTID(t.saveID)));
|
||||
}
|
||||
|
||||
ui::titleview::~titleview()
|
||||
{
|
||||
for(ui::titleTile *t : tiles)
|
||||
delete t;
|
||||
}
|
||||
|
||||
void ui::titleview::refresh()
|
||||
{
|
||||
for(ui::titleTile *t : tiles)
|
||||
delete t;
|
||||
|
||||
tiles.clear();
|
||||
for(const data::userTitleInfo& t : u->titleInfo)
|
||||
tiles.emplace_back(new ui::titleTile(iconW, iconH, data::isFavorite(t.saveID), data::getTitleIconByTID(t.saveID)));
|
||||
}
|
||||
|
||||
void ui::titleview::update()
|
||||
{
|
||||
if(selected > (int)tiles.size() - 1 && selected > 0)
|
||||
selected = tiles.size() - 1;
|
||||
|
||||
if(!active)
|
||||
return;
|
||||
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_StickLUp:
|
||||
case HidNpadButton_StickRUp:
|
||||
case HidNpadButton_Up:
|
||||
if((selected -= rowCount) < 0)
|
||||
selected = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLDown:
|
||||
case HidNpadButton_StickRDown:
|
||||
case HidNpadButton_Down:
|
||||
if((selected += rowCount) > (int)(tiles.size() - 1))
|
||||
selected = tiles.size() - 1;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLLeft:
|
||||
case HidNpadButton_StickRLeft:
|
||||
case HidNpadButton_Left:
|
||||
if(selected > 0)
|
||||
--selected;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLRight:
|
||||
case HidNpadButton_StickRRight:
|
||||
case HidNpadButton_Right:
|
||||
if(selected < (int)(tiles.size() - 1))
|
||||
++selected;
|
||||
break;
|
||||
|
||||
case HidNpadButton_L:
|
||||
if((selected -= rowCount * 3) < 0)
|
||||
selected = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
if((selected += rowCount * 3) > (int)(tiles.size() - 1))
|
||||
selected = tiles.size() - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(callback)
|
||||
(*callback)(this);
|
||||
}
|
||||
|
||||
void ui::titleview::draw(SDL_Texture *target)
|
||||
{
|
||||
if(tiles.size() <= 0)
|
||||
return;
|
||||
|
||||
int tH = 0, tY = 0;
|
||||
SDL_QueryTexture(target, NULL, NULL, NULL, &tH);
|
||||
tY = tH - 214;
|
||||
if(selRectY > tY)
|
||||
{
|
||||
float add = ((float)tY - (float)selRectY) / ui::animScale;
|
||||
y += ceil(add);
|
||||
}
|
||||
else if(selRectY < 38)
|
||||
{
|
||||
float add = (38.0f - (float)selRectY) / ui::animScale;
|
||||
y += ceil(add);
|
||||
}
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrShft += 6;
|
||||
if(clrShft >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrShft -= 3;
|
||||
if(clrShft <= 0)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
int totalTitles = tiles.size(), selX = 32, selY = 64;
|
||||
for(int tY = y, i = 0; i < totalTitles; tY += iconH + vertGap)
|
||||
{
|
||||
int endRow = i + rowCount;
|
||||
for(int tX = x; i < endRow; tX += iconW + horGap, i++)
|
||||
{
|
||||
if(i >= totalTitles)
|
||||
break;
|
||||
|
||||
if(i == selected)
|
||||
{
|
||||
//save x and y for later so it's draw over top
|
||||
selX = tX;
|
||||
selY = tY;
|
||||
selRectX = tX - 24;
|
||||
selRectY = tY - 24;
|
||||
}
|
||||
else
|
||||
tiles[i]->draw(target, tX, tY, false);
|
||||
}
|
||||
}
|
||||
|
||||
if(showSel)
|
||||
{
|
||||
ui::drawBoundBox(target, selRectX, selRectY, 176, 176, clrShft);
|
||||
tiles[selected]->draw(target, selX, selY, true);
|
||||
}
|
||||
else
|
||||
tiles[selected]->draw(target, selX, selY, false);
|
||||
ui::drawTextbox(NULL, 320, 262, 640, 256);
|
||||
gfx::drawRect(NULL, &fillBack, 352, 464, 576, 32);
|
||||
gfx::drawRect(NULL, &fillBar, 352, 464, (int)width, 32);
|
||||
gfx::drawTextf(NULL, 18, progX, 471, &ui::txtCont, progStr);
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 288, 576, &ui::txtCont, text.c_str());
|
||||
}
|
||||
|
||||
ui::popMessageMngr::~popMessageMngr()
|
||||
|
|
@ -532,81 +313,10 @@ void ui::popMessageMngr::draw()
|
|||
p.y += (y - p.y) / ui::animScale;
|
||||
|
||||
gfx::drawRect(NULL, &ui::tboxClr, 64, p.y, p.rectWidth, 40);
|
||||
gfx::drawTextf(NULL, 24, 80, p.y + 8, &ui::txtDiag, p.message.c_str());
|
||||
gfx::drawTextf(NULL, 24, 80, p.y + 8, &ui::txtCont, p.message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ui::threadProcMngr::~threadProcMngr()
|
||||
{
|
||||
for(threadInfo *t : threads)
|
||||
{
|
||||
threadWaitForExit(t->thrdPtr);
|
||||
threadClose(t->thrdPtr);
|
||||
delete t->thrdPtr;
|
||||
delete t->status;
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::threadProcMngr::newThread(ThreadFunc func, void *args)
|
||||
{
|
||||
threadInfo *t = new threadInfo;
|
||||
t->thrdPtr = new Thread;
|
||||
t->status = new std::string;
|
||||
t->finished = false;
|
||||
t->argPtr = args;
|
||||
|
||||
if(R_SUCCEEDED(threadCreate(t->thrdPtr, func, t, NULL, 0x8000, 0x2B, 1)))
|
||||
{
|
||||
mutexLock(&threadLock);
|
||||
threads.push_back(t);
|
||||
mutexUnlock(&threadLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete t->thrdPtr;
|
||||
delete t->status;
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::threadProcMngr::update()
|
||||
{
|
||||
if(!threads.empty())
|
||||
{
|
||||
threadInfo *t = threads[0];
|
||||
if(t->running == false && t->finished == false)
|
||||
{
|
||||
t->running = true;
|
||||
threadStart(t->thrdPtr);
|
||||
}
|
||||
else if(t->running == true && t->finished == true)
|
||||
{
|
||||
threadWaitForExit(t->thrdPtr);
|
||||
threadClose(t->thrdPtr);
|
||||
delete t->thrdPtr;
|
||||
delete t->status;
|
||||
delete t;
|
||||
mutexLock(&threadLock);
|
||||
threads.erase(threads.begin(), threads.begin() + 1);
|
||||
mutexUnlock(&threadLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::threadProcMngr::draw()
|
||||
{
|
||||
if(++frameCount % 4 == 0 && ++lgFrame > 7)
|
||||
lgFrame = 0;
|
||||
|
||||
gfx::drawRect(NULL, &darkenBack, 0, 0, 1280, 720);
|
||||
gfx::drawTextf(NULL, 32, 56, 673, &ui::loadGlyphClr, loadGlyphArray[lgFrame].c_str());
|
||||
mutexLock(&threads[0]->statusLock);
|
||||
int statX = 640 - (gfx::getTextWidth(threads[0]->status->c_str(), 18) / 2);
|
||||
gfx::drawTextf(NULL, 18, statX, 387, &ui::txtCont, threads[0]->status->c_str());
|
||||
mutexUnlock(&threads[0]->statusLock);
|
||||
}
|
||||
|
||||
void ui::showMessage(const char *head, const char *fmt, ...)
|
||||
{
|
||||
char tmp[1024];
|
||||
|
|
@ -634,7 +344,7 @@ void ui::showMessage(const char *head, const char *fmt, ...)
|
|||
ui::updateInput();
|
||||
}
|
||||
|
||||
bool ui::confirm(bool hold, const char *fmt, ...)
|
||||
ui::confirmArgs *ui::confirmArgsCreate(bool _hold, funcPtr _func, void *_funcArgs, bool _cleanup, const char *fmt, ...)
|
||||
{
|
||||
char tmp[1024];
|
||||
va_list args;
|
||||
|
|
@ -642,100 +352,57 @@ bool ui::confirm(bool hold, const char *fmt, ...)
|
|||
vsprintf(tmp, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
bool ret = false, heldDown = false;
|
||||
unsigned loadFrame = 0, holdCount = 0;
|
||||
uint8_t holdClrDiff = 0;
|
||||
SDL_Color holdClr = ui::txtDiag;
|
||||
|
||||
unsigned headX = (640 / 2) - (gfx::getTextWidth(ui::confirmHead.c_str(), 20) / 2);
|
||||
unsigned yesX = 160 - (gfx::getTextWidth(ui::yt.c_str(), 20) / 2);
|
||||
unsigned noX = 160 - (gfx::getTextWidth(ui::nt.c_str(), 20) / 2);
|
||||
|
||||
std::string yesText = yt;
|
||||
|
||||
while(true)
|
||||
{
|
||||
ui::updateInput();
|
||||
|
||||
uint64_t down = ui::padKeysDown();
|
||||
uint64_t held = ui::padKeysHeld();
|
||||
|
||||
if(hold && held & HidNpadButton_A)
|
||||
{
|
||||
heldDown = true;
|
||||
holdCount++, holdClrDiff++;
|
||||
if(holdCount % 4 == 0)
|
||||
{
|
||||
loadFrame++;
|
||||
if(loadFrame > 7)
|
||||
loadFrame = 0;
|
||||
}
|
||||
|
||||
if(holdCount >= 120)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(holdCount <= 40)
|
||||
yesText = ui::holdingText[0];
|
||||
else if(holdCount <= 80)
|
||||
yesText = ui::holdingText[1];
|
||||
else if(holdCount < 120)
|
||||
yesText = ui::holdingText[2];
|
||||
|
||||
yesText += loadGlyphArray[loadFrame];
|
||||
yesX = 160 - (gfx::getTextWidth(yesText.c_str(), 20) / 2);
|
||||
}
|
||||
else if(hold && heldDown)
|
||||
{
|
||||
//Reset everything
|
||||
heldDown= false;
|
||||
holdCount = 0, loadFrame = 0, holdClrDiff = 0;
|
||||
yesX = 160 - (gfx::getTextWidth(ui::yt.c_str(), 20) / 2);
|
||||
yesText = ui::yt;
|
||||
holdClr = ui::txtDiag;
|
||||
}
|
||||
else if(down & HidNpadButton_A)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
else if(down & HidNpadButton_B)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(hold && heldDown)
|
||||
{
|
||||
if(ui::thmID == ColorSetId_Light)
|
||||
holdClr = {0xFF, (uint8_t)(0xFF - holdClrDiff), (uint8_t)(0xFF - holdClrDiff), 0xFF};
|
||||
else
|
||||
holdClr = {(uint8_t)(0x25 + holdClrDiff), 0x00, 0x00, 0xFF};
|
||||
}
|
||||
|
||||
ui::drawTextbox(NULL, 320, 150, 640, 420);
|
||||
gfx::drawTextf(NULL, 20, 320 + headX, 168, &ui::txtDiag, ui::confirmHead.c_str());
|
||||
gfx::drawTextf(NULL, 20, 320 + yesX, 522, &holdClr, yesText.c_str());
|
||||
gfx::drawTextf(NULL, 20, 640 + noX, 522, &ui::txtDiag, ui::nt.c_str());
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 230, 576, &ui::txtDiag, tmp);
|
||||
gfx::present();
|
||||
}
|
||||
|
||||
ui::updateInput();
|
||||
ui::confirmArgs *ret = new confirmArgs;
|
||||
ret->hold = _hold;
|
||||
ret->func = _func;
|
||||
ret->args = _funcArgs;
|
||||
ret->cleanup = _cleanup;
|
||||
ret->text = tmp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ui::confirmTransfer(const std::string& f, const std::string& t)
|
||||
//todo: more inline with original
|
||||
void confirm_t(void *a)
|
||||
{
|
||||
return confirm(false, ui::confCopy.c_str(), f.c_str(), t.c_str());
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
ui::confirmArgs *c = (ui::confirmArgs *)t->argPtr;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(ui::padKeysDown() & HidNpadButton_A)
|
||||
{
|
||||
ui::newThread(c->func, c->args, NULL);
|
||||
break;
|
||||
}
|
||||
else if(ui::padKeysDown() & HidNpadButton_B)
|
||||
break;
|
||||
|
||||
svcSleepThread(1000000);
|
||||
}
|
||||
if(c->cleanup)
|
||||
delete c;
|
||||
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
bool ui::confirmDelete(const std::string& p)
|
||||
//For now this will work
|
||||
void confirmDrawFunc(void *a)
|
||||
{
|
||||
return confirm(data::config["holdDel"], ui::confDel.c_str(), p.c_str());
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
ui::confirmArgs *c = (ui::confirmArgs *)t->argPtr;
|
||||
if(!t->finished)
|
||||
{
|
||||
ui::drawTextbox(NULL, 320, 262, 640, 256);
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 288, 576, &ui::txtCont, c->text.c_str());
|
||||
gfx::drawTextf(NULL, 18, 320 + 128, 476, &ui::txtCont, ui::yt.c_str());
|
||||
gfx::drawTextf(NULL, 18, 960 - 208, 476, &ui::txtCont, ui::nt.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ui::confirm(void *a)
|
||||
{
|
||||
ui::newThread(confirm_t, a, confirmDrawFunc);
|
||||
}
|
||||
|
||||
void ui::drawTextbox(SDL_Texture *target, int x, int y, int w, int h)
|
||||
|
|
|
|||
48
src/ui/sldpanel.cpp
Normal file
48
src/ui/sldpanel.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <SDL.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "gfx.h"
|
||||
|
||||
ui::slideOutPanel::slideOutPanel(int _w, int _h, int _y, funcPtr _draw)
|
||||
{
|
||||
w = _w;
|
||||
h = _h;
|
||||
y = _y;
|
||||
drawFunc = _draw;
|
||||
panel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
SDL_SetTextureBlendMode(panel, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
ui::slideOutPanel::~slideOutPanel()
|
||||
{
|
||||
SDL_DestroyTexture(panel);
|
||||
}
|
||||
|
||||
void ui::slideOutPanel::update()
|
||||
{
|
||||
if(open && callback)
|
||||
(*callback)(cbArgs);
|
||||
}
|
||||
|
||||
void ui::slideOutPanel::draw(const SDL_Color *backCol)
|
||||
{
|
||||
gfx::clearTarget(panel, backCol);
|
||||
|
||||
if(open && x > 1280 - w)
|
||||
{
|
||||
float add = ((1280 - (float)w) - (float)x) / ui::animScale;
|
||||
x += ceil(add);
|
||||
}
|
||||
else if(!open && x < 1280)
|
||||
{
|
||||
float add = (1280 - (float)x) / ui::animScale;
|
||||
x += ceil(add);
|
||||
}
|
||||
|
||||
//don't waste time drawing if you can't even see it.
|
||||
if(x < 1280)
|
||||
{
|
||||
(*drawFunc)(panel);
|
||||
gfx::texDraw(NULL, panel, x, y);
|
||||
}
|
||||
}
|
||||
83
src/ui/thrdProc.cpp
Normal file
83
src/ui/thrdProc.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <switch.h>
|
||||
#include <vector>
|
||||
|
||||
#include "ui.h"
|
||||
#include "gfx.h"
|
||||
|
||||
static const SDL_Color darkenBack = {0x00, 0x00, 0x00, 0xBB};
|
||||
|
||||
ui::threadProcMngr::~threadProcMngr()
|
||||
{
|
||||
for(threadInfo *t : threads)
|
||||
{
|
||||
threadWaitForExit(&t->thrd);
|
||||
threadClose(&t->thrd);
|
||||
delete t->status;
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
|
||||
threadInfo *ui::threadProcMngr::newThread(ThreadFunc func, void *args, funcPtr _drawfunc)
|
||||
{
|
||||
threadInfo *t = new threadInfo;
|
||||
t->status = new threadStatus;
|
||||
t->finished = false;
|
||||
t->drawFunc = _drawfunc;
|
||||
t->argPtr = args;
|
||||
|
||||
if(R_SUCCEEDED(threadCreate(&t->thrd, func, t, NULL, 0x8000, 0x2B, 1)))
|
||||
{
|
||||
mutexLock(&threadLock);
|
||||
threads.push_back(t);
|
||||
mutexUnlock(&threadLock);
|
||||
return threads[threads.size() - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
delete t->status;
|
||||
delete t;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ui::threadProcMngr::update()
|
||||
{
|
||||
if(!threads.empty())
|
||||
{
|
||||
threadInfo *t = threads[0];
|
||||
if(t->running == false && t->finished == false)
|
||||
{
|
||||
t->running = true;
|
||||
threadStart(&t->thrd);
|
||||
}
|
||||
else if(t->running == true && t->finished == true)
|
||||
{
|
||||
threadWaitForExit(&t->thrd);
|
||||
threadClose(&t->thrd);
|
||||
delete t->status;
|
||||
delete t;
|
||||
mutexLock(&threadLock);
|
||||
threads.erase(threads.begin());
|
||||
mutexUnlock(&threadLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::threadProcMngr::draw()
|
||||
{
|
||||
if(++frameCount % 4 == 0 && ++lgFrame > 7)
|
||||
lgFrame = 0;
|
||||
|
||||
gfx::drawRect(NULL, &darkenBack, 0, 0, 1280, 720);
|
||||
gfx::drawTextf(NULL, 32, 56, 673, &ui::loadGlyphClr, loadGlyphArray[lgFrame].c_str());
|
||||
if(threads[0]->drawFunc)
|
||||
(*(threads[0]->drawFunc))(threads[0]);
|
||||
else
|
||||
{
|
||||
std::string gStatus;
|
||||
threads[0]->status->getStatus(gStatus);
|
||||
|
||||
int statX = 640 - (gfx::getTextWidth(gStatus.c_str(), 18) / 2);
|
||||
gfx::drawTextf(NULL, 18, statX, 387, &ui::txtCont, gStatus.c_str());
|
||||
}
|
||||
}
|
||||
105
src/ui/ttl.cpp
105
src/ui/ttl.cpp
|
|
@ -11,6 +11,7 @@ static ui::menu *ttlOpts, *fldMenu;
|
|||
static ui::slideOutPanel *ttlOptsPanel, *infoPanel, *fldPanel;//There's no reason to have a separate folder section
|
||||
static fs::dirList *fldList;
|
||||
static fs::backupArgs *backargs;
|
||||
static ui::confirmArgs *overwriteArgs, *deleteArgs, *restArgs;
|
||||
static std::string infoPanelString;
|
||||
|
||||
void ui::refreshAllViews()
|
||||
|
|
@ -30,6 +31,10 @@ void ui::populateFldMenu()
|
|||
fs::loadPathFilters(targetDir + "pathFilters.txt");
|
||||
|
||||
*backargs = {fldMenu, fldList};
|
||||
//todo: text stuff
|
||||
*overwriteArgs = {"Overwrite?", data::config["holdOver"], false, fs::overwriteBackup, backargs};
|
||||
*deleteArgs = {"Delete?", data::config["holdDel"], false, fs::deleteBackup, backargs};
|
||||
*restArgs = {"Restore?", data::config["holdRest"], false, fs::restoreBackup, backargs};
|
||||
|
||||
fldMenu->addOpt(NULL, "New");
|
||||
fldMenu->optAddButtonEvent(0, HidNpadButton_A, fs::createNewBackup, backargs);
|
||||
|
|
@ -38,9 +43,9 @@ void ui::populateFldMenu()
|
|||
{
|
||||
fldMenu->addOpt(NULL, fldList->getItem(i));
|
||||
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_A, fs::overwriteBackup, backargs);
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_X, fs::deleteBackup, backargs);
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_Y, fs::restoreBackup, backargs);
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_A, confirm, overwriteArgs);
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_X, confirm, deleteArgs);
|
||||
fldMenu->optAddButtonEvent(i + 1, HidNpadButton_Y, confirm, restArgs);
|
||||
}
|
||||
|
||||
fldMenu->setActive(true);
|
||||
|
|
@ -115,38 +120,46 @@ static void ttlOptsShowInfoPanel(void *a)
|
|||
static void ttlOptsBlacklistTitle(void *a)
|
||||
{
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(false, ui::confBlacklist.c_str(), title.c_str()))
|
||||
{
|
||||
data::blacklistAdd(data::curData.saveID);
|
||||
ui::refreshAllViews();
|
||||
}
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(false, NULL, NULL, true, ui::confBlacklist.c_str(), title.c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
||||
static void ttlOptsDefinePath(void *a)
|
||||
{
|
||||
uint64_t tid = data::curData.saveID;
|
||||
std::string safeTitle = data::getTitleInfoByTID(tid)->safeTitle;
|
||||
std::string newSafeTitle = util::getStringInput(safeTitle, "Input New Output Folder", 0x200, 0, NULL);
|
||||
std::string newSafeTitle = util::getStringInput(SwkbdType_QWERTY, safeTitle, "Input New Output Folder", 0x200, 0, NULL);
|
||||
if(!newSafeTitle.empty())
|
||||
data::pathDefAdd(tid, newSafeTitle);
|
||||
}
|
||||
|
||||
static void ttlOptsResetSaveData_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
t->status->setStatus("Resetting save data for " + title + "...");
|
||||
|
||||
fs::mountSave(data::curData.saveInfo);
|
||||
fs::delDir("sv:/");
|
||||
fsdevCommitDevice("sv:/");
|
||||
fs::unmountSave();
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataResetSuccess.c_str(), title.c_str());
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
static void ttlOptsResetSaveData(void *a)
|
||||
{
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(data::config["holdDel"], ui::saveDataReset.c_str(), title.c_str()) && fs::mountSave(data::curData.saveInfo))
|
||||
{
|
||||
fs::delDir("sv:/");
|
||||
fsdevCommitDevice("sv:/");
|
||||
fs::unmountSave();
|
||||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataResetSuccess.c_str(), title.c_str());
|
||||
}
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(data::config["holdDel"], ttlOptsResetSaveData_t, NULL, true, ui::saveDataReset.c_str(), title.c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
||||
static void ttlOptsDeleteSaveData(void *a)
|
||||
static void ttlOptsDeleteSaveData_t(void *a)
|
||||
{
|
||||
threadInfo *t = (threadInfo *)a;
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(data::config["holdDel"], ui::confEraseNand.c_str(), title.c_str()) && R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id, data::curData.saveInfo.save_data_id)))
|
||||
t->status->setStatus("Deleting save data for " + title + "...");
|
||||
if(R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id, data::curData.saveInfo.save_data_id)))
|
||||
{
|
||||
data::loadUsersTitles(false);
|
||||
if(data::curUser.titleInfo.size() == 0)
|
||||
|
|
@ -161,25 +174,61 @@ static void ttlOptsDeleteSaveData(void *a)
|
|||
ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataDeleteSuccess.c_str(), title.c_str());
|
||||
ttlViews[data::selUser]->refresh();
|
||||
}
|
||||
t->finished = true;
|
||||
}
|
||||
|
||||
static void ttlOptsDeleteSaveData(void *a)
|
||||
{
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(data::config["holdDel"], ttlOptsDeleteSaveData_t, NULL, true, ui::confEraseNand.c_str(), title.c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
||||
static void ttlOptsExtendSaveData_t(void *a)
|
||||
{
|
||||
threadInfo *w = (threadInfo *)a;
|
||||
std::string expSizeStr = util::getStringInput("", "Enter New Size in MB", 4, 0, NULL);
|
||||
std::string expSizeStr = util::getStringInput(SwkbdType_NumPad, "", "Enter New Size in MB", 4, 0, NULL);
|
||||
if(!expSizeStr.empty())
|
||||
{
|
||||
data::titleInfo *extend = data::getTitleInfoByTID(data::curData.saveID);
|
||||
w->updateStatus("Expanding save filesystem for " + extend->title);
|
||||
w->status->setStatus("Expanding save filesystem for " + extend->title);
|
||||
uint64_t expMB = strtoul(expSizeStr.c_str(), NULL, 10);
|
||||
FsSaveDataSpaceId space = (FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id;
|
||||
uint64_t sid = data::curData.saveInfo.save_data_id;
|
||||
int64_t expSize = expMB * 1024 * 1024;
|
||||
int64_t journ = 0;
|
||||
if(extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size)
|
||||
journ = extend->nacp.user_account_save_data_journal_size_max;
|
||||
else
|
||||
journ = extend->nacp.user_account_save_data_journal_size;
|
||||
switch(data::curData.saveInfo.save_data_type)
|
||||
{
|
||||
case FsSaveDataType_Account:
|
||||
if(extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size)
|
||||
journ = extend->nacp.user_account_save_data_journal_size_max;
|
||||
else
|
||||
journ = extend->nacp.user_account_save_data_journal_size;
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Bcat:
|
||||
journ = extend->nacp.bcat_delivery_cache_storage_size;
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Cache:
|
||||
if(extend->nacp.cache_storage_data_and_journal_size_max > extend->nacp.cache_storage_journal_size)
|
||||
journ = extend->nacp.cache_storage_data_and_journal_size_max;
|
||||
else
|
||||
journ = extend->nacp.cache_storage_journal_size;
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Device:
|
||||
if(extend->nacp.device_save_data_journal_size_max > extend->nacp.device_save_data_journal_size)
|
||||
journ = extend->nacp.device_save_data_journal_size_max;
|
||||
else
|
||||
journ = extend->nacp.device_save_data_journal_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
//will just fail
|
||||
journ = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Result res = 0;
|
||||
if(R_FAILED(res = fsExtendSaveDataFileSystem(space, sid, expSize, journ)))
|
||||
|
|
@ -198,7 +247,7 @@ static void ttlOptsExtendSaveData_t(void *a)
|
|||
|
||||
static void ttlOptsExtendSaveData(void *a)
|
||||
{
|
||||
ui::newThread(ttlOptsExtendSaveData_t, NULL);
|
||||
ui::newThread(ttlOptsExtendSaveData_t, NULL, NULL);
|
||||
}
|
||||
|
||||
static void infoPanelDraw(void *a)
|
||||
|
|
@ -272,6 +321,9 @@ void ui::ttlInit()
|
|||
|
||||
fldList = new fs::dirList;
|
||||
backargs = new fs::backupArgs;
|
||||
overwriteArgs = new ui::confirmArgs;
|
||||
deleteArgs = new ui::confirmArgs;
|
||||
restArgs = new ui::confirmArgs;
|
||||
|
||||
ttlOpts->setActive(false);
|
||||
ttlOpts->addOpt(NULL, ui::titleOptString[0]);
|
||||
|
|
@ -301,6 +353,9 @@ void ui::ttlExit()
|
|||
delete fldMenu;
|
||||
delete fldList;
|
||||
delete backargs;
|
||||
delete overwriteArgs;
|
||||
delete deleteArgs;
|
||||
delete restArgs;
|
||||
}
|
||||
|
||||
void ui::ttlSetActive(int usr)
|
||||
|
|
|
|||
177
src/ui/ttlview.cpp
Normal file
177
src/ui/ttlview.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include "ui.h"
|
||||
#include "ui/ttlview.h"
|
||||
|
||||
//Todo make less hardcoded
|
||||
void ui::titleTile::draw(SDL_Texture *target, int x, int y, bool sel)
|
||||
{
|
||||
unsigned xScale = w * 1.28, yScale = h * 1.28;
|
||||
if(sel)
|
||||
{
|
||||
if(wS < xScale)
|
||||
wS += 18;
|
||||
if(hS < yScale)
|
||||
hS += 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(wS > w)
|
||||
wS -= 9;
|
||||
if(hS > h)
|
||||
hS -= 9;
|
||||
}
|
||||
|
||||
int dX = x - ((wS - w) / 2);
|
||||
int dY = y - ((hS - h) / 2);
|
||||
gfx::texDrawStretch(target, icon, dX, dY, wS, hS);
|
||||
if(fav)
|
||||
gfx::drawTextf(target, 20, dX + 8, dY + 8, &ui::heartColor, "♥");
|
||||
}
|
||||
|
||||
ui::titleview::titleview(const data::user& _u, int _iconW, int _iconH, int _horGap, int _vertGap, int _rowCount, funcPtr _callback)
|
||||
{
|
||||
iconW = _iconW;
|
||||
iconH = _iconH;
|
||||
horGap = _horGap;
|
||||
vertGap = _vertGap;
|
||||
rowCount = _rowCount;
|
||||
callback = _callback;
|
||||
u = &_u;
|
||||
|
||||
for(const data::userTitleInfo& t : u->titleInfo)
|
||||
tiles.emplace_back(new ui::titleTile(_iconW, _iconH, data::isFavorite(t.saveID), data::getTitleIconByTID(t.saveID)));
|
||||
}
|
||||
|
||||
ui::titleview::~titleview()
|
||||
{
|
||||
for(ui::titleTile *t : tiles)
|
||||
delete t;
|
||||
}
|
||||
|
||||
void ui::titleview::refresh()
|
||||
{
|
||||
for(ui::titleTile *t : tiles)
|
||||
delete t;
|
||||
|
||||
tiles.clear();
|
||||
for(const data::userTitleInfo& t : u->titleInfo)
|
||||
tiles.emplace_back(new ui::titleTile(iconW, iconH, data::isFavorite(t.saveID), data::getTitleIconByTID(t.saveID)));
|
||||
|
||||
if(selected > (int)tiles.size() - 1 && selected > 0)
|
||||
selected = tiles.size() - 1;
|
||||
}
|
||||
|
||||
void ui::titleview::update()
|
||||
{
|
||||
if(selected > (int)tiles.size() - 1 && selected > 0)
|
||||
selected = tiles.size() - 1;
|
||||
|
||||
if(!active)
|
||||
return;
|
||||
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_StickLUp:
|
||||
case HidNpadButton_StickRUp:
|
||||
case HidNpadButton_Up:
|
||||
if((selected -= rowCount) < 0)
|
||||
selected = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLDown:
|
||||
case HidNpadButton_StickRDown:
|
||||
case HidNpadButton_Down:
|
||||
if((selected += rowCount) > (int)(tiles.size() - 1))
|
||||
selected = tiles.size() - 1;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLLeft:
|
||||
case HidNpadButton_StickRLeft:
|
||||
case HidNpadButton_Left:
|
||||
if(selected > 0)
|
||||
--selected;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLRight:
|
||||
case HidNpadButton_StickRRight:
|
||||
case HidNpadButton_Right:
|
||||
if(selected < (int)(tiles.size() - 1))
|
||||
++selected;
|
||||
break;
|
||||
|
||||
case HidNpadButton_L:
|
||||
if((selected -= rowCount * 3) < 0)
|
||||
selected = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
if((selected += rowCount * 3) > (int)(tiles.size() - 1))
|
||||
selected = tiles.size() - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(callback)
|
||||
(*callback)(this);
|
||||
}
|
||||
|
||||
void ui::titleview::draw(SDL_Texture *target)
|
||||
{
|
||||
if(tiles.size() <= 0)
|
||||
return;
|
||||
|
||||
int tH = 0, tY = 0;
|
||||
SDL_QueryTexture(target, NULL, NULL, NULL, &tH);
|
||||
tY = tH - 214;
|
||||
if(selRectY > tY)
|
||||
{
|
||||
float add = ((float)tY - (float)selRectY) / ui::animScale;
|
||||
y += ceil(add);
|
||||
}
|
||||
else if(selRectY < 38)
|
||||
{
|
||||
float add = (38.0f - (float)selRectY) / ui::animScale;
|
||||
y += ceil(add);
|
||||
}
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrShft += 6;
|
||||
if(clrShft >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrShft -= 3;
|
||||
if(clrShft <= 0)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
int totalTitles = tiles.size(), selX = 32, selY = 64;
|
||||
for(int tY = y, i = 0; i < totalTitles; tY += iconH + vertGap)
|
||||
{
|
||||
int endRow = i + rowCount;
|
||||
for(int tX = x; i < endRow; tX += iconW + horGap, i++)
|
||||
{
|
||||
if(i >= totalTitles)
|
||||
break;
|
||||
|
||||
if(i == selected)
|
||||
{
|
||||
//save x and y for later so it's draw over top
|
||||
selX = tX;
|
||||
selY = tY;
|
||||
selRectX = tX - 24;
|
||||
selRectY = tY - 24;
|
||||
}
|
||||
else
|
||||
tiles[i]->draw(target, tX, tY, false);
|
||||
}
|
||||
}
|
||||
|
||||
if(showSel)
|
||||
{
|
||||
ui::drawBoundBox(target, selRectX, selRectY, 176, 176, clrShft);
|
||||
tiles[selected]->draw(target, selX, selY, true);
|
||||
}
|
||||
else
|
||||
tiles[selected]->draw(target, selX, selY, false);
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ static void usrOptDeleteAllUserSaves_t(void *a)
|
|||
data::user *u = &data::users[data::selUser];
|
||||
for(data::userTitleInfo& tinf : u->titleInfo)
|
||||
{
|
||||
*t->status = "Deleting " + data::getTitleNameByTID(tinf.saveID);
|
||||
t->status->setStatus("Deleting " + data::getTitleNameByTID(tinf.saveID));
|
||||
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tinf.saveInfo.save_data_id);;
|
||||
}
|
||||
data::loadUsersTitles(false);
|
||||
|
|
@ -146,8 +146,8 @@ static void usrOptDeleteAllUserSaves_t(void *a)
|
|||
static void usrOptDeleteAllUserSaves(void *a)
|
||||
{
|
||||
data::user *u = &data::users[data::selUser];
|
||||
if(ui::confirm(true, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*", u->getUsername().c_str()))
|
||||
ui::newThread(usrOptDeleteAllUserSaves_t, NULL);
|
||||
ui::confirmArgs *conf = ui::confirmArgsCreate(true, usrOptDeleteAllUserSaves_t, NULL, true, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*", u->getUsername().c_str());
|
||||
ui::confirm(conf);
|
||||
}
|
||||
|
||||
static void usrOptPanelDraw(void *a)
|
||||
|
|
@ -211,7 +211,7 @@ static void createSaveData_t(void *a)
|
|||
break;
|
||||
}
|
||||
data::titleInfo *create = data::getTitleInfoByTID(sid);
|
||||
t->updateStatus("Creating save data for " + create->title);
|
||||
t->status->setStatus("Creating save data for " + create->title);
|
||||
|
||||
FsSaveDataAttribute attr;
|
||||
memset(&attr, 0, sizeof(FsSaveDataAttribute));
|
||||
|
|
@ -220,7 +220,14 @@ static void createSaveData_t(void *a)
|
|||
attr.system_save_data_id = 0;
|
||||
attr.save_data_type = type;
|
||||
attr.save_data_rank = 0;
|
||||
attr.save_data_index = 0;//Todo: Let user input this
|
||||
|
||||
uint16_t index = 0;
|
||||
if(type == FsSaveDataType_Cache)
|
||||
{
|
||||
std::string getIndex = util::getStringInput(SwkbdType_NumPad, "", "Input Cache save index", 2, 0, NULL);
|
||||
index = strtoul(getIndex.c_str(), 0, 10);
|
||||
}
|
||||
attr.save_data_index = index;
|
||||
|
||||
FsSaveDataCreationInfo svCreate;
|
||||
memset(&svCreate, 0, sizeof(FsSaveDataCreationInfo));
|
||||
|
|
@ -239,7 +246,7 @@ static void createSaveData_t(void *a)
|
|||
|
||||
case FsSaveDataType_Bcat:
|
||||
saveSize = create->nacp.bcat_delivery_cache_storage_size;
|
||||
journalSize = create->nacp.bcat_delivery_cache_storage_size;//This needs to be fixed
|
||||
journalSize = create->nacp.bcat_delivery_cache_storage_size;
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Cache:
|
||||
|
|
@ -280,7 +287,7 @@ static void createSaveData_t(void *a)
|
|||
|
||||
static void createSaveData(void *a)
|
||||
{
|
||||
ui::newThread(createSaveData_t, a);
|
||||
ui::newThread(createSaveData_t, a, NULL);
|
||||
}
|
||||
|
||||
void ui::usrInit()
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ std::string util::getInfoString(data::user& u, const uint64_t& tid)
|
|||
|
||||
case FsSaveDataType_Cache:
|
||||
ret += "Cache Storage\n";
|
||||
ret += "Save Index: " + std::to_string(data::curData.saveInfo.save_data_index) + "\n";
|
||||
break;
|
||||
|
||||
case FsSaveDataType_SystemBcat:
|
||||
|
|
@ -238,7 +239,7 @@ std::string util::getInfoString(data::user& u, const uint64_t& tid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string util::getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[])
|
||||
std::string util::getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[])
|
||||
{
|
||||
SwkbdConfig swkbd;
|
||||
swkbdCreate(&swkbd, dictCnt);
|
||||
|
|
@ -247,7 +248,7 @@ std::string util::getStringInput(const std::string& def, const std::string& head
|
|||
swkbdConfigSetHeaderText(&swkbd, head.c_str());
|
||||
swkbdConfigSetGuideText(&swkbd, head.c_str());
|
||||
swkbdConfigSetInitialCursorPos(&swkbd, SwkbdPosEnd);
|
||||
swkbdConfigSetType(&swkbd, SwkbdType_QWERTY);
|
||||
swkbdConfigSetType(&swkbd, _type);
|
||||
swkbdConfigSetStringLenMax(&swkbd, maxLength);
|
||||
swkbdConfigSetKeySetDisableBitmask(&swkbd, SwkbdKeyDisableBitmask_Backslash | SwkbdKeyDisableBitmask_ForwardSlash | SwkbdKeyDisableBitmask_Percent);
|
||||
swkbdConfigSetDicFlag(&swkbd, 1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user