From b6c4fc962c6b0d6a0f071069fd0e90053e58f135 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 1 Nov 2014 18:42:59 -0400 Subject: [PATCH] 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. --- .../gui/team_window/VariablesView.cpp | 82 +++++++++++++++++-- .../gui/team_window/VariablesView.h | 7 +- .../gui/value/TableCellBoolRenderer.cpp | 6 +- .../gui/value/TableCellBoolRenderer.h | 5 +- .../value/TableCellEnumerationRenderer.cpp | 10 ++- .../gui/value/TableCellEnumerationRenderer.h | 5 +- .../gui/value/TableCellFloatRenderer.cpp | 6 +- .../gui/value/TableCellFloatRenderer.h | 5 +- .../gui/value/TableCellIntegerRenderer.cpp | 7 +- .../gui/value/TableCellIntegerRenderer.h | 5 +- .../gui/value/TableCellStringRenderer.cpp | 7 +- .../gui/value/TableCellStringRenderer.h | 5 +- .../gui/value/TableCellValueRenderer.h | 5 +- .../gui/value/TableCellValueRendererUtils.cpp | 11 ++- .../gui/value/TableCellValueRendererUtils.h | 1 + 15 files changed, 129 insertions(+), 38 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp index 0f62edec9c..1c8455cfb2 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp @@ -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 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(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 functionIDReference(functionID, true); + StackFrameValues* values = new(std::nothrow) StackFrameValues; + if (values == NULL) + return; + BReference 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); diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h index 83583f49c0..c07a868faa 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h @@ -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(); diff --git a/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.cpp index d7c19953d0..ac1cb79591 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.cpp @@ -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(_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); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.h index d3f4246755..bae90e8a37 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellBoolRenderer.h @@ -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); }; diff --git a/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.cpp index 1852e5eaa1..461db6cfac 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.cpp @@ -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); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.h index 6a68fb544a..a0fa34f889 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellEnumerationRenderer.h @@ -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); }; diff --git a/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.cpp index fa71cb841f..b28f0d4b09 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.cpp @@ -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(_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); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.h index 2058d9ae61..b6253ac26b 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellFloatRenderer.h @@ -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); }; diff --git a/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.cpp index 751fcfac7b..bba8e2ed55 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.cpp @@ -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(_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); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.h index 2061fec649..9d8a630df9 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellIntegerRenderer.h @@ -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); diff --git a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp index ebb905f77a..2d273e90d2 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp @@ -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); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.h index 5e05efd6f7..f76332692b 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.h @@ -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); }; diff --git a/src/apps/debugger/user_interface/gui/value/TableCellValueRenderer.h b/src/apps/debugger/user_interface/gui/value/TableCellValueRenderer.h index 019e4c9102..f943c7ec38 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellValueRenderer.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellValueRenderer.h @@ -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; }; diff --git a/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.cpp b/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.cpp index 3af19347cd..2df04720d7 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.cpp @@ -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(); } diff --git a/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.h b/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.h index 1f48993532..cd77cf0180 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.h +++ b/src/apps/debugger/user_interface/gui/value/TableCellValueRendererUtils.h @@ -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,