macMsgBox.mm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #import <Cocoa/Cocoa.h>
  23. #include "platform/nativeDialogs/msgBox.h"
  24. #include "console/console.h"
  25. void Platform::AlertOK(const char *windowTitle, const char *message)
  26. {
  27. Platform::messageBox(windowTitle, message, MBOk, MIInformation);
  28. }
  29. //--------------------------------------
  30. bool Platform::AlertOKCancel(const char *windowTitle, const char *message)
  31. {
  32. return ( Platform::messageBox(windowTitle, message, MBOkCancel, MIInformation) == MROk );
  33. }
  34. //--------------------------------------
  35. bool Platform::AlertRetry(const char *windowTitle, const char *message)
  36. {
  37. return ( Platform::messageBox(windowTitle, message, MBRetryCancel, MIInformation) == MRRetry );
  38. }
  39. namespace MsgBoxMac
  40. {
  41. struct _NSStringMap
  42. {
  43. S32 num;
  44. NSString* ok;
  45. NSString* cancel;
  46. NSString* third;
  47. };
  48. static _NSStringMap sgButtonTextMap[] =
  49. {
  50. { MBOk, @"OK", nil, nil },
  51. { MBOkCancel, @"OK", @"Cancel", nil },
  52. { MBRetryCancel, @"Retry", @"Cancel", nil },
  53. { MBSaveDontSave, @"Yes", @"No", nil },
  54. { MBSaveDontSaveCancel, @"Yes", @"No", @"Cancel" },
  55. { -1, nil, nil, nil }
  56. };
  57. struct _NSAlertResultMap
  58. {
  59. S32 num;
  60. S32 ok;
  61. S32 cancel;
  62. S32 third;
  63. };
  64. static _NSAlertResultMap sgAlertResultMap[] =
  65. {
  66. { MBOk, MROk, 0, 0 },
  67. { MBOkCancel, MROk, MRCancel, 0 },
  68. { MBRetryCancel, MRRetry, MRCancel, 0 },
  69. { MBSaveDontSave, MROk, MRDontSave, 0 },
  70. { MBSaveDontSaveCancel, MROk, MRDontSave, MRCancel },
  71. { -1, nil, nil, nil }
  72. };
  73. } // end MsgBoxMac namespace
  74. //-----------------------------------------------------------------------------
  75. S32 Platform::messageBox(const UTF8 *title, const UTF8 *message, MBButtons buttons, MBIcons icon)
  76. {
  77. // TODO: put this on the main thread
  78. // determine the button text
  79. NSString *okBtn = nil;
  80. NSString *cancelBtn = nil;
  81. NSString *thirdBtn = nil;
  82. U32 i;
  83. for(i = 0; MsgBoxMac::sgButtonTextMap[i].num != -1; i++)
  84. {
  85. if(MsgBoxMac::sgButtonTextMap[i].num != buttons)
  86. continue;
  87. okBtn = MsgBoxMac::sgButtonTextMap[i].ok;
  88. cancelBtn = MsgBoxMac::sgButtonTextMap[i].cancel;
  89. thirdBtn = MsgBoxMac::sgButtonTextMap[i].third;
  90. break;
  91. }
  92. if(MsgBoxMac::sgButtonTextMap[i].num == -1)
  93. Con::errorf("Unknown message box button set requested. Mac Platform::messageBox() probably needs to be updated.");
  94. // convert title and message to NSStrings
  95. NSString *nsTitle = [NSString stringWithUTF8String:title];
  96. NSString *nsMessage = [NSString stringWithUTF8String:message];
  97. // TODO: ensure that the cursor is the expected shape
  98. // show the alert
  99. S32 result = -2;
  100. NSAlert *alert = [NSAlert alertWithMessageText:nsTitle
  101. defaultButton:okBtn
  102. alternateButton:thirdBtn
  103. otherButton:cancelBtn
  104. informativeTextWithFormat:nsMessage];
  105. switch(icon)
  106. {
  107. // TODO:
  108. // Currently, NSAlert only provides two alert icon options.
  109. // NSWarningAlertStyle and NSInformationalAlertStyle are identical and
  110. // display the application icon, while NSCriticalAlertStyle displays
  111. // a shrunken app icon badge on a yellow-triangle-with-a-bang icon.
  112. // If custom icons were created, they could be used here with the
  113. // message [alert setIcon:foo]
  114. case MIWarning: // MIWarning = 0
  115. case MIQuestion: // MIquestion = 3
  116. [alert setAlertStyle:NSWarningAlertStyle];
  117. break;
  118. case MIInformation: // MIInformation = 1
  119. [alert setAlertStyle:NSInformationalAlertStyle];
  120. break;
  121. case MIStop: // MIStop = 3
  122. [alert setAlertStyle:NSCriticalAlertStyle];
  123. break;
  124. default:
  125. Con::errorf("Unknown message box icon requested. Mac Platform::messageBox() probably needs to be updated.");
  126. }
  127. id appDelegate = [NSApp delegate];
  128. [NSApp setDelegate: nil];
  129. U32 cursorDepth = 0;
  130. while(!CGCursorIsVisible())
  131. {
  132. CGDisplayShowCursor(kCGDirectMainDisplay);
  133. cursorDepth++;
  134. }
  135. CGAssociateMouseAndMouseCursorPosition(true);
  136. result = [alert runModal];
  137. [NSApp setDelegate: appDelegate];
  138. S32 ret = 0;
  139. for(U32 i = 0; MsgBoxMac::sgAlertResultMap[i].num != -1; i++)
  140. {
  141. if(MsgBoxMac::sgAlertResultMap[i].num != buttons)
  142. continue;
  143. switch(result)
  144. {
  145. case NSAlertDefaultReturn:
  146. ret = MsgBoxMac::sgAlertResultMap[i].ok; break;
  147. case NSAlertOtherReturn:
  148. ret = MsgBoxMac::sgAlertResultMap[i].cancel; break;
  149. case NSAlertAlternateReturn:
  150. ret = MsgBoxMac::sgAlertResultMap[i].third; break;
  151. }
  152. }
  153. return ret;
  154. }