GUI; mobile file dialog improvements

This commit is contained in:
tildearrow 2022-12-02 16:52:47 -05:00
parent dc7aec2dc1
commit 4e88a677d0
9 changed files with 60 additions and 22 deletions

View file

@ -1,25 +1,29 @@
package org.tildearrow.furnace; package org.tildearrow.furnace;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.widget.Toast;
import org.libsdl.app.SDLActivity; import org.libsdl.app.SDLActivity;
public class MainActivity extends SDLActivity { public class MainActivity extends SDLActivity {
static final int TA_FILE_REQUEST=1000; static final int TA_FILE_REQUEST=1000;
public boolean showFileDialog() { public void showFileDialog() {
Intent picker=new Intent(Intent.ACTION_GET_CONTENT); Intent picker=new Intent(Intent.ACTION_GET_CONTENT);
picker.setType("*/*"); picker.setType("*/*");
picker=Intent.createChooser(picker,"test"); picker=Intent.createChooser(picker,"test");
startActivityForResult(picker,TA_FILE_REQUEST); startActivityForResult(picker,TA_FILE_REQUEST);
return true;
} }
@Override protected void onActivityResult(int request, int result, Intent intent) { @Override protected void onActivityResult(int request, int result, Intent intent) {
super.onActivityResult(request,result,intent); super.onActivityResult(request,result,intent);
if (request==TA_FILE_REQUEST) { if (request==TA_FILE_REQUEST) {
// TODO: fire an event here if (result==RESULT_OK) {
Context context=getApplicationContext();
Toast toast=Toast.makeText(context,"Got a file",Toast.LENGTH_SHORT);
toast.show();
}
} }
} }
} }

View file

@ -79,6 +79,8 @@ SOFTWARE.
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#define DOUBLE_CLICKED ((singleClickSel && ImGui::IsMouseReleased(0)) || (!singleClickSel && ImGui::IsMouseDoubleClicked(0)))
#ifdef USE_THUMBNAILS #ifdef USE_THUMBNAILS
#ifndef DONT_DEFINE_AGAIN__STB_IMAGE_IMPLEMENTATION #ifndef DONT_DEFINE_AGAIN__STB_IMAGE_IMPLEMENTATION
#ifndef STB_IMAGE_IMPLEMENTATION #ifndef STB_IMAGE_IMPLEMENTATION
@ -3319,7 +3321,7 @@ namespace IGFD
//// FILE DIALOG CONSTRUCTOR / DESTRUCTOR /////////////////////////////////////////// //// FILE DIALOG CONSTRUCTOR / DESTRUCTOR ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
IGFD::FileDialog::FileDialog() : BookMarkFeature(), KeyExplorerFeature(), ThumbnailFeature() {DpiScale=1.0f;} IGFD::FileDialog::FileDialog() : BookMarkFeature(), KeyExplorerFeature(), ThumbnailFeature() {DpiScale=1.0f; singleClickSel=false;}
IGFD::FileDialog::~FileDialog() = default; IGFD::FileDialog::~FileDialog() = default;
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
@ -3972,7 +3974,7 @@ namespace IGFD
} }
else // no nav system => classic behavior else // no nav system => classic behavior
{ {
if (ImGui::IsMouseDoubleClicked(0)) // 0 -> left mouse button double click if (DOUBLE_CLICKED) // 0 -> left mouse button double click
{ {
isSelectingDir=true; isSelectingDir=true;
fdi.puPathClicked = fdi.SelectDirectory(vInfos); fdi.puPathClicked = fdi.SelectDirectory(vInfos);
@ -3987,7 +3989,7 @@ namespace IGFD
} }
else else
{ {
if (ImGui::IsMouseDoubleClicked(0)) { if (DOUBLE_CLICKED) {
fdi.SelectFileName(prFileDialogInternal, vInfos); fdi.SelectFileName(prFileDialogInternal, vInfos);
prFileDialogInternal.puIsOk = true; prFileDialogInternal.puIsOk = true;
return 2; return 2;

View file

@ -1142,6 +1142,7 @@ namespace IGFD
public: public:
bool puAnyWindowsHovered = false; // not remember why haha :) todo : to check if we can remove bool puAnyWindowsHovered = false; // not remember why haha :) todo : to check if we can remove
double DpiScale; double DpiScale;
bool singleClickSel;
public: public:
static FileDialog* Instance() // Singleton for easier accces form anywhere but only one dialog at a time static FileDialog* Instance() // Singleton for easier accces form anywhere but only one dialog at a time

View file

@ -116,7 +116,7 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
} }
jclass class_=jniEnv->GetObjectClass(activity); jclass class_=jniEnv->GetObjectClass(activity);
jmethodID showFileDialog=jniEnv->GetMethodID(class_,"showFileDialog","()B"); jmethodID showFileDialog=jniEnv->GetMethodID(class_,"showFileDialog","()V");
if (showFileDialog==NULL) { if (showFileDialog==NULL) {
logE("method showFileDialog not found!"); logE("method showFileDialog not found!");
@ -126,12 +126,12 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
return false; return false;
} }
jboolean mret=jniEnv->CallBooleanMethod(activity,showFileDialog); jniEnv->CallVoidMethod(activity,showFileDialog);
if (!(bool)mret) { /*if (!(bool)mret) {
hasError=true; hasError=true;
logW("could not open Android file picker..."); logW("could not open Android file picker...");
} }*/
jniEnv->DeleteLocalRef(class_); jniEnv->DeleteLocalRef(class_);
jniEnv->DeleteLocalRef(activity); jniEnv->DeleteLocalRef(activity);
@ -142,6 +142,7 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
#endif #endif
} else { } else {
hasError=false; hasError=false;
ImGuiFileDialog::Instance()->singleClickSel=singleClickSel;
ImGuiFileDialog::Instance()->DpiScale=dpiScale; ImGuiFileDialog::Instance()->DpiScale=dpiScale;
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,allowMultiple?999:1,nullptr,0,clickCallback); ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,allowMultiple?999:1,nullptr,0,clickCallback);
} }
@ -178,6 +179,7 @@ bool FurnaceGUIFileDialog::openSave(String header, std::vector<String> filter, c
#endif #endif
} else { } else {
hasError=false; hasError=false;
ImGuiFileDialog::Instance()->singleClickSel=false;
ImGuiFileDialog::Instance()->DpiScale=dpiScale; ImGuiFileDialog::Instance()->DpiScale=dpiScale;
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite); ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite);
} }

View file

@ -47,6 +47,7 @@ class FurnaceGUIFileDialog {
pfd::save_file* dialogS; pfd::save_file* dialogS;
#endif #endif
public: public:
bool singleClickSel;
bool openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback=NULL, bool allowMultiple=false); bool openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback=NULL, bool allowMultiple=false);
bool openSave(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale); bool openSave(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale);
bool accepted(); bool accepted();
@ -65,5 +66,6 @@ class FurnaceGUIFileDialog {
jniEnv(NULL), jniEnv(NULL),
#endif #endif
dialogO(NULL), dialogO(NULL),
dialogS(NULL) {} dialogS(NULL),
singleClickSel(false) {}
}; };

View file

@ -2630,10 +2630,12 @@ void FurnaceGUI::toggleMobileUI(bool enable, bool force) {
if (mobileUI) { if (mobileUI) {
ImGui::GetIO().IniFilename=NULL; ImGui::GetIO().IniFilename=NULL;
ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_InertialScrollEnable; ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_InertialScrollEnable;
fileDialog->singleClickSel=true;
} else { } else {
ImGui::GetIO().IniFilename=NULL; ImGui::GetIO().IniFilename=NULL;
ImGui::LoadIniSettingsFromDisk(finalLayoutPath); ImGui::LoadIniSettingsFromDisk(finalLayoutPath);
ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_InertialScrollEnable; ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_InertialScrollEnable;
fileDialog->singleClickSel=false;
} }
} }
} }
@ -5225,7 +5227,7 @@ bool FurnaceGUI::init() {
#endif #endif
// initialize SDL // initialize SDL
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO|SDL_INIT_HAPTIC);
const char* videoBackend=SDL_GetCurrentVideoDriver(); const char* videoBackend=SDL_GetCurrentVideoDriver();
if (videoBackend!=NULL) { if (videoBackend!=NULL) {
@ -5448,6 +5450,17 @@ bool FurnaceGUI::init() {
return curIns; return curIns;
}); });
vibrator=SDL_HapticOpen(0);
if (vibrator==NULL) {
logD("could not open vibration device: %s",SDL_GetError());
} else {
if (SDL_HapticRumbleInit(vibrator)==0) {
vibratorAvailable=true;
} else {
logD("vibration not available: %s",SDL_GetError());
}
}
return true; return true;
} }
@ -5578,6 +5591,10 @@ bool FurnaceGUI::finish() {
SDL_DestroyRenderer(sdlRend); SDL_DestroyRenderer(sdlRend);
SDL_DestroyWindow(sdlWin); SDL_DestroyWindow(sdlWin);
if (vibrator) {
SDL_HapticClose(vibrator);
}
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
delete oldPat[i]; delete oldPat[i];
} }
@ -5593,6 +5610,8 @@ FurnaceGUI::FurnaceGUI():
e(NULL), e(NULL),
sdlWin(NULL), sdlWin(NULL),
sdlRend(NULL), sdlRend(NULL),
vibrator(NULL),
vibratorAvailable(false),
sampleTex(NULL), sampleTex(NULL),
sampleTexW(0), sampleTexW(0),
sampleTexH(0), sampleTexH(0),
@ -5766,7 +5785,7 @@ FurnaceGUI::FurnaceGUI():
curWindowLast(GUI_WINDOW_NOTHING), curWindowLast(GUI_WINDOW_NOTHING),
curWindowThreadSafe(GUI_WINDOW_NOTHING), curWindowThreadSafe(GUI_WINDOW_NOTHING),
lastPatternWidth(0.0f), lastPatternWidth(0.0f),
longThreshold(0.4f), longThreshold(0.48f),
latchNote(-1), latchNote(-1),
latchIns(-2), latchIns(-2),
latchVol(-1), latchVol(-1),

View file

@ -53,10 +53,15 @@
_wi->std.waveMacro.vScroll=-1; \ _wi->std.waveMacro.vScroll=-1; \
} }
#define CHECK_LONG_HOLD (mobileUI && ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] && ImGui::GetIO().MouseDownDuration[ImGuiMouseButton_Left]>longThreshold && !ImGui::IsInertialScroll()) #define CHECK_LONG_HOLD (mobileUI && ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] && ImGui::GetIO().MouseDownDuration[ImGuiMouseButton_Left]>=longThreshold && ImGui::GetIO().MouseDownDurationPrev[ImGuiMouseButton_Left]<longThreshold && !ImGui::IsInertialScroll())
// for now // for now
#define NOTIFY_LONG_HOLD logV("long hold"); #define NOTIFY_LONG_HOLD \
if (vibrator && vibratorAvailable) { \
if (SDL_HapticRumblePlay(vibrator,0.5f,20)!=0) { \
logV("could not vibrate: %s!",SDL_GetError()); \
} \
}
#define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str() #define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str()
@ -1053,6 +1058,8 @@ class FurnaceGUI {
SDL_Window* sdlWin; SDL_Window* sdlWin;
SDL_Renderer* sdlRend; SDL_Renderer* sdlRend;
SDL_Haptic* vibrator;
bool vibratorAvailable;
SDL_Texture* sampleTex; SDL_Texture* sampleTex;
int sampleTexW, sampleTexH; int sampleTexW, sampleTexH;

View file

@ -128,7 +128,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(0,0,i,true); startSelection(0,0,i,true);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }
@ -182,7 +182,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,0,i); updateSelection(j,0,i);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }
@ -226,7 +226,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,1,i); updateSelection(j,1,i);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }
@ -264,7 +264,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,2,i); updateSelection(j,2,i);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }
@ -313,7 +313,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index-1,i); updateSelection(j,index-1,i);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }
@ -343,7 +343,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index,i); updateSelection(j,index,i);
} }
if (CHECK_LONG_HOLD) { if (ImGui::IsItemActive() && CHECK_LONG_HOLD) {
ImGui::InhibitInertialScroll(); ImGui::InhibitInertialScroll();
NOTIFY_LONG_HOLD; NOTIFY_LONG_HOLD;
} }

View file

@ -3290,6 +3290,7 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
ImGui::GetIO().ConfigInputTrickleEventQueue=settings.eventDelay; ImGui::GetIO().ConfigInputTrickleEventQueue=settings.eventDelay;
ImGui::GetIO().ConfigWindowsMoveFromTitleBarOnly=settings.moveWindowTitle; ImGui::GetIO().ConfigWindowsMoveFromTitleBarOnly=settings.moveWindowTitle;
ImGui::GetIO().ConfigInertialScrollToleranceSqr=pow(dpiScale*4.0f,2.0f);
for (int i=0; i<256; i++) { for (int i=0; i<256; i++) {
ImVec4& base=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH]; ImVec4& base=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH];