The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
24KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. static juce_wchar getDefaultPasswordChar() noexcept
  22. {
  23. #if JUCE_LINUX
  24. return 0x2022;
  25. #else
  26. return 0x25cf;
  27. #endif
  28. }
  29. //==============================================================================
  30. AlertWindow::AlertWindow (const String& title,
  31. const String& message,
  32. AlertIconType iconType,
  33. Component* comp)
  34. : TopLevelWindow (title, true),
  35. alertIconType (iconType),
  36. associatedComponent (comp),
  37. escapeKeyCancels (true)
  38. {
  39. setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows());
  40. if (message.isEmpty())
  41. text = " "; // to force an update if the message is empty
  42. setMessage (message);
  43. AlertWindow::lookAndFeelChanged();
  44. constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000);
  45. }
  46. AlertWindow::~AlertWindow()
  47. {
  48. removeAllChildren();
  49. }
  50. void AlertWindow::userTriedToCloseWindow()
  51. {
  52. if (escapeKeyCancels || buttons.size() > 0)
  53. exitModalState (0);
  54. }
  55. //==============================================================================
  56. void AlertWindow::setMessage (const String& message)
  57. {
  58. const String newMessage (message.substring (0, 2048));
  59. if (text != newMessage)
  60. {
  61. text = newMessage;
  62. updateLayout (true);
  63. repaint();
  64. }
  65. }
  66. //==============================================================================
  67. void AlertWindow::buttonClicked (Button* button)
  68. {
  69. if (Component* parent = button->getParentComponent())
  70. parent->exitModalState (button->getCommandID());
  71. }
  72. //==============================================================================
  73. void AlertWindow::addButton (const String& name,
  74. const int returnValue,
  75. const KeyPress& shortcutKey1,
  76. const KeyPress& shortcutKey2)
  77. {
  78. TextButton* const b = new TextButton (name, String());
  79. buttons.add (b);
  80. b->setWantsKeyboardFocus (true);
  81. b->setMouseClickGrabsKeyboardFocus (false);
  82. b->setCommandToTrigger (0, returnValue, false);
  83. b->addShortcut (shortcutKey1);
  84. b->addShortcut (shortcutKey2);
  85. b->addListener (this);
  86. Array<TextButton*> buttonsArray (buttons.begin(), buttons.size());
  87. const int buttonHeight = getLookAndFeel().getAlertWindowButtonHeight();
  88. const Array<int> buttonWidths = getLookAndFeel().getWidthsForTextButtons (*this, buttonsArray);
  89. jassert (buttonWidths.size() == buttons.size());
  90. const int n = buttonWidths.size();
  91. for (int i = 0; i < n; ++i)
  92. buttons.getUnchecked (i)->setSize (buttonWidths.getReference (i), buttonHeight);
  93. addAndMakeVisible (b, 0);
  94. updateLayout (false);
  95. }
  96. int AlertWindow::getNumButtons() const
  97. {
  98. return buttons.size();
  99. }
  100. void AlertWindow::triggerButtonClick (const String& buttonName)
  101. {
  102. for (int i = buttons.size(); --i >= 0;)
  103. {
  104. TextButton* const b = buttons.getUnchecked(i);
  105. if (buttonName == b->getName())
  106. {
  107. b->triggerClick();
  108. break;
  109. }
  110. }
  111. }
  112. void AlertWindow::setEscapeKeyCancels (bool shouldEscapeKeyCancel)
  113. {
  114. escapeKeyCancels = shouldEscapeKeyCancel;
  115. }
  116. //==============================================================================
  117. void AlertWindow::addTextEditor (const String& name,
  118. const String& initialContents,
  119. const String& onScreenLabel,
  120. const bool isPasswordBox)
  121. {
  122. TextEditor* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0);
  123. ed->setSelectAllWhenFocused (true);
  124. ed->setEscapeAndReturnKeysConsumed (false);
  125. textBoxes.add (ed);
  126. allComps.add (ed);
  127. ed->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId));
  128. ed->setFont (getLookAndFeel().getAlertWindowMessageFont());
  129. addAndMakeVisible (ed);
  130. ed->setText (initialContents);
  131. ed->setCaretPosition (initialContents.length());
  132. textboxNames.add (onScreenLabel);
  133. updateLayout (false);
  134. }
  135. TextEditor* AlertWindow::getTextEditor (const String& nameOfTextEditor) const
  136. {
  137. for (int i = textBoxes.size(); --i >= 0;)
  138. if (textBoxes.getUnchecked(i)->getName() == nameOfTextEditor)
  139. return textBoxes.getUnchecked(i);
  140. return nullptr;
  141. }
  142. String AlertWindow::getTextEditorContents (const String& nameOfTextEditor) const
  143. {
  144. if (auto* t = getTextEditor (nameOfTextEditor))
  145. return t->getText();
  146. return {};
  147. }
  148. //==============================================================================
  149. void AlertWindow::addComboBox (const String& name,
  150. const StringArray& items,
  151. const String& onScreenLabel)
  152. {
  153. ComboBox* const cb = new ComboBox (name);
  154. comboBoxes.add (cb);
  155. allComps.add (cb);
  156. cb->addItemList (items, 1);
  157. addAndMakeVisible (cb);
  158. cb->setSelectedItemIndex (0);
  159. comboBoxNames.add (onScreenLabel);
  160. updateLayout (false);
  161. }
  162. ComboBox* AlertWindow::getComboBoxComponent (const String& nameOfList) const
  163. {
  164. for (int i = comboBoxes.size(); --i >= 0;)
  165. if (comboBoxes.getUnchecked(i)->getName() == nameOfList)
  166. return comboBoxes.getUnchecked(i);
  167. return nullptr;
  168. }
  169. //==============================================================================
  170. class AlertTextComp : public TextEditor
  171. {
  172. public:
  173. AlertTextComp (AlertWindow& owner, const String& message, const Font& font)
  174. {
  175. if (owner.isColourSpecified (AlertWindow::textColourId))
  176. setColour (TextEditor::textColourId, owner.findColour (AlertWindow::textColourId));
  177. setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
  178. setColour (TextEditor::outlineColourId, Colours::transparentBlack);
  179. setColour (TextEditor::shadowColourId, Colours::transparentBlack);
  180. setReadOnly (true);
  181. setMultiLine (true, true);
  182. setCaretVisible (false);
  183. setScrollbarsShown (true);
  184. lookAndFeelChanged();
  185. setWantsKeyboardFocus (false);
  186. setFont (font);
  187. setText (message, false);
  188. bestWidth = 2 * (int) std::sqrt (font.getHeight() * font.getStringWidth (message));
  189. }
  190. int getPreferredWidth() const noexcept { return bestWidth; }
  191. void updateLayout (const int width)
  192. {
  193. AttributedString s;
  194. s.setJustification (Justification::topLeft);
  195. s.append (getText(), getFont());
  196. TextLayout text;
  197. text.createLayoutWithBalancedLineLengths (s, width - 8.0f);
  198. setSize (width, jmin (width, (int) (text.getHeight() + getFont().getHeight())));
  199. }
  200. private:
  201. int bestWidth;
  202. JUCE_DECLARE_NON_COPYABLE (AlertTextComp)
  203. };
  204. void AlertWindow::addTextBlock (const String& textBlock)
  205. {
  206. AlertTextComp* const c = new AlertTextComp (*this, textBlock, getLookAndFeel().getAlertWindowMessageFont());
  207. textBlocks.add (c);
  208. allComps.add (c);
  209. addAndMakeVisible (c);
  210. updateLayout (false);
  211. }
  212. //==============================================================================
  213. void AlertWindow::addProgressBarComponent (double& progressValue)
  214. {
  215. ProgressBar* const pb = new ProgressBar (progressValue);
  216. progressBars.add (pb);
  217. allComps.add (pb);
  218. addAndMakeVisible (pb);
  219. updateLayout (false);
  220. }
  221. //==============================================================================
  222. void AlertWindow::addCustomComponent (Component* const component)
  223. {
  224. customComps.add (component);
  225. allComps.add (component);
  226. addAndMakeVisible (component);
  227. updateLayout (false);
  228. }
  229. int AlertWindow::getNumCustomComponents() const
  230. {
  231. return customComps.size();
  232. }
  233. Component* AlertWindow::getCustomComponent (const int index) const
  234. {
  235. return customComps [index];
  236. }
  237. Component* AlertWindow::removeCustomComponent (const int index)
  238. {
  239. Component* const c = getCustomComponent (index);
  240. if (c != nullptr)
  241. {
  242. customComps.removeFirstMatchingValue (c);
  243. allComps.removeFirstMatchingValue (c);
  244. removeChildComponent (c);
  245. updateLayout (false);
  246. }
  247. return c;
  248. }
  249. //==============================================================================
  250. void AlertWindow::paint (Graphics& g)
  251. {
  252. getLookAndFeel().drawAlertBox (g, *this, textArea, textLayout);
  253. g.setColour (findColour (textColourId));
  254. g.setFont (getLookAndFeel().getAlertWindowFont());
  255. for (int i = textBoxes.size(); --i >= 0;)
  256. {
  257. const TextEditor* const te = textBoxes.getUnchecked(i);
  258. g.drawFittedText (textboxNames[i],
  259. te->getX(), te->getY() - 14,
  260. te->getWidth(), 14,
  261. Justification::centredLeft, 1);
  262. }
  263. for (int i = comboBoxNames.size(); --i >= 0;)
  264. {
  265. const ComboBox* const cb = comboBoxes.getUnchecked(i);
  266. g.drawFittedText (comboBoxNames[i],
  267. cb->getX(), cb->getY() - 14,
  268. cb->getWidth(), 14,
  269. Justification::centredLeft, 1);
  270. }
  271. for (int i = customComps.size(); --i >= 0;)
  272. {
  273. const Component* const c = customComps.getUnchecked(i);
  274. g.drawFittedText (c->getName(),
  275. c->getX(), c->getY() - 14,
  276. c->getWidth(), 14,
  277. Justification::centredLeft, 1);
  278. }
  279. }
  280. void AlertWindow::updateLayout (const bool onlyIncreaseSize)
  281. {
  282. const int titleH = 24;
  283. const int iconWidth = 80;
  284. LookAndFeel& lf = getLookAndFeel();
  285. const Font messageFont (lf.getAlertWindowMessageFont());
  286. const int wid = jmax (messageFont.getStringWidth (text),
  287. messageFont.getStringWidth (getName()));
  288. const int sw = (int) std::sqrt (messageFont.getHeight() * wid);
  289. int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f));
  290. const int edgeGap = 10;
  291. const int labelHeight = 18;
  292. int iconSpace = 0;
  293. AttributedString attributedText;
  294. attributedText.append (getName(), lf.getAlertWindowTitleFont());
  295. if (text.isNotEmpty())
  296. attributedText.append ("\n\n" + text, messageFont);
  297. attributedText.setColour (findColour (textColourId));
  298. if (alertIconType == NoIcon)
  299. {
  300. attributedText.setJustification (Justification::centredTop);
  301. textLayout.createLayoutWithBalancedLineLengths (attributedText, (float) w);
  302. }
  303. else
  304. {
  305. attributedText.setJustification (Justification::topLeft);
  306. textLayout.createLayoutWithBalancedLineLengths (attributedText, (float) w);
  307. iconSpace = iconWidth;
  308. }
  309. w = jmax (350, (int) textLayout.getWidth() + iconSpace + edgeGap * 4);
  310. w = jmin (w, (int) (getParentWidth() * 0.7f));
  311. const int textLayoutH = (int) textLayout.getHeight();
  312. const int textBottom = 16 + titleH + textLayoutH;
  313. int h = textBottom;
  314. int buttonW = 40;
  315. for (int i = 0; i < buttons.size(); ++i)
  316. buttonW += 16 + buttons.getUnchecked (i)->getWidth();
  317. w = jmax (buttonW, w);
  318. h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50;
  319. if (buttons.size() > 0)
  320. h += 20 + buttons.getUnchecked (0)->getHeight();
  321. for (int i = customComps.size(); --i >= 0;)
  322. {
  323. Component* c = customComps.getUnchecked (i);
  324. w = jmax (w, (c->getWidth() * 100) / 80);
  325. h += 10 + c->getHeight();
  326. if (c->getName().isNotEmpty())
  327. h += labelHeight;
  328. }
  329. for (int i = textBlocks.size(); --i >= 0;)
  330. {
  331. const AlertTextComp* const ac = static_cast<const AlertTextComp*> (textBlocks.getUnchecked(i));
  332. w = jmax (w, ac->getPreferredWidth());
  333. }
  334. w = jmin (w, (int) (getParentWidth() * 0.7f));
  335. for (int i = textBlocks.size(); --i >= 0;)
  336. {
  337. AlertTextComp* const ac = static_cast<AlertTextComp*> (textBlocks.getUnchecked(i));
  338. ac->updateLayout ((int) (w * 0.8f));
  339. h += ac->getHeight() + 10;
  340. }
  341. h = jmin (getParentHeight() - 50, h);
  342. if (onlyIncreaseSize)
  343. {
  344. w = jmax (w, getWidth());
  345. h = jmax (h, getHeight());
  346. }
  347. if (! isVisible())
  348. centreAroundComponent (associatedComponent, w, h);
  349. else
  350. setBounds (getBounds().withSizeKeepingCentre (w, h));
  351. textArea.setBounds (edgeGap, edgeGap, w - (edgeGap * 2), h - edgeGap);
  352. const int spacer = 16;
  353. int totalWidth = -spacer;
  354. for (int i = buttons.size(); --i >= 0;)
  355. totalWidth += buttons.getUnchecked(i)->getWidth() + spacer;
  356. int x = (w - totalWidth) / 2;
  357. int y = (int) (getHeight() * 0.95f);
  358. for (int i = 0; i < buttons.size(); ++i)
  359. {
  360. TextButton* const c = buttons.getUnchecked(i);
  361. int ny = proportionOfHeight (0.95f) - c->getHeight();
  362. c->setTopLeftPosition (x, ny);
  363. if (ny < y)
  364. y = ny;
  365. x += c->getWidth() + spacer;
  366. c->toFront (false);
  367. }
  368. y = textBottom;
  369. for (int i = 0; i < allComps.size(); ++i)
  370. {
  371. Component* const c = allComps.getUnchecked(i);
  372. h = 22;
  373. const int comboIndex = comboBoxes.indexOf (dynamic_cast<ComboBox*> (c));
  374. if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty())
  375. y += labelHeight;
  376. const int tbIndex = textBoxes.indexOf (dynamic_cast<TextEditor*> (c));
  377. if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty())
  378. y += labelHeight;
  379. if (customComps.contains (c))
  380. {
  381. if (c->getName().isNotEmpty())
  382. y += labelHeight;
  383. c->setTopLeftPosition (proportionOfWidth (0.1f), y);
  384. h = c->getHeight();
  385. }
  386. else if (textBlocks.contains (c))
  387. {
  388. c->setTopLeftPosition ((getWidth() - c->getWidth()) / 2, y);
  389. h = c->getHeight();
  390. }
  391. else
  392. {
  393. c->setBounds (proportionOfWidth (0.1f), y, proportionOfWidth (0.8f), h);
  394. }
  395. y += h + 10;
  396. }
  397. setWantsKeyboardFocus (getNumChildComponents() == 0);
  398. }
  399. bool AlertWindow::containsAnyExtraComponents() const
  400. {
  401. return allComps.size() > 0;
  402. }
  403. //==============================================================================
  404. void AlertWindow::mouseDown (const MouseEvent& e)
  405. {
  406. dragger.startDraggingComponent (this, e);
  407. }
  408. void AlertWindow::mouseDrag (const MouseEvent& e)
  409. {
  410. dragger.dragComponent (this, e, &constrainer);
  411. }
  412. bool AlertWindow::keyPressed (const KeyPress& key)
  413. {
  414. for (int i = buttons.size(); --i >= 0;)
  415. {
  416. TextButton* const b = buttons.getUnchecked(i);
  417. if (b->isRegisteredForShortcut (key))
  418. {
  419. b->triggerClick();
  420. return true;
  421. }
  422. }
  423. if (key.isKeyCode (KeyPress::escapeKey) && escapeKeyCancels && buttons.size() == 0)
  424. {
  425. exitModalState (0);
  426. return true;
  427. }
  428. if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1)
  429. {
  430. buttons.getUnchecked(0)->triggerClick();
  431. return true;
  432. }
  433. return false;
  434. }
  435. void AlertWindow::lookAndFeelChanged()
  436. {
  437. const int newFlags = getLookAndFeel().getAlertBoxWindowFlags();
  438. setUsingNativeTitleBar ((newFlags & ComponentPeer::windowHasTitleBar) != 0);
  439. setDropShadowEnabled (isOpaque() && (newFlags & ComponentPeer::windowHasDropShadow) != 0);
  440. updateLayout (false);
  441. }
  442. int AlertWindow::getDesktopWindowStyleFlags() const
  443. {
  444. return getLookAndFeel().getAlertBoxWindowFlags();
  445. }
  446. //==============================================================================
  447. class AlertWindowInfo
  448. {
  449. public:
  450. AlertWindowInfo (const String& t, const String& m, Component* component,
  451. AlertWindow::AlertIconType icon, int numButts,
  452. ModalComponentManager::Callback* cb, bool runModally)
  453. : title (t), message (m), iconType (icon), numButtons (numButts),
  454. returnValue (0), associatedComponent (component),
  455. callback (cb), modal (runModally)
  456. {
  457. }
  458. String title, message, button1, button2, button3;
  459. int invoke() const
  460. {
  461. MessageManager::getInstance()->callFunctionOnMessageThread (showCallback, (void*) this);
  462. return returnValue;
  463. }
  464. private:
  465. AlertWindow::AlertIconType iconType;
  466. int numButtons, returnValue;
  467. WeakReference<Component> associatedComponent;
  468. ModalComponentManager::Callback* callback;
  469. bool modal;
  470. void show()
  471. {
  472. LookAndFeel& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel()
  473. : LookAndFeel::getDefaultLookAndFeel();
  474. ScopedPointer<Component> alertBox (lf.createAlertWindow (title, message, button1, button2, button3,
  475. iconType, numButtons, associatedComponent));
  476. jassert (alertBox != nullptr); // you have to return one of these!
  477. alertBox->setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows());
  478. #if JUCE_MODAL_LOOPS_PERMITTED
  479. if (modal)
  480. {
  481. returnValue = alertBox->runModalLoop();
  482. }
  483. else
  484. #endif
  485. {
  486. ignoreUnused (modal);
  487. alertBox->enterModalState (true, callback, true);
  488. alertBox.release();
  489. }
  490. }
  491. static void* showCallback (void* userData)
  492. {
  493. static_cast<AlertWindowInfo*> (userData)->show();
  494. return nullptr;
  495. }
  496. };
  497. #if JUCE_MODAL_LOOPS_PERMITTED
  498. void AlertWindow::showMessageBox (AlertIconType iconType,
  499. const String& title,
  500. const String& message,
  501. const String& buttonText,
  502. Component* associatedComponent)
  503. {
  504. if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows())
  505. {
  506. NativeMessageBox::showMessageBox (iconType, title, message, associatedComponent);
  507. }
  508. else
  509. {
  510. AlertWindowInfo info (title, message, associatedComponent, iconType, 1, nullptr, true);
  511. info.button1 = buttonText.isEmpty() ? TRANS("OK") : buttonText;
  512. info.invoke();
  513. }
  514. }
  515. #endif
  516. void AlertWindow::showMessageBoxAsync (AlertIconType iconType,
  517. const String& title,
  518. const String& message,
  519. const String& buttonText,
  520. Component* associatedComponent,
  521. ModalComponentManager::Callback* callback)
  522. {
  523. if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows())
  524. {
  525. NativeMessageBox::showMessageBoxAsync (iconType, title, message, associatedComponent, callback);
  526. }
  527. else
  528. {
  529. AlertWindowInfo info (title, message, associatedComponent, iconType, 1, callback, false);
  530. info.button1 = buttonText.isEmpty() ? TRANS("OK") : buttonText;
  531. info.invoke();
  532. }
  533. }
  534. bool AlertWindow::showOkCancelBox (AlertIconType iconType,
  535. const String& title,
  536. const String& message,
  537. const String& button1Text,
  538. const String& button2Text,
  539. Component* associatedComponent,
  540. ModalComponentManager::Callback* callback)
  541. {
  542. if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows())
  543. return NativeMessageBox::showOkCancelBox (iconType, title, message, associatedComponent, callback);
  544. AlertWindowInfo info (title, message, associatedComponent, iconType, 2, callback, callback == nullptr);
  545. info.button1 = button1Text.isEmpty() ? TRANS("OK") : button1Text;
  546. info.button2 = button2Text.isEmpty() ? TRANS("Cancel") : button2Text;
  547. return info.invoke() != 0;
  548. }
  549. int AlertWindow::showYesNoCancelBox (AlertIconType iconType,
  550. const String& title,
  551. const String& message,
  552. const String& button1Text,
  553. const String& button2Text,
  554. const String& button3Text,
  555. Component* associatedComponent,
  556. ModalComponentManager::Callback* callback)
  557. {
  558. if (LookAndFeel::getDefaultLookAndFeel().isUsingNativeAlertWindows())
  559. return NativeMessageBox::showYesNoCancelBox (iconType, title, message, associatedComponent, callback);
  560. AlertWindowInfo info (title, message, associatedComponent, iconType, 3, callback, callback == nullptr);
  561. info.button1 = button1Text.isEmpty() ? TRANS("Yes") : button1Text;
  562. info.button2 = button2Text.isEmpty() ? TRANS("No") : button2Text;
  563. info.button3 = button3Text.isEmpty() ? TRANS("Cancel") : button3Text;
  564. return info.invoke();
  565. }
  566. #if JUCE_MODAL_LOOPS_PERMITTED
  567. bool AlertWindow::showNativeDialogBox (const String& title,
  568. const String& bodyText,
  569. bool isOkCancel)
  570. {
  571. if (isOkCancel)
  572. return NativeMessageBox::showOkCancelBox (AlertWindow::NoIcon, title, bodyText);
  573. NativeMessageBox::showMessageBox (AlertWindow::NoIcon, title, bodyText);
  574. return true;
  575. }
  576. #endif
  577. //==============================================================================
  578. struct NativeMessageBoxCallback : ModalComponentManager::Callback
  579. {
  580. NativeMessageBoxCallback (std::function<void (int)> && lambda)
  581. : callback (static_cast<std::function<void (int)>&&> (lambda))
  582. {}
  583. void modalStateFinished (int returnValue) override { if (callback) callback (returnValue); }
  584. std::function<void (int)> callback;
  585. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeMessageBoxCallback);
  586. };
  587. void NativeMessageBox::showMessageBox (MessageBoxType dialogType, AlertWindow::AlertIconType iconType,
  588. const String& title, const String& message,
  589. std::function<void (int)> && lambda, Component* associatedComponent)
  590. {
  591. auto* callback = new NativeMessageBoxCallback (static_cast<std::function<void (int)>&&> (lambda));
  592. switch (dialogType)
  593. {
  594. case okType: showMessageBoxAsync (iconType, title, message, associatedComponent, callback); break;
  595. case okCancelType: showOkCancelBox (iconType, title, message, associatedComponent, callback); break;
  596. case yesNoType: showYesNoBox (iconType, title, message, associatedComponent, callback); break;
  597. case yesNoCancelType: showYesNoCancelBox (iconType, title, message, associatedComponent, callback); break;
  598. default:
  599. jassertfalse;
  600. }
  601. }
  602. } // namespace juce