1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

ScopedMessageBox: Replace old AlertWindow uses with new API

This commit is contained in:
reuk 2023-02-22 20:54:45 +00:00
parent 79ed81c24a
commit 39a731de46
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
55 changed files with 893 additions and 677 deletions

View file

@ -596,13 +596,17 @@ private:
const auto u = fc.getURLResult();
if (! audioFileReader.loadURL (u))
NativeMessageBox::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::WarningIcon)
.withTitle ("Error loading file")
.withMessage ("Unable to load audio file"),
nullptr);
{
auto options = MessageBoxOptions().withIconType (MessageBoxIconType::WarningIcon)
.withTitle ("Error loading file")
.withMessage ("Unable to load audio file")
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
else
{
thumbnailComp.setCurrentURL (u);
}
}
fileChooser = nullptr;
@ -629,6 +633,7 @@ private:
AudioFileReaderComponent& audioFileReader;
std::unique_ptr<FileChooser> fileChooser;
ScopedMessageBox messageBox;
};
//==============================================================================

View file

@ -279,13 +279,14 @@ private:
return legacyStartChannel.getText().getIntValue() <= legacyEndChannel.getText().getIntValue();
}
void handleInvalidLegacyModeParameters() const
void handleInvalidLegacyModeParameters()
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Invalid legacy mode channel layout",
"Cannot set legacy mode start/end channel:\n"
"The end channel must not be less than the start channel!",
"Got it");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Invalid legacy mode channel layout",
"Cannot set legacy mode start/end channel:\n"
"The end channel must not be less than the start channel!",
"Got it");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
Range<int> getLegacyModeChannelRange() const
@ -338,6 +339,8 @@ private:
ComboBox numberOfVoices;
Label numberOfVoicesLabel { {}, "Number of synth voices"};
ScopedMessageBox messageBox;
static constexpr int defaultMemberChannels = 15,
defaultMasterPitchbendRange = 2,
defaultNotePitchbendRange = 48;

View file

@ -195,7 +195,13 @@ private:
addAndMakeVisible (textButton);
shapeButton.setShape (getJUCELogoPath(), false, true, false);
shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Alert", "This is an AlertWindow"); };
shapeButton.onClick = [this]
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"Alert",
"This is an AlertWindow");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
};
shapeButton.setHasFocusOutline (true);
addAndMakeVisible (shapeButton);
}
@ -250,6 +256,7 @@ private:
Colours::darkorange,
Colours::darkorange.brighter (0.5f),
Colours::darkorange.brighter (0.75f) };
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonsComponent)

View file

@ -252,8 +252,10 @@ private:
}
else
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Camera open failed",
"Camera open failed, reason: " + error);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Camera open failed",
"Camera open failed, reason: " + error);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
snapshotButton .setEnabled (cameraDevice.get() != nullptr && ! contentSharingPending);
@ -365,9 +367,10 @@ private:
void errorOccurred (const String& error)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
"Camera Device Error",
"An error has occurred: " + error + " Camera will be closed.");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"Camera Device Error",
"An error has occurred: " + error + " Camera will be closed.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
cameraDevice.reset();
@ -378,14 +381,17 @@ private:
void sharingFinished (bool success, bool isCapture)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
isCapture ? "Image sharing result" : "Video sharing result",
success ? "Success!" : "Failed!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
isCapture ? "Image sharing result" : "Video sharing result",
success ? "Success!" : "Failed!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
contentSharingPending = false;
snapshotButton .setEnabled (true);
recordMovieButton.setEnabled (true);
}
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CameraDemo)
};

View file

@ -48,12 +48,19 @@
#include "../Assets/DemoUtilities.h"
//==============================================================================
struct MessageBoxOwnerComponent : public Component
{
ScopedMessageBox messageBox;
};
//==============================================================================
class DemoBackgroundThread : public ThreadWithProgressWindow
{
public:
DemoBackgroundThread()
: ThreadWithProgressWindow ("busy doing some important things...", true, true)
explicit DemoBackgroundThread (MessageBoxOwnerComponent& comp)
: ThreadWithProgressWindow ("busy doing some important things...", true, true),
owner (&comp)
{
setStatusMessage ("Getting ready...");
}
@ -91,21 +98,26 @@ public:
{
const String messageString (userPressedCancel ? "You pressed cancel!" : "Thread finished ok!");
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Progress window")
.withMessage (messageString)
.withButton ("OK"),
nullptr);
if (owner != nullptr)
{
owner->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Progress window")
.withMessage (messageString)
.withButton ("OK"),
nullptr);
}
// ..and clean up by deleting our thread object..
delete this;
}
Component::SafePointer<MessageBoxOwnerComponent> owner;
};
//==============================================================================
class DialogsDemo : public Component
class DialogsDemo : public MessageBoxOwnerComponent
{
public:
enum DialogType
@ -114,7 +126,7 @@ public:
warningAlertWindow,
infoAlertWindow,
questionAlertWindow,
okCancelAlertWindow,
yesNoCancelAlertWindow,
extraComponentsAlertWindow,
calloutBoxWindow,
progressWindow,
@ -140,7 +152,7 @@ public:
"Alert Window With Warning Icon",
"Alert Window With Info Icon",
"Alert Window With Question Icon",
"OK Cancel Alert Window",
"Yes No Cancel Alert Window",
"Alert Window With Extra Components",
"CalloutBox",
"Thread With Progress Window",
@ -168,18 +180,19 @@ public:
setSize (500, 500);
RuntimePermissions::request (RuntimePermissions::readExternalStorage,
[] (bool granted)
{
if (! granted)
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::WarningIcon)
.withTitle ("Permissions warning")
.withMessage ("External storage access permission not granted, some files"
" may be inaccessible.")
.withButton ("OK"),
nullptr);
});
RuntimePermissions::request (RuntimePermissions::readExternalStorage, [ptr = Component::SafePointer (this)] (bool granted)
{
if (granted || ptr == nullptr)
return;
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::WarningIcon)
.withTitle ("Permissions warning")
.withMessage ("External storage access permission not granted, some files"
" may be inaccessible.")
.withButton ("OK"),
nullptr);
});
}
//==============================================================================
@ -214,49 +227,51 @@ private:
OwnedArray<TextButton> windowButtons;
ToggleButton nativeButton;
struct AlertBoxResultChosen
auto getAlertBoxResultChosen()
{
void operator() (int result) const noexcept
return [ptr = Component::SafePointer (this)] (int result)
{
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Alert Box")
.withMessage ("Result code: " + String (result))
.withButton ("OK"),
nullptr);
}
};
if (ptr != nullptr)
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Alert Box")
.withMessage ("Result code: " + String (result))
.withButton ("OK"),
nullptr);
};
}
struct AsyncAlertBoxResultChosen
auto getAsyncAlertBoxResultChosen()
{
void operator() (int result) const noexcept
return [ptr = Component::SafePointer (this)] (int result)
{
auto& aw = *demo.asyncAlertWindow;
if (ptr == nullptr)
return;
auto& aw = *ptr->asyncAlertWindow;
aw.exitModalState (result);
aw.setVisible (false);
if (result == 0)
{
AlertBoxResultChosen{} (result);
ptr->getAlertBoxResultChosen() (result);
return;
}
auto optionIndexChosen = aw.getComboBoxComponent ("option")->getSelectedItemIndex();
auto text = aw.getTextEditorContents ("text");
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Alert Box")
.withMessage ("Result code: " + String (result) + newLine
+ "Option index chosen: " + String (optionIndexChosen) + newLine
+ "Text: " + text)
.withButton ("OK"),
nullptr);
}
DialogsDemo& demo;
};
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Alert Box")
.withMessage ("Result code: " + String (result) + newLine
+ "Option index chosen: " + String (optionIndexChosen) + newLine
+ "Text: " + text)
.withButton ("OK"),
nullptr);
};
}
void showWindow (Component& button, DialogType type)
{
@ -268,16 +283,19 @@ private:
if (type == infoAlertWindow) icon = MessageBoxIconType::InfoIcon;
if (type == questionAlertWindow) icon = MessageBoxIconType::QuestionIcon;
AlertWindow::showMessageBoxAsync (icon, "This is an AlertWindow",
"And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.",
"OK");
auto options = MessageBoxOptions::makeOptionsOk (icon,
"This is an AlertWindow",
"And this is the AlertWindow's message. "
"Blah blah blah blah blah blah blah blah blah blah blah blah blah.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else if (type == okCancelAlertWindow)
else if (type == yesNoCancelAlertWindow)
{
AlertWindow::showOkCancelBox (MessageBoxIconType::QuestionIcon, "This is an ok/cancel AlertWindow",
"And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.",
{}, {}, {},
ModalCallbackFunction::create (AlertBoxResultChosen{}));
auto options = MessageBoxOptions::makeOptionsYesNoCancel (MessageBoxIconType::QuestionIcon,
"This is a yes/no/cancel AlertWindow",
"And this is the AlertWindow's message. "
"Blah blah blah blah blah blah blah blah blah blah blah blah blah.");
messageBox = AlertWindow::showScopedAsync (options, getAlertBoxResultChosen());
}
else if (type == calloutBoxWindow)
{
@ -301,13 +319,13 @@ private:
asyncAlertWindow->addButton ("OK", 1, KeyPress (KeyPress::returnKey, 0, 0));
asyncAlertWindow->addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey, 0, 0));
asyncAlertWindow->enterModalState (true, ModalCallbackFunction::create (AsyncAlertBoxResultChosen { *this }));
asyncAlertWindow->enterModalState (true, ModalCallbackFunction::create (getAsyncAlertBoxResultChosen()));
}
else if (type == progressWindow)
{
// This will launch our ThreadWithProgressWindow in a modal state. (Our subclass
// will take care of deleting the object when the task has finished)
(new DemoBackgroundThread())->launchThread();
(new DemoBackgroundThread (*this))->launchThread();
}
else if (type >= loadChooser && type <= saveChooser)
{
@ -318,9 +336,10 @@ private:
fc.reset (new FileChooser ("Choose a file to open...", File::getCurrentWorkingDirectory(),
"*", useNativeVersion));
fc->launchAsync (FileBrowserComponent::canSelectMultipleItems | FileBrowserComponent::openMode
| FileBrowserComponent::canSelectFiles,
[] (const FileChooser& chooser)
fc->launchAsync (FileBrowserComponent::canSelectMultipleItems
| FileBrowserComponent::openMode
| FileBrowserComponent::canSelectFiles,
[this] (const FileChooser& chooser)
{
String chosen;
auto results = chooser.getURLResults();
@ -329,12 +348,12 @@ private:
chosen << (result.isLocalFile() ? result.getLocalFile().getFullPathName()
: result.toString (false)) << "\n";
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + chosen)
.withButton ("OK"),
nullptr);
messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + chosen)
.withButton ("OK"),
nullptr);
});
}
else if (type == loadWithPreviewChooser)
@ -344,9 +363,10 @@ private:
fc.reset (new FileChooser ("Choose an image to open...", File::getCurrentWorkingDirectory(),
"*.jpg;*.jpeg;*.png;*.gif", useNativeVersion));
fc->launchAsync (FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles
| FileBrowserComponent::canSelectMultipleItems,
[] (const FileChooser& chooser)
fc->launchAsync (FileBrowserComponent::openMode
| FileBrowserComponent::canSelectFiles
| FileBrowserComponent::canSelectMultipleItems,
[this] (const FileChooser& chooser)
{
String chosen;
auto results = chooser.getURLResults();
@ -355,12 +375,12 @@ private:
chosen << (result.isLocalFile() ? result.getLocalFile().getFullPathName()
: result.toString (false)) << "\n";
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + chosen)
.withButton ("OK"),
nullptr);
messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + chosen)
.withButton ("OK"),
nullptr);
},
&imagePreview);
}
@ -385,7 +405,7 @@ private:
"*", useNativeVersion));
fc->launchAsync (FileBrowserComponent::saveMode | FileBrowserComponent::canSelectFiles,
[fileToSave] (const FileChooser& chooser)
[this, fileToSave] (const FileChooser& chooser)
{
auto result = chooser.getURLResult();
auto name = result.isEmpty() ? String()
@ -409,12 +429,12 @@ private:
}
#endif
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + name)
.withButton ("OK"),
nullptr);
messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + name)
.withButton ("OK"),
nullptr);
});
}
else if (type == directoryChooser)
@ -425,35 +445,37 @@ private:
useNativeVersion));
fc->launchAsync (FileBrowserComponent::openMode | FileBrowserComponent::canSelectDirectories,
[] (const FileChooser& chooser)
[this] (const FileChooser& chooser)
{
auto result = chooser.getURLResult();
auto name = result.isLocalFile() ? result.getLocalFile().getFullPathName()
: result.toString (true);
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + name)
.withButton ("OK"),
nullptr);
messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("File Chooser...")
.withMessage ("You picked: " + name)
.withButton ("OK"),
nullptr);
});
}
}
else if (type == shareText)
{
ContentSharer::getInstance()->shareText ("I love JUCE!",
[] (bool success, const String& error)
{
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")");
ContentSharer::getInstance()->shareText ("I love JUCE!", [ptr = Component::SafePointer (this)] (bool success, const String& error)
{
if (ptr == nullptr)
return;
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Text Result")
.withMessage ("Sharing text finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")");
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Text Result")
.withMessage ("Sharing text finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
}
else if (type == shareFile)
{
@ -467,18 +489,20 @@ private:
Array<URL> urls;
urls.add (URL (fileToSave));
ContentSharer::getInstance()->shareFiles (urls,
[] (bool success, const String& error)
{
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")");
ContentSharer::getInstance()->shareFiles (urls, [ptr = Component::SafePointer (this)] (bool success, const String& error)
{
if (ptr == nullptr)
return;
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Files Result")
.withMessage ("Sharing files finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")");
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Files Result")
.withMessage ("Sharing files finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
}
}
@ -495,19 +519,21 @@ private:
Array<Image> images { myImage, myImage2 };
ContentSharer::getInstance()->shareImages (images,
[] (bool success, const String& error)
{
String resultString = success ? String ("success")
: ("failure\n (error: " + error + ")");
ContentSharer::getInstance()->shareImages (images, [ptr = Component::SafePointer (this)] (bool success, const String& error)
{
if (ptr == nullptr)
return;
AlertWindow::showAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Images Result")
.withMessage ("Sharing images finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
String resultString = success ? String ("success")
: ("failure\n (error: " + error + ")");
ptr->messageBox = AlertWindow::showScopedAsync (MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Sharing Images Result")
.withMessage ("Sharing images finished\nwith " + resultString)
.withButton ("OK"),
nullptr);
});
}
}

View file

@ -61,8 +61,10 @@ public:
void buttonClicked() override
{
++counter;
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Action Button Pressed",
"Pressing this type of property component can trigger an action such as showing an alert window!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"Action Button Pressed",
"Pressing this type of property component can trigger an action such as showing an alert window!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
refresh();
}
@ -73,6 +75,7 @@ public:
private:
int counter = 0;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DemoButtonPropertyComponent)
};

View file

@ -134,12 +134,15 @@ private:
}
else
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Couldn't load the file!",
result.getErrorMessage());
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Couldn't load the file!",
result.getErrorMessage());
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MovieComponentWithFileBrowser)
};

View file

@ -213,11 +213,10 @@ public:
{
if (error.isNotEmpty())
{
NativeMessageBox::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Plugin Load Failed",
error,
nullptr,
nullptr);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Plugin Load Failed",
error);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
return;
}
@ -281,6 +280,7 @@ private:
std::unique_ptr<AudioPluginInstance> inner;
EditorStyle editorStyle = EditorStyle{};
bool active = false;
ScopedMessageBox messageBox;
static constexpr const char* innerStateTag = "inner_state";
static constexpr const char* editorStyleTag = "editor_style";
@ -298,7 +298,6 @@ private:
}
};
constexpr const char* HostAudioProcessorImpl::innerStateTag;
constexpr const char* HostAudioProcessorImpl::editorStyleTag;

View file

@ -1192,7 +1192,7 @@ private:
}
}
bool isLegacyModeValid() const
bool isLegacyModeValid()
{
if (! areLegacyModeParametersValid())
{
@ -1233,13 +1233,14 @@ private:
return getFirstChannel() <= getLastChannel();
}
void handleInvalidLegacyModeParameters() const
void handleInvalidLegacyModeParameters()
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Invalid legacy mode channel layout",
"Cannot set legacy mode start/end channel:\n"
"The end channel must not be less than the start channel!",
"Got it");
auto options = MessageBoxOptions::makeOptionsOk (AlertWindow::WarningIcon,
"Invalid legacy mode channel layout",
"Cannot set legacy mode start/end channel:\n"
"The end channel must not be less than the start channel!",
"Got it");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
MPESettingsDataModel dataModel;
@ -1251,6 +1252,7 @@ private:
legacyPitchbendRangeLabel { {}, "Pitchbend range (semitones)" };
UndoManager* undoManager;
ScopedMessageBox messageBox;
};
//==============================================================================

View file

@ -156,12 +156,13 @@ private:
voiceProduct.purchasePrice = "In-App purchases unavailable";
}
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"In-app purchase is unavailable!",
"In-App purchases are not available. This either means you are trying "
"to use IAP on a platform that does not support IAP or you haven't setup "
"your app correctly to work with IAP.",
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"In-app purchase is unavailable!",
"In-App purchases are not available. This either means you are trying "
"to use IAP on a platform that does not support IAP or you haven't setup "
"your app correctly to work with IAP.",
"OK");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else
{
@ -178,11 +179,12 @@ private:
}
}
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Your credit card will be charged!",
"You are running the sample code for JUCE In-App purchases. "
"Although this is only sample code, it will still CHARGE YOUR CREDIT CARD!",
"Understood!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Your credit card will be charged!",
"You are running the sample code for JUCE In-App purchases. "
"Although this is only sample code, it will still CHARGE YOUR CREDIT CARD!",
"Understood!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
guiUpdater.triggerAsyncUpdate();
@ -264,6 +266,7 @@ private:
AsyncUpdater& guiUpdater;
bool havePurchasesBeenRestored = false, havePricesBeenFetched = false, purchaseInProgress = false;
Array<VoiceProduct> voiceProducts;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VoicePurchases)
};

View file

@ -222,16 +222,17 @@ private:
//==============================================================================
void showConnectionErrorMessage (const String& messageText)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Connection error",
messageText,
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Connection error",
messageText);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
//==============================================================================
Slider rotaryKnob;
OSCSender sender1, sender2;
Label senderLabel { {}, "Sender" };
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCSenderDemo)
};
@ -273,15 +274,16 @@ private:
void showConnectionErrorMessage (const String& messageText)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Connection error",
messageText,
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Connection error",
messageText);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
//==============================================================================
Slider rotaryKnob;
Label receiverLabel { {}, "Receiver" };
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCReceiverDemo)
};
@ -403,28 +405,28 @@ private:
//==============================================================================
void handleConnectError (int failedPort)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"OSC Connection error",
"Error: could not connect to port " + String (failedPort),
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"OSC Connection error",
"Error: could not connect to port " + String (failedPort));
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
//==============================================================================
void handleDisconnectError()
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Unknown error",
"An unknown error occurred while trying to disconnect from UDP port.",
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Unknown error",
"An unknown error occurred while trying to disconnect from UDP port.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
//==============================================================================
void handleInvalidPortNumberEntered()
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Invalid port number",
"Error: you have entered an invalid UDP port number.",
"OK");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Invalid port number",
"Error: you have entered an invalid UDP port number.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
//==============================================================================
@ -457,6 +459,8 @@ private:
connectionStatusLabel.setJustificationType (Justification::centredRight);
}
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCMonitorDemo)
};

View file

@ -185,21 +185,25 @@ public:
{ PushNotifications::getInstance()->removeAllPendingLocalNotifications(); };
#endif
remoteView.getDeviceTokenButton.onClick = []
remoteView.getDeviceTokenButton.onClick = [this]
{
String token = PushNotifications::getInstance()->getDeviceToken();
DBG ("token = " + token);
if (token.isEmpty())
{
showRemoteInstructions();
}
else
NativeMessageBox::showAsync (MessageBoxOptions()
{
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Device token")
.withMessage (token)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
};
#if JUCE_ANDROID
@ -313,12 +317,12 @@ private:
String requiredFields = "all required fields";
#endif
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Incorrect notifications setup")
.withMessage ("Please make sure that " + requiredFields + " are set.")
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
return;
}
@ -565,14 +569,14 @@ private:
{
ignoreUnused (isLocalNotification);
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Received notification")
.withMessage ("ID: " + n.identifier
+ ", title: " + n.title
+ ", body: " + n.body)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void handleNotificationAction (bool isLocalNotification,
@ -582,7 +586,7 @@ private:
{
ignoreUnused (isLocalNotification);
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Received notification action")
.withMessage ("ID: " + n.identifier
@ -590,22 +594,22 @@ private:
+ ", body: " + n.body
+ ", action: " + actionIdentifier
+ ", optionalResponse: " + optionalResponse)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
PushNotifications::getInstance()->removeDeliveredNotification (n.identifier);
}
void localNotificationDismissedByUser (const PushNotifications::Notification& n) override
{
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Notification dismissed by a user")
.withMessage ("ID: " + n.identifier
+ ", title: " + n.title
+ ", body: " + n.body)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void deliveredNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
@ -615,12 +619,12 @@ private:
for (auto& n : notifs)
text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Received notification list")
.withMessage (text)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void pendingLocalNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
@ -630,54 +634,54 @@ private:
for (auto& n : notifs)
text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Pending notification list")
.withMessage (text)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void deviceTokenRefreshed (const String& token) override
{
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Device token refreshed")
.withMessage (token)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
#if JUCE_ANDROID
void remoteNotificationsDeleted() override
{
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Remote notifications deleted")
.withMessage ("Some of the pending messages were removed!")
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void upstreamMessageSent (const String& messageId) override
{
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Upstream message sent")
.withMessage ("Message id: " + messageId)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
void upstreamMessageSendingError (const String& messageId, const String& error) override
{
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Upstream message sending error")
.withMessage ("Message id: " + messageId
+ "\nerror: " + error)
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
}
static Array<PushNotifications::Channel> getAndroidChannels()
@ -1207,8 +1211,8 @@ private:
struct DemoTabbedComponent : public TabbedComponent
{
explicit DemoTabbedComponent (TabbedButtonBar::Orientation orientation)
: TabbedComponent (orientation)
DemoTabbedComponent (PushNotificationsDemo& demoIn, TabbedButtonBar::Orientation orientation)
: TabbedComponent (orientation), demo (demoIn)
{
}
@ -1216,27 +1220,28 @@ private:
{
if (! showedRemoteInstructions && newCurrentTabName == "Remote")
{
PushNotificationsDemo::showRemoteInstructions();
demo.showRemoteInstructions();
showedRemoteInstructions = true;
}
}
private:
bool showedRemoteInstructions = false;
PushNotificationsDemo& demo;
};
static void showRemoteInstructions()
void showRemoteInstructions()
{
#if JUCE_IOS || JUCE_MAC
NativeMessageBox::showAsync (MessageBoxOptions()
auto options = MessageBoxOptions()
.withIconType (MessageBoxIconType::InfoIcon)
.withTitle ("Remote Notifications instructions")
.withMessage ("In order to be able to test remote notifications "
"ensure that the app is signed and that you register "
"the bundle ID for remote notifications in "
"Apple Developer Center.")
.withButton ("OK"),
nullptr);
.withButton ("OK");
messageBox = NativeMessageBox::showScopedAsync (options, nullptr);
#endif
}
@ -1246,10 +1251,11 @@ private:
AuxActionsView auxActionsView;
TabbedComponent localNotificationsTabs { TabbedButtonBar::TabsAtTop };
RemoteView remoteView;
DemoTabbedComponent mainTabs { TabbedButtonBar::TabsAtTop };
DemoTabbedComponent mainTabs { *this, TabbedButtonBar::TabsAtTop };
TextButton sendButton { "Send!" };
Label notAvailableYetLabel { "notAvailableYetLabel",
"Push Notifications feature is not available on this platform yet!" };
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PushNotificationsDemo)

View file

@ -100,9 +100,10 @@ void PluginGraph::addPluginCallback (std::unique_ptr<AudioPluginInstance> instan
{
if (instance == nullptr)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Couldn't create plugin"),
error);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Couldn't create plugin"),
error);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else
{

View file

@ -110,6 +110,7 @@ private:
AudioPluginFormatManager& formatManager;
KnownPluginList& knownPlugins;
OwnedArray<PluginWindow> activePluginWindows;
ScopedMessageBox messageBox;
NodeID lastUID;
NodeID getNextUID() noexcept;

View file

@ -110,19 +110,20 @@ public:
return;
SafePointer<TemplateComponent> safeThis { this };
NewProjectWizard::createNewProject (projectTemplate,
dir.getChildFile (projectNameValue.get().toString()),
projectNameValue.get(),
modulesValue.get(),
exportersValue.get(),
fileOptionsValue.get(),
modulePathValue.getCurrentValue(),
modulePathValue.getWrappedValueTreePropertyWithDefault().isUsingDefault(),
[safeThis, dir] (std::unique_ptr<Project> project)
messageBox = NewProjectWizard::createNewProject (projectTemplate,
dir.getChildFile (projectNameValue.get().toString()),
projectNameValue.get(),
modulesValue.get(),
exportersValue.get(),
fileOptionsValue.get(),
modulePathValue.getCurrentValue(),
modulePathValue.getWrappedValueTreePropertyWithDefault().isUsingDefault(),
[safeThis, dir] (ScopedMessageBox mb, std::unique_ptr<Project> project)
{
if (safeThis == nullptr)
return;
safeThis->messageBox = std::move (mb);
safeThis->projectCreatedCallback (std::move (project));
getAppSettings().lastWizardFolder = dir;
});
@ -249,6 +250,8 @@ private:
return builder.components;
}
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateComponent)
};

View file

@ -237,57 +237,51 @@ File NewProjectWizard::getLastWizardFolder()
return lastFolderFallback;
}
static void displayFailedFilesMessage (const StringArray& failedFiles)
static ScopedMessageBox displayFailedFilesMessage (const StringArray& failedFiles)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Errors in Creating Project!"),
TRANS("The following files couldn't be written:")
+ "\n\n"
+ failedFiles.joinIntoString ("\n", 0, 10));
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Errors in Creating Project!"),
TRANS ("The following files couldn't be written:")
+ "\n\n"
+ failedFiles.joinIntoString ("\n", 0, 10));
return AlertWindow::showScopedAsync (options, nullptr);
}
template <typename Callback>
static void prepareDirectory (const File& targetFolder, Callback&& callback)
static ScopedMessageBox prepareDirectory (const File& targetFolder, Callback&& callback)
{
StringArray failedFiles;
if (! targetFolder.exists())
{
if (! targetFolder.createDirectory())
{
displayFailedFilesMessage ({ targetFolder.getFullPathName() });
return;
}
return displayFailedFilesMessage ({ targetFolder.getFullPathName() });
}
else if (FileHelpers::containsAnyNonHiddenFiles (targetFolder))
{
AlertWindow::showOkCancelBox (MessageBoxIconType::InfoIcon,
TRANS("New JUCE Project"),
TRANS("You chose the folder:\n\nXFLDRX\n\n").replace ("XFLDRX", targetFolder.getFullPathName())
+ TRANS("This folder isn't empty - are you sure you want to create the project there?")
+ "\n\n"
+ TRANS("Any existing files with the same names may be overwritten by the new files."),
{},
{},
nullptr,
ModalCallbackFunction::create ([callback] (int result)
{
if (result != 0)
callback();
}));
return;
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::InfoIcon,
TRANS ("New JUCE Project"),
TRANS ("You chose the folder:\n\nXFLDRX\n\n").replace ("XFLDRX", targetFolder.getFullPathName())
+ TRANS ("This folder isn't empty - are you sure you want to create the project there?")
+ "\n\n"
+ TRANS ("Any existing files with the same names may be overwritten by the new files."));
return AlertWindow::showScopedAsync (options, [callback] (int result)
{
if (result != 0)
callback();
});
}
callback();
return ScopedMessageBox();
}
void NewProjectWizard::createNewProject (const NewProjectTemplates::ProjectTemplate& projectTemplate,
const File& targetFolder, const String& name, var modules, var exporters, var fileOptions,
const String& modulePath, bool useGlobalModulePath,
std::function<void (std::unique_ptr<Project>)> callback)
ScopedMessageBox NewProjectWizard::createNewProject (const NewProjectTemplates::ProjectTemplate& projectTemplate,
const File& targetFolder, const String& name, var modules, var exporters, var fileOptions,
const String& modulePath, bool useGlobalModulePath,
std::function<void (ScopedMessageBox, std::unique_ptr<Project>)> callback)
{
prepareDirectory (targetFolder, [=]
return prepareDirectory (targetFolder, [=]
{
auto project = std::make_unique<Project> (targetFolder.getChildFile (File::createLegalFileName (name))
.withFileExtension (Project::projectFileExtension));
@ -310,18 +304,18 @@ void NewProjectWizard::createNewProject (const NewProjectTemplates::ProjectTempl
{
uniqueProject->setChangedFlag (false);
uniqueProject->loadFrom (uniqueProject->getFile(), true);
callback (std::move (uniqueProject));
callback ({}, std::move (uniqueProject));
return;
}
auto failedFilesCopy = failedFiles;
failedFilesCopy.add (uniqueProject->getFile().getFullPathName());
displayFailedFilesMessage (failedFilesCopy);
callback (displayFailedFilesMessage (failedFilesCopy), {});
});
return;
}
displayFailedFilesMessage (failedFiles);
callback (displayFailedFilesMessage (failedFiles), {});
});
}

View file

@ -32,8 +32,8 @@ namespace NewProjectWizard
{
File getLastWizardFolder();
void createNewProject (const NewProjectTemplates::ProjectTemplate& projectTemplate,
const File& targetFolder, const String& name, var modules, var exporters, var fileOptions,
const String& modulePath, bool useGlobalModulePath,
std::function<void (std::unique_ptr<Project>)> callback);
ScopedMessageBox createNewProject (const NewProjectTemplates::ProjectTemplate& projectTemplate,
const File& targetFolder, const String& name, var modules, var exporters, var fileOptions,
const String& modulePath, bool useGlobalModulePath,
std::function<void (ScopedMessageBox, std::unique_ptr<Project>)> callback);
}

View file

@ -122,10 +122,11 @@ private:
if (postStrings.size() != preStrings.size())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Error"),
TRANS("The pre- and post-translation text doesn't match!\n\n"
"Perhaps it got mangled by the translator?"));
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Error"),
TRANS ("The pre- and post-translation text doesn't match!\n\n"
"Perhaps it got mangled by the translator?"));
messageBox = AlertWindow::showScopedAsync (options, nullptr);
return;
}
@ -136,10 +137,16 @@ private:
void scanProject()
{
if (Project* project = ProjucerApplication::getApp().mainWindowList.getFrontmostProject())
{
setPreTranslationText (TranslationHelpers::getPreTranslationText (*project));
}
else
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Translation Tool",
"This will only work when you have a project open!");
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Translation Tool",
"This will only work when you have a project open!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
void scanFolder()
@ -195,4 +202,5 @@ private:
loadTranslationButton { "Load existing translation file..."};
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
};

View file

@ -1098,13 +1098,14 @@ void ProjucerApplication::createNewProjectFromClipboard()
tempFile.create();
tempFile.appendText (SystemClipboard::getTextFromClipboard());
auto cleanup = [tempFile] (String errorString)
auto cleanup = [parent = WeakReference { this }, tempFile] (String errorString)
{
if (errorString.isNotEmpty())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Error", errorString);
tempFile.deleteFile();
}
if (parent == nullptr || errorString.isEmpty())
return;
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon, "Error", errorString);
parent->messageBox = AlertWindow::showScopedAsync (options, nullptr);
tempFile.deleteFile();
};
if (! isPIPFile (tempFile))
@ -1113,7 +1114,7 @@ void ProjucerApplication::createNewProjectFromClipboard()
return;
}
openFile (tempFile, [parent = WeakReference<ProjucerApplication> { this }, cleanup] (bool openedSuccessfully)
openFile (tempFile, [parent = WeakReference { this }, cleanup] (bool openedSuccessfully)
{
if (parent == nullptr)
return;

View file

@ -217,6 +217,7 @@ private:
int selectedColourSchemeIndex = 0, selectedEditorColourSchemeIndex = 0;
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjucerApplication)

View file

@ -56,11 +56,14 @@ void LatestVersionCheckerAndUpdater::run()
if (info == nullptr)
{
if (! backgroundCheck)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Update Server Communication Error",
"Failed to communicate with the JUCE update server.\n"
"Please try again in a few minutes.\n\n"
"If this problem persists you can download the latest version of JUCE from juce.com");
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Update Server Communication Error",
"Failed to communicate with the JUCE update server.\n"
"Please try again in a few minutes.\n\n"
"If this problem persists you can download the latest version of JUCE from juce.com");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
return;
}
@ -68,9 +71,12 @@ void LatestVersionCheckerAndUpdater::run()
if (! info->isNewerVersionThanCurrent())
{
if (! backgroundCheck)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
"No New Version Available",
"Your JUCE version is up to date.");
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"No New Version Available",
"Your JUCE version is up to date.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
return;
}
@ -109,9 +115,12 @@ void LatestVersionCheckerAndUpdater::run()
}
if (! backgroundCheck)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Failed to find any new downloads",
"Please try again in a few minutes.");
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Failed to find any new downloads",
"Please try again in a few minutes.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
//==============================================================================
@ -275,33 +284,38 @@ void LatestVersionCheckerAndUpdater::askUserForLocationToDownload (const Version
{
if (targetFolder.getChildFile (".git").isDirectory())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Downloading New JUCE Version",
targetFolderPath + "\n\nis a GIT repository!\n\nYou should use a \"git pull\" to update it to the latest version.");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Downloading New JUCE Version",
targetFolderPath + "\n\n"
"is a GIT repository!\n\n"
"You should use a \"git pull\" to update it to the latest version.");
if (weakThis != nullptr)
weakThis->messageBox = AlertWindow::showScopedAsync (options, nullptr);
return;
}
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
"Overwrite Existing JUCE Folder?",
"Do you want to replace the folder\n\n" + targetFolderPath + "\n\nwith the latest version from juce.com?\n\n"
"This will move the existing folder to " + targetFolderPath + "_old.\n\n"
"Replacing the folder that contains the currently running Projucer executable may not work on Windows.",
{},
{},
nullptr,
ModalCallbackFunction::create (onResult));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
"Overwrite Existing JUCE Folder?",
"Do you want to replace the folder\n\n" + targetFolderPath + "\n\n"
"with the latest version from juce.com?\n\n"
"This will move the existing folder to " + targetFolderPath + "_old.\n\n"
"Replacing the folder that contains the currently running Projucer executable may not work on Windows.");
if (weakThis != nullptr)
weakThis->messageBox = AlertWindow::showScopedAsync (options, onResult);
return;
}
if (targetFolder.exists())
{
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
"Existing File Or Directory",
"Do you want to move\n\n" + targetFolderPath + "\n\nto\n\n" + targetFolderPath + "_old?",
{},
{},
nullptr,
ModalCallbackFunction::create (onResult));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
"Existing File Or Directory",
"Do you want to move\n\n" + targetFolderPath + "\n\n"
"to\n\n" + targetFolderPath + "_old?");
if (weakThis != nullptr)
weakThis->messageBox = AlertWindow::showScopedAsync (options, onResult);
return;
}
@ -369,7 +383,7 @@ void LatestVersionCheckerAndUpdater::addNotificationToOpenProjects (const Versio
class DownloadAndInstallThread : private ThreadWithProgressWindow
{
public:
DownloadAndInstallThread (const VersionInfo::Asset& a, const File& t, std::function<void()>&& cb)
DownloadAndInstallThread (const VersionInfo::Asset& a, const File& t, std::function<void (Result)>&& cb)
: ThreadWithProgressWindow ("Downloading New Version", true, true),
asset (a), targetFolder (t), completionCallback (std::move (cb))
{
@ -387,12 +401,10 @@ private:
if (result.wasOk() && ! threadShouldExit())
result = install (zipData);
if (result.failed())
MessageManager::callAsync ([result] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Installation Failed",
result.getErrorMessage()); });
else
MessageManager::callAsync (completionCallback);
MessageManager::callAsync ([result, callback = completionCallback]
{
callback (result);
});
}
Result download (MemoryBlock& dest)
@ -517,7 +529,7 @@ private:
VersionInfo::Asset asset;
File targetFolder;
std::function<void()> completionCallback;
std::function<void (Result)> completionCallback;
};
static void restartProcess (const File& targetFolder)
@ -548,12 +560,22 @@ static void restartProcess (const File& targetFolder)
void LatestVersionCheckerAndUpdater::downloadAndInstall (const VersionInfo::Asset& asset, const File& targetFolder)
{
installer.reset (new DownloadAndInstallThread (asset, targetFolder,
[this, targetFolder]
{
installer.reset();
restartProcess (targetFolder);
}));
installer.reset (new DownloadAndInstallThread (asset, targetFolder, [this, targetFolder] (const auto result)
{
if (result.failed())
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Installation Failed",
result.getErrorMessage());
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else
{
installer.reset();
restartProcess (targetFolder);
}
}));
}
//==============================================================================

View file

@ -57,6 +57,7 @@ private:
std::unique_ptr<DownloadAndInstallThread> installer;
std::unique_ptr<Component> dialogWindow;
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
JUCE_DECLARE_WEAK_REFERENCEABLE (LatestVersionCheckerAndUpdater)
};

View file

@ -462,9 +462,10 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba
if (generatorResult != Result::ok())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"PIP Error.",
generatorResult.getErrorMessage());
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"PIP Error.",
generatorResult.getErrorMessage());
messageBox = AlertWindow::showScopedAsync (options, nullptr);
if (callback != nullptr)
callback (false);
@ -474,9 +475,10 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba
if (! generator->createMainCpp())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"PIP Error.",
"Failed to create Main.cpp.");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"PIP Error.",
"Failed to create Main.cpp.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
if (callback != nullptr)
callback (false);
@ -491,9 +493,10 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba
if (! openedSuccessfully)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"PIP Error.",
"Failed to open .jucer file.");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"PIP Error.",
"Failed to open .jucer file.");
parent->messageBox = AlertWindow::showScopedAsync (options, nullptr);
if (callback != nullptr)
callback (false);

View file

@ -104,6 +104,8 @@ private:
std::unique_ptr<Component> blurOverlayComponent;
bool loginFormOpen = false;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};

View file

@ -176,15 +176,14 @@ void OpenDocumentManager::saveIfNeededAndUserAgrees (OpenDocumentManager::Docume
return;
}
AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon,
TRANS("Closing document..."),
TRANS("Do you want to save the changes to \"")
+ doc->getName() + "\"?",
TRANS("Save"),
TRANS("Discard changes"),
TRANS("Cancel"),
nullptr,
ModalCallbackFunction::create ([parent = WeakReference<OpenDocumentManager> { this }, doc, callback] (int r)
auto options = MessageBoxOptions::makeOptionsYesNoCancel (MessageBoxIconType::QuestionIcon,
TRANS ("Closing document..."),
TRANS ("Do you want to save the changes to \"")
+ doc->getName() + "\"?",
TRANS ("Save"),
TRANS ("Discard changes"),
TRANS ("Cancel"));
messageBox = AlertWindow::showScopedAsync (options, [parent = WeakReference<OpenDocumentManager> { this }, doc, callback] (int r)
{
if (parent == nullptr)
return;
@ -204,7 +203,7 @@ void OpenDocumentManager::saveIfNeededAndUserAgrees (OpenDocumentManager::Docume
if (callback != nullptr)
callback (r == 2 ? FileBasedDocument::savedOk : FileBasedDocument::userCancelledSave);
}));
});
}
bool OpenDocumentManager::closeDocumentWithoutSaving (Document* doc)

View file

@ -108,8 +108,7 @@ public:
class DocumentType
{
public:
DocumentType() {}
virtual ~DocumentType() {}
virtual ~DocumentType() = default;
virtual bool canOpenFile (const File& file) = 0;
virtual Document* openFile (Project* project, const File& file) = 0;
@ -117,7 +116,6 @@ public:
void registerType (DocumentType* type, int index = -1);
private:
//==============================================================================
void closeLastDocumentUsingProjectRecursive (WeakReference<OpenDocumentManager>,
@ -129,6 +127,7 @@ private:
OwnedArray<DocumentType> types;
OwnedArray<Document> documents;
Array<DocumentCloseListener*> listeners;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenDocumentManager)
JUCE_DECLARE_WEAK_REFERENCEABLE (OpenDocumentManager)

View file

@ -265,8 +265,11 @@ void ResourceEditorPanel::reloadAll()
failed.add (document.getResources().getResourceNames() [i]);
if (failed.size() > 0)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Reloading resources"),
TRANS("The following resources couldn't be reloaded from their original files:\n\n")
+ failed.joinIntoString (", "));
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Reloading resources"),
TRANS ("The following resources couldn't be reloaded from their original files:\n\n")
+ failed.joinIntoString (", "));
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}

View file

@ -56,4 +56,5 @@ private:
JucerDocument& document;
std::unique_ptr<TableListBox> listBox;
TextButton addButton, reloadAllButton, delButton;
ScopedMessageBox messageBox;
};

View file

@ -160,9 +160,10 @@ void BinaryResources::browseForResource (const String& title,
{
if (! safeThis->add (resourceName, result))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Adding Resource"),
TRANS("Failed to load the file!"));
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Adding Resource"),
TRANS ("Failed to load the file!"));
safeThis->messageBox = AlertWindow::showScopedAsync (options, nullptr);
resourceName.clear();
}

View file

@ -93,6 +93,7 @@ private:
JucerDocument* document;
OwnedArray<BinaryResource> resources;
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_WEAK_REFERENCEABLE (BinaryResources)

View file

@ -687,19 +687,24 @@ void EnabledModulesList::addModuleOfferingToCopy (const File& f, bool isFromUser
if (! m.isValid())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
"Add Module", "This wasn't a valid module folder!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"Add Module",
"This wasn't a valid module folder!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
return;
}
if (isModuleEnabled (m.getID()))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
"Add Module", "The project already contains this module!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
"Add Module",
"The project already contains this module!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
return;
}
addModule (m.getModuleFolder(), areMostModulesCopiedLocally(),
addModule (m.getModuleFolder(),
areMostModulesCopiedLocally(),
isFromUserSpecifiedFolder ? false : areMostModulesUsingGlobalPath());
}

View file

@ -143,6 +143,7 @@ private:
ValueTree state;
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModulesList)
};

View file

@ -77,7 +77,10 @@ public:
void deleteItem() override
{
auto resultCallback = [safeThis = WeakReference<ExporterItem> { this }] (int result)
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
"Delete Exporter",
"Are you sure you want to delete this export target?");
messageBox = AlertWindow::showScopedAsync (options, [safeThis = WeakReference { this }] (int result)
{
if (safeThis == nullptr || result == 0)
return;
@ -87,15 +90,7 @@ public:
auto parent = safeThis->exporter->settings.getParent();
parent.removeChild (safeThis->exporter->settings,
safeThis->project.getUndoManagerFor (parent));
};
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
"Delete Exporter",
"Are you sure you want to delete this export target?",
"",
"",
nullptr,
ModalCallbackFunction::create (std::move (resultCallback)));
});
}
void addSubItems() override
@ -180,6 +175,8 @@ private:
Value targetLocationValue;
ScopedMessageBox messageBox;
void valueChanged (Value& value) override
{
if (value == exporter->getTargetLocationValue())
@ -243,13 +240,10 @@ public:
void deleteItem() override
{
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
"Delete Configuration",
"Are you sure you want to delete this configuration?",
"",
"",
nullptr,
ModalCallbackFunction::create ([parent = WeakReference<ConfigItem> { this }] (int result)
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
"Delete Configuration",
"Are you sure you want to delete this configuration?");
messageBox = AlertWindow::showScopedAsync (options, [parent = WeakReference { this }] (int result)
{
if (parent == nullptr)
return;
@ -259,7 +253,7 @@ public:
parent->closeSettingsPage();
parent->config->removeFromExporter();
}));
});
}
void showPopupMenu (Point<int> p) override
@ -293,6 +287,7 @@ private:
ProjectExporter::BuildConfiguration::Ptr config;
ProjectExporter& exporter;
ValueTree configTree;
ScopedMessageBox messageBox;
//==============================================================================
class SettingsComp : public Component
@ -321,7 +316,6 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConfigItem)
JUCE_DECLARE_WEAK_REFERENCEABLE (ConfigItem)
};
//==============================================================================

View file

@ -138,15 +138,14 @@ public:
if (filesToTrash.size() > maxFilesToList)
fileList << "\n...plus " << (filesToTrash.size() - maxFilesToList) << " more files...";
AlertWindow::showYesNoCancelBox (MessageBoxIconType::NoIcon,
"Delete Project Items",
"As well as removing the selected item(s) from the project, do you also want to move their files to the trash:\n\n"
+ fileList,
"Just remove references",
"Also move files to Trash",
"Cancel",
tree->getTopLevelComponent(),
ModalCallbackFunction::create ([treeRootItem, filesToTrash, doDelete] (int r) mutable
auto options = MessageBoxOptions::makeOptionsYesNoCancel (MessageBoxIconType::NoIcon,
"Delete Project Items",
"As well as removing the selected item(s) from the project, do you also want to move their files to the trash:\n\n" + fileList,
"Just remove references",
"Also move files to Trash",
"Cancel",
tree->getTopLevelComponent());
messageBox = AlertWindow::showScopedAsync (options, [treeRootItem, filesToTrash, doDelete] (int r) mutable
{
if (treeRootItem == nullptr)
return;
@ -158,7 +157,7 @@ public:
filesToTrash.clear();
doDelete (filesToTrash);
}));
});
return;
}
@ -471,6 +470,8 @@ protected:
return -1;
}
ScopedMessageBox messageBox;
private:
std::unique_ptr<FileChooser> chooser;
@ -521,10 +522,13 @@ public:
{
if (newName != File::createLegalFileName (newName))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"File Rename",
"That filename contained some illegal characters!");
triggerAsyncRename (item);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"File Rename",
"That filename contained some illegal characters!");
messageBox = AlertWindow::showScopedAsync (options, [this, item = item] (int)
{
triggerAsyncRename (item);
});
return;
}
@ -538,42 +542,40 @@ public:
if (correspondingItem.isValid())
{
AlertWindow::showOkCancelBox (MessageBoxIconType::NoIcon,
"File Rename",
"Do you also want to rename the corresponding file \"" + correspondingFile.getFileName() + "\" to match?",
{},
{},
nullptr,
ModalCallbackFunction::create ([parent = WeakReference<SourceFileItem> { this },
oldFile, newFile, correspondingFile, correspondingItem] (int result) mutable
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::NoIcon,
"File Rename",
"Do you also want to rename the corresponding file \"" + correspondingFile.getFileName() + "\" to match?");
messageBox = AlertWindow::showScopedAsync (options, [parent = WeakReference { this }, oldFile, newFile, correspondingFile, correspondingItem] (int result) mutable
{
if (parent == nullptr || result == 0)
return;
if (! parent->item.renameFile (newFile))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename \"" + oldFile.getFullPathName() + "\"!\n\nCheck your file permissions!");
auto opts = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename \"" + oldFile.getFullPathName() + "\"!\n\nCheck your file permissions!");
parent->messageBox = AlertWindow::showScopedAsync (opts, nullptr);
return;
}
if (! correspondingItem.renameFile (newFile.withFileExtension (correspondingFile.getFileExtension())))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename \"" + correspondingFile.getFullPathName() + "\"!\n\nCheck your file permissions!");
auto opts = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename \"" + correspondingFile.getFullPathName() + "\"!\n\nCheck your file permissions!");
parent->messageBox = AlertWindow::showScopedAsync (opts, nullptr);
}
}));
});
}
}
if (! item.renameFile (newFile))
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename the file!\n\nCheck your file permissions!");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"File Rename",
"Failed to rename the file!\n\nCheck your file permissions!");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}

View file

@ -375,10 +375,11 @@ private:
{
missingDependencies = enabledModules.getExtraDependenciesNeeded (moduleID);
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Adding Missing Dependencies",
"Couldn't locate some of these modules - you'll need to find their "
"folders manually and add them to the list.");
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Adding Missing Dependencies",
"Couldn't locate some of these modules - you'll need to find their "
"folders manually and add them to the list.");
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
@ -393,6 +394,7 @@ private:
String moduleID;
StringArray missingDependencies;
TextButton fixButton { "Add Required Modules" };
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MissingDependenciesComponent)
};

View file

@ -318,25 +318,26 @@ void ProjectContentComponent::closeDocument()
hideEditor();
}
static void showSaveWarning (OpenDocumentManager::Document* currentDocument)
static ScopedMessageBox showSaveWarning (OpenDocumentManager::Document* currentDocument)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Save failed!"),
TRANS("Couldn't save the file:")
+ "\n" + currentDocument->getFile().getFullPathName());
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Save failed!"),
TRANS ("Couldn't save the file:")
+ "\n" + currentDocument->getFile().getFullPathName());
return AlertWindow::showScopedAsync (options, nullptr);
}
void ProjectContentComponent::saveDocumentAsync()
{
if (currentDocument != nullptr)
{
currentDocument->saveAsync ([parent = SafePointer<ProjectContentComponent> { this }] (bool savedSuccessfully)
currentDocument->saveAsync ([parent = SafePointer { this }] (bool savedSuccessfully)
{
if (parent == nullptr)
return;
if (! savedSuccessfully)
showSaveWarning (parent->currentDocument);
parent->messageBox = showSaveWarning (parent->currentDocument);
parent->refreshProjectTreeFileStatuses();
});
@ -351,13 +352,13 @@ void ProjectContentComponent::saveAsAsync()
{
if (currentDocument != nullptr)
{
currentDocument->saveAsAsync ([parent = SafePointer<ProjectContentComponent> { this }] (bool savedSuccessfully)
currentDocument->saveAsAsync ([parent = SafePointer { this }] (bool savedSuccessfully)
{
if (parent == nullptr)
return;
if (! savedSuccessfully)
showSaveWarning (parent->currentDocument);
parent->messageBox = showSaveWarning (parent->currentDocument);
parent->refreshProjectTreeFileStatuses();
});

View file

@ -147,6 +147,7 @@ private:
int lastViewedTab = 0;
std::unique_ptr<WizardHolder> wizardHolder;
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectContentComponent)

View file

@ -462,7 +462,8 @@ void Project::removeDefunctExporters()
warningMessage << "\n"
<< TRANS ("These exporters have been removed from the project. If you save the project they will be also erased from the .jucer file.");
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, warningTitle, warningMessage);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon, warningTitle, warningMessage);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
}

View file

@ -659,6 +659,7 @@ private:
std::unique_ptr<FileChooser> chooser;
std::unique_ptr<ProjectSaver> saver;
ScopedMessageBox messageBox;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Project)

View file

@ -771,10 +771,16 @@ public:
"Since JUCE 4.2, this is instead done using \"AU/VST/VST2/AAX Binary Location\" in the Xcode (OS X) configuration settings.\n\n"
"Click 'Update' to remove the script (otherwise your plug-in may not compile correctly).";
if (AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
"Project settings: " + project.getDocumentTitle(),
alertWindowText, "Update", "Cancel", nullptr, nullptr))
postbuildCommandValue.resetToDefault();
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
"Project settings: " + project.getDocumentTitle(),
alertWindowText,
"Update",
"Cancel");
messageBox = AlertWindow::showScopedAsync (options, [this] (int result)
{
if (result != 0)
postbuildCommandValue.resetToDefault();
});
}
}
@ -3637,6 +3643,7 @@ private:
iosContentSharingValue, iosBackgroundAudioValue, iosBackgroundBleValue, iosPushNotificationsValue, iosAppGroupsValue, iCloudPermissionsValue,
networkingMulticastValue, iosDevelopmentTeamIDValue, iosAppGroupsIDValue, keepCustomXcodeSchemesValue, useHeaderMapValue, customLaunchStoryboardValue,
exporterBundleIdentifierValue, suppressPlistResourceUsageValue, useLegacyBuildSystemValue, buildNumber;
ScopedMessageBox messageBox;
struct SandboxFileAccessProperty
{

View file

@ -64,14 +64,14 @@ public:
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.cpp", "*.cpp", parent, [parent] (File newFile)
askUserToChooseNewFile ("SourceCode.cpp", "*.cpp", parent, [this, parent] (File newFile)
{
if (newFile != File())
create (parent, newFile, "jucer_NewCppFileTemplate_cpp");
create (*this, parent, newFile, "jucer_NewCppFileTemplate_cpp");
});
}
static bool create (Project::Item parent, const File& newFile, const char* templateName)
static bool create (NewFileWizard::Type& wizard, Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
@ -79,7 +79,7 @@ public:
return true;
}
showFailedToWriteMessage (newFile);
wizard.showFailedToWriteMessage (newFile);
return false;
}
};
@ -92,14 +92,14 @@ public:
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.h", "*.h", parent, [parent] (File newFile)
askUserToChooseNewFile ("SourceCode.h", "*.h", parent, [this, parent] (File newFile)
{
if (newFile != File())
create (parent, newFile, "jucer_NewCppFileTemplate_h");
create (*this, parent, newFile, "jucer_NewCppFileTemplate_h");
});
}
static bool create (Project::Item parent, const File& newFile, const char* templateName)
static bool create (NewFileWizard::Type& wizard, Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
@ -107,7 +107,7 @@ public:
return true;
}
showFailedToWriteMessage (newFile);
wizard.showFailedToWriteMessage (newFile);
return false;
}
};
@ -120,10 +120,10 @@ public:
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.h", "*.h;*.cpp", parent, [parent] (File newFile)
askUserToChooseNewFile ("SourceCode.h", "*.h;*.cpp", parent, [this, parent] (File newFile)
{
if (NewCppFileWizard::create (parent, newFile.withFileExtension ("h"), "jucer_NewCppFileTemplate_h"))
NewCppFileWizard::create (parent, newFile.withFileExtension ("cpp"), "jucer_NewCppFileTemplate_cpp");
if (NewCppFileWizard::create (*this, parent, newFile.withFileExtension ("h"), "jucer_NewCppFileTemplate_h"))
NewCppFileWizard::create (*this, parent, newFile.withFileExtension ("cpp"), "jucer_NewCppFileTemplate_cpp");
});
}
};
@ -139,7 +139,7 @@ public:
createNewFileInternal (parent);
}
static bool create (const String& className, Project::Item parent,
static bool create (NewFileWizard::Type& wizard, const String& className, Project::Item parent,
const File& newFile, const char* templateName)
{
auto content = fillInBasicTemplateFields (newFile, parent, templateName)
@ -154,15 +154,15 @@ public:
return true;
}
showFailedToWriteMessage (newFile);
wizard.showFailedToWriteMessage (newFile);
return false;
}
private:
virtual void createFiles (Project::Item parent, const String& className, const File& newFile)
{
if (create (className, parent, newFile.withFileExtension ("h"), "jucer_NewComponentTemplate_h"))
create (className, parent, newFile.withFileExtension ("cpp"), "jucer_NewComponentTemplate_cpp");
if (create (*this, className, parent, newFile.withFileExtension ("h"), "jucer_NewComponentTemplate_h"))
create (*this, className, parent, newFile.withFileExtension ("cpp"), "jucer_NewComponentTemplate_cpp");
}
static String getClassNameFieldName() { return "Class Name"; }
@ -227,17 +227,17 @@ public:
void createFiles (Project::Item parent, const String& className, const File& newFile) override
{
create (className, parent, newFile.withFileExtension ("h"), "jucer_NewInlineComponentTemplate_h");
create (*this, className, parent, newFile.withFileExtension ("h"), "jucer_NewInlineComponentTemplate_h");
}
};
//==============================================================================
void NewFileWizard::Type::showFailedToWriteMessage (const File& file)
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
"Failed to Create File!",
"Couldn't write to the file: " + file.getFullPathName());
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Failed to Create File!",
"Couldn't write to the file: " + file.getFullPathName());
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
void NewFileWizard::Type::askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,

View file

@ -39,23 +39,23 @@ public:
class Type
{
public:
Type() {}
virtual ~Type() {}
virtual ~Type() = default;
//==============================================================================
virtual String getName() = 0;
virtual void createNewFile (Project&, Project::Item projectGroupToAddTo) = 0;
void showFailedToWriteMessage (const File& file);
protected:
//==============================================================================
void askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,
const Project::Item& projectGroupToAddTo,
std::function<void (File)> callback);
static void showFailedToWriteMessage (const File& file);
private:
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
};
//==============================================================================

View file

@ -209,9 +209,12 @@ public:
processor->getStateInformation (data);
if (! fc.getResult().replaceWithData (data.getData(), data.getSize()))
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
TRANS("Error whilst saving"),
TRANS("Couldn't write to the specified file!"));
{
auto opts = MessageBoxOptions::makeOptionsOk (AlertWindow::WarningIcon,
TRANS ("Error whilst saving"),
TRANS ("Couldn't write to the specified file!"));
messageBox = AlertWindow::showScopedAsync (opts, nullptr);
}
});
}
@ -234,11 +237,16 @@ public:
MemoryBlock data;
if (fc.getResult().loadFileAsData (data))
{
processor->setStateInformation (data.getData(), (int) data.getSize());
}
else
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
TRANS("Error whilst loading"),
TRANS("Couldn't read from the specified file!"));
{
auto opts = MessageBoxOptions::makeOptionsOk (AlertWindow::WarningIcon,
TRANS ("Error whilst loading"),
TRANS ("Couldn't read from the specified file!"));
messageBox = AlertWindow::showScopedAsync (opts, nullptr);
}
});
}
@ -417,6 +425,7 @@ public:
Array<MidiDeviceInfo> lastMidiDevices;
std::unique_ptr<FileChooser> stateFileChooser;
ScopedMessageBox messageBox;
private:
/* This class can be used to ensure that audio callbacks use buffers with a

View file

@ -64,7 +64,7 @@ public:
if (columnId == nameCol)
text = list.getBlacklistedFiles() [row - list.getNumTypes()];
else if (columnId == descCol)
text = TRANS("Deactivated after failing to initialise correctly");
text = TRANS ("Deactivated after failing to initialise correctly");
}
else
{
@ -155,11 +155,11 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, Kno
TableHeaderComponent& header = table.getHeader();
header.addColumn (TRANS("Name"), TableModel::nameCol, 200, 100, 700, TableHeaderComponent::defaultFlags | TableHeaderComponent::sortedForwards);
header.addColumn (TRANS("Format"), TableModel::typeCol, 80, 80, 80, TableHeaderComponent::notResizable);
header.addColumn (TRANS("Category"), TableModel::categoryCol, 100, 100, 200);
header.addColumn (TRANS("Manufacturer"), TableModel::manufacturerCol, 200, 100, 300);
header.addColumn (TRANS("Description"), TableModel::descCol, 300, 100, 500, TableHeaderComponent::notSortable);
header.addColumn (TRANS ("Name"), TableModel::nameCol, 200, 100, 700, TableHeaderComponent::defaultFlags | TableHeaderComponent::sortedForwards);
header.addColumn (TRANS ("Format"), TableModel::typeCol, 80, 80, 80, TableHeaderComponent::notResizable);
header.addColumn (TRANS ("Category"), TableModel::categoryCol, 100, 100, 200);
header.addColumn (TRANS ("Manufacturer"), TableModel::manufacturerCol, 200, 100, 300);
header.addColumn (TRANS ("Description"), TableModel::descCol, 300, 100, 500, TableHeaderComponent::notSortable);
table.setHeaderHeight (22);
table.setRowHeight (20);
@ -289,7 +289,7 @@ void PluginListComponent::removePluginItem (int index)
PopupMenu PluginListComponent::createOptionsMenu()
{
PopupMenu menu;
menu.addItem (PopupMenu::Item (TRANS("Clear list"))
menu.addItem (PopupMenu::Item (TRANS ("Clear list"))
.setAction ([this] { list.clear(); }));
menu.addSeparator();
@ -306,18 +306,18 @@ PopupMenu PluginListComponent::createOptionsMenu()
menu.addSeparator();
menu.addItem (PopupMenu::Item (TRANS("Remove selected plug-in from list"))
menu.addItem (PopupMenu::Item (TRANS ("Remove selected plug-in from list"))
.setEnabled (table.getNumSelectedRows() > 0)
.setAction ([this] { removeSelectedPlugins(); }));
menu.addItem (PopupMenu::Item (TRANS("Remove any plug-ins whose files no longer exist"))
menu.addItem (PopupMenu::Item (TRANS ("Remove any plug-ins whose files no longer exist"))
.setAction ([this] { removeMissingPlugins(); }));
menu.addSeparator();
auto selectedRow = table.getSelectedRow();
menu.addItem (PopupMenu::Item (TRANS("Show folder containing selected plug-in"))
menu.addItem (PopupMenu::Item (TRANS ("Show folder containing selected plug-in"))
.setEnabled (canShowFolderForPlugin (list, selectedRow))
.setAction ([this, selectedRow] { showFolderForPlugin (list, selectedRow); }));
@ -337,10 +337,10 @@ PopupMenu PluginListComponent::createMenuForRow (int rowNumber)
if (rowNumber >= 0 && rowNumber < tableModel->getNumRows())
{
menu.addItem (PopupMenu::Item (TRANS("Remove plug-in from list"))
menu.addItem (PopupMenu::Item (TRANS ("Remove plug-in from list"))
.setAction ([this, rowNumber] { removePluginItem (rowNumber); }));
menu.addItem (PopupMenu::Item (TRANS("Show folder containing plug-in"))
menu.addItem (PopupMenu::Item (TRANS ("Show folder containing plug-in"))
.setEnabled (canShowFolderForPlugin (list, rowNumber))
.setAction ([this, rowNumber] { showFolderForPlugin (list, rowNumber); }));
}
@ -391,7 +391,7 @@ public:
formatToScan (format),
filesOrIdentifiersToScan (filesOrIdentifiers),
propertiesToUse (properties),
pathChooserWindow (TRANS("Select folders to scan..."), String(), MessageBoxIconType::NoIcon),
pathChooserWindow (TRANS ("Select folders to scan..."), String(), MessageBoxIconType::NoIcon),
progressWindow (title, text, MessageBoxIconType::NoIcon),
numThreads (threads),
allowAsync (allowPluginsWhichRequireAsynchronousInstantiation)
@ -417,8 +417,8 @@ public:
pathList.setPath (path);
pathChooserWindow.addCustomComponent (&pathList);
pathChooserWindow.addButton (TRANS("Scan"), 1, KeyPress (KeyPress::returnKey));
pathChooserWindow.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
pathChooserWindow.addButton (TRANS ("Scan"), 1, KeyPress (KeyPress::returnKey));
pathChooserWindow.addButton (TRANS ("Cancel"), 0, KeyPress (KeyPress::escapeKey));
pathChooserWindow.enterModalState (true,
ModalCallbackFunction::forComponent (startScanCallback,
@ -455,6 +455,7 @@ private:
std::atomic<bool> finished { false };
std::unique_ptr<ThreadPool> pool;
std::set<String> initiallyBlacklistedFiles;
ScopedMessageBox messageBox;
static void startScanCallback (int result, AlertWindow* alert, Scanner* scanner)
{
@ -476,18 +477,23 @@ private:
if (File::isAbsolutePath (f) && isStupidPath (File (f)))
{
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
TRANS("Plugin Scanning"),
TRANS("If you choose to scan folders that contain non-plugin files, "
"then scanning may take a long time, and can cause crashes when "
"attempting to load unsuitable files.")
+ newLine
+ TRANS ("Are you sure you want to scan the folder \"XYZ\"?")
.replace ("XYZ", f),
TRANS ("Scan"),
String(),
nullptr,
ModalCallbackFunction::create (warnAboutStupidPathsCallback, this));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
TRANS ("Plugin Scanning"),
TRANS ("If you choose to scan folders that contain non-plugin files, "
"then scanning may take a long time, and can cause crashes when "
"attempting to load unsuitable files.")
+ newLine
+ TRANS ("Are you sure you want to scan the folder \"XYZ\"?")
.replace ("XYZ", f),
TRANS ("Scan"));
messageBox = AlertWindow::showScopedAsync (options, [this] (int result)
{
if (result != 0)
startScan();
else
finishedScan();
});
return;
}
}
@ -524,14 +530,6 @@ private:
return false;
}
static void warnAboutStupidPathsCallback (int result, Scanner* scanner)
{
if (result != 0)
scanner->startScan();
else
scanner->finishedScan();
}
void startScan()
{
pathChooserWindow.setVisible (false);
@ -549,7 +547,7 @@ private:
propertiesToUse->saveIfNeeded();
}
progressWindow.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
progressWindow.addButton (TRANS ("Cancel"), 0, KeyPress (KeyPress::escapeKey));
progressWindow.addProgressBarComponent (progress);
progressWindow.enterModalState();
@ -599,7 +597,7 @@ private:
if (finished)
finishedScan();
else
progressWindow.setMessage (TRANS("Testing") + ":\n\n" + pluginBeingScanned);
progressWindow.setMessage (TRANS ("Testing") + ":\n\n" + pluginBeingScanned);
}
bool doNextScan()
@ -639,8 +637,8 @@ void PluginListComponent::scanFor (AudioPluginFormat& format)
void PluginListComponent::scanFor (AudioPluginFormat& format, const StringArray& filesOrIdentifiersToScan)
{
currentScanner.reset (new Scanner (*this, format, filesOrIdentifiersToScan, propertiesToUse, allowAsync, numThreads,
dialogTitle.isNotEmpty() ? dialogTitle : TRANS("Scanning for plug-ins..."),
dialogText.isNotEmpty() ? dialogText : TRANS("Searching for all possible plug-in files...")));
dialogTitle.isNotEmpty() ? dialogTitle : TRANS ("Scanning for plug-ins..."),
dialogText.isNotEmpty() ? dialogText : TRANS ("Searching for all possible plug-in files...")));
}
bool PluginListComponent::isScanning() const noexcept
@ -672,9 +670,12 @@ void PluginListComponent::scanFinished (const StringArray& failedFiles,
currentScanner.reset(); // mustn't delete this before using the failed files array
if (! warnings.isEmpty())
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
TRANS("Scan complete"),
warnings.joinIntoString ("\n\n"));
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
TRANS ("Scan complete"),
warnings.joinIntoString ("\n\n"));
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
}
} // namespace juce

View file

@ -130,6 +130,8 @@ private:
class Scanner;
std::unique_ptr<Scanner> currentScanner;
ScopedMessageBox messageBox;
void scanFinished (const StringArray&, const std::vector<String>&);
void updateList();
void removeMissingPlugins();

View file

@ -401,9 +401,11 @@ public:
}
if (error.isNotEmpty())
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Error when trying to open audio device!"),
error);
messageBox = AlertWindow::showScopedAsync (MessageBoxOptions().withIconType (MessageBoxIconType::WarningIcon)
.withTitle (TRANS ("Error when trying to open audio device!"))
.withMessage (error)
.withButton (TRANS ("OK")),
nullptr);
}
bool showDeviceControlPanel()
@ -966,6 +968,7 @@ public:
private:
std::unique_ptr<ChannelSelectorListBox> inputChanList, outputChanList;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioDeviceSettingsPanel)
};

View file

@ -182,28 +182,26 @@ void FileChooserDialogBox::fileDoubleClicked (const File&)
void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) {}
void FileChooserDialogBox::browserRootChanged (const File&) {}
void FileChooserDialogBox::okToOverwriteFileCallback (int result, FileChooserDialogBox* box)
{
if (result != 0 && box != nullptr)
box->exitModalState (1);
}
void FileChooserDialogBox::okButtonPressed()
{
if (warnAboutOverwritingExistingFiles
&& content->chooserComponent.isSaveMode()
&& content->chooserComponent.getSelectedFile(0).exists())
{
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
TRANS("File already exists"),
TRANS("There's already a file called: FLNM")
.replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName())
+ "\n\n"
+ TRANS("Are you sure you want to overwrite it?"),
TRANS("Overwrite"),
TRANS("Cancel"),
this,
ModalCallbackFunction::forComponent (okToOverwriteFileCallback, this));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
TRANS ("File already exists"),
TRANS ("There's already a file called: FLNM")
.replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName())
+ "\n\n"
+ TRANS ("Are you sure you want to overwrite it?"),
TRANS ("Overwrite"),
TRANS ("Cancel"),
this);
messageBox = AlertWindow::showScopedAsync (options, [this] (int result)
{
if (result != 0)
exitModalState (1);
});
}
else
{
@ -251,9 +249,12 @@ void FileChooserDialogBox::createNewFolderConfirmed (const String& nameFromDialo
auto parent = content->chooserComponent.getRoot();
if (! parent.getChildFile (name).createDirectory())
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS ("New Folder"),
TRANS ("Couldn't create the folder!"));
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("New Folder"),
TRANS ("Couldn't create the folder!"));
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
content->chooserComponent.refresh();
}

View file

@ -158,9 +158,10 @@ private:
void createNewFolder();
void createNewFolderConfirmed (const String& name);
static void okToOverwriteFileCallback (int result, FileChooserDialogBox*);
static void createNewFolderCallback (int result, FileChooserDialogBox*, Component::SafePointer<AlertWindow>);
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileChooserDialogBox)
};

View file

@ -26,10 +26,59 @@
namespace juce
{
template <ScopedMessageBox::Pimpl::MapFn mapFn = nullptr>
static int showNativeBoxUnmanaged (const MessageBoxOptions& opts, ModalComponentManager::Callback* cb)
enum class ResultCodeMappingMode
{
return ScopedMessageBox::Pimpl::showUnmanaged<mapFn> (ScopedMessageBoxInterface::create (opts), cb);
plainIndex, // The result code is equal to the index of the selected button.
// This is used for NativeMessageBox::show, showAsync, and showMessageBox.
alertWindow, // The result code is mapped in the same way as AlertWindow, i.e. if there
// are N buttons then button X will return ((X + 1) % N).
};
static std::unique_ptr<ScopedMessageBoxInterface> makeNativeMessageBoxWithMappedResult (const MessageBoxOptions& opts,
ResultCodeMappingMode mode)
{
class Adapter : public ScopedMessageBoxInterface
{
public:
explicit Adapter (const MessageBoxOptions& options)
: inner (ScopedMessageBoxInterface::create (options)),
numButtons (options.getNumButtons()) {}
void runAsync (std::function<void (int)> fn) override
{
inner->runAsync ([fn, n = numButtons] (int result)
{
fn (map (result, n));
});
}
int runSync() override
{
return map (inner->runSync(), numButtons);
}
void close() override
{
inner->close();
}
private:
static int map (int button, int numButtons) { return (button + 1) % numButtons; }
std::unique_ptr<ScopedMessageBoxInterface> inner;
int numButtons = 0;
};
return mode == ResultCodeMappingMode::plainIndex ? ScopedMessageBoxInterface::create (opts)
: std::make_unique<Adapter> (opts);
}
static int showNativeBoxUnmanaged (const MessageBoxOptions& opts,
ModalComponentManager::Callback* cb,
ResultCodeMappingMode mode)
{
auto implementation = makeNativeMessageBoxWithMappedResult (opts, mode);
return ScopedMessageBox::Pimpl::showUnmanaged (std::move (implementation), cb);
}
#if JUCE_MODAL_LOOPS_PERMITTED
@ -37,17 +86,18 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType iconType
const String& title, const String& message,
Component* associatedComponent)
{
showNativeBoxUnmanaged<ScopedMessageBox::Pimpl::messageBox> (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("OK"))
.withAssociatedComponent (associatedComponent),
nullptr);
showNativeBoxUnmanaged (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("OK"))
.withAssociatedComponent (associatedComponent),
nullptr,
ResultCodeMappingMode::plainIndex);
}
int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options)
{
return showNativeBoxUnmanaged<> (options, nullptr);
return showNativeBoxUnmanaged (options, nullptr, ResultCodeMappingMode::plainIndex);
}
#endif
@ -56,12 +106,8 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType ico
Component* associatedComponent,
ModalComponentManager::Callback* callback)
{
showNativeBoxUnmanaged<ScopedMessageBox::Pimpl::messageBox> (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("OK"))
.withAssociatedComponent (associatedComponent),
callback);
auto options = MessageBoxOptions::makeOptionsOk (iconType, title, message, {}, associatedComponent);
showNativeBoxUnmanaged (options, callback, ResultCodeMappingMode::alertWindow);
}
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconType,
@ -69,13 +115,8 @@ bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconTyp
Component* associatedComponent,
ModalComponentManager::Callback* callback)
{
return showNativeBoxUnmanaged<ScopedMessageBox::Pimpl::okCancel> (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("OK"))
.withButton (TRANS("Cancel"))
.withAssociatedComponent (associatedComponent),
callback) != 0;
auto options = MessageBoxOptions::makeOptionsOkCancel (iconType, title, message, {}, {}, associatedComponent);
return showNativeBoxUnmanaged (options, callback, ResultCodeMappingMode::alertWindow) != 0;
}
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconType,
@ -83,14 +124,8 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconT
Component* associatedComponent,
ModalComponentManager::Callback* callback)
{
return showNativeBoxUnmanaged<ScopedMessageBox::Pimpl::yesNoCancel> (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("Yes"))
.withButton (TRANS("No"))
.withButton (TRANS("Cancel"))
.withAssociatedComponent (associatedComponent),
callback);
auto options = MessageBoxOptions::makeOptionsYesNoCancel (iconType, title, message, {}, {}, {}, associatedComponent);
return showNativeBoxUnmanaged (options, callback, ResultCodeMappingMode::alertWindow);
}
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType,
@ -98,19 +133,14 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType,
Component* associatedComponent,
ModalComponentManager::Callback* callback)
{
return showNativeBoxUnmanaged<ScopedMessageBox::Pimpl::okCancel> (MessageBoxOptions().withIconType (iconType)
.withTitle (title)
.withMessage (message)
.withButton (TRANS("Yes"))
.withButton (TRANS("No"))
.withAssociatedComponent (associatedComponent),
callback);
auto options = MessageBoxOptions::makeOptionsYesNo (iconType, title, message, {}, {}, associatedComponent);
return showNativeBoxUnmanaged (options, callback, ResultCodeMappingMode::alertWindow);
}
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
ModalComponentManager::Callback* callback)
{
showNativeBoxUnmanaged<> (options, callback);
showNativeBoxUnmanaged (options, callback, ResultCodeMappingMode::plainIndex);
}
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
@ -121,7 +151,8 @@ void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options
ScopedMessageBox NativeMessageBox::showScopedAsync (const MessageBoxOptions& options, std::function<void (int)> callback)
{
return ScopedMessageBox::Pimpl::show (ScopedMessageBoxInterface::create (options), std::move (callback));
auto implementation = makeNativeMessageBoxWithMappedResult (options, ResultCodeMappingMode::alertWindow);
return ScopedMessageBox::Pimpl::show (std::move (implementation), std::move (callback));
}
} // namespace juce

View file

@ -262,6 +262,23 @@ public:
The box will be displayed and placed into a modal state, but this method will return
immediately, and the callback will be invoked later when the user dismisses the box.
This function is always asynchronous, even if the callback is null.
For consistency with AlertWindow, the result codes returned by the alert window are as
follows.
- One button:
- button[0] returns 0
- Two buttons:
- button[0] returns 1
- button[1] returns 0
- Three buttons:
- button[0] returns 1
- button[1] returns 2
- button[2] returns 0
Another way of expressing this is that, when there are N buttons, then the result code for
button X is equal to ((X + 1) % N).
@param options the options to use when creating the dialog.
@param callback if this is non-null, the callback will receive a call to its
modalStateFinished() when the box is dismissed with the index of the

View file

@ -214,7 +214,7 @@ public:
[] (SafeParentPointer ptr, auto cb)
{
if (ptr != nullptr)
ptr->askToSaveChanges (ptr, std::move (cb));
ptr->askToSaveChangesAsync (ptr, std::move (cb));
},
[parent] (bool askUserForFileIfNotSpecified,
bool showMessageOnFailure,
@ -337,12 +337,15 @@ private:
MouseCursor::hideWaitCursor();
if (showMessageOnFailure)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS ("Failed to open file..."),
TRANS ("There was an error while trying to load the file: FLNM")
.replace ("FLNM", "\n" + newFile.getFullPathName())
+ "\n\n"
+ result.getErrorMessage());
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Failed to open file..."),
TRANS ("There was an error while trying to load the file: FLNM")
.replace ("FLNM", "\n" + newFile.getFullPathName())
+ "\n\n"
+ result.getErrorMessage());
parent->messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
if (completed != nullptr)
completed (result);
@ -435,28 +438,35 @@ private:
}
//==============================================================================
int askToSaveChanges (SafeParentPointer parent,
std::function<void (SafeParentPointer, int)> callback)
MessageBoxOptions getAskToSaveChangesOptions() const
{
auto* modalCallback = callback == nullptr
? nullptr
: ModalCallbackFunction::create ([parent, callback = std::move (callback)] (int alertResult)
{
if (parent != nullptr)
callback (parent, alertResult);
});
return AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon,
TRANS ("Closing document..."),
TRANS ("Do you want to save the changes to \"DCNM\"?")
.replace ("DCNM", document.getDocumentTitle()),
TRANS ("Save"),
TRANS ("Discard changes"),
TRANS ("Cancel"),
nullptr,
modalCallback);
return MessageBoxOptions::makeOptionsYesNoCancel (MessageBoxIconType::QuestionIcon,
TRANS ("Closing document..."),
TRANS ("Do you want to save the changes to \"DCNM\"?")
.replace ("DCNM", document.getDocumentTitle()),
TRANS ("Save"),
TRANS ("Discard changes"),
TRANS ("Cancel"));
}
void askToSaveChangesAsync (SafeParentPointer parent,
std::function<void (SafeParentPointer, int)> callback)
{
messageBox = AlertWindow::showScopedAsync (getAskToSaveChangesOptions(),
[parent, callback = std::move (callback)] (int alertResult)
{
if (parent != nullptr)
callback (parent, alertResult);
});
}
#if JUCE_MODAL_LOOPS_PERMITTED
int askToSaveChangesSync()
{
return AlertWindow::show (getAskToSaveChangesOptions());
}
#endif
//==============================================================================
template <typename DoSaveDocument>
void saveInternal (SafeParentPointer parent,
@ -508,13 +518,16 @@ private:
MouseCursor::hideWaitCursor();
if (showMessageOnFailure)
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS ("Error writing to file..."),
TRANS ("An error occurred while trying to save \"DCNM\" to the file: FLNM")
.replace ("DCNM", parent->document.getDocumentTitle())
.replace ("FLNM", "\n" + newFile.getFullPathName())
+ "\n\n"
+ result.getErrorMessage());
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Error writing to file..."),
TRANS ("An error occurred while trying to save \"DCNM\" to the file: FLNM")
.replace ("DCNM", parent->document.getDocumentTitle())
.replace ("FLNM", "\n" + newFile.getFullPathName())
+ "\n\n"
+ result.getErrorMessage());
parent->messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
parent->document.sendChangeMessage(); // because the filename may have changed
@ -615,7 +628,7 @@ private:
[] (SafeParentPointer ptr, const File& destination, std::function<void (SafeParentPointer, bool)> cb)
{
if (ptr != nullptr)
ptr->askToOverwriteFile (ptr, destination, std::move (cb));
ptr->askToOverwriteFileAsync (ptr, destination, std::move (cb));
},
[parent] (const File& destination, std::function<void (Result)> cb)
{
@ -660,38 +673,45 @@ private:
[] (SafeParentPointer ptr, const File& destination, auto cb)
{
if (ptr != nullptr)
ptr->askToOverwriteFile (ptr, destination, std::move (cb));
ptr->askToOverwriteFileAsync (ptr, destination, std::move (cb));
});
}
//==============================================================================
bool askToOverwriteFile (SafeParentPointer parent,
const File& newFile,
std::function<void (SafeParentPointer, bool)> callback)
MessageBoxOptions getAskToOverwriteFileOptions (const File& newFile) const
{
return MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
TRANS ("File already exists"),
TRANS ("There's already a file called: FLNM")
.replace ("FLNM", newFile.getFullPathName())
+ "\n\n"
+ TRANS ("Are you sure you want to overwrite it?"),
TRANS ("Overwrite"),
TRANS ("Cancel"));
}
void askToOverwriteFileAsync (SafeParentPointer parent,
const File& newFile,
std::function<void (SafeParentPointer, bool)> callback)
{
if (parent == nullptr)
return false;
return;
auto* modalCallback = callback == nullptr
? nullptr
: ModalCallbackFunction::create ([parent, callback = std::move (callback)] (int r)
{
if (parent != nullptr)
callback (parent, r == 1);
});
return AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
TRANS ("File already exists"),
TRANS ("There's already a file called: FLNM")
.replace ("FLNM", newFile.getFullPathName())
+ "\n\n"
+ TRANS ("Are you sure you want to overwrite it?"),
TRANS ("Overwrite"),
TRANS ("Cancel"),
nullptr,
modalCallback);
messageBox = AlertWindow::showScopedAsync (getAskToOverwriteFileOptions (newFile),
[parent, callback = std::move (callback)] (int r)
{
if (parent != nullptr)
callback (parent, r != 1);
});
}
#if JUCE_MODAL_LOOPS_PERMITTED
bool askToOverwriteFileSync (const File& newFile)
{
return AlertWindow::show (getAskToOverwriteFileOptions (newFile));
}
#endif
//==============================================================================
void getSaveAsFilenameAsync (SafeParentPointer parent,
bool warnAboutOverwritingExistingFiles,
@ -886,7 +906,7 @@ private:
template <typename Callback>
void askToSaveChangesSync (SafeParentPointer parent, Callback&& callback)
{
callback (parent, askToSaveChanges (parent, nullptr));
callback (parent, askToSaveChangesSync());
}
//==============================================================================
@ -908,7 +928,7 @@ private:
const File& newFile,
Callback&& callback)
{
callback (parent, askToOverwriteFile (parent, newFile, nullptr));
callback (parent, askToOverwriteFileSync (newFile));
}
//==============================================================================
@ -945,6 +965,7 @@ private:
bool changedSinceSave = false;
String fileExtension, fileWildcard, openFileDialogTitle, saveFileDialogTitle;
std::unique_ptr<FileChooser> asyncFc;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
JUCE_DECLARE_WEAK_REFERENCEABLE (Pimpl)

View file

@ -142,12 +142,6 @@ public:
JUCE_DECLARE_NON_COPYABLE (KeyEntryWindow)
};
static void assignNewKeyCallback (int result, ChangeKeyButton* button, KeyPress newKey)
{
if (result != 0 && button != nullptr)
button->setNewKey (newKey, true);
}
void setNewKey (const KeyPress& newKey, bool dontAskUser)
{
if (newKey.isValid())
@ -165,17 +159,20 @@ public:
}
else
{
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon,
TRANS("Change key-mapping"),
TRANS("This key is already assigned to the command \"CMDN\"")
.replace ("CMDN", owner.getCommandManager().getNameOfCommand (previousCommand))
+ "\n\n"
+ TRANS("Do you want to re-assign it to this new command instead?"),
TRANS("Re-assign"),
TRANS("Cancel"),
this,
ModalCallbackFunction::forComponent (assignNewKeyCallback,
this, KeyPress (newKey)));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::WarningIcon,
TRANS("Change key-mapping"),
TRANS("This key is already assigned to the command \"CMDN\"")
.replace ("CMDN", owner.getCommandManager().getNameOfCommand (previousCommand))
+ "\n\n"
+ TRANS("Do you want to re-assign it to this new command instead?"),
TRANS("Re-assign"),
TRANS("Cancel"),
this);
messageBox = AlertWindow::showScopedAsync (options, [this, newKey] (int result)
{
if (result != 0)
setNewKey (newKey, true);
});
}
}
}
@ -205,6 +202,7 @@ private:
const CommandID commandID;
const int keyNum;
std::unique_ptr<KeyEntryWindow> currentKeyEntryWindow;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChangeKeyButton)
};
@ -383,12 +381,6 @@ private:
KeyMappingEditorComponent& owner;
};
static void resetKeyMappingsToDefaultsCallback (int result, KeyMappingEditorComponent* owner)
{
if (result != 0 && owner != nullptr)
owner->getMappings().resetToDefaultMappings();
}
//==============================================================================
KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet& mappingManager,
const bool showResetToDefaultButton)
@ -403,12 +395,17 @@ KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet& mappin
resetButton.onClick = [this]
{
AlertWindow::showOkCancelBox (MessageBoxIconType::QuestionIcon,
TRANS("Reset to defaults"),
TRANS("Are you sure you want to reset all the key-mappings to their default state?"),
TRANS("Reset"),
{}, this,
ModalCallbackFunction::forComponent (resetKeyMappingsToDefaultsCallback, this));
auto options = MessageBoxOptions::makeOptionsOkCancel (MessageBoxIconType::QuestionIcon,
TRANS("Reset to defaults"),
TRANS("Are you sure you want to reset all the key-mappings to their default state?"),
TRANS("Reset"),
{},
this);
messageBox = AlertWindow::showScopedAsync (options, [this] (int result)
{
if (result != 0)
getMappings().resetToDefaultMappings();
});
};
}

View file

@ -125,6 +125,7 @@ private:
class CategoryItem;
class ItemComponent;
std::unique_ptr<TopLevelItem> treeItem;
ScopedMessageBox messageBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KeyMappingEditorComponent)
};

View file

@ -100,15 +100,17 @@ struct OnlineUnlockForm::OverlayComp : public Component,
if (result.errorMessage.isNotEmpty())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
TRANS("Registration Failed"),
result.errorMessage);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
TRANS ("Registration Failed"),
result.errorMessage);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else if (result.informativeMessage.isNotEmpty())
{
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon,
TRANS("Registration Complete!"),
result.informativeMessage);
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::InfoIcon,
TRANS ("Registration Complete!"),
result.informativeMessage);
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
else if (result.urlToLaunch.isNotEmpty())
{
@ -143,6 +145,7 @@ struct OnlineUnlockForm::OverlayComp : public Component,
Spinner spinner;
OnlineUnlockStatus::UnlockResult result;
String email, password;
ScopedMessageBox messageBox;
std::unique_ptr<TextButton> cancelButton;

View file

@ -111,7 +111,13 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver
int64 getContentLength() const override { return download.contentLength; }
Status getStatus() const override { return SKDownloadStateToDownloadStatus (download.downloadState); }
#else
int64 getContentLength() const override { return download.expectedContentLength; }
int64 getContentLength() const override
{
if (@available (macOS 10.15, *))
return download.expectedContentLength;
return download.contentLength.longLongValue;
}
Status getStatus() const override { return SKDownloadStateToDownloadStatus (download.state); }
#endif