Atlas - SDL_bmessagebox.cc
Home / ext / SDL / src / video / haiku Lines: 4 | Size: 10477 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 Copyright (C) 2018-2019 EXL <[email protected]> 5 6 This software is provided 'as-is', without any express or implied 7 warranty. In no event will the authors be held liable for any damages 8 arising from the use of this software. 9 10 Permission is granted to anyone to use this software for any purpose, 11 including commercial applications, and to alter it and redistribute it 12 freely, subject to the following restrictions: 13 14 1. The origin of this software must not be misrepresented; you must not 15 claim that you wrote the original software. If you use this software 16 in a product, an acknowledgment in the product documentation would be 17 appreciated but is not required. 18 2. Altered source versions must be plainly marked as such, and must not be 19 misrepresented as being the original software. 20 3. This notice may not be removed or altered from any source distribution. 21*/ 22 23#include "SDL_internal.h" 24 25#ifdef SDL_VIDEO_DRIVER_HAIKU 26 27 28// For application signature. 29#include "../../core/haiku/SDL_BeApp.h" 30 31#include <Alert.h> 32#include <Application.h> 33#include <Button.h> 34#include <Font.h> 35#include <Layout.h> 36#include <String.h> 37#include <TextView.h> 38#include <View.h> 39#include <Window.h> 40 41#include <InterfaceDefs.h> 42#include <SupportDefs.h> 43#include <GraphicsDefs.h> 44 45#include <new> 46#include <vector> 47#include <algorithm> 48#include <memory> 49 50enum 51{ 52 G_CLOSE_BUTTON_ID = -1, 53 G_DEFAULT_BUTTON_ID = 0, 54 G_MAX_STRING_LENGTH_BYTES = 120 55}; 56 57class HAIKU_SDL_MessageBox : public BAlert 58{ 59 float fComputedMessageBoxWidth; 60 61 BTextView *fMessageBoxTextView; 62 63 int fCloseButton; 64 int fDefaultButton; 65 66 bool fCustomColorScheme; 67 bool fThereIsLongLine; 68 rgb_color fTextColor; 69 70 const char *fTitle; 71 const char *HAIKU_SDL_DefTitle; 72 const char *HAIKU_SDL_DefMessage; 73 const char *HAIKU_SDL_DefButton; 74 75 std::vector<const SDL_MessageBoxButtonData *> fButtons; 76 77 static bool 78 SortButtonsPredicate(const SDL_MessageBoxButtonData *aButtonLeft, 79 const SDL_MessageBoxButtonData *aButtonRight) 80 { 81 return aButtonLeft->buttonID < aButtonRight->buttonID; 82 } 83 84 alert_type 85 ConvertMessageBoxType(const SDL_MessageBoxFlags aWindowType) const 86 { 87 switch (aWindowType) 88 { 89 default: 90 case SDL_MESSAGEBOX_WARNING: 91 { 92 return B_WARNING_ALERT; 93 } 94 case SDL_MESSAGEBOX_ERROR: 95 { 96 return B_STOP_ALERT; 97 } 98 case SDL_MESSAGEBOX_INFORMATION: 99 { 100 return B_INFO_ALERT; 101 } 102 } 103 } 104 105 rgb_color 106 ConvertColorType(const SDL_MessageBoxColor *aColor) const 107 { 108 rgb_color color = { aColor->r, aColor->g, aColor->b, color.alpha = 255 }; 109 return color; 110 } 111 112 int32 113 GetLeftPanelWidth(void) const 114 { 115 // See file "haiku/src/kits/interface/Alert.cpp" for this magic numbers. 116 // IconStripeWidth = 30 * Scale 117 // IconSize = 32 * Scale 118 // Scale = max_c(1, ((int32)be_plain_font->Size() + 15) / 16) 119 // RealWidth = (IconStripeWidth * Scale) + (IconSize * Scale) 120 121 int32 scale = max_c(1, ((int32)be_plain_font->Size() + 15) / 16); 122 return (30 * scale) + (32 * scale); 123 } 124 125 void 126 UpdateTextViewWidth(void) 127 { 128 fComputedMessageBoxWidth = fMessageBoxTextView->PreferredSize().Width() + GetLeftPanelWidth(); 129 } 130 131 void 132 ParseSdlMessageBoxData(const SDL_MessageBoxData *aMessageBoxData) 133 { 134 if (aMessageBoxData == NULL) { 135 SetTitle(HAIKU_SDL_DefTitle); 136 SetMessageText(HAIKU_SDL_DefMessage); 137 AddButton(HAIKU_SDL_DefButton); 138 return; 139 } 140 141 if (aMessageBoxData->numbuttons <= 0) { 142 AddButton(HAIKU_SDL_DefButton); 143 } else { 144 AddSdlButtons(aMessageBoxData->buttons, aMessageBoxData->numbuttons); 145 } 146 147 if (aMessageBoxData->colorScheme != NULL) { 148 fCustomColorScheme = true; 149 ApplyAndParseColorScheme(aMessageBoxData->colorScheme); 150 } 151 152 (aMessageBoxData->title[0]) ? 153 SetTitle(aMessageBoxData->title) : SetTitle(HAIKU_SDL_DefTitle); 154 (aMessageBoxData->message[0]) ? 155 SetMessageText(aMessageBoxData->message) : SetMessageText(HAIKU_SDL_DefMessage); 156 157 SetType(ConvertMessageBoxType(aMessageBoxData->flags)); 158 } 159 160 void 161 ApplyAndParseColorScheme(const SDL_MessageBoxColorScheme *aColorScheme) 162 { 163 SetBackgroundColor(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BACKGROUND]); 164 fTextColor = ConvertColorType(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_TEXT]); 165 SetButtonColors(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER], 166 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND], 167 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_TEXT], 168 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED]); 169 } 170 171 void 172 SetButtonColors(const SDL_MessageBoxColor *aBorderColor, 173 const SDL_MessageBoxColor *aBackgroundColor, 174 const SDL_MessageBoxColor *aTextColor, 175 const SDL_MessageBoxColor *aSelectedColor) 176 { 177 if (fCustomColorScheme) { 178 int32 countButtons = CountButtons(); 179 for (int i = 0; i < countButtons; ++i) { 180 ButtonAt(i)->SetViewColor(ConvertColorType(aBorderColor)); 181 ButtonAt(i)->SetLowColor(ConvertColorType(aBackgroundColor)); 182 183 // This doesn't work. See this why: 184 // https://github.com/haiku/haiku/commit/de9c53f8f5008c7b3b0af75d944a628e17f6dffe 185 // Let it remain. 186 ButtonAt(i)->SetHighColor(ConvertColorType(aTextColor)); 187 } 188 } 189 // TODO: Not Implemented. 190 // Is it even necessary?! 191 (void)aSelectedColor; 192 } 193 194 void 195 SetBackgroundColor(const SDL_MessageBoxColor *aColor) 196 { 197 rgb_color background = ConvertColorType(aColor); 198 199 GetLayout()->View()->SetViewColor(background); 200 // See file "haiku/src/kits/interface/Alert.cpp", the "TAlertView" is the internal name of the left panel. 201 FindView("TAlertView")->SetViewColor(background); 202 fMessageBoxTextView->SetViewColor(background); 203 } 204 205 bool 206 CheckLongLines(const char *aMessage) 207 { 208 int final = 0; 209 210 // This UTF-8 friendly. 211 BString message = aMessage; 212 int32 length = message.CountChars(); 213 214 for (int i = 0, c = 0; i < length; ++i) { 215 c++; 216 if (*(message.CharAt(i)) == '\n') { 217 c = 0; 218 } 219 if (c > final) { 220 final = c; 221 } 222 } 223 224 return (final > G_MAX_STRING_LENGTH_BYTES); 225 } 226 227 void 228 SetMessageText(const char *aMessage) 229 { 230 fThereIsLongLine = CheckLongLines(aMessage); 231 if (fThereIsLongLine) { 232 fMessageBoxTextView->SetWordWrap(true); 233 } 234 235 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); 236 if (fCustomColorScheme) { 237 textColor = fTextColor; 238 } 239 240 /* 241 if (fNoTitledWindow) { 242 fMessageBoxTextView->SetFontAndColor(be_bold_font); 243 fMessageBoxTextView->Insert(fTitle); 244 fMessageBoxTextView->Insert("\n\n"); 245 fMessageBoxTextView->SetFontAndColor(be_plain_font); 246 } 247 */ 248 249 fMessageBoxTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor); 250 fMessageBoxTextView->Insert(aMessage); 251 252 // Be sure to call update width method. 253 UpdateTextViewWidth(); 254 } 255 256 void 257 AddSdlButtons(const SDL_MessageBoxButtonData *aButtons, int aNumButtons) 258 { 259 for (int i = 0; i < aNumButtons; ++i) { 260 fButtons.push_back(&aButtons[i]); 261 } 262 263 std::sort(fButtons.begin(), fButtons.end(), &HAIKU_SDL_MessageBox::SortButtonsPredicate); 264 265 size_t countButtons = fButtons.size(); 266 for (size_t i = 0; i < countButtons; ++i) { 267 if (fButtons[i]->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) { 268 fCloseButton = static_cast<int>(i); 269 } 270 if (fButtons[i]->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { 271 fDefaultButton = static_cast<int>(i); 272 } 273 AddButton(fButtons[i]->text); 274 } 275 276 SetDefaultButton(ButtonAt(fDefaultButton)); 277 } 278 279public: 280 explicit 281 HAIKU_SDL_MessageBox(const SDL_MessageBoxData *aMessageBoxData) 282 : BAlert(NULL, NULL, NULL, NULL, NULL, B_WIDTH_FROM_LABEL, B_WARNING_ALERT), 283 fComputedMessageBoxWidth(0.0f), 284 fCloseButton(G_CLOSE_BUTTON_ID), fDefaultButton(G_DEFAULT_BUTTON_ID), 285 fCustomColorScheme(false), fThereIsLongLine(false), 286 HAIKU_SDL_DefTitle("SDL MessageBox"), 287 HAIKU_SDL_DefMessage("Some information has been lost."), 288 HAIKU_SDL_DefButton("OK") 289 { 290 // MessageBox settings. 291 // We need a title to display it. 292 SetLook(B_TITLED_WINDOW_LOOK); 293 SetFlags(Flags() | B_CLOSE_ON_ESCAPE); 294 295 // MessageBox TextView settings. 296 fMessageBoxTextView = TextView(); 297 fMessageBoxTextView->SetWordWrap(false); 298 fMessageBoxTextView->SetStylable(true); 299 300 ParseSdlMessageBoxData(aMessageBoxData); 301 } 302 303 int 304 GetCloseButtonId(void) const 305 { 306 return fCloseButton; 307 } 308 309 virtual 310 ~HAIKU_SDL_MessageBox(void) 311 { 312 fButtons.clear(); 313 } 314 315protected: 316 virtual void 317 FrameResized(float aNewWidth, float aNewHeight) 318 { 319 if (fComputedMessageBoxWidth > aNewWidth) { 320 ResizeTo(fComputedMessageBoxWidth, aNewHeight); 321 } else { 322 BAlert::FrameResized(aNewWidth, aNewHeight); 323 } 324 } 325 326 virtual void 327 SetTitle(const char *aTitle) 328 { 329 fTitle = aTitle; 330 BAlert::SetTitle(aTitle); 331 } 332}; 333 334#ifdef __cplusplus 335extern "C" { 336#endif 337 338bool HAIKU_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) 339{ 340 // Initialize button by closed or error value first. 341 *buttonID = G_CLOSE_BUTTON_ID; 342 343 // We need to check "be_app" pointer to "NULL". The "messageboxdata->window" pointer isn't appropriate here 344 // because it is possible to create a MessageBox from another thread. This fixes the following errors: 345 // "You need a valid BApplication object before interacting with the app_server." 346 // "2 BApplication objects were created. Only one is allowed." 347 std::unique_ptr<BApplication> application; 348 if (!be_app) { 349 application = std::unique_ptr<BApplication>(new(std::nothrow) BApplication(SDL_signature)); 350 if (!application) { 351 return SDL_SetError("Cannot create the BApplication object. Lack of memory?"); 352 } 353 } 354 355 HAIKU_SDL_MessageBox *SDL_MessageBox = new(std::nothrow) HAIKU_SDL_MessageBox(messageboxdata); 356 if (!SDL_MessageBox) { 357 return SDL_SetError("Cannot create the HAIKU_SDL_MessageBox (BAlert inheritor) object. Lack of memory?"); 358 } 359 const int closeButton = SDL_MessageBox->GetCloseButtonId(); 360 int pushedButton = SDL_MessageBox->Go(); 361 362 // The close button is equivalent to pressing Escape. 363 if (closeButton != G_CLOSE_BUTTON_ID && pushedButton == G_CLOSE_BUTTON_ID) { 364 pushedButton = closeButton; 365 } 366 367 // It's deleted by itself after the "Go()" method was executed. 368 /* 369 if (messageBox != NULL) { 370 delete messageBox; 371 } 372 */ 373 // Initialize button by real pushed value then. 374 *buttonID = pushedButton; 375 376 return true; 377} 378 379#ifdef __cplusplus 380} 381#endif 382 383#endif // SDL_VIDEO_DRIVER_HAIKU 384[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.