From 7114fbc8dc4f2768feea88529d74be3500ac4f33 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 8 Jan 2019 15:19:48 +0100 Subject: [PATCH] [escher] Simplify ScrollViewIndicator --- escher/include/escher/scroll_view.h | 3 - escher/include/escher/scroll_view_indicator.h | 14 ++-- escher/src/scroll_view.cpp | 80 +++++++------------ escher/src/scroll_view_indicator.cpp | 51 +++++------- 4 files changed, 54 insertions(+), 94 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 097913aa1..7000ccc09 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -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; diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index fee919f2b..e568da8a1 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -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; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 015b5f527..8686d7a06 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -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(); } diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index e5be1f5c8..3a7ece58f 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -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