* 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:
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user