From 314f0e011f76002470005b85e732c1594cde426f Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 30 Apr 2009 23:51:43 +0000 Subject: [PATCH] * Added a maximum size parameter to ChartAxis::PreferredSize(), specifying how big the axis can maximally become. This helps to solve the chicken and egg problem that the axis can't compute a size without knowing what legends to use, which in turn requires knowing the size. * Reimplemented LegendChartAxis accordingly. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30527 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debuganalyzer/gui/chart/Chart.cpp | 12 +-- src/apps/debuganalyzer/gui/chart/ChartAxis.h | 2 +- .../gui/chart/LegendChartAxis.cpp | 74 +++++++++++++++---- .../debuganalyzer/gui/chart/LegendChartAxis.h | 4 +- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/src/apps/debuganalyzer/gui/chart/Chart.cpp b/src/apps/debuganalyzer/gui/chart/Chart.cpp index 1bf463dcf0..b090507fab 100644 --- a/src/apps/debuganalyzer/gui/chart/Chart.cpp +++ b/src/apps/debuganalyzer/gui/chart/Chart.cpp @@ -288,13 +288,15 @@ printf("Chart::DoLayout(%f, %f)\n", size.width, size.height); int32 bottom = 0; if (fLeftAxis.axis != NULL) - left = fLeftAxis.axis->PreferredSize(this).IntegerWidth() + 1; + left = fLeftAxis.axis->PreferredSize(this, size).IntegerWidth() + 1; if (fRightAxis.axis != NULL) - right = fRightAxis.axis->PreferredSize(this).IntegerWidth() + 1; + right = fRightAxis.axis->PreferredSize(this, size).IntegerWidth() + 1; if (fTopAxis.axis != NULL) - top = fTopAxis.axis->PreferredSize(this).IntegerHeight() + 1; - if (fBottomAxis.axis != NULL) - bottom = fBottomAxis.axis->PreferredSize(this).IntegerHeight() + 1; + top = fTopAxis.axis->PreferredSize(this, size).IntegerHeight() + 1; + if (fBottomAxis.axis != NULL) { + bottom = fBottomAxis.axis->PreferredSize(this, size).IntegerHeight() + + 1; + } fChartFrame = BRect(left, top, width - right - 1, height - bottom - 1); fRenderer->SetFrame(fChartFrame.InsetByCopy(1, 1)); diff --git a/src/apps/debuganalyzer/gui/chart/ChartAxis.h b/src/apps/debuganalyzer/gui/chart/ChartAxis.h index 8c8a99bc10..968d22ad76 100644 --- a/src/apps/debuganalyzer/gui/chart/ChartAxis.h +++ b/src/apps/debuganalyzer/gui/chart/ChartAxis.h @@ -21,7 +21,7 @@ public: virtual void SetLocation(ChartAxisLocation location) = 0; virtual void SetRange(const ChartDataRange& range) = 0; virtual void SetFrame(BRect frame) = 0; - virtual BSize PreferredSize(BView* view) = 0; + virtual BSize PreferredSize(BView* view, BSize maxSize) = 0; virtual void Render(BView* view, BRect updateRect) = 0; }; diff --git a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp index f713a11edc..a882bd01d8 100644 --- a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp +++ b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp @@ -192,19 +192,53 @@ printf("LegendChartAxis::SetFrame((%f, %f) - (%f, %f))\n", frame.left, frame.top BSize -LegendChartAxis::PreferredSize(BView* view) +LegendChartAxis::PreferredSize(BView* view, BSize maxSize) { -// TODO: Implement for real! - BSize size = fLegendRenderer->MaximumLegendSize(view); + // estimate the maximum legend count we might need + float hSpacing, vSpacing; + int32 maxLegends = _EstimateMaxLegendCount(view, maxSize, &hSpacing, + &vSpacing); + BSize spacing(hSpacing, vSpacing); + if (maxLegends < 4) + maxLegends = 4; + + // get the legends + ChartLegend* legends[maxLegends]; + double values[maxLegends]; + + int32 legendCount = fLegendSource->GetAxisLegends(fRange, legends, values, + maxLegends); + + // get the sizes, delete the legends, and compute the preferred size + float BSize::* sizeField; + float BSize::* otherSizeField; if (fLocation == CHART_AXIS_LEFT || fLocation == CHART_AXIS_RIGHT) { - size.width += kChartLegendDistance; - size.height = std::max(size.height * 4, 100.0f); + sizeField = &BSize::height; + otherSizeField = &BSize::width; } else { - size.width = std::max(size.width * 4, 100.0f); - size.height += kChartLegendDistance; + sizeField = &BSize::width; + otherSizeField = &BSize::height; } - return size; + BSize preferredSize; + + for (int32 i = 0; i < legendCount; i++) { + ChartLegend* legend = legends[i]; + BSize size = fLegendRenderer->LegendSize(legend, view); + delete legend; + + if (size.*sizeField > preferredSize.*sizeField) + preferredSize.*sizeField = size.*sizeField; + if (size.*otherSizeField > preferredSize.*otherSizeField) + preferredSize.*otherSizeField = size.*otherSizeField; + } + + // Suppose we want to have at least 2 legends. + preferredSize.*sizeField + = ceilf(preferredSize.*sizeField * 2 + spacing.*sizeField); + preferredSize.*otherSizeField += kChartLegendDistance; + + return preferredSize; } @@ -331,15 +365,9 @@ printf("LegendChartAxis::_ValidateLayout()\n"); int32 height = fFrame.IntegerHeight() + 1; printf(" width: %ld, height: %ld\n", width, height); - fLegendRenderer->GetMinimumLegendSpacing(view, &fHorizontalSpacing, - &fVerticalSpacing); - // estimate the maximum legend count we might need - int32 maxLegends; - if (fLocation == CHART_AXIS_LEFT || fLocation == CHART_AXIS_RIGHT) - maxLegends = height / (10 + fVerticalSpacing); - else - maxLegends = width / (20 + fHorizontalSpacing); + int32 maxLegends = _EstimateMaxLegendCount(view, fFrame.Size(), + &fHorizontalSpacing, &fVerticalSpacing); printf(" max %ld legends\n", maxLegends); if (maxLegends == 0) @@ -387,3 +415,17 @@ printf(" failed to create legend info!\n"); fLayoutValid = true; return true; } + + +int32 +LegendChartAxis::_EstimateMaxLegendCount(BView* view, BSize size, + float* _hSpacing, float* _vSpacing) +{ + // get the legend spacing + fLegendRenderer->GetMinimumLegendSpacing(view, _hSpacing, _vSpacing); + + // estimate the maximum legend count we might need + if (fLocation == CHART_AXIS_LEFT || fLocation == CHART_AXIS_RIGHT) + return (size.IntegerHeight() + 1) / (10 + *_vSpacing); + return (size.IntegerWidth() + 1) / (20 + *_hSpacing); +} diff --git a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.h b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.h index 796624cd81..7976d7c014 100644 --- a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.h +++ b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.h @@ -25,7 +25,7 @@ public: virtual void SetLocation(ChartAxisLocation location); virtual void SetRange(const ChartDataRange& range); virtual void SetFrame(BRect frame); - virtual BSize PreferredSize(BView* view); + virtual BSize PreferredSize(BView* view, BSize maxSize); virtual void Render(BView* view, BRect updateRect); private: @@ -34,6 +34,8 @@ private: private: void _InvalidateLayout(); bool _ValidateLayout(BView* view); + int32 _EstimateMaxLegendCount(BView* view, BSize size, + float* _hSpacing, float* _vSpacing); inline float _LegendPosition(double value, float legendSize, float totalSize, double scale); inline void _FilterLegends(int32 totalSize, int32 spacing,