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:
parent
cae8421db8
commit
9a14c8a25d
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user