Debugger: Layout changes to team settings window.

TeamSettingsWindow:
- Split out functionality into separate views for images and exceptions,
  which in turn are held in dedicated tabs.
This commit is contained in:
Rene Gollent
2015-07-02 22:38:08 -04:00
parent c3c2ab3169
commit 10b962261a
7 changed files with 652 additions and 445 deletions
+2
View File
@@ -290,6 +290,8 @@ Application Debugger :
VariablesView.cpp
# user_interface/gui/team_settings_window
ExceptionStopConfigView.cpp
ImageStopConfigView.cpp
TeamSettingsWindow.cpp
# user_interface/gui/util
@@ -0,0 +1,176 @@
/*
* Copyright 2013-2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ExceptionStopConfigView.h"
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "FunctionInstance.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "MessageCodes.h"
#include "UserInterface.h"
#include "Team.h"
enum {
MSG_STOP_ON_THROWN_EXCEPTION_CHANGED = 'stec',
MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED = 'scec',
};
ExceptionStopConfigView::ExceptionStopConfigView(::Team* team,
UserInterfaceListener* listener)
:
BGroupView(B_VERTICAL),
fTeam(team),
fListener(listener),
fExceptionThrown(NULL),
fExceptionCaught(NULL)
{
SetName("Exceptions");
}
ExceptionStopConfigView::~ExceptionStopConfigView()
{
}
ExceptionStopConfigView*
ExceptionStopConfigView::Create(::Team* team, UserInterfaceListener* listener)
{
ExceptionStopConfigView* self = new ExceptionStopConfigView(
team, listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
ExceptionStopConfigView::AttachedToWindow()
{
fExceptionThrown->SetTarget(this);
fExceptionCaught->SetTarget(this);
AutoLocker< ::Team> teamLocker(fTeam);
_UpdateExceptionState();
BGroupView::AttachedToWindow();
}
void
ExceptionStopConfigView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_STOP_ON_THROWN_EXCEPTION_CHANGED:
{
_UpdateThrownBreakpoints(fExceptionThrown->Value()
== B_CONTROL_ON);
break;
}
case MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED:
{
break;
}
default:
BGroupView::MessageReceived(message);
break;
}
}
void
ExceptionStopConfigView::_Init()
{
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGlue()
.Add(fExceptionThrown = new BCheckBox("exceptionThrown",
"Stop when an exception is thrown",
new BMessage(MSG_STOP_ON_THROWN_EXCEPTION_CHANGED)))
.Add(fExceptionCaught = new BCheckBox("exceptionCaught",
"Stop when an exception is caught",
new BMessage(MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED)))
.AddGlue();
// TODO: enable once implemented
fExceptionCaught->SetEnabled(false);
}
void
ExceptionStopConfigView::_UpdateThrownBreakpoints(bool enable)
{
AutoLocker< ::Team> teamLocker(fTeam);
for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
it.HasNext();) {
Image* image = it.Next();
ImageDebugInfo* info = image->GetImageDebugInfo();
target_addr_t address;
if (_FindExceptionFunction(info, address) != B_OK)
continue;
if (enable)
fListener->SetBreakpointRequested(address, true, true);
else
fListener->ClearBreakpointRequested(address);
}
}
status_t
ExceptionStopConfigView::_FindExceptionFunction(ImageDebugInfo* info,
target_addr_t& _foundAddress) const
{
if (info != NULL) {
FunctionInstance* instance = info->FunctionByName(
"__cxa_allocate_exception");
if (instance == NULL)
instance = info->FunctionByName("__throw(void)");
if (instance != NULL) {
_foundAddress = instance->Address();
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void
ExceptionStopConfigView::_UpdateExceptionState()
{
// check if the exception breakpoints are already installed
for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
it.HasNext();) {
Image* image = it.Next();
ImageDebugInfo* info = image->GetImageDebugInfo();
target_addr_t address;
if (_FindExceptionFunction(info, address) != B_OK)
continue;
if (fTeam->BreakpointAtAddress(address) != NULL) {
fExceptionThrown->SetValue(B_CONTROL_ON);
break;
}
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2013-2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef EXCEPTION_STOP_CONFIG_VIEW_H
#define EXCEPTION_STOP_CONFIG_VIEW_H
#include <GroupView.h>
#include "types/Types.h"
class BBox;
class BButton;
class BCheckBox;
class ImageDebugInfo;
class Team;
class UserInterfaceListener;
class ExceptionStopConfigView : public BGroupView {
public:
ExceptionStopConfigView(::Team* team,
UserInterfaceListener* listener);
~ExceptionStopConfigView();
static ExceptionStopConfigView* Create(::Team* team,
UserInterfaceListener* listener);
// throws
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message);
private:
void _Init();
void _UpdateThrownBreakpoints(bool enable);
status_t _FindExceptionFunction(ImageDebugInfo* info,
target_addr_t& _foundAddress) const;
void _UpdateExceptionState();
private:
::Team* fTeam;
UserInterfaceListener* fListener;
BCheckBox* fExceptionThrown;
BCheckBox* fExceptionCaught;
};
#endif // EXCEPTION_STOP_CONFIG_VIEW_H
@@ -0,0 +1,337 @@
/*
* Copyright 2013-2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ImageStopConfigView.h"
#include <Button.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <ListView.h>
#include <MenuField.h>
#include <ScrollView.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "FunctionInstance.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "MessageCodes.h"
#include "UserInterface.h"
enum {
MSG_SET_STOP_FOR_ALL_IMAGES = 'sfai',
MSG_SET_STOP_FOR_CUSTOM_IMAGES = 'sfci',
MSG_IMAGE_NAME_SELECTION_CHANGED = 'insc',
MSG_ADD_IMAGE_NAME = 'anin',
MSG_REMOVE_IMAGE_NAME = 'arin',
MSG_IMAGE_NAME_INPUT_CHANGED = 'inic'
};
static int SortStringItems(const void* a, const void* b)
{
BStringItem* item1 = *(BStringItem**)a;
BStringItem* item2 = *(BStringItem**)b;
return strcmp(item1->Text(), item2->Text());
}
ImageStopConfigView::ImageStopConfigView(::Team* team,
UserInterfaceListener* listener)
:
BGroupView(B_VERTICAL),
fTeam(team),
fListener(listener),
fStopOnImageLoad(NULL),
fStopImageConstraints(NULL),
fStopImageNames(NULL),
fStopImageNameInput(NULL),
fAddImageNameButton(NULL),
fRemoveImageNameButton(NULL),
fCustomImageGroup(NULL),
fStopOnLoadEnabled(false),
fUseCustomImages(false)
{
SetName("Images");
fTeam->AddListener(this);
}
ImageStopConfigView::~ImageStopConfigView()
{
fTeam->RemoveListener(this);
}
ImageStopConfigView*
ImageStopConfigView::Create(::Team* team, UserInterfaceListener* listener)
{
ImageStopConfigView* self = new ImageStopConfigView(team, listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
ImageStopConfigView::AttachedToWindow()
{
fAddImageNameButton->SetEnabled(false);
fRemoveImageNameButton->SetEnabled(false);
fStopImageConstraints->Menu()->SetTargetForItems(this);
fStopOnImageLoad->SetTarget(this);
fAddImageNameButton->SetTarget(this);
fRemoveImageNameButton->SetTarget(this);
fStopImageNames->SetTarget(this);
fStopImageNameInput->SetTarget(this);
AutoLocker< ::Team> teamLocker(fTeam);
_UpdateStopImageState();
BGroupView::AttachedToWindow();
}
void
ImageStopConfigView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SET_STOP_FOR_ALL_IMAGES:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
false);
break;
}
case MSG_SET_STOP_FOR_CUSTOM_IMAGES:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
true);
break;
}
case MSG_IMAGE_NAME_SELECTION_CHANGED:
{
if (!fUseCustomImages)
break;
fRemoveImageNameButton->SetEnabled(
fStopImageNames->CurrentSelection() >= 0);
break;
}
case MSG_IMAGE_NAME_INPUT_CHANGED:
{
BString imageName(fStopImageNameInput->Text());
imageName.Trim();
fAddImageNameButton->SetEnabled(!imageName.IsEmpty());
break;
}
case MSG_STOP_ON_IMAGE_LOAD:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
fUseCustomImages);
break;
}
case MSG_STOP_IMAGE_SETTINGS_CHANGED:
{
_UpdateStopImageState();
break;
}
case MSG_ADD_IMAGE_NAME:
{
BString imageName(fStopImageNameInput->Text());
imageName.Trim();
AutoLocker< ::Team> teamLocker(fTeam);
if (fTeam->StopImageNames().HasString(imageName))
break;
fStopImageNameInput->SetText("");
fListener->AddStopImageNameRequested(imageName.String());
break;
}
case MSG_STOP_IMAGE_NAME_ADDED:
{
const char* imageName;
if (message->FindString("name", &imageName) != B_OK)
break;
BStringItem* item = new(std::nothrow) BStringItem(imageName);
if (item == NULL)
break;
ObjectDeleter<BStringItem> itemDeleter(item);
if (!fStopImageNames->AddItem(item)) {
break;
}
itemDeleter.Detach();
fStopImageNames->SortItems(SortStringItems);
break;
}
case MSG_REMOVE_IMAGE_NAME:
{
BStringItem* item;
int32 selectedIndex;
AutoLocker< ::Team> teamLocker(fTeam);
int32 i = 0;
while ((selectedIndex = fStopImageNames->CurrentSelection(i++))
>= 0) {
item = (BStringItem*)fStopImageNames->ItemAt(selectedIndex);
fListener->RemoveStopImageNameRequested(item->Text());
}
break;
}
case MSG_STOP_IMAGE_NAME_REMOVED:
{
const char* imageName;
if (message->FindString("name", &imageName) != B_OK)
break;
for (int32 i = 0; i < fStopImageNames->CountItems(); i++) {
BStringItem* item = (BStringItem*)fStopImageNames->ItemAt(i);
if (strcmp(item->Text(), imageName) == 0) {
fStopImageNames->RemoveItem(i);
delete item;
}
}
break;
}
default:
BGroupView::MessageReceived(message);
break;
}
}
void
ImageStopConfigView::StopOnImageLoadSettingsChanged(
const Team::ImageLoadEvent& event)
{
BMessage message(MSG_STOP_IMAGE_SETTINGS_CHANGED);
message.AddBool("enabled", event.StopOnImageLoad());
message.AddBool("useNameList", event.StopImageNameListEnabled());
BMessenger(this).SendMessage(&message);
}
void
ImageStopConfigView::StopOnImageLoadNameAdded(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_ADDED);
message.AddString("name", event.ImageName());
BMessenger(this).SendMessage(&message);
}
void
ImageStopConfigView::StopOnImageLoadNameRemoved(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_REMOVED);
message.AddString("name", event.ImageName());
BMessenger(this).SendMessage(&message);
}
void
ImageStopConfigView::_Init()
{
BMenu* stopImageMenu = new BMenu("stopImageTypesMenu");
stopImageMenu->AddItem(new BMenuItem("All",
new BMessage(MSG_SET_STOP_FOR_ALL_IMAGES)));
stopImageMenu->AddItem(new BMenuItem("Custom",
new BMessage(MSG_SET_STOP_FOR_CUSTOM_IMAGES)));
fStopImageNames = new BListView("customImageList",
B_MULTIPLE_SELECTION_LIST);
fStopImageNames->SetSelectionMessage(
new BMessage(MSG_IMAGE_NAME_SELECTION_CHANGED));
fCustomImageGroup = new BGroupView();
BLayoutBuilder::Group<>(fCustomImageGroup, B_VERTICAL, 0.0)
.Add(new BScrollView("stopImageScroll", fStopImageNames,
0, false, true))
.Add(fStopImageNameInput = new BTextControl("stopImageName",
"Image:", NULL, NULL))
.AddGroup(B_HORIZONTAL)
.SetInsets(B_USE_SMALL_SPACING)
.AddGlue()
.Add(fAddImageNameButton = new BButton("Add",
new BMessage(MSG_ADD_IMAGE_NAME)))
.Add(fRemoveImageNameButton = new BButton("Remove",
new BMessage(MSG_REMOVE_IMAGE_NAME)))
.End();
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_SMALL_SPACING)
.Add(fStopOnImageLoad = new BCheckBox("stopOnImage",
"Stop when an image is loaded",
new BMessage(MSG_STOP_ON_IMAGE_LOAD)))
.Add(fStopImageConstraints = new BMenuField(
"stopTypes", "Types:", stopImageMenu))
.Add(fCustomImageGroup);
font_height fontHeight;
be_plain_font->GetHeight(&fontHeight);
float minListHeight = 5 * (fontHeight.ascent + fontHeight.descent
+ fontHeight.leading);
fStopImageNames->SetExplicitMinSize(BSize(B_SIZE_UNSET, minListHeight));
stopImageMenu->SetLabelFromMarked(true);
fStopImageNameInput->SetModificationMessage(
new BMessage(MSG_IMAGE_NAME_INPUT_CHANGED));
}
void
ImageStopConfigView::_UpdateStopImageState()
{
fStopOnLoadEnabled = fTeam->StopOnImageLoad();
fStopOnImageLoad->SetValue(
fStopOnLoadEnabled ? B_CONTROL_ON : B_CONTROL_OFF);
fUseCustomImages = fTeam->StopImageNameListEnabled();
fStopImageConstraints->Menu()
->ItemAt(fUseCustomImages ? 1 : 0)->SetMarked(true);
fStopImageNames->MakeEmpty();
const BStringList& imageNames = fTeam->StopImageNames();
for (int32 i = 0; i < imageNames.CountStrings(); i++) {
BStringItem* item = new(std::nothrow) BStringItem(
imageNames.StringAt(i));
if (item == NULL)
return;
item->SetEnabled(fUseCustomImages);
ObjectDeleter<BStringItem> itemDeleter(item);
if (!fStopImageNames->AddItem(item))
return;
itemDeleter.Detach();
}
fStopImageConstraints->SetEnabled(fStopOnLoadEnabled);
fStopImageNameInput->SetEnabled(fUseCustomImages);
}
@@ -0,0 +1,70 @@
/*
* Copyright 2013-2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef IMAGE_STOP_CONFIG_VIEW_H
#define IMAGE_STOP_CONFIG_VIEW_H
#include <GroupView.h>
#include "Team.h"
#include "types/Types.h"
class BBox;
class BButton;
class BCheckBox;
class BListView;
class BMenuField;
class BTextControl;
class ImageDebugInfo;
class UserInterfaceListener;
class ImageStopConfigView : public BGroupView, private Team::Listener {
public:
ImageStopConfigView(::Team* team,
UserInterfaceListener* listener);
~ImageStopConfigView();
static ImageStopConfigView* Create(::Team* team,
UserInterfaceListener* listener);
// throws
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message);
// Team::Listener
virtual void StopOnImageLoadSettingsChanged(
const Team::ImageLoadEvent& event);
virtual void StopOnImageLoadNameAdded(
const Team::ImageLoadNameEvent& event);
virtual void StopOnImageLoadNameRemoved(
const Team::ImageLoadNameEvent& event);
private:
void _Init();
void _UpdateStopImageState();
// must be called with team lock held
private:
::Team* fTeam;
UserInterfaceListener* fListener;
BCheckBox* fStopOnImageLoad;
BMenuField* fStopImageConstraints;
BListView* fStopImageNames;
BTextControl* fStopImageNameInput;
BButton* fAddImageNameButton;
BButton* fRemoveImageNameButton;
BView* fCustomImageGroup;
bool fStopOnLoadEnabled;
bool fUseCustomImages;
};
#endif // IMAGE_STOP_CONFIG_VIEW_H
@@ -4,44 +4,13 @@
*/
#include "TeamSettingsWindow.h"
#include <Box.h>
#include <Button.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <ListView.h>
#include <MenuField.h>
#include <ScrollView.h>
#include <TabView.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "FunctionInstance.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "ExceptionStopConfigView.h"
#include "ImageStopConfigView.h"
#include "MessageCodes.h"
#include "UserInterface.h"
#include "Team.h"
enum {
MSG_STOP_ON_THROWN_EXCEPTION_CHANGED = 'stec',
MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED = 'scec',
MSG_SET_STOP_FOR_ALL_IMAGES = 'sfai',
MSG_SET_STOP_FOR_CUSTOM_IMAGES = 'sfci',
MSG_IMAGE_NAME_SELECTION_CHANGED = 'insc',
MSG_ADD_IMAGE_NAME = 'anin',
MSG_REMOVE_IMAGE_NAME = 'arin',
MSG_IMAGE_NAME_INPUT_CHANGED = 'inic'
};
static int SortStringItems(const void* a, const void* b)
{
BStringItem* item1 = *(BStringItem**)a;
BStringItem* item2 = *(BStringItem**)b;
return strcmp(item1->Text(), item2->Text());
}
TeamSettingsWindow::TeamSettingsWindow(::Team* team,
@@ -51,29 +20,14 @@ TeamSettingsWindow::TeamSettingsWindow(::Team* team,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fTeam(team),
fListener(listener),
fExceptionSettingsBox(NULL),
fImageSettingsBox(NULL),
fExceptionThrown(NULL),
fExceptionCaught(NULL),
fStopOnImageLoad(NULL),
fStopImageConstraints(NULL),
fStopImageNames(NULL),
fStopImageNameInput(NULL),
fAddImageNameButton(NULL),
fRemoveImageNameButton(NULL),
fCustomImageGroup(NULL),
fStopOnLoadEnabled(false),
fUseCustomImages(false),
fCloseButton(NULL),
fTarget(target)
{
fTeam->AddListener(this);
}
TeamSettingsWindow::~TeamSettingsWindow()
{
fTeam->RemoveListener(this);
BMessenger(fTarget).SendMessage(MSG_TEAM_SETTINGS_WINDOW_CLOSED);
}
@@ -93,141 +47,6 @@ TeamSettingsWindow::Create(::Team* team,
}
return self;
}
void
TeamSettingsWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_STOP_ON_THROWN_EXCEPTION_CHANGED:
{
_UpdateThrownBreakpoints(fExceptionThrown->Value()
== B_CONTROL_ON);
break;
}
case MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED:
{
break;
}
case MSG_SET_STOP_FOR_ALL_IMAGES:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
false);
break;
}
case MSG_SET_STOP_FOR_CUSTOM_IMAGES:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
true);
break;
}
case MSG_IMAGE_NAME_SELECTION_CHANGED:
{
if (!fUseCustomImages)
break;
fRemoveImageNameButton->SetEnabled(
fStopImageNames->CurrentSelection() >= 0);
break;
}
case MSG_IMAGE_NAME_INPUT_CHANGED:
{
BString imageName(fStopImageNameInput->Text());
imageName.Trim();
fAddImageNameButton->SetEnabled(!imageName.IsEmpty());
break;
}
case MSG_STOP_ON_IMAGE_LOAD:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
fUseCustomImages);
break;
}
case MSG_STOP_IMAGE_SETTINGS_CHANGED:
{
_UpdateStopImageState();
break;
}
case MSG_ADD_IMAGE_NAME:
{
BString imageName(fStopImageNameInput->Text());
imageName.Trim();
AutoLocker< ::Team> teamLocker(fTeam);
if (fTeam->StopImageNames().HasString(imageName))
break;
fStopImageNameInput->SetText("");
fListener->AddStopImageNameRequested(imageName.String());
break;
}
case MSG_STOP_IMAGE_NAME_ADDED:
{
const char* imageName;
if (message->FindString("name", &imageName) != B_OK)
break;
BStringItem* item = new(std::nothrow) BStringItem(imageName);
if (item == NULL)
break;
ObjectDeleter<BStringItem> itemDeleter(item);
if (!fStopImageNames->AddItem(item)) {
break;
}
itemDeleter.Detach();
fStopImageNames->SortItems(SortStringItems);
break;
}
case MSG_REMOVE_IMAGE_NAME:
{
BStringItem* item;
int32 selectedIndex;
AutoLocker< ::Team> teamLocker(fTeam);
int32 i = 0;
while ((selectedIndex = fStopImageNames->CurrentSelection(i++))
>= 0) {
item = (BStringItem*)fStopImageNames->ItemAt(selectedIndex);
fListener->RemoveStopImageNameRequested(item->Text());
}
break;
}
case MSG_STOP_IMAGE_NAME_REMOVED:
{
const char* imageName;
if (message->FindString("name", &imageName) != B_OK)
break;
for (int32 i = 0; i < fStopImageNames->CountItems(); i++) {
BStringItem* item = (BStringItem*)fStopImageNames->ItemAt(i);
if (strcmp(item->Text(), imageName) == 0) {
fStopImageNames->RemoveItem(i);
delete item;
}
}
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
@@ -239,232 +58,25 @@ TeamSettingsWindow::Show()
}
void
TeamSettingsWindow::StopOnImageLoadSettingsChanged(
const Team::ImageLoadEvent& event)
{
BMessage message(MSG_STOP_IMAGE_SETTINGS_CHANGED);
message.AddBool("enabled", event.StopOnImageLoad());
message.AddBool("useNameList", event.StopImageNameListEnabled());
PostMessage(&message);
}
void
TeamSettingsWindow::StopOnImageLoadNameAdded(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_ADDED);
message.AddString("name", event.ImageName());
PostMessage(&message);
}
void
TeamSettingsWindow::StopOnImageLoadNameRemoved(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_REMOVED);
message.AddString("name", event.ImageName());
PostMessage(&message);
}
void
TeamSettingsWindow::_Init()
{
fExceptionSettingsBox = new BBox("exceptionBox");
fExceptionSettingsBox->SetLabel("Exceptions");
fExceptionSettingsBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fExceptionThrown = new BCheckBox("exceptionThrown",
"Stop when an exception is thrown",
new BMessage(MSG_STOP_ON_THROWN_EXCEPTION_CHANGED)))
.Add(fExceptionCaught = new BCheckBox("exceptionCaught",
"Stop when an exception is caught",
new BMessage(MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED)))
.View());
fExceptionThrown->SetTarget(this);
fExceptionCaught->SetTarget(this);
// TODO: enable once implemented
fExceptionCaught->SetEnabled(false);
fImageSettingsBox = new BBox("imageBox");
fImageSettingsBox->SetLabel("Images");
BMenu* stopImageMenu = new BMenu("stopImageTypesMenu");
stopImageMenu->AddItem(new BMenuItem("All",
new BMessage(MSG_SET_STOP_FOR_ALL_IMAGES)));
stopImageMenu->AddItem(new BMenuItem("Custom",
new BMessage(MSG_SET_STOP_FOR_CUSTOM_IMAGES)));
fStopImageNames = new BListView("customImageList",
B_MULTIPLE_SELECTION_LIST);
fStopImageNames->SetSelectionMessage(
new BMessage(MSG_IMAGE_NAME_SELECTION_CHANGED));
fCustomImageGroup = new BGroupView();
BLayoutBuilder::Group<>(fCustomImageGroup, B_VERTICAL, 0.0)
.Add(new BScrollView("stopImageScroll", fStopImageNames,
0, false, true))
.Add(fStopImageNameInput = new BTextControl("stopImageName",
"Image:", NULL, NULL))
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fAddImageNameButton = new BButton("Add",
new BMessage(MSG_ADD_IMAGE_NAME)))
.Add(fRemoveImageNameButton = new BButton("Remove",
new BMessage(MSG_REMOVE_IMAGE_NAME)))
.End();
fImageSettingsBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fStopOnImageLoad = new BCheckBox("stopOnImage",
"Stop when an image is loaded",
new BMessage(MSG_STOP_ON_IMAGE_LOAD)))
.Add(fStopImageConstraints = new BMenuField(
"stopTypes", "Types:", stopImageMenu))
.Add(fCustomImageGroup)
.View());
font_height fontHeight;
be_plain_font->GetHeight(&fontHeight);
float minListHeight = 5 * (fontHeight.ascent + fontHeight.descent
+ fontHeight.leading);
fStopImageNames->SetExplicitMinSize(BSize(B_SIZE_UNSET, minListHeight));
BTabView* tabView = new BTabView("config tab view");
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fExceptionSettingsBox)
.Add(fImageSettingsBox)
.Add(tabView)
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fCloseButton = new BButton("Close", new BMessage(
B_QUIT_REQUESTED)))
.End();
ImageStopConfigView* imageView = ImageStopConfigView::Create(fTeam,
fListener);
tabView->AddTab(imageView);
ExceptionStopConfigView* exceptionView = ExceptionStopConfigView::Create(
fTeam, fListener);
tabView->AddTab(exceptionView);
fCloseButton->SetTarget(this);
fAddImageNameButton->SetEnabled(false);
fRemoveImageNameButton->SetEnabled(false);
stopImageMenu->SetTargetForItems(this);
stopImageMenu->SetLabelFromMarked(true);
fStopImageNameInput->SetModificationMessage(
new BMessage(MSG_IMAGE_NAME_INPUT_CHANGED));
fCustomImageGroup->Hide();
AutoLocker< ::Team> teamLocker(fTeam);
_UpdateStopImageState();
_UpdateExceptionState();
}
void
TeamSettingsWindow::_UpdateThrownBreakpoints(bool enable)
{
AutoLocker< ::Team> teamLocker(fTeam);
for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
it.HasNext();) {
Image* image = it.Next();
ImageDebugInfo* info = image->GetImageDebugInfo();
target_addr_t address;
if (_FindExceptionFunction(info, address) != B_OK)
continue;
if (enable)
fListener->SetBreakpointRequested(address, true, true);
else
fListener->ClearBreakpointRequested(address);
}
}
status_t
TeamSettingsWindow::_FindExceptionFunction(ImageDebugInfo* info,
target_addr_t& _foundAddress) const
{
if (info != NULL) {
FunctionInstance* instance = info->FunctionByName(
"__cxa_allocate_exception");
if (instance == NULL)
instance = info->FunctionByName("__throw(void)");
if (instance != NULL) {
_foundAddress = instance->Address();
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void
TeamSettingsWindow::_UpdateExceptionState()
{
// check if the exception breakpoints are already installed
for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
it.HasNext();) {
Image* image = it.Next();
ImageDebugInfo* info = image->GetImageDebugInfo();
target_addr_t address;
if (_FindExceptionFunction(info, address) != B_OK)
continue;
if (fTeam->BreakpointAtAddress(address) != NULL) {
fExceptionThrown->SetValue(B_CONTROL_ON);
break;
}
}
}
void
TeamSettingsWindow::_UpdateStopImageState()
{
bool previousStop = fStopOnLoadEnabled;
bool previousCustomImages = fUseCustomImages && fStopOnLoadEnabled;
fStopOnLoadEnabled = fTeam->StopOnImageLoad();
fStopOnImageLoad->SetValue(
fStopOnLoadEnabled ? B_CONTROL_ON : B_CONTROL_OFF);
fUseCustomImages = fTeam->StopImageNameListEnabled();
fStopImageConstraints->Menu()
->ItemAt(fTeam->StopImageNameListEnabled() ? 1 : 0)->SetMarked(true);
fStopImageNames->MakeEmpty();
const BStringList& imageNames = fTeam->StopImageNames();
for (int32 i = 0; i < imageNames.CountStrings(); i++) {
BStringItem* item = new(std::nothrow) BStringItem(
imageNames.StringAt(i));
if (item == NULL)
return;
item->SetEnabled(fUseCustomImages);
ObjectDeleter<BStringItem> itemDeleter(item);
if (!fStopImageNames->AddItem(item))
return;
itemDeleter.Detach();
}
_UpdateStopImageButtons(previousStop, previousCustomImages);
}
void
TeamSettingsWindow::_UpdateStopImageButtons(bool previousStop,
bool previousCustomImages)
{
fStopImageConstraints->SetEnabled(fStopOnLoadEnabled);
bool showCustomGroup = fUseCustomImages && fStopOnLoadEnabled;
if (!previousCustomImages && showCustomGroup)
fCustomImageGroup->Show();
else if (previousCustomImages && !showCustomGroup)
fCustomImageGroup->Hide();
}
@@ -8,22 +8,15 @@
#include <Window.h>
#include "Team.h"
#include "types/Types.h"
class BBox;
class BButton;
class BCheckBox;
class BListView;
class BMenuField;
class BTextControl;
class ImageDebugInfo;
class ExceptionStopConfigView;
class ImageStopConfigView;
class Team;
class UserInterfaceListener;
class TeamSettingsWindow : public BWindow, private Team::Listener {
class TeamSettingsWindow : public BWindow {
public:
TeamSettingsWindow(::Team* team,
UserInterfaceListener* listener,
@@ -36,49 +29,14 @@ public:
BHandler* target);
// throws
virtual void MessageReceived(BMessage* message);
virtual void Show();
// Team::Listener
virtual void StopOnImageLoadSettingsChanged(
const Team::ImageLoadEvent& event);
virtual void StopOnImageLoadNameAdded(
const Team::ImageLoadNameEvent& event);
virtual void StopOnImageLoadNameRemoved(
const Team::ImageLoadNameEvent& event);
private:
void _Init();
void _UpdateThrownBreakpoints(bool enable);
status_t _FindExceptionFunction(ImageDebugInfo* info,
target_addr_t& _foundAddress) const;
void _UpdateExceptionState();
void _UpdateStopImageState();
void _UpdateStopImageButtons(bool previousStop,
bool previousCustomImages);
// must be called with team lock held
private:
::Team* fTeam;
UserInterfaceListener* fListener;
BBox* fExceptionSettingsBox;
BBox* fImageSettingsBox;
BCheckBox* fExceptionThrown;
BCheckBox* fExceptionCaught;
BCheckBox* fStopOnImageLoad;
BMenuField* fStopImageConstraints;
BListView* fStopImageNames;
BTextControl* fStopImageNameInput;
BButton* fAddImageNameButton;
BButton* fRemoveImageNameButton;
BView* fCustomImageGroup;
bool fStopOnLoadEnabled;
bool fUseCustomImages;
BButton* fCloseButton;
BHandler* fTarget;
};