Pull a ValueNodeManager class out of VariableTableModel.
- The intention is to have a class which handles the actual management of the variable node graph, creating child nodes and such. This way the GUI, CLI and report generator don't have to each reimplement these low-level parts and can instead concentrate on their relevant representations thereof.
This commit is contained in:
parent
adf4c44437
commit
c1034c63fb
@ -263,6 +263,7 @@ Application Debugger :
|
||||
ValueLoader.cpp
|
||||
ValueNode.cpp
|
||||
ValueNodeContainer.cpp
|
||||
ValueNodeManager.cpp
|
||||
|
||||
# value/type_handlers
|
||||
BListTypeHandler.cpp
|
||||
|
234
src/apps/debugger/debug_managers/ValueNodeManager.cpp
Normal file
234
src/apps/debugger/debug_managers/ValueNodeManager.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "ValueNodeManager.h"
|
||||
|
||||
#include "AutoLocker.h"
|
||||
|
||||
#include "StackFrame.h"
|
||||
#include "Thread.h"
|
||||
#include "TypeHandlerRoster.h"
|
||||
#include "ValueNode.h"
|
||||
#include "Variable.h"
|
||||
#include "VariableValueNodeChild.h"
|
||||
|
||||
|
||||
ValueNodeManager::ValueNodeManager()
|
||||
:
|
||||
fContainer(NULL),
|
||||
fStackFrame(NULL),
|
||||
fThread(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueNodeManager::~ValueNodeManager()
|
||||
{
|
||||
SetStackFrame(NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueNodeManager::SetStackFrame(Thread* thread,
|
||||
StackFrame* stackFrame)
|
||||
{
|
||||
if (fContainer != NULL) {
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
fContainer->RemoveListener(this);
|
||||
|
||||
fContainer->RemoveAllChildren();
|
||||
containerLocker.Unlock();
|
||||
fContainer->ReleaseReference();
|
||||
fContainer = NULL;
|
||||
}
|
||||
|
||||
fStackFrame = stackFrame;
|
||||
fThread = thread;
|
||||
|
||||
if (fStackFrame != NULL) {
|
||||
fContainer = new(std::nothrow) ValueNodeContainer;
|
||||
if (fContainer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = fContainer->Init();
|
||||
if (error != B_OK) {
|
||||
delete fContainer;
|
||||
fContainer = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
fContainer->AddListener(this);
|
||||
|
||||
for (int32 i = 0; Variable* variable = fStackFrame->ParameterAt(i);
|
||||
i++) {
|
||||
_AddNode(variable);
|
||||
}
|
||||
|
||||
for (int32 i = 0; Variable* variable
|
||||
= fStackFrame->LocalVariableAt(i); i++) {
|
||||
_AddNode(variable);
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueNodeManager::AddListener(ValueNodeContainer::Listener* listener)
|
||||
{
|
||||
return fListeners.AddItem(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::RemoveListener(ValueNodeContainer::Listener* listener)
|
||||
{
|
||||
fListeners.RemoveItem(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::ValueNodeChanged(ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode)
|
||||
{
|
||||
if (fContainer == NULL)
|
||||
return;
|
||||
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
if (oldNode != NULL)
|
||||
newNode->CreateChildren();
|
||||
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::ValueNodeChildrenCreated(ValueNode* node)
|
||||
{
|
||||
if (fContainer == NULL)
|
||||
return;
|
||||
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChildrenCreated(node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::ValueNodeChildrenDeleted(ValueNode* node)
|
||||
{
|
||||
if (fContainer == NULL)
|
||||
return;
|
||||
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::ValueNodeValueChanged(ValueNode* valueNode)
|
||||
{
|
||||
if (fContainer == NULL)
|
||||
return;
|
||||
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
// check whether we know the node
|
||||
ValueNodeChild* nodeChild = valueNode->NodeChild();
|
||||
if (nodeChild == NULL)
|
||||
return;
|
||||
|
||||
if (valueNode->ChildCreationNeedsValue()
|
||||
&& !valueNode->ChildrenCreated()) {
|
||||
status_t error = valueNode->CreateChildren();
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
for (int32 i = 0; i < valueNode->CountChildren(); i++) {
|
||||
ValueNodeChild* child = valueNode->ChildAt(i);
|
||||
_CreateValueNode(child);
|
||||
AddChildNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeValueChanged(valueNode);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeManager::_AddNode(Variable* variable)
|
||||
{
|
||||
// create the node child for the variable
|
||||
ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild(
|
||||
variable);
|
||||
BReference<ValueNodeChild> nodeChildReference(nodeChild, true);
|
||||
if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) {
|
||||
delete nodeChild;
|
||||
return;
|
||||
}
|
||||
|
||||
// automatically add child nodes for the top level nodes
|
||||
AddChildNodes(nodeChild);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild)
|
||||
{
|
||||
if (nodeChild->Node() != NULL)
|
||||
return B_OK;
|
||||
|
||||
// create the node
|
||||
ValueNode* valueNode;
|
||||
status_t error;
|
||||
if (nodeChild->IsInternal()) {
|
||||
error = nodeChild->CreateInternalNode(valueNode);
|
||||
} else {
|
||||
error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
|
||||
nodeChild->GetType(), valueNode);
|
||||
}
|
||||
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
nodeChild->SetNode(valueNode);
|
||||
valueNode->ReleaseReference();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueNodeManager::AddChildNodes(ValueNodeChild* nodeChild)
|
||||
{
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
// create a value node for the value node child, if doesn't have one yet
|
||||
ValueNode* valueNode = nodeChild->Node();
|
||||
if (valueNode == NULL) {
|
||||
status_t error = _CreateValueNode(nodeChild);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
valueNode = nodeChild->Node();
|
||||
}
|
||||
|
||||
// check if this node requires child creation
|
||||
// to be deferred until after its location/value have been resolved
|
||||
if (valueNode->ChildCreationNeedsValue())
|
||||
return B_OK;
|
||||
|
||||
// create the children, if not done yet
|
||||
if (valueNode->ChildrenCreated())
|
||||
return B_OK;
|
||||
|
||||
return valueNode->CreateChildren();
|
||||
}
|
54
src/apps/debugger/debug_managers/ValueNodeManager.h
Normal file
54
src/apps/debugger/debug_managers/ValueNodeManager.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_NODE_MANAGER_H
|
||||
#define VALUE_NODE_MANAGER_H
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
class StackFrame;
|
||||
class Thread;
|
||||
class Variable;
|
||||
|
||||
|
||||
class ValueNodeManager : public BReferenceable,
|
||||
private ValueNodeContainer::Listener {
|
||||
public:
|
||||
ValueNodeManager();
|
||||
virtual ~ValueNodeManager();
|
||||
|
||||
status_t SetStackFrame(Thread* thread,
|
||||
StackFrame* frame);
|
||||
|
||||
bool AddListener(
|
||||
ValueNodeContainer::Listener* listener);
|
||||
void RemoveListener(
|
||||
ValueNodeContainer::Listener* listener);
|
||||
|
||||
virtual void ValueNodeChanged(ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode);
|
||||
virtual void ValueNodeChildrenCreated(ValueNode* node);
|
||||
virtual void ValueNodeChildrenDeleted(ValueNode* node);
|
||||
virtual void ValueNodeValueChanged(ValueNode* node);
|
||||
|
||||
ValueNodeContainer* GetContainer() const { return fContainer; };
|
||||
|
||||
status_t AddChildNodes(ValueNodeChild* nodeChild);
|
||||
|
||||
private:
|
||||
typedef BObjectList<ValueNodeContainer::Listener> ListenerList;
|
||||
|
||||
void _AddNode(Variable* variable);
|
||||
status_t _CreateValueNode(ValueNodeChild* nodeChild);
|
||||
|
||||
private:
|
||||
ValueNodeContainer* fContainer;
|
||||
StackFrame* fStackFrame;
|
||||
Thread* fThread;
|
||||
ListenerList fListeners;
|
||||
};
|
||||
|
||||
#endif // VALUE_NODE_MANAGER_H
|
Loading…
Reference in New Issue
Block a user