Initial implementation of #9755.
- ImageFunctionsView now contains a text input allowing one to specify a filter for its contained functions. - When in filtered mode, the previous flattened view is used rather than the hierarchical tree. - The matching portion of the string is highlighted. However, currently only simple string matches are supported.
This commit is contained in:
@@ -11,7 +11,10 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include <LayoutBuilder.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
#include <StringList.h>
|
#include <StringList.h>
|
||||||
|
#include <TextControl.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
@@ -25,6 +28,15 @@
|
|||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 MSG_FUNCTION_FILTER_CHANGED = 'mffc';
|
||||||
|
static const uint32 MSG_FUNCTION_TYPING_TIMEOUT = 'mftt';
|
||||||
|
|
||||||
|
static const uint32 kKeypressTimeout = 250000;
|
||||||
|
|
||||||
|
// from ColumnTypes.cpp
|
||||||
|
static const float kTextMargin = 8.0;
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - SourcePathComponentNode
|
// #pragma mark - SourcePathComponentNode
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +163,65 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HighlightingTableColumn
|
||||||
|
|
||||||
|
|
||||||
|
class ImageFunctionsView::HighlightingTableColumn : public StringTableColumn {
|
||||||
|
public:
|
||||||
|
HighlightingTableColumn(int32 modelIndex, const char* title, float width,
|
||||||
|
float minWidth, float maxWidth, uint32 truncate,
|
||||||
|
alignment align = B_ALIGN_LEFT)
|
||||||
|
:
|
||||||
|
StringTableColumn(modelIndex, title, width, minWidth, maxWidth,
|
||||||
|
truncate, align),
|
||||||
|
fFilter(),
|
||||||
|
fFilterWidth(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFilter(const BString& filter)
|
||||||
|
{
|
||||||
|
fFilter = filter;
|
||||||
|
fFilterWidth = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawValue(const BVariant& value, BRect rect,
|
||||||
|
BView* targetView)
|
||||||
|
{
|
||||||
|
StringTableColumn::DrawValue(value, rect, targetView);
|
||||||
|
|
||||||
|
if (!fFilter.IsEmpty()) {
|
||||||
|
if (fFilterWidth == 0.0)
|
||||||
|
fFilterWidth = targetView->StringWidth(fFilter);
|
||||||
|
|
||||||
|
// TODO: handle this case as well
|
||||||
|
if (fField.HasClippedString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* fieldString = fField.String();
|
||||||
|
const char* filterMatch = strstr(fieldString, fFilter.String());
|
||||||
|
if (filterMatch == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
targetView->PushState();
|
||||||
|
BRect fillRect(rect);
|
||||||
|
fillRect.left += kTextMargin + targetView->StringWidth(
|
||||||
|
fieldString, filterMatch - fieldString);
|
||||||
|
fillRect.right = fillRect.left + fFilterWidth;
|
||||||
|
targetView->SetLowColor(255, 255, 0, 255);
|
||||||
|
targetView->SetDrawingMode(B_OP_MIN);
|
||||||
|
targetView->FillRect(fillRect, B_SOLID_LOW);
|
||||||
|
targetView->PopState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fFilter;
|
||||||
|
float fFilterWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - FunctionsTableModel
|
// #pragma mark - FunctionsTableModel
|
||||||
|
|
||||||
|
|
||||||
@@ -198,6 +269,7 @@ public:
|
|||||||
|
|
||||||
LocatableFile* currentFile = NULL;
|
LocatableFile* currentFile = NULL;
|
||||||
BStringList pathComponents;
|
BStringList pathComponents;
|
||||||
|
bool applyFilter = !fCurrentFilter.IsEmpty();
|
||||||
int32 functionCount = fImageDebugInfo->CountFunctions();
|
int32 functionCount = fImageDebugInfo->CountFunctions();
|
||||||
for (int32 i = 0; i < functionCount; i++) {
|
for (int32 i = 0; i < functionCount; i++) {
|
||||||
FunctionInstance* instance = fImageDebugInfo->FunctionAt(i);
|
FunctionInstance* instance = fImageDebugInfo->FunctionAt(i);
|
||||||
@@ -213,6 +285,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
LocatableFile* sourceFile = instance->SourceFile();
|
LocatableFile* sourceFile = instance->SourceFile();
|
||||||
|
BString sourcePath;
|
||||||
|
if (sourceFile != NULL)
|
||||||
|
sourceFile->GetPath(sourcePath);
|
||||||
|
|
||||||
|
if (applyFilter && !_FilterFunction(instance, sourcePath))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (sourceFile == NULL) {
|
if (sourceFile == NULL) {
|
||||||
if (!_AddFunctionNode(sourcelessNode, instance, NULL))
|
if (!_AddFunctionNode(sourcelessNode, instance, NULL))
|
||||||
return;
|
return;
|
||||||
@@ -221,9 +300,14 @@ public:
|
|||||||
|
|
||||||
if (sourceFile != currentFile) {
|
if (sourceFile != currentFile) {
|
||||||
currentFile = sourceFile;
|
currentFile = sourceFile;
|
||||||
if (!_GetSourcePathComponents(currentFile,
|
pathComponents.MakeEmpty();
|
||||||
|
if (applyFilter) {
|
||||||
|
pathComponents.Add(sourcePath);
|
||||||
|
} else {
|
||||||
|
if (!_GetSourcePathComponents(currentFile,
|
||||||
pathComponents)) {
|
pathComponents)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,6 +435,13 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetFilter(const char* filter)
|
||||||
|
{
|
||||||
|
fCurrentFilter = filter;
|
||||||
|
|
||||||
|
SetImageDebugInfo(fImageDebugInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _GetSourcePathComponents(LocatableFile* currentFile,
|
bool _GetSourcePathComponents(LocatableFile* currentFile,
|
||||||
BStringList& pathComponents)
|
BStringList& pathComponents)
|
||||||
@@ -360,8 +451,6 @@ private:
|
|||||||
if (sourcePath.IsEmpty())
|
if (sourcePath.IsEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pathComponents.MakeEmpty();
|
|
||||||
|
|
||||||
int32 startIndex = 0;
|
int32 startIndex = 0;
|
||||||
if (sourcePath[0] == '/')
|
if (sourcePath[0] == '/')
|
||||||
startIndex = 1;
|
startIndex = 1;
|
||||||
@@ -438,6 +527,15 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _FilterFunction(FunctionInstance* instance, const BString& sourcePath)
|
||||||
|
{
|
||||||
|
if (instance->PrettyName().IFindFirst(fCurrentFilter) >= 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return sourcePath.IFindFirst(fCurrentFilter) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BObjectList<SourcePathComponentNode> ChildPathComponentList;
|
typedef BObjectList<SourcePathComponentNode> ChildPathComponentList;
|
||||||
|
|
||||||
@@ -445,6 +543,7 @@ private:
|
|||||||
ImageDebugInfo* fImageDebugInfo;
|
ImageDebugInfo* fImageDebugInfo;
|
||||||
ChildPathComponentList fChildPathComponents;
|
ChildPathComponentList fChildPathComponents;
|
||||||
SourcePathComponentNode* fSourcelessNode;
|
SourcePathComponentNode* fSourcelessNode;
|
||||||
|
BString fCurrentFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -455,9 +554,12 @@ ImageFunctionsView::ImageFunctionsView(Listener* listener)
|
|||||||
:
|
:
|
||||||
BGroupView(B_VERTICAL),
|
BGroupView(B_VERTICAL),
|
||||||
fImageDebugInfo(NULL),
|
fImageDebugInfo(NULL),
|
||||||
|
fFilterField(NULL),
|
||||||
fFunctionsTable(NULL),
|
fFunctionsTable(NULL),
|
||||||
fFunctionsTableModel(NULL),
|
fFunctionsTableModel(NULL),
|
||||||
fListener(listener)
|
fListener(listener),
|
||||||
|
fHighlightingColumn(NULL),
|
||||||
|
fLastFilterKeypress(0)
|
||||||
{
|
{
|
||||||
SetName("Functions");
|
SetName("Functions");
|
||||||
}
|
}
|
||||||
@@ -544,6 +646,45 @@ ImageFunctionsView::SetFunction(FunctionInstance* function)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageFunctionsView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BView::AttachedToWindow();
|
||||||
|
|
||||||
|
fFilterField->SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageFunctionsView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_FUNCTION_FILTER_CHANGED:
|
||||||
|
{
|
||||||
|
fLastFilterKeypress = system_time();
|
||||||
|
BMessage keypressMessage(MSG_FUNCTION_TYPING_TIMEOUT);
|
||||||
|
BMessageRunner::StartSending(BMessenger(this), &keypressMessage,
|
||||||
|
kKeypressTimeout, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MSG_FUNCTION_TYPING_TIMEOUT:
|
||||||
|
{
|
||||||
|
if (system_time() - fLastFilterKeypress >= kKeypressTimeout) {
|
||||||
|
fFunctionsTableModel->SetFilter(fFilterField->Text());
|
||||||
|
fHighlightingColumn->SetFilter(fFilterField->Text());
|
||||||
|
_ExpandFilteredNodes();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageFunctionsView::LoadSettings(const BMessage& settings)
|
ImageFunctionsView::LoadSettings(const BMessage& settings)
|
||||||
{
|
{
|
||||||
@@ -591,11 +732,17 @@ ImageFunctionsView::_Init()
|
|||||||
{
|
{
|
||||||
fFunctionsTable = new TreeTable("functions", 0, B_FANCY_BORDER);
|
fFunctionsTable = new TreeTable("functions", 0, B_FANCY_BORDER);
|
||||||
AddChild(fFunctionsTable->ToView());
|
AddChild(fFunctionsTable->ToView());
|
||||||
|
AddChild(fFilterField = new BTextControl("filtertext", "Filter:",
|
||||||
|
NULL, NULL));
|
||||||
|
|
||||||
|
fFilterField->SetModificationMessage(new BMessage(
|
||||||
|
MSG_FUNCTION_FILTER_CHANGED));
|
||||||
fFunctionsTable->SetSortingEnabled(false);
|
fFunctionsTable->SetSortingEnabled(false);
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
fFunctionsTable->AddColumn(new StringTableColumn(0, "File/Function", 300,
|
fFunctionsTable->AddColumn(fHighlightingColumn
|
||||||
100, 1000, B_TRUNCATE_BEGINNING, B_ALIGN_LEFT));
|
= new HighlightingTableColumn(0, "File/Function", 300, 100, 1000,
|
||||||
|
B_TRUNCATE_BEGINNING, B_ALIGN_LEFT));
|
||||||
|
|
||||||
fFunctionsTableModel = new FunctionsTableModel();
|
fFunctionsTableModel = new FunctionsTableModel();
|
||||||
fFunctionsTable->SetTreeTableModel(fFunctionsTableModel);
|
fFunctionsTable->SetTreeTableModel(fFunctionsTableModel);
|
||||||
@@ -605,6 +752,23 @@ ImageFunctionsView::_Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageFunctionsView::_ExpandFilteredNodes()
|
||||||
|
{
|
||||||
|
if (fFilterField->TextView()->TextLength() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fFunctionsTableModel->CountChildren(
|
||||||
|
fFunctionsTableModel); i++) {
|
||||||
|
TreeTablePath path;
|
||||||
|
path.AddComponent(i);
|
||||||
|
fFunctionsTable->SetNodeExpanded(path, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fFunctionsTable->ResizeAllColumnsToPreferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Listener
|
// #pragma mark - Listener
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BTextControl;
|
||||||
class FunctionInstance;
|
class FunctionInstance;
|
||||||
|
|
||||||
|
|
||||||
@@ -31,12 +32,15 @@ public:
|
|||||||
void SetImageDebugInfo(
|
void SetImageDebugInfo(
|
||||||
ImageDebugInfo* imageDebugInfo);
|
ImageDebugInfo* imageDebugInfo);
|
||||||
void SetFunction(FunctionInstance* function);
|
void SetFunction(FunctionInstance* function);
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
void LoadSettings(const BMessage& settings);
|
void LoadSettings(const BMessage& settings);
|
||||||
status_t SaveSettings(BMessage& settings);
|
status_t SaveSettings(BMessage& settings);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class FunctionsTableModel;
|
class FunctionsTableModel;
|
||||||
|
class HighlightingTableColumn;
|
||||||
class SourcePathComponentNode;
|
class SourcePathComponentNode;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -45,11 +49,16 @@ private:
|
|||||||
|
|
||||||
void _Init();
|
void _Init();
|
||||||
|
|
||||||
|
void _ExpandFilteredNodes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImageDebugInfo* fImageDebugInfo;
|
ImageDebugInfo* fImageDebugInfo;
|
||||||
|
BTextControl* fFilterField;
|
||||||
TreeTable* fFunctionsTable;
|
TreeTable* fFunctionsTable;
|
||||||
FunctionsTableModel* fFunctionsTableModel;
|
FunctionsTableModel* fFunctionsTableModel;
|
||||||
Listener* fListener;
|
Listener* fListener;
|
||||||
|
HighlightingTableColumn* fHighlightingColumn;
|
||||||
|
bigtime_t fLastFilterKeypress;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user