1/*
2 * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "DebugWindow.h"
8
9#include <algorithm>
10#include <stdio.h>
11
12#include <Button.h>
13#include <Catalog.h>
14#include <ControlLook.h>
15#include <GroupLayout.h>
16#include <LayoutBuilder.h>
17#include <Locale.h>
18#include <IconUtils.h>
19#include <Resources.h>
20#include <RadioButton.h>
21#include <StripeView.h>
22#include <TextView.h>
23
24#undef B_TRANSLATION_CONTEXT
25#define B_TRANSLATION_CONTEXT "DebugServer"
26
27
28DebugWindow::DebugWindow(const char* appName)
29	:
30	BWindow(BRect(0, 0, 100, 50), "Crashed program",
31		B_MODAL_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
32		B_CLOSE_ON_ESCAPE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS),
33	fBitmap(IconSize(), B_RGBA32),
34	fSemaphore(create_sem(0, "DebugWindow")),
35	fAction(kActionKillTeam)
36{
37	BString buffer(B_TRANSLATE(
38		"The application:\n\n      %app\n\n"
39		"has encountered an error which prevents it from continuing. Haiku "
40		"will terminate the application and clean up."));
41	buffer.ReplaceFirst("%app", appName);
42
43	BResources resources;
44	resources.SetToImage(B_TRANSLATION_CONTEXT);
45	size_t size;
46	const uint8* iconData = (const uint8*)resources.LoadResource('VICN', 2,
47		&size);
48	BIconUtils::GetVectorIcon(iconData, size, &fBitmap);
49	BStripeView *stripeView = new BStripeView(fBitmap);
50
51	BTextView *message = new BTextView("_tv_");
52	message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
53	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
54	message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
55	message->MakeEditable(false);
56	message->MakeSelectable(false);
57	message->SetWordWrap(true);
58	message->SetText(buffer);
59	message->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNSET));
60	float width = message->StringWidth(appName)
61		+ message->StringWidth(" ") * 12;
62	width = std::max(width, message->StringWidth("W") * 30);
63	message->SetExplicitMinSize(BSize(width, B_SIZE_UNSET));
64
65	BRadioButton *terminate = new BRadioButton("terminate",
66		B_TRANSLATE("Terminate"), new BMessage(kActionKillTeam));
67#ifdef HANDOVER_USE_DEBUGGER
68	BRadioButton *report = new BRadioButton("report",
69		B_TRANSLATE("Save report"), new BMessage(kActionSaveReportTeam));
70#endif
71	BRadioButton *debug = new BRadioButton("debug",
72		B_TRANSLATE("Debug"), new BMessage(kActionDebugTeam));
73	BRadioButton *core = new BRadioButton("core",
74		B_TRANSLATE("Write core file"), new BMessage(kActionWriteCoreFile));
75
76	fOKButton = new BButton("close", B_TRANSLATE("Oh no!"),
77		new BMessage(B_QUIT_REQUESTED));
78	fOKButton->MakeDefault(true);
79
80	terminate->SetValue(B_CONTROL_ON);
81
82	BLayoutBuilder::Group<>(this)
83		.AddGroup(B_HORIZONTAL)
84			.Add(stripeView)
85			.AddGroup(B_VERTICAL)
86				.SetInsets(B_USE_SMALL_SPACING)
87				.Add(message)
88				.AddGroup(B_VERTICAL, 0)
89					.Add(terminate)
90					.Add(debug)
91					.Add(report)
92					.Add(core)
93				.End()
94				.AddGroup(B_HORIZONTAL)
95					.AddGlue()
96					.Add(fOKButton)
97				.End()
98			.End()
99		.End();
100
101	ResizeToPreferred();
102	CenterOnScreen();
103}
104
105
106DebugWindow::~DebugWindow()
107{
108	delete_sem(fSemaphore);
109}
110
111
112void
113DebugWindow::MessageReceived(BMessage* message)
114{
115	switch(message->what) {
116		case B_QUIT_REQUESTED:
117			release_sem(fSemaphore);
118			break;
119
120		case kActionKillTeam:
121		case kActionDebugTeam:
122		case kActionWriteCoreFile:
123		case kActionSaveReportTeam:
124			fAction = message->what;
125			fOKButton->SetLabel(fAction == kActionDebugTeam
126				? B_TRANSLATE("Oh yeah!") : B_TRANSLATE("Oh no!"));
127			return;
128	}
129
130	BWindow::MessageReceived(message);
131}
132
133
134int32
135DebugWindow::Go()
136{
137	Show();
138
139	// Wait for user to close the window
140	acquire_sem(fSemaphore);
141	return fAction;
142}
143
144
145BRect
146DebugWindow::IconSize()
147{
148	return BRect(BPoint(0, 0), be_control_look->ComposeIconSize(32));
149}
150