Author: bonefish Date: 2009-12-09 16:31:39 +0100 (Wed, 09 Dec 2009) New Revision: 34590 Changeset: http://dev.haiku-os.org/changeset/34590/haiku Modified: haiku/trunk/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp Log: 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. Modified: haiku/trunk/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp =================================================================== --- haiku/trunk/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp 2009-12-09 15:27:14 UTC (rev 34589) +++ haiku/trunk/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp 2009-12-09 15:31:39 UTC (rev 34590) @@ -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 @@ fListener->DataRangeChanged(); } - void MessageReceived(BMessage* message) + virtual void MessageReceived(BMessage* message) { switch (message->what) { case B_MOUSE_WHEEL_CHANGED: @@ -659,7 +661,8 @@ 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 @@ // + 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 @@ } } + 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))