root/src/servers/debug/DebugWindow.cpp
/*
 * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk.
 * Distributed under the terms of the MIT License.
 */


#include "DebugWindow.h"

#include <algorithm>
#include <stdio.h>

#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <GroupLayout.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <IconUtils.h>
#include <Resources.h>
#include <RadioButton.h>
#include <StripeView.h>
#include <TextView.h>

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "DebugServer"


DebugWindow::DebugWindow(const char* appName)
        :
        BWindow(BRect(0, 0, 100, 50), "Crashed program",
                B_MODAL_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
                B_CLOSE_ON_ESCAPE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS),
        fBitmap(IconSize(), B_RGBA32),
        fSemaphore(create_sem(0, "DebugWindow")),
        fAction(kActionKillTeam)
{
        BString buffer(B_TRANSLATE(
                "The application:\n\n      %app\n\n"
                "has encountered an error which prevents it from continuing. Haiku "
                "will terminate the application and clean up."));
        buffer.ReplaceFirst("%app", appName);

        BResources resources;
        resources.SetToImage(B_TRANSLATION_CONTEXT);
        size_t size;
        const uint8* iconData = (const uint8*)resources.LoadResource('VICN', 2,
                &size);
        BIconUtils::GetVectorIcon(iconData, size, &fBitmap);
        BStripeView *stripeView = new BStripeView(fBitmap);

        BTextView *message = new BTextView("_tv_");
        message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
        rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
        message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
        message->MakeEditable(false);
        message->MakeSelectable(false);
        message->SetWordWrap(true);
        message->SetText(buffer);
        message->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNSET));
        float width = message->StringWidth(appName)
                + message->StringWidth(" ") * 12;
        width = std::max(width, message->StringWidth("W") * 30);
        message->SetExplicitMinSize(BSize(width, B_SIZE_UNSET));

        BRadioButton *terminate = new BRadioButton("terminate",
                B_TRANSLATE("Terminate"), new BMessage(kActionKillTeam));
#ifdef HANDOVER_USE_DEBUGGER
        BRadioButton *report = new BRadioButton("report",
                B_TRANSLATE("Save report"), new BMessage(kActionSaveReportTeam));
#endif
        BRadioButton *debug = new BRadioButton("debug",
                B_TRANSLATE("Debug"), new BMessage(kActionDebugTeam));
        BRadioButton *core = new BRadioButton("core",
                B_TRANSLATE("Write core file"), new BMessage(kActionWriteCoreFile));

        fOKButton = new BButton("close", B_TRANSLATE("Oh no!"),
                new BMessage(B_QUIT_REQUESTED));
        fOKButton->MakeDefault(true);

        terminate->SetValue(B_CONTROL_ON);

        BLayoutBuilder::Group<>(this)
                .AddGroup(B_HORIZONTAL)
                        .Add(stripeView)
                        .AddGroup(B_VERTICAL)
                                .SetInsets(B_USE_SMALL_SPACING)
                                .Add(message)
                                .AddGroup(B_VERTICAL, 0)
                                        .Add(terminate)
                                        .Add(debug)
                                        .Add(report)
                                        .Add(core)
                                .End()
                                .AddGroup(B_HORIZONTAL)
                                        .AddGlue()
                                        .Add(fOKButton)
                                .End()
                        .End()
                .End();

        ResizeToPreferred();
        CenterOnScreen();
}


DebugWindow::~DebugWindow()
{
        delete_sem(fSemaphore);
}


void
DebugWindow::MessageReceived(BMessage* message)
{
        switch(message->what) {
                case B_QUIT_REQUESTED:
                        release_sem(fSemaphore);
                        break;

                case kActionKillTeam:
                case kActionDebugTeam:
                case kActionWriteCoreFile:
                case kActionSaveReportTeam:
                        fAction = message->what;
                        fOKButton->SetLabel(fAction == kActionDebugTeam
                                ? B_TRANSLATE("Oh yeah!") : B_TRANSLATE("Oh no!"));
                        return;
        }

        BWindow::MessageReceived(message);
}


int32
DebugWindow::Go()
{
        Show();

        // Wait for user to close the window
        acquire_sem(fSemaphore);
        return fAction;
}


BRect
DebugWindow::IconSize()
{
        return BRect(BPoint(0, 0), be_control_look->ComposeIconSize(32));
}