mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-16 00:34:19 +00:00
iOS: Make sure that native FileChooser is visible and is dismissed correctly when user taps outside the chooser window
This commit is contained in:
parent
8152b21bf2
commit
dd3c96b7e7
1 changed files with 77 additions and 36 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue