* Introduce TeamMemoryBlock[Manager]. These provide an interface to raw memory

page data of the target team.
* Jobs: Add RetrieveMemoryBlockJob which performs a background read of the
  target team's memory. Used by InspectRequested() to perform the actual work.
* TeamDebugger: Added InspectRequested() hooks to allow clients to ask for
  a memory read to be performed.
* Introduce InspectorWindow and MemoryView to form the basis of a memory inspector.
  As yet these are more or less stubs and not yet hooked in.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42080 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent
2011-06-10 01:58:39 +00:00
parent a99d0dd7b7
commit 3e3ce16f5e
15 changed files with 929 additions and 3 deletions
+8 -1
View File
@@ -20,6 +20,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui inspector_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ;
@@ -54,6 +55,7 @@ Application Debugger :
BreakpointManager.cpp
Debugger.cpp
Jobs.cpp
TeamMemoryBlockManager.cpp
TeamDebugger.cpp
ThreadHandler.cpp
Worker.cpp
@@ -127,6 +129,7 @@ Application Debugger :
UserBreakpoint.cpp
Team.cpp
TeamMemory.cpp
TeamMemoryBlock.cpp
Thread.cpp
ThreadInfo.cpp
Type.cpp
@@ -167,6 +170,10 @@ Application Debugger :
VariablesViewState.cpp
VariablesViewStateHistory.cpp
# user_interface/gui/inspector_window
InspectorWindow.cpp
MemoryView.cpp
# user_interface/gui/teams_window
TeamsWindow.cpp
TeamsListView.cpp
@@ -253,7 +260,7 @@ Application Debugger :
libshared.a
$(TARGET_LIBSTDC++)
be tracker libdebug.so
be tracker libdebug.so libshared.a libexpression_parser.a libmapm.a
: Debugger.rdef
;
+40
View File
@@ -24,6 +24,8 @@
#include "StackFrameValues.h"
#include "StackTrace.h"
#include "Team.h"
#include "TeamMemory.h"
#include "TeamMemoryBlock.h"
#include "TeamDebugInfo.h"
#include "Thread.h"
#include "Tracing.h"
@@ -633,3 +635,41 @@ ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
return nodeResolutionState != VALUE_NODE_UNRESOLVED
? nodeResolutionState : B_ERROR;
}
RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(TeamMemory* teamMemory,
TeamMemoryBlock* memoryBlock)
:
fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK),
fTeamMemory(teamMemory),
fMemoryBlock(memoryBlock)
{
fMemoryBlock->AcquireReference();
}
RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob()
{
fMemoryBlock->ReleaseReference();
}
const JobKey&
RetrieveMemoryBlockJob::Key() const
{
return fKey;
}
status_t
RetrieveMemoryBlockJob::Do()
{
ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(),
fMemoryBlock->Data(), fMemoryBlock->Size());
if (result < 0)
return result;
fMemoryBlock->MarkValid();
return B_OK;
}
+23 -1
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2011, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef JOBS_H
@@ -7,6 +8,7 @@
#include "ImageDebugInfoProvider.h"
#include "Types.h"
#include "Worker.h"
@@ -20,6 +22,8 @@ class Image;
class StackFrame;
class StackFrameValues;
class Team;
class TeamMemory;
class TeamMemoryBlock;
class Thread;
class Type;
class TypeComponentPath;
@@ -38,7 +42,8 @@ enum {
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
JOB_TYPE_LOAD_SOURCE_CODE,
JOB_TYPE_GET_STACK_FRAME_VALUE,
JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
JOB_TYPE_RESOLVE_VALUE_NODE_VALUE,
JOB_TYPE_GET_MEMORY_BLOCK
};
@@ -177,4 +182,21 @@ private:
};
class RetrieveMemoryBlockJob : public Job {
public:
RetrieveMemoryBlockJob(
TeamMemory* teamMemory,
TeamMemoryBlock* memoryBlock);
virtual ~RetrieveMemoryBlockJob();
virtual const JobKey& Key() const;
virtual status_t Do();
private:
SimpleJobKey fKey;
TeamMemory* fTeamMemory;
TeamMemoryBlock* fMemoryBlock;
};
#endif // JOBS_H
+3 -1
View File
@@ -44,7 +44,9 @@ enum {
MSG_TEAM_DEBUGGER_QUIT = 'dbqt',
MSG_SHOW_TEAMS_WINDOW = 'stsw',
MSG_TEAMS_WINDOW_CLOSED = 'tswc',
MSG_DEBUG_THIS_TEAM = 'dbtt'
MSG_DEBUG_THIS_TEAM = 'dbtt',
MSG_INSPECTOR_WINDOW_CLOSED = 'irwc',
MSG_INSPECT_ADDRESS = 'isad'
};
+107
View File
@@ -14,6 +14,7 @@
#include <Message.h>
#include <ExpressionParser.h>
#include <AutoLocker.h>
#include "debug_utils.h"
@@ -37,6 +38,8 @@
#include "Statement.h"
#include "SymbolInfo.h"
#include "TeamDebugInfo.h"
#include "TeamMemoryBlock.h"
#include "TeamMemoryBlockManager.h"
#include "TeamSettings.h"
#include "Tracing.h"
#include "ValueNode.h"
@@ -446,6 +449,26 @@ TeamDebugger::MessageReceived(BMessage* message)
break;
}
case MSG_INSPECT_ADDRESS:
{
TeamMemoryBlock::Listener* listener;
if (message->FindPointer("listener",
reinterpret_cast<void **>(&listener)) != B_OK) {
break;
}
const char* addressExpression;
target_addr_t address;
if (message->FindString("addressExpression",
&addressExpression) == B_OK) {
_HandleInspectAddress(addressExpression, listener);
} else if (message->FindUInt64("address",
&address) == B_OK) {
_HandleInspectAddress(address, listener);
}
break;
}
case MSG_THREAD_STATE_CHANGED:
{
int32 threadID;
@@ -661,6 +684,28 @@ TeamDebugger::ClearBreakpointRequested(UserBreakpoint* breakpoint)
}
void
TeamDebugger::InspectRequested(const char* addressExpression,
TeamMemoryBlock::Listener *listener)
{
BMessage message(MSG_INSPECT_ADDRESS);
message.AddString("addressExpression", addressExpression);
message.AddPointer("listener", listener);
PostMessage(&message);
}
void
TeamDebugger::InspectRequested(target_addr_t address,
TeamMemoryBlock::Listener *listener)
{
BMessage message(MSG_INSPECT_ADDRESS);
message.AddUInt64("address", address);
message.AddPointer("listener", listener);
PostMessage(&message);
}
bool
TeamDebugger::UserInterfaceQuitRequested()
{
@@ -1243,6 +1288,68 @@ TeamDebugger::_HandleClearUserBreakpoint(UserBreakpoint* breakpoint)
}
void
TeamDebugger::_HandleInspectAddress(const char* addressExpression,
TeamMemoryBlock::Listener* listener)
{
TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%s, %p)\n",
addressExpression, listener);
ExpressionParser parser;
parser.SetSupportHexInput(true);
target_addr_t address = 0LL;
try {
address = parser.EvaluateToInt64(addressExpression);
} catch(ParseException parseError) {
_NotifyUser("Inspect Address", "Failed to parse address: %s",
parseError.message.String());
return;
} catch(...) {
_NotifyUser("Inspect Address", "Unknown error while parsing address");
return;
}
_HandleInspectAddress(address, listener);
}
void
TeamDebugger::_HandleInspectAddress(target_addr_t address,
TeamMemoryBlock::Listener* listener)
{
TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(" B_PRIx64 ", %p)\n",
addressExpression, listener);
TeamMemoryBlock* memoryBlock = fMemoryBlockManager
->GetMemoryBlock(address);
if (memoryBlock == NULL) {
_NotifyUser("Inspect Address", "Failed to allocate memory block");
return;
}
if (!memoryBlock->HasListener(listener))
memoryBlock->AddListener(listener);
if (!memoryBlock->IsValid()) {
AutoLocker< ::Team> teamLocker(fTeam);
TeamMemory* memory = fTeam->GetTeamMemory();
// schedule the job
status_t result;
if ((result = fWorker->ScheduleJob(
new(std::nothrow) RetrieveMemoryBlockJob(memory, memoryBlock),
this)) != B_OK) {
memoryBlock->ReleaseReference();
_NotifyUser("Inspect Address", "Failed to retrieve memory data: %s",
strerror(result));
}
} else
memoryBlock->NotifyDataRetrieved();
}
ThreadHandler*
TeamDebugger::_GetThreadHandler(thread_id threadID)
{
+14
View File
@@ -22,6 +22,7 @@ class DebuggerInterface;
class FileManager;
class SettingsManager;
class TeamDebugInfo;
class TeamMemoryBlockManager;
class TeamDebugger : public BLooper, private UserInterfaceListener,
@@ -65,6 +66,10 @@ private:
virtual void ClearBreakpointRequested(target_addr_t address);
virtual void ClearBreakpointRequested(
UserBreakpoint* breakpoint);
virtual void InspectRequested(target_addr_t address,
TeamMemoryBlock::Listener* listener);
virtual void InspectRequested(const char* addressExpression,
TeamMemoryBlock::Listener* listener);
virtual bool UserInterfaceQuitRequested();
// JobListener
@@ -118,6 +123,13 @@ private:
void _HandleClearUserBreakpoint(
UserBreakpoint* breakpoint);
void _HandleInspectAddress(
target_addr_t address,
TeamMemoryBlock::Listener* listener);
void _HandleInspectAddress(
const char* addressExpression,
TeamMemoryBlock::Listener* listener);
ThreadHandler* _GetThreadHandler(thread_id threadID);
status_t _AddImage(const ImageInfo& imageInfo,
@@ -142,6 +154,8 @@ private:
FileManager* fFileManager;
Worker* fWorker;
BreakpointManager* fBreakpointManager;
TeamMemoryBlockManager*
fMemoryBlockManager;
thread_id fDebugEventListener;
UserInterface* fUserInterface;
volatile bool fTerminating;
@@ -0,0 +1,208 @@
/*
* Copyright 2011, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TeamMemoryBlockManager.h"
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "TeamMemoryBlock.h"
struct TeamMemoryBlockManager::Key {
target_addr_t address;
Key(target_addr_t address)
:
address(address)
{
}
uint32 HashValue() const
{
return (uint32)address;
}
bool operator==(const Key& other) const
{
return address == other.address;
}
};
struct TeamMemoryBlockManager::MemoryBlockEntry : Key {
TeamMemoryBlock* block;
MemoryBlockEntry* next;
MemoryBlockEntry(TeamMemoryBlock* block)
:
Key(block->BaseAddress()),
block(block)
{
block->AcquireReference();
}
~MemoryBlockEntry()
{
block->ReleaseReference();
}
};
struct TeamMemoryBlockManager::MemoryBlockHashDefinition {
typedef Key KeyType;
typedef MemoryBlockEntry ValueType;
size_t HashKey(const Key& key) const
{
return key.HashValue();
}
size_t Hash(const MemoryBlockEntry* value) const
{
return value->HashValue();
}
bool Compare(const Key& key, const MemoryBlockEntry* value) const
{
return key == *value;
}
MemoryBlockEntry*& GetLink(MemoryBlockEntry* value) const
{
return value->next;
}
};
TeamMemoryBlockManager::TeamMemoryBlockManager()
:
fActiveBlocks(NULL),
fDeadBlocks(NULL)
{
}
TeamMemoryBlockManager::~TeamMemoryBlockManager()
{
_Cleanup();
}
status_t
TeamMemoryBlockManager::Init()
{
status_t result = fLock.InitCheck();
if (result != B_OK)
return result;
fActiveBlocks = new(std::nothrow) MemoryBlockTable();
if (fActiveBlocks == NULL)
return B_NO_MEMORY;
ObjectDeleter<MemoryBlockTable> activeDeleter(fActiveBlocks);
result = fActiveBlocks->Init();
if (result != B_OK)
return result;
fDeadBlocks = new(std::nothrow) MemoryBlockTable();
if (fDeadBlocks == NULL)
return B_NO_MEMORY;
ObjectDeleter<MemoryBlockTable> deadDeleter(fDeadBlocks);
result = fDeadBlocks->Init();
if (result != B_OK)
return result;
activeDeleter.Detach();
deadDeleter.Detach();
return B_OK;
}
TeamMemoryBlock*
TeamMemoryBlockManager::GetMemoryBlock(target_addr_t address)
{
AutoLocker<BLocker> lock(fLock);
address &= ~B_PAGE_SIZE - 1;
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry == NULL) {
TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address,
this);
if (block == NULL)
return NULL;
entry = new(std::nothrow) MemoryBlockEntry(block);
if (entry == NULL) {
delete block;
return NULL;
}
fActiveBlocks->Insert(entry);
}
int32 refCount = entry->block->AcquireReference();
if (refCount == 0) {
// this block already had its last reference released,
// move it to the dead list and retrieve a new one instead.
_MarkDeadBlock(address);
return GetMemoryBlock(address);
}
return entry->block;
}
void
TeamMemoryBlockManager::_Cleanup()
{
if (fActiveBlocks != NULL) {
MemoryBlockEntry* entry = fActiveBlocks->Clear(true);
while (entry != NULL) {
MemoryBlockEntry* next = entry->next;
delete entry;
entry = next;
}
delete fActiveBlocks;
fActiveBlocks = NULL;
}
}
void
TeamMemoryBlockManager::_MarkDeadBlock(target_addr_t address)
{
AutoLocker<BLocker> lock(fLock);
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry != NULL) {
fActiveBlocks->Remove(entry);
fDeadBlocks->Insert(entry);
}
}
void
TeamMemoryBlockManager::_RemoveBlock(target_addr_t address)
{
AutoLocker<BLocker> lock(fLock);
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
if (entry != NULL) {
fActiveBlocks->Remove(entry);
delete entry;
return;
}
entry = fDeadBlocks->Lookup(address);
if (entry != NULL) {
fDeadBlocks->Remove(entry);
delete entry;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2011, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_MEMORY_BLOCK_MANAGER_H
#define TEAM_MEMORY_BLOCK_MANAGER_H
#include <Locker.h>
#include <Referenceable.h>
#include <util/OpenHashTable.h>
#include "Types.h"
struct MemoryBlockHashDefinition;
class TeamMemoryBlock;
class TeamMemoryBlockManager
{
public:
TeamMemoryBlockManager();
~TeamMemoryBlockManager();
status_t Init();
TeamMemoryBlock* GetMemoryBlock(target_addr_t address);
private:
struct Key;
struct MemoryBlockEntry;
struct MemoryBlockHashDefinition;
typedef BOpenHashTable<MemoryBlockHashDefinition> MemoryBlockTable;
private:
void _Cleanup();
void _MarkDeadBlock(target_addr_t address);
void _RemoveBlock(target_addr_t address);
private:
friend class TeamMemoryBlock;
private:
BLocker fLock;
MemoryBlockTable* fActiveBlocks;
MemoryBlockTable* fDeadBlocks;
};
#endif // TEAM_MEMORY_BLOCK_MANAGER_H
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright 2011, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TeamMemoryBlock.h"
#include <AutoLocker.h>
#include "TeamMemoryBlockManager.h"
// #pragma mark - TeamMemoryBlock
TeamMemoryBlock::TeamMemoryBlock(target_addr_t baseAddress,
TeamMemoryBlockManager* manager)
:
fValid(false),
fBaseAddress(baseAddress),
fBlockManager(manager)
{
}
TeamMemoryBlock::~TeamMemoryBlock()
{
}
void
TeamMemoryBlock::AddListener(Listener* listener)
{
AutoLocker<BLocker> lock(fLock);
fListeners.Add(listener);
}
bool
TeamMemoryBlock::HasListener(Listener* listener)
{
AutoLocker<BLocker> lock(fLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (iterator.HasNext()) {
if (iterator.Next() == listener)
return true;
}
return false;
}
void
TeamMemoryBlock::RemoveListener(Listener* listener)
{
AutoLocker<BLocker> lock(fLock);
fListeners.Remove(listener);
}
void
TeamMemoryBlock::MarkValid()
{
fValid = true;
NotifyDataRetrieved();
}
void
TeamMemoryBlock::Invalidate()
{
fValid = false;
}
void
TeamMemoryBlock::NotifyDataRetrieved()
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->MemoryBlockRetrieved(this);
}
}
void
TeamMemoryBlock::LastReferenceReleased()
{
fBlockManager->_RemoveBlock(fBaseAddress);
BReferenceable::LastReferenceReleased();
}
// #pragma mark - TeamMemoryBlock
TeamMemoryBlock::Listener::~Listener()
{
}
void
TeamMemoryBlock::Listener::MemoryBlockRetrieved(TeamMemoryBlock* block)
{
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright 2011, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_MEMORY_BLOCK_H
#define TEAM_MEMORY_BLOCK_H
#include <OS.h>
#include <Locker.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include "Types.h"
class TeamMemoryBlockManager;
class TeamMemoryBlock : public BReferenceable {
public:
class Listener;
public:
TeamMemoryBlock(target_addr_t baseAddress,
TeamMemoryBlockManager* manager);
~TeamMemoryBlock();
void AddListener(Listener* listener);
bool HasListener(Listener* listener);
void RemoveListener(Listener* listener);
bool IsValid() const { return fValid; };
void MarkValid();
void Invalidate();
target_addr_t BaseAddress() const { return fBaseAddress; };
uint8* Data() { return fData; };
size_t Size() const { return sizeof(fData); };
void NotifyDataRetrieved();
protected:
virtual void LastReferenceReleased();
private:
typedef DoublyLinkedList<Listener> ListenerList;
private:
bool fValid;
target_addr_t fBaseAddress;
uint8 fData[B_PAGE_SIZE];
ListenerList fListeners;
TeamMemoryBlockManager*
fBlockManager;
BLocker fLock;
};
class TeamMemoryBlock::Listener : public DoublyLinkedListLinkImpl<Listener> {
public:
virtual ~Listener();
virtual void MemoryBlockRetrieved(TeamMemoryBlock* block);
};
#endif // TEAM_MEMORY_BLOCK_H
@@ -10,6 +10,7 @@
#include <Referenceable.h>
#include "TeamMemoryBlock.h"
#include "Types.h"
@@ -82,6 +83,13 @@ public:
UserBreakpoint* breakpoint) = 0;
// TODO: Consolidate those!
virtual void InspectRequested(
target_addr_t address,
TeamMemoryBlock::Listener* listener) = 0;
virtual void InspectRequested(
const char* addressExpression,
TeamMemoryBlock::Listener* listener) = 0;
virtual bool UserInterfaceQuitRequested() = 0;
};
@@ -0,0 +1,92 @@
/*
* Copyright 2011, Rene Gollent, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "InspectorWindow.h"
#include <Application.h>
#include <Button.h>
#include <LayoutBuilder.h>
#include <ScrollView.h>
#include <TextControl.h>
#include <stdio.h>
#include "MemoryView.h"
#include "MessageCodes.h"
#include "UserInterface.h"
InspectorWindow::InspectorWindow(UserInterfaceListener* listener)
:
BWindow(BRect(100, 100, 500, 250), "Inspector", B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS),
fListener(listener)
{
}
InspectorWindow::~InspectorWindow()
{
}
/* static */ InspectorWindow*
InspectorWindow::Create(UserInterfaceListener* listener)
{
InspectorWindow* self = new InspectorWindow(listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
InspectorWindow::_Init()
{
BLayoutBuilder::Group<>(this, B_VERTICAL)
.Add(fAddressInput = new BTextControl("addrInput",
"Target Address:", "",
new BMessage(MSG_INSPECT_ADDRESS)))
.Add(fMemoryView = new MemoryView(NULL, NULL))
.End();
fAddressInput->SetTarget(this);
}
void
InspectorWindow::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case MSG_INSPECT_ADDRESS:
{
const char* addressExpression = fAddressInput->Text();
fListener->InspectRequested(addressExpression, this);
break;
}
}
}
bool
InspectorWindow::QuitRequested()
{
be_app_messenger.SendMessage(MSG_INSPECTOR_WINDOW_CLOSED);
return true;
}
void
InspectorWindow::MemoryBlockRetrieved(TeamMemoryBlock* block)
{
// TODO: implement
}
@@ -0,0 +1,45 @@
/*
* Copyright 2011, Rene Gollent, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef INSPECTOR_WINDOW_H
#define INSPECTOR_WINDOW_H
#include <Window.h>
#include "TeamMemoryBlock.h"
#include "Types.h"
class BButton;
class BTextControl;
class MemoryView;
class UserInterfaceListener;
class InspectorWindow : public BWindow,
public TeamMemoryBlock::Listener {
public:
InspectorWindow(
UserInterfaceListener* listener);
virtual ~InspectorWindow();
static InspectorWindow* Create(UserInterfaceListener* listener);
// throws
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
virtual void MemoryBlockRetrieved(TeamMemoryBlock* block);
private:
void _Init();
private:
UserInterfaceListener* fListener;
BTextControl* fAddressInput;
MemoryView* fMemoryView;
};
#endif // INSPECTOR_WINDOW_H
@@ -0,0 +1,96 @@
/*
* Copyright 2011, Rene Gollent, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "MemoryView.h"
MemoryView::MemoryView(Team* team, Listener* listener)
:
BView("memoryView", B_WILL_DRAW | B_SUBPIXEL_PRECISE),
fTeam(team),
fListener(listener)
{
}
MemoryView::~MemoryView()
{
UnsetListener();
}
/*static */ MemoryView*
MemoryView::Create(Team* team, Listener* listener)
{
MemoryView* self = new MemoryView(team, listener);
try {
self->_Init();
} catch(...) {
delete self;
throw;
}
return self;
}
void
MemoryView::UnsetListener()
{
fListener = NULL;
}
void
MemoryView::SetTargetAddress(target_addr_t address)
{
fTargetAddress = address;
Invalidate();
}
void
MemoryView::TargetAddressChanged(target_addr_t address)
{
SetTargetAddress(address);
}
void
MemoryView::TargetedByScrollView(BScrollView* scrollView)
{
BView::TargetedByScrollView(scrollView);
}
void
MemoryView::Draw(BRect rect)
{
BView::Draw(rect);
}
void
MemoryView::MessageReceived(BMessage* message)
{
switch(message->what) {
default:
BView::MessageReceived(message);
break;
}
}
void
MemoryView::_Init()
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
MemoryView::Listener::~Listener()
{
}
@@ -0,0 +1,57 @@
/*
* Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef MEMORY_VIEW_H
#define MEMORY_VIEW_H
#include <View.h>
#include "Team.h"
class MemoryView : public BView {
public:
class Listener;
public:
MemoryView(
Team* team, Listener* listener);
virtual ~MemoryView();
static MemoryView* Create(Team* team, Listener* listener);
// throws
void UnsetListener();
void SetTargetAddress(target_addr_t address);
void TargetAddressChanged(target_addr_t address);
virtual void TargetedByScrollView(BScrollView* scrollView);
virtual void Draw(BRect rect);
virtual void MessageReceived(BMessage* message);
private:
void _Init();
private:
Team* fTeam;
target_addr_t fTargetAddress;
Listener* fListener;
};
class MemoryView::Listener {
public:
virtual ~Listener();
virtual void SetTargetAddressRequested(
target_addr_t address) = 0;
};
#endif // MEMORY_VIEW_H