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:
@@ -290,6 +290,8 @@ Application Debugger :
|
||||
VariablesView.cpp
|
||||
|
||||
# user_interface/gui/team_settings_window
|
||||
ExceptionStopConfigView.cpp
|
||||
ImageStopConfigView.cpp
|
||||
TeamSettingsWindow.cpp
|
||||
|
||||
# user_interface/gui/util
|
||||
|
||||
+176
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user