1/*
2 * Copyright 2019-2023, Adrien Destugues, pulkomandy@pulkomandy.tk.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "AlertWithCheckbox.h"
8
9#include <algorithm>
10#include <stdio.h>
11
12#include <Button.h>
13#include <Catalog.h>
14#include <CheckBox.h>
15#include <ControlLook.h>
16#include <GroupLayout.h>
17#include <LayoutBuilder.h>
18#include <Locale.h>
19#include <IconUtils.h>
20#include <Resources.h>
21#include <StripeView.h>
22#include <TextView.h>
23
24#undef B_TRANSLATION_CONTEXT
25#define B_TRANSLATION_CONTEXT "DebugServer"
26
27
28enum {
29	kButton1Message,
30	kButton2Message,
31	kButton3Message
32};
33
34
35AlertWithCheckbox::AlertWithCheckbox(const char* title, const char* messageText,
36	const char* checkboxLabel, const char* label1, const char* label2, const char* label3)
37	:
38	BWindow(BRect(0, 0, 100, 50), title,
39		B_MODAL_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
40		B_CLOSE_ON_ESCAPE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS),
41	fBitmap(IconSize(), B_RGBA32),
42	fSemaphore(create_sem(0, "AlertWithCheckbox")),
43	fAction(0)
44{
45	BIconUtils::GetSystemIcon("dialog-information", &fBitmap);
46	BStripeView *stripeView = new BStripeView(fBitmap);
47
48	BTextView *message = new BTextView("_tv_");
49	message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
50	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
51	message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
52	message->MakeEditable(false);
53	message->MakeSelectable(false);
54	message->SetText(messageText);
55	BRect textRect = message->TextRect();
56	textRect.PrintToStream();
57	message->SetWordWrap(true);
58	message->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNSET));
59	float width = message->StringWidth("W") * 40;
60	if (width < textRect.Width()) {
61		message->SetExplicitMinSize(BSize(width, B_SIZE_UNSET));
62	}
63
64	fDontAskAgain = new BCheckBox("checkbox", checkboxLabel, NULL);
65
66	BGroupView* buttonGroup = new BGroupView(B_HORIZONTAL);
67	BLayoutBuilder::Group<> layoutBuilder(buttonGroup);
68
69	layoutBuilder.AddGlue();
70
71	if (label1) {
72		BButton* button = new BButton(label1, label1, new BMessage(kButton1Message));
73		button->MakeDefault(true);
74		layoutBuilder.Add(button);
75	}
76
77	if (label2) {
78		BButton* button = new BButton(label2, label2, new BMessage(kButton2Message));
79		layoutBuilder.Add(button);
80	}
81
82	if (label3) {
83		BButton* button = new BButton(label3, label3, new BMessage(kButton3Message));
84		layoutBuilder.Add(button);
85	}
86
87	BLayoutBuilder::Group<>(this)
88		.AddGroup(B_HORIZONTAL)
89			.Add(stripeView)
90			.AddGroup(B_VERTICAL)
91				.SetInsets(B_USE_SMALL_SPACING)
92				.Add(message)
93				.AddGroup(B_HORIZONTAL, 0)
94					.Add(fDontAskAgain)
95					.AddGlue()
96				.End()
97				.Add(buttonGroup)
98			.End()
99		.End();
100
101	ResizeToPreferred();
102	CenterOnScreen();
103}
104
105
106AlertWithCheckbox::~AlertWithCheckbox()
107{
108	delete_sem(fSemaphore);
109}
110
111
112void
113AlertWithCheckbox::MessageReceived(BMessage* message)
114{
115	switch(message->what) {
116		case B_QUIT_REQUESTED:
117			release_sem(fSemaphore);
118			break;
119
120		case 0:
121		case 1:
122		case 2:
123			fAction = message->what;
124			PostMessage(B_QUIT_REQUESTED);
125			return;
126	}
127
128	BWindow::MessageReceived(message);
129}
130
131
132int32
133AlertWithCheckbox::Go(bool& dontAskAgain)
134{
135	Show();
136
137	// Wait for user to close the window
138	acquire_sem(fSemaphore);
139	dontAskAgain = fDontAskAgain->Value();
140	return fAction;
141}
142
143
144BRect
145AlertWithCheckbox::IconSize()
146{
147	return BRect(BPoint(0, 0), be_control_look->ComposeIconSize(32));
148}
149