* 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
This commit is contained in:
Ingo Weinhold
2009-04-30 23:51:43 +00:00
parent 5664cf424e
commit 314f0e011f
4 changed files with 69 additions and 23 deletions
+7 -5
View File
@@ -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));
+1 -1
View File
@@ -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;
};
@@ -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);
}
@@ -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,