Browse Source

iOS: Make sure that native FileChooser is visible and is dismissed correctly when user taps outside the chooser window

tags/2021-05-28
ed 5 years ago
parent
commit
dd3c96b7e7
1 changed files with 77 additions and 36 deletions
  1. +77
    -36
      modules/juce_gui_basics/native/juce_ios_FileChooser.mm

+ 77
- 36
modules/juce_gui_basics/native/juce_ios_FileChooser.mm View File

@@ -26,19 +26,22 @@
namespace juce
{
class FileChooser::Native : private Component,
public FileChooser::Pimpl
class FileChooser::Native : public FileChooser::Pimpl,
public Component,
private AsyncUpdater
{
public:
Native (FileChooser& fileChooser, int flags)
: owner (fileChooser)
{
String firstFileExtension;
static FileChooserDelegateClass cls;
delegate.reset ([cls.createInstance() init]);
static FileChooserDelegateClass delegateClass;
delegate.reset ([delegateClass.createInstance() init]);
FileChooserDelegateClass::setOwner (delegate.get(), this);
static FileChooserControllerClass controllerClass;
auto* controllerClassInstance = controllerClass.createInstance();
String firstFileExtension;
auto utTypeArray = createNSArrayFromStringArray (getUTTypesForWildcards (owner.filters, firstFileExtension));
if ((flags & FileBrowserComponent::saveMode) != 0)
@@ -69,47 +72,51 @@ public:
}
auto url = [[NSURL alloc] initFileURLWithPath: juceStringToNS (currentFileOrDirectory.getFullPathName())];
controller.reset ([[UIDocumentPickerViewController alloc] initWithURL: url
inMode: pickerMode]);
controller.reset ([controllerClassInstance initWithURL: url
inMode: pickerMode]);
[url release];
}
else
{
controller.reset ([[UIDocumentPickerViewController alloc] initWithDocumentTypes: utTypeArray
inMode: UIDocumentPickerModeOpen]);
controller.reset ([controllerClassInstance initWithDocumentTypes: utTypeArray
inMode: UIDocumentPickerModeOpen]);
}
FileChooserControllerClass::setOwner (controller.get(), this);
[controller.get() setDelegate: delegate.get()];
[controller.get() setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
setOpaque (false);
if (SystemStats::isRunningInAppExtensionSandbox())
if (fileChooser.parent != nullptr)
{
if (fileChooser.parent != nullptr)
{
[controller.get() setModalPresentationStyle:UIModalPresentationFullScreen];
[controller.get() setModalPresentationStyle: UIModalPresentationFullScreen];
auto chooserBounds = fileChooser.parent->getBounds();
setBounds (chooserBounds);
auto chooserBounds = fileChooser.parent->getBounds();
setBounds (chooserBounds);
setAlwaysOnTop (true);
fileChooser.parent->addAndMakeVisible (this);
}
else
setAlwaysOnTop (true);
fileChooser.parent->addAndMakeVisible (this);
}
else
{
if (SystemStats::isRunningInAppExtensionSandbox())
{
// Opening a native top-level window in an AUv3 is not allowed (sandboxing). You need to specify a
// parent component (for example your editor) to parent the native file chooser window. To do this
// specify a parent component in the FileChooser's constructor!
jassert (fileChooser.parent != nullptr);
jassertfalse;
return;
}
}
else
{
auto chooserBounds = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
setBounds (chooserBounds);
setAlwaysOnTop (true);
setVisible (true);
addToDesktop (0);
}
}
@@ -131,8 +138,6 @@ public:
#endif
}
private:
//==============================================================================
void parentHierarchyChanged() override
{
auto* newPeer = dynamic_cast<UIViewComponentPeer*> (getPeer());
@@ -141,11 +146,23 @@ private:
{
peer = newPeer;
if (auto* parentController = peer->controller)
[parentController showViewController: controller.get() sender: parentController];
if (peer != nullptr)
{
if (auto* parentController = peer->controller)
[parentController showViewController: controller.get() sender: parentController];
peer->toFront (false);
}
}
}
private:
//==============================================================================
void handleAsyncUpdate() override
{
pickerWasCancelled();
}
//==============================================================================
static StringArray getUTTypesForWildcards (const String& filterWildcards, String& firstExtension)
{
@@ -182,7 +199,9 @@ private:
}
}
else
{
result.add ("public.data");
}
return result;
}
@@ -207,6 +226,8 @@ private:
//==============================================================================
void didPickDocumentAtURL (NSURL* url)
{
cancelPendingUpdate();
bool isWriting = controller.get().documentPickerMode == UIDocumentPickerModeExportToService
| controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;
@@ -267,9 +288,9 @@ private:
void pickerWasCancelled()
{
Array<URL> chooserResults;
cancelPendingUpdate();
owner.finished (chooserResults);
owner.finished ({});
exitModalState (0);
}
@@ -294,21 +315,40 @@ private:
//==============================================================================
static void didPickDocumentAtURL (id self, SEL, UIDocumentPickerViewController*, NSURL* url)
{
auto picker = getOwner (self);
if (picker != nullptr)
if (auto* picker = getOwner (self))
picker->didPickDocumentAtURL (url);
}
static void documentPickerWasCancelled (id self, SEL, UIDocumentPickerViewController*)
{
auto picker = getOwner (self);
if (picker != nullptr)
if (auto* picker = getOwner (self))
picker->pickerWasCancelled();
}
};
struct FileChooserControllerClass : public ObjCClass<UIDocumentPickerViewController>
{
FileChooserControllerClass() : ObjCClass<UIDocumentPickerViewController> ("FileChooserController_")
{
addIvar<Native*> ("owner");
addMethod (@selector (viewDidDisappear:), viewDidDisappear, "v@:@c");
registerClass();
}
static void setOwner (id self, Native* owner) { object_setInstanceVariable (self, "owner", owner); }
static Native* getOwner (id self) { return getIvar<Native*> (self, "owner"); }
//==============================================================================
static void viewDidDisappear (id self, SEL, BOOL animated)
{
sendSuperclassMessage<void> (self, @selector (viewDidDisappear:), animated);
if (auto* picker = getOwner (self))
picker->triggerAsyncUpdate();
}
};
//==============================================================================
FileChooser& owner;
std::unique_ptr<NSObject<UIDocumentPickerDelegate>, NSObjectDeleter> delegate;
@@ -316,6 +356,7 @@ private:
UIViewComponentPeer* peer = nullptr;
static FileChooserDelegateClass fileChooserDelegateClass;
static FileChooserControllerClass fileChooserControllerClass;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Native)


Loading…
Cancel
Save