1 // -*- C++ -*-
2 /* GG is a GUI for OpenGL.
3    Copyright (C) 2003-2008 T. Zachary Laine
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation; either version 2.1
8    of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA
19 
20    If you do not wish to comply with the terms of the LGPL please
21    contact the author as other terms are available for a fee.
22 
23    Zach Laine
24    whatwasthataddress@gmail.com */
25 
26 /** \file Scroll.h \brief Contains the Scroll scrollbar control class. */
27 
28 #ifndef _GG_Scroll_h_
29 #define _GG_Scroll_h_
30 
31 #include <GG/Control.h>
32 #include <GG/GLClientAndServerBuffer.h>
33 
34 #include <boost/signals2/signal.hpp>
35 
36 
37 namespace GG {
38 
39 class Button;
40 
41 /** \brief This is a basic scrollbar control.
42 
43     The range of the values the scrollbar represents is [m_range_min,
44     m_range_max].  However, m_posn can only range over [m_range_min,
45     m_range_max - m_page_sz], because the tab has a logical width of
46     m_page_sz.  So the region of the scrollbar's range being viewed at any one
47     time is [m_posn, m_posn + m_page_sz].  (m_posn + m_page_sz is actually the
48     last + 1 element of the range.)  The parent of the control is notified of
49     a scroll via ScrolledSignalType signals; these are emitted from the
50     Scroll*() functions and the UpdatePosn() function.  This should cover
51     every instance in which m_posn is altered.  The parent can poll the
52     control to get its current view area with a call to GetPosnRange().  An
53     increase in a vertical scroll is down, and a decrease is up; since GG
54     assumes the y-coordinates are downwardly increasing.  The rather plain
55     default buttons and tab can be replaced by any Button-derived controls
56     desired. */
57 class GG_API Scroll : public Control
58 {
59 public:
60     /// the clickable regions of a Scroll
61     GG_CLASS_ENUM(ScrollRegion,
62         SBR_NONE,
63         SBR_PAGE_DN,
64         SBR_PAGE_UP
65     )
66 
67     /** \name Signal Types */ ///@{
68     /** emitted whenever the scrollbar is moved; the upper and lower extents
69         of the tab and the upper and lower bounds of the scroll's range are
70         indicated, respectively */
71     typedef boost::signals2::signal<void (int, int, int, int)> ScrolledSignalType;
72     /** emitted when the scrollbar's tab is stopped after being dragged, the
73         scrollbar is adjusted using the keyboard, or the scrollbar is moved
74         programmatically; the upper and lower extents of the tab and the
75         upper and lower bounds of the scroll's range are indicated,
76         respectively */
77     typedef boost::signals2::signal<void (int, int, int, int)> ScrolledAndStoppedSignalType;
78     //@}
79 
80     /** \name Structors */ ///@{
81     /** Ctor. */
82     Scroll(Orientation orientation, Clr color, Clr interior);
83     //@}
84     void CompleteConstruction() override;
85 
86     /** \name Accessors */ ///@{
87     Pt MinUsableSize() const override;
88 
89     std::pair<int, int>  PosnRange() const;         ///< range currently being viewed
90     std::pair<int, int>  ScrollRange() const;       ///< defined possible range of control
91     unsigned int         LineSize() const;          ///< returns the current line size
92     unsigned int         PageSize() const;          ///< returns the current page size
93 
94     Clr                  InteriorColor() const;     ///< returns the color used to render the interior of the Scroll
95     Orientation          ScrollOrientation() const; ///< returns the orientation of the Scroll
96 
97     mutable ScrolledSignalType           ScrolledSignal;           ///< the scrolled signal object for this Scroll
98     mutable ScrolledAndStoppedSignalType ScrolledAndStoppedSignal; ///< the scrolled-and-stopped signal object for this Scroll
99     //@}
100 
101     /** \name Mutators */ ///@{
102     void Render() override;
103 
104     void SizeMove(const Pt& ul, const Pt& lr) override;
105 
106     void Disable(bool b = true) override;
107     void SetColor(Clr c) override;
108 
109     virtual void DoLayout();
110 
111     void SetInteriorColor(Clr c); ///< sets the color painted into the client area of the control
112     void SizeScroll(int min, int max, unsigned int line, unsigned int page); ///< sets the logical ranges of the control, and the logical increment values
113     void SetMax(int max);         ///< sets the maximum value of the scroll
114     void SetMin(int min);         ///< sets the minimum value of the scroll
115     void SetLineSize(unsigned int line); ///< sets the size of a line in the scroll. This is the number of logical units the tab moves when either of the up or down buttons is pressed.
116     void SetPageSize(unsigned int page); ///< sets the size of a line page in the scroll. This is the number of logical units the tab moves when either of the page-up or page-down areas is clicked.
117 
118     void ScrollTo(int p);  ///< scrolls the control to a certain spot
119     void ScrollLineIncr(int lines = 1); ///< scrolls the control down (or right) by \a lines lines
120     void ScrollLineDecr(int lines = 1); ///< scrolls the control up (or left) by \a lines lines
121     void ScrollPageIncr(); ///< scrolls the control down (or right) by a page
122     void ScrollPageDecr(); ///< scrolls the control up (or left) by a page
123     //@}
124 
125 protected:
126     /** \name Accessors */ ///@{
127     unsigned int  TabSpace() const;          ///< returns the space the tab has to move about in (the control's width less the width of the incr & decr buttons)
128     unsigned int  TabWidth() const;          ///< returns the calculated width of the tab, based on PageSize() and the logical size of the control, in pixels
129     ScrollRegion  RegionUnder(const Pt& pt); ///< determines whether a pt is in the incr or decr or tab buttons, or in PgUp/PgDn regions in between
130 
131     Button*       TabButton() const;     ///< returns the button representing the tab
132     Button*       IncrButton() const;    ///< returns the increase button (line down/line right)
133     Button*       DecrButton() const;    ///< returns the decrease button (line up/line left)
134     //@}
135 
136     /** \name Mutators */ ///@{
137     void LButtonDown(const Pt& pt, Flags<ModKey> mod_keys) override;
138     void LButtonUp(const Pt& pt, Flags<ModKey> mod_keys) override;
139     void LClick(const Pt& pt, Flags<ModKey> mod_keys) override;
140     void MouseHere(const Pt& pt, Flags<ModKey> mod_keys) override;
141     bool EventFilter(Wnd* w, const WndEvent& event) override;
142 
143     virtual void InitBuffer();
144     //@}
145 
146     GG::GL2DVertexBuffer    m_buffer;
147 
148 private:
149     void UpdatePosn();                      ///< adjusts m_posn due to a tab-drag
150     void MoveTabToPosn();                   ///< adjusts tab due to a button click, PgUp, etc.
151     void ScrollLineIncrDecrImpl(bool signal, int lines);
152 
153     Clr                     m_int_color;    ///< color inside border of slide area
154     const Orientation       m_orientation;  ///< vertical or horizontal scroll? (use enum for these declared above)
155     int                     m_posn;         ///< current position of tab in logical coords (will be in [m_range_min, m_range_max - m_page_sz])
156     int                     m_range_min;    ///< lowest value in range of scrollbar
157     int                     m_range_max;    ///< highest value "
158     unsigned int            m_line_sz;      ///< logical units traversed in a line movement (such as a click on either end button)
159     unsigned int            m_page_sz;      ///< logical units traversed for a page movement (such as a click in non-tab middle area, or PgUp/PgDn)
160     std::shared_ptr<Button> m_tab;          ///< the button representing the tab
161     std::shared_ptr<Button> m_incr;         ///< the increase button (line down/line right)
162     std::shared_ptr<Button> m_decr;         ///< the decrease button (line up/line left)
163     ScrollRegion            m_initial_depressed_region; ///< the part of the scrollbar originally under cursor in LButtonDown msg
164     ScrollRegion            m_depressed_region;         ///< the part of the scrollbar currently being "depressed" by held-down mouse button
165     bool                    m_dragging_tab = false;
166     bool                    m_tab_dragged = false;
167 };
168 
169 /** A convenience function that signals \a scroll's position, via
170     Scroll::ScrolledSignal.  If \a stopped is true, the position is
171     additionally signalled on Scroll::ScrolledAndStoppedSignal. */
172 GG_API void SignalScroll(const Scroll& scroll, bool stopped);
173 
174 } // namespace GG
175 
176 #endif
177