Debugger: Implement #9946.
TableCellValueRenderer{Utils}: - The rendering calls now take a boolean indicating if the value being rendered differs from its previous state. This is taken into account by rendering it in a different color to indicate the change. Adjust all implementing subclasses accordingly. VariablesView::ModelNode: - Now stores the previous value of the corresponding value node, and can be queried if its value has changed. Used by renderers. VariablesView::_{Add,Apply}ViewStateDescendentInfos(): - When walking the model, also store/restore the values of nodes in the history. In summation of all the above changes, when stepping through a function, we now display values that have changed since the last step, or that have appeared for the first time in a different color.
This commit is contained in:
parent
f40556afab
commit
b6c4fc962c
@ -108,13 +108,15 @@ public:
|
||||
fNodeChild(nodeChild),
|
||||
fVariable(variable),
|
||||
fValue(NULL),
|
||||
fPreviousValue(),
|
||||
fValueHandler(NULL),
|
||||
fTableCellRenderer(NULL),
|
||||
fLastRendererSettings(),
|
||||
fCastedType(NULL),
|
||||
fComponentPath(NULL),
|
||||
fIsPresentationNode(isPresentationNode),
|
||||
fHidden(false)
|
||||
fHidden(false),
|
||||
fValueChanged(false)
|
||||
{
|
||||
fNodeChild->AcquireReference();
|
||||
}
|
||||
@ -202,6 +204,18 @@ public:
|
||||
|
||||
if (fValue != NULL)
|
||||
fValue->AcquireReference();
|
||||
|
||||
_CompareValues();
|
||||
}
|
||||
|
||||
const BVariant& PreviousValue() const
|
||||
{
|
||||
return fPreviousValue;
|
||||
}
|
||||
|
||||
void SetPreviousValue(const BVariant& value)
|
||||
{
|
||||
fPreviousValue = value;
|
||||
}
|
||||
|
||||
Type* GetCastedType() const
|
||||
@ -288,6 +302,11 @@ public:
|
||||
fHidden = hidden;
|
||||
}
|
||||
|
||||
bool ValueChanged() const
|
||||
{
|
||||
return fValueChanged;
|
||||
}
|
||||
|
||||
int32 CountChildren() const
|
||||
{
|
||||
return fChildren.CountItems();
|
||||
@ -332,11 +351,24 @@ public:
|
||||
private:
|
||||
typedef BObjectList<ModelNode> ChildList;
|
||||
|
||||
private:
|
||||
void _CompareValues()
|
||||
{
|
||||
if (fValue == NULL)
|
||||
fValueChanged = false;
|
||||
else {
|
||||
BVariant newValue;
|
||||
fValue->ToVariant(newValue);
|
||||
fValueChanged = (fPreviousValue != newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ModelNode* fParent;
|
||||
ValueNodeChild* fNodeChild;
|
||||
Variable* fVariable;
|
||||
Value* fValue;
|
||||
BVariant fPreviousValue;
|
||||
ValueHandler* fValueHandler;
|
||||
TableCellValueRenderer* fTableCellRenderer;
|
||||
BMessage fLastRendererSettings;
|
||||
@ -345,6 +377,7 @@ private:
|
||||
TypeComponentPath* fComponentPath;
|
||||
bool fIsPresentationNode;
|
||||
bool fHidden;
|
||||
bool fValueChanged;
|
||||
|
||||
public:
|
||||
ModelNode* fNext;
|
||||
@ -373,8 +406,8 @@ protected:
|
||||
ModelNode* node = dynamic_cast<ModelNode*>(value.ToReferenceable());
|
||||
if (node != NULL && node->GetValue() != NULL
|
||||
&& node->TableCellRenderer() != NULL) {
|
||||
node->TableCellRenderer()->RenderValue(node->GetValue(), rect,
|
||||
targetView);
|
||||
node->TableCellRenderer()->RenderValue(node->GetValue(),
|
||||
node->ValueChanged(), rect, targetView);
|
||||
return;
|
||||
}
|
||||
} else if (value.Type() == B_STRING_TYPE) {
|
||||
@ -1102,6 +1135,8 @@ VariablesView::VariableTableModel::ValueNodeValueChanged(ValueNode* valueNode)
|
||||
settings->RestoreValues(modelNode->GetLastRendererSettings());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// notify table model listeners
|
||||
NotifyNodeChanged(modelNode);
|
||||
}
|
||||
@ -2168,6 +2203,14 @@ VariablesView::_SaveViewState() const
|
||||
return;
|
||||
BReference<FunctionID> functionIDReference(functionID, true);
|
||||
|
||||
StackFrameValues* values = new(std::nothrow) StackFrameValues;
|
||||
if (values == NULL)
|
||||
return;
|
||||
BReference<StackFrameValues> valuesReference(values, true);
|
||||
|
||||
if (values->Init() != B_OK)
|
||||
return;
|
||||
|
||||
// create an empty view state
|
||||
VariablesViewState* viewState = new(std::nothrow) VariablesViewState;
|
||||
if (viewState == NULL)
|
||||
@ -2177,13 +2220,14 @@ VariablesView::_SaveViewState() const
|
||||
if (viewState->Init() != B_OK)
|
||||
return;
|
||||
|
||||
viewState->SetValues(values);
|
||||
|
||||
// populate it
|
||||
TreeTablePath path;
|
||||
if (_AddViewStateDescendentNodeInfos(viewState, fVariableTableModel->Root(),
|
||||
path) != B_OK) {
|
||||
if (_AddViewStateDescendentNodeInfos(viewState,
|
||||
fVariableTableModel->Root(), path) != B_OK) {
|
||||
return;
|
||||
}
|
||||
// TODO: Add values!
|
||||
|
||||
// add the view state to the history
|
||||
fViewStateHistory->SetState(fThread->ID(), functionID, viewState);
|
||||
@ -2243,11 +2287,23 @@ VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
||||
nodeInfo.SetRendererSettings(settings->Message());
|
||||
}
|
||||
|
||||
status_t error = viewState->SetNodeInfo(node->GetVariable()->ID(),
|
||||
node->GetPath(), nodeInfo);
|
||||
ObjectID* id = node->GetVariable()->ID();
|
||||
TypeComponentPath* componentPath = node->GetPath();
|
||||
|
||||
status_t error = viewState->SetNodeInfo(id, componentPath, nodeInfo);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
Value* value = node->GetValue();
|
||||
if (value != NULL) {
|
||||
BVariant variableValueData;
|
||||
if (value->ToVariant(variableValueData))
|
||||
error = viewState->Values()->SetValue(id, componentPath,
|
||||
variableValueData);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
// recurse
|
||||
error = _AddViewStateDescendentNodeInfos(viewState, node, path);
|
||||
if (error != B_OK)
|
||||
@ -2271,8 +2327,10 @@ VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// apply the node's info, if any
|
||||
ObjectID* objectID = node->GetVariable()->ID();
|
||||
TypeComponentPath* componentPath = node->GetPath();
|
||||
const VariablesViewNodeInfo* nodeInfo = viewState->GetNodeInfo(
|
||||
node->GetVariable()->ID(), node->GetPath());
|
||||
objectID, componentPath);
|
||||
if (nodeInfo != NULL) {
|
||||
// NB: if the node info indicates that the node in question
|
||||
// was being cast to a different type, this *must* be applied
|
||||
@ -2295,6 +2353,12 @@ VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
||||
|
||||
fVariableTable->SetNodeExpanded(path, nodeInfo->IsNodeExpanded());
|
||||
|
||||
BVariant previousValue;
|
||||
if (viewState->Values()->GetValue(objectID, componentPath,
|
||||
previousValue)) {
|
||||
node->SetPreviousValue(previousValue);
|
||||
}
|
||||
|
||||
// recurse
|
||||
status_t error = _ApplyViewStateDescendentNodeInfos(viewState, node,
|
||||
path);
|
||||
|
@ -16,6 +16,7 @@ class ActionMenuItem;
|
||||
class CpuState;
|
||||
class SettingsMenu;
|
||||
class StackFrame;
|
||||
class StackFrameValues;
|
||||
class Thread;
|
||||
class Type;
|
||||
class TypeComponentPath;
|
||||
@ -81,10 +82,12 @@ private:
|
||||
void _SaveViewState() const;
|
||||
void _RestoreViewState();
|
||||
status_t _AddViewStateDescendentNodeInfos(
|
||||
VariablesViewState* viewState, void* parent,
|
||||
VariablesViewState* viewState,
|
||||
void* parent,
|
||||
TreeTablePath& path) const;
|
||||
status_t _ApplyViewStateDescendentNodeInfos(
|
||||
VariablesViewState* viewState, void* parent,
|
||||
VariablesViewState* viewState,
|
||||
void* parent,
|
||||
TreeTablePath& path);
|
||||
void _CopyVariableValueToClipboard();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -18,14 +19,15 @@ bool_value_string(BoolValue* value)
|
||||
|
||||
|
||||
void
|
||||
TableCellBoolRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
|
||||
TableCellBoolRenderer::RenderValue(Value* _value, bool valueChanged,
|
||||
BRect rect, BView* targetView)
|
||||
{
|
||||
BoolValue* value = dynamic_cast<BoolValue*>(_value);
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect,
|
||||
bool_value_string(value), B_ALIGN_RIGHT, true);
|
||||
bool_value_string(value), valueChanged, B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -13,8 +14,8 @@
|
||||
|
||||
class TableCellBoolRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -19,8 +20,8 @@ TableCellEnumerationRenderer::TableCellEnumerationRenderer(Config* config)
|
||||
|
||||
|
||||
void
|
||||
TableCellEnumerationRenderer::RenderValue(Value* _value, BRect rect,
|
||||
BView* targetView)
|
||||
TableCellEnumerationRenderer::RenderValue(Value* _value, bool valueChanged,
|
||||
BRect rect, BView* targetView)
|
||||
{
|
||||
Config* config = GetConfig();
|
||||
if (config != NULL && config->IntegerFormat() == INTEGER_FORMAT_DEFAULT) {
|
||||
@ -31,12 +32,13 @@ TableCellEnumerationRenderer::RenderValue(Value* _value, BRect rect,
|
||||
if (EnumeratorValue* enumValue
|
||||
= value->GetType()->ValueFor(value->GetValue())) {
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect,
|
||||
enumValue->Name(), B_ALIGN_RIGHT, true);
|
||||
enumValue->Name(), valueChanged, B_ALIGN_RIGHT, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TableCellIntegerRenderer::RenderValue(_value, rect, targetView);
|
||||
TableCellIntegerRenderer::RenderValue(_value, valueChanged, rect,
|
||||
targetView);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -15,8 +16,8 @@ class TableCellEnumerationRenderer : public TableCellIntegerRenderer {
|
||||
public:
|
||||
TableCellEnumerationRenderer(Config* config);
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -13,7 +14,8 @@
|
||||
|
||||
|
||||
void
|
||||
TableCellFloatRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
|
||||
TableCellFloatRenderer::RenderValue(Value* _value, bool valueChanged,
|
||||
BRect rect, BView* targetView)
|
||||
{
|
||||
FloatValue* value = dynamic_cast<FloatValue*>(_value);
|
||||
if (value == NULL)
|
||||
@ -23,7 +25,7 @@ TableCellFloatRenderer::RenderValue(Value* _value, BRect rect, BView* targetView
|
||||
snprintf(buffer, sizeof(buffer), "%g", value->GetValue());
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
|
||||
B_ALIGN_RIGHT, true);
|
||||
valueChanged, B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -13,8 +14,8 @@
|
||||
|
||||
class TableCellFloatRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -41,8 +42,8 @@ TableCellIntegerRenderer::GetSettings() const
|
||||
|
||||
|
||||
void
|
||||
TableCellIntegerRenderer::RenderValue(Value* _value, BRect rect,
|
||||
BView* targetView)
|
||||
TableCellIntegerRenderer::RenderValue(Value* _value, bool valueChanged,
|
||||
BRect rect, BView* targetView)
|
||||
{
|
||||
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
|
||||
if (value == NULL)
|
||||
@ -59,7 +60,7 @@ TableCellIntegerRenderer::RenderValue(Value* _value, BRect rect,
|
||||
|
||||
// render
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
|
||||
B_ALIGN_RIGHT, true);
|
||||
valueChanged, B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -25,8 +26,8 @@ public:
|
||||
|
||||
virtual Settings* GetSettings() const;
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -15,8 +16,8 @@
|
||||
|
||||
|
||||
void
|
||||
TableCellStringRenderer::RenderValue(Value* value, BRect rect,
|
||||
BView* targetView)
|
||||
TableCellStringRenderer::RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView)
|
||||
{
|
||||
BString string = "\"";
|
||||
BString tempString;
|
||||
@ -64,7 +65,7 @@ TableCellStringRenderer::RenderValue(Value* value, BRect rect,
|
||||
string += "\"";
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, string,
|
||||
B_ALIGN_RIGHT, true);
|
||||
valueChanged, B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -13,8 +14,8 @@
|
||||
|
||||
class TableCellStringRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -23,8 +24,8 @@ public:
|
||||
virtual Settings* GetSettings() const;
|
||||
// returns NULL, if no settings
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView) = 0;
|
||||
virtual void RenderValue(Value* value, bool valueChanged,
|
||||
BRect rect, BView* targetView) = 0;
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView) = 0;
|
||||
};
|
||||
|
@ -16,7 +16,8 @@ static const float kTextMargin = 8;
|
||||
|
||||
/*static*/ void
|
||||
TableCellValueRendererUtils::DrawString(BView* view, BRect rect,
|
||||
const char* string, enum alignment alignment, bool truncate)
|
||||
const char* string, bool valueChanged, enum alignment alignment,
|
||||
bool truncate)
|
||||
{
|
||||
// get font height info
|
||||
font_height fontHeight;
|
||||
@ -56,7 +57,15 @@ TableCellValueRendererUtils::DrawString(BView* view, BRect rect,
|
||||
// TODO: This is the computation BColumnListView (respectively
|
||||
// BTitledColumn) is using, which I find somewhat weird.
|
||||
|
||||
if (valueChanged) {
|
||||
view->PushState();
|
||||
view->SetHighColor((rgb_color){255, 0, 0, 255});
|
||||
}
|
||||
|
||||
view->DrawString(string, BPoint(x, y));
|
||||
|
||||
if (valueChanged)
|
||||
view->PopState();
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ class TableCellValueRendererUtils {
|
||||
public:
|
||||
static void DrawString(BView* view, BRect rect,
|
||||
const char* string,
|
||||
bool valueChanged,
|
||||
enum alignment alignment,
|
||||
bool truncate = false);
|
||||
static float PreferredStringWidth(BView* view,
|
||||
|
Loading…
Reference in New Issue
Block a user