[haiku-commits] haiku: hrev51790 - src/apps/debugger/user_interface/gui/team_window src/kits/debugger/value src/kits/debugger/value/type_handlers src/apps/debugger/user_interface/gui/model headers/private/debugger/value

  • From: rene@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 4 Feb 2018 14:20:53 -0500 (EST)

hrev51790 adds 1 changeset to branch 'master'
old head: 401fb209ea379d373fbcee0cc69f8b63a53e2e18
new head: 770075026caa7953c27fb2d7489c5b3ea25a5853
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=770075026caa+%5E401fb209ea37

----------------------------------------------------------------------------

770075026caa: Debugger: Rework type handlers to allow for custom selection.
  
  TypeHandler:
  - Add name field for presentation purposes. Adapt subclasses accordingly.
  
  TypeHandlerRoster:
  - Add methods to count and retrieve all type handlers for a given type,
    and adjust CreateValueNode to allow for passing in an explicit handler.
    Adjust callers accordingly.
  
  VariablesViewState:
  - Add helpers to store an explicitly chosen type handler for a node.
  
  TypeHandlerMenuItem:
  - ActionMenuItem subclass that takes care of reference management
    for its contained type handler.
  
  VariablesView:
  - Add context menu for choosing type handlers if applicable. Implement
    support for invoking said type handlers in a similar manner to explicit
    typecasts.
  - Adjust saving/restoring the view state so that hidden nodes are taken
    into account as well. This is necessary since it may be the case that
    the handler had to be applied to the hidden child rather than the visible
    node (i.e. the BMessage handler when applied to a pointer to a BMessage).
  
  All together, these changes allow choosing to switch between views of a type
  when the Debugger has multiple handlers for it. For example, for BMessages
  this allows switching between displaying the raw underlying structure vs
  the decoded message content.

                                         [ Rene Gollent <rene@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev51790
Commit:      770075026caa7953c27fb2d7489c5b3ea25a5853
URL:         http://cgit.haiku-os.org/haiku/commit/?id=770075026caa
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Fri Jan 19 03:14:02 2018 UTC

----------------------------------------------------------------------------

18 files changed, 463 insertions(+), 60 deletions(-)
headers/private/debugger/value/TypeHandler.h     |   4 +-
.../private/debugger/value/TypeHandlerRoster.h   |  12 +-
src/apps/debugger/Jamfile                        |   1 +
.../gui/model/VariablesViewState.cpp             |  21 +-
.../gui/model/VariablesViewState.h               |   9 +-
.../gui/team_window/TypeHandlerMenuItem.cpp      |  47 ++++
.../gui/team_window/TypeHandlerMenuItem.h        |  32 +++
.../gui/team_window/VariablesView.cpp            | 237 +++++++++++++++++--
.../gui/team_window/VariablesView.h              |   4 +
.../debugger/debug_managers/ValueNodeManager.cpp |   5 +-
.../c_family/CLanguageExpressionEvaluator.cpp    |   2 +-
src/kits/debugger/value/TypeHandlerRoster.cpp    | 101 ++++++--
.../value/type_handlers/BListTypeHandler.cpp     |  11 +-
.../value/type_handlers/BListTypeHandler.h       |   5 +-
.../value/type_handlers/BMessageTypeHandler.cpp  |  11 +-
.../value/type_handlers/BMessageTypeHandler.h    |   5 +-
.../value/type_handlers/CStringTypeHandler.cpp   |  11 +-
.../value/type_handlers/CStringTypeHandler.h     |   5 +-

----------------------------------------------------------------------------

diff --git a/headers/private/debugger/value/TypeHandler.h 
b/headers/private/debugger/value/TypeHandler.h
index 01c4444937..95c722b7ff 100644
--- a/headers/private/debugger/value/TypeHandler.h
+++ b/headers/private/debugger/value/TypeHandler.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef TYPE_HANDLER_H
@@ -18,7 +19,8 @@ class TypeHandler : public BReferenceable {
 public:
        virtual                                         ~TypeHandler();
 
-       virtual float                           SupportsType(Type* type) = 0;
+       virtual const char*                     Name() const = 0;
+       virtual float                           SupportsType(Type* type) const 
= 0;
        virtual status_t                        CreateValueNode(ValueNodeChild* 
nodeChild,
                                                                        Type* 
type, ValueNode*& _node) = 0;
                                                                        // 
returns a reference
diff --git a/headers/private/debugger/value/TypeHandlerRoster.h 
b/headers/private/debugger/value/TypeHandlerRoster.h
index 973f202e1e..f848a1c98b 100644
--- a/headers/private/debugger/value/TypeHandlerRoster.h
+++ b/headers/private/debugger/value/TypeHandlerRoster.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef TYPE_HANDLER_ROSTER_H
@@ -31,11 +32,18 @@ public:
                        status_t                        Init();
                        status_t                        
RegisterDefaultHandlers();
 
-                       status_t                        
FindTypeHandler(ValueNodeChild* nodeChild,
+                       int32                           CountTypeHandlers(Type* 
type);
+                       status_t                        
FindBestTypeHandler(ValueNodeChild* nodeChild,
                                                                        Type* 
type, TypeHandler*& _handler);
                                                                        // 
returns a reference
+                       status_t                        
FindTypeHandlers(ValueNodeChild* nodeChild,
+                                                                       Type* 
type, TypeHandlerList*& _handlers);
+                                                                       // 
returns list of references
                        status_t                        
CreateValueNode(ValueNodeChild* nodeChild,
-                                                                       Type* 
type, ValueNode*& _node);
+                                                                       Type* 
type, TypeHandler* handler,
+                                                                       
ValueNode*& _node);
+                                                                       // 
handler can be null if automatic
+                                                                       // 
search is desired.
                                                                        // 
returns a reference
 
                        bool                            
RegisterHandler(TypeHandler* handler);
diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index f218e26f62..e8f66fc6ae 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -127,6 +127,7 @@ local sources =
        StackTraceView.cpp
        TeamWindow.cpp
        ThreadListView.cpp
+       TypeHandlerMenuItem.cpp
        VariablesView.cpp
 
        # user_interface/gui/team_settings_window
diff --git a/src/apps/debugger/user_interface/gui/model/VariablesViewState.cpp 
b/src/apps/debugger/user_interface/gui/model/VariablesViewState.cpp
index e6979f262b..c6b4037f74 100644
--- a/src/apps/debugger/user_interface/gui/model/VariablesViewState.cpp
+++ b/src/apps/debugger/user_interface/gui/model/VariablesViewState.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Distributed under the terms of the MIT License.
  */
@@ -14,6 +14,7 @@
 #include "StackFrameValues.h"
 #include "Type.h"
 #include "TypeComponentPath.h"
+#include "TypeHandler.h"
 
 
 // #pragma mark - VariablesViewNodeInfo
@@ -23,6 +24,7 @@ VariablesViewNodeInfo::VariablesViewNodeInfo()
        :
        fNodeExpanded(false),
        fCastedType(NULL),
+       fTypeHandler(NULL),
        fRendererSettings()
 {
 }
@@ -32,6 +34,7 @@ VariablesViewNodeInfo::VariablesViewNodeInfo(const 
VariablesViewNodeInfo& other)
        :
        fNodeExpanded(other.fNodeExpanded),
        fCastedType(other.fCastedType),
+       fTypeHandler(other.fTypeHandler),
        fRendererSettings(other.fRendererSettings)
 {
        if (fCastedType != NULL)
@@ -43,6 +46,9 @@ VariablesViewNodeInfo::~VariablesViewNodeInfo()
 {
        if (fCastedType != NULL)
                fCastedType->ReleaseReference();
+
+       if (fTypeHandler != NULL)
+               fTypeHandler->ReleaseReference();
 }
 
 
@@ -51,6 +57,7 @@ VariablesViewNodeInfo::operator=(const VariablesViewNodeInfo& 
other)
 {
        fNodeExpanded = other.fNodeExpanded;
        SetCastedType(other.fCastedType);
+       SetTypeHandler(other.fTypeHandler);
        fRendererSettings = other.fRendererSettings;
 
        return *this;
@@ -76,6 +83,18 @@ VariablesViewNodeInfo::SetCastedType(Type* type)
 }
 
 
+void
+VariablesViewNodeInfo::SetTypeHandler(TypeHandler* handler)
+{
+       if (fTypeHandler != NULL)
+               fTypeHandler->ReleaseReference();
+
+       fTypeHandler = handler;
+       if (fTypeHandler != NULL)
+               fTypeHandler->AcquireReference();
+}
+
+
 void
 VariablesViewNodeInfo::SetRendererSettings(const BMessage& settings)
 {
diff --git a/src/apps/debugger/user_interface/gui/model/VariablesViewState.h 
b/src/apps/debugger/user_interface/gui/model/VariablesViewState.h
index a36dd8bebc..8dc8ddf4f6 100644
--- a/src/apps/debugger/user_interface/gui/model/VariablesViewState.h
+++ b/src/apps/debugger/user_interface/gui/model/VariablesViewState.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Distributed under the terms of the MIT License.
  */
@@ -17,6 +17,7 @@ class ObjectID;
 class StackFrameValues;
 class Type;
 class TypeComponentPath;
+class TypeHandler;
 
 
 class VariablesViewNodeInfo {
@@ -37,6 +38,11 @@ public:
                                                                        { 
return fCastedType; }
                        void                            SetCastedType(Type* 
type);
 
+                       TypeHandler*            GetTypeHandler() const
+                                                                       { 
return fTypeHandler; }
+                       void                            
SetTypeHandler(TypeHandler* handler);
+
+
                        const BMessage&         GetRendererSettings() const
                                                                        { 
return fRendererSettings; }
 
@@ -45,6 +51,7 @@ public:
 private:
                        bool                            fNodeExpanded;
                        Type*                           fCastedType;
+                       TypeHandler*            fTypeHandler;
                        BMessage                        fRendererSettings;
 };
 
diff --git 
a/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.cpp 
b/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.cpp
new file mode 100644
index 0000000000..e47859cfda
--- /dev/null
+++ b/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "TypeHandlerMenuItem.h"
+
+#include "TypeHandler.h"
+
+
+TypeHandlerMenuItem::TypeHandlerMenuItem(const char* label,    BMessage* 
message,
+       char shortcut, uint32 modifiers)
+       :
+       ActionMenuItem(label, message, shortcut, modifiers),
+       fTypeHandler(NULL)
+{
+}
+
+
+TypeHandlerMenuItem::~TypeHandlerMenuItem()
+{
+       if (fTypeHandler != NULL)
+               fTypeHandler->ReleaseReference();
+}
+
+
+void
+TypeHandlerMenuItem::ItemSelected()
+{
+       // if the item was selected, acquire a reference
+       // on behalf of the message target, as ours will be released
+       // when our menu item is freed.
+       fTypeHandler->AcquireReference();
+}
+
+
+status_t
+TypeHandlerMenuItem::SetTypeHandler(TypeHandler* handler)
+{
+       status_t error = Message()->AddPointer("handler", handler);
+       if (error != B_OK)
+               return error;
+
+       fTypeHandler = handler;
+       return B_OK;
+}
diff --git 
a/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.h 
b/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.h
new file mode 100644
index 0000000000..6a1768c2b6
--- /dev/null
+++ b/src/apps/debugger/user_interface/gui/team_window/TypeHandlerMenuItem.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef TYPE_HANDLER_MENU_ITEM_H
+#define TYPE_HANDLER_MENU_ITEM_H
+
+
+#include "ActionMenuItem.h"
+
+
+class TypeHandler;
+
+
+class TypeHandlerMenuItem : public ActionMenuItem {
+public:
+                                                               
TypeHandlerMenuItem(const char* label,
+                                                                       
BMessage* message, char shortcut = 0,
+                                                                       uint32 
modifiers = 0);
+       virtual                                         ~TypeHandlerMenuItem();
+
+       virtual void                            ItemSelected();
+
+                       status_t                        
SetTypeHandler(TypeHandler* handler);
+                                                                       // 
takes over caller's reference
+
+private:
+       TypeHandler*                            fTypeHandler;
+};
+
+
+#endif // TYPE_HANDLER_MENU_ITEM_H
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 a30bba3d0f..de156c9147 100644
--- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp
+++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2011-2016, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2011-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -51,6 +51,8 @@
 #include "Thread.h"
 #include "Tracing.h"
 #include "TypeComponentPath.h"
+#include "TypeHandler.h"
+#include "TypeHandlerMenuItem.h"
 #include "TypeHandlerRoster.h"
 #include "TypeLookupConstraints.h"
 #include "UiUtils.h"
@@ -77,7 +79,9 @@ enum {
        MSG_VALUE_NODE_NEEDS_VALUE              = 'mvnv',
        MSG_RESTORE_PARTIAL_VIEW_STATE  = 'mpvs',
        MSG_ADD_WATCH_EXPRESSION                = 'awex',
-       MSG_REMOVE_WATCH_EXPRESSION             = 'rwex'
+       MSG_REMOVE_WATCH_EXPRESSION             = 'rwex',
+       MSG_USE_AUTOMATIC_HANDLER               = 'uaha',
+       MSG_USE_EXPLICIT_HANDLER                = 'ueha'
 };
 
 
@@ -267,6 +271,7 @@ public:
                fTableCellRenderer(NULL),
                fLastRendererSettings(),
                fCastedType(NULL),
+               fTypeHandler(NULL),
                fComponentPath(NULL),
                fIsPresentationNode(isPresentationNode),
                fHidden(false),
@@ -294,6 +299,9 @@ public:
 
                if (fCastedType != NULL)
                        fCastedType->ReleaseReference();
+
+               if (fTypeHandler != NULL)
+                       fTypeHandler->ReleaseReference();
        }
 
        status_t Init()
@@ -396,6 +404,22 @@ public:
                        fCastedType->AcquireReference();
        }
 
+       TypeHandler* GetTypeHandler() const
+       {
+               return fTypeHandler;
+       }
+
+       void SetTypeHandler(TypeHandler* handler)
+       {
+               if (fTypeHandler != NULL)
+                       fTypeHandler->ReleaseReference();
+
+               fTypeHandler = handler;
+               if (fTypeHandler != NULL)
+                       fTypeHandler->AcquireReference();
+       }
+
+
        const BMessage& GetLastRendererSettings() const
        {
                return fLastRendererSettings;
@@ -544,6 +568,7 @@ private:
        TableCellValueRenderer* fTableCellRenderer;
        BMessage                                fLastRendererSettings;
        Type*                                   fCastedType;
+       TypeHandler*                    fTypeHandler;
        ChildList                               fChildren;
        TypeComponentPath*              fComponentPath;
        bool                                    fIsPresentationNode;
@@ -1599,7 +1624,7 @@ 
VariablesView::VariableTableModel::AddSyntheticNode(Variable* variable,
                        error = _child->CreateInternalNode(valueNode);
                else {
                        error = 
TypeHandlerRoster::Default()->CreateValueNode(_child,
-                               _child->GetType(), valueNode);
+                               _child->GetType(), NULL, valueNode);
                }
 
                if (error != B_OK)
@@ -2025,7 +2050,7 @@ VariablesView::MessageReceived(BMessage* message)
                        typeRef.SetTo(addressType, true);
                        ValueNode* valueNode = NULL;
                        if (TypeHandlerRoster::Default()->CreateValueNode(
-                                       node->NodeChild(), addressType, 
valueNode) != B_OK) {
+                                       node->NodeChild(), addressType, NULL, 
valueNode) != B_OK) {
                                break;
                        }
 
@@ -2204,6 +2229,34 @@ VariablesView::MessageReceived(BMessage* message)
 
                        break;
                }
+               case MSG_USE_AUTOMATIC_HANDLER:
+               case MSG_USE_EXPLICIT_HANDLER:
+               {
+                       TypeHandler* handler = NULL;
+                       ModelNode* node = NULL;
+                       if (message->FindPointer("node", reinterpret_cast<void 
**>(&node))
+                                       != B_OK) {
+                               break;
+                       }
+
+                       if (message->what == MSG_USE_EXPLICIT_HANDLER
+                               && message->FindPointer("handler", 
reinterpret_cast<void**>(
+                                               &handler)) != B_OK) {
+                               break;
+                       }
+
+                       ValueNode* newNode;
+                       ValueNodeChild* child = node->NodeChild();
+                       if (TypeHandlerRoster::Default()->CreateValueNode(child,
+                                       child->GetType(), handler, newNode) != 
B_OK) {
+                               return;
+                       }
+
+                       node->SetTypeHandler(handler);
+                       child->SetNode(newNode);
+                       _RequestNodeValue(node);
+                       break;
+               }
                case MSG_VALUE_NODE_CHANGED:
                {
                        ValueNodeChild* nodeChild;
@@ -2607,7 +2660,12 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
                        message->AddUInt64("address", 
location->PieceAt(0).address);
                }
 
-               ValueNode* valueNode = node->NodeChild()->Node();
+               ValueNodeChild* child = node->NodeChild();
+               ValueNode* valueNode = child->Node();
+
+               result = _AddTypeHandlerMenuIfNeeded(node, _preActions);
+               if (result != B_OK)
+                       return result;
 
                if (valueNode != NULL) {
                        Value* value = valueNode->GetValue();
@@ -2699,23 +2757,142 @@ status_t
 VariablesView::_AddContextAction(const char* action, uint32 what,
        ContextActionList* actions, BMessage*& _message)
 {
-       _message = new(std::nothrow) BMessage(what);
-       if (_message == NULL)
+       ActionMenuItem* item = NULL;
+       status_t result = _CreateContextAction(action, what, item);
+       if (result != B_OK)
+               return result;
+
+       ObjectDeleter<ActionMenuItem> actionDeleter(item);
+       if (!actions->AddItem(item))
                return B_NO_MEMORY;
 
-       ObjectDeleter<BMessage> messageDeleter(_message);
+       actionDeleter.Detach();
+       _message = item->Message();
 
-       ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action,
-               _message);
-       if (item == NULL)
+       return B_OK;
+}
+
+
+status_t
+VariablesView::_CreateContextAction(const char* action, uint32 what,
+       ActionMenuItem*& _item)
+{
+       BMessage* message = new(std::nothrow) BMessage(what);
+       if (message == NULL)
                return B_NO_MEMORY;
 
-       messageDeleter.Detach();
-       ObjectDeleter<ActionMenuItem> actionDeleter(item);
-       if (!actions->AddItem(item))
+       ObjectDeleter<BMessage> messageDeleter(message);
+
+       _item = new(std::nothrow) ActionMenuItem(action,
+               message);
+       if (_item == NULL)
                return B_NO_MEMORY;
 
-       actionDeleter.Detach();
+       messageDeleter.Detach();
+
+       return B_OK;
+}
+
+
+status_t
+VariablesView::_AddTypeHandlerMenuIfNeeded(ModelNode* node,
+       ContextActionList* actions)
+{
+       ValueNodeChild* child = node->NodeChild();
+
+       Type* type = child->GetType();
+       if (node->CountChildren() == 1 && node->ChildAt(0)->IsHidden()) {
+               node = node->ChildAt(0);
+               child = node->NodeChild();
+               type = child->GetType();
+       }
+
+       int32 handlerCount = TypeHandlerRoster::Default()->CountTypeHandlers(
+               child->GetType());
+       if (handlerCount > 1) {
+               TypeHandler* lastHandler = node->GetTypeHandler();
+               BMenu* handlerMenu = new(std::nothrow) BMenu("Show as");
+               if (handlerMenu == NULL)
+                       return B_NO_MEMORY;
+
+               ObjectDeleter<BMenu> menuDeleter(handlerMenu);
+               ActionMenuItem* menuItem = new(std::nothrow) ActionMenuItem(
+                       handlerMenu);
+               if (menuItem == NULL)
+                       return B_NO_MEMORY;
+               ObjectDeleter<ActionMenuItem> menuItemDeleter(menuItem);
+               menuDeleter.Detach();
+
+               ActionMenuItem* item = NULL;
+               status_t result = _CreateContextAction("Automatic",
+                       MSG_USE_AUTOMATIC_HANDLER, item);
+               if (item == NULL)
+                       return B_NO_MEMORY;
+               item->Message()->AddPointer("node", node);
+
+               ObjectDeleter<ActionMenuItem> itemDeleter(item);
+               if (!handlerMenu->AddItem(item) || 
!handlerMenu->AddSeparatorItem())
+                       return B_NO_MEMORY;
+
+               itemDeleter.Detach();
+               if (lastHandler == NULL)
+                       item->SetMarked(true);
+
+               TypeHandlerList* handlers = NULL;
+               result = TypeHandlerRoster::Default()->FindTypeHandlers(child,
+                       child->GetType(), handlers);
+               if (result != B_OK)
+                       return result;
+
+               ObjectDeleter<TypeHandlerList> listDeleter(handlers);
+               while (handlers->CountItems() > 0) {
+                       TypeHandler* handler = handlers->ItemAt(0);
+                       BMessage* message = new(std::nothrow) BMessage(
+                               MSG_USE_EXPLICIT_HANDLER);
+                       if (message == NULL) {
+                               result = B_NO_MEMORY;
+                               break;
+                       }
+                       message->AddPointer("node", node);
+
+                       TypeHandlerMenuItem* typeItem
+                               = new(std::nothrow) 
TypeHandlerMenuItem(handler->Name(),
+                                       message);
+                       if (typeItem == NULL) {
+                               result = B_NO_MEMORY;
+                               break;
+                       }
+                       ObjectDeleter<TypeHandlerMenuItem> 
typeItemDeleter(typeItem);
+
+                       result = typeItem->SetTypeHandler(handler);
+                       if (result != B_OK)
+                               break;
+                       handlers->RemoveItemAt(0);
+                       if (!handlerMenu->AddItem(typeItem)) {
+                               result = B_NO_MEMORY;
+                               break;
+                       }
+
+                       typeItemDeleter.Detach();
+                       if (handler == lastHandler)
+                               typeItem->SetMarked(true);
+               }
+
+               if (result != B_OK) {
+                       for (int32 i = 0; TypeHandler* handler = 
handlers->ItemAt(i);
+                               i++) {
+                               handler->ReleaseReference();
+                       }
+
+                       return result;
+               }
+
+               if (!actions->AddItem(menuItem))
+                       return B_NO_MEMORY;
+
+               handlerMenu->SetTargetForItems(this);
+               menuItemDeleter.Detach();
+       }
 
        return B_OK;
 }
@@ -2843,9 +3020,14 @@ status_t
 VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
        void* parent, TreeTablePath& path, bool updateValues) const
 {
-       int32 childCount = fVariableTableModel->CountChildren(parent);
+       bool isRoot = parent == fVariableTableModel->Root();
+       int32 childCount = isRoot ? fVariableTableModel->CountChildren(parent)
+                       : ((ModelNode*)parent)->CountChildren();
        for (int32 i = 0; i < childCount; i++) {
-               ModelNode* node = 
(ModelNode*)fVariableTableModel->ChildAt(parent, i);
+               ModelNode* node = (ModelNode*)(isRoot ? 
fVariableTableModel->ChildAt(
+                                       parent, i)
+                               : ((ModelNode*)parent)->ChildAt(i));
+
                if (!path.AddComponent(i))
                        return B_NO_MEMORY;
 
@@ -2853,6 +3035,7 @@ 
VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
                VariablesViewNodeInfo nodeInfo;
                nodeInfo.SetNodeExpanded(fVariableTable->IsNodeExpanded(path));
                nodeInfo.SetCastedType(node->GetCastedType());
+               nodeInfo.SetTypeHandler(node->GetTypeHandler());
                TableCellValueRenderer* renderer = node->TableCellRenderer();
                if (renderer != NULL) {
                        Settings* settings = renderer->GetSettings();
@@ -2895,9 +3078,13 @@ status_t
 VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* 
viewState,
        void* parent, TreeTablePath& path)
 {
-       int32 childCount = fVariableTableModel->CountChildren(parent);
+       bool isRoot = parent == fVariableTableModel->Root();
+       int32 childCount = isRoot ? fVariableTableModel->CountChildren(parent)
+                       : ((ModelNode*)parent)->CountChildren();
        for (int32 i = 0; i < childCount; i++) {
-               ModelNode* node = 
(ModelNode*)fVariableTableModel->ChildAt(parent, i);
+               ModelNode* node = (ModelNode*)(isRoot ? 
fVariableTableModel->ChildAt(
+                                       parent, i)
+                               : ((ModelNode*)parent)->ChildAt(i));
                if (!path.AddComponent(i))
                        return B_NO_MEMORY;
 
@@ -2912,12 +3099,16 @@ 
VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
                        // before any other view state restoration, since it
                        // potentially changes the child hierarchy under that 
node.
                        Type* type = nodeInfo->GetCastedType();
-                       if (type != NULL) {
+                       TypeHandler* handler = nodeInfo->GetTypeHandler();
+                       node->SetCastedType(type);
+                       node->SetTypeHandler(handler);
+                       if (type != NULL || handler != NULL) {
+                               if (type == NULL)
+                                       type = node->GetType();
                                ValueNode* valueNode = NULL;
                                if 
(TypeHandlerRoster::Default()->CreateValueNode(
-                                       node->NodeChild(), type, valueNode) == 
B_OK) {
+                                       node->NodeChild(), type, handler, 
valueNode) == B_OK) {
                                        node->NodeChild()->SetNode(valueNode);
-                                       node->SetCastedType(type);
                                }
                        }
 
@@ -3209,7 +3400,7 @@ VariablesView::_HandleTypecastResult(status_t result, 
ExpressionResult* value)
        ValueNode* valueNode = NULL;
        ModelNode* node = fPendingTypecastInfo->TargetNode();
        if (TypeHandlerRoster::Default()->CreateValueNode(node->NodeChild(), 
type,
-                       valueNode) != B_OK) {
+                       NULL, valueNode) != B_OK) {
                return;
        }
 
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 91c47b529c..d02450df1d 100644
--- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h
+++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h
@@ -104,6 +104,10 @@ private:
                        status_t                        _AddContextAction(const 
char* action,
                                                                        uint32 
what, ContextActionList* actions,
                                                                        
BMessage*& _message);
+                       status_t                        
_CreateContextAction(const char* action,
+                                                                       uint32 
what, ActionMenuItem*& _item);
+                       status_t                        
_AddTypeHandlerMenuIfNeeded(ModelNode* node,
+                                                                       
ContextActionList* actions);
                        void                            _FinishContextMenu(bool 
force);
                        void                            _SaveViewState(bool 
updateValues) const;
                        void                            _RestoreViewState();
diff --git a/src/kits/debugger/debug_managers/ValueNodeManager.cpp 
b/src/kits/debugger/debug_managers/ValueNodeManager.cpp
index 2fb4367f45..9aa1e0aa47 100644
--- a/src/kits/debugger/debug_managers/ValueNodeManager.cpp
+++ b/src/kits/debugger/debug_managers/ValueNodeManager.cpp
@@ -112,9 +112,8 @@ ValueNodeManager::ValueNodeChanged(ValueNodeChild* 
nodeChild,
        for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
                fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, 
newNode);
 
-       if (oldNode != NULL)
+       if (oldNode != NULL && !newNode->ChildCreationNeedsValue())
                
newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation());
-
 }
 
 
@@ -201,7 +200,7 @@ ValueNodeManager::_CreateValueNode(ValueNodeChild* 
nodeChild)
                error = nodeChild->CreateInternalNode(valueNode);
        } else {
                error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
-                       nodeChild->GetType(), valueNode);
+                       nodeChild->GetType(), NULL, valueNode);
        }
 
        if (error != B_OK)
diff --git 
a/src/kits/debugger/source_language/c_family/CLanguageExpressionEvaluator.cpp 
b/src/kits/debugger/source_language/c_family/CLanguageExpressionEvaluator.cpp
index 11e73012d3..a406056bca 100644
--- 
a/src/kits/debugger/source_language/c_family/CLanguageExpressionEvaluator.cpp
+++ 
b/src/kits/debugger/source_language/c_family/CLanguageExpressionEvaluator.cpp
@@ -1782,7 +1782,7 @@ CLanguageExpressionEvaluator::_ParseAtom()
 
                ValueNode* newNode = NULL;
                status_t error = 
TypeHandlerRoster::Default()->CreateValueNode(child,
-                       castType, newNode);
+                       castType, NULL, newNode);
                if (error != B_OK) {
                        throw ParseException("Unable to create value node for 
typecast"
                                " operation.", token.position);
diff --git a/src/kits/debugger/value/TypeHandlerRoster.cpp 
b/src/kits/debugger/value/TypeHandlerRoster.cpp
index 4924d33fe2..718dacbeca 100644
--- a/src/kits/debugger/value/TypeHandlerRoster.cpp
+++ b/src/kits/debugger/value/TypeHandlerRoster.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -24,6 +25,14 @@
 #include "TypeHandler.h"
 
 
+static int CompareTypeHandlers(const TypeHandler* a, const TypeHandler* b,
+       void* state)
+{
+       Type* type = (Type*)state;
+       return a->SupportsType(type) > b->SupportsType(type) ? 1 : -1;
+}
+
+
 // #pragma mark - BasicTypeHandler
 
 
@@ -33,7 +42,12 @@ namespace {
 template<typename TypeClass, typename NodeClass>
 class BasicTypeHandler : public TypeHandler {
 public:
-       virtual float SupportsType(Type* type)
+       virtual const char* Name() const
+       {
+               return "Raw";
+       }
+
+       virtual float SupportsType(Type* type) const
        {
                return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0;
        }
@@ -161,8 +175,23 @@ TypeHandlerRoster::RegisterDefaultHandlers()
 }
 
 
+int32
+TypeHandlerRoster::CountTypeHandlers(Type* type)
+{
+       AutoLocker<BLocker>  locker(fLock);
+
+       int32 count = 0;
+       for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
+               if (handler->SupportsType(type) > 0)
+                       ++count;
+       }
+
+       return count;
+}
+
+
 status_t
-TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type,
+TypeHandlerRoster::FindBestTypeHandler(ValueNodeChild* nodeChild, Type* type,
        TypeHandler*& _handler)
 {
        // find the best-supporting handler
@@ -189,26 +218,66 @@ TypeHandlerRoster::FindTypeHandler(ValueNodeChild* 
nodeChild, Type* type,
 
 
 status_t
-TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
-       ValueNode*& _node)
+TypeHandlerRoster::FindTypeHandlers(ValueNodeChild* nodeChild, Type* type,
+       TypeHandlerList*& _handlers)
 {
        // find the best-supporting handler
-       while (true) {
-               TypeHandler* handler;
-               status_t error = FindTypeHandler(nodeChild, type, handler);
-               if (error == B_OK) {
-                       // let the handler create the node
-                       BReference<TypeHandler> handlerReference(handler, true);
-                       return handler->CreateValueNode(nodeChild, type, _node);
+       AutoLocker<BLocker> locker(fLock);
+
+       TypeHandlerList* handlers = new(std::nothrow) TypeHandlerList(10, 
false);
+       ObjectDeleter<TypeHandlerList> listDeleter(handlers);
+       if (handlers == NULL)
+               return B_NO_MEMORY;
+
+       for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
+               if (handler->SupportsType(type) > 0) {
+                       if (!handlers->AddItem(handler))
+                               return B_NO_MEMORY;
                }
+       }
+
+       if (handlers->CountItems() == 0)
+               return B_ENTRY_NOT_FOUND;
+
+       for (int32 i = 0; TypeHandler* handler = handlers->ItemAt(i); i++)
+               handler->AcquireReference();
+
+       handlers->SortItems(CompareTypeHandlers, type);
+
+       _handlers = handlers;
+       listDeleter.Detach();
+
+       return B_OK;
+}
 
-               // not found yet -- try to strip a modifier/typedef from the 
type
-               Type* nextType = type->ResolveRawType(true);
-               if (nextType == NULL || nextType == type)
-                       return B_UNSUPPORTED;
 
-               type = nextType;
+status_t
+TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
+       TypeHandler* handler, ValueNode*& _node)
+{
+       BReference<TypeHandler> handlerReference;
+
+       // if the caller doesn't supply us with a handler to use, try to find
+       // the best match.
+       if (handler == NULL) {
+               // find the best-supporting handler
+               while (true) {
+                       status_t error = FindBestTypeHandler(nodeChild, type, 
handler);
+                       if (error == B_OK) {
+                               handlerReference.SetTo(handler, true);
+                               break;
+                       }
+
+                       // not found yet -- try to strip a modifier/typedef 
from the type
+                       Type* nextType = type->ResolveRawType(true);
+                       if (nextType == NULL || nextType == type)
+                               return B_UNSUPPORTED;
+
+                       type = nextType;
+               }
        }
+
+       return handler->CreateValueNode(nodeChild, type, _node);
 }
 
 
diff --git a/src/kits/debugger/value/type_handlers/BListTypeHandler.cpp 
b/src/kits/debugger/value/type_handlers/BListTypeHandler.cpp
index 961d3a38b4..318190f81a 100644
--- a/src/kits/debugger/value/type_handlers/BListTypeHandler.cpp
+++ b/src/kits/debugger/value/type_handlers/BListTypeHandler.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2012-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -17,8 +17,15 @@ BListTypeHandler::~BListTypeHandler()
 }
 
 
+const char*
+BListTypeHandler::Name() const
+{
+       return "List content";
+}
+
+
 float
-BListTypeHandler::SupportsType(Type* type)
+BListTypeHandler::SupportsType(Type* type) const
 {
        if (dynamic_cast<CompoundType*>(type) != NULL
                && (type->Name() == "BList"
diff --git a/src/kits/debugger/value/type_handlers/BListTypeHandler.h 
b/src/kits/debugger/value/type_handlers/BListTypeHandler.h
index 12f37546bd..d24ddffc80 100644
--- a/src/kits/debugger/value/type_handlers/BListTypeHandler.h
+++ b/src/kits/debugger/value/type_handlers/BListTypeHandler.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2012-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef BLIST_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class BListTypeHandler : public TypeHandler {
 public:
        virtual                                 ~BListTypeHandler();
 
-       virtual float                   SupportsType(Type* type);
+       virtual const char*             Name() const;
+       virtual float                   SupportsType(Type* type) const;
        virtual status_t                CreateValueNode(ValueNodeChild* 
nodeChild,
                                                                Type* type, 
ValueNode*& _node);
 };
diff --git a/src/kits/debugger/value/type_handlers/BMessageTypeHandler.cpp 
b/src/kits/debugger/value/type_handlers/BMessageTypeHandler.cpp
index a46fcbbbee..3358113343 100644
--- a/src/kits/debugger/value/type_handlers/BMessageTypeHandler.cpp
+++ b/src/kits/debugger/value/type_handlers/BMessageTypeHandler.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2011-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -17,8 +17,15 @@ BMessageTypeHandler::~BMessageTypeHandler()
 }
 
 
+const char*
+BMessageTypeHandler::Name() const
+{
+       return "Message content";
+}
+
+
 float
-BMessageTypeHandler::SupportsType(Type* type)
+BMessageTypeHandler::SupportsType(Type* type) const
 {
        if (dynamic_cast<CompoundType*>(type) != NULL
                && type->Name() == "BMessage")
diff --git a/src/kits/debugger/value/type_handlers/BMessageTypeHandler.h 
b/src/kits/debugger/value/type_handlers/BMessageTypeHandler.h
index 321672e314..3816315504 100644
--- a/src/kits/debugger/value/type_handlers/BMessageTypeHandler.h
+++ b/src/kits/debugger/value/type_handlers/BMessageTypeHandler.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2011-2018, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef BMESSAGE_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class BMessageTypeHandler : public TypeHandler {
 public:
        virtual                                 ~BMessageTypeHandler();
 
-       virtual float                   SupportsType(Type* type);
+       virtual const char*             Name() const;
+       virtual float                   SupportsType(Type* type) const;
        virtual status_t                CreateValueNode(ValueNodeChild* 
nodeChild,
                                                                Type* type, 
ValueNode*& _node);
 };
diff --git a/src/kits/debugger/value/type_handlers/CStringTypeHandler.cpp 
b/src/kits/debugger/value/type_handlers/CStringTypeHandler.cpp
index 1d0bcc363a..2c0d76de90 100644
--- a/src/kits/debugger/value/type_handlers/CStringTypeHandler.cpp
+++ b/src/kits/debugger/value/type_handlers/CStringTypeHandler.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, Rene Gollent, rene@xxxxxxxxxxx
+ * Copyright 2010-2018, Rene Gollent, rene@xxxxxxxxxxx
  * Distributed under the terms of the MIT License.
  */
 
@@ -19,8 +19,15 @@ CStringTypeHandler::~CStringTypeHandler()
 }
 
 
+const char*
+CStringTypeHandler::Name() const
+{
+       return "String";
+}
+
+
 float
-CStringTypeHandler::SupportsType(Type* type)
+CStringTypeHandler::SupportsType(Type* type) const
 {
        AddressType* addressType = dynamic_cast<AddressType*>(type);
        ArrayType* arrayType = dynamic_cast<ArrayType*>(type);
diff --git a/src/kits/debugger/value/type_handlers/CStringTypeHandler.h 
b/src/kits/debugger/value/type_handlers/CStringTypeHandler.h
index 1f8a146495..98739fa85e 100644
--- a/src/kits/debugger/value/type_handlers/CStringTypeHandler.h
+++ b/src/kits/debugger/value/type_handlers/CStringTypeHandler.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, Rene Gollent, rene@xxxxxxxxxxx
+ * Copyright 2010-2018, Rene Gollent, rene@xxxxxxxxxxx
  * Distributed under the terms of the MIT License.
  */
 #ifndef CSTRING_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class CStringTypeHandler : public TypeHandler {
 public:
        virtual                                 ~CStringTypeHandler();
 
-       virtual float                   SupportsType(Type* type);
+       virtual const char*             Name() const;
+       virtual float                   SupportsType(Type* type) const;
        virtual status_t                CreateValueNode(ValueNodeChild* 
nodeChild,
                                                                Type* type, 
ValueNode*& _node);
 };


Other related posts:

  • » [haiku-commits] haiku: hrev51790 - src/apps/debugger/user_interface/gui/team_window src/kits/debugger/value src/kits/debugger/value/type_handlers src/apps/debugger/user_interface/gui/model headers/private/debugger/value - rene