diff options
Diffstat (limited to 'src/widget_type.h')
-rw-r--r-- | src/widget_type.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/widget_type.h b/src/widget_type.h index f61937aa8..7b5597ed7 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -502,6 +502,132 @@ public: }; /** + * Scrollbar data structure + */ +class Scrollbar { +private: + const bool is_vertical; ///< Scrollbar has vertical orientation. + uint16 count; ///< Number of elements in the list. + uint16 cap; ///< Number of visible elements of the scroll bar. + uint16 pos; ///< Index of first visible item of the list. + +public: + Scrollbar(bool is_vertical) : is_vertical(is_vertical) + { + } + + /** + * Gets the number of elements in the list + * @return the number of elements + */ + FORCEINLINE uint16 GetCount() const + { + return this->count; + } + + /** + * Gets the number of visible elements of the scrollbar + * @return the number of visible elements + */ + FORCEINLINE uint16 GetCapacity() const + { + return this->cap; + } + + /** + * Gets the position of the first visible element in the list + * @return the position of the element + */ + FORCEINLINE uint16 GetPosition() const + { + return this->pos; + } + + /** + * Checks whether given current item is visible in the list + * @param item to check + * @return true iff the item is visible + */ + FORCEINLINE bool IsVisible(uint16 item) const + { + return IsInsideBS(item, this->GetPosition(), this->GetCapacity()); + } + + /** + * Sets the number of elements in the list + * @param num the number of elements in the list + * @note updates the position if needed + */ + void SetCount(int num) + { + assert(num >= 0); + assert(num <= MAX_UVALUE(uint16)); + + this->count = num; + num -= this->cap; + if (num < 0) num = 0; + if (num < this->pos) this->pos = num; + } + + /** + * Set the capacity of visible elements. + * @param capacity the new capacity + * @note updates the position if needed + */ + void SetCapacity(int capacity) + { + assert(capacity > 0); + assert(capacity <= MAX_UVALUE(uint16)); + + this->cap = capacity; + if (this->cap + this->pos > this->count) this->pos = max(0, this->count - this->cap); + } + + void SetCapacityFromWidget(Window *w, int widget, int padding = 0); + + /** + * Sets the position of the first visible element + * @param position the position of the element + */ + void SetPosition(int position) + { + assert(position >= 0); + assert(this->count <= this->cap ? (position == 0) : (position + this->cap <= this->count)); + this->pos = position; + } + + /** + * Updates the position of the first visible element by the given amount. + * If the position would be too low or high it will be clamped appropriately + * @param difference the amount of change requested + */ + void UpdatePosition(int difference) + { + if (difference == 0) return; + this->SetPosition(Clamp(this->pos + difference, 0, max(this->count - this->cap, 0))); + } + + /** + * Scroll towards the given position; if the item is visible nothing + * happens, otherwise it will be shown either at the bottom or top of + * the window depending on where in the list it was. + * @param position the position to scroll towards. + */ + void ScrollTowards(int position) + { + if (position < this->GetPosition()) { + /* scroll up to the item */ + this->SetPosition(position); + } else if (position >= this->GetPosition() + this->GetCapacity()) { + /* scroll down so that the item is at the bottom */ + this->SetPosition(position - this->GetCapacity() + 1); + } + } + + int GetScrolledRowFromWidget(int clickpos, const Window * const w, int widget, int padding = 0, int line_height = -1) const; +}; + +/** * Nested widget to display and control a scrollbar in a window. * Also assign the scrollbar to other widgets using #SetScrollbar() to make the mousewheel work. * @ingroup NestedWidgets |