Implement configuration for stop on image load with names.

- BreakConditionConfigWindow is now a team listener so it can watch for
the appropriate events.
- Implement reading/maintaining state in response to the various
notifications.
- Implement adding/removing names and enabling/disabling the use of the
name list.
This commit is contained in:
Rene Gollent 2013-07-07 00:34:12 -04:00
parent cae8421db8
commit 9a14c8a25d
2 changed files with 215 additions and 31 deletions

View File

@ -12,6 +12,7 @@
#include <MenuField.h>
#include <ScrollView.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "FunctionInstance.h"
@ -33,6 +34,22 @@ enum {
};
static int SortStringItems(const void* a, const void* b)
{
BStringItem* item1 = *(BStringItem**)a;
BStringItem* item2 = *(BStringItem**)b;
return strcmp(item1->Text(), item2->Text());
}
static bool UpdateItemState(BListItem* item, void* enabled)
{
item->SetEnabled((bool)enabled);
return false;
}
BreakConditionConfigWindow::BreakConditionConfigWindow(::Team* team,
UserInterfaceListener* listener, BHandler* target)
:
@ -48,14 +65,17 @@ BreakConditionConfigWindow::BreakConditionConfigWindow(::Team* team,
fStopImageNameInput(NULL),
fAddImageNameButton(NULL),
fRemoveImageNameButton(NULL),
fUseCustomImages(false),
fCloseButton(NULL),
fTarget(target)
{
fTeam->AddListener(this);
}
BreakConditionConfigWindow::~BreakConditionConfigWindow()
{
fTeam->RemoveListener(this);
BMessenger(fTarget).SendMessage(MSG_BREAK_CONDITION_CONFIG_WINDOW_CLOSED);
}
@ -96,28 +116,27 @@ BreakConditionConfigWindow::MessageReceived(BMessage* message)
case MSG_SET_STOP_FOR_ALL_IMAGES:
{
for (int32 i = 0; i < fStopImageNames->CountItems(); i++)
fStopImageNames->ItemAt(i)->SetEnabled(false);
fStopImageNameInput->SetEnabled(false);
fAddImageNameButton->SetEnabled(false);
fRemoveImageNameButton->SetEnabled(false);
fUseCustomImages = false;
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
fUseCustomImages);
break;
}
case MSG_SET_STOP_FOR_CUSTOM_IMAGES:
{
for (int32 i = 0; i < fStopImageNames->CountItems(); i++)
fStopImageNames->ItemAt(i)->SetEnabled(true);
fStopImageNameInput->SetEnabled(true);
fAddImageNameButton->SetEnabled(
fStopImageNameInput->TextView()->TextLength() > 0);
fRemoveImageNameButton->SetEnabled(
fStopImageNames->CurrentSelection() >= 0);
fUseCustomImages = true;
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON,
fUseCustomImages);
break;
}
case MSG_IMAGE_NAME_SELECTION_CHANGED:
{
if (!fUseCustomImages)
break;
fRemoveImageNameButton->SetEnabled(
fStopImageNames->CurrentSelection() >= 0);
break;
@ -126,10 +145,79 @@ BreakConditionConfigWindow::MessageReceived(BMessage* message)
case MSG_STOP_ON_IMAGE_LOAD:
{
fListener->SetStopOnImageLoadRequested(
fStopOnImageLoad->Value() == B_CONTROL_ON);
fStopOnImageLoad->Value() == B_CONTROL_ON,
fUseCustomImages);
break;
}
case MSG_STOP_IMAGE_SETTINGS_CHANGED:
{
_UpdateStopImageButtons();
break;
}
case MSG_ADD_IMAGE_NAME:
{
BString imageName(fStopImageNameInput->Text());
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;
@ -146,6 +234,37 @@ BreakConditionConfigWindow::Show()
}
void
BreakConditionConfigWindow::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
BreakConditionConfigWindow::StopOnImageLoadNameAdded(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_ADDED);
message.AddString("name", event.ImageName());
PostMessage(&message);
}
void
BreakConditionConfigWindow::StopOnImageLoadNameRemoved(
const Team::ImageLoadNameEvent& event)
{
BMessage message(MSG_STOP_IMAGE_NAME_REMOVED);
message.AddString("name", event.ImageName());
PostMessage(&message);
}
void
BreakConditionConfigWindow::_Init()
{
@ -179,7 +298,7 @@ BreakConditionConfigWindow::_Init()
stopImageMenu->AddItem(new BMenuItem("Custom",
new BMessage(MSG_SET_STOP_FOR_CUSTOM_IMAGES)));
BListView* fStopImageNames = new BListView("customImageList",
fStopImageNames = new BListView("customImageList",
B_MULTIPLE_SELECTION_LIST);
fStopImageNames->SetSelectionMessage(
new BMessage(MSG_IMAGE_NAME_SELECTION_CHANGED));
@ -226,24 +345,11 @@ BreakConditionConfigWindow::_Init()
fCloseButton->SetTarget(this);
stopImageMenu->SetTargetForItems(this);
stopImageMenu->SetLabelFromMarked(true);
stopImageMenu->ItemAt(0L)->SetMarked(true);
// check if the exception breakpoints are already installed
AutoLocker< ::Team> teamLocker(fTeam);
for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
it.HasNext();) {
Image* image = it.Next();
_UpdateStopImageState();
_UpdateExceptionState();
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;
}
}
}
@ -286,3 +392,64 @@ BreakConditionConfigWindow::_FindExceptionFunction(ImageDebugInfo* info,
return B_NAME_NOT_FOUND;
}
void
BreakConditionConfigWindow::_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
BreakConditionConfigWindow::_UpdateStopImageState()
{
fUseCustomImages = fTeam->StopImageNameListEnabled();
fStopImageConstraints->Menu()->ItemAt(0)->SetMarked(!fUseCustomImages);
fStopImageConstraints->Menu()->ItemAt(1)->SetMarked(fUseCustomImages);
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();
}
void
BreakConditionConfigWindow::_UpdateStopImageButtons()
{
bool stopOnImageLoad = fTeam->StopOnImageLoad();
fStopOnImageLoad->SetValue(stopOnImageLoad ? B_CONTROL_ON : B_CONTROL_OFF);
bool enabled = stopOnImageLoad && fUseCustomImages;
fStopImageConstraints->SetEnabled(stopOnImageLoad);
fAddImageNameButton->SetEnabled(enabled);
fRemoveImageNameButton->SetEnabled(enabled
&& fStopImageNames->CurrentSelection() >= 0);
fStopImageNames->DoForEach(UpdateItemState, (void*)enabled);
fStopImageNameInput->TextView()->MakeEditable(enabled);
}

View File

@ -8,6 +8,8 @@
#include <Window.h>
#include "Team.h"
#include "types/Types.h"
@ -17,11 +19,10 @@ class BListView;
class BMenuField;
class BTextControl;
class ImageDebugInfo;
class Team;
class UserInterfaceListener;
class BreakConditionConfigWindow : public BWindow {
class BreakConditionConfigWindow : public BWindow, private Team::Listener {
public:
BreakConditionConfigWindow(::Team* team,
UserInterfaceListener* listener,
@ -38,12 +39,27 @@ public:
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();
// must be called with team lock held
private:
::Team* fTeam;
@ -56,6 +72,7 @@ private:
BTextControl* fStopImageNameInput;
BButton* fAddImageNameButton;
BButton* fRemoveImageNameButton;
bool fUseCustomImages;
BButton* fCloseButton;
BHandler* fTarget;
};