JUCEのAlertWindowをAsyncで使う

JUCE_MODAL_LOOPS_PERMITTEDがデフォルトで0になる（すでになったかも）。これが意味するところは、AlertWindowを下記のように使っていたコードは全部エラーになるということ…。

```hoge.cpp
    auto result = AlertWindow::showOkCancelBox(AlertWindow::WarningIcon,
                                               "Write a program",
                                               "Are you sure to overwrite?");
    if (result)
    {
        // Okだった場合の処理
    }
```
なぜなら、

```juce_AlertWindow.h
    static bool JUCE_CALLTYPE showOkCancelBox (MessageBoxIconType iconType,
                                               const String& title,
                                               const String& message,
                                              #if JUCE_MODAL_LOOPS_PERMITTED
                                               const String& button1Text = String(),
                                               const String& button2Text = String(),
                                               Component* associatedComponent = nullptr,
                                               ModalComponentManager::Callback* callback = nullptr);
                                              #else
                                               const String& button1Text,
                                               const String& button2Text,
                                               Component* associatedComponent,
                                               ModalComponentManager::Callback* callback);
                                              #endif

```
というように第3引数以降もデフォルト値が定義されていないから。かつ、Async実行になるのでshowOkCancelBox()の返り値を使っての処理ができなくなる。今後は、

```hoge.cpp
    AlertWindow::showOkCancelBox (AlertWindow::NoIcon,
                                  "Write a program",
                                  "Are you sure to overwrite?",
                                  String(),
                                  String(),
                                  nullptr,
                                  ModalCallbackFunction::create([](int result){
        if (result)
        {
            // Okだった場合の処理
        }
    }));
```
のように書く必要がある。上記はラムダ式を使って書いてるけど、静的メンバ関数を定義しても良い。ただし、いちいち定義がめんどくさいし、メンバ変数を使いたかったりするとめんどくさいのでラムダ式が良いかと。JUCEのDemorunnerでは静的メンバ関数になってるけど。自動変数を使いたい場合は[]の中に書いておけばいい。

```hoge.cpp
    int a = 10;
    AlertWindow::showOkCancelBox (AlertWindow::NoIcon,
                                  "Write a program",
                                  "Are you sure to overwrite?",
                                  String(),
                                  String(),
                                  nullptr,
                                  ModalCallbackFunction::create([a](int result){
        if (result)
        {
            // Okだった場合の処理
            printf ("%d\n", a);
        }
    }));
```
メンバ関数を呼び出したい場合は[]の中にthisを書いておく。

```hoge.cpp
    AlertWindow::showOkCancelBox (AlertWindow::NoIcon,
                                  "Write a program",
                                  "Are you sure to overwrite?",
                                  String(),
                                  String(),
                                  nullptr,
                                  ModalCallbackFunction::create([this](int result){
        if (result)
        {
            // Okだった場合の処理
            foo(); // foo()はメンバ関数
        }
    }));
```
実際多いのは下記のように両方使う場合かも。

```hoge.cpp
    int a = 10;
    AlertWindow::showOkCancelBox (AlertWindow::NoIcon,
                                  "Write a program",
                                  "Are you sure to overwrite?",
                                  String(),
                                  String(),
                                  nullptr,
                                  ModalCallbackFunction::create([this, a](int result){
        if (result)
        {
            // Okだった場合の処理
            foo(a); // foo()はメンバ関数
        }
    }));
```
JUCE_MODAL_LOOPS_PERMITTEDのデフォルトが変わった背景は、Androidではモーダル処理が許可されていないことにあるらしい。なので、Androidでも動くコードを書くにはこの対応が必須らしい。

AlertWindowだけでなくFileChooserもほぼ同様。ただし、ModalCallbackFunction::create()を使わずにラムダ式を書けば良い様子。AlertWindowのうちMessageBoxは特に何も処理しないのであればコールバック指定なしに使えるが、メンバ関数がAsync専用のAlertWindow::showMessageBoxAsync()になる。FileChooserのインスタンスはクラスのメンバ変数として保持しておくなどの必要あり（めんどくさい…）。場合によっては(?)、thisもSafePointerを使って安全に使えるようにするべきっぽい。もっと良い例は
DemoRunnerにある。

```hoge.h
class Home
{
//  <-- snip -->
private:
    std::unique_ptr<FileChooser> fileChooser;
}

```

```hoge.cpp
    SafePointer<Hoge> safeThis (this);
    static const char* fileExt = ".txt";
    auto fileToSave = File::createTempFile ("temp");

    fileChooser.reset (new FileChooser ("Choose a location to save...",
                                        File::getCurrentWorkingDirectory().getChildFile (fileToSave.getFileName()),
                                        String("*") + fileExt, true));
    fileChooser->launchAsync(FileBrowserComponent::saveMode | FileBrowserComponent::canSelectFiles,
                             [safeThis, fileToSave] (const FileChooser& fc)
    {
        auto result = fc.getURLResult();
        if (! result.isEmpty())
        {
            std::unique_ptr<InputStream>  wi (fileToSave.createInputStream());
            std::unique_ptr<OutputStream> wo (result.createOutputStream());
            
            if (wi.get() != nullptr && wo.get() != nullptr)
            {
                auto numWritten = wo->writeFromInputStream (*wi, -1);
                if (numWritten == 0)
                {
                    AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
                                                      "Failed to save file",
                                                      "Failed to create presets backup.");
                }
                ignoreUnused (numWritten);
                wo->flush();
            }
        }
        bool removed = fileToSave.deleteFile();
        jassert(removed);
        ignoreUnused(removed);
    });
```