implement file picker in iOS with .ext to UTI filtering

This commit is contained in:
2019-09-09 15:31:47 +02:00
parent 4b3b1749d6
commit 096930b02e
5 changed files with 83 additions and 46 deletions

View File

@@ -155,6 +155,7 @@
AD7FB09022470C75005913AB /* node_panel_floating.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB08E22470C75005913AB /* node_panel_floating.cpp */; }; AD7FB09022470C75005913AB /* node_panel_floating.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB08E22470C75005913AB /* node_panel_floating.cpp */; };
AD7FB09222470DE5005913AB /* app_vr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB09122470DE2005913AB /* app_vr.cpp */; }; AD7FB09222470DE5005913AB /* app_vr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB09122470DE2005913AB /* app_vr.cpp */; };
AD7FB09322470DE5005913AB /* app_vr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB09122470DE2005913AB /* app_vr.cpp */; }; AD7FB09322470DE5005913AB /* app_vr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7FB09122470DE2005913AB /* app_vr.cpp */; };
AD83A0D323268B6F005B0871 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD83A0D223268B6F005B0871 /* MobileCoreServices.framework */; };
ADA2A57822BE8D8E00C6B6C9 /* node_tool_bucket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA2A57622BE8D8E00C6B6C9 /* node_tool_bucket.cpp */; }; ADA2A57822BE8D8E00C6B6C9 /* node_tool_bucket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA2A57622BE8D8E00C6B6C9 /* node_tool_bucket.cpp */; };
ADA2A57922BE8D8E00C6B6C9 /* node_tool_bucket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA2A57622BE8D8E00C6B6C9 /* node_tool_bucket.cpp */; }; ADA2A57922BE8D8E00C6B6C9 /* node_tool_bucket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA2A57622BE8D8E00C6B6C9 /* node_tool_bucket.cpp */; };
ADA3ABF6222C8C370083B825 /* node_panel_quick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA3ABF4222C8C350083B825 /* node_panel_quick.cpp */; }; ADA3ABF6222C8C370083B825 /* node_panel_quick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADA3ABF4222C8C350083B825 /* node_panel_quick.cpp */; };
@@ -460,6 +461,7 @@
AD7FB08D22470C74005913AB /* node_panel_floating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = node_panel_floating.h; sourceTree = "<group>"; }; AD7FB08D22470C74005913AB /* node_panel_floating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = node_panel_floating.h; sourceTree = "<group>"; };
AD7FB08E22470C75005913AB /* node_panel_floating.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_panel_floating.cpp; sourceTree = "<group>"; }; AD7FB08E22470C75005913AB /* node_panel_floating.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_panel_floating.cpp; sourceTree = "<group>"; };
AD7FB09122470DE2005913AB /* app_vr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_vr.cpp; sourceTree = "<group>"; }; AD7FB09122470DE2005913AB /* app_vr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_vr.cpp; sourceTree = "<group>"; };
AD83A0D223268B6F005B0871 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.4.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };
AD8CF71F1E913F0500083FFD /* log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = "<group>"; }; AD8CF71F1E913F0500083FFD /* log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = "<group>"; };
AD8CF7201E913F0500083FFD /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; }; AD8CF7201E913F0500083FFD /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
AD95AEC31E41EDEC002DD03A /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = "<group>"; }; AD95AEC31E41EDEC002DD03A /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = "<group>"; };
@@ -588,6 +590,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
AD83A0D323268B6F005B0871 /* MobileCoreServices.framework in Frameworks */,
ADC8F77F216678270084ECAD /* CoreTelephony.framework in Frameworks */, ADC8F77F216678270084ECAD /* CoreTelephony.framework in Frameworks */,
ADC8F780216678270084ECAD /* CoreText.framework in Frameworks */, ADC8F780216678270084ECAD /* CoreText.framework in Frameworks */,
ADC8F781216678270084ECAD /* QuartzCore.framework in Frameworks */, ADC8F781216678270084ECAD /* QuartzCore.framework in Frameworks */,
@@ -892,6 +895,7 @@
AD759B631F2793AD00211963 /* Frameworks */ = { AD759B631F2793AD00211963 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
AD83A0D223268B6F005B0871 /* MobileCoreServices.framework */,
ADF396DB216F6BD800024722 /* AppKit.framework */, ADF396DB216F6BD800024722 /* AppKit.framework */,
ADFD32232166B12A00F46F85 /* Foundation.framework */, ADFD32232166B12A00F46F85 /* Foundation.framework */,
AD06989820CC6C3E0010825F /* OSX */, AD06989820CC6C3E0010825F /* OSX */,

View File

@@ -16,19 +16,24 @@
@interface GameViewController : UIViewController< @interface GameViewController : UIViewController<
UIKeyInput, UIKeyInput,
UIImagePickerControllerDelegate, UIImagePickerControllerDelegate,
UIDocumentPickerDelegate,
UINavigationControllerDelegate, UINavigationControllerDelegate,
UIDocumentInteractionControllerDelegate UIDocumentInteractionControllerDelegate
> >
{ {
@public GameView* glview; @public GameView* glview;
@public EAGLContext* context; @public EAGLContext* context;
@public bool input_enabled;
} }
- (void)show_keyboard;
- (void)hide_keyboard;
- (void)display_file:(std::string)filename; - (void)display_file:(std::string)filename;
- (void)reset_touch; - (void)reset_touch;
- (void)async_lock; - (void)async_lock;
- (void)async_unlock; - (void)async_unlock;
- (void)async_swap; - (void)async_swap;
- (void)pick_photo:(std::function<void(std::string)>) callback; - (void)pick_photo:(std::function<void(std::string)>) callback;
- (void)pick_file:(NSArray<NSString*>*)types then:(std::function<void(std::string)>)callback;
- (void)registerForKeyboardNotifications; - (void)registerForKeyboardNotifications;
- (void)unregisterForKeyboardNotifications; - (void)unregisterForKeyboardNotifications;
- (void)crash; - (void)crash;

View File

@@ -12,6 +12,7 @@
#include "app.h" #include "app.h"
#include "settings.h" #include "settings.h"
#import "objc_utils.h" #import "objc_utils.h"
#import <MobileCoreServices/MobileCoreServices.h>
std::mutex render_mutex; std::mutex render_mutex;
std::condition_variable render_cv; std::condition_variable render_cv;
@@ -25,6 +26,15 @@ std::condition_variable render_cv;
@implementation GameImagePicker @implementation GameImagePicker
@end @end
@interface GameFilePicker : UIDocumentPickerViewController
{
@public std::promise<std::string> promise;
@public std::function<void(std::string)> callback;
}
@end
@implementation GameFilePicker
@end
//std::map< //std::map<
bool pen_down = false; bool pen_down = false;
int t_count = 0; int t_count = 0;
@@ -152,15 +162,41 @@ std::recursive_mutex lock_mutex;
GameImagePicker* p = static_cast<GameImagePicker*>(picker); GameImagePicker* p = static_cast<GameImagePicker*>(picker);
std::string path = [chosenImage cStringUsingEncoding:NSUTF8StringEncoding]; std::string path = [chosenImage cStringUsingEncoding:NSUTF8StringEncoding];
p->callback(path); p->callback(path);
[picker dismissViewControllerAnimated:YES completion:^{ [picker dismissViewControllerAnimated:YES completion:NULL];
[self keyboardWasHidden:nil];
}];
} }
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{ {
[picker dismissViewControllerAnimated:YES completion:^{ [picker dismissViewControllerAnimated:YES completion:NULL];
[self keyboardWasHidden:nil]; }
}];
- (void)pick_file:(NSArray<NSString*>*)types then:(std::function<void(std::string)>)callback
{
// convert extension into UTIs from the system database
NSMutableArray* UTIs = [NSMutableArray arrayWithCapacity:types.count];
for (NSString* ext : types)
{
NSString *typeForExt = (__bridge NSString*)
UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
(__bridge CFStringRef)ext, NULL);
[UTIs addObject:typeForExt];
}
GameFilePicker *picker = [[GameFilePicker alloc] initWithDocumentTypes:UTIs inMode:UIDocumentPickerModeImport];
picker.delegate = self;
picker->callback = callback;
[self presentViewController:picker animated:YES completion:NULL];
}
-(void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url
{
NSString *chosenImage = [url path];
GameFilePicker* p = static_cast<GameFilePicker*>(controller);
std::string path = [chosenImage cStringUsingEncoding:NSUTF8StringEncoding];
p->callback(path);
[controller dismissViewControllerAnimated:YES completion:NULL];
}
-(void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller
{
[controller dismissViewControllerAnimated:YES completion:NULL];
} }
- (void)insertText:(NSString *)text - (void)insertText:(NSString *)text
@@ -185,7 +221,19 @@ std::recursive_mutex lock_mutex;
return YES; return YES;
} }
- (BOOL)canBecomeFirstResponder { - (BOOL)canBecomeFirstResponder {
return YES; return input_enabled;
}
-(void)show_keyboard
{
input_enabled = YES;
[self becomeFirstResponder];
}
-(void)hide_keyboard
{
input_enabled = NO;
[self resignFirstResponder];
} }
// Call this method somewhere in your view controller setup code. // Call this method somewhere in your view controller setup code.
@@ -416,6 +464,7 @@ std::set<UITouch*> ignored_touch;
- (void)viewDidLoad - (void)viewDidLoad
{ {
[super viewDidLoad]; [super viewDidLoad];
input_enabled = NO;
App::I = new App; App::I = new App;
App::I->ios_view = self; App::I->ios_view = self;
App::I->initLog(); App::I->initLog();

View File

@@ -105,8 +105,7 @@ void App::showKeyboard()
redraw = true; redraw = true;
#ifdef __IOS__ #ifdef __IOS__
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
//[ios_view registerForKeyboardNotifications]; [ios_view show_keyboard];
[ios_view becomeFirstResponder];
}); });
#elif __ANDROID__ #elif __ANDROID__
displayKeyboard(true); displayKeyboard(true);
@@ -119,8 +118,7 @@ void App::hideKeyboard()
redraw = true; redraw = true;
#ifdef __IOS__ #ifdef __IOS__
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[ios_view resignFirstResponder]; [ios_view hide_keyboard];
// [ios_view unregisterForKeyboardNotifications];
}); });
#elif __ANDROID__ #elif __ANDROID__
displayKeyboard(false); displayKeyboard(false);
@@ -154,14 +152,14 @@ void App::pick_file(std::vector<std::string> types, std::function<void (std::str
{ {
redraw = true; redraw = true;
#ifdef __IOS__ #ifdef __IOS__
// not implemented on ios
// fallback to pick_image
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_photo:callback]; NSMutableArray<NSString*>* fileTypes = [NSMutableArray arrayWithCapacity:types.size()];
for (const auto& t : types)
[fileTypes addObject:[NSString stringWithCString:t.c_str() encoding:NSUTF8StringEncoding]];
[ios_view pick_file:fileTypes then:callback];
}); });
#elif __OSX__ #elif __OSX__
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
//NSArray* fileTypes = [NSArray arrayWithObjects:@"ppi", @"PPI", nil];
NSMutableArray<NSString*>* fileTypes = [NSMutableArray arrayWithCapacity:types.size()]; NSMutableArray<NSString*>* fileTypes = [NSMutableArray arrayWithCapacity:types.size()];
for (const auto& t : types) for (const auto& t : types)
[fileTypes addObject:[NSString stringWithCString:t.c_str() encoding:NSUTF8StringEncoding]]; [fileTypes addObject:[NSString stringWithCString:t.c_str() encoding:NSUTF8StringEncoding]];
@@ -198,10 +196,8 @@ void App::pick_file_save(std::vector<std::string> types, std::function<void (std
{ {
redraw = true; redraw = true;
#ifdef __IOS__ #ifdef __IOS__
// not implemented on ios
// fallback to pick_image
// dispatch_async(dispatch_get_main_queue(), ^{ // dispatch_async(dispatch_get_main_queue(), ^{
// [ios_view pick_photo:callback]; // [ios_view pick_file_save:callback];
// }); // });
#elif __OSX__ #elif __OSX__
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{

View File

@@ -525,22 +525,7 @@ void App::init_menu_file()
}; };
if (auto b = popup->find<NodeButtonCustom>("file-import")) if (auto b = popup->find<NodeButtonCustom>("file-import"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup](Node*) {
pick_file({ "JPG", "PNG", "ABR" }, [this](std::string path){ pick_image([this](std::string path){
std::string name, base, ext;
std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return;
base = m[1].str();
name = m[2].str();
ext = m[3].str();
if (str_iequals(ext, "abr"))
{
std::thread([this,path] { presets->import_abr(path); }).detach();
}
else
{
Image img; Image img;
img.load_file(path); img.load_file(path);
if (img.width == img.height / 6 || img.width == img.height * 2) if (img.width == img.height / 6 || img.width == img.height * 2)
@@ -554,8 +539,6 @@ void App::init_menu_file()
m->m_source_image = std::move(img); m->m_source_image = std::move(img);
Canvas::set_mode(kCanvasMode::Import); Canvas::set_mode(kCanvasMode::Import);
} }
async_redraw();
}
}); });
popup->mouse_release(); popup->mouse_release();
popup->destroy(); popup->destroy();