- Add AlertWindow::show() and showAsync() methods that take a MessageBoxOptions argument - Add NativeMessageBox::show() and showAsync() methods that take a MessageBoxOptions argument - Update the DialogsDemo to demonstrate the new methods - Deprecate AlertWindow::showNativeDialogBox() in favour of the NativeMessageBox methods - Pass button strings specified in MesssageBoxOptions to native dialog boxes correctly - Use modern TaskDialog on Windows for the native dialog box where availablev6.1.6
@@ -612,7 +612,11 @@ private: | |||
auto u = fc.getURLResult(); | |||
if (! audioFileReader.loadURL (u)) | |||
NativeMessageBox::showOkCancelBox (AlertWindow::WarningIcon, "Error loading file", "Unable to load audio file", nullptr, nullptr); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::WarningIcon) | |||
.withTitle ("Error loading file") | |||
.withMessage ("Unable to load audio file"), | |||
nullptr); | |||
else | |||
thumbnailComp.setCurrentURL (u); | |||
} | |||
@@ -529,10 +529,13 @@ private: | |||
} | |||
else | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::WarningIcon, "Enable Code Signing", | |||
"You need to enable code-signing for your iOS project and enable \"iCloud Documents\" " | |||
"permissions to be able to open audio files on your iDevice. See: " | |||
"https://forum.juce.com/t/native-ios-android-file-choosers"); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::WarningIcon) | |||
.withTitle ("Enable Code Signing") | |||
.withMessage ("You need to enable code-signing for your iOS project and enable \"iCloud Documents\" " | |||
"permissions to be able to open audio files on your iDevice. See: " | |||
"https://forum.juce.com/t/native-ios-android-file-choosers"), | |||
nullptr); | |||
} | |||
} | |||
} | |||
@@ -359,11 +359,11 @@ private: | |||
fileToShare.deleteFile(); | |||
if (! success && error.isNotEmpty()) | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
"Sharing Error", | |||
error); | |||
} | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::WarningIcon) | |||
.withTitle ("Sharing Error") | |||
.withMessage (error), | |||
nullptr); | |||
}); | |||
#endif | |||
@@ -524,7 +524,7 @@ private: | |||
void handleInvalidLegacyModeParameters() const | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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!", | |||
@@ -193,7 +193,7 @@ private: | |||
addAndMakeVisible (textButton); | |||
shapeButton.setShape (getJUCELogoPath(), false, true, false); | |||
shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "Alert", "This is an AlertWindow"); }; | |||
shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Alert", "This is an AlertWindow"); }; | |||
addAndMakeVisible (shapeButton); | |||
} | |||
@@ -252,7 +252,7 @@ private: | |||
} | |||
else | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Camera open failed", | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Camera open failed", | |||
"Camera open failed, reason: " + error); | |||
} | |||
@@ -365,7 +365,7 @@ private: | |||
void errorOccurred (const String& error) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
"Camera Device Error", | |||
"An error has occurred: " + error + " Camera will be closed."); | |||
@@ -378,7 +378,7 @@ private: | |||
void sharingFinished (bool success, bool isCapture) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
isCapture ? "Image sharing result" : "Video sharing result", | |||
success ? "Success!" : "Failed!"); | |||
@@ -89,19 +89,14 @@ public: | |||
// This method gets called on the message thread once our thread has finished.. | |||
void threadComplete (bool userPressedCancel) override | |||
{ | |||
if (userPressedCancel) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
"Progress window", | |||
"You pressed cancel!"); | |||
} | |||
else | |||
{ | |||
// thread finished normally.. | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
"Progress window", | |||
"Thread finished ok!"); | |||
} | |||
const String messageString (userPressedCancel ? "You pressed cancel!" : "Thread finished ok!"); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Progress window") | |||
.withMessage (messageString) | |||
.withButton ("OK"), | |||
nullptr); | |||
// ..and clean up by deleting our thread object.. | |||
delete this; | |||
@@ -177,12 +172,13 @@ public: | |||
[] (bool granted) | |||
{ | |||
if (! granted) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
"Permissions warning", | |||
"External storage access permission not granted, some files" | |||
" may be inaccessible."); | |||
} | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::WarningIcon) | |||
.withTitle ("Permissions warning") | |||
.withMessage ("External storage access permission not granted, some files" | |||
" may be inaccessible.") | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
@@ -222,9 +218,12 @@ private: | |||
{ | |||
void operator() (int result) const noexcept | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Alert Box", | |||
"Result code: " + String (result)); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Alert Box") | |||
.withMessage ("Result code: " + String (result)) | |||
.withButton ("OK"), | |||
nullptr); | |||
} | |||
}; | |||
@@ -246,10 +245,14 @@ private: | |||
auto optionIndexChosen = aw.getComboBoxComponent ("option")->getSelectedItemIndex(); | |||
auto text = aw.getTextEditorContents ("text"); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "Alert Box", | |||
"Result code: " + String (result) + newLine | |||
+ "Option index chosen: " + String (optionIndexChosen) + newLine | |||
+ "Text: " + 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; | |||
@@ -259,11 +262,11 @@ private: | |||
{ | |||
if (type >= plainAlertWindow && type <= questionAlertWindow) | |||
{ | |||
AlertWindow::AlertIconType icon = AlertWindow::NoIcon; | |||
MessageBoxIconType icon = MessageBoxIconType::NoIcon; | |||
if (type == warningAlertWindow) icon = AlertWindow::WarningIcon; | |||
if (type == infoAlertWindow) icon = AlertWindow::InfoIcon; | |||
if (type == questionAlertWindow) icon = AlertWindow::QuestionIcon; | |||
if (type == warningAlertWindow) icon = MessageBoxIconType::WarningIcon; | |||
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.", | |||
@@ -271,7 +274,7 @@ private: | |||
} | |||
else if (type == okCancelAlertWindow) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, "This is an ok/cancel AlertWindow", | |||
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{})); | |||
@@ -291,7 +294,7 @@ private: | |||
{ | |||
asyncAlertWindow = std::make_unique<AlertWindow> ("AlertWindow demo..", | |||
"This AlertWindow has a couple of extra components added to show how to add drop-down lists and text entry boxes.", | |||
AlertWindow::QuestionIcon); | |||
MessageBoxIconType::QuestionIcon); | |||
asyncAlertWindow->addTextEditor ("text", "enter some text here", "text field:"); | |||
asyncAlertWindow->addComboBox ("option", { "option 1", "option 2", "option 3", "option 4" }, "some options"); | |||
@@ -326,9 +329,12 @@ private: | |||
chosen << (result.isLocalFile() ? result.getLocalFile().getFullPathName() | |||
: result.toString (false)) << "\n"; | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"File Chooser...", | |||
"You picked: " + chosen); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("File Chooser...") | |||
.withMessage ("You picked: " + chosen) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
else if (type == loadWithPreviewChooser) | |||
@@ -349,9 +355,12 @@ private: | |||
chosen << (result.isLocalFile() ? result.getLocalFile().getFullPathName() | |||
: result.toString (false)) << "\n"; | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"File Chooser...", | |||
"You picked: " + chosen); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("File Chooser...") | |||
.withMessage ("You picked: " + chosen) | |||
.withButton ("OK"), | |||
nullptr); | |||
}, | |||
&imagePreview); | |||
} | |||
@@ -401,9 +410,12 @@ private: | |||
} | |||
#endif | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"File Chooser...", | |||
"You picked: " + name); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("File Chooser...") | |||
.withMessage ("You picked: " + name) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
else if (type == directoryChooser) | |||
@@ -420,9 +432,12 @@ private: | |||
auto name = result.isLocalFile() ? result.getLocalFile().getFullPathName() | |||
: result.toString (true); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"File Chooser...", | |||
"You picked: " + name); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("File Chooser...") | |||
.withMessage ("You picked: " + name) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
} | |||
@@ -433,8 +448,12 @@ private: | |||
{ | |||
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")"); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "Sharing Text Result", | |||
"Sharing text finished\nwith " + resultString); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Sharing Text Result") | |||
.withMessage ("Sharing text finished\nwith " + resultString) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
else if (type == shareFile) | |||
@@ -454,9 +473,12 @@ private: | |||
{ | |||
auto resultString = success ? String ("success") : ("failure\n (error: " + error + ")"); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Sharing Files Result", | |||
"Sharing files finished\nwith " + resultString); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Sharing Files Result") | |||
.withMessage ("Sharing files finished\nwith " + resultString) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
@@ -480,8 +502,12 @@ private: | |||
String resultString = success ? String ("success") | |||
: ("failure\n (error: " + error + ")"); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "Sharing Images Result", | |||
"Sharing images finished\nwith " + resultString); | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Sharing Images Result") | |||
.withMessage ("Sharing images finished\nwith " + resultString) | |||
.withButton ("OK"), | |||
nullptr); | |||
}); | |||
} | |||
} | |||
@@ -61,7 +61,7 @@ public: | |||
void buttonClicked() override | |||
{ | |||
++counter; | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "Action Button Pressed", | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Action Button Pressed", | |||
"Pressing this type of property component can trigger an action such as showing an alert window!"); | |||
refresh(); | |||
} | |||
@@ -134,7 +134,7 @@ private: | |||
} | |||
else | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Couldn't load the file!", | |||
result.getErrorMessage()); | |||
} | |||
@@ -354,7 +354,7 @@ public: | |||
{ | |||
if (! granted) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Permissions warning", | |||
"External storage access permission not granted, some files" | |||
" may be inaccessible."); | |||
@@ -503,7 +503,7 @@ private: | |||
void askIfUseNativeControls (const URL& url) | |||
{ | |||
auto* aw = new AlertWindow ("Choose viewer type", {}, AlertWindow::NoIcon); | |||
auto* aw = new AlertWindow ("Choose viewer type", {}, MessageBoxIconType::NoIcon); | |||
aw->addButton ("Yes", 1, KeyPress (KeyPress::returnKey)); | |||
aw->addButton ("No", 0, KeyPress (KeyPress::escapeKey)); | |||
@@ -559,7 +559,7 @@ private: | |||
void showVideoUrlPrompt() | |||
{ | |||
auto* aw = new AlertWindow ("Enter URL for video to load", {}, AlertWindow::NoIcon); | |||
auto* aw = new AlertWindow ("Enter URL for video to load", {}, MessageBoxIconType::NoIcon); | |||
aw->addButton ("OK", 1, KeyPress (KeyPress::returnKey)); | |||
aw->addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey)); | |||
@@ -596,7 +596,7 @@ private: | |||
} | |||
else | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Couldn't load the file!", | |||
result.getErrorMessage()); | |||
} | |||
@@ -677,7 +677,7 @@ private: | |||
void errorOccurred (const String& errorMessage) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
"An error has occurred", | |||
errorMessage + ", video will be unloaded."); | |||
@@ -156,7 +156,7 @@ private: | |||
voiceProduct.purchasePrice = "In-App purchases unavailable"; | |||
} | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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 " | |||
@@ -178,7 +178,7 @@ private: | |||
} | |||
} | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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!", | |||
@@ -222,7 +222,7 @@ private: | |||
//============================================================================== | |||
void showConnectionErrorMessage (const String& messageText) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Connection error", | |||
messageText, | |||
"OK"); | |||
@@ -273,7 +273,7 @@ private: | |||
void showConnectionErrorMessage (const String& messageText) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Connection error", | |||
messageText, | |||
"OK"); | |||
@@ -403,7 +403,7 @@ private: | |||
//============================================================================== | |||
void handleConnectError (int failedPort) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"OSC Connection error", | |||
"Error: could not connect to port " + String (failedPort), | |||
"OK"); | |||
@@ -412,7 +412,7 @@ private: | |||
//============================================================================== | |||
void handleDisconnectError() | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Unknown error", | |||
"An unknown error occurred while trying to disconnect from UDP port.", | |||
"OK"); | |||
@@ -421,7 +421,7 @@ private: | |||
//============================================================================== | |||
void handleInvalidPortNumberEntered() | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Invalid port number", | |||
"Error: you have entered an invalid UDP port number.", | |||
"OK"); | |||
@@ -194,7 +194,11 @@ public: | |||
if (token.isEmpty()) | |||
showRemoteInstructions(); | |||
else | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Device token", token); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Device token") | |||
.withMessage (token), | |||
nullptr); | |||
}; | |||
#if JUCE_ANDROID | |||
@@ -308,11 +312,11 @@ private: | |||
String requiredFields = "all required fields"; | |||
#endif | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Incorrect notifications setup", | |||
"Please make sure that " | |||
+ requiredFields + " are set."); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Incorrect notifications setup") | |||
.withMessage ("Please make sure that " + requiredFields + " are set."), | |||
nullptr); | |||
return; | |||
} | |||
@@ -559,11 +563,13 @@ private: | |||
{ | |||
ignoreUnused (isLocalNotification); | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Received notification", | |||
"ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Received notification") | |||
.withMessage ("ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body), | |||
nullptr); | |||
} | |||
void handleNotificationAction (bool isLocalNotification, | |||
@@ -573,24 +579,28 @@ private: | |||
{ | |||
ignoreUnused (isLocalNotification); | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Received notification action", | |||
"ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body | |||
+ ", action: " + actionIdentifier | |||
+ ", optionalResponse: " + optionalResponse); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Received notification action") | |||
.withMessage ("ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body | |||
+ ", action: " + actionIdentifier | |||
+ ", optionalResponse: " + optionalResponse), | |||
nullptr); | |||
PushNotifications::getInstance()->removeDeliveredNotification (n.identifier); | |||
} | |||
void localNotificationDismissedByUser (const PushNotifications::Notification& n) override | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Notification dismissed by a user", | |||
"ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Notification dismissed by a user") | |||
.withMessage ("ID: " + n.identifier | |||
+ ", title: " + n.title | |||
+ ", body: " + n.body), | |||
nullptr); | |||
} | |||
void deliveredNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override | |||
@@ -600,7 +610,11 @@ private: | |||
for (auto& n : notifs) | |||
text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), "; | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Received notification list", text); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Received notification list") | |||
.withMessage (text), | |||
nullptr); | |||
} | |||
void pendingLocalNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override | |||
@@ -610,37 +624,49 @@ private: | |||
for (auto& n : notifs) | |||
text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), "; | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Pending notification list", text); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Pending notification list") | |||
.withMessage (text), | |||
nullptr); | |||
} | |||
void deviceTokenRefreshed (const String& token) override | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Device token refreshed", | |||
token); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Device token refreshed") | |||
.withMessage (token), | |||
nullptr); | |||
} | |||
#if JUCE_ANDROID | |||
void remoteNotificationsDeleted() override | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Remote notifications deleted", | |||
"Some of the pending messages were removed!"); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Remote notifications deleted") | |||
.withMessage ("Some of the pending messages were removed!"), | |||
nullptr); | |||
} | |||
void upstreamMessageSent (const String& messageId) override | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Upstream message sent", | |||
"Message id: " + messageId); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Upstream message sent") | |||
.withMessage ("Message id: " + messageId), | |||
nullptr); | |||
} | |||
void upstreamMessageSendingError (const String& messageId, const String& error) override | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Upstream message sending error", | |||
"Message id: " + messageId | |||
+ "\nerror: " + error); | |||
NativeMessageBox::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("Upstream message sending error") | |||
.withMessage ("Message id: " + messageId | |||
+ "\nerror: " + error), | |||
nullptr); | |||
} | |||
static Array<PushNotifications::Channel> getAndroidChannels() | |||
@@ -1191,12 +1217,14 @@ private: | |||
static void showRemoteInstructions() | |||
{ | |||
#if JUCE_IOS || JUCE_MAC | |||
NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
"Remote Notifications instructions", | |||
"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."); | |||
NativeMessageBox::showAsync (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."), | |||
nullptr); | |||
#endif | |||
} | |||
@@ -98,7 +98,7 @@ void PluginGraph::addPluginCallback (std::unique_ptr<AudioPluginInstance> instan | |||
{ | |||
if (instance == nullptr) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Couldn't create plugin"), | |||
error); | |||
} | |||
@@ -222,7 +222,7 @@ File NewProjectWizard::getLastWizardFolder() | |||
static void displayFailedFilesMessage (const StringArray& failedFiles) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Errors in Creating Project!"), | |||
TRANS("The following files couldn't be written:") | |||
+ "\n\n" | |||
@@ -244,7 +244,7 @@ static void prepareDirectory (const File& targetFolder, Callback&& callback) | |||
} | |||
else if (FileHelpers::containsAnyNonHiddenFiles (targetFolder)) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::InfoIcon, | |||
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?") | |||
@@ -122,7 +122,7 @@ private: | |||
if (postStrings.size() != preStrings.size()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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?")); | |||
@@ -138,7 +138,7 @@ private: | |||
if (Project* project = ProjucerApplication::getApp().mainWindowList.getFrontmostProject()) | |||
setPreTranslationText (TranslationHelpers::getPreTranslationText (*project)); | |||
else | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Translation Tool", | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Translation Tool", | |||
"This will only work when you have a project open!"); | |||
} | |||
@@ -835,7 +835,7 @@ void ProjucerApplication::launchDemoRunner() | |||
"Couldn't find a compiled version of the Demo Runner." | |||
" Please compile the Demo Runner project in the JUCE examples directory.", | |||
"OK", {}, {}, | |||
AlertWindow::WarningIcon, 1, | |||
MessageBoxIconType::WarningIcon, 1, | |||
mainWindowList.getFrontmostWindow (false))); | |||
demoRunnerAlert->enterModalState (true, ModalCallbackFunction::create ([this] (int) | |||
{ | |||
@@ -847,7 +847,7 @@ void ProjucerApplication::launchDemoRunner() | |||
"Couldn't find a compiled version of the Demo Runner." | |||
" Do you want to open the project?", | |||
"Open project", "Cancel", {}, | |||
AlertWindow::QuestionIcon, 2, | |||
MessageBoxIconType::QuestionIcon, 2, | |||
mainWindowList.getFrontmostWindow (false))); | |||
demoRunnerAlert->enterModalState (true, ModalCallbackFunction::create ([this, demoRunnerFile] (int retVal) | |||
{ | |||
@@ -1102,7 +1102,7 @@ void ProjucerApplication::createNewProjectFromClipboard() | |||
{ | |||
if (errorString.isNotEmpty()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", errorString); | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Error", errorString); | |||
tempFile.deleteFile(); | |||
} | |||
}; | |||
@@ -56,7 +56,7 @@ void LatestVersionCheckerAndUpdater::run() | |||
if (info == nullptr) | |||
{ | |||
if (! backgroundCheck) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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" | |||
@@ -68,7 +68,7 @@ void LatestVersionCheckerAndUpdater::run() | |||
if (! info->isNewerVersionThanCurrent()) | |||
{ | |||
if (! backgroundCheck) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
"No New Version Available", | |||
"Your JUCE version is up to date."); | |||
return; | |||
@@ -109,7 +109,7 @@ void LatestVersionCheckerAndUpdater::run() | |||
} | |||
if (! backgroundCheck) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Failed to find any new downloads", | |||
"Please try again in a few minutes."); | |||
} | |||
@@ -275,13 +275,13 @@ void LatestVersionCheckerAndUpdater::askUserForLocationToDownload (const Version | |||
{ | |||
if (targetFolder.getChildFile (".git").isDirectory()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Downloading New JUCE Version", | |||
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."); | |||
return; | |||
} | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
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" | |||
@@ -295,7 +295,7 @@ void LatestVersionCheckerAndUpdater::askUserForLocationToDownload (const Version | |||
if (targetFolder.exists()) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
"Existing File Or Directory", | |||
"Do you want to move\n\n" + targetFolderPath + "\n\nto\n\n" + targetFolderPath + "_old?", | |||
{}, | |||
@@ -388,7 +388,7 @@ private: | |||
result = install (zipData); | |||
if (result.failed()) | |||
MessageManager::callAsync ([result] { AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
MessageManager::callAsync ([result] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Installation Failed", | |||
result.getErrorMessage()); }); | |||
else | |||
@@ -452,7 +452,7 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba | |||
if (generatorResult != Result::ok()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"PIP Error.", | |||
generatorResult.getErrorMessage()); | |||
@@ -464,7 +464,7 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba | |||
if (! generator->createMainCpp()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"PIP Error.", | |||
"Failed to create Main.cpp."); | |||
@@ -481,7 +481,7 @@ void MainWindow::openPIP (const File& pipFile, std::function<void (bool)> callba | |||
if (! openedSuccessfully) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"PIP Error.", | |||
"Failed to open .jucer file."); | |||
@@ -176,7 +176,7 @@ void OpenDocumentManager::saveIfNeededAndUserAgrees (OpenDocumentManager::Docume | |||
return; | |||
} | |||
AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon, | |||
AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon, | |||
TRANS("Closing document..."), | |||
TRANS("Do you want to save the changes to \"") | |||
+ doc->getName() + "\"?", | |||
@@ -658,7 +658,7 @@ void CppCodeEditorComponent::insertComponentClass() | |||
{ | |||
asyncAlertWindow = std::make_unique<AlertWindow> (TRANS ("Insert a new Component class"), | |||
TRANS ("Please enter a name for the new class"), | |||
AlertWindow::NoIcon, | |||
MessageBoxIconType::NoIcon, | |||
nullptr); | |||
const String classNameField { "Class Name" }; | |||
@@ -265,7 +265,7 @@ void ResourceEditorPanel::reloadAll() | |||
failed.add (document.getResources().getResourceNames() [i]); | |||
if (failed.size() > 0) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Reloading resources"), | |||
TRANS("The following resources couldn't be reloaded from their original files:\n\n") | |||
+ failed.joinIntoString (", ")); | |||
@@ -143,7 +143,7 @@ void BinaryResources::browseForResource (const String& title, | |||
if (! add (name, fc.getResult())) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Adding Resource"), | |||
TRANS("Failed to load the file!")); | |||
@@ -682,14 +682,14 @@ void EnabledModulesList::addModuleOfferingToCopy (const File& f, bool isFromUser | |||
if (! m.isValid()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
"Add Module", "This wasn't a valid module folder!"); | |||
return; | |||
} | |||
if (isModuleEnabled (m.getID())) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
"Add Module", "The project already contains this module!"); | |||
return; | |||
} | |||
@@ -90,7 +90,7 @@ public: | |||
safeThis->project.getUndoManagerFor (parent)); | |||
}; | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
"Delete Exporter", | |||
"Are you sure you want to delete this export target?", | |||
"", | |||
@@ -244,7 +244,7 @@ public: | |||
void deleteItem() override | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
"Delete Configuration", | |||
"Are you sure you want to delete this configuration?", | |||
"", | |||
@@ -138,7 +138,7 @@ public: | |||
if (filesToTrash.size() > maxFilesToList) | |||
fileList << "\n...plus " << (filesToTrash.size() - maxFilesToList) << " more files..."; | |||
AlertWindow::showYesNoCancelBox (AlertWindow::NoIcon, | |||
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, | |||
@@ -521,7 +521,7 @@ public: | |||
{ | |||
if (newName != File::createLegalFileName (newName)) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"File Rename", | |||
"That filename contained some illegal characters!"); | |||
triggerAsyncRename (item); | |||
@@ -538,7 +538,7 @@ public: | |||
if (correspondingItem.isValid()) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::NoIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::NoIcon, | |||
"File Rename", | |||
"Do you also want to rename the corresponding file \"" + correspondingFile.getFileName() + "\" to match?", | |||
{}, | |||
@@ -552,7 +552,7 @@ public: | |||
if (! parent->item.renameFile (newFile)) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"File Rename", | |||
"Failed to rename \"" + oldFile.getFullPathName() + "\"!\n\nCheck your file permissions!"); | |||
return; | |||
@@ -560,7 +560,7 @@ public: | |||
if (! correspondingItem.renameFile (newFile.withFileExtension (correspondingFile.getFileExtension()))) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"File Rename", | |||
"Failed to rename \"" + correspondingFile.getFullPathName() + "\"!\n\nCheck your file permissions!"); | |||
} | |||
@@ -571,7 +571,7 @@ public: | |||
if (! item.renameFile (newFile)) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"File Rename", | |||
"Failed to rename the file!\n\nCheck your file permissions!"); | |||
} | |||
@@ -378,7 +378,7 @@ private: | |||
{ | |||
missingDependencies = enabledModules.getExtraDependenciesNeeded (moduleID); | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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."); | |||
@@ -320,7 +320,7 @@ void ProjectContentComponent::closeDocument() | |||
static void showSaveWarning (OpenDocumentManager::Document* currentDocument) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Save failed!"), | |||
TRANS("Couldn't save the file:") | |||
+ "\n" + currentDocument->getFile().getFullPathName()); | |||
@@ -407,7 +407,7 @@ void Project::removeDefunctExporters() | |||
if (ProjucerApplication::getApp().isRunningCommandLine) | |||
std::cout << "WARNING! The " + oldExporters[key] + " Exporter is deprecated. The exporter will be removed from this project." << std::endl; | |||
else | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS (oldExporters[key]), | |||
TRANS ("The " + oldExporters[key] + " Exporter is deprecated. The exporter will be removed from this project.")); | |||
@@ -723,7 +723,7 @@ public: | |||
"Since JUCE 4.2, this is instead done using \"AU/VST/VST2/AAX/RTAS 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 (AlertWindow::WarningIcon, | |||
if (AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
"Project settings: " + project.getDocumentTitle(), | |||
alertWindowText, "Update", "Cancel", nullptr, nullptr)) | |||
postbuildCommandValue.resetToDefault(); | |||
@@ -171,7 +171,7 @@ private: | |||
{ | |||
asyncAlertWindow = std::make_unique<AlertWindow> (TRANS ("Create new Component class"), | |||
TRANS ("Please enter the name for the new class"), | |||
AlertWindow::NoIcon, nullptr); | |||
MessageBoxIconType::NoIcon, nullptr); | |||
asyncAlertWindow->addTextEditor (getClassNameFieldName(), String(), String(), false); | |||
asyncAlertWindow->addButton (TRANS ("Create Files"), 1, KeyPress (KeyPress::returnKey)); | |||
@@ -235,7 +235,7 @@ public: | |||
//============================================================================== | |||
void NewFileWizard::Type::showFailedToWriteMessage (const File& file) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
"Failed to Create File!", | |||
"Couldn't write to the file: " + file.getFullPathName()); | |||
} | |||
@@ -388,8 +388,8 @@ public: | |||
PropertiesFile* properties, bool allowPluginsWhichRequireAsynchronousInstantiation, int threads, | |||
const String& title, const String& text) | |||
: owner (plc), formatToScan (format), filesOrIdentifiersToScan (filesOrIdentifiers), propertiesToUse (properties), | |||
pathChooserWindow (TRANS("Select folders to scan..."), String(), AlertWindow::NoIcon), | |||
progressWindow (title, text, AlertWindow::NoIcon), | |||
pathChooserWindow (TRANS("Select folders to scan..."), String(), MessageBoxIconType::NoIcon), | |||
progressWindow (title, text, MessageBoxIconType::NoIcon), | |||
numThreads (threads), allowAsync (allowPluginsWhichRequireAsynchronousInstantiation) | |||
{ | |||
FileSearchPath path (formatToScan.getDefaultLocationsToSearch()); | |||
@@ -467,7 +467,7 @@ private: | |||
if (isStupidPath (f)) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
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 " | |||
@@ -642,7 +642,7 @@ void PluginListComponent::scanFinished (const StringArray& failedFiles) | |||
currentScanner.reset(); // mustn't delete this before using the failed files array | |||
if (shortNames.size() > 0) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
TRANS("Scan complete"), | |||
TRANS("Note that the following files appeared to be plugin files, but failed to load correctly") | |||
+ ":\n\n" | |||
@@ -405,7 +405,7 @@ public: | |||
} | |||
if (error.isNotEmpty()) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Error when trying to open audio device!"), | |||
error); | |||
} | |||
@@ -289,25 +289,4 @@ int ModalComponentManager::runEventLoopForCurrentComponent() | |||
} | |||
#endif | |||
//============================================================================== | |||
struct LambdaCallback : public ModalComponentManager::Callback | |||
{ | |||
LambdaCallback (std::function<void (int)> fn) noexcept : function (fn) {} | |||
void modalStateFinished (int result) override | |||
{ | |||
if (function != nullptr) | |||
function (result); | |||
} | |||
std::function<void (int)> function; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LambdaCallback) | |||
}; | |||
ModalComponentManager::Callback* ModalCallbackFunction::create (std::function<void (int)> f) | |||
{ | |||
return new LambdaCallback (f); | |||
} | |||
} // namespace juce |
@@ -163,14 +163,26 @@ class JUCE_API ModalCallbackFunction | |||
{ | |||
public: | |||
/** This is a utility function to create a ModalComponentManager::Callback that will | |||
call a lambda function. | |||
call a callable object. | |||
The lambda that you supply must take an integer parameter, which is the result code that | |||
The function that you supply must take an integer parameter, which is the result code that | |||
was returned when the modal component was dismissed. | |||
@see ModalComponentManager::Callback | |||
*/ | |||
static ModalComponentManager::Callback* create (std::function<void (int)>); | |||
template <typename CallbackFn> | |||
static ModalComponentManager::Callback* create (CallbackFn&& fn) | |||
{ | |||
struct Callable : public ModalComponentManager::Callback | |||
{ | |||
explicit Callable (CallbackFn&& f) : fn (std::forward<CallbackFn> (f)) {} | |||
void modalStateFinished (int result) override { fn (result); } | |||
CallbackFn fn; | |||
}; | |||
return new Callable (std::forward<CallbackFn> (fn)); | |||
} | |||
//============================================================================== | |||
/** This is a utility function to create a ModalComponentManager::Callback that will | |||
@@ -194,7 +194,7 @@ void FileChooserDialogBox::okButtonPressed() | |||
&& content->chooserComponent.isSaveMode() | |||
&& content->chooserComponent.getSelectedFile(0).exists()) | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
TRANS("File already exists"), | |||
TRANS("There's already a file called: FLNM") | |||
.replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName()) | |||
@@ -229,7 +229,7 @@ void FileChooserDialogBox::createNewFolder() | |||
{ | |||
auto* aw = new AlertWindow (TRANS("New Folder"), | |||
TRANS("Please enter the name for the folder"), | |||
AlertWindow::NoIcon, this); | |||
MessageBoxIconType::NoIcon, this); | |||
aw->addTextEditor ("Folder Name", String(), String(), false); | |||
aw->addButton (TRANS("Create Folder"), 1, KeyPress (KeyPress::returnKey)); | |||
@@ -251,7 +251,7 @@ void FileChooserDialogBox::createNewFolderConfirmed (const String& nameFromDialo | |||
auto parent = content->chooserComponent.getRoot(); | |||
if (! parent.getChildFile (name).createDirectory()) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS ("New Folder"), | |||
TRANS ("Couldn't create the folder!")); | |||
@@ -66,6 +66,7 @@ | |||
#include <windowsx.h> | |||
#include <vfw.h> | |||
#include <commdlg.h> | |||
#include <commctrl.h> | |||
#if ! JUCE_MINGW | |||
#include <UIAutomation.h> | |||
@@ -82,6 +83,7 @@ | |||
#elif ! JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
#pragma comment(lib, "vfw32.lib") | |||
#pragma comment(lib, "imm32.lib") | |||
#pragma comment(lib, "comctl32.lib") | |||
#if JUCE_OPENGL | |||
#pragma comment(lib, "OpenGL32.Lib") | |||
@@ -258,6 +258,7 @@ namespace juce | |||
#include "misc/juce_JUCESplashScreen.h" | |||
#include "widgets/juce_TreeView.h" | |||
#include "windows/juce_TopLevelWindow.h" | |||
#include "windows/juce_MessageBoxOptions.h" | |||
#include "windows/juce_AlertWindow.h" | |||
#include "windows/juce_CallOutBox.h" | |||
#include "windows/juce_ComponentPeer.h" | |||
@@ -407,7 +407,7 @@ void LookAndFeel_V2::drawDrawableButton (Graphics& g, DrawableButton& button, | |||
//============================================================================== | |||
AlertWindow* LookAndFeel_V2::createAlertWindow (const String& title, const String& message, | |||
const String& button1, const String& button2, const String& button3, | |||
AlertWindow::AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
int numButtons, Component* associatedComponent) | |||
{ | |||
AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent); | |||
@@ -457,13 +457,13 @@ void LookAndFeel_V2::drawAlertBox (Graphics& g, AlertWindow& alert, | |||
const Rectangle<int> iconRect (iconSize / -10, iconSize / -10, | |||
iconSize, iconSize); | |||
if (alert.getAlertType() != AlertWindow::NoIcon) | |||
if (alert.getAlertType() != MessageBoxIconType::NoIcon) | |||
{ | |||
Path icon; | |||
uint32 colour; | |||
char character; | |||
if (alert.getAlertType() == AlertWindow::WarningIcon) | |||
if (alert.getAlertType() == MessageBoxIconType::WarningIcon) | |||
{ | |||
colour = 0x55ff5555; | |||
character = '!'; | |||
@@ -476,8 +476,8 @@ void LookAndFeel_V2::drawAlertBox (Graphics& g, AlertWindow& alert, | |||
} | |||
else | |||
{ | |||
colour = alert.getAlertType() == AlertWindow::InfoIcon ? (uint32) 0x605555ff : (uint32) 0x40b69900; | |||
character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?'; | |||
colour = alert.getAlertType() == MessageBoxIconType::InfoIcon ? (uint32) 0x605555ff : (uint32) 0x40b69900; | |||
character = alert.getAlertType() == MessageBoxIconType::InfoIcon ? 'i' : '?'; | |||
icon.addEllipse (iconRect.toFloat()); | |||
} | |||
@@ -67,7 +67,7 @@ public: | |||
const String& button1, | |||
const String& button2, | |||
const String& button3, | |||
AlertWindow::AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
int numButtons, Component* associatedComponent) override; | |||
void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) override; | |||
@@ -385,7 +385,7 @@ void LookAndFeel_V4::changeToggleButtonWidthToFitText (ToggleButton& button) | |||
//============================================================================== | |||
AlertWindow* LookAndFeel_V4::createAlertWindow (const String& title, const String& message, | |||
const String& button1, const String& button2, const String& button3, | |||
AlertWindow::AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
int numButtons, Component* associatedComponent) | |||
{ | |||
auto boundsOffset = 50; | |||
@@ -429,13 +429,13 @@ void LookAndFeel_V4::drawAlertBox (Graphics& g, AlertWindow& alert, | |||
Rectangle<int> iconRect (iconSize / -10, iconSize / -10, | |||
iconSize, iconSize); | |||
if (alert.getAlertType() != AlertWindow::NoIcon) | |||
if (alert.getAlertType() != MessageBoxIconType::NoIcon) | |||
{ | |||
Path icon; | |||
char character; | |||
uint32 colour; | |||
if (alert.getAlertType() == AlertWindow::WarningIcon) | |||
if (alert.getAlertType() == MessageBoxIconType::WarningIcon) | |||
{ | |||
character = '!'; | |||
@@ -449,7 +449,7 @@ void LookAndFeel_V4::drawAlertBox (Graphics& g, AlertWindow& alert, | |||
else | |||
{ | |||
colour = Colour (0xff00b0b9).withAlpha (0.4f).getARGB(); | |||
character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?'; | |||
character = alert.getAlertType() == MessageBoxIconType::InfoIcon ? 'i' : '?'; | |||
icon.addEllipse (iconRect.toFloat()); | |||
} | |||
@@ -130,7 +130,7 @@ public: | |||
const String& button1, | |||
const String& button2, | |||
const String& button3, | |||
AlertWindow::AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
int numButtons, Component* associatedComponent) override; | |||
void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) override; | |||
@@ -1226,8 +1226,8 @@ DECLARE_JNI_CLASS (AndroidDialogOnClickListener, "android/content/DialogInterfac | |||
class DialogListener : public juce::AndroidInterfaceImplementer | |||
{ | |||
public: | |||
DialogListener (ModalComponentManager::Callback* callbackToUse, int resultToUse) | |||
: callback (callbackToUse), result (resultToUse) | |||
DialogListener (std::shared_ptr<ModalComponentManager::Callback> callbackToUse, int resultToUse) | |||
: callback (std::move (callbackToUse)), result (resultToUse) | |||
{} | |||
void onResult (jobject dialog) | |||
@@ -1257,46 +1257,44 @@ private: | |||
return AndroidInterfaceImplementer::invoke (proxy, method, args); | |||
} | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
std::shared_ptr<ModalComponentManager::Callback> callback; | |||
int result; | |||
}; | |||
//============================================================================== | |||
static void createAndroidDialog (const String& title, const String& message, | |||
ModalComponentManager::Callback* callback, | |||
const String& positiveButton = {}, const String& negativeButton = {}, | |||
const String& neutralButton = {}) | |||
static void createAndroidDialog (const MessageBoxOptions& opts, | |||
std::unique_ptr<ModalComponentManager::Callback> callback) | |||
{ | |||
auto* env = getEnv(); | |||
LocalRef<jobject> builder (env->NewObject (AndroidAlertDialogBuilder, AndroidAlertDialogBuilder.construct, getMainActivity().get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setTitle, javaString (title).get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setMessage, javaString (message).get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setTitle, javaString (opts.getTitle()).get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setMessage, javaString (opts.getMessage()).get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setCancelable, true)); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setOnCancelListener, | |||
CreateJavaInterface (new DialogListener (callback, 0), | |||
"android/content/DialogInterface$OnCancelListener").get())); | |||
std::shared_ptr<ModalComponentManager::Callback> sharedCallback (std::move (callback)); | |||
auto positiveButtonText = positiveButton.isEmpty() ? String ("OK") : positiveButton; | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setOnCancelListener, | |||
CreateJavaInterface (new DialogListener (sharedCallback, 0), | |||
"android/content/DialogInterface$OnCancelListener").get())); | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setPositiveButton, | |||
javaString (positiveButtonText).get(), | |||
CreateJavaInterface (new DialogListener (callback, positiveButton.isEmpty() ? 0 : 1), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
javaString (opts.getButtonText (0)).get(), | |||
CreateJavaInterface (new DialogListener (sharedCallback, 0), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
if (negativeButton.isNotEmpty()) | |||
if (opts.getButtonText (1).isNotEmpty()) | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNegativeButton, | |||
javaString (negativeButton).get(), | |||
CreateJavaInterface (new DialogListener (callback, neutralButton.isEmpty() ? 0 : 2), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
javaString (opts.getButtonText (1)).get(), | |||
CreateJavaInterface (new DialogListener (sharedCallback, 1), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
if (neutralButton.isNotEmpty()) | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNegativeButton, | |||
javaString (neutralButton).get(), | |||
CreateJavaInterface (new DialogListener (callback, 0), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
if (opts.getButtonText (2).isNotEmpty()) | |||
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNeutralButton, | |||
javaString (opts.getButtonText (2)).get(), | |||
CreateJavaInterface (new DialogListener (sharedCallback, 2), | |||
"android/content/DialogInterface$OnClickListener").get())); | |||
LocalRef<jobject> dialog (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.create)); | |||
@@ -1315,47 +1313,76 @@ static void createAndroidDialog (const String& title, const String& message, | |||
env->CallVoidMethod (window.get(), AndroidWindow.clearFlags, FLAG_NOT_FOCUSABLE); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType /*iconType*/, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
createAndroidDialog (title, message, callback); | |||
showAsync (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")), | |||
AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::messageBox)); | |||
} | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType /*iconType*/, | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
jassert (callback != nullptr); // on android, all alerts must be non-modal!! | |||
showAsync (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withButton (TRANS("Cancel")), | |||
AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)); | |||
createAndroidDialog (title, message, callback, "OK", "Cancel"); | |||
return false; | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType /*iconType*/, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
jassert (callback != nullptr); // on android, all alerts must be non-modal!! | |||
showAsync (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")) | |||
.withButton (TRANS("Cancel")), | |||
AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::yesNoCancel)); | |||
createAndroidDialog (title, message, callback, "Yes", "No", "Cancel"); | |||
return 0; | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
jassert (callback != nullptr); // on android, all alerts must be non-modal!! | |||
showAsync (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")), | |||
AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)); | |||
createAndroidDialog (title, message, callback, "Yes", "No"); | |||
return 0; | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
createAndroidDialog (options, std::unique_ptr<ModalComponentManager::Callback> (callback)); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
//============================================================================== | |||
static bool androidScreenSaverEnabled = true; | |||
@@ -437,19 +437,18 @@ void LookAndFeel::playAlertSound() | |||
class iOSMessageBox | |||
{ | |||
public: | |||
iOSMessageBox (const String& title, const String& message, | |||
NSString* button1, NSString* button2, NSString* button3, | |||
ModalComponentManager::Callback* cb, const bool async) | |||
: result (0), resultReceived (false), callback (cb), isAsync (async) | |||
iOSMessageBox (const MessageBoxOptions& opts, std::unique_ptr<ModalComponentManager::Callback>&& cb) | |||
: callback (std::move (cb)) | |||
{ | |||
if (currentlyFocusedPeer != nullptr) | |||
{ | |||
UIAlertController* alert = [UIAlertController alertControllerWithTitle: juceStringToNS (title) | |||
message: juceStringToNS (message) | |||
UIAlertController* alert = [UIAlertController alertControllerWithTitle: juceStringToNS (opts.getTitle()) | |||
message: juceStringToNS (opts.getMessage()) | |||
preferredStyle: UIAlertControllerStyleAlert]; | |||
addButton (alert, button1, 0); | |||
addButton (alert, button2, 1); | |||
addButton (alert, button3, 2); | |||
addButton (alert, opts.getButtonText (0)); | |||
addButton (alert, opts.getButtonText (1)); | |||
addButton (alert, opts.getButtonText (2)); | |||
[currentlyFocusedPeer->controller presentViewController: alert | |||
animated: YES | |||
@@ -469,105 +468,146 @@ public: | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
while (! resultReceived) | |||
while (result < 0) | |||
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; | |||
} | |||
return result; | |||
} | |||
void buttonClicked (const int buttonIndex) noexcept | |||
void buttonClicked (int buttonIndex) noexcept | |||
{ | |||
result = buttonIndex; | |||
resultReceived = true; | |||
if (callback != nullptr) | |||
callback->modalStateFinished (result); | |||
callback->modalStateFinished (buttonIndex); | |||
if (isAsync) | |||
delete this; | |||
delete this; | |||
} | |||
private: | |||
int result; | |||
bool resultReceived; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
const bool isAsync; | |||
void addButton (UIAlertController* alert, NSString* text, int index) | |||
void addButton (UIAlertController* alert, const String& text) | |||
{ | |||
if (text != nil) | |||
[alert addAction: [UIAlertAction actionWithTitle: text | |||
if (! text.isEmpty()) | |||
{ | |||
const auto index = [[alert actions] count]; | |||
[alert addAction: [UIAlertAction actionWithTitle: juceStringToNS (text) | |||
style: UIAlertActionStyleDefault | |||
handler: ^(UIAlertAction*) { this->buttonClicked (index); }]]; | |||
handler: ^(UIAlertAction*) { this->buttonClicked ((int) index); }]]; | |||
} | |||
} | |||
int result = -1; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (iOSMessageBox) | |||
}; | |||
//============================================================================== | |||
static int showDialog (const MessageBoxOptions& options, | |||
std::unique_ptr<ModalComponentManager::Callback> callback, | |||
Async async) | |||
{ | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (async == Async::no) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
iOSMessageBox messageBox (options, std::move (callback)); | |||
return messageBox.getResult(); | |||
} | |||
} | |||
#endif | |||
ignoreUnused (async); | |||
new iOSMessageBox (options, std::move (callback)); | |||
return 0; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType /*iconType*/, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false); | |||
ignoreUnused (mb.getResult()); | |||
} | |||
showDialog (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")), | |||
nullptr, Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options) | |||
{ | |||
return showDialog (options, nullptr, Async::no); | |||
} | |||
#endif | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType /*iconType*/, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
new iOSMessageBox (title, message, @"OK", nil, nil, callback, true); | |||
showDialog (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::messageBox)), | |||
Async::yes); | |||
} | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType /*iconType*/, | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"OK", | |||
nil, callback, callback != nullptr)); | |||
if (callback == nullptr) | |||
return mb->getResult() == 1; | |||
mb.release(); | |||
return false; | |||
return showDialog (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withButton (TRANS("Cancel")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no) == 1; | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType /*iconType*/, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"Yes", @"No", callback, callback != nullptr)); | |||
if (callback == nullptr) | |||
return mb->getResult(); | |||
mb.release(); | |||
return 0; | |||
return showDialog (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")) | |||
.withButton (TRANS("Cancel")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::yesNoCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType /*iconType*/, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType /*iconType*/, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"No", @"Yes", nil, callback, callback != nullptr)); | |||
return showDialog (MessageBoxOptions() | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
if (callback == nullptr) | |||
return mb->getResult(); | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
showDialog (options, rawToUniquePtr (callback), Async::yes); | |||
} | |||
mb.release(); | |||
return 0; | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
//============================================================================== | |||
@@ -654,16 +654,86 @@ void LookAndFeel::playAlertSound() | |||
} | |||
//============================================================================== | |||
static int showDialog (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback, | |||
Async async) | |||
{ | |||
const auto dummyCallback = [] (int) {}; | |||
switch (options.getNumButtons()) | |||
{ | |||
case 2: | |||
{ | |||
if (async == Async::yes && callback == nullptr) | |||
callback = ModalCallbackFunction::create (dummyCallback); | |||
return AlertWindow::showOkCancelBox (options.getIconType(), | |||
options.getTitle(), | |||
options.getMessage(), | |||
options.getButtonText (0), | |||
options.getButtonText (1), | |||
options.getAssociatedComponent(), | |||
callback) ? 1 : 0; | |||
} | |||
case 3: | |||
{ | |||
if (async == Async::yes && callback == nullptr) | |||
callback = ModalCallbackFunction::create (dummyCallback); | |||
return AlertWindow::showYesNoCancelBox (options.getIconType(), | |||
options.getTitle(), | |||
options.getMessage(), | |||
options.getButtonText (0), | |||
options.getButtonText (1), | |||
options.getButtonText (2), | |||
options.getAssociatedComponent(), | |||
callback); | |||
} | |||
case 1: | |||
default: | |||
break; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (async == Async::no) | |||
{ | |||
AlertWindow::showMessageBox (options.getIconType(), | |||
options.getTitle(), | |||
options.getMessage(), | |||
options.getButtonText (0), | |||
options.getAssociatedComponent()); | |||
} | |||
else | |||
#endif | |||
{ | |||
AlertWindow::showMessageBoxAsync (options.getIconType(), | |||
options.getTitle(), | |||
options.getMessage(), | |||
options.getButtonText (0), | |||
options.getAssociatedComponent(), | |||
callback); | |||
} | |||
return 0; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component*) | |||
Component* /*associatedComponent*/) | |||
{ | |||
AlertWindow::showMessageBox (iconType, title, message); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options) | |||
{ | |||
return showDialog (options, nullptr, Async::no); | |||
} | |||
#endif | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
@@ -671,7 +741,7 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIcon | |||
AlertWindow::showMessageBoxAsync (iconType, title, message, {}, associatedComponent, callback); | |||
} | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType, | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
@@ -679,7 +749,7 @@ bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType | |||
return AlertWindow::showOkCancelBox (iconType, title, message, {}, {}, associatedComponent, callback); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
@@ -688,15 +758,27 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy | |||
associatedComponent, callback); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
return AlertWindow::showOkCancelBox (iconType, title, message, TRANS ("Yes"), TRANS ("No"), | |||
return AlertWindow::showOkCancelBox (iconType, title, message, TRANS("Yes"), TRANS("No"), | |||
associatedComponent, callback); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
showDialog (options, callback, Async::yes); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
//============================================================================== | |||
Image juce_createIconForFile (const File&) | |||
{ | |||
@@ -35,47 +35,29 @@ void LookAndFeel::playAlertSound() | |||
class OSXMessageBox : private AsyncUpdater | |||
{ | |||
public: | |||
OSXMessageBox (AlertWindow::AlertIconType type, const String& t, const String& m, | |||
const char* b1, const char* b2, const char* b3, | |||
ModalComponentManager::Callback* c, const bool runAsync) | |||
: iconType (type), title (t), message (m), callback (c), | |||
button1 (b1), button2 (b2), button3 (b3) | |||
OSXMessageBox (const MessageBoxOptions& opts, | |||
std::unique_ptr<ModalComponentManager::Callback>&& c) | |||
: options (opts), callback (std::move (c)) | |||
{ | |||
if (runAsync) | |||
triggerAsyncUpdate(); | |||
} | |||
int getResult() const | |||
{ | |||
switch (getRawResult()) | |||
{ | |||
case NSAlertFirstButtonReturn: return 1; | |||
case NSAlertThirdButtonReturn: return 2; | |||
default: return 0; | |||
case NSAlertFirstButtonReturn: return 0; | |||
case NSAlertSecondButtonReturn: return 1; | |||
case NSAlertThirdButtonReturn: return 2; | |||
default: break; | |||
} | |||
} | |||
static int show (AlertWindow::AlertIconType iconType, const String& title, const String& message, | |||
ModalComponentManager::Callback* callback, const char* b1, const char* b2, const char* b3, | |||
bool runAsync) | |||
{ | |||
std::unique_ptr<OSXMessageBox> mb (new OSXMessageBox (iconType, title, message, b1, b2, b3, | |||
callback, runAsync)); | |||
if (! runAsync) | |||
return mb->getResult(); | |||
mb.release(); | |||
jassertfalse; | |||
return 0; | |||
} | |||
private: | |||
AlertWindow::AlertIconType iconType; | |||
String title, message; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
const char* button1; | |||
const char* button2; | |||
const char* button3; | |||
using AsyncUpdater::triggerAsyncUpdate; | |||
private: | |||
void handleAsyncUpdate() override | |||
{ | |||
auto result = getResult(); | |||
@@ -86,73 +68,147 @@ private: | |||
delete this; | |||
} | |||
static void addButton (NSAlert* alert, const String& button) | |||
{ | |||
if (! button.isEmpty()) | |||
[alert addButtonWithTitle: juceStringToNS (button)]; | |||
} | |||
NSInteger getRawResult() const | |||
{ | |||
NSAlert* alert = [[[NSAlert alloc] init] autorelease]; | |||
[alert setMessageText: juceStringToNS (title)]; | |||
[alert setInformativeText: juceStringToNS (message)]; | |||
[alert setMessageText: juceStringToNS (options.getTitle())]; | |||
[alert setInformativeText: juceStringToNS (options.getMessage())]; | |||
[alert setAlertStyle: options.getIconType() == MessageBoxIconType::WarningIcon ? NSAlertStyleCritical | |||
: NSAlertStyleInformational]; | |||
[alert setAlertStyle: iconType == AlertWindow::WarningIcon ? NSAlertStyleCritical | |||
: NSAlertStyleInformational]; | |||
addButton (alert, button1); | |||
addButton (alert, button2); | |||
addButton (alert, button3); | |||
const auto button1Text = options.getButtonText (0); | |||
addButton (alert, button1Text.isEmpty() ? "OK" : button1Text); | |||
addButton (alert, options.getButtonText (1)); | |||
addButton (alert, options.getButtonText (2)); | |||
return [alert runModal]; | |||
} | |||
static void addButton (NSAlert* alert, const char* button) | |||
{ | |||
if (button != nullptr) | |||
[alert addButtonWithTitle: juceStringToNS (TRANS (button))]; | |||
} | |||
MessageBoxOptions options; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXMessageBox) | |||
}; | |||
static int showDialog (const MessageBoxOptions& options, | |||
std::unique_ptr<ModalComponentManager::Callback> callback, | |||
Async async) | |||
{ | |||
auto messageBox = std::make_unique<OSXMessageBox> (options, std::move (callback)); | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (async == Async::no) | |||
return messageBox->getResult(); | |||
#endif | |||
ignoreUnused (async); | |||
messageBox->triggerAsyncUpdate(); | |||
messageBox.release(); | |||
return 0; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/) | |||
{ | |||
OSXMessageBox::show (iconType, title, message, nullptr, "OK", nullptr, nullptr, false); | |||
showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")), | |||
nullptr, | |||
Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options) | |||
{ | |||
return showDialog (options, nullptr, Async::no); | |||
} | |||
#endif | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
OSXMessageBox::show (iconType, title, message, callback, "OK", nullptr, nullptr, true); | |||
showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::messageBox)), | |||
Async::yes); | |||
} | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType, | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
return OSXMessageBox::show (iconType, title, message, callback, | |||
"OK", "Cancel", nullptr, callback != nullptr) == 1; | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withButton (TRANS("Cancel")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no) != 0; | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
return OSXMessageBox::show (iconType, title, message, callback, | |||
"Yes", "Cancel", "No", callback != nullptr); | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")) | |||
.withButton (TRANS("Cancel")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::yesNoCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* /*associatedComponent*/, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
return OSXMessageBox::show (iconType, title, message, callback, | |||
"Yes", "No", nullptr, callback != nullptr); | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
showDialog (options, rawToUniquePtr (callback), Async::yes); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
//============================================================================== | |||
static NSRect getDragRect (NSView* view, NSEvent* event) | |||
@@ -4411,30 +4411,44 @@ bool juce_areThereAnyAlwaysOnTopWindows() | |||
} | |||
//============================================================================== | |||
class WindowsMessageBox : public AsyncUpdater | |||
#if JUCE_MSVC | |||
// required to enable the newer dialog box on vista and above | |||
#pragma comment(linker, \ | |||
"\"/MANIFESTDEPENDENCY:type='Win32' " \ | |||
"name='Microsoft.Windows.Common-Controls' " \ | |||
"version='6.0.0.0' " \ | |||
"processorArchitecture='*' " \ | |||
"publicKeyToken='6595b64144ccf1df' " \ | |||
"language='*'\"" \ | |||
) | |||
#endif | |||
class WindowsMessageBoxBase : private AsyncUpdater | |||
{ | |||
public: | |||
WindowsMessageBox (AlertWindow::AlertIconType iconType, | |||
const String& boxTitle, const String& m, | |||
Component* associatedComponent, UINT extraFlags, | |||
ModalComponentManager::Callback* cb, const bool runAsync) | |||
: flags (extraFlags | getMessageBoxFlags (iconType)), | |||
owner (getWindowForMessageBox (associatedComponent)), | |||
title (boxTitle), message (m), callback (cb) | |||
WindowsMessageBoxBase (Component* comp, | |||
std::unique_ptr<ModalComponentManager::Callback>&& cb) | |||
: associatedComponent (comp), | |||
callback (std::move (cb)) | |||
{ | |||
if (runAsync) | |||
triggerAsyncUpdate(); | |||
} | |||
int getResult() const | |||
virtual int getResult() = 0; | |||
HWND getParentHWND() const | |||
{ | |||
const int r = MessageBox (owner, message.toWideCharPointer(), title.toWideCharPointer(), flags); | |||
return (r == IDYES || r == IDOK) ? 1 : (r == IDNO && (flags & 1) != 0 ? 2 : 0); | |||
if (associatedComponent != nullptr) | |||
return (HWND) associatedComponent->getWindowHandle(); | |||
return nullptr; | |||
} | |||
using AsyncUpdater::triggerAsyncUpdate; | |||
private: | |||
void handleAsyncUpdate() override | |||
{ | |||
const int result = getResult(); | |||
const auto result = getResult(); | |||
if (callback != nullptr) | |||
callback->modalStateFinished (result); | |||
@@ -4442,97 +4456,303 @@ public: | |||
delete this; | |||
} | |||
private: | |||
UINT flags; | |||
HWND owner; | |||
String title, message; | |||
Component::SafePointer<Component> associatedComponent; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
static UINT getMessageBoxFlags (AlertWindow::AlertIconType iconType) noexcept | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsMessageBoxBase) | |||
}; | |||
class PreVistaMessageBox : public WindowsMessageBoxBase | |||
{ | |||
public: | |||
PreVistaMessageBox (const MessageBoxOptions& opts, | |||
UINT extraFlags, | |||
std::unique_ptr<ModalComponentManager::Callback>&& callback) | |||
: WindowsMessageBoxBase (opts.getAssociatedComponent(), std::move (callback)), | |||
flags (extraFlags | getMessageBoxFlags (opts.getIconType())), | |||
title (opts.getTitle()), message (opts.getMessage()) | |||
{ | |||
UINT flags = MB_TASKMODAL | MB_SETFOREGROUND; | |||
} | |||
int getResult() override | |||
{ | |||
const auto result = MessageBox (getParentHWND(), message.toWideCharPointer(), title.toWideCharPointer(), flags); | |||
if (result == IDYES || result == IDOK) return 0; | |||
if (result == IDNO && ((flags & 1) != 0)) return 1; | |||
return 2; | |||
} | |||
private: | |||
static UINT getMessageBoxFlags (MessageBoxIconType iconType) noexcept | |||
{ | |||
// this window can get lost behind JUCE windows which are set to be alwaysOnTop | |||
// so if there are any set it to be topmost | |||
if (juce_areThereAnyAlwaysOnTopWindows()) | |||
flags |= MB_TOPMOST; | |||
const auto topmostFlag = juce_areThereAnyAlwaysOnTopWindows() ? MB_TOPMOST : 0; | |||
switch (iconType) | |||
const auto iconFlags = [&]() -> decltype (topmostFlag) | |||
{ | |||
case AlertWindow::QuestionIcon: flags |= MB_ICONQUESTION; break; | |||
case AlertWindow::WarningIcon: flags |= MB_ICONWARNING; break; | |||
case AlertWindow::InfoIcon: flags |= MB_ICONINFORMATION; break; | |||
case AlertWindow::NoIcon: JUCE_FALLTHROUGH | |||
default: break; | |||
switch (iconType) | |||
{ | |||
case MessageBoxIconType::QuestionIcon: return MB_ICONQUESTION; | |||
case MessageBoxIconType::WarningIcon: return MB_ICONWARNING; | |||
case MessageBoxIconType::InfoIcon: return MB_ICONINFORMATION; | |||
case MessageBoxIconType::NoIcon: break; | |||
} | |||
return 0; | |||
}(); | |||
return static_cast<UINT> (MB_TASKMODAL | MB_SETFOREGROUND | topmostFlag | iconFlags); | |||
} | |||
const UINT flags; | |||
const String title, message; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PreVistaMessageBox) | |||
}; | |||
using TaskDialogIndirectFunc = HRESULT (WINAPI*) (const TASKDIALOGCONFIG*, INT*, INT*, BOOL*); | |||
static TaskDialogIndirectFunc taskDialogIndirect = nullptr; | |||
class WindowsTaskDialog : public WindowsMessageBoxBase | |||
{ | |||
public: | |||
WindowsTaskDialog (const MessageBoxOptions& opts, | |||
std::unique_ptr<ModalComponentManager::Callback>&& callback) | |||
: WindowsMessageBoxBase (opts.getAssociatedComponent(), std::move (callback)), | |||
iconType (opts.getIconType()), | |||
title (opts.getTitle()), message (opts.getMessage()), | |||
button1 (opts.getButtonText (0)), button2 (opts.getButtonText (1)), button3 (opts.getButtonText (2)) | |||
{ | |||
} | |||
int getResult() override | |||
{ | |||
TASKDIALOGCONFIG config = { 0 }; | |||
config.cbSize = sizeof (config); | |||
config.pszWindowTitle = title.toWideCharPointer(); | |||
config.pszContent = message.toWideCharPointer(); | |||
config.hInstance = (HINSTANCE) Process::getCurrentModuleInstanceHandle(); | |||
if (iconType == MessageBoxIconType::QuestionIcon) | |||
{ | |||
if (auto* questionIcon = LoadIcon (nullptr, IDI_QUESTION)) | |||
{ | |||
config.hMainIcon = questionIcon; | |||
config.dwFlags |= TDF_USE_HICON_MAIN; | |||
} | |||
} | |||
else | |||
{ | |||
auto icon = [this]() -> LPWSTR | |||
{ | |||
switch (iconType) | |||
{ | |||
case MessageBoxIconType::WarningIcon: return TD_WARNING_ICON; | |||
case MessageBoxIconType::InfoIcon: return TD_INFORMATION_ICON; | |||
case MessageBoxIconType::QuestionIcon: JUCE_FALLTHROUGH | |||
case MessageBoxIconType::NoIcon: | |||
break; | |||
} | |||
return nullptr; | |||
}(); | |||
return flags; | |||
if (icon != nullptr) | |||
config.pszMainIcon = icon; | |||
} | |||
std::vector<TASKDIALOG_BUTTON> buttons; | |||
for (const auto* buttonText : { &button1, &button2, &button3 }) | |||
if (buttonText->isNotEmpty()) | |||
buttons.push_back ({ (int) buttons.size(), buttonText->toWideCharPointer() }); | |||
config.pButtons = buttons.data(); | |||
config.cButtons = (UINT) buttons.size(); | |||
int buttonIndex = 0; | |||
taskDialogIndirect (&config, &buttonIndex, nullptr, nullptr); | |||
return buttonIndex; | |||
} | |||
static HWND getWindowForMessageBox (Component* associatedComponent) | |||
static bool loadTaskDialog() | |||
{ | |||
return associatedComponent != nullptr ? (HWND) associatedComponent->getWindowHandle() : nullptr; | |||
static bool hasChecked = false; | |||
if (! hasChecked) | |||
{ | |||
hasChecked = true; | |||
const auto comctl = "Comctl32.dll"; | |||
LoadLibraryA (comctl); | |||
const auto comctlModule = GetModuleHandleA (comctl); | |||
if (comctlModule != nullptr) | |||
taskDialogIndirect = (TaskDialogIndirectFunc) GetProcAddress (comctlModule, "TaskDialogIndirect"); | |||
} | |||
return taskDialogIndirect != nullptr; | |||
} | |||
private: | |||
MessageBoxIconType iconType; | |||
String title, message, button1, button2, button3; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsTaskDialog) | |||
}; | |||
static std::unique_ptr<WindowsMessageBoxBase> createMessageBox (const MessageBoxOptions& options, | |||
std::unique_ptr<ModalComponentManager::Callback> callback) | |||
{ | |||
std::unique_ptr<WindowsMessageBoxBase> messageBox; | |||
if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista | |||
&& WindowsTaskDialog::loadTaskDialog()) | |||
{ | |||
messageBox.reset (new WindowsTaskDialog (options, std::move (callback))); | |||
} | |||
else | |||
{ | |||
const auto extraFlags = [&options] | |||
{ | |||
const auto numButtons = options.getNumButtons(); | |||
if (numButtons == 3) | |||
return MB_YESNOCANCEL; | |||
if (numButtons == 2) | |||
return options.getButtonText (0) == "OK" ? MB_OKCANCEL | |||
: MB_YESNO; | |||
return MB_OK; | |||
}(); | |||
messageBox.reset (new PreVistaMessageBox (options, (UINT) extraFlags, std::move (callback))); | |||
} | |||
return messageBox; | |||
} | |||
static int showDialog (const MessageBoxOptions& options, | |||
std::unique_ptr<ModalComponentManager::Callback> callback, | |||
Async async) | |||
{ | |||
auto messageBox = createMessageBox (options, std::move (callback)); | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (async == Async::no) | |||
return messageBox->getResult(); | |||
#endif | |||
ignoreUnused (async); | |||
messageBox->triggerAsyncUpdate(); | |||
messageBox.release(); | |||
return 0; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent) | |||
{ | |||
WindowsMessageBox box (iconType, title, message, associatedComponent, MB_OK, nullptr, false); | |||
(void) box.getResult(); | |||
showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withAssociatedComponent (associatedComponent), | |||
nullptr, | |||
Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options) | |||
{ | |||
return showDialog (options, nullptr, Async::no); | |||
} | |||
#endif | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType, | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
new WindowsMessageBox (iconType, title, message, associatedComponent, MB_OK, callback, true); | |||
showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::messageBox)), | |||
Async::yes); | |||
} | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType, | |||
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<WindowsMessageBox> mb (new WindowsMessageBox (iconType, title, message, associatedComponent, | |||
MB_OKCANCEL, callback, callback != nullptr)); | |||
if (callback == nullptr) | |||
return mb->getResult() != 0; | |||
mb.release(); | |||
return false; | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("OK")) | |||
.withButton (TRANS("Cancel")) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no) == 1; | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<WindowsMessageBox> mb (new WindowsMessageBox (iconType, title, message, associatedComponent, | |||
MB_YESNOCANCEL, callback, callback != nullptr)); | |||
if (callback == nullptr) | |||
return mb->getResult(); | |||
mb.release(); | |||
return 0; | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")) | |||
.withButton (TRANS("Cancel")) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::yesNoCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType iconType, | |||
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType, | |||
const String& title, const String& message, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
std::unique_ptr<WindowsMessageBox> mb (new WindowsMessageBox (iconType, title, message, associatedComponent, | |||
MB_YESNO, callback, callback != nullptr)); | |||
if (callback == nullptr) | |||
return mb->getResult(); | |||
return showDialog (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (TRANS("Yes")) | |||
.withButton (TRANS("No")) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel)), | |||
callback != nullptr ? Async::yes : Async::no); | |||
} | |||
mb.release(); | |||
return 0; | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
showDialog (options, rawToUniquePtr (callback), Async::yes); | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
//============================================================================== | |||
@@ -38,7 +38,7 @@ static juce_wchar getDefaultPasswordChar() noexcept | |||
//============================================================================== | |||
AlertWindow::AlertWindow (const String& title, | |||
const String& message, | |||
AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
Component* comp) | |||
: TopLevelWindow (title, true), | |||
alertIconType (iconType), | |||
@@ -561,20 +561,21 @@ int AlertWindow::getDesktopWindowStyleFlags() const | |||
return getLookAndFeel().getAlertBoxWindowFlags(); | |||
} | |||
enum class Async { no, yes }; | |||
//============================================================================== | |||
class AlertWindowInfo | |||
{ | |||
public: | |||
AlertWindowInfo (const String& t, const String& m, Component* component, | |||
AlertWindow::AlertIconType icon, int numButts, | |||
ModalComponentManager::Callback* cb, bool runModally) | |||
: title (t), message (m), iconType (icon), numButtons (numButts), | |||
associatedComponent (component), callback (cb), modal (runModally) | |||
AlertWindowInfo (const MessageBoxOptions& opts, | |||
std::unique_ptr<ModalComponentManager::Callback>&& cb, | |||
Async showAsync) | |||
: options (opts), | |||
callback (std::move (cb)), | |||
async (showAsync) | |||
{ | |||
} | |||
String title, message, button1, button2, button3; | |||
int invoke() const | |||
{ | |||
MessageManager::getInstance()->callFunctionOnMessageThread (showCallback, (void*) this); | |||
@@ -582,88 +583,153 @@ public: | |||
} | |||
private: | |||
AlertWindow::AlertIconType iconType; | |||
int numButtons, returnValue = 0; | |||
WeakReference<Component> associatedComponent; | |||
ModalComponentManager::Callback* callback; | |||
bool modal; | |||
static void* showCallback (void* userData) | |||
{ | |||
static_cast<AlertWindowInfo*> (userData)->show(); | |||
return nullptr; | |||
} | |||
void show() | |||
{ | |||
auto& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel() | |||
: LookAndFeel::getDefaultLookAndFeel(); | |||
auto* component = options.getAssociatedComponent(); | |||
auto& lf = (component != nullptr ? component->getLookAndFeel() | |||
: LookAndFeel::getDefaultLookAndFeel()); | |||
std::unique_ptr<AlertWindow> alertBox (lf.createAlertWindow (title, message, button1, button2, button3, | |||
iconType, numButtons, associatedComponent)); | |||
std::unique_ptr<AlertWindow> alertBox (lf.createAlertWindow (options.getTitle(), options.getMessage(), | |||
options.getButtonText (0), options.getButtonText (1), options.getButtonText (2), | |||
options.getIconType(), options.getNumButtons(), component)); | |||
jassert (alertBox != nullptr); // you have to return one of these! | |||
alertBox->setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (modal) | |||
{ | |||
if (async == Async::no) | |||
returnValue = alertBox->runModalLoop(); | |||
} | |||
else | |||
#endif | |||
{ | |||
ignoreUnused (modal); | |||
ignoreUnused (async); | |||
alertBox->enterModalState (true, callback, true); | |||
alertBox->enterModalState (true, callback.release(), true); | |||
alertBox.release(); | |||
} | |||
} | |||
static void* showCallback (void* userData) | |||
MessageBoxOptions options; | |||
std::unique_ptr<ModalComponentManager::Callback> callback; | |||
const Async async; | |||
int returnValue = 0; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AlertWindowInfo) | |||
}; | |||
namespace AlertWindowMappings | |||
{ | |||
static int messageBox (int) { return 0; } | |||
static int okCancel (int buttonIndex) { return buttonIndex == 0 ? 1 : 0; } | |||
static int yesNoCancel (int buttonIndex) { return buttonIndex == 2 ? 0 : buttonIndex + 1; } | |||
ModalComponentManager::Callback* getWrappedCallback (ModalComponentManager::Callback* callbackIn, | |||
std::function<int (int)> mapFn) | |||
{ | |||
static_cast<AlertWindowInfo*> (userData)->show(); | |||
return nullptr; | |||
if (callbackIn == nullptr) | |||
return nullptr; | |||
auto wrappedCallback = [innerCallback = rawToUniquePtr (callbackIn), mapFn] (int buttonIndex) | |||
{ | |||
innerCallback->modalStateFinished (mapFn (buttonIndex)); | |||
}; | |||
return ModalCallbackFunction::create (std::move (wrappedCallback)); | |||
} | |||
}; | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
void AlertWindow::showMessageBox (AlertIconType iconType, | |||
void AlertWindow::showMessageBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& buttonText, | |||
Component* associatedComponent) | |||
{ | |||
show (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (buttonText.isEmpty() ? TRANS("OK") : buttonText) | |||
.withAssociatedComponent (associatedComponent)); | |||
} | |||
int AlertWindow::show (const MessageBoxOptions& options) | |||
{ | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
return NativeMessageBox::show (options); | |||
AlertWindowInfo info (options, nullptr, Async::no); | |||
return info.invoke(); | |||
} | |||
#endif | |||
void AlertWindow::showAsync (const MessageBoxOptions& options, ModalComponentManager::Callback* callback) | |||
{ | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
{ | |||
NativeMessageBox::showMessageBox (iconType, title, message, associatedComponent); | |||
NativeMessageBox::showAsync (options, callback); | |||
} | |||
else | |||
{ | |||
AlertWindowInfo info (title, message, associatedComponent, iconType, 1, nullptr, true); | |||
info.button1 = buttonText.isEmpty() ? TRANS("OK") : buttonText; | |||
AlertWindowInfo info (options, rawToUniquePtr (callback), Async::yes); | |||
info.invoke(); | |||
} | |||
} | |||
#endif | |||
void AlertWindow::showMessageBoxAsync (AlertIconType iconType, | |||
void AlertWindow::showAsync (const MessageBoxOptions& options, std::function<void (int)> callback) | |||
{ | |||
showAsync (options, ModalCallbackFunction::create (callback)); | |||
} | |||
void AlertWindow::showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& buttonText, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
callback = AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::messageBox); | |||
showAsync (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (buttonText.isEmpty() ? TRANS("OK") : buttonText) | |||
.withAssociatedComponent (associatedComponent), | |||
callback); | |||
} | |||
static int showMaybeAsync (const MessageBoxOptions& options, | |||
std::unique_ptr<ModalComponentManager::Callback> callback) | |||
{ | |||
const auto showAsync = (callback != nullptr ? Async::yes | |||
: Async::no); | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
{ | |||
NativeMessageBox::showMessageBoxAsync (iconType, title, message, associatedComponent, callback); | |||
} | |||
else | |||
{ | |||
AlertWindowInfo info (title, message, associatedComponent, iconType, 1, callback, false); | |||
info.button1 = buttonText.isEmpty() ? TRANS("OK") : buttonText; | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
if (showAsync == Async::no) | |||
return NativeMessageBox::show (options); | |||
#endif | |||
info.invoke(); | |||
NativeMessageBox::showAsync (options, callback.release()); | |||
return false; | |||
} | |||
AlertWindowInfo info (options, std::move (callback), showAsync); | |||
return info.invoke(); | |||
} | |||
bool AlertWindow::showOkCancelBox (AlertIconType iconType, | |||
bool AlertWindow::showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& button1Text, | |||
@@ -672,16 +738,19 @@ bool AlertWindow::showOkCancelBox (AlertIconType iconType, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
return NativeMessageBox::showOkCancelBox (iconType, title, message, associatedComponent, callback); | |||
AlertWindowInfo info (title, message, associatedComponent, iconType, 2, callback, callback == nullptr); | |||
info.button1 = button1Text.isEmpty() ? TRANS("OK") : button1Text; | |||
info.button2 = button2Text.isEmpty() ? TRANS("Cancel") : button2Text; | |||
callback = AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::okCancel); | |||
return info.invoke() != 0; | |||
return showMaybeAsync (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (button1Text.isEmpty() ? TRANS("OK") : button1Text) | |||
.withButton (button2Text.isEmpty() ? TRANS("Cancel") : button2Text) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (callback)) == 1; | |||
} | |||
int AlertWindow::showYesNoCancelBox (AlertIconType iconType, | |||
int AlertWindow::showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& button1Text, | |||
@@ -691,29 +760,19 @@ int AlertWindow::showYesNoCancelBox (AlertIconType iconType, | |||
ModalComponentManager::Callback* callback) | |||
{ | |||
if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows()) | |||
return NativeMessageBox::showYesNoCancelBox (iconType, title, message, associatedComponent, callback); | |||
AlertWindowInfo info (title, message, associatedComponent, iconType, 3, callback, callback == nullptr); | |||
info.button1 = button1Text.isEmpty() ? TRANS("Yes") : button1Text; | |||
info.button2 = button2Text.isEmpty() ? TRANS("No") : button2Text; | |||
info.button3 = button3Text.isEmpty() ? TRANS("Cancel") : button3Text; | |||
return info.invoke(); | |||
callback = AlertWindowMappings::getWrappedCallback (callback, AlertWindowMappings::yesNoCancel); | |||
return showMaybeAsync (MessageBoxOptions() | |||
.withIconType (iconType) | |||
.withTitle (title) | |||
.withMessage (message) | |||
.withButton (button1Text.isEmpty() ? TRANS("Yes") : button1Text) | |||
.withButton (button2Text.isEmpty() ? TRANS("No") : button2Text) | |||
.withButton (button3Text.isEmpty() ? TRANS("Cancel") : button3Text) | |||
.withAssociatedComponent (associatedComponent), | |||
rawToUniquePtr (callback)); | |||
} | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
bool AlertWindow::showNativeDialogBox (const String& title, | |||
const String& bodyText, | |||
bool isOkCancel) | |||
{ | |||
if (isOkCancel) | |||
return NativeMessageBox::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); | |||
NativeMessageBox::showMessageBox (AlertWindow::NoIcon, title, bodyText); | |||
return true; | |||
} | |||
#endif | |||
//============================================================================== | |||
std::unique_ptr<AccessibilityHandler> AlertWindow::createAccessibilityHandler() | |||
{ | |||
@@ -44,20 +44,6 @@ namespace juce | |||
class JUCE_API AlertWindow : public TopLevelWindow | |||
{ | |||
public: | |||
//============================================================================== | |||
/** The type of icon to show in the dialog box. */ | |||
enum AlertIconType | |||
{ | |||
NoIcon, /**< No icon will be shown on the dialog box. */ | |||
QuestionIcon, /**< A question-mark icon, for dialog boxes that need the | |||
user to answer a question. */ | |||
WarningIcon, /**< An exclamation mark to indicate that the dialog is a | |||
warning about something and shouldn't be ignored. */ | |||
InfoIcon /**< An icon that indicates that the dialog box is just | |||
giving the user some information, which doesn't require | |||
a response from them. */ | |||
}; | |||
//============================================================================== | |||
/** Creates an AlertWindow. | |||
@@ -71,7 +57,7 @@ public: | |||
*/ | |||
AlertWindow (const String& title, | |||
const String& message, | |||
AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
Component* associatedComponent = nullptr); | |||
/** Destroys the AlertWindow */ | |||
@@ -80,7 +66,7 @@ public: | |||
//============================================================================== | |||
/** Returns the type of alert icon that was specified when the window | |||
was created. */ | |||
AlertIconType getAlertType() const noexcept { return alertIconType; } | |||
MessageBoxIconType getAlertType() const noexcept { return alertIconType; } | |||
//============================================================================== | |||
/** Changes the dialog box's message. | |||
@@ -226,8 +212,6 @@ public: | |||
bool containsAnyExtraComponents() const; | |||
//============================================================================== | |||
// easy-to-use message box functions: | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
/** Shows a dialog box that just has a message and a single button to get rid of it. | |||
@@ -244,13 +228,57 @@ public: | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
*/ | |||
static void JUCE_CALLTYPE showMessageBox (AlertIconType iconType, | |||
static void JUCE_CALLTYPE showMessageBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& buttonText = String(), | |||
Component* associatedComponent = nullptr); | |||
/** Shows a dialog box using the specified options. | |||
The box is shown modally, and the method will block until the user dismisses it. | |||
@param options the options to use when creating the dialog. | |||
@returns the index of the button that was clicked. | |||
@see MessageBoxOptions | |||
*/ | |||
static int JUCE_CALLTYPE show (const MessageBoxOptions& options); | |||
#endif | |||
/** Shows a dialog box using the specified options. | |||
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. | |||
@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 | |||
button that was clicked as its argument. | |||
The callback object will be owned and deleted by the system, so make sure | |||
that it works safely and doesn't keep any references to objects that might | |||
be deleted before it gets called. | |||
@see MessageBoxOptions | |||
*/ | |||
static void JUCE_CALLTYPE showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback); | |||
/** Shows a dialog box using the specified options. | |||
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. | |||
@param options the options to use when creating the dialog. | |||
@param callback if this is non-null, the callback will be called when the box is | |||
dismissed with the index of the button that was clicked as its argument. | |||
@see MessageBoxOptions | |||
*/ | |||
static void JUCE_CALLTYPE showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback); | |||
/** Shows a dialog box that just has a message and a single button to get rid of it. | |||
The box will be displayed and placed into a modal state, but this method will | |||
@@ -272,7 +300,7 @@ public: | |||
safely and doesn't keep any references to objects that might be deleted | |||
before it gets called. | |||
*/ | |||
static void JUCE_CALLTYPE showMessageBoxAsync (AlertIconType iconType, | |||
static void JUCE_CALLTYPE showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
const String& buttonText = String(), | |||
@@ -314,20 +342,20 @@ public: | |||
is not null, the method always returns false, and the user's choice is delivered | |||
later by the callback. | |||
*/ | |||
static bool JUCE_CALLTYPE showOkCancelBox (AlertIconType iconType, | |||
static bool JUCE_CALLTYPE showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
const String& button1Text = String(), | |||
const String& button2Text = String(), | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
#else | |||
#else | |||
const String& button1Text, | |||
const String& button2Text, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback); | |||
#endif | |||
#endif | |||
/** Shows a dialog box with three buttons. | |||
@@ -368,24 +396,27 @@ public: | |||
- 1 if the first button was pressed (normally used for 'yes') | |||
- 2 if the middle button was pressed (normally used for 'no') | |||
*/ | |||
static int JUCE_CALLTYPE showYesNoCancelBox (AlertIconType iconType, | |||
static int JUCE_CALLTYPE showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
const String& button1Text = String(), | |||
const String& button2Text = String(), | |||
const String& button3Text = String(), | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
#else | |||
#else | |||
const String& button1Text, | |||
const String& button2Text, | |||
const String& button3Text, | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback); | |||
#endif | |||
#endif | |||
//============================================================================== | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
// This has been deprecated, use the NativeMessageBox methods instead for more options. | |||
/** Shows an operating-system native dialog box. | |||
@param title the title to use at the top | |||
@@ -394,10 +425,9 @@ public: | |||
it'll show a box with just an ok button | |||
@returns true if the ok button was pressed, false if they pressed cancel. | |||
*/ | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
static bool JUCE_CALLTYPE showNativeDialogBox (const String& title, | |||
const String& bodyText, | |||
bool isOkCancel); | |||
JUCE_DEPRECATED (static bool JUCE_CALLTYPE showNativeDialogBox (const String& title, | |||
const String& bodyText, | |||
bool isOkCancel)); | |||
#endif | |||
@@ -428,7 +458,7 @@ public: | |||
const String& button1, | |||
const String& button2, | |||
const String& button3, | |||
AlertWindow::AlertIconType iconType, | |||
MessageBoxIconType iconType, | |||
int numButtons, | |||
Component* associatedComponent) = 0; | |||
@@ -444,6 +474,14 @@ public: | |||
virtual Font getAlertWindowFont() = 0; | |||
}; | |||
//============================================================================== | |||
using AlertIconType = MessageBoxIconType; | |||
static constexpr auto NoIcon = MessageBoxIconType::NoIcon; | |||
static constexpr auto QuestionIcon = MessageBoxIconType::QuestionIcon; | |||
static constexpr auto WarningIcon = MessageBoxIconType::WarningIcon; | |||
static constexpr auto InfoIcon = MessageBoxIconType::InfoIcon; | |||
protected: | |||
//============================================================================== | |||
/** @internal */ | |||
@@ -470,7 +508,7 @@ private: | |||
String text; | |||
TextLayout textLayout; | |||
Label accessibleMessageLabel; | |||
AlertIconType alertIconType; | |||
MessageBoxIconType alertIconType; | |||
ComponentBoundsConstrainer constrainer; | |||
ComponentDragger dragger; | |||
Rectangle<int> textArea; | |||
@@ -0,0 +1,141 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library. | |||
Copyright (c) 2020 - Raw Material Software Limited | |||
JUCE is an open source library subject to commercial or open-source | |||
licensing. | |||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License | |||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||
End User License Agreement: www.juce.com/juce-6-licence | |||
Privacy Policy: www.juce.com/juce-privacy-policy | |||
Or: You may also use this code under the terms of the GPL v3 (see | |||
www.gnu.org/licenses). | |||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
DISCLAIMED. | |||
============================================================================== | |||
*/ | |||
namespace juce | |||
{ | |||
/** The type of icon to show in the dialog box. */ | |||
enum class MessageBoxIconType | |||
{ | |||
NoIcon, /**< No icon will be shown on the dialog box. */ | |||
QuestionIcon, /**< A question-mark icon, for dialog boxes that need the | |||
user to answer a question. */ | |||
WarningIcon, /**< An exclamation mark to indicate that the dialog is a | |||
warning about something and shouldn't be ignored. */ | |||
InfoIcon /**< An icon that indicates that the dialog box is just | |||
giving the user some information, which doesn't require | |||
a response from them. */ | |||
}; | |||
//============================================================================== | |||
/** Class used to create a set of options to pass to the AlertWindow and NativeMessageBox | |||
methods for showing dialog boxes. | |||
You can chain together a series of calls to this class's methods to create | |||
a set of whatever options you want to specify. | |||
E.g. @code | |||
AlertWindow::showAsync (MessageBoxOptions() | |||
.withIconType (MessageBoxIconType::InfoIcon) | |||
.withTitle ("A Title") | |||
.withMessage ("A message.") | |||
.withButton ("OK") | |||
.withButton ("Cancel") | |||
.withAssociatedComponent (myComp), | |||
myCallback); | |||
@endcode | |||
*/ | |||
class JUCE_API MessageBoxOptions | |||
{ | |||
public: | |||
MessageBoxOptions() = default; | |||
MessageBoxOptions (const MessageBoxOptions&) = default; | |||
MessageBoxOptions& operator= (const MessageBoxOptions&) = default; | |||
//============================================================================== | |||
/** Sets the type of icon that should be used for the dialog box. */ | |||
MessageBoxOptions withIconType (MessageBoxIconType type) const { return with (*this, &MessageBoxOptions::iconType, type); } | |||
/** Sets the title of the dialog box. */ | |||
MessageBoxOptions withTitle (const String& boxTitle) const { return with (*this, &MessageBoxOptions::title, boxTitle); } | |||
/** Sets the message that should be displayed in the dialog box. */ | |||
MessageBoxOptions withMessage (const String& boxMessage) const { return with (*this, &MessageBoxOptions::message, boxMessage); } | |||
/** If the string passed in is not empty, this will add a button to the | |||
dialog box with the specified text. | |||
Generally up to 3 buttons are supported for dialog boxes, so adding any more | |||
than this may have no effect. | |||
*/ | |||
MessageBoxOptions withButton (const String& text) const { auto copy = *this; copy.buttons.add (text); return copy; } | |||
/** The component that the dialog box should be associated with. */ | |||
MessageBoxOptions withAssociatedComponent (Component* component) const { return with (*this, &MessageBoxOptions::associatedComponent, component); } | |||
//============================================================================== | |||
/** Returns the icon type of the dialog box. | |||
@see withIconType | |||
*/ | |||
MessageBoxIconType getIconType() const noexcept { return iconType; } | |||
/** Returns the title of the dialog box. | |||
@see withTitle | |||
*/ | |||
String getTitle() const { return title; } | |||
/** Returns the message of the dialog box. | |||
@see withMessage | |||
*/ | |||
String getMessage() const { return message; } | |||
/** Returns the number of buttons that have been added to the dialog box. | |||
@see withButtonText | |||
*/ | |||
int getNumButtons() const noexcept { return buttons.size(); } | |||
/** Returns the text that has been set for one of the buttons of the dialog box. | |||
@see withButtonText, getNumButtons | |||
*/ | |||
String getButtonText (int buttonIndex) const { return buttons[buttonIndex]; } | |||
/** Returns the component that the dialog box is associated with. | |||
@see withAssociatedComponent | |||
*/ | |||
Component* getAssociatedComponent() const noexcept { return associatedComponent; } | |||
private: | |||
//============================================================================== | |||
template <typename Member, typename Item> | |||
static MessageBoxOptions with (MessageBoxOptions options, Member&& member, Item&& item) | |||
{ | |||
options.*member = std::forward<Item> (item); | |||
return options; | |||
} | |||
//============================================================================== | |||
MessageBoxIconType iconType = MessageBoxIconType::InfoIcon; | |||
String title, message; | |||
StringArray buttons; | |||
WeakReference<Component> associatedComponent; | |||
}; | |||
} // namespace juce |
@@ -35,33 +35,77 @@ namespace juce | |||
class NativeMessageBox | |||
{ | |||
public: | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
/** Shows a dialog box that just has a message and a single 'ok' button to close it. | |||
The box is shown modally, and the method will block until the user has clicked its | |||
button (or pressed the escape or return keys). | |||
@param iconType the type of icon to show | |||
@param title the headline to show at the top of the box | |||
@param message a longer, more descriptive message to show underneath the title | |||
@param iconType the type of icon to show. | |||
@param title the headline to show at the top of the box. | |||
@param message a longer, more descriptive message to show underneath the title. | |||
@param associatedComponent if this is non-null, it specifies the component that the | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
*/ | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
static void JUCE_CALLTYPE showMessageBox (AlertWindow::AlertIconType iconType, | |||
static void JUCE_CALLTYPE showMessageBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
Component* associatedComponent = nullptr); | |||
/** Shows a dialog box using the specified options. | |||
The box is shown modally, and the method will block until the user dismisses it. | |||
@param options the options to use when creating the dialog. | |||
@returns the index of the button that was clicked. | |||
@see MessageBoxOptions | |||
*/ | |||
static int JUCE_CALLTYPE show (const MessageBoxOptions& options); | |||
#endif | |||
/** Shows a dialog box using the specified options. | |||
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. | |||
@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 | |||
button that was clicked as its argument. | |||
The callback object will be owned and deleted by the system, so make sure | |||
that it works safely and doesn't keep any references to objects that might | |||
be deleted before it gets called. | |||
@see MessageBoxOptions | |||
*/ | |||
static void JUCE_CALLTYPE showAsync (const MessageBoxOptions& options, | |||
ModalComponentManager::Callback* callback); | |||
/** Shows a dialog box using the specified options. | |||
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. | |||
@param options the options to use when creating the dialog. | |||
@param callback if this is non-null, the callback will be called when the box is | |||
dismissed with the index of the button that was clicked as its argument. | |||
@see MessageBoxOptions | |||
*/ | |||
static void JUCE_CALLTYPE showAsync (const MessageBoxOptions& options, | |||
std::function<void (int)> callback); | |||
/** Shows a dialog box that just has a message and a single 'ok' button to close it. | |||
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. | |||
@param iconType the type of icon to show | |||
@param title the headline to show at the top of the box | |||
@param message a longer, more descriptive message to show underneath the title | |||
@param iconType the type of icon to show. | |||
@param title the headline to show at the top of the box. | |||
@param message a longer, more descriptive message to show underneath the title. | |||
@param associatedComponent if this is non-null, it specifies the component that the | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
@@ -74,26 +118,26 @@ public: | |||
@see ModalCallbackFunction | |||
*/ | |||
static void JUCE_CALLTYPE showMessageBoxAsync (AlertWindow::AlertIconType iconType, | |||
const String& title, | |||
const String& message, | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
static void JUCE_CALLTYPE showMessageBoxAsync (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
/** Shows a dialog box with two buttons. | |||
Ideal for ok/cancel or yes/no choices. The return key can also be used | |||
to trigger the first button, and the escape key for the second button. | |||
If the callback parameter is null, the box is shown modally, and the method will | |||
block until the user has clicked the button (or pressed the escape or return keys). | |||
If the callback parameter is non-null, the box will be displayed and placed into a | |||
modal state, but this method will return immediately, and the callback will be invoked | |||
If the callback parameter is null and modal loops are enabled, the box is shown modally, | |||
and the method will block until the user has clicked the button (or pressed the escape or | |||
return keys). If the callback parameter is non-null, 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. | |||
@param iconType the type of icon to show | |||
@param title the headline to show at the top of the box | |||
@param message a longer, more descriptive message to show underneath the title | |||
@param iconType the type of icon to show. | |||
@param title the headline to show at the top of the box. | |||
@param message a longer, more descriptive message to show underneath the title. | |||
@param associatedComponent if this is non-null, it specifies the component that the | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
@@ -111,16 +155,16 @@ public: | |||
@see ModalCallbackFunction | |||
*/ | |||
static bool JUCE_CALLTYPE showOkCancelBox (AlertWindow::AlertIconType iconType, | |||
static bool JUCE_CALLTYPE showOkCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
#else | |||
#else | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback); | |||
#endif | |||
#endif | |||
/** Shows a dialog box with three buttons. | |||
@@ -128,15 +172,15 @@ public: | |||
The escape key can be used to trigger the third button. | |||
If the callback parameter is null, the box is shown modally, and the method will | |||
block until the user has clicked the button (or pressed the escape or return keys). | |||
If the callback parameter is non-null, the box will be displayed and placed into a | |||
modal state, but this method will return immediately, and the callback will be invoked | |||
If the callback parameter is null and modal loops are enabled, the box is shown modally, | |||
and the method will block until the user has clicked the button (or pressed the escape or | |||
return keys). If the callback parameter is non-null, 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. | |||
@param iconType the type of icon to show | |||
@param title the headline to show at the top of the box | |||
@param message a longer, more descriptive message to show underneath the title | |||
@param iconType the type of icon to show. | |||
@param title the headline to show at the top of the box. | |||
@param message a longer, more descriptive message to show underneath the title. | |||
@param associatedComponent if this is non-null, it specifies the component that the | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
@@ -157,16 +201,16 @@ public: | |||
@see ModalCallbackFunction | |||
*/ | |||
static int JUCE_CALLTYPE showYesNoCancelBox (AlertWindow::AlertIconType iconType, | |||
static int JUCE_CALLTYPE showYesNoCancelBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
Component* associatedComponent = nullptr, | |||
ModalComponentManager::Callback* callback = nullptr); | |||
#else | |||
#else | |||
Component* associatedComponent, | |||
ModalComponentManager::Callback* callback); | |||
#endif | |||
#endif | |||
/** Shows a dialog box with two buttons. | |||
@@ -174,15 +218,15 @@ public: | |||
The escape key can be used to trigger the no button. | |||
If the callback parameter is null, the box is shown modally, and the method will | |||
block until the user has clicked the button (or pressed the escape or return keys). | |||
If the callback parameter is non-null, the box will be displayed and placed into a | |||
modal state, but this method will return immediately, and the callback will be invoked | |||
If the callback parameter is null and modal loops are enabled, the box is shown modally, | |||
and the method will block until the user has clicked the button (or pressed the escape or | |||
return keys). If the callback parameter is non-null, 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. | |||
@param iconType the type of icon to show | |||
@param title the headline to show at the top of the box | |||
@param message a longer, more descriptive message to show underneath the title | |||
@param iconType the type of icon to show. | |||
@param title the headline to show at the top of the box. | |||
@param message a longer, more descriptive message to show underneath the title. | |||
@param associatedComponent if this is non-null, it specifies the component that the | |||
alert window should be associated with. Depending on the look | |||
and feel, this might be used for positioning of the alert window. | |||
@@ -202,7 +246,7 @@ public: | |||
@see ModalCallbackFunction | |||
*/ | |||
static int JUCE_CALLTYPE showYesNoBox (AlertWindow::AlertIconType iconType, | |||
static int JUCE_CALLTYPE showYesNoBox (MessageBoxIconType iconType, | |||
const String& title, | |||
const String& message, | |||
#if JUCE_MODAL_LOOPS_PERMITTED | |||
@@ -41,7 +41,7 @@ ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title, | |||
.createAlertWindow (title, {}, | |||
cancelButtonText.isEmpty() ? TRANS("Cancel") | |||
: cancelButtonText, | |||
{}, {}, AlertWindow::NoIcon, hasCancelButton ? 1 : 0, | |||
{}, {}, MessageBoxIconType::NoIcon, hasCancelButton ? 1 : 0, | |||
componentToCentreAround)); | |||
// if there are no buttons, we won't allow the user to interrupt the thread. | |||
@@ -339,7 +339,7 @@ private: | |||
auto result = Result::fail (TRANS ("The file doesn't exist")); | |||
if (showMessageOnFailure) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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()) | |||
@@ -448,7 +448,7 @@ private: | |||
callback (parent, alertResult); | |||
}); | |||
return AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon, | |||
return AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon, | |||
TRANS ("Closing document..."), | |||
TRANS ("Do you want to save the changes to \"DCNM\"?") | |||
.replace ("DCNM", document.getDocumentTitle()), | |||
@@ -510,7 +510,7 @@ private: | |||
MouseCursor::hideWaitCursor(); | |||
if (showMessageOnFailure) | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
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()) | |||
@@ -682,7 +682,7 @@ private: | |||
callback (parent, r == 1); | |||
}); | |||
return AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
return AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
TRANS ("File already exists"), | |||
TRANS ("There's already a file called: FLNM") | |||
.replace ("FLNM", newFile.getFullPathName()) | |||
@@ -98,7 +98,7 @@ public: | |||
KeyEntryWindow (KeyMappingEditorComponent& kec) | |||
: AlertWindow (TRANS("New key-mapping"), | |||
TRANS("Please press a key combination now..."), | |||
AlertWindow::NoIcon), | |||
MessageBoxIconType::NoIcon), | |||
owner (kec) | |||
{ | |||
addButton (TRANS("OK"), 1); | |||
@@ -165,7 +165,7 @@ public: | |||
} | |||
else | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, | |||
AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon, | |||
TRANS("Change key-mapping"), | |||
TRANS("This key is already assigned to the command \"CMDN\"") | |||
.replace ("CMDN", owner.getCommandManager().getNameOfCommand (previousCommand)) | |||
@@ -403,7 +403,7 @@ KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet& mappin | |||
resetButton.onClick = [this] | |||
{ | |||
AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, | |||
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"), | |||
@@ -100,13 +100,13 @@ struct OnlineUnlockForm::OverlayComp : public Component, | |||
if (result.errorMessage.isNotEmpty()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, | |||
TRANS("Registration Failed"), | |||
result.errorMessage); | |||
} | |||
else if (result.informativeMessage.isNotEmpty()) | |||
{ | |||
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, | |||
TRANS("Registration Complete!"), | |||
result.informativeMessage); | |||
} | |||