root/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.cpp
/*
 * Copyright 2019-2023, Adrien Destugues, pulkomandy@pulkomandy.tk.
 * Distributed under the terms of the MIT License.
 */


#include "AlertWithCheckbox.h"

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

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

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "DebugServer"


enum {
        kButton1Message,
        kButton2Message,
        kButton3Message
};


AlertWithCheckbox::AlertWithCheckbox(const char* title, const char* messageText,
        const char* checkboxLabel, const char* label1, const char* label2, const char* label3)
        :
        BWindow(BRect(0, 0, 100, 50), title,
                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, "AlertWithCheckbox")),
        fAction(0)
{
        BIconUtils::GetSystemIcon("dialog-information", &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->SetText(messageText);
        BRect textRect = message->TextRect();
        textRect.PrintToStream();
        message->SetWordWrap(true);
        message->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNSET));
        float width = message->StringWidth("W") * 40;
        if (width < textRect.Width()) {
                message->SetExplicitMinSize(BSize(width, B_SIZE_UNSET));
        }

        fDontAskAgain = new BCheckBox("checkbox", checkboxLabel, NULL);

        BGroupView* buttonGroup = new BGroupView(B_HORIZONTAL);
        BLayoutBuilder::Group<> layoutBuilder(buttonGroup);

        layoutBuilder.AddGlue();

        if (label1) {
                BButton* button = new BButton(label1, label1, new BMessage(kButton1Message));
                button->MakeDefault(true);
                layoutBuilder.Add(button);
        }

        if (label2) {
                BButton* button = new BButton(label2, label2, new BMessage(kButton2Message));
                layoutBuilder.Add(button);
        }

        if (label3) {
                BButton* button = new BButton(label3, label3, new BMessage(kButton3Message));
                layoutBuilder.Add(button);
        }

        BLayoutBuilder::Group<>(this)
                .AddGroup(B_HORIZONTAL)
                        .Add(stripeView)
                        .AddGroup(B_VERTICAL)
                                .SetInsets(B_USE_SMALL_SPACING)
                                .Add(message)
                                .AddGroup(B_HORIZONTAL, 0)
                                        .Add(fDontAskAgain)
                                        .AddGlue()
                                .End()
                                .Add(buttonGroup)
                        .End()
                .End();

        ResizeToPreferred();
        CenterOnScreen();
}


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


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

                case 0:
                case 1:
                case 2:
                        fAction = message->what;
                        PostMessage(B_QUIT_REQUESTED);
                        return;
        }

        BWindow::MessageReceived(message);
}


int32
AlertWithCheckbox::Go(bool& dontAskAgain)
{
        Show();

        // Wait for user to close the window
        acquire_sem(fSemaphore);
        dontAskAgain = fDontAskAgain->Value();
        return fAction;
}


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