Implement #9777.
- Introduce class BreakpointProxy which acts as a container for either a breakpoint or a watchpoint. BreakpointsTableModel now stores a single list of these rather than separate Breakpoint/Watchpoint lists. - Switch BreakpointListView to allow multiple selection mode, and consequently change selection/listener interfaces to use a list of BreakpointProxy objects. Adjust implementors accordingly. - Rework breakpoint list columns to better mesh with a unified display of breakpoint and watchpoint information. - Add an input filter to handle removing breakpoints when the delete key is pressed.
This commit is contained in:
parent
74875a2e90
commit
6b308faf1e
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2011-2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -11,12 +11,16 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <MessageFilter.h>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "FunctionID.h"
|
||||
#include "GuiSettingsUtils.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "MessageCodes.h"
|
||||
#include "table/TableColumns.h"
|
||||
#include "TargetAddressTableColumn.h"
|
||||
#include "Team.h"
|
||||
@ -24,6 +28,73 @@
|
||||
#include "Watchpoint.h"
|
||||
|
||||
|
||||
// #pragma mark - BreakpointProxy
|
||||
|
||||
|
||||
BreakpointProxy::BreakpointProxy(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint)
|
||||
:
|
||||
fBreakpoint(breakpoint),
|
||||
fWatchpoint(watchpoint)
|
||||
{
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->AcquireReference();
|
||||
|
||||
if (fWatchpoint != NULL)
|
||||
fWatchpoint->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
BreakpointProxy::~BreakpointProxy()
|
||||
{
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->ReleaseReference();
|
||||
|
||||
if (fWatchpoint != NULL)
|
||||
fWatchpoint->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
breakpoint_proxy_type
|
||||
BreakpointProxy::Type() const
|
||||
{
|
||||
return fBreakpoint != NULL ? BREAKPOINT_PROXY_TYPE_BREAKPOINT
|
||||
: BREAKPOINT_PROXY_TYPE_WATCHPOINT;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ListInputFilter
|
||||
|
||||
|
||||
class BreakpointListView::ListInputFilter : public BMessageFilter {
|
||||
public:
|
||||
ListInputFilter(BView* view)
|
||||
:
|
||||
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, B_KEY_DOWN),
|
||||
fTargetView(view)
|
||||
{
|
||||
}
|
||||
|
||||
~ListInputFilter()
|
||||
{
|
||||
}
|
||||
|
||||
filter_result Filter(BMessage* message, BHandler** target)
|
||||
{
|
||||
const char* bytes;
|
||||
if (message->FindString("bytes", &bytes) == B_OK
|
||||
&& bytes[0] == B_DELETE) {
|
||||
BMessenger(fTargetView).SendMessage(MSG_CLEAR_BREAKPOINT);
|
||||
}
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
|
||||
private:
|
||||
BView* fTargetView;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - BreakpointsTableModel
|
||||
|
||||
|
||||
@ -34,25 +105,23 @@ public:
|
||||
fTeam(team)
|
||||
{
|
||||
UpdateBreakpoint(NULL);
|
||||
UpdateWatchpoint(NULL);
|
||||
}
|
||||
|
||||
~BreakpointsTableModel()
|
||||
{
|
||||
fTeam = NULL;
|
||||
UpdateBreakpoint(NULL);
|
||||
UpdateWatchpoint(NULL);
|
||||
}
|
||||
|
||||
bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint)
|
||||
bool UpdateBreakpoint(BreakpointProxy* proxy)
|
||||
{
|
||||
if (fTeam == NULL) {
|
||||
for (int32 i = 0;
|
||||
UserBreakpoint* breakpoint = fBreakpoints.ItemAt(i);
|
||||
BreakpointProxy* proxy = fBreakpointProxies.ItemAt(i);
|
||||
i++) {
|
||||
breakpoint->ReleaseReference();
|
||||
proxy->ReleaseReference();
|
||||
}
|
||||
fBreakpoints.MakeEmpty();
|
||||
fBreakpointProxies.MakeEmpty();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -61,132 +130,126 @@ public:
|
||||
|
||||
UserBreakpointList::ConstIterator it
|
||||
= fTeam->UserBreakpoints().GetIterator();
|
||||
int32 watchpointIndex = 0;
|
||||
UserBreakpoint* newBreakpoint = it.Next();
|
||||
Watchpoint* newWatchpoint = fTeam->WatchpointAt(watchpointIndex);
|
||||
int32 index = 0;
|
||||
bool remove;
|
||||
|
||||
// remove no longer existing breakpoints
|
||||
while (UserBreakpoint* oldBreakpoint = fBreakpoints.ItemAt(index)) {
|
||||
if (oldBreakpoint == newBreakpoint) {
|
||||
if (oldBreakpoint == changedBreakpoint)
|
||||
NotifyRowsChanged(index, 1);
|
||||
index++;
|
||||
newBreakpoint = it.Next();
|
||||
} else {
|
||||
while (BreakpointProxy* oldProxy = fBreakpointProxies.ItemAt(index)) {
|
||||
remove = false;
|
||||
switch (oldProxy->Type()) {
|
||||
case BREAKPOINT_PROXY_TYPE_BREAKPOINT:
|
||||
{
|
||||
UserBreakpoint* breakpoint = oldProxy->GetBreakpoint();
|
||||
if (breakpoint == newBreakpoint) {
|
||||
if (breakpoint == proxy->GetBreakpoint())
|
||||
NotifyRowsChanged(index, 1);
|
||||
++index;
|
||||
newBreakpoint = it.Next();
|
||||
} else
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BREAKPOINT_PROXY_TYPE_WATCHPOINT:
|
||||
{
|
||||
Watchpoint* watchpoint = oldProxy->GetWatchpoint();
|
||||
if (watchpoint == newWatchpoint) {
|
||||
if (watchpoint == proxy->GetWatchpoint())
|
||||
NotifyRowsChanged(index, 1);
|
||||
++watchpointIndex;
|
||||
++index;
|
||||
newWatchpoint = fTeam->WatchpointAt(watchpointIndex);
|
||||
} else
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
// TODO: Not particularly efficient!
|
||||
fBreakpoints.RemoveItemAt(index);
|
||||
oldBreakpoint->ReleaseReference();
|
||||
fBreakpointProxies.RemoveItemAt(index);
|
||||
oldProxy->ReleaseReference();
|
||||
NotifyRowsRemoved(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// add new breakpoints
|
||||
int32 countBefore = fBreakpoints.CountItems();
|
||||
int32 countBefore = fBreakpointProxies.CountItems();
|
||||
BreakpointProxy* newProxy = NULL;
|
||||
BReference<BreakpointProxy> proxyReference;
|
||||
while (newBreakpoint != NULL) {
|
||||
if (!fBreakpoints.AddItem(newBreakpoint))
|
||||
newProxy = new(std::nothrow) BreakpointProxy(newBreakpoint, NULL);
|
||||
if (newProxy == NULL)
|
||||
return false;
|
||||
|
||||
newBreakpoint->AcquireReference();
|
||||
proxyReference.SetTo(newProxy, true);
|
||||
if (!fBreakpointProxies.AddItem(newProxy))
|
||||
return false;
|
||||
|
||||
proxyReference.Detach();
|
||||
newBreakpoint = it.Next();
|
||||
}
|
||||
|
||||
int32 count = fBreakpoints.CountItems();
|
||||
// add new watchpoints
|
||||
while (newWatchpoint != NULL) {
|
||||
newProxy = new(std::nothrow) BreakpointProxy(NULL, newWatchpoint);
|
||||
if (newProxy == NULL)
|
||||
return false;
|
||||
|
||||
proxyReference.SetTo(newProxy, true);
|
||||
if (!fBreakpointProxies.AddItem(newProxy))
|
||||
return false;
|
||||
|
||||
proxyReference.Detach();
|
||||
newWatchpoint = fTeam->WatchpointAt(++watchpointIndex);
|
||||
}
|
||||
|
||||
|
||||
int32 count = fBreakpointProxies.CountItems();
|
||||
if (count > countBefore)
|
||||
NotifyRowsAdded(countBefore, count - countBefore);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdateWatchpoint(Watchpoint* changedWatchpoint)
|
||||
{
|
||||
if (fTeam == NULL) {
|
||||
for (int32 i = 0;
|
||||
Watchpoint* watchpoint = fWatchpoints.ItemAt(i);
|
||||
i++) {
|
||||
watchpoint->ReleaseReference();
|
||||
}
|
||||
fWatchpoints.MakeEmpty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AutoLocker<Team> locker(fTeam);
|
||||
|
||||
int32 breakpointCount = fBreakpoints.CountItems();
|
||||
int32 index = 0;
|
||||
int32 teamIndex = 0;
|
||||
Watchpoint* newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||
// remove no longer existing breakpoints
|
||||
while (Watchpoint* oldWatchpoint = fWatchpoints.ItemAt(index)) {
|
||||
if (oldWatchpoint == newWatchpoint) {
|
||||
if (oldWatchpoint == changedWatchpoint)
|
||||
NotifyRowsChanged(index + breakpointCount, 1);
|
||||
index++;
|
||||
teamIndex++;
|
||||
newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||
} else {
|
||||
// TODO: Not particularly efficient!
|
||||
fWatchpoints.RemoveItemAt(index);
|
||||
oldWatchpoint->ReleaseReference();
|
||||
NotifyRowsRemoved(index + breakpointCount, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// add new breakpoints
|
||||
int32 countBefore = fWatchpoints.CountItems();
|
||||
while (newWatchpoint != NULL) {
|
||||
if (!fWatchpoints.AddItem(newWatchpoint))
|
||||
return false;
|
||||
|
||||
newWatchpoint->AcquireReference();
|
||||
teamIndex++;
|
||||
newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||
}
|
||||
|
||||
int32 count = fWatchpoints.CountItems();
|
||||
if (count > countBefore)
|
||||
NotifyRowsAdded(countBefore + breakpointCount, count - countBefore);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int32 CountColumns() const
|
||||
{
|
||||
return 5;
|
||||
return 3;
|
||||
}
|
||||
|
||||
virtual int32 CountRows() const
|
||||
{
|
||||
return fBreakpoints.CountItems() + fWatchpoints.CountItems();
|
||||
return fBreakpointProxies.CountItems();
|
||||
}
|
||||
|
||||
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
|
||||
{
|
||||
int32 breakpointCount = fBreakpoints.CountItems();
|
||||
if (rowIndex < breakpointCount)
|
||||
return _GetBreakpointValueAt(rowIndex, columnIndex, value);
|
||||
BreakpointProxy* proxy = fBreakpointProxies.ItemAt(rowIndex);
|
||||
if (proxy == NULL)
|
||||
return false;
|
||||
|
||||
return _GetWatchpointValueAt(rowIndex - breakpointCount, columnIndex,
|
||||
value);
|
||||
if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT) {
|
||||
return _GetBreakpointValueAt(proxy->GetBreakpoint(), rowIndex,
|
||||
columnIndex, value);
|
||||
}
|
||||
|
||||
return _GetWatchpointValueAt(proxy->GetWatchpoint(), rowIndex,
|
||||
columnIndex, value);
|
||||
}
|
||||
|
||||
UserBreakpoint* BreakpointAt(int32 index) const
|
||||
BreakpointProxy* BreakpointProxyAt(int32 index) const
|
||||
{
|
||||
return fBreakpoints.ItemAt(index);
|
||||
}
|
||||
|
||||
Watchpoint* WatchpointAt(int32 index) const
|
||||
{
|
||||
return fWatchpoints.ItemAt(index - fBreakpoints.CountItems());
|
||||
return fBreakpointProxies.ItemAt(index);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _GetBreakpointValueAt(int32 rowIndex, int32 columnIndex,
|
||||
BVariant &value)
|
||||
bool _GetBreakpointValueAt(UserBreakpoint* breakpoint, int32 rowIndex,
|
||||
int32 columnIndex, BVariant &value)
|
||||
{
|
||||
UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex);
|
||||
if (breakpoint == NULL)
|
||||
return false;
|
||||
const UserBreakpointLocation& location = breakpoint->Location();
|
||||
|
||||
switch (columnIndex) {
|
||||
@ -198,62 +261,75 @@ private:
|
||||
B_VARIANT_DONT_COPY_DATA);
|
||||
return true;
|
||||
case 2:
|
||||
if (LocatableFile* sourceFile = location.SourceFile()) {
|
||||
value.SetTo(sourceFile->Name(), B_VARIANT_DONT_COPY_DATA);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 3:
|
||||
if (location.SourceFile() != NULL) {
|
||||
value.SetTo(location.GetSourceLocation().Line() + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 4:
|
||||
if (location.SourceFile() == NULL) {
|
||||
{
|
||||
LocatableFile* sourceFile = location.SourceFile();
|
||||
if (sourceFile != NULL) {
|
||||
BString data;
|
||||
data.SetToFormat("%s:%" B_PRId32, sourceFile->Name(),
|
||||
location.GetSourceLocation().Line() + 1);
|
||||
value.SetTo(data);
|
||||
} else {
|
||||
AutoLocker<Team> teamLocker(fTeam);
|
||||
if (UserBreakpointInstance* instance
|
||||
= breakpoint->InstanceAt(0)) {
|
||||
value.SetTo(instance->Address());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool _GetWatchpointValueAt(int32 rowIndex, int32 columnIndex,
|
||||
BVariant& value)
|
||||
bool _GetWatchpointValueAt(Watchpoint* watchpoint, int32 rowIndex,
|
||||
int32 columnIndex, BVariant &value)
|
||||
{
|
||||
Watchpoint* watchpoint = fWatchpoints.ItemAt(rowIndex);
|
||||
if (watchpoint == NULL)
|
||||
return false;
|
||||
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
value.SetTo((int32)watchpoint->IsEnabled());
|
||||
return true;
|
||||
case 1:
|
||||
value.SetTo("Watchpoint");
|
||||
{
|
||||
BString data;
|
||||
data.SetToFormat("%s at 0x%" B_PRIx64 " (%" B_PRId32 " bytes)",
|
||||
_WatchpointTypeToString(watchpoint->Type()),
|
||||
watchpoint->Address(), watchpoint->Length());
|
||||
value.SetTo(data);
|
||||
return true;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return false;
|
||||
case 3:
|
||||
return false;
|
||||
case 4:
|
||||
value.SetTo(watchpoint->Address());
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char* _WatchpointTypeToString(uint32 type) const
|
||||
{
|
||||
switch (type) {
|
||||
case WATCHPOINT_CAPABILITY_FLAG_READ:
|
||||
{
|
||||
return "read";
|
||||
}
|
||||
case WATCHPOINT_CAPABILITY_FLAG_WRITE:
|
||||
{
|
||||
return "write";
|
||||
}
|
||||
case WATCHPOINT_CAPABILITY_FLAG_READ_WRITE:
|
||||
{
|
||||
return "read/write";
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Team* fTeam;
|
||||
BObjectList<UserBreakpoint> fBreakpoints;
|
||||
BObjectList<Watchpoint> fWatchpoints;
|
||||
BreakpointProxyList fBreakpointProxies;
|
||||
};
|
||||
|
||||
|
||||
@ -264,7 +340,6 @@ BreakpointListView::BreakpointListView(Team* team, Listener* listener)
|
||||
:
|
||||
BGroupView(B_VERTICAL),
|
||||
fTeam(team),
|
||||
fBreakpoint(NULL),
|
||||
fBreakpointsTable(NULL),
|
||||
fBreakpointsTableModel(NULL),
|
||||
fListener(listener)
|
||||
@ -280,12 +355,12 @@ BreakpointListView::~BreakpointListView()
|
||||
|
||||
|
||||
/*static*/ BreakpointListView*
|
||||
BreakpointListView::Create(Team* team, Listener* listener)
|
||||
BreakpointListView::Create(Team* team, Listener* listener, BView* filterTarget)
|
||||
{
|
||||
BreakpointListView* self = new BreakpointListView(team, listener);
|
||||
|
||||
try {
|
||||
self->_Init();
|
||||
self->_Init(filterTarget);
|
||||
} catch (...) {
|
||||
delete self;
|
||||
throw;
|
||||
@ -302,46 +377,19 @@ BreakpointListView::UnsetListener()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint)
|
||||
{
|
||||
if (breakpoint == fBreakpoint)
|
||||
return;
|
||||
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->ReleaseReference();
|
||||
|
||||
fBreakpoint = breakpoint;
|
||||
|
||||
if (fBreakpoint != NULL) {
|
||||
fBreakpoint->AcquireReference();
|
||||
|
||||
for (int32 i = 0;
|
||||
UserBreakpoint* other = fBreakpointsTableModel->BreakpointAt(i);
|
||||
i++) {
|
||||
if (fBreakpoint == other) {
|
||||
fBreakpointsTable->SelectRow(i, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fBreakpointsTable->DeselectAllRows();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
||||
{
|
||||
fBreakpointsTableModel->UpdateBreakpoint(breakpoint);
|
||||
BreakpointProxy proxy(breakpoint, NULL);
|
||||
fBreakpointsTableModel->UpdateBreakpoint(&proxy);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointListView::WatchpointChanged(Watchpoint* watchpoint)
|
||||
{
|
||||
fBreakpointsTableModel->UpdateWatchpoint(watchpoint);
|
||||
BreakpointProxy proxy(NULL, watchpoint);
|
||||
fBreakpointsTableModel->UpdateBreakpoint(&proxy);
|
||||
}
|
||||
|
||||
|
||||
@ -378,20 +426,22 @@ BreakpointListView::TableSelectionChanged(Table* table)
|
||||
return;
|
||||
|
||||
TableSelectionModel* selectionModel = table->SelectionModel();
|
||||
UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt(
|
||||
selectionModel->RowAt(0));
|
||||
if (breakpoint != NULL)
|
||||
fListener->BreakpointSelectionChanged(breakpoint);
|
||||
else {
|
||||
Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt(
|
||||
selectionModel->RowAt(0));
|
||||
fListener->WatchpointSelectionChanged(watchpoint);
|
||||
BreakpointProxyList proxyList;
|
||||
for (int32 i = 0; i < selectionModel->CountRows(); i++) {
|
||||
BreakpointProxy* proxy = fBreakpointsTableModel->BreakpointProxyAt(
|
||||
selectionModel->RowAt(i));
|
||||
if (proxy == NULL)
|
||||
continue;
|
||||
if (!proxyList.AddItem(proxy))
|
||||
return;
|
||||
}
|
||||
|
||||
fListener->BreakpointSelectionChanged(proxyList);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointListView::_Init()
|
||||
BreakpointListView::_Init(BView* filterTarget)
|
||||
{
|
||||
fBreakpointsTable = new Table("breakpoints list", 0, B_FANCY_BORDER);
|
||||
AddChild(fBreakpointsTable->ToView());
|
||||
@ -399,17 +449,15 @@ BreakpointListView::_Init()
|
||||
// columns
|
||||
fBreakpointsTable->AddColumn(new BoolStringTableColumn(0, "State", 70, 20,
|
||||
1000, "Enabled", "Disabled"));
|
||||
fBreakpointsTable->AddColumn(new StringTableColumn(1, "Function", 250, 40,
|
||||
fBreakpointsTable->AddColumn(new StringTableColumn(1, "Location", 250, 40,
|
||||
1000, B_TRUNCATE_END, B_ALIGN_LEFT));
|
||||
fBreakpointsTable->AddColumn(new StringTableColumn(2, "File", 250, 40,
|
||||
1000, B_TRUNCATE_END, B_ALIGN_LEFT));
|
||||
fBreakpointsTable->AddColumn(new Int32TableColumn(3, "Line", 60, 20,
|
||||
1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
|
||||
fBreakpointsTable->AddColumn(new TargetAddressTableColumn(4, "Address", 100,
|
||||
20, 1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
|
||||
fBreakpointsTable->AddColumn(new StringTableColumn(2, "File:Line/Address",
|
||||
250, 40, 1000, B_TRUNCATE_END, B_ALIGN_LEFT));
|
||||
|
||||
fBreakpointsTable->SetSelectionMode(B_SINGLE_SELECTION_LIST);
|
||||
fBreakpointsTable->SetSelectionMode(B_MULTIPLE_SELECTION_LIST);
|
||||
fBreakpointsTable->AddTableListener(this);
|
||||
fBreakpointsTable->AddFilter(new ListInputFilter(filterTarget));
|
||||
|
||||
|
||||
fBreakpointsTableModel = new BreakpointsTableModel(fTeam);
|
||||
fBreakpointsTable->SetTableModel(fBreakpointsTableModel);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BREAKPOINT_LIST_VIEW_H
|
||||
@ -16,6 +17,31 @@ class UserBreakpoint;
|
||||
class Watchpoint;
|
||||
|
||||
|
||||
enum breakpoint_proxy_type {
|
||||
BREAKPOINT_PROXY_TYPE_BREAKPOINT = 0,
|
||||
BREAKPOINT_PROXY_TYPE_WATCHPOINT = 1
|
||||
};
|
||||
|
||||
|
||||
class BreakpointProxy : public BReferenceable {
|
||||
public:
|
||||
BreakpointProxy(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint);
|
||||
~BreakpointProxy();
|
||||
|
||||
breakpoint_proxy_type Type() const;
|
||||
|
||||
UserBreakpoint* GetBreakpoint() const { return fBreakpoint; }
|
||||
Watchpoint* GetWatchpoint() const { return fWatchpoint; }
|
||||
|
||||
private:
|
||||
UserBreakpoint* fBreakpoint;
|
||||
Watchpoint* fWatchpoint;
|
||||
};
|
||||
|
||||
typedef BObjectList<BreakpointProxy> BreakpointProxyList;
|
||||
|
||||
|
||||
class BreakpointListView : public BGroupView, private TableListener {
|
||||
public:
|
||||
class Listener;
|
||||
@ -25,14 +51,12 @@ public:
|
||||
Listener* listener);
|
||||
~BreakpointListView();
|
||||
|
||||
static BreakpointListView* Create(Team* team, Listener* listener);
|
||||
static BreakpointListView* Create(Team* team, Listener* listener,
|
||||
BView* filterTarget);
|
||||
// throws
|
||||
|
||||
void UnsetListener();
|
||||
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
void UserBreakpointChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
void WatchpointChanged(
|
||||
@ -43,17 +67,16 @@ public:
|
||||
|
||||
private:
|
||||
class BreakpointsTableModel;
|
||||
class ListInputFilter;
|
||||
|
||||
private:
|
||||
// TableListener
|
||||
virtual void TableSelectionChanged(Table* table);
|
||||
|
||||
void _Init();
|
||||
void _Init(BView* filterTarget);
|
||||
|
||||
private:
|
||||
Team* fTeam;
|
||||
UserBreakpoint* fBreakpoint;
|
||||
Watchpoint* fWatchpoint;
|
||||
Table* fBreakpointsTable;
|
||||
BreakpointsTableModel* fBreakpointsTableModel;
|
||||
Listener* fListener;
|
||||
@ -65,10 +88,7 @@ public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint) = 0;
|
||||
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* watchpoint) = 0;
|
||||
BreakpointProxyList& breakpoints) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2011-2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -27,8 +27,6 @@ BreakpointsView::BreakpointsView(Team* team, Listener* listener)
|
||||
:
|
||||
BGroupView(B_HORIZONTAL, 4.0f),
|
||||
fTeam(team),
|
||||
fBreakpoint(NULL),
|
||||
fWatchpoint(NULL),
|
||||
fListView(NULL),
|
||||
fToggleBreakpointButton(NULL),
|
||||
fRemoveBreakpointButton(NULL),
|
||||
@ -68,32 +66,6 @@ BreakpointsView::UnsetListener()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint)
|
||||
{
|
||||
if (breakpoint == fBreakpoint && watchpoint == fWatchpoint)
|
||||
return;
|
||||
|
||||
if (fWatchpoint != NULL)
|
||||
fWatchpoint->ReleaseReference();
|
||||
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->ReleaseReference();
|
||||
|
||||
fWatchpoint = watchpoint;
|
||||
fBreakpoint = breakpoint;
|
||||
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->AcquireReference();
|
||||
else if (fWatchpoint != NULL)
|
||||
fWatchpoint->AcquireReference();
|
||||
|
||||
fListView->SetBreakpoint(breakpoint, watchpoint);
|
||||
|
||||
_UpdateButtons();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
||||
{
|
||||
@ -117,35 +89,9 @@ BreakpointsView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_ENABLE_BREAKPOINT:
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||
true);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||
true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSG_DISABLE_BREAKPOINT:
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||
false);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||
false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSG_CLEAR_BREAKPOINT:
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->ClearBreakpointRequested(fBreakpoint);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->ClearWatchpointRequested(fWatchpoint);
|
||||
}
|
||||
}
|
||||
_HandleBreakpointAction(message->what);
|
||||
break;
|
||||
default:
|
||||
BGroupView::MessageReceived(message);
|
||||
@ -187,18 +133,12 @@ BreakpointsView::SaveSettings(BMessage& settings)
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
|
||||
BreakpointsView::BreakpointSelectionChanged(BreakpointProxyList& proxies)
|
||||
{
|
||||
if (fListener != NULL)
|
||||
fListener->BreakpointSelectionChanged(breakpoint);
|
||||
}
|
||||
fListener->BreakpointSelectionChanged(proxies);
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint)
|
||||
{
|
||||
if (fListener != NULL)
|
||||
fListener->WatchpointSelectionChanged(watchpoint);
|
||||
_SetSelection(proxies);
|
||||
}
|
||||
|
||||
|
||||
@ -206,7 +146,7 @@ void
|
||||
BreakpointsView::_Init()
|
||||
{
|
||||
BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0.0f)
|
||||
.Add(fListView = BreakpointListView::Create(fTeam, this))
|
||||
.Add(fListView = BreakpointListView::Create(fTeam, this, this))
|
||||
.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
|
||||
.SetInsets(B_USE_SMALL_SPACING)
|
||||
.Add(fToggleBreakpointButton = new BButton("Toggle"))
|
||||
@ -226,19 +166,44 @@ BreakpointsView::_UpdateButtons()
|
||||
{
|
||||
AutoLocker<Team> teamLocker(fTeam);
|
||||
|
||||
bool enabled = false;
|
||||
bool hasEnabled = false;
|
||||
bool hasDisabled = false;
|
||||
bool valid = false;
|
||||
|
||||
if (fBreakpoint != NULL && fBreakpoint->IsValid()) {
|
||||
valid = true;
|
||||
enabled = fBreakpoint->IsEnabled();
|
||||
} else if (fWatchpoint != NULL) {
|
||||
valid = true;
|
||||
enabled = fWatchpoint->IsEnabled();
|
||||
for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) {
|
||||
BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i);
|
||||
switch (proxy->Type()) {
|
||||
case BREAKPOINT_PROXY_TYPE_BREAKPOINT:
|
||||
{
|
||||
UserBreakpoint* breakpoint = proxy->GetBreakpoint();
|
||||
if (breakpoint->IsValid()) {
|
||||
valid = true;
|
||||
if (breakpoint->IsEnabled())
|
||||
hasEnabled = true;
|
||||
else
|
||||
hasDisabled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BREAKPOINT_PROXY_TYPE_WATCHPOINT:
|
||||
{
|
||||
Watchpoint* watchpoint = proxy->GetWatchpoint();
|
||||
valid = true;
|
||||
if (watchpoint->IsEnabled())
|
||||
hasEnabled = true;
|
||||
else
|
||||
hasDisabled = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (enabled) {
|
||||
// if we have at least one disabled breakpoint in the
|
||||
// selection, we leave the button as an Enable button
|
||||
if (hasEnabled && !hasDisabled) {
|
||||
fToggleBreakpointButton->SetLabel("Disable");
|
||||
fToggleBreakpointButton->SetMessage(
|
||||
new BMessage(MSG_DISABLE_BREAKPOINT));
|
||||
@ -258,6 +223,56 @@ BreakpointsView::_UpdateButtons()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::_SetSelection(BreakpointProxyList& proxies)
|
||||
{
|
||||
for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++)
|
||||
fSelectedBreakpoints.ItemAt(i)->ReleaseReference();
|
||||
|
||||
fSelectedBreakpoints.MakeEmpty();
|
||||
|
||||
for (int32 i = 0; i < proxies.CountItems(); i++) {
|
||||
BreakpointProxy* proxy = proxies.ItemAt(i);
|
||||
if (!fSelectedBreakpoints.AddItem(proxy))
|
||||
return;
|
||||
proxy->AcquireReference();
|
||||
}
|
||||
|
||||
_UpdateButtons();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::_HandleBreakpointAction(uint32 action)
|
||||
{
|
||||
if (fListener == NULL)
|
||||
return;
|
||||
|
||||
for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) {
|
||||
BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i);
|
||||
if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT) {
|
||||
UserBreakpoint* breakpoint = proxy->GetBreakpoint();
|
||||
if (action == MSG_ENABLE_BREAKPOINT && !breakpoint->IsEnabled())
|
||||
fListener->SetBreakpointEnabledRequested(breakpoint, true);
|
||||
else if (action == MSG_DISABLE_BREAKPOINT
|
||||
&& breakpoint->IsEnabled()) {
|
||||
fListener->SetBreakpointEnabledRequested(breakpoint, false);
|
||||
} else if (action == MSG_CLEAR_BREAKPOINT)
|
||||
fListener->ClearBreakpointRequested(breakpoint);
|
||||
} else {
|
||||
Watchpoint* watchpoint = proxy->GetWatchpoint();
|
||||
if (action == MSG_ENABLE_BREAKPOINT && !watchpoint->IsEnabled())
|
||||
fListener->SetWatchpointEnabledRequested(watchpoint, true);
|
||||
else if (action == MSG_DISABLE_BREAKPOINT
|
||||
&& watchpoint->IsEnabled()) {
|
||||
fListener->SetWatchpointEnabledRequested(watchpoint, false);
|
||||
} else if (action == MSG_CLEAR_BREAKPOINT)
|
||||
fListener->ClearWatchpointRequested(watchpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Listener
|
||||
|
||||
|
||||
|
@ -28,9 +28,6 @@ public:
|
||||
|
||||
void UnsetListener();
|
||||
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
void UserBreakpointChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
void WatchpointChanged(
|
||||
@ -45,19 +42,18 @@ public:
|
||||
private:
|
||||
// BreakpointListView::Listener
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* watchpoint);
|
||||
BreakpointProxyList& proxies);
|
||||
|
||||
void _Init();
|
||||
|
||||
void _UpdateButtons();
|
||||
|
||||
void _SetSelection(BreakpointProxyList& proxies);
|
||||
void _HandleBreakpointAction(uint32 action);
|
||||
private:
|
||||
Team* fTeam;
|
||||
UserBreakpoint* fBreakpoint;
|
||||
Watchpoint* fWatchpoint;
|
||||
BreakpointListView* fListView;
|
||||
BreakpointProxyList fSelectedBreakpoints;
|
||||
BButton* fToggleBreakpointButton;
|
||||
BButton* fRemoveBreakpointButton;
|
||||
Listener* fListener;
|
||||
@ -70,15 +66,13 @@ public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint) = 0;
|
||||
BreakpointProxyList& proxies) = 0;
|
||||
virtual void SetBreakpointEnabledRequested(
|
||||
UserBreakpoint* breakpoint,
|
||||
bool enabled) = 0;
|
||||
virtual void ClearBreakpointRequested(
|
||||
UserBreakpoint* breakpoint) = 0;
|
||||
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* Watchpoint) = 0;
|
||||
virtual void SetWatchpointEnabledRequested(
|
||||
Watchpoint* breakpoint,
|
||||
bool enabled) = 0;
|
||||
|
@ -610,9 +610,17 @@ TeamWindow::FunctionSelectionChanged(FunctionInstance* function)
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
|
||||
TeamWindow::BreakpointSelectionChanged(BreakpointProxyList &proxies)
|
||||
{
|
||||
_SetActiveBreakpoint(breakpoint);
|
||||
if (proxies.CountItems() == 0 && fActiveBreakpoint != NULL) {
|
||||
fActiveBreakpoint->ReleaseReference();
|
||||
fActiveBreakpoint = NULL;
|
||||
} else if (proxies.CountItems() == 1) {
|
||||
BreakpointProxy* proxy = proxies.ItemAt(0);
|
||||
if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT)
|
||||
_SetActiveBreakpoint(proxy->GetBreakpoint());
|
||||
}
|
||||
// if more than one item is selected, do nothing.
|
||||
}
|
||||
|
||||
|
||||
@ -653,13 +661,6 @@ TeamWindow::ThreadActionRequested(::Thread* thread, uint32 action,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint)
|
||||
{
|
||||
fBreakpointsView->SetBreakpoint(NULL, watchpoint);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
|
||||
bool enabled)
|
||||
@ -1041,8 +1042,6 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
|
||||
// automatically, if the active function remains the same)
|
||||
_ScrollToActiveFunction();
|
||||
}
|
||||
|
||||
fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,15 +88,13 @@ private:
|
||||
|
||||
// BreakpointsView::Listener
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
BreakpointProxyList& proxies);
|
||||
virtual void SetBreakpointEnabledRequested(
|
||||
UserBreakpoint* breakpoint,
|
||||
bool enabled);
|
||||
virtual void ClearBreakpointRequested(
|
||||
UserBreakpoint* breakpoint);
|
||||
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* Watchpoint);
|
||||
virtual void SetWatchpointEnabledRequested(
|
||||
Watchpoint* breakpoint,
|
||||
bool enabled);
|
||||
|
Loading…
Reference in New Issue
Block a user