summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc')
-rw-r--r--contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc383
1 files changed, 383 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc b/contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc
new file mode 100644
index 0000000..75bef70
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/video/haiku/SDL_bmessagebox.cc
@@ -0,0 +1,383 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4 Copyright (C) 2018-2019 EXL <exlmotodev@gmail.com>
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