* Copyright 2012-2016, 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 "model/Thread.h"
#include "StackFrame.h"
#include "Team.h"
#include "TypeHandlerRoster.h"
#include "ValueNode.h"
#include "Variable.h"
#include "VariableValueNodeChild.h"
ValueNodeManager::ValueNodeManager(bool addFrameNodes)
:
fAddFrameNodes(addFrameNodes),
fContainer(NULL),
fStackFrame(NULL),
fThread(NULL)
{
SetStackFrame(NULL, 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)
return B_OK;
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);
if (fStackFrame != NULL && fAddFrameNodes) {
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);
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
if (oldNode != NULL && !newNode->ChildCreationNeedsValue())
newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation());
}
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);
ValueNodeChild* nodeChild = valueNode->NodeChild();
if (nodeChild == NULL)
return;
if (valueNode->ChildCreationNeedsValue()
&& !valueNode->ChildrenCreated()) {
status_t error = valueNode->CreateChildren(
fThread->GetTeam()->GetTeamTypeInformation());
if (error == B_OK) {
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)
{
ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild(
variable);
BReference<ValueNodeChild> nodeChildReference(nodeChild, true);
if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) {
delete nodeChild;
return;
}
AddChildNodes(nodeChild);
}
status_t
ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild)
{
if (nodeChild->Node() != NULL)
return B_OK;
ValueNode* valueNode;
status_t error;
if (nodeChild->IsInternal()) {
error = nodeChild->CreateInternalNode(valueNode);
} else {
error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
nodeChild->GetType(), NULL, 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);
ValueNode* valueNode = nodeChild->Node();
if (valueNode == NULL) {
status_t error = _CreateValueNode(nodeChild);
if (error != B_OK)
return error;
valueNode = nodeChild->Node();
}
if (valueNode->ChildCreationNeedsValue())
return B_OK;
if (valueNode->ChildrenCreated())
return B_OK;
return valueNode->CreateChildren(
fThread->GetTeam()->GetTeamTypeInformation());
}