Added support for filtering the thread list (context menu).

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34575 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-08 23:26:38 +00:00
parent 63481b10d3
commit 815678a637
2 changed files with 140 additions and 26 deletions
@@ -13,6 +13,8 @@
#include <LayoutBuilder.h> #include <LayoutBuilder.h>
#include <LayoutUtils.h> #include <LayoutUtils.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <ScrollView.h> #include <ScrollView.h>
#include <SplitView.h> #include <SplitView.h>
@@ -33,6 +35,12 @@ static const float kThreadNameMargin = 3.0f;
static const float kViewSeparationMargin = 1.0f; static const float kViewSeparationMargin = 1.0f;
enum {
MSG_SCHEDULING_FILTER = 'schf',
MSG_SCHEDULING_RESET_FILTER = 'schr'
};
struct MainWindow::SchedulingPage::SchedulingEvent { struct MainWindow::SchedulingPage::SchedulingEvent {
nanotime_t time; nanotime_t time;
Model::ThreadWaitObjectGroup* waitObject; Model::ThreadWaitObjectGroup* waitObject;
@@ -223,10 +231,12 @@ private:
class MainWindow::SchedulingPage::BaseView : public BView { class MainWindow::SchedulingPage::BaseView : public BView {
public: public:
BaseView(const char* name, FontInfo& fontInfo, uint32 flags = 0) BaseView(const char* name, FontInfo& fontInfo,
ListSelectionModel* filterModel, uint32 flags = 0)
: :
BView(name, flags), BView(name, flags),
fModel(NULL), fModel(NULL),
fFilterModel(filterModel),
fFontInfo(fontInfo) fFontInfo(fontInfo)
{ {
} }
@@ -241,7 +251,7 @@ public:
protected: protected:
int32 CountLines() const int32 CountLines() const
{ {
return fModel != NULL ? fModel->CountThreads() : 0; return fFilterModel->CountSelectedItems();
} }
float TotalHeight() const float TotalHeight() const
@@ -271,8 +281,9 @@ protected:
} }
protected: protected:
Model* fModel; Model* fModel;
FontInfo& fFontInfo; ListSelectionModel* fFilterModel;
FontInfo& fFontInfo;
}; };
@@ -280,21 +291,71 @@ class MainWindow::SchedulingPage::LineBaseView : public BaseView,
protected ListSelectionModel::Listener { protected ListSelectionModel::Listener {
public: public:
LineBaseView(const char* name, FontInfo& fontInfo, LineBaseView(const char* name, FontInfo& fontInfo,
ListSelectionModel* selectionModel) ListSelectionModel* filterModel, ListSelectionModel* selectionModel)
: :
BaseView(name, fontInfo, B_WILL_DRAW), BaseView(name, fontInfo, filterModel, B_WILL_DRAW),
fSelectionModel(selectionModel), fSelectionModel(selectionModel),
fTextColor(ui_color(B_DOCUMENT_TEXT_COLOR)), fTextColor(ui_color(B_DOCUMENT_TEXT_COLOR)),
fSelectedTextColor(fTextColor), fSelectedTextColor(fTextColor),
fBackgroundColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR)), fBackgroundColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR)),
fSelectedBackgroundColor(tint_color(fBackgroundColor, B_DARKEN_2_TINT)) fSelectedBackgroundColor(tint_color(fBackgroundColor, B_DARKEN_2_TINT))
{ {
fFilterModel->AddListener(this);
fSelectionModel->AddListener(this); fSelectionModel->AddListener(this);
} }
void RemoveListeners() void RemoveListeners()
{ {
fSelectionModel->RemoveListener(this); fSelectionModel->RemoveListener(this);
fFilterModel->RemoveListener(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SCHEDULING_FILTER:
{
int32 threadCount = fModel->CountThreads();
int32 selectedCount = fSelectionModel->CountSelectedItems();
if (selectedCount == 0 || selectedCount == threadCount)
break;
// Set the filter model to the selected items.
// There might already be a filter applied, so we have to
// build the new filter model manually.
ListSelectionModel tempModel;
for (int32 i = 0; i < selectedCount; i++) {
int32 index = fFilterModel->SelectedItemAt(
fSelectionModel->SelectedItemAt(i));
if (index >= 0)
tempModel.SelectItem(index, true);
}
fSelectionModel->Clear();
*fFilterModel = tempModel;
Invalidate();
break;
}
case MSG_SCHEDULING_RESET_FILTER:
{
int32 threadCount = fModel->CountThreads();
if (fFilterModel->CountSelectedItems() == threadCount)
break;
// unset the filter
ListSelectionModel tempModel = *fFilterModel;
fSelectionModel->Clear();
fFilterModel->SelectItems(0, threadCount, false);
*fSelectionModel = tempModel;
Invalidate();
break;
}
default:
BaseView::MessageReceived(message);
break;
}
} }
virtual void MouseDown(BPoint where) virtual void MouseDown(BPoint where)
@@ -312,6 +373,7 @@ public:
if (message->FindInt32("modifiers", &modifiers) != B_OK) if (message->FindInt32("modifiers", &modifiers) != B_OK)
modifiers = 0; modifiers = 0;
// update selection
int32 line = LineAt(where); int32 line = LineAt(where);
if (line >= 0) { if (line >= 0) {
if ((modifiers & B_SHIFT_KEY) != 0) { if ((modifiers & B_SHIFT_KEY) != 0) {
@@ -337,18 +399,49 @@ public:
} }
} else } else
fSelectionModel->Clear(); fSelectionModel->Clear();
// on right mouse button open context menu
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0 && fModel != NULL) {
BPopUpMenu* contextMenu = new BPopUpMenu("scheduling context menu",
false, false);
BMenuItem* item = new BMenuItem("Filter",
new BMessage(MSG_SCHEDULING_FILTER));
contextMenu->AddItem(item);
item->SetTarget(this);
if (fSelectionModel->CountSelectedItems() == 0)
item->SetEnabled(false);
item = new BMenuItem("Reset Filter",
new BMessage(MSG_SCHEDULING_RESET_FILTER));
contextMenu->AddItem(item);
item->SetTarget(this);
if (fFilterModel->CountSelectedItems() == fModel->CountThreads())
item->SetEnabled(false);
BPoint screenWhere = ConvertToScreen(where);
BRect mouseRect(screenWhere, screenWhere);
mouseRect.InsetBy(-4.0, -4.0);
contextMenu->Go(screenWhere, true, false, mouseRect, true);
}
} }
virtual void ItemsSelected(ListSelectionModel* model, int32 index, virtual void ItemsSelected(ListSelectionModel* model, int32 index,
int32 count) int32 count)
{ {
InvalidateLines(index, count); if (model == fFilterModel)
Invalidate();
else
InvalidateLines(index, count);
} }
virtual void ItemsDeselected(ListSelectionModel* model, int32 index, virtual void ItemsDeselected(ListSelectionModel* model, int32 index,
int32 count) int32 count)
{ {
InvalidateLines(index, count); if (model == fFilterModel)
Invalidate();
else
InvalidateLines(index, count);
} }
void InvalidateLines(int32 index, int32 count) void InvalidateLines(int32 index, int32 count)
@@ -370,9 +463,10 @@ protected:
class MainWindow::SchedulingPage::ThreadsView : public LineBaseView { class MainWindow::SchedulingPage::ThreadsView : public LineBaseView {
public: public:
ThreadsView(FontInfo& fontInfo, ListSelectionModel* selectionModel) ThreadsView(FontInfo& fontInfo, ListSelectionModel* filterModel,
ListSelectionModel* selectionModel)
: :
LineBaseView("threads", fontInfo, selectionModel) LineBaseView("threads", fontInfo, filterModel, selectionModel)
{ {
SetViewColor(B_TRANSPARENT_32_BIT); SetViewColor(B_TRANSPARENT_32_BIT);
} }
@@ -402,10 +496,14 @@ public:
} }
FillRect(lineRect, B_SOLID_LOW); FillRect(lineRect, B_SOLID_LOW);
Model::Thread* thread = fModel->ThreadAt(
fFilterModel->SelectedItemAt(i));
if (thread == NULL)
continue;
// draw the string // draw the string
float y = lineRect.bottom - fFontInfo.fontHeight.descent + 1; float y = lineRect.bottom - fFontInfo.fontHeight.descent + 1;
DrawString(fModel->ThreadAt(i)->Name(), DrawString(thread->Name(), BPoint(kThreadNameMargin, y));
BPoint(kThreadNameMargin, y));
} }
BRect bounds(Bounds()); BRect bounds(Bounds());
@@ -449,9 +547,10 @@ private:
}; };
public: public:
SchedulingView(FontInfo& fontInfo, ListSelectionModel* selectionModel) SchedulingView(FontInfo& fontInfo, ListSelectionModel* filterModel,
ListSelectionModel* selectionModel)
: :
LineBaseView("scheduling", fontInfo, selectionModel), LineBaseView("scheduling", fontInfo, filterModel, selectionModel),
fStartTime(0), fStartTime(0),
fEndTime(0), fEndTime(0),
fNSecsPerPixel(1000000), fNSecsPerPixel(1000000),
@@ -557,7 +656,7 @@ public:
} }
} }
BView::MessageReceived(message); LineBaseView::MessageReceived(message);
} }
void MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) void MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
@@ -579,9 +678,12 @@ public:
_UpdateData(); _UpdateData();
// draw the events // draw the events
// TODO: Draw only the threads currently visible.
int32 threadCount = fModel->CountThreads(); // get the lines intersecting with the update rect
for (int32 i = 0; i < threadCount; i++) { int32 minLine, maxLine;
GetLineRange(updateRect, minLine, maxLine);
for (int32 i = minLine; i <= maxLine; i++) {
// draw the background // draw the background
const rgb_color* activityColors; const rgb_color* activityColors;
if (fSelectionModel->IsItemSelected(i)) { if (fSelectionModel->IsItemSelected(i)) {
@@ -591,9 +693,14 @@ public:
activityColors = fActivityColors; activityColors = fActivityColors;
SetLowColor(fBackgroundColor); SetLowColor(fBackgroundColor);
} }
FillRect(LineRect(i), B_SOLID_LOW); BRect lineRect = LineRect(i);
FillRect(lineRect, B_SOLID_LOW);
Model::Thread* thread = fModel->ThreadAt(
fFilterModel->SelectedItemAt(i));
if (thread == NULL)
continue;
Model::Thread* thread = fModel->ThreadAt(i);
const Array<SchedulingEvent>& events const Array<SchedulingEvent>& events
= fSchedulingData.EventsForThread(thread->Index()); = fSchedulingData.EventsForThread(thread->Index());
@@ -622,7 +729,7 @@ public:
continue; continue;
} }
BRect rect = LineRect(i); BRect rect = lineRect;
rect.left = startTime / fNSecsPerPixel; rect.left = startTime / fNSecsPerPixel;
rect.right = endTime / fNSecsPerPixel - 1; rect.right = endTime / fNSecsPerPixel - 1;
FillRect(rect); FillRect(rect);
@@ -1038,9 +1145,10 @@ class MainWindow::SchedulingPage::ViewPort : public BaseView,
private HeaderListener, private SchedulingView::Listener { private HeaderListener, private SchedulingView::Listener {
public: public:
ViewPort(HeaderView* headerView, ThreadsView* threadsView, ViewPort(HeaderView* headerView, ThreadsView* threadsView,
SchedulingView* schedulingView, FontInfo& fontInfo) SchedulingView* schedulingView, FontInfo& fontInfo,
ListSelectionModel* filterModel)
: :
BaseView("viewport", fontInfo), BaseView("viewport", fontInfo, filterModel),
fHeaderView(headerView), fHeaderView(headerView),
fThreadsView(threadsView), fThreadsView(threadsView),
fSchedulingView(schedulingView) fSchedulingView(schedulingView)
@@ -1191,6 +1299,7 @@ MainWindow::SchedulingPage::SchedulingPage(MainWindow* parent)
fViewPort(NULL), fViewPort(NULL),
fThreadsView(NULL), fThreadsView(NULL),
fSchedulingView(NULL), fSchedulingView(NULL),
fFilterModel(),
fSelectionModel() fSelectionModel()
{ {
SetName("Scheduling"); SetName("Scheduling");
@@ -1203,9 +1312,11 @@ MainWindow::SchedulingPage::SchedulingPage(MainWindow* parent)
BView* scrollChild = BLayoutBuilder::Group<>(B_VERTICAL) BView* scrollChild = BLayoutBuilder::Group<>(B_VERTICAL)
.Add(headerView) .Add(headerView)
.Add(fViewPort = new ViewPort(headerView, .Add(fViewPort = new ViewPort(headerView,
fThreadsView = new ThreadsView(fFontInfo, &fSelectionModel), fThreadsView = new ThreadsView(fFontInfo, &fFilterModel,
fSchedulingView = new SchedulingView(fFontInfo, &fSelectionModel), &fSelectionModel),
fFontInfo)) fSchedulingView = new SchedulingView(fFontInfo, &fFilterModel,
&fSelectionModel),
fFontInfo, &fFilterModel))
; ;
AddChild(fScrollView = new BScrollView("scroll", scrollChild, 0, true, AddChild(fScrollView = new BScrollView("scroll", scrollChild, 0, true,
@@ -1232,6 +1343,7 @@ MainWindow::SchedulingPage::SetModel(Model* model)
return; return;
fSelectionModel.Clear(); fSelectionModel.Clear();
fFilterModel.Clear();
if (fModel != NULL) { if (fModel != NULL) {
} }
@@ -1239,6 +1351,7 @@ MainWindow::SchedulingPage::SetModel(Model* model)
fModel = model; fModel = model;
if (fModel != NULL) { if (fModel != NULL) {
fFilterModel.SelectItems(0, fModel->CountThreads(), false);
} }
fViewPort->SetModel(fModel); fViewPort->SetModel(fModel);
@@ -49,6 +49,7 @@ private:
ThreadsView* fThreadsView; ThreadsView* fThreadsView;
SchedulingView* fSchedulingView; SchedulingView* fSchedulingView;
FontInfo fFontInfo; FontInfo fFontInfo;
ListSelectionModel fFilterModel;
ListSelectionModel fSelectionModel; ListSelectionModel fSelectionModel;
}; };