[escher] Simplify ScrollViewIndicator

This commit is contained in:
Ruben Dashyan
2019-01-08 15:19:48 +01:00
committed by EmilieNumworks
parent 8772e1dc10
commit 7114fbc8dc
4 changed files with 54 additions and 94 deletions

View File

@@ -47,7 +47,6 @@ protected:
KDCoordinate maxContentHeightDisplayableWithoutScrolling();
KDRect visibleContentRect();
void layoutSubviews() override;
void updateScrollIndicator();
KDSize contentSize();
#if ESCHER_VIEW_LOGGING
virtual const char * className() const override;
@@ -61,8 +60,6 @@ private:
ScrollViewIndicator m_verticalScrollIndicator;
ScrollViewIndicator m_horizontalScrollIndicator;
bool hasVerticalIndicator() const;
bool hasHorizontalIndicator() const;
KDCoordinate m_topMargin;
KDCoordinate m_rightMargin;
KDCoordinate m_bottomMargin;

View File

@@ -19,11 +19,8 @@ public:
void setMargin(KDCoordinate m) { m_margin = m; }
KDCoordinate margin() const { return m_margin; }
float start() const;
void setStart(float start);
float end() const;
void setEnd(float end);
KDRect frame();
void update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength);
bool visible() const { return 0 < m_offset || m_visibleLength < 1; }
protected:
#if ESCHER_VIEW_LOGGING
virtual const char * className() const override;
@@ -32,8 +29,11 @@ protected:
private:
constexpr static KDCoordinate k_indicatorThickness = 4;
Direction m_direction;
float m_start;
float m_end;
KDCoordinate totalLength() const {
return ((m_direction == Direction::Horizontal) ? m_frame.width() : m_frame.height()) - 2*m_margin;
}
float m_offset;
float m_visibleLength;
KDColor m_indicatorColor;
KDColor m_backgroundColor;
KDCoordinate m_margin;

View File

@@ -31,33 +31,22 @@ void ScrollView::setCommonMargins() {
setLeftMargin(Metric::CommonLeftMargin);
}
bool ScrollView::hasVerticalIndicator() const {
if (m_showsIndicators) {
return m_verticalScrollIndicator.end() < 1 || m_verticalScrollIndicator.start() > 0;
}
return false;
}
bool ScrollView::hasHorizontalIndicator() const {
if (m_showsIndicators) {
return m_horizontalScrollIndicator.end() < 1 || m_horizontalScrollIndicator.start() > 0;
}
return false;
}
int ScrollView::numberOfSubviews() const {
return 1 + hasVerticalIndicator() + hasHorizontalIndicator();
return (m_showsIndicators) ? 1 + m_verticalScrollIndicator.visible() + m_horizontalScrollIndicator.visible() : 1;
}
View * ScrollView::subviewAtIndex(int index) {
switch (index) {
case 0:
return m_contentView;
case 1:
return hasHorizontalIndicator() ? &m_horizontalScrollIndicator : &m_verticalScrollIndicator;
case 2:
return &m_verticalScrollIndicator;
if (index == 0) {
return m_contentView;
}
if (m_showsIndicators) {
switch (index) {
case 1:
return m_horizontalScrollIndicator.visible() ? &m_horizontalScrollIndicator : &m_verticalScrollIndicator;
case 2:
return &m_verticalScrollIndicator;
}
}
return nullptr;
}
@@ -133,52 +122,41 @@ void ScrollView::layoutSubviews() {
KDRect contentFrame = KDRect(absoluteOffset, m_contentView->bounds().size());
m_contentView->setFrame(contentFrame);
if (!m_showsIndicators) {
return;
}
// We recompute the size of the scroll indicator
updateScrollIndicator();
m_verticalScrollIndicator.update(
m_contentView->bounds().height()+m_topMargin+m_bottomMargin,
contentOffset().y(),
m_frame.height()
);
m_horizontalScrollIndicator.update(
m_contentView->bounds().width()+m_leftMargin+m_rightMargin,
contentOffset().x(),
m_frame.width()
);
// Layout indicators
/* If the two indicators are visible, we leave an empty rectangle in the right
* bottom corner. Otherwise, the only indicator uses all the height/width. */
if (hasVerticalIndicator()) {
if (m_verticalScrollIndicator.visible()) {
KDRect verticalIndicatorFrame = KDRect(
m_frame.width() - m_indicatorThickness, 0,
m_indicatorThickness, m_frame.height() - hasHorizontalIndicator() * m_indicatorThickness
m_indicatorThickness, m_frame.height() - m_horizontalScrollIndicator.visible() * m_indicatorThickness
);
m_verticalScrollIndicator.setFrame(verticalIndicatorFrame);
}
if (hasHorizontalIndicator()) {
if (m_horizontalScrollIndicator.visible()) {
KDRect horizontalIndicatorFrame = KDRect(
0, m_frame.height() - m_indicatorThickness,
m_frame.width() - hasVerticalIndicator() * m_indicatorThickness, m_indicatorThickness
m_frame.width() - m_verticalScrollIndicator.visible() * m_indicatorThickness, m_indicatorThickness
);
m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame);
}
}
void ScrollView::updateScrollIndicator() {
if (!m_showsIndicators) {
return;
}
float contentHeight = m_contentView->bounds().height()+m_topMargin+m_bottomMargin;
bool hadVerticalIndicator = hasVerticalIndicator();
float verticalStart = contentOffset().y();
float verticalEnd = contentOffset().y() + m_frame.height();
m_verticalScrollIndicator.setStart(verticalStart/contentHeight);
m_verticalScrollIndicator.setEnd(verticalEnd/contentHeight);
if (hadVerticalIndicator && !hasVerticalIndicator()) {
markRectAsDirty(m_verticalScrollIndicator.frame());
}
float contentWidth = m_contentView->bounds().width()+m_leftMargin+m_rightMargin;
bool hadHorizontalIndicator = hasHorizontalIndicator();
float horizontalStart = contentOffset().x();
float horizontalEnd = contentOffset().x() + m_frame.width();
m_horizontalScrollIndicator.setStart(horizontalStart/contentWidth);
m_horizontalScrollIndicator.setEnd(horizontalEnd/contentWidth);
if (hadHorizontalIndicator && !hasHorizontalIndicator()) {
markRectAsDirty(m_horizontalScrollIndicator.frame());
}
}
KDSize ScrollView::contentSize() {
return m_contentView->minimalSizeForOptimalDisplay();
}

View File

@@ -7,8 +7,8 @@ extern "C" {
ScrollViewIndicator::ScrollViewIndicator(ScrollViewIndicator::Direction direction) :
View(),
m_direction(direction),
m_start(0),
m_end(0),
m_offset(0),
m_visibleLength(0),
m_indicatorColor(Palette::GreyDark),
m_backgroundColor(Palette::GreyMiddle),
m_margin(14)
@@ -19,52 +19,37 @@ void ScrollViewIndicator::drawRect(KDContext * ctx, KDRect rect) const {
KDRect frame = KDRectZero;
if (m_direction == Direction::Horizontal) {
frame = KDRect(m_margin, (m_frame.height() - k_indicatorThickness)/2,
m_frame.width() - 2*m_margin, k_indicatorThickness);
totalLength(), k_indicatorThickness);
} else {
assert(m_direction == Direction::Vertical);
frame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin,
k_indicatorThickness, m_frame.height() - 2*m_margin);
k_indicatorThickness, totalLength());
}
ctx->fillRect(frame, m_backgroundColor);
KDRect indicatorFrame = KDRectZero;
if (m_direction == Direction::Horizontal) {
KDCoordinate indicatorWidth = m_frame.width() - 2*m_margin;
indicatorFrame = KDRect(m_margin+m_start*indicatorWidth, (m_frame.height() - k_indicatorThickness)/2,
(m_end-m_start)*indicatorWidth, k_indicatorThickness);
indicatorFrame = KDRect(m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2,
m_visibleLength*totalLength(), k_indicatorThickness);
} else {
assert(m_direction == Direction::Vertical);
KDCoordinate indicatorHeight = m_frame.height() - 2*m_margin;
indicatorFrame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin+m_start*indicatorHeight,
k_indicatorThickness, (m_end-m_start)*indicatorHeight);
indicatorFrame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(),
k_indicatorThickness, m_visibleLength*totalLength());
}
ctx->fillRect(indicatorFrame, m_indicatorColor);
}
float ScrollViewIndicator::start() const {
return m_start;
}
void ScrollViewIndicator::setStart(float start) {
if (m_start != start) {
m_start = start;
void ScrollViewIndicator::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) {
float offset = contentOffset;
float visibleLength = visibleContentLength;
offset = offset / totalContentLength;
visibleLength = visibleLength / totalContentLength;
if (m_offset != offset || m_visibleLength != visibleLength) {
m_offset = offset;
m_visibleLength = visibleLength;
markRectAsDirty(bounds());
}
}
float ScrollViewIndicator::end() const {
return m_end;
}
void ScrollViewIndicator::setEnd(float end) {
if (m_end != end) {
m_end = end;
markRectAsDirty(bounds());
}
}
KDRect ScrollViewIndicator::frame() {
return m_frame;
}
#if ESCHER_VIEW_LOGGING
const char * ScrollViewIndicator::className() const {
return "ScrollViewIndicator";
@@ -72,7 +57,7 @@ const char * ScrollViewIndicator::className() const {
void ScrollViewIndicator::logAttributes(std::ostream &os) const {
View::logAttributes(os);
os << " start=\"" << m_start << "\"";
os << " end=\"" << m_end << "\"";
os << " offset=\"" << m_offset << "\"";
os << " visibleLength=\"" << m_visibleLength << "\"";
}
#endif