mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 05:40:38 +01:00
[escher] Simplify ScrollViewIndicator
This commit is contained in:
committed by
EmilieNumworks
parent
8772e1dc10
commit
7114fbc8dc
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user