Add inspection context menu action.
- TableCellContextMenuTracker now supports menus that don't have a settings submenu, since some variables won't have renderer settings but will still have context actions. - Add _GetContextActionsForNode() to retrieve the list of contextual actions available for a given model node. Currently this is only adds an action to inspect the memory address of the highlighted value, but will be extended for other actions later.
This commit is contained in:
parent
ae8018310a
commit
17ef26a9f8
@ -37,6 +37,7 @@
|
||||
#include "Value.h"
|
||||
#include "ValueHandler.h"
|
||||
#include "ValueHandlerRoster.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNode.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
#include "Variable.h"
|
||||
@ -492,11 +493,19 @@ public:
|
||||
ContextActionList* preSettingsActions = NULL,
|
||||
ContextActionList* postSettingsActions = NULL)
|
||||
{
|
||||
fRendererSettings = rendererSettings;
|
||||
fRendererSettings->AcquireReference();
|
||||
if (rendererSettings == NULL && preSettingsActions == NULL
|
||||
&& postSettingsActions == NULL) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fRendererSettingsMenu = rendererSettingsMenu;
|
||||
fRendererSettingsMenu->AcquireReference();
|
||||
if (rendererSettings != NULL) {
|
||||
fRendererSettings = rendererSettings;
|
||||
fRendererSettings->AcquireReference();
|
||||
|
||||
|
||||
fRendererSettingsMenu = rendererSettingsMenu;
|
||||
fRendererSettingsMenu->AcquireReference();
|
||||
}
|
||||
|
||||
fContextMenu = new(std::nothrow) ContextMenu(fParent,
|
||||
"table cell settings popup");
|
||||
@ -504,39 +513,52 @@ public:
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = B_OK;
|
||||
if (preSettingsActions != NULL) {
|
||||
if (preSettingsActions != NULL
|
||||
&& preSettingsActions->CountItems() > 0) {
|
||||
error = _AddActionItems(preSettingsActions);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (fRendererSettingsMenu != NULL || postSettingsActions != NULL)
|
||||
fContextMenu->AddSeparatorItem();
|
||||
}
|
||||
|
||||
error = fRendererSettingsMenu->AddToMenu(fContextMenu, 0);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (fRendererSettingsMenu != NULL) {
|
||||
error = fRendererSettingsMenu->AddToMenu(fContextMenu,
|
||||
fContextMenu->CountItems());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (postSettingsActions != NULL)
|
||||
fContextMenu->AddSeparatorItem();
|
||||
}
|
||||
|
||||
if (postSettingsActions != NULL) {
|
||||
error = _AddActionItems(postSettingsActions);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
AutoLocker<Settings> settingsLocker(fRendererSettings);
|
||||
fRendererSettings->AddListener(this);
|
||||
|
||||
fRendererMenuAdded = true;
|
||||
if (fRendererSettings != NULL) {
|
||||
AutoLocker<Settings> settingsLocker(fRendererSettings);
|
||||
fRendererSettings->AddListener(this);
|
||||
fRendererMenuAdded = true;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void ShowMenu(BPoint screenWhere)
|
||||
{
|
||||
fRendererSettingsMenu->PrepareToShow(fParentLooper);
|
||||
if (fRendererMenuAdded)
|
||||
fRendererSettingsMenu->PrepareToShow(fParentLooper);
|
||||
|
||||
for (int32 i = 0; i < fContextMenu->CountItems(); i++) {
|
||||
ActionMenuItem* item = dynamic_cast<ActionMenuItem*>(
|
||||
fContextMenu->ItemAt(i));
|
||||
if (item != NULL)
|
||||
item->PrepareToShow(fParentLooper, fContextMenu);
|
||||
item->PrepareToShow(fParentLooper, fParent.Target(NULL));
|
||||
}
|
||||
|
||||
fMenuPreparedToShow = true;
|
||||
@ -551,13 +573,15 @@ public:
|
||||
bool stillActive = false;
|
||||
|
||||
if (fMenuPreparedToShow) {
|
||||
stillActive = fRendererSettingsMenu->Finish(fParentLooper, force);
|
||||
if (fRendererMenuAdded)
|
||||
stillActive = fRendererSettingsMenu->Finish(fParentLooper,
|
||||
force);
|
||||
for (int32 i = 0; i < fContextMenu->CountItems(); i++) {
|
||||
ActionMenuItem* item = dynamic_cast<ActionMenuItem*>(
|
||||
fContextMenu->ItemAt(i));
|
||||
if (item != NULL) {
|
||||
stillActive |= item->Finish(fParentLooper, fContextMenu,
|
||||
force);
|
||||
stillActive |= item->Finish(fParentLooper,
|
||||
fParent.Target(NULL), force);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1462,6 +1486,15 @@ void
|
||||
VariablesView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_SHOW_INSPECTOR_WINDOW:
|
||||
{
|
||||
// TODO: it'd probably be more ideal to extend the context
|
||||
// action mechanism to allow one to specify an explicit
|
||||
// target for each action rather than them all defaulting
|
||||
// to targetting here.
|
||||
Looper()->PostMessage(message);
|
||||
break;
|
||||
}
|
||||
case MSG_VALUE_NODE_CHANGED:
|
||||
{
|
||||
ValueNodeChild* nodeChild;
|
||||
@ -1644,25 +1677,39 @@ VariablesView::TreeTableCellMouseDown(TreeTable* table,
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
Settings* settings = NULL;
|
||||
SettingsMenu* settingsMenu = NULL;
|
||||
BReference<SettingsMenu> settingsMenuReference;
|
||||
status_t error = B_OK;
|
||||
TableCellValueRenderer* cellRenderer = node->TableCellRenderer();
|
||||
if (cellRenderer == NULL)
|
||||
return;
|
||||
|
||||
Settings* settings = cellRenderer->GetSettings();
|
||||
if (settings == NULL)
|
||||
return;
|
||||
|
||||
SettingsMenu* settingsMenu;
|
||||
status_t error = node->GetValueHandler()->CreateTableCellValueSettingsMenu(
|
||||
node->GetValue(), settings, settingsMenu);
|
||||
BReference<SettingsMenu> settingsMenuReference(settingsMenu, true);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
if (cellRenderer != NULL) {
|
||||
settings = cellRenderer->GetSettings();
|
||||
if (settings != NULL) {
|
||||
error = node->GetValueHandler()
|
||||
->CreateTableCellValueSettingsMenu(node->GetValue(), settings,
|
||||
settingsMenu);
|
||||
settingsMenuReference.SetTo(settingsMenu, true);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TableCellContextMenuTracker* tracker = new(std::nothrow)
|
||||
TableCellContextMenuTracker(node, Looper(), this);
|
||||
BReference<TableCellContextMenuTracker> trackerReference(tracker);
|
||||
if (tracker == NULL || tracker->Init(settings, settingsMenu) != B_OK)
|
||||
|
||||
ContextActionList* preActionList = new(std::nothrow) ContextActionList;
|
||||
if (preActionList == NULL)
|
||||
return;
|
||||
|
||||
BPrivate::ObjectDeleter<ContextActionList> preActionListDeleter(
|
||||
preActionList);
|
||||
|
||||
error = _GetContextActionsForNode(node, preActionList);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
if (tracker == NULL || tracker->Init(settings, settingsMenu, preActionList) != B_OK)
|
||||
return;
|
||||
|
||||
fTableCellContextMenuTracker = trackerReference.Detach();
|
||||
@ -1729,6 +1776,39 @@ VariablesView::_RequestNodeValue(ModelNode* node)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VariablesView::_GetContextActionsForNode(ModelNode* node,
|
||||
ContextActionList* actions)
|
||||
{
|
||||
ValueLocation* location = node->NodeChild()->Location();
|
||||
|
||||
// if the location's stored somewhere other than in memory,
|
||||
// then we won't be able to inspect it this way.
|
||||
if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY)
|
||||
return B_OK;
|
||||
|
||||
BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW);
|
||||
if (message == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ObjectDeleter<BMessage> messageDeleter(message);
|
||||
message->AddUInt64("address", location->PieceAt(0).address);
|
||||
|
||||
ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect",
|
||||
message);
|
||||
if (item == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
messageDeleter.Detach();
|
||||
ObjectDeleter<ActionMenuItem> actionDeleter(item);
|
||||
if (!actions->AddItem(item))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
actionDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VariablesView::_FinishContextMenu(bool force)
|
||||
{
|
||||
|
@ -68,8 +68,9 @@ private:
|
||||
void _Init();
|
||||
|
||||
void _RequestNodeValue(ModelNode* node);
|
||||
status_t _GetContextActionsForNode(ModelNode* node,
|
||||
ContextActionList* actions);
|
||||
void _FinishContextMenu(bool force);
|
||||
|
||||
void _SaveViewState() const;
|
||||
void _RestoreViewState();
|
||||
status_t _AddViewStateDescendentNodeInfos(
|
||||
|
Loading…
Reference in New Issue
Block a user