2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 Copyright (C) 2018-2019 EXL <exlmotodev@gmail.com>
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.
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:
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.
23 #include "../../SDL_internal.h"
25 #if SDL_VIDEO_DRIVER_HAIKU
27 #include "SDL_messagebox.h"
29 /* For application signature. */
30 #include "../../main/haiku/SDL_BeApp.h"
33 #include <Application.h>
42 #include <InterfaceDefs.h>
43 #include <SupportDefs.h>
44 #include <GraphicsDefs.h>
52 G_CLOSE_BUTTON_ID = -1,
53 G_DEFAULT_BUTTON_ID = 0,
54 G_MAX_STRING_LENGTH_BYTES = 120
57 class HAIKU_SDL_MessageBox : public BAlert
59 float fComputedMessageBoxWidth;
61 BTextView *fMessageBoxTextView;
66 bool fCustomColorScheme;
67 bool fThereIsLongLine;
71 const char *HAIKU_SDL_DefTitle;
72 const char *HAIKU_SDL_DefMessage;
73 const char *HAIKU_SDL_DefButton;
75 std::vector<const SDL_MessageBoxButtonData *> fButtons;
78 SortButtonsPredicate(const SDL_MessageBoxButtonData *aButtonLeft,
79 const SDL_MessageBoxButtonData *aButtonRight)
81 return aButtonLeft->buttonid < aButtonRight->buttonid;
85 ConvertMessageBoxType(const SDL_MessageBoxFlags aWindowType) const
90 case SDL_MESSAGEBOX_WARNING:
92 return B_WARNING_ALERT;
94 case SDL_MESSAGEBOX_ERROR:
98 case SDL_MESSAGEBOX_INFORMATION:
106 ConvertColorType(const SDL_MessageBoxColor *aColor) const
108 rgb_color color = { aColor->r, aColor->g, aColor->b, color.alpha = 255 };
113 GetLeftPanelWidth(void) const
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)
121 int32 scale = max_c(1, ((int32)be_plain_font->Size() + 15) / 16);
122 return (30 * scale) + (32 * scale);
126 UpdateTextViewWidth(void)
128 fComputedMessageBoxWidth = fMessageBoxTextView->PreferredSize().Width() + GetLeftPanelWidth();
132 ParseSdlMessageBoxData(const SDL_MessageBoxData *aMessageBoxData)
134 if (aMessageBoxData == NULL)
136 SetTitle(HAIKU_SDL_DefTitle);
137 SetMessageText(HAIKU_SDL_DefMessage);
138 AddButton(HAIKU_SDL_DefButton);
142 if (aMessageBoxData->numbuttons <= 0)
144 AddButton(HAIKU_SDL_DefButton);
148 AddSdlButtons(aMessageBoxData->buttons, aMessageBoxData->numbuttons);
151 if (aMessageBoxData->colorScheme != NULL)
153 fCustomColorScheme = true;
154 ApplyAndParseColorScheme(aMessageBoxData->colorScheme);
157 (aMessageBoxData->title[0]) ?
158 SetTitle(aMessageBoxData->title) : SetTitle(HAIKU_SDL_DefTitle);
159 (aMessageBoxData->message[0]) ?
160 SetMessageText(aMessageBoxData->message) : SetMessageText(HAIKU_SDL_DefMessage);
162 SetType(ConvertMessageBoxType(static_cast<SDL_MessageBoxFlags>(aMessageBoxData->flags)));
166 ApplyAndParseColorScheme(const SDL_MessageBoxColorScheme *aColorScheme)
168 SetBackgroundColor(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BACKGROUND]);
169 fTextColor = ConvertColorType(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_TEXT]);
170 SetButtonColors(&aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER],
171 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND],
172 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_TEXT],
173 &aColorScheme->colors[SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED]);
177 SetButtonColors(const SDL_MessageBoxColor *aBorderColor,
178 const SDL_MessageBoxColor *aBackgroundColor,
179 const SDL_MessageBoxColor *aTextColor,
180 const SDL_MessageBoxColor *aSelectedColor)
182 if (fCustomColorScheme)
184 int32 countButtons = CountButtons();
185 for (int i = 0; i < countButtons; ++i)
187 ButtonAt(i)->SetViewColor(ConvertColorType(aBorderColor));
188 ButtonAt(i)->SetLowColor(ConvertColorType(aBackgroundColor));
190 // This doesn't work. See this why:
191 // https://github.com/haiku/haiku/commit/de9c53f8f5008c7b3b0af75d944a628e17f6dffe
193 ButtonAt(i)->SetHighColor(ConvertColorType(aTextColor));
196 // TODO: Not Implemented.
197 // Is it even necessary?!
198 (void)aSelectedColor;
202 SetBackgroundColor(const SDL_MessageBoxColor *aColor)
204 rgb_color background = ConvertColorType(aColor);
206 GetLayout()->View()->SetViewColor(background);
207 // See file "haiku/src/kits/interface/Alert.cpp", the "TAlertView" is the internal name of the left panel.
208 FindView("TAlertView")->SetViewColor(background);
209 fMessageBoxTextView->SetViewColor(background);
213 CheckLongLines(const char *aMessage)
217 // This UTF-8 friendly.
218 BString message = aMessage;
219 int32 length = message.CountChars();
221 for (int i = 0, c = 0; i < length; ++i)
224 if (*(message.CharAt(i)) == '\n')
234 return (final > G_MAX_STRING_LENGTH_BYTES);
238 SetMessageText(const char *aMessage)
240 fThereIsLongLine = CheckLongLines(aMessage);
241 if (fThereIsLongLine)
243 fMessageBoxTextView->SetWordWrap(true);
246 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
247 if (fCustomColorScheme)
249 textColor = fTextColor;
255 fMessageBoxTextView->SetFontAndColor(be_bold_font);
256 fMessageBoxTextView->Insert(fTitle);
257 fMessageBoxTextView->Insert("\n\n");
258 fMessageBoxTextView->SetFontAndColor(be_plain_font);
262 fMessageBoxTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
263 fMessageBoxTextView->Insert(aMessage);
265 // Be sure to call update width method.
266 UpdateTextViewWidth();
270 AddSdlButtons(const SDL_MessageBoxButtonData *aButtons, int aNumButtons)
272 for (int i = 0; i < aNumButtons; ++i)
274 fButtons.push_back(&aButtons[i]);
277 std::sort(fButtons.begin(), fButtons.end(), &HAIKU_SDL_MessageBox::SortButtonsPredicate);
279 size_t countButtons = fButtons.size();
280 for (size_t i = 0; i < countButtons; ++i)
282 switch (fButtons[i]->flags)
284 case SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT:
286 fCloseButton = static_cast<int>(i);
289 case SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT:
291 fDefaultButton = static_cast<int>(i);
299 AddButton(fButtons[i]->text);
302 SetDefaultButton(ButtonAt(fDefaultButton));
307 HAIKU_SDL_MessageBox(const SDL_MessageBoxData *aMessageBoxData)
308 : BAlert(NULL, NULL, NULL, NULL, NULL, B_WIDTH_FROM_LABEL, B_WARNING_ALERT),
309 fComputedMessageBoxWidth(0.0f),
310 fCloseButton(G_CLOSE_BUTTON_ID), fDefaultButton(G_DEFAULT_BUTTON_ID),
311 fCustomColorScheme(false), fThereIsLongLine(false),
312 HAIKU_SDL_DefTitle("SDL2 MessageBox"),
313 HAIKU_SDL_DefMessage("Some information has been lost."),
314 HAIKU_SDL_DefButton("OK")
316 // MessageBox settings.
317 // We need a title to display it.
318 SetLook(B_TITLED_WINDOW_LOOK);
319 SetFlags(Flags() | B_CLOSE_ON_ESCAPE);
321 // MessageBox TextView settings.
322 fMessageBoxTextView = TextView();
323 fMessageBoxTextView->SetWordWrap(false);
324 fMessageBoxTextView->SetStylable(true);
326 ParseSdlMessageBoxData(aMessageBoxData);
330 GetCloseButtonId(void) const
336 ~HAIKU_SDL_MessageBox(void)
343 FrameResized(float aNewWidth, float aNewHeight)
345 if (fComputedMessageBoxWidth > aNewWidth)
347 ResizeTo(fComputedMessageBoxWidth, aNewHeight);
351 BAlert::FrameResized(aNewWidth, aNewHeight);
356 SetTitle(const char* aTitle)
359 BAlert::SetTitle(aTitle);
368 HAIKU_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
370 // Initialize button by closed or error value first.
371 *buttonid = G_CLOSE_BUTTON_ID;
373 // We need to check "be_app" pointer to "NULL". The "messageboxdata->window" pointer isn't appropriate here
374 // because it is possible to create a MessageBox from another thread. This fixes the following errors:
375 // "You need a valid BApplication object before interacting with the app_server."
376 // "2 BApplication objects were created. Only one is allowed."
377 BApplication *application = NULL;
380 application = new(std::nothrow) BApplication(signature);
381 if (application == NULL)
383 return SDL_SetError("Cannot create the BApplication object. Lack of memory?");
387 HAIKU_SDL_MessageBox *SDL_MessageBox = new(std::nothrow) HAIKU_SDL_MessageBox(messageboxdata);
388 if (SDL_MessageBox == NULL)
390 return SDL_SetError("Cannot create the HAIKU_SDL_MessageBox (BAlert inheritor) object. Lack of memory?");
392 const int closeButton = SDL_MessageBox->GetCloseButtonId();
393 int pushedButton = SDL_MessageBox->Go();
395 // The close button is equivalent to pressing Escape.
396 if (closeButton != G_CLOSE_BUTTON_ID && pushedButton == G_CLOSE_BUTTON_ID)
398 pushedButton = closeButton;
401 // It's deleted by itself after the "Go()" method was executed.
403 if (messageBox != NULL)
408 if (application != NULL)
413 // Initialize button by real pushed value then.
414 *buttonid = pushedButton;
423 #endif /* SDL_VIDEO_DRIVER_HAIKU */
425 /* vi: set ts=4 sw=4 expandtab: */