* Made the displayed domain and range settable.

* Added support for scrolling.
* Automatic white space cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30648 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-05-06 15:31:44 +00:00
parent de7e498829
commit a5c1cac5a8
2 changed files with 198 additions and 35 deletions

View File

@ -11,6 +11,7 @@
#include <ControlLook.h>
#include <Region.h>
#include <ScrollBar.h>
#include "chart/ChartAxis.h"
#include "chart/ChartDataSource.h"
@ -58,7 +59,11 @@ Chart::AxisInfo::Render(BView* view, const BRect& updateRect)
Chart::Chart(ChartRenderer* renderer, const char* name)
:
BView(name, B_FRAME_EVENTS | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fRenderer(renderer)
fRenderer(renderer),
fHScrollSize(0),
fVScrollSize(0),
fHScrollValue(0),
fVScrollValue(0)
{
SetViewColor(B_TRANSPARENT_32_BIT);
@ -129,7 +134,7 @@ printf("Chart::RemoveDataSource(%ld)\n", index);
fRenderer->RemoveDataSource(dataSource);
_UpdateDomainAndRange();
return dataSource;
}
@ -178,29 +183,80 @@ Chart::SetAxis(ChartAxisLocation location, ChartAxis* axis)
}
#if 0
ChartDataRange
Chart::Domain() const
{
return fDataSource != NULL ? fDataSource->Domain() : ChartDataRange();
}
void
Chart::SetDisplayDomain(const ChartDataRange& domain)
Chart::SetDisplayDomain(ChartDataRange domain)
{
fRenderer->SetDomain(domain);
// sanitize the supplied range
if (domain.IsValid() && domain.Size() < fDomain.Size()) {
if (domain.min < fDomain.min)
domain.OffsetBy(fDomain.min - domain.min);
else if (domain.max > fDomain.max)
domain.OffsetBy(fDomain.max - domain.max);
} else
domain = fDomain;
if (domain == fDisplayDomain)
return;
fDisplayDomain = domain;
fRenderer->SetDomain(fDisplayDomain);
fTopAxis.SetRange(fDisplayDomain);
fBottomAxis.SetRange(fDisplayDomain);
_UpdateScrollBar(true);
InvalidateLayout();
Invalidate();
}
void
Chart::SetDisplayDomain(const ChartDataRange& range)
Chart::SetDisplayRange(ChartDataRange range)
{
fRenderer->SetRange(range);
// sanitize the supplied range
if (range.IsValid() && range.Size() < fRange.Size()) {
if (range.min < fRange.min)
range.OffsetBy(fRange.min - range.min);
else if (range.max > fRange.max)
range.OffsetBy(fRange.max - range.max);
} else
range = fRange;
if (range == fDisplayRange)
return;
fDisplayRange = range;
fRenderer->SetRange(fDisplayRange);
fLeftAxis.SetRange(fDisplayRange);
fRightAxis.SetRange(fDisplayRange);
_UpdateScrollBar(false);
InvalidateLayout();
Invalidate();
}
#endif
void
Chart::DomainChanged()
{
if (ScrollBar(B_HORIZONTAL) != NULL && fDisplayDomain.IsValid())
SetDisplayDomain(fDisplayDomain);
else
SetDisplayDomain(fDomain);
}
void
Chart::RangeChanged()
{
if (ScrollBar(B_VERTICAL) != NULL && fDisplayRange.IsValid())
SetDisplayRange(fDisplayRange);
else
SetDisplayRange(fRange);
}
void
@ -209,6 +265,9 @@ Chart::FrameResized(float newWidth, float newHeight)
//printf("Chart::FrameResized(%f, %f)\n", newWidth, newHeight);
// fRenderer->SetFrame(Bounds());
_UpdateScrollBar(true);
_UpdateScrollBar(false);
Invalidate();
}
@ -252,24 +311,36 @@ printf("Chart::Draw((%f, %f) - (%f, %f))\n", updateRect.left, updateRect.top, up
}
#if 0
void
Chart::ScrollTo(BPoint where)
{
_ScrollTo(where.x, true);
_ScrollTo(where.y, false);
}
BSize
Chart::MinSize()
{
// TODO: Implement for real!
return BSize(100, 100);
}
BSize
Chart::MaxSize()
{
// TODO: Implement for real!
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
BSize
Chart::PreferredSize()
{
// TODO: Implement for real!
return MinSize();
}
#endif
void
@ -316,15 +387,17 @@ printf(" fChartFrame: (%f, %f) - (%f, %f)\n", fChartFrame.left, fChartFrame.top
void
Chart::_UpdateDomainAndRange()
{
ChartDataRange oldDomain = fDomain;
ChartDataRange oldRange = fRange;
if (fDataSources.IsEmpty()) {
fDomain = ChartDataRange();
fRange = ChartDataRange();
return;
} else {
ChartDataSource* firstSource = fDataSources.ItemAt(0);
fDomain = firstSource->Domain();
fRange = firstSource->Range();
for (int32 i = 1; ChartDataSource* source = fDataSources.ItemAt(i);
i++) {
fDomain.Extend(source->Domain());
@ -332,11 +405,65 @@ Chart::_UpdateDomainAndRange()
}
}
fRenderer->SetDomain(fDomain);
fRenderer->SetRange(fRange);
fLeftAxis.SetRange(fRange);
fTopAxis.SetRange(fDomain);
fRightAxis.SetRange(fRange);
fBottomAxis.SetRange(fDomain);
if (fDomain != oldDomain)
DomainChanged();
if (fRange != oldRange)
RangeChanged();
}
void
Chart::_UpdateScrollBar(bool horizontal)
{
const ChartDataRange& range = horizontal ? fDomain : fRange;
const ChartDataRange& displayRange = horizontal
? fDisplayDomain : fDisplayRange;
float chartSize = horizontal ? fChartFrame.Width() : fChartFrame.Height();
chartSize += 3; // +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);
float proportion;
if (range.IsValid() && displayRange.IsValid()) {
scrollSize = (range.Size() / displayRange.Size() - 1) * chartSize;
scrollValue = (displayRange.min - range.min) / displayRange.Size()
* chartSize;
proportion = displayRange.Size() / range.Size();
} else {
scrollSize = 0;
scrollValue = 0;
proportion = 1;
}
if (scrollBar != NULL) {
scrollBar->SetRange(0, scrollSize);
// TODO: If the scroll range changes, we might need to reset the scroll value.
scrollBar->SetValue(scrollValue);
scrollBar->SetProportion(proportion);
}
}
void
Chart::_ScrollTo(float value, bool horizontal)
{
float& scrollValue = horizontal ? fHScrollValue : fVScrollValue;
if (value == scrollValue)
return;
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
const float& scrollSize = horizontal ? fHScrollSize : fVScrollSize;
scrollValue = value;
displayRange.OffsetTo(value / scrollSize
* (range.Size() - displayRange.Size()));
if (horizontal)
SetDisplayDomain(displayRange);
else
SetDisplayRange(displayRange);
}

View File

@ -40,21 +40,25 @@ public:
void SetAxis(ChartAxisLocation location,
ChartAxis* axis);
#if 0
ChartDataRange Domain() const;
inline ChartDataRange Domain() const;
inline ChartDataRange Range() const;
void SetDisplayDomain(const ChartDataRange& domain);
void SetDisplayRange(const ChartDataRange& range);
#endif
inline ChartDataRange DisplayDomain() const;
inline ChartDataRange DisplayRange() const;
void SetDisplayDomain(ChartDataRange domain);
void SetDisplayRange(ChartDataRange range);
virtual void DomainChanged();
virtual void RangeChanged();
virtual void FrameResized(float newWidth, float newHeight);
virtual void Draw(BRect updateRect);
virtual void ScrollTo(BPoint where);
#if 0
virtual BSize MinSize();
virtual BSize MaxSize();
virtual BSize PreferredSize();
#endif
virtual void DoLayout();
@ -74,6 +78,8 @@ private:
private:
void _UpdateDomainAndRange();
void _UpdateScrollBar(bool horizontal);
void _ScrollTo(float value, bool horizontal);
private:
ChartRenderer* fRenderer;
@ -84,12 +90,42 @@ private:
AxisInfo fBottomAxis;
ChartDataRange fDomain;
ChartDataRange fRange;
#if 0
ChartDataRange fDisplayDomain;
ChartDataRange fDisplayRange;
#endif
BRect fChartFrame;
float fHScrollSize;
float fVScrollSize;
float fHScrollValue;
float fVScrollValue;
};
ChartDataRange
Chart::Domain() const
{
return fDomain;
}
ChartDataRange
Chart::Range() const
{
return fRange;
}
ChartDataRange
Chart::DisplayDomain() const
{
return fDisplayDomain;
}
ChartDataRange
Chart::DisplayRange() const
{
return fDisplayRange;
}
#endif // CHART_H