diff --git a/src/apps/debugger/Debugger.rdef b/src/apps/debugger/Debugger.rdef index f5872ad101..3c47c3a5e5 100644 --- a/src/apps/debugger/Debugger.rdef +++ b/src/apps/debugger/Debugger.rdef @@ -22,7 +22,7 @@ resource app_version { resource app_flags B_SINGLE_LAUNCH; -resource vector_icon { +resource(1) vector_icon { $"6E6369660B03000100010001005A02000604BC00000000000000003C00004940" $"004B000000FF9E063FF7F378D7FFEA97FFFFB94B02000604BC00000000000000" $"003C00004940004B00000038BC382B279127D253ED53FF2EAA2E020006023A9D" diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index f65f876644..c97e3fa322 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -137,6 +137,7 @@ local sources = # user_interface/gui/util ActionMenuItem.cpp + AlertWithCheckbox.cpp GuiSettingsUtils.cpp SettingsMenu.cpp SignalDispositionMenu.cpp diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp index 9d7bc96a2f..2d61cfe74d 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp @@ -13,6 +13,7 @@ #include #include +#include "AlertWithCheckbox.h" #include "GuiTeamUiSettings.h" #include "MessageCodes.h" #include "TeamWindow.h" @@ -129,7 +130,8 @@ GraphicalUserInterface::GraphicalUserInterface() fTeamWindow(NULL), fTeamWindowMessenger(NULL), fFilePanelHandler(NULL), - fFilePanel(NULL) + fFilePanel(NULL), + fDefaultActions(10, true) { } @@ -271,11 +273,35 @@ GraphicalUserInterface::SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3) { - BAlert* alert = new(std::nothrow) BAlert(title, message, - choice1, choice2, choice3); + // If the user already answered the question and asked for their choice to be remembered, + // return the previously made choice again + BString key(title); + key += choice1; + key += choice2; + key += choice3; + + for (int i = 0; i < fDefaultActions.CountItems(); i++) { + if (fDefaultActions.ItemAt(i)->fKey == key) + return fDefaultActions.ItemAt(i)->fDecision; + } + + AlertWithCheckbox* alert = new(std::nothrow) AlertWithCheckbox(title, message, + "Don't ask again", choice1, choice2, choice3); + if (alert == NULL) return 0; - return alert->Go(); + + bool dontAskAgain = false; + int result = alert->Go(dontAskAgain); + + if (dontAskAgain) { + DefaultAction* defaultAction = new DefaultAction; + defaultAction->fKey = key; + defaultAction->fDecision = result; + fDefaultActions.AddItem(defaultAction); + } + + return result; } diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h index d031fb373d..e2671c73e0 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h @@ -9,6 +9,9 @@ #include "UserInterface.h" +#include "ObjectList.h" +#include "String.h" + class BFilePanel; class BHandler; @@ -54,6 +57,12 @@ private: BMessenger* fTeamWindowMessenger; FilePanelHandler* fFilePanelHandler; BFilePanel* fFilePanel; + + struct DefaultAction { + BString fKey; + int fDecision; + }; + BObjectList fDefaultActions; }; diff --git a/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.cpp b/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.cpp new file mode 100644 index 0000000000..64d0b37965 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2019-2023, Adrien Destugues, pulkomandy@pulkomandy.tk. + * Distributed under the terms of the MIT License. + */ + + +#include "AlertWithCheckbox.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) +{ + BResources resources; + resources.SetToImage(B_TRANSLATION_CONTEXT); + size_t size; + const uint8* iconData = (const uint8*)resources.LoadResource('VICN', 1, + &size); + + // TODO load "info" icon from app_server instead? + 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(messageText); + message->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNSET)); + float width = message->StringWidth("W") * 40; + message->SetExplicitMinSize(BSize(width, B_SIZE_UNSET)); + + fDontAskAgain = new BCheckBox("checkbox", + checkboxLabel, NULL); + + BButton* button1 = new BButton(label1, label1, new BMessage(kButton1Message)); + BButton* button2 = new BButton(label2, label2, new BMessage(kButton2Message)); + BButton* button3 = new BButton(label3, label3, new BMessage(kButton3Message)); + button1->MakeDefault(true); + + 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() + .AddGroup(B_HORIZONTAL) + .AddGlue() + .Add(button1) + .Add(button2) + .Add(button3) + .End() + .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)); +} diff --git a/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.h b/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.h new file mode 100644 index 0000000000..1872d31224 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/util/AlertWithCheckbox.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019-2023, Adrien Destugues, pulkomandy@pulkomandy.tk. + * Distributed under the terms of the MIT License. + */ +#ifndef ALERTWITHCHECKBOX_H +#define ALERTWITHCHECKBOX_H + + +#include +#include + + +class BCheckBox; + + +class AlertWithCheckbox : public BWindow { +public: + AlertWithCheckbox(const char* title, const char* message, const char* checkBox, + const char* button1, const char* button2, const char* button3); + ~AlertWithCheckbox(); + + void MessageReceived(BMessage* message); + int32 Go(bool& dontAskAgain); + +private: + static BRect IconSize(); + +private: + BBitmap fBitmap; + BCheckBox* fDontAskAgain; + sem_id fSemaphore; + int32 fAction; +}; + + +#endif /* !ALERTWITHCHECKBOX_H */