diff --git a/src/apps/debuganalyzer/gui/chart/Chart.cpp b/src/apps/debuganalyzer/gui/chart/Chart.cpp index d799d94415..42da209c24 100644 --- a/src/apps/debuganalyzer/gui/chart/Chart.cpp +++ b/src/apps/debuganalyzer/gui/chart/Chart.cpp @@ -63,7 +63,9 @@ Chart::Chart(ChartRenderer* renderer, const char* name) fHScrollSize(0), fVScrollSize(0), fHScrollValue(0), - fVScrollValue(0) + fVScrollValue(0), + fDomainZoomLimit(0), + fLastMousePos(-1, -1) { SetViewColor(B_TRANSPARENT_32_BIT); @@ -239,6 +241,20 @@ Chart::SetDisplayRange(ChartDataRange range) } +double +Chart::DomainZoomLimit() const +{ + return fDomainZoomLimit; +} + + +void +Chart::SetDomainZoomLimit(double limit) +{ + fDomainZoomLimit = limit; +} + + void Chart::DomainChanged() { @@ -259,6 +275,31 @@ Chart::RangeChanged() } +void +Chart::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_MOUSE_WHEEL_CHANGED: + { + // We're only interested in Shift + vertical wheel, if the mouse + // is in the chart frame. + float deltaY; + if ((modifiers() & B_SHIFT_KEY) == 0 + || message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK + || !fChartFrame.InsetByCopy(1, 1).Contains(fLastMousePos)) { + break; + } + + _Zoom(fLastMousePos.x, deltaY); + + return; + } + } + + BView::MessageReceived(message); +} + + void Chart::FrameResized(float newWidth, float newHeight) { @@ -272,6 +313,13 @@ Chart::FrameResized(float newWidth, float newHeight) } +void +Chart::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) +{ + fLastMousePos = where; +} + + void Chart::Draw(BRect updateRect) { @@ -419,7 +467,7 @@ Chart::_UpdateScrollBar(bool horizontal) const ChartDataRange& displayRange = horizontal ? fDisplayDomain : fDisplayRange; float chartSize = horizontal ? fChartFrame.Width() : fChartFrame.Height(); - chartSize += 3; // +1 for pixel size, +2 for border + chartSize--; // +1 for pixel size, -2 for border float& scrollSize = horizontal ? fHScrollSize : fVScrollSize; float& scrollValue = horizontal ? fHScrollValue : fVScrollValue; BScrollBar* scrollBar = ScrollBar(horizontal ? B_HORIZONTAL : B_VERTICAL); @@ -456,7 +504,7 @@ Chart::_ScrollTo(float value, bool horizontal) const ChartDataRange& range = horizontal ? fDomain : fRange; ChartDataRange displayRange = horizontal ? fDisplayDomain : fDisplayRange; float chartSize = horizontal ? fChartFrame.Width() : fChartFrame.Height(); - chartSize += 3; // +1 for pixel size, +2 for border + chartSize--; // +1 for pixel size, -2 for border const float& scrollSize = horizontal ? fHScrollSize : fVScrollSize; scrollValue = value; @@ -467,3 +515,46 @@ Chart::_ScrollTo(float value, bool horizontal) else SetDisplayRange(displayRange); } + + +void +Chart::_Zoom(float x, float steps) +{ + double displayDomainSize = fDisplayDomain.Size(); + if (fDomainZoomLimit <= 0 || !fDomain.IsValid() || !fDisplayDomain.IsValid() + || steps == 0) { + return; + } + + // compute the domain point where to zoom in + float chartSize = fChartFrame.Width() - 1; + x -= fChartFrame.left + 1; + double domainPos = (fHScrollValue + x) / (fHScrollSize + chartSize) + * fDomain.Size(); + + double factor = 2; + if (steps < 0) { + steps = -steps; + factor = 1.0 / factor; + } + + for (; steps > 0; steps--) + displayDomainSize *= factor; + + if (displayDomainSize < fDomainZoomLimit) + displayDomainSize = fDomainZoomLimit; + if (displayDomainSize > fDomain.Size()) + displayDomainSize = fDomain.Size(); + + if (displayDomainSize == fDisplayDomain.Size()) + return; + + domainPos -= displayDomainSize * x / chartSize; + ChartDataRange displayDomain(domainPos, domainPos + displayDomainSize); + if (displayDomain.min < fDomain.min) + displayDomain.OffsetTo(fDomain.min); + if (displayDomain.max > fDomain.max) + displayDomain.OffsetTo(fDomain.max - displayDomainSize); + + SetDisplayDomain(displayDomain); +} diff --git a/src/apps/debuganalyzer/gui/chart/Chart.h b/src/apps/debuganalyzer/gui/chart/Chart.h index ee8eb1c57d..10cd8aea23 100644 --- a/src/apps/debuganalyzer/gui/chart/Chart.h +++ b/src/apps/debuganalyzer/gui/chart/Chart.h @@ -49,9 +49,16 @@ public: void SetDisplayDomain(ChartDataRange domain); void SetDisplayRange(ChartDataRange range); + double DomainZoomLimit() const; + void SetDomainZoomLimit(double limit); + virtual void DomainChanged(); virtual void RangeChanged(); + virtual void MessageReceived(BMessage* message); + + virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage); virtual void FrameResized(float newWidth, float newHeight); virtual void Draw(BRect updateRect); virtual void ScrollTo(BPoint where); @@ -80,6 +87,7 @@ private: void _UpdateDomainAndRange(); void _UpdateScrollBar(bool horizontal); void _ScrollTo(float value, bool horizontal); + void _Zoom(float x, float steps); private: ChartRenderer* fRenderer; @@ -97,6 +105,8 @@ private: float fVScrollSize; float fHScrollValue; float fVScrollValue; + double fDomainZoomLimit; + BPoint fLastMousePos; };