From 87ca58b8984f6a237911a65b4e1e870305539897 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Tue, 3 Jan 2017 05:19:44 +0100 Subject: [PATCH] FScrollView now has on-demand scroll bars --- ChangeLog | 3 + src/fenum.h | 8 +++ src/fscrollview.cpp | 169 ++++++++++++++++++++++++++++++++++---------- src/fscrollview.h | 70 +++++++++--------- src/fvterm.cpp | 2 +- 5 files changed, 183 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d9d2d9e..703111d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2017-01-03 Markus Gans + * FScrollView now has on-demand scroll bars + 2017-01-02 Markus Gans * The new FScrollView widget provides a scrollable viewport to change the area of interest diff --git a/src/fenum.h b/src/fenum.h index ad8a2144..114a155c 100644 --- a/src/fenum.h +++ b/src/fenum.h @@ -906,6 +906,14 @@ class fc FocusDefiniteWidget = 0x03 }; + // scroll bar visibility mode + enum scrollBarMode + { + Auto = 0, // Shows a scroll bar when area is larger than viewport + Hidden = 1, // Never shows a scroll bar + Scroll = 2 // Always shows a scroll bar + }; + // xterm cursor style enum xtermCursorStyle { diff --git a/src/fscrollview.cpp b/src/fscrollview.cpp index cfee1766..4fbd5204 100644 --- a/src/fscrollview.cpp +++ b/src/fscrollview.cpp @@ -18,7 +18,9 @@ FScrollView::FScrollView (FWidget* parent) , vbar(0) , hbar(0) , nf_offset(0) - , own_print_area(false) + , use_own_print_area(false) + , vMode(fc::Auto) + , hMode(fc::Auto) { init(); } @@ -39,7 +41,7 @@ void FScrollView::setScrollWidth (int width) if ( width < getClientWidth() ) width = getClientWidth(); - if ( scroll_size.getWidth() == width ) + if ( getScrollWidth() == width ) return; if ( viewport ) @@ -52,9 +54,7 @@ void FScrollView::setScrollWidth (int width) hbar->setMaximum (width - getClientWidth()); hbar->setPageSize (width, getClientWidth()); hbar->calculateSliderValues(); - - if ( ! hbar->isVisible() ) - hbar->setVisible(); + setHorizontalScrollBarVisibility(); } //---------------------------------------------------------------------- @@ -63,7 +63,7 @@ void FScrollView::setScrollHeight (int height) if ( height < getClientHeight() ) height = getClientHeight(); - if ( scroll_size.getHeight() == height ) + if ( getScrollHeight() == height ) return; if ( viewport ) @@ -76,9 +76,7 @@ void FScrollView::setScrollHeight (int height) vbar->setMaximum (height - getClientHeight()); vbar->setPageSize (height, getClientHeight()); vbar->calculateSliderValues(); - - if ( ! vbar->isVisible() ) - vbar->setVisible(); + setVerticalScrollBarVisibility(); } //---------------------------------------------------------------------- @@ -90,8 +88,7 @@ void FScrollView::setScrollSize (int width, int height) if ( height < getClientHeight() ) height = getClientHeight(); - if ( scroll_size.getWidth() == width - && scroll_size.getHeight() == height ) + if ( getScrollWidth() == width && getScrollHeight() == height ) return; if ( viewport ) @@ -104,30 +101,46 @@ void FScrollView::setScrollSize (int width, int height) hbar->setMaximum (width - getClientWidth()); hbar->setPageSize (width, getClientWidth()); hbar->calculateSliderValues(); - - if ( ! hbar->isVisible() ) - hbar->setVisible(); + setHorizontalScrollBarVisibility(); vbar->setMaximum (height - getClientHeight()); vbar->setPageSize (height, getClientHeight()); vbar->calculateSliderValues(); - - if ( ! vbar->isVisible() ) - vbar->setVisible(); + setVerticalScrollBarVisibility(); } //---------------------------------------------------------------------- void FScrollView::setX (int x, bool adjust) { FWidget::setX (x, adjust); - scroll_size.setX (getTermX() - 1); + + if ( ! adjust ) + { + scroll_size.setX (getTermX() - 1); + + if ( viewport ) + { + viewport->x_offset = scroll_size.getX(); + viewport->y_offset = scroll_size.getY(); + } + } } //---------------------------------------------------------------------- void FScrollView::setY (int y, bool adjust) { FWidget::setY (y, adjust); - scroll_size.setY (getTermY() - 1); + + if ( ! adjust ) + { + scroll_size.setY (getTermY() - 1); + + if ( viewport ) + { + viewport->x_offset = scroll_size.getX(); + viewport->y_offset = scroll_size.getY(); + } + } } //---------------------------------------------------------------------- @@ -135,6 +148,15 @@ void FScrollView::setPos (int x, int y, bool adjust) { FWidget::setPos (x, y, adjust); scroll_size.setPos (getTermX() - 1, getTermY() - 1); + + if ( ! adjust ) + { + if ( viewport ) + { + viewport->x_offset = scroll_size.getX(); + viewport->y_offset = scroll_size.getY(); + } + } } //---------------------------------------------------------------------- @@ -143,7 +165,7 @@ void FScrollView::setWidth (int w, bool adjust) FWidget::setWidth (w, adjust); calculateScrollbarPos(); - if ( scroll_size.getWidth() < getClientWidth() ) + if ( getScrollWidth() < getClientWidth() ) setScrollWidth (getClientWidth()); } @@ -153,7 +175,7 @@ void FScrollView::setHeight (int h, bool adjust) FWidget::setHeight (h, adjust); calculateScrollbarPos(); - if ( scroll_size.getHeight() < getClientHeight() ) + if ( getScrollHeight() < getClientHeight() ) setScrollHeight (getClientHeight()); } @@ -163,8 +185,8 @@ void FScrollView::setSize (int w, int h, bool adjust) FWidget::setSize (w, h, adjust); calculateScrollbarPos(); - if ( scroll_size.getWidth() < getClientWidth() - || scroll_size.getHeight() < getClientHeight() ) + if ( getScrollWidth() < getClientWidth() + || getScrollHeight() < getClientHeight() ) setScrollSize (getClientWidth(), getClientHeight()); } @@ -175,9 +197,30 @@ void FScrollView::setGeometry (int x, int y, int w, int h, bool adjust) scroll_size.setPos (getTermX() - 1, getTermY() - 1); calculateScrollbarPos(); - if ( scroll_size.getWidth() < getClientWidth() - || scroll_size.getHeight() < getClientHeight() ) + if ( getScrollWidth() < getClientWidth() + || getScrollHeight() < getClientHeight() ) + { setScrollSize (getClientWidth(), getClientHeight()); + } + else if ( ! adjust && viewport ) + { + viewport->x_offset = scroll_size.getX(); + viewport->y_offset = scroll_size.getY(); + } +} + +//---------------------------------------------------------------------- +void FScrollView::setHorizontalScrollBarMode (fc::scrollBarMode mode) +{ + hMode = mode; + setHorizontalScrollBarVisibility(); +} + +//---------------------------------------------------------------------- +void FScrollView::setVerticalScrollBarMode (fc::scrollBarMode mode) +{ + vMode = mode; + setVerticalScrollBarVisibility(); } //---------------------------------------------------------------------- @@ -190,7 +233,7 @@ void FScrollView::clearArea (int fillchar) //---------------------------------------------------------------------- void FScrollView::draw() { - own_print_area = true; + use_own_print_area = true; if ( FWidget* p = getParentWidget() ) setColor (p->getForegroundColor(), p->getBackgroundColor()); @@ -202,7 +245,7 @@ void FScrollView::draw() else drawBorder(); - own_print_area = false; + use_own_print_area = false; copy2area(); if ( vbar->isVisible() ) @@ -210,7 +253,6 @@ void FScrollView::draw() if ( hbar->isVisible() ) hbar->redraw(); - } //---------------------------------------------------------------------- @@ -235,7 +277,7 @@ void FScrollView::onWheel (FWheelEvent* ev) case fc::WheelDown: { - int yoffset_end = scroll_size.getHeight() - getClientHeight(); + int yoffset_end = getScrollHeight() - getClientHeight(); if ( yoffset_end < 0 ) yoffset_end = 0; @@ -279,7 +321,7 @@ FVTerm::term_area* FScrollView::getPrintArea() { // returns the viewport print area - if ( viewport && ! own_print_area ) + if ( viewport && ! use_own_print_area ) return viewport; else return FVTerm::getPrintArea(); @@ -294,19 +336,30 @@ void FScrollView::adjustSize() int xoffset = scroll_offset.getX(); int yoffset = scroll_offset.getY(); - hbar->setMaximum (scroll_size.getWidth() - getClientWidth()); - hbar->setPageSize (scroll_size.getWidth(), getClientWidth()); + scroll_size.setPos (getTermX() - 1, getTermY() - 1); + + if ( viewport ) + { + viewport->x_offset = scroll_size.getX(); + viewport->y_offset = scroll_size.getY(); + } + + hbar->setMaximum (getScrollWidth() - getClientWidth()); + hbar->setPageSize (getScrollWidth(), getClientWidth()); hbar->setY (height); hbar->setWidth (width - 2, false); hbar->setValue (xoffset); hbar->resize(); + setHorizontalScrollBarVisibility(); - vbar->setMaximum (scroll_size.getHeight() - getClientHeight()); - vbar->setPageSize (scroll_size.getHeight(), getClientHeight()); + vbar->setMaximum (getScrollHeight() - getClientHeight()); + vbar->setPageSize (getScrollHeight(), getClientHeight()); vbar->setX (width); vbar->setHeight (height - 2, false); vbar->setValue (yoffset); vbar->resize(); + setVerticalScrollBarVisibility(); + } //---------------------------------------------------------------------- @@ -412,6 +465,50 @@ void FScrollView::calculateScrollbarPos() hbar->resize(); } +//---------------------------------------------------------------------- +void FScrollView::setHorizontalScrollBarVisibility() +{ + switch ( hMode ) + { + case fc::Auto: + if ( getScrollWidth() > getClientWidth() ) + hbar->setVisible(); + else + hbar->hide(); + break; + + case fc::Hidden: + hbar->hide(); + break; + + case fc::Scroll: + hbar->setVisible(); + break; + } +} + +//---------------------------------------------------------------------- +void FScrollView::setVerticalScrollBarVisibility() +{ + switch ( vMode ) + { + case fc::Auto: + if ( getScrollHeight() > getClientHeight() ) + vbar->setVisible(); + else + vbar->hide(); + break; + + case fc::Hidden: + vbar->hide(); + break; + + case fc::Scroll: + vbar->setVisible(); + break; + } +} + //---------------------------------------------------------------------- void FScrollView::cb_VBarChange (FWidget*, void*) { @@ -420,7 +517,7 @@ void FScrollView::cb_VBarChange (FWidget*, void*) int distance = 1; int yoffset = scroll_offset.getY(); int yoffset_before = yoffset; - int yoffset_end = scroll_size.getHeight() - getClientHeight(); + int yoffset_end = getScrollHeight() - getClientHeight(); scrollType = vbar->getScrollType(); switch ( scrollType ) @@ -527,7 +624,7 @@ void FScrollView::cb_HBarChange (FWidget*, void*) int distance = 1; int xoffset = scroll_offset.getX(); int xoffset_before = xoffset; - int xoffset_end = scroll_size.getWidth() - getClientWidth(); + int xoffset_end = getScrollWidth() - getClientWidth(); scrollType = hbar->getScrollType(); switch ( scrollType ) diff --git a/src/fscrollview.h b/src/fscrollview.h index ebed1b91..094cdc37 100644 --- a/src/fscrollview.h +++ b/src/fscrollview.h @@ -54,41 +54,43 @@ class FScrollView : public FWidget virtual ~FScrollView(); // Accessors - const char* getClassName() const; - int getScrollWidth(); - int getScrollHeight(); + const char* getClassName() const; + int getScrollWidth(); + int getScrollHeight(); // Mutator - void setScrollWidth (int); - void setScrollHeight (int); - void setScrollSize (int, int); - void setScrollOffset (FPoint); - void setScrollOffset (int, int); - virtual void setX (int, bool = true); - virtual void setY (int, bool = true); - virtual void setPos (int, int, bool = true); - virtual void setWidth (int, bool = true); - virtual void setHeight (int, bool = true); - virtual void setSize (int, int, bool = true); - void setGeometry (int, int, int, int, bool = true); + void setScrollWidth (int); + void setScrollHeight (int); + void setScrollSize (int, int); + void setScrollOffset (FPoint); + void setScrollOffset (int, int); + virtual void setX (int, bool = true); + virtual void setY (int, bool = true); + virtual void setPos (int, int, bool = true); + virtual void setWidth (int, bool = true); + virtual void setHeight (int, bool = true); + virtual void setSize (int, int, bool = true); + void setGeometry (int, int, int, int, bool = true); + void setHorizontalScrollBarMode (fc::scrollBarMode); + void setVerticalScrollBarMode (fc::scrollBarMode); // Method - virtual void clearArea (int = ' '); - virtual void draw(); + virtual void clearArea (int = ' '); + virtual void draw(); // Event handlers - void onWheel (FWheelEvent*); + void onWheel (FWheelEvent*); protected: // Using-declaration using FVTerm::clearArea; // Accessor - term_area* getPrintArea(); + term_area* getPrintArea(); // Method - void adjustSize(); - void copy2area(); + void adjustSize(); + void copy2area(); private: // Disable copy constructor @@ -98,21 +100,25 @@ class FScrollView : public FWidget FScrollView& operator = (const FScrollView&); // Methods - void init(); - void calculateScrollbarPos(); + void init(); + void calculateScrollbarPos(); + void setHorizontalScrollBarVisibility(); + void setVerticalScrollBarVisibility(); // Callback methods - void cb_VBarChange (FWidget*, void*); - void cb_HBarChange (FWidget*, void*); + void cb_VBarChange (FWidget*, void*); + void cb_HBarChange (FWidget*, void*); // Data Members - FRect scroll_size; - FPoint scroll_offset; - term_area* viewport; // virtual scroll content - FScrollbar* vbar; - FScrollbar* hbar; - int nf_offset; - bool own_print_area; + FRect scroll_size; + FPoint scroll_offset; + term_area* viewport; // virtual scroll content + FScrollbar* vbar; + FScrollbar* hbar; + int nf_offset; + bool use_own_print_area; + fc::scrollBarMode vMode; // fc:Auto, fc::Hidden or fc::Scroll + fc::scrollBarMode hMode; }; #pragma pack(pop) diff --git a/src/fvterm.cpp b/src/fvterm.cpp index a31456c9..5d438fc0 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -1652,7 +1652,7 @@ void FVTerm::clearArea (term_area* area, int fillchar) std::memcpy (&nc, &next_attribute, sizeof(char_data)); nc.code = fillchar; - if ( ! area ) + if ( ! (area && area->text) ) return; total_width = area->width + area->right_shadow;