* Copyright 2001-2009, Ingo Weinhold <ingo_weinhold@gmx.de>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "Scrollable.h"
#include <algorithm>
#include <stdio.h>
#include "Scroller.h"
Scrollable::Scrollable()
: fDataRect(0.0, 0.0, 0.0, 0.0),
fScrollOffset(0.0, 0.0),
fVisibleWidth(0),
fVisibleHeight(0),
fScrollSource(NULL)
{
}
Scrollable::~Scrollable()
{
if (fScrollSource)
fScrollSource->SetScrollTarget(NULL);
}
void
Scrollable::SetScrollSource(Scroller* source)
{
Scroller* oldSource = fScrollSource;
if (oldSource != source) {
fScrollSource = NULL;
if (oldSource && oldSource->ScrollTarget() == this)
oldSource->SetScrollTarget(NULL);
fScrollSource = source;
if (source && source->ScrollTarget() != this)
source->SetScrollTarget(this);
ScrollSourceChanged(oldSource, fScrollSource);
}
}
Scroller*
Scrollable::ScrollSource() const
{
return fScrollSource;
}
void
Scrollable::SetDataRect(BRect dataRect, bool validateScrollOffset)
{
if (fDataRect != dataRect && dataRect.IsValid()) {
BRect oldDataRect = fDataRect;
fDataRect = dataRect;
DataRectChanged(oldDataRect, fDataRect);
if (fScrollSource)
fScrollSource->DataRectChanged(oldDataRect, fDataRect);
if (validateScrollOffset) {
BPoint offset = ValidScrollOffsetFor(fScrollOffset);
if (offset != fScrollOffset)
SetScrollOffset(offset);
}
}
}
BRect
Scrollable::DataRect() const
{
return fDataRect;
}
void
Scrollable::SetScrollOffset(BPoint offset)
{
offset = ValidScrollOffsetFor(offset);
if (fScrollOffset != offset) {
BPoint oldOffset = fScrollOffset;
fScrollOffset = offset;
ScrollOffsetChanged(oldOffset, fScrollOffset);
if (fScrollSource)
fScrollSource->ScrollOffsetChanged(oldOffset, fScrollOffset);
}
}
BPoint
Scrollable::ScrollOffset() const
{
return fScrollOffset;
}
void
Scrollable::SetDataRectAndScrollOffset(BRect dataRect, BPoint offset)
{
if (fDataRect != dataRect && dataRect.IsValid()) {
BRect oldDataRect = fDataRect;
fDataRect = dataRect;
DataRectChanged(oldDataRect, fDataRect);
if (fScrollSource) {
fScrollSource->SetScrollingEnabled(false);
fScrollSource->DataRectChanged(oldDataRect, fDataRect);
}
offset = ValidScrollOffsetFor(offset);
if (offset != fScrollOffset)
SetScrollOffset(offset);
if (fScrollSource)
fScrollSource->SetScrollingEnabled(true);
}
}
BPoint
Scrollable::ValidScrollOffsetFor(BPoint offset) const
{
return ValidScrollOffsetFor(offset, fDataRect);
}
BPoint
Scrollable::ValidScrollOffsetFor(BPoint offset, const BRect& dataRect) const
{
float maxX = max_c(dataRect.left, dataRect.right - fVisibleWidth);
float maxY = max_c(dataRect.top, dataRect.bottom - fVisibleHeight);
if (offset.x < dataRect.left)
offset.x = dataRect.left;
else if (offset.x > maxX)
offset.x = maxX;
if (offset.y < dataRect.top)
offset.y = dataRect.top;
else if (offset.y > maxY)
offset.y = maxY;
return offset;
}
void
Scrollable::SetVisibleSize(float width, float height)
{
if ((fVisibleWidth != width || fVisibleHeight != height) &&
width >= 0 && height >= 0) {
float oldWidth = fVisibleWidth;
float oldHeight = fVisibleHeight;
fVisibleWidth = width;
fVisibleHeight = height;
VisibleSizeChanged(oldWidth, oldHeight, fVisibleWidth, fVisibleHeight);
if (fScrollSource) {
fScrollSource->VisibleSizeChanged(oldWidth, oldHeight,
fVisibleWidth, fVisibleHeight);
}
BPoint offset = ValidScrollOffsetFor(fScrollOffset);
if (offset != fScrollOffset)
SetScrollOffset(offset);
}
}
BRect
Scrollable::VisibleBounds() const
{
return BRect(0.0, 0.0, fVisibleWidth, fVisibleHeight);
}
BRect
Scrollable::VisibleRect() const
{
BRect rect(0.0, 0.0, fVisibleWidth, fVisibleHeight);
rect.OffsetBy(fScrollOffset);
return rect;
}
void
Scrollable::DataRectChanged(BRect , BRect )
{
}
void
Scrollable::ScrollOffsetChanged(BPoint , BPoint )
{
}
void
Scrollable::VisibleSizeChanged(float , float ,
float , float )
{
}
void
Scrollable::ScrollSourceChanged(Scroller* ,
Scroller* )
{
}