Added tool tips to the SchedulingView. A tool tip shows the time and the

thread at the mouse cursor position as well as the thread's state, how long
the thread has been in this state, and what threads are running on all CPUs.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34590 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-09 15:31:39 +00:00
parent b1627c9e23
commit 951be023f9
@@ -17,6 +17,7 @@
#include <PopUpMenu.h>
#include <ScrollView.h>
#include <SplitView.h>
#include <ToolTip.h>
#include <DebugEventStream.h>
@@ -29,6 +30,7 @@
#include "chart/StringChartLegend.h"
#include "HeaderView.h"
#include "Model.h"
#include "util/TimeUtils.h"
static const float kThreadNameMargin = 3.0f;
@@ -637,7 +639,7 @@ public:
fListener->DataRangeChanged();
}
void MessageReceived(BMessage* message)
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case B_MOUSE_WHEEL_CHANGED:
@@ -659,7 +661,8 @@ public:
LineBaseView::MessageReceived(message);
}
void MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
virtual void MouseMoved(BPoint where, uint32 code,
const BMessage* dragMessage)
{
fLastMousePos = where - LeftTop();
@@ -670,6 +673,105 @@ public:
// + fDraggingStartPos.x - where.x);
}
virtual bool GetToolTipAt(BPoint point, BToolTip** _tip)
{
Model::Thread* thread;
nanotime_t time;
_GetThreadAndTimeAt(point, thread, time);
if (thread == NULL)
return false;
ThreadState threadState = UNKNOWN;
nanotime_t threadStateTime = time;
nanotime_t threadStateEndTime = time;
Model::ThreadWaitObjectGroup* threadWaitObject = NULL;
// get the thread's state
{
const Array<SchedulingEvent>& threadEvents
= fSchedulingData.EventsForThread(thread->Index());
int32 threadEventCount = threadEvents.Size();
int32 lower = 0;
int32 upper = threadEventCount - 1;
while (lower < upper) {
int32 mid = (lower + upper + 1) / 2;
const SchedulingEvent& event = threadEvents[mid];
if (event.time > time)
upper = mid - 1;
else
lower = mid;
}
if (lower >= 0 && lower < threadEventCount) {
threadState = threadEvents[lower].state;
threadStateTime = threadEvents[lower].time;
threadWaitObject = threadEvents[lower].waitObject;
if (lower + 1 < threadEventCount)
threadStateEndTime = threadEvents[lower + 1].time;
else
threadStateEndTime = fModel->LastEventTime();
}
}
// find out which threads are running
system_profiler_event_header** events = fModel->Events();
size_t eventIndex = fModel->ClosestEventIndex(time + 1);
// find the first event after the one we're interested in; we'll
// skip it in the loop
int32 cpuCount = fModel->CountCPUs();
int32 missingThreads = cpuCount;
Model::Thread* runningThreads[cpuCount];
memset(runningThreads, 0, sizeof(Model::Thread*) * cpuCount);
while (missingThreads > 0 && eventIndex > 0) {
eventIndex--;
system_profiler_event_header* header = events[eventIndex];
if (header->event != B_SYSTEM_PROFILER_THREAD_SCHEDULED
|| runningThreads[header->cpu] != NULL) {
continue;
}
system_profiler_thread_scheduled* event
= (system_profiler_thread_scheduled*)(header + 1);
if (Model::Thread* thread = fModel->ThreadByID(event->thread)) {
runningThreads[header->cpu] = thread;
missingThreads--;
}
}
// create the tool tip
BString text;
text << "Time: " << format_nanotime(time) << "\n";
text << "Thread: " << thread->Name() << "\n";
text << "State: " << thread_state_name(threadState);
if (threadWaitObject != NULL) {
char objectName[32];
snprintf(objectName, sizeof(objectName), "%#lx",
threadWaitObject->Object());
text << " at " << wait_object_type_name(threadWaitObject->Type())
<< " \"" << threadWaitObject->Name() << "\" "
<< objectName << "\n";
} else
text << "\n";
text << "For: " << format_nanotime(time - threadStateTime) << " of "
<< format_nanotime(threadStateEndTime - threadStateTime) << "\n";
text << "\n";
text << "Running Threads:";
for (int32 i = 0; i < cpuCount; i++) {
text << "\n " << i << ": ";
if (Model::Thread* thread = runningThreads[i])
text << thread->Name() << " (" << thread->ID() << ")";
else
text << "?";
}
*_tip = new(std::nothrow) BTextToolTip(text);
return *_tip != NULL;
}
virtual void Draw(BRect updateRect)
{
if (fModel == NULL || fSchedulingData.InitCheck() != B_OK)
@@ -866,6 +968,14 @@ printf("failed to read event!\n");
}
}
void _GetThreadAndTimeAt(BPoint point, Model::Thread*& _thread,
nanotime_t& _time)
{
_thread = fModel->ThreadAt(
fFilterModel->SelectedItemAt(LineAt(point)));
_time = (nanotime_t)point.x * fNSecsPerPixel;
}
float _ScrollOffset() const
{
if (BScrollBar* scrollBar = ScrollBar(B_HORIZONTAL))