* SourceView can now show markers for stack frame instruction pointers.
Furthermore it automatically scrolls to the current IP of the currently
selected stack frame.
* TeamWindow:
- Be lazy setting the SourceCode, i.e. as long as no other source shall be
shown (e.g. another stack frame is selected) we keep the previous one.
- When a new stack strace is set, automatically select the top-most frame.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31170 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,32 +11,118 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <LayoutUtils.h>
|
#include <LayoutUtils.h>
|
||||||
|
#include <Polygon.h>
|
||||||
#include <ScrollBar.h>
|
#include <ScrollBar.h>
|
||||||
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
#include "SourceCode.h"
|
#include "SourceCode.h"
|
||||||
#include "StackFrame.h"
|
#include "StackTrace.h"
|
||||||
|
#include "Statement.h"
|
||||||
#include "TeamDebugModel.h"
|
#include "TeamDebugModel.h"
|
||||||
|
|
||||||
|
|
||||||
static const int32 kLeftTextMargin = 3;
|
static const int32 kLeftTextMargin = 3;
|
||||||
|
static const float kMinViewHeight = 80.0f;
|
||||||
|
|
||||||
|
|
||||||
class SourceView::MarkerView : public BView {
|
class SourceView::BaseView : public BView {
|
||||||
|
public:
|
||||||
|
BaseView(const char* name, SourceView* sourceView, FontInfo* fontInfo)
|
||||||
|
:
|
||||||
|
BView(name, B_WILL_DRAW | B_SUBPIXEL_PRECISE),
|
||||||
|
fSourceView(sourceView),
|
||||||
|
fFontInfo(fontInfo),
|
||||||
|
fSourceCode(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetSourceCode(SourceCode* sourceCode)
|
||||||
|
{
|
||||||
|
fSourceCode = sourceCode;
|
||||||
|
|
||||||
|
InvalidateLayout();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize PreferredSize()
|
||||||
|
{
|
||||||
|
return MinSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32 LineCount() const
|
||||||
|
{
|
||||||
|
return fSourceCode != NULL ? fSourceCode->CountLines() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TotalHeight() const
|
||||||
|
{
|
||||||
|
float height = LineCount() * fFontInfo->lineHeight - 1;
|
||||||
|
return std::max(height, kMinViewHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetLineRange(BRect rect, int32& minLine, int32& maxLine)
|
||||||
|
{
|
||||||
|
int32 lineHeight = (int32)fFontInfo->lineHeight;
|
||||||
|
minLine = (int32)rect.top / lineHeight;
|
||||||
|
maxLine = ((int32)ceilf(rect.bottom) + lineHeight - 1) / lineHeight;
|
||||||
|
minLine = std::max(minLine, 0L);
|
||||||
|
maxLine = std::min(maxLine, fSourceCode->CountLines() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SourceView* fSourceView;
|
||||||
|
FontInfo* fFontInfo;
|
||||||
|
SourceCode* fSourceCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SourceView::MarkerView : public BaseView {
|
||||||
public:
|
public:
|
||||||
MarkerView(SourceView* sourceView, FontInfo* fontInfo)
|
MarkerView(SourceView* sourceView, FontInfo* fontInfo)
|
||||||
:
|
:
|
||||||
BView("source marker view", B_WILL_DRAW),
|
BaseView("source marker view", sourceView, fontInfo),
|
||||||
fSourceView(sourceView),
|
fStackTrace(NULL),
|
||||||
fFontInfo(fontInfo)
|
fStackFrame(NULL),
|
||||||
|
fMarkers(20, true),
|
||||||
|
fMarkersValid(false)
|
||||||
{
|
{
|
||||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~MarkerView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetSourceCode(SourceCode* sourceCode)
|
||||||
|
{
|
||||||
|
fMarkers.MakeEmpty();
|
||||||
|
fMarkersValid = false;
|
||||||
|
BaseView::SetSourceCode(sourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStackTrace(StackTrace* stackTrace)
|
||||||
|
{
|
||||||
|
fStackTrace = stackTrace;
|
||||||
|
fMarkers.MakeEmpty();
|
||||||
|
fMarkersValid = false;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStackFrame(StackFrame* stackFrame)
|
||||||
|
{
|
||||||
|
fStackFrame = stackFrame;
|
||||||
|
fMarkers.MakeEmpty();
|
||||||
|
fMarkersValid = false;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
virtual BSize MinSize()
|
virtual BSize MinSize()
|
||||||
{
|
{
|
||||||
return BSize(40, 10);
|
return BSize(40, TotalHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BSize MaxSize()
|
virtual BSize MaxSize()
|
||||||
@@ -44,49 +130,184 @@ public:
|
|||||||
return BSize(MinSize().width, B_SIZE_UNLIMITED);
|
return BSize(MinSize().width, B_SIZE_UNLIMITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BSize PreferredSize()
|
|
||||||
{
|
|
||||||
return MinSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Draw(BRect updateRect)
|
virtual void Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
|
_UpdateMarkers();
|
||||||
|
|
||||||
|
if (fSourceCode == NULL || fMarkers.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get the lines intersecting with the update rect
|
||||||
|
int32 minLine, maxLine;
|
||||||
|
GetLineRange(updateRect, minLine, maxLine);
|
||||||
|
|
||||||
|
// draw the markers
|
||||||
|
float width = Bounds().Width();
|
||||||
|
// TODO: The markers should be sorted, so we don't need to iterate over
|
||||||
|
// all of them.
|
||||||
|
for (int32 i = 0; Marker* marker = fMarkers.ItemAt(i); i++) {
|
||||||
|
int32 line = marker->Line();
|
||||||
|
if (line < minLine || line > maxLine)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float y = (float)line * fFontInfo->lineHeight;
|
||||||
|
BRect rect(0, y, width, y + fFontInfo->lineHeight - 1);
|
||||||
|
marker->Draw(this, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Draw possible breakpoint marks!
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SourceView* fSourceView;
|
struct Marker {
|
||||||
FontInfo* fFontInfo;
|
Marker(uint32 line)
|
||||||
|
:
|
||||||
|
fLine(line)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Marker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Line() const
|
||||||
|
{
|
||||||
|
return fLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Draw(MarkerView* view, BRect rect) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InstructionPointerMarker : Marker {
|
||||||
|
InstructionPointerMarker(uint32 line, bool topIP, bool currentIP)
|
||||||
|
:
|
||||||
|
Marker(line),
|
||||||
|
fIsTopIP(topIP),
|
||||||
|
fIsCurrentIP(currentIP)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Draw(MarkerView* view, BRect rect)
|
||||||
|
{
|
||||||
|
// Get the arrow color -- for the top IP, if current, we use blue,
|
||||||
|
// otherwise a gray.
|
||||||
|
rgb_color color;
|
||||||
|
if (fIsCurrentIP && fIsTopIP) {
|
||||||
|
color.set_to(0, 0, 255, 255);
|
||||||
|
} else {
|
||||||
|
color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
|
||||||
|
B_DARKEN_3_TINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a filled array for the current IP, otherwise just an
|
||||||
|
// outline.
|
||||||
|
BPoint tip(rect.right - 3.5f, floorf((rect.top + rect.bottom) / 2));
|
||||||
|
if (fIsCurrentIP) {
|
||||||
|
_DrawArrow(view, tip, BSize(10, 10), BSize(5, 5), color, true);
|
||||||
|
} else {
|
||||||
|
_DrawArrow(view, tip + BPoint(-0.5f, 0), BSize(9, 8),
|
||||||
|
BSize(5, 4), color, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _DrawArrow(BView* view, BPoint tip, BSize size, BSize base,
|
||||||
|
const rgb_color& color, bool fill)
|
||||||
|
{
|
||||||
|
view->SetHighColor(color);
|
||||||
|
|
||||||
|
float baseTop = tip.y - base.height / 2;
|
||||||
|
float baseBottom = tip.y + base.height / 2;
|
||||||
|
float top = tip.y - size.height / 2;
|
||||||
|
float bottom = tip.y + size.height / 2;
|
||||||
|
float left = tip.x - size.width;
|
||||||
|
float middle = left + base.width;
|
||||||
|
|
||||||
|
BPoint points[7];
|
||||||
|
points[0].Set(tip.x, tip.y);
|
||||||
|
points[1].Set(middle, top);
|
||||||
|
points[2].Set(middle, baseTop);
|
||||||
|
points[3].Set(left, baseTop);
|
||||||
|
points[4].Set(left, baseBottom);
|
||||||
|
points[5].Set(middle, baseBottom);
|
||||||
|
points[6].Set(middle, bottom);
|
||||||
|
|
||||||
|
if (fill)
|
||||||
|
view->FillPolygon(points, 7);
|
||||||
|
else
|
||||||
|
view->StrokePolygon(points, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fIsTopIP;
|
||||||
|
bool fIsCurrentIP;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BObjectList<Marker> MarkerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _UpdateMarkers()
|
||||||
|
{
|
||||||
|
if (fMarkersValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fMarkers.MakeEmpty();
|
||||||
|
|
||||||
|
if (fSourceCode != NULL && fStackTrace != NULL) {
|
||||||
|
for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i);
|
||||||
|
i++) {
|
||||||
|
target_addr_t ip = frame->InstructionPointer();
|
||||||
|
Statement* statement = fSourceCode->StatementAtAddress(ip);
|
||||||
|
if (statement == NULL)
|
||||||
|
continue;
|
||||||
|
uint32 line = statement->StartSourceLocation().Line();
|
||||||
|
if (line >= (uint32)LineCount())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Marker* marker = new(std::nothrow) InstructionPointerMarker(
|
||||||
|
line, i == 0, frame == fStackFrame);
|
||||||
|
if (marker == NULL || !fMarkers.AddItem(marker)) {
|
||||||
|
delete marker;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Filter duplicate IP markers (recursive functions)!
|
||||||
|
|
||||||
|
fMarkersValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StackTrace* fStackTrace;
|
||||||
|
StackFrame* fStackFrame;
|
||||||
|
MarkerList fMarkers;
|
||||||
|
bool fMarkersValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SourceView::TextView : public BView {
|
class SourceView::TextView : public BaseView {
|
||||||
public:
|
public:
|
||||||
TextView(SourceView* sourceView, FontInfo* fontInfo)
|
TextView(SourceView* sourceView, FontInfo* fontInfo)
|
||||||
:
|
:
|
||||||
BView("source text view", B_WILL_DRAW),
|
BaseView("source text view", sourceView, fontInfo),
|
||||||
fSourceView(sourceView),
|
|
||||||
fFontInfo(fontInfo),
|
|
||||||
fSourceCode(NULL),
|
|
||||||
fMaxLineWidth(-1)
|
fMaxLineWidth(-1)
|
||||||
{
|
{
|
||||||
SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
||||||
fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR);
|
fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSourceCode(SourceCode* sourceCode)
|
virtual void SetSourceCode(SourceCode* sourceCode)
|
||||||
{
|
{
|
||||||
fSourceCode = sourceCode;
|
|
||||||
fMaxLineWidth = -1;
|
fMaxLineWidth = -1;
|
||||||
|
BaseView::SetSourceCode(sourceCode);
|
||||||
InvalidateLayout();
|
|
||||||
Invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BSize MinSize()
|
virtual BSize MinSize()
|
||||||
{
|
{
|
||||||
float height = _LineCount() * fFontInfo->lineHeight;
|
return BSize(kLeftTextMargin + _MaxLineWidth() - 1, TotalHeight());
|
||||||
return BSize(kLeftTextMargin + _MaxLineWidth() - 1,
|
|
||||||
std::max(height - 1, 100.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BSize MaxSize()
|
virtual BSize MaxSize()
|
||||||
@@ -94,23 +315,14 @@ public:
|
|||||||
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
|
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BSize PreferredSize()
|
|
||||||
{
|
|
||||||
return MinSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Draw(BRect updateRect)
|
virtual void Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
if (fSourceCode == NULL)
|
if (fSourceCode == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// get the lines intersecting with the update rect
|
// get the lines intersecting with the update rect
|
||||||
int32 lineHeight = (int32)fFontInfo->lineHeight;
|
int32 minLine, maxLine;
|
||||||
int32 minLine = (int32)updateRect.top / lineHeight;
|
GetLineRange(updateRect, minLine, maxLine);
|
||||||
int32 maxLine = ((int32)ceilf(updateRect.bottom) + lineHeight - 1)
|
|
||||||
/ lineHeight;
|
|
||||||
minLine = std::max(minLine, 0L);
|
|
||||||
maxLine = std::min(maxLine, fSourceCode->CountLines() - 1);
|
|
||||||
|
|
||||||
// draw the affected lines
|
// draw the affected lines
|
||||||
SetHighColor(fTextColor);
|
SetHighColor(fTextColor);
|
||||||
@@ -123,11 +335,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32 _LineCount() const
|
|
||||||
{
|
|
||||||
return fSourceCode != NULL ? fSourceCode->CountLines() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float _MaxLineWidth()
|
float _MaxLineWidth()
|
||||||
{
|
{
|
||||||
if (fMaxLineWidth >= 0)
|
if (fMaxLineWidth >= 0)
|
||||||
@@ -145,9 +352,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SourceView* fSourceView;
|
|
||||||
FontInfo* fFontInfo;
|
|
||||||
SourceCode* fSourceCode;
|
|
||||||
float fMaxLineWidth;
|
float fMaxLineWidth;
|
||||||
rgb_color fTextColor;
|
rgb_color fTextColor;
|
||||||
};
|
};
|
||||||
@@ -160,6 +364,7 @@ SourceView::SourceView(TeamDebugModel* debugModel, Listener* listener)
|
|||||||
:
|
:
|
||||||
BView("source view", 0),
|
BView("source view", 0),
|
||||||
fDebugModel(debugModel),
|
fDebugModel(debugModel),
|
||||||
|
fStackTrace(NULL),
|
||||||
fStackFrame(NULL),
|
fStackFrame(NULL),
|
||||||
fSourceCode(NULL),
|
fSourceCode(NULL),
|
||||||
fMarkerView(NULL),
|
fMarkerView(NULL),
|
||||||
@@ -177,6 +382,8 @@ SourceView::SourceView(TeamDebugModel* debugModel, Listener* listener)
|
|||||||
SourceView::~SourceView()
|
SourceView::~SourceView()
|
||||||
{
|
{
|
||||||
SetStackFrame(NULL);
|
SetStackFrame(NULL);
|
||||||
|
SetStackTrace(NULL);
|
||||||
|
SetSourceCode(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -204,49 +411,112 @@ SourceView::UnsetListener()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourceView::SetStackFrame(StackFrame* frame)
|
SourceView::SetStackTrace(StackTrace* stackTrace)
|
||||||
{
|
{
|
||||||
printf("SourceView::SetStackFrame(%p)\n", frame);
|
printf("SourceView::SetStackTrace(%p)\n", stackTrace);
|
||||||
if (frame == fStackFrame)
|
if (stackTrace == fStackTrace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fStackFrame != NULL)
|
if (fStackTrace != NULL) {
|
||||||
fStackFrame->RemoveReference();
|
fMarkerView->SetStackTrace(NULL);
|
||||||
|
fStackTrace->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
fStackFrame = frame;
|
fStackTrace = stackTrace;
|
||||||
|
|
||||||
if (fStackFrame != NULL)
|
if (fStackTrace != NULL)
|
||||||
fStackFrame->AddReference();
|
fStackTrace->AddReference();
|
||||||
|
|
||||||
UpdateSourceCode();
|
fMarkerView->SetStackTrace(fStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourceView::UpdateSourceCode()
|
SourceView::SetStackFrame(StackFrame* stackFrame)
|
||||||
{
|
{
|
||||||
// get a reference to the source code
|
if (stackFrame == fStackFrame)
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
return;
|
||||||
|
|
||||||
SourceCode* sourceCode = fStackFrame != NULL
|
if (fStackFrame != NULL) {
|
||||||
? fStackFrame->GetSourceCode() : NULL;
|
fMarkerView->SetStackFrame(NULL);
|
||||||
Reference<SourceCode> sourceCodeReference(sourceCode);
|
fStackFrame->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
locker.Unlock();
|
fStackFrame = stackFrame;
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
fStackFrame->AddReference();
|
||||||
|
|
||||||
|
fMarkerView->SetStackFrame(fStackFrame);
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
ScrollToAddress(fStackFrame->InstructionPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceView::SetSourceCode(SourceCode* sourceCode)
|
||||||
|
{
|
||||||
// set the source code, if it changed
|
// set the source code, if it changed
|
||||||
if (sourceCode == fSourceCode)
|
if (sourceCode == fSourceCode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fSourceCode != NULL) {
|
if (fSourceCode != NULL) {
|
||||||
fTextView->SetSourceCode(NULL);
|
fTextView->SetSourceCode(NULL);
|
||||||
|
fMarkerView->SetSourceCode(NULL);
|
||||||
fSourceCode->RemoveReference();
|
fSourceCode->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
fSourceCode = sourceCodeReference.Detach();
|
fSourceCode = sourceCode;
|
||||||
|
|
||||||
|
if (fSourceCode != NULL)
|
||||||
|
fSourceCode->AddReference();
|
||||||
|
|
||||||
fTextView->SetSourceCode(fSourceCode);
|
fTextView->SetSourceCode(fSourceCode);
|
||||||
|
fMarkerView->SetSourceCode(fSourceCode);
|
||||||
_UpdateScrollBars();
|
_UpdateScrollBars();
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
ScrollToAddress(fStackFrame->InstructionPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
SourceView::ScrollToAddress(target_addr_t address)
|
||||||
|
{
|
||||||
|
if (fSourceCode == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Statement* statement = fSourceCode->StatementAtAddress(address);
|
||||||
|
if (statement == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ScrollToLine(statement->StartSourceLocation().Line());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
SourceView::ScrollToLine(uint32 line)
|
||||||
|
{
|
||||||
|
printf("SourceView::ScrollToLine(%lu)\n", line);
|
||||||
|
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float top = (float)line * fFontInfo.lineHeight;
|
||||||
|
float bottom = top + fFontInfo.lineHeight - 1;
|
||||||
|
|
||||||
|
BRect visible = _VisibleRect();
|
||||||
|
|
||||||
|
// If not visible at all, scroll to the center, otherwise scroll so that at
|
||||||
|
// least one more line is visible.
|
||||||
|
if (top >= visible.bottom || bottom <= visible.top)
|
||||||
|
ScrollTo(visible.left, top - (visible.Height() + 1) / 2);
|
||||||
|
else if (top - fFontInfo.lineHeight < visible.top)
|
||||||
|
ScrollBy(0, top - fFontInfo.lineHeight - visible.top);
|
||||||
|
else if (bottom + fFontInfo.lineHeight > visible.bottom)
|
||||||
|
ScrollBy(0, bottom + fFontInfo.lineHeight - visible.bottom);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -360,6 +630,13 @@ SourceView::_DataRectSize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect
|
||||||
|
SourceView::_VisibleRect() const
|
||||||
|
{
|
||||||
|
return BRect(Bounds().LeftTop(), Frame().Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Listener
|
// #pragma mark - Listener
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
#include <Font.h>
|
#include <Font.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
|
#include "ArchitectureTypes.h"
|
||||||
|
|
||||||
|
|
||||||
class SourceCode;
|
class SourceCode;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
|
class StackTrace;
|
||||||
class TeamDebugModel;
|
class TeamDebugModel;
|
||||||
|
|
||||||
|
|
||||||
@@ -29,8 +32,12 @@ public:
|
|||||||
|
|
||||||
void UnsetListener();
|
void UnsetListener();
|
||||||
|
|
||||||
void SetStackFrame(StackFrame* frame);
|
void SetStackTrace(StackTrace* stackTrace);
|
||||||
void UpdateSourceCode();
|
void SetStackFrame(StackFrame* stackFrame);
|
||||||
|
void SetSourceCode(SourceCode* sourceCode);
|
||||||
|
|
||||||
|
bool ScrollToAddress(target_addr_t address);
|
||||||
|
bool ScrollToLine(uint32 line);
|
||||||
|
|
||||||
virtual void TargetedByScrollView(BScrollView* scrollView);
|
virtual void TargetedByScrollView(BScrollView* scrollView);
|
||||||
|
|
||||||
@@ -41,6 +48,7 @@ public:
|
|||||||
virtual void DoLayout();
|
virtual void DoLayout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class BaseView;
|
||||||
class MarkerView;
|
class MarkerView;
|
||||||
class TextView;
|
class TextView;
|
||||||
|
|
||||||
@@ -54,9 +62,11 @@ private:
|
|||||||
void _Init();
|
void _Init();
|
||||||
void _UpdateScrollBars();
|
void _UpdateScrollBars();
|
||||||
BSize _DataRectSize() const;
|
BSize _DataRectSize() const;
|
||||||
|
BRect _VisibleRect() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TeamDebugModel* fDebugModel;
|
TeamDebugModel* fDebugModel;
|
||||||
|
StackTrace* fStackTrace;
|
||||||
StackFrame* fStackFrame;
|
StackFrame* fStackFrame;
|
||||||
SourceCode* fSourceCode;
|
SourceCode* fSourceCode;
|
||||||
MarkerView* fMarkerView;
|
MarkerView* fMarkerView;
|
||||||
|
|||||||
@@ -209,6 +209,22 @@ StackTraceView::SetStackTrace(StackTrace* stackTrace)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
StackTraceView::SetStackFrame(StackFrame* stackFrame)
|
||||||
|
{
|
||||||
|
if (fStackTrace != NULL && stackFrame != NULL) {
|
||||||
|
for (int32 i = 0; StackFrame* other = fStackTrace->FrameAt(i); i++) {
|
||||||
|
if (stackFrame == other) {
|
||||||
|
fFramesTable->SelectRow(i, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fFramesTable->DeselectAllRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
StackTraceView::TableSelectionChanged(Table* table)
|
StackTraceView::TableSelectionChanged(Table* table)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
void UnsetListener();
|
void UnsetListener();
|
||||||
|
|
||||||
void SetStackTrace(StackTrace* stackTrace);
|
void SetStackTrace(StackTrace* stackTrace);
|
||||||
|
void SetStackFrame(StackFrame* stackFrame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class FramesTableModel;
|
class FramesTableModel;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "ImageListView.h"
|
#include "ImageListView.h"
|
||||||
#include "MessageCodes.h"
|
#include "MessageCodes.h"
|
||||||
#include "RegisterView.h"
|
#include "RegisterView.h"
|
||||||
|
#include "SourceCode.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "StackTraceView.h"
|
#include "StackTraceView.h"
|
||||||
#include "TeamDebugModel.h"
|
#include "TeamDebugModel.h"
|
||||||
@@ -35,7 +36,9 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
|
|||||||
B_ASYNCHRONOUS_CONTROLS),
|
B_ASYNCHRONOUS_CONTROLS),
|
||||||
fDebugModel(debugModel),
|
fDebugModel(debugModel),
|
||||||
fActiveThread(NULL),
|
fActiveThread(NULL),
|
||||||
|
fActiveStackTrace(NULL),
|
||||||
fActiveStackFrame(NULL),
|
fActiveStackFrame(NULL),
|
||||||
|
fActiveSourceCode(NULL),
|
||||||
fListener(listener),
|
fListener(listener),
|
||||||
fTabView(NULL),
|
fTabView(NULL),
|
||||||
fLocalsTabView(NULL),
|
fLocalsTabView(NULL),
|
||||||
@@ -69,6 +72,15 @@ TeamWindow::~TeamWindow()
|
|||||||
fSourceView->UnsetListener();
|
fSourceView->UnsetListener();
|
||||||
|
|
||||||
fDebugModel->GetTeam()->RemoveListener(this);
|
fDebugModel->GetTeam()->RemoveListener(this);
|
||||||
|
|
||||||
|
if (fActiveSourceCode != NULL)
|
||||||
|
fActiveSourceCode->RemoveReference();
|
||||||
|
if (fActiveStackFrame != NULL)
|
||||||
|
fActiveStackFrame->RemoveReference();
|
||||||
|
if (fActiveStackTrace != NULL)
|
||||||
|
fActiveStackTrace->RemoveReference();
|
||||||
|
if (fActiveThread != NULL)
|
||||||
|
fActiveThread->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -283,8 +295,14 @@ TeamWindow::_SetActiveThread(::Thread* thread)
|
|||||||
if (thread == fActiveThread)
|
if (thread == fActiveThread)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (fActiveThread != NULL)
|
||||||
|
fActiveThread->RemoveReference();
|
||||||
|
|
||||||
fActiveThread = thread;
|
fActiveThread = thread;
|
||||||
|
|
||||||
|
if (fActiveThread != NULL)
|
||||||
|
fActiveThread->AddReference();
|
||||||
|
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
_UpdateRunButtons();
|
_UpdateRunButtons();
|
||||||
|
|
||||||
@@ -295,11 +313,33 @@ TeamWindow::_SetActiveThread(::Thread* thread)
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
fStackTraceView->SetStackTrace(stackTrace);
|
_SetActiveStackTrace(stackTrace);
|
||||||
_UpdateCpuState();
|
_UpdateCpuState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::_SetActiveStackTrace(StackTrace* stackTrace)
|
||||||
|
{
|
||||||
|
if (stackTrace == fActiveStackTrace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fActiveStackTrace != NULL)
|
||||||
|
fActiveStackTrace->RemoveReference();
|
||||||
|
|
||||||
|
fActiveStackTrace = stackTrace;
|
||||||
|
|
||||||
|
if (fActiveStackTrace != NULL)
|
||||||
|
fActiveStackTrace->AddReference();
|
||||||
|
|
||||||
|
fStackTraceView->SetStackTrace(fActiveStackTrace);
|
||||||
|
fSourceView->SetStackTrace(fActiveStackTrace);
|
||||||
|
|
||||||
|
if (fActiveStackTrace != NULL)
|
||||||
|
_SetActiveStackFrame(fActiveStackTrace->FrameAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
||||||
{
|
{
|
||||||
@@ -315,10 +355,18 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
|||||||
|
|
||||||
fActiveStackFrame = frame;
|
fActiveStackFrame = frame;
|
||||||
|
|
||||||
|
SourceCode* sourceCode = NULL;
|
||||||
|
Reference<SourceCode> sourceCodeReference;
|
||||||
|
bool setSourceCode = false;
|
||||||
|
|
||||||
if (fActiveStackFrame != NULL) {
|
if (fActiveStackFrame != NULL) {
|
||||||
fActiveStackFrame->AddReference();
|
fActiveStackFrame->AddReference();
|
||||||
fActiveStackFrame->AddListener(this);
|
fActiveStackFrame->AddListener(this);
|
||||||
|
|
||||||
|
sourceCode = fActiveStackFrame->GetSourceCode();
|
||||||
|
sourceCodeReference.SetTo(sourceCode);
|
||||||
|
setSourceCode = true;
|
||||||
|
|
||||||
// If the source code is not loaded yet, request it.
|
// If the source code is not loaded yet, request it.
|
||||||
if (fActiveStackFrame->SourceCodeState() == STACK_SOURCE_NOT_LOADED)
|
if (fActiveStackFrame->SourceCodeState() == STACK_SOURCE_NOT_LOADED)
|
||||||
fListener->StackFrameSourceCodeRequested(this, fActiveStackFrame);
|
fListener->StackFrameSourceCodeRequested(this, fActiveStackFrame);
|
||||||
@@ -328,10 +376,32 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
|
if (setSourceCode)
|
||||||
|
_SetActiveSourceCode(sourceCode);
|
||||||
|
|
||||||
|
fStackTraceView->SetStackFrame(fActiveStackFrame);
|
||||||
fSourceView->SetStackFrame(fActiveStackFrame);
|
fSourceView->SetStackFrame(fActiveStackFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
|
||||||
|
{
|
||||||
|
if (sourceCode == fActiveSourceCode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fActiveSourceCode != NULL)
|
||||||
|
fActiveSourceCode->RemoveReference();
|
||||||
|
|
||||||
|
fActiveSourceCode = sourceCode;
|
||||||
|
|
||||||
|
if (fActiveSourceCode != NULL)
|
||||||
|
fActiveSourceCode->AddReference();
|
||||||
|
|
||||||
|
fSourceView->SetSourceCode(fActiveSourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::_UpdateCpuState()
|
TeamWindow::_UpdateCpuState()
|
||||||
{
|
{
|
||||||
@@ -427,14 +497,26 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
fStackTraceView->SetStackTrace(stackTrace);
|
_SetActiveStackTrace(stackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::_HandleSourceCodeChanged()
|
TeamWindow::_HandleSourceCodeChanged()
|
||||||
{
|
{
|
||||||
fSourceView->UpdateSourceCode();
|
// If we don't have an active stack frame anymore, the message is obsolete.
|
||||||
|
if (fActiveStackFrame == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get a reference to the source code
|
||||||
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
|
|
||||||
|
SourceCode* sourceCode = fActiveStackFrame->GetSourceCode();
|
||||||
|
Reference<SourceCode> sourceCodeReference(sourceCode);
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
_SetActiveSourceCode(sourceCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class BButton;
|
|||||||
class BTabView;
|
class BTabView;
|
||||||
class ImageListView;
|
class ImageListView;
|
||||||
class RegisterView;
|
class RegisterView;
|
||||||
|
class SourceCode;
|
||||||
class TeamDebugModel;
|
class TeamDebugModel;
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +65,9 @@ private:
|
|||||||
void _Init();
|
void _Init();
|
||||||
|
|
||||||
void _SetActiveThread(::Thread* thread);
|
void _SetActiveThread(::Thread* thread);
|
||||||
|
void _SetActiveStackTrace(StackTrace* stackTrace);
|
||||||
void _SetActiveStackFrame(StackFrame* frame);
|
void _SetActiveStackFrame(StackFrame* frame);
|
||||||
|
void _SetActiveSourceCode(SourceCode* sourceCode);
|
||||||
void _UpdateCpuState();
|
void _UpdateCpuState();
|
||||||
void _UpdateRunButtons();
|
void _UpdateRunButtons();
|
||||||
|
|
||||||
@@ -76,7 +79,9 @@ private:
|
|||||||
private:
|
private:
|
||||||
TeamDebugModel* fDebugModel;
|
TeamDebugModel* fDebugModel;
|
||||||
::Thread* fActiveThread;
|
::Thread* fActiveThread;
|
||||||
|
StackTrace* fActiveStackTrace;
|
||||||
StackFrame* fActiveStackFrame;
|
StackFrame* fActiveStackFrame;
|
||||||
|
SourceCode* fActiveSourceCode;
|
||||||
Listener* fListener;
|
Listener* fListener;
|
||||||
BTabView* fTabView;
|
BTabView* fTabView;
|
||||||
BTabView* fLocalsTabView;
|
BTabView* fLocalsTabView;
|
||||||
|
|||||||
Reference in New Issue
Block a user