1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 /*!
12 \file GUIListContainer.h
13 \brief
14 */
15 
16 #include "GUIAction.h"
17 #include "IGUIContainer.h"
18 #include "utils/Stopwatch.h"
19 
20 #include <list>
21 #include <utility>
22 #include <vector>
23 
24 /*!
25  \ingroup controls
26  \brief
27  */
28 
29 class IListProvider;
30 class TiXmlNode;
31 class CGUIListItemLayout;
32 
33 class CGUIBaseContainer : public IGUIContainer
34 {
35 public:
36   CGUIBaseContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems);
37   CGUIBaseContainer(const CGUIBaseContainer &);
38   ~CGUIBaseContainer(void) override;
39 
40   bool OnAction(const CAction &action) override;
41   void OnDown() override;
42   void OnUp() override;
43   void OnLeft() override;
44   void OnRight() override;
45   bool OnMouseOver(const CPoint &point) override;
46   bool CanFocus() const override;
47   bool OnMessage(CGUIMessage& message) override;
48   void SetFocus(bool bOnOff) override;
49   void AllocResources() override;
50   void FreeResources(bool immediately = false) override;
51   void UpdateVisibility(const CGUIListItem *item = NULL) override;
52 
53   virtual unsigned int GetRows() const;
54 
55   virtual bool HasNextPage() const;
56   virtual bool HasPreviousPage() const;
57 
58   void SetPageControl(int id);
59 
60   std::string GetDescription() const override;
61   void SaveStates(std::vector<CControlState> &states) override;
62   virtual int GetSelectedItem() const;
63 
64   void DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions) override;
65   void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) override;
66 
67   void LoadLayout(TiXmlElement *layout);
68   void LoadListProvider(TiXmlElement *content, int defaultItem, bool defaultAlways);
69 
70   CGUIListItemPtr GetListItem(int offset, unsigned int flag = 0) const override;
71 
72   bool GetCondition(int condition, int data) const override;
73   std::string GetLabel(int info) const override;
74 
75   /*! \brief Set the list provider for this container (for python).
76    \param provider the list provider to use for this container.
77    */
78   void SetListProvider(IListProvider *provider);
79 
80   /*! \brief Set the offset of the first item in the container from the container's position
81    Useful for lists/panels where the focused item may be larger than the non-focused items and thus
82    normally cut off from the clipping window defined by the container's position + size.
83    \param offset CPoint holding the offset in skin coordinates.
84    */
85   void SetRenderOffset(const CPoint &offset);
86 
SetClickActions(const CGUIAction & clickActions)87   void SetClickActions(const CGUIAction& clickActions) { m_clickActions = clickActions; };
SetFocusActions(const CGUIAction & focusActions)88   void SetFocusActions(const CGUIAction& focusActions) { m_focusActions = focusActions; };
SetUnFocusActions(const CGUIAction & unfocusActions)89   void SetUnFocusActions(const CGUIAction& unfocusActions) { m_unfocusActions = unfocusActions; };
90 
91   void SetAutoScrolling(const TiXmlNode *node);
92   void ResetAutoScrolling();
93   void UpdateAutoScrolling(unsigned int currentTime);
94 
95 #ifdef _DEBUG
96   void DumpTextureUse() override;
97 #endif
98 protected:
99   EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event) override;
100   bool OnClick(int actionID);
101 
102   virtual void ProcessItem(float posX, float posY, CGUIListItemPtr& item, bool focused, unsigned int currentTime, CDirtyRegionList &dirtyregions);
103 
104   void Render() override;
105   virtual void RenderItem(float posX, float posY, CGUIListItem *item, bool focused);
106   virtual void Scroll(int amount);
107   virtual bool MoveDown(bool wrapAround);
108   virtual bool MoveUp(bool wrapAround);
109   virtual bool GetOffsetRange(int &minOffset, int &maxOffset) const;
110   virtual void ValidateOffset();
111   virtual int  CorrectOffset(int offset, int cursor) const;
112   virtual void UpdateLayout(bool refreshAllItems = false);
113   virtual void SetPageControlRange();
114   virtual void UpdatePageControl(int offset);
115   virtual void CalculateLayout();
SelectItem(int item)116   virtual void SelectItem(int item) {};
SelectItemFromPoint(const CPoint & point)117   virtual bool SelectItemFromPoint(const CPoint &point) { return false; };
118   virtual int GetCursorFromPoint(const CPoint &point, CPoint *itemPoint = NULL) const { return -1; };
119   virtual void Reset();
GetNumItems()120   virtual size_t GetNumItems() const { return m_items.size(); };
121   virtual int GetCurrentPage() const;
122   bool InsideLayout(const CGUIListItemLayout *layout, const CPoint &point) const;
123   void OnFocus() override;
124   void OnUnFocus() override;
125   void UpdateListProvider(bool forceRefresh = false);
126 
127   int ScrollCorrectionRange() const;
128   inline float Size() const;
129   void FreeMemory(int keepStart, int keepEnd);
130   void GetCurrentLayouts();
131   CGUIListItemLayout *GetFocusedLayout() const;
132 
133   CPoint m_renderOffset; ///< \brief render offset of the first item in the list \sa SetRenderOffset
134 
135   float m_analogScrollCount;
136   unsigned int m_lastHoldTime;
137 
138   ORIENTATION m_orientation;
139   int m_itemsPerPage;
140 
141   std::vector< CGUIListItemPtr > m_items;
142   typedef std::vector<CGUIListItemPtr> ::iterator iItems;
143   CGUIListItemPtr m_lastItem;
144 
145   int m_pageControl;
146 
147   std::list<CGUIListItemLayout> m_layouts;
148   std::list<CGUIListItemLayout> m_focusedLayouts;
149 
150   CGUIListItemLayout *m_layout;
151   CGUIListItemLayout *m_focusedLayout;
152   bool m_layoutCondition = false;
153   bool m_focusedLayoutCondition = false;
154 
155   void ScrollToOffset(int offset);
156   void SetContainerMoving(int direction);
157   void UpdateScrollOffset(unsigned int currentTime);
158 
159   CScroller m_scroller;
160 
161   IListProvider *m_listProvider;
162 
163   bool m_wasReset;  // true if we've received a Reset message until we've rendered once.  Allows
164                     // us to make sure we don't tell the infomanager that we've been moving when
165                     // the "movement" was simply due to the list being repopulated (thus cursor position
166                     // changing around)
167 
168   void UpdateScrollByLetter();
169   void GetCacheOffsets(int &cacheBefore, int &cacheAfter) const;
GetCacheCount()170   int GetCacheCount() const { return m_cacheItems; };
ScrollingDown()171   bool ScrollingDown() const { return m_scroller.IsScrollingDown(); };
ScrollingUp()172   bool ScrollingUp() const { return m_scroller.IsScrollingUp(); };
173   void OnNextLetter();
174   void OnPrevLetter();
175   void OnJumpLetter(const std::string& letter, bool skip = false);
176   void OnJumpSMS(int letter);
177   std::vector< std::pair<int, std::string> > m_letterOffsets;
178 
179   /*! \brief Set the cursor position
180    Should be used by all base classes rather than directly setting it, as
181    this also marks the control as dirty (if needed)
182    */
183   virtual void SetCursor(int cursor);
GetCursor()184   inline int GetCursor() const { return m_cursor; };
185 
186   /*! \brief Set the container offset
187    Should be used by all base classes rather than directly setting it, as
188    this also marks the control as dirty (if needed)
189    */
190   void SetOffset(int offset);
191   /*! \brief Returns the index of the first visible row
192    returns the first row. This may be outside of the range of available items. Use GetItemOffset() to retrieve the first visible item in the list.
193    \sa GetItemOffset
194   */
GetOffset()195   inline int GetOffset() const { return m_offset; };
196   /*! \brief Returns the index of the first visible item
197    returns the first visible item. This will always be in the range of available items. Use GetOffset() to retrieve the first visible row in the list.
198    \sa GetOffset
199   */
GetItemOffset()200   inline int GetItemOffset() const { return CorrectOffset(GetOffset(), 0); }
201 
202   // autoscrolling
203   INFO::InfoPtr m_autoScrollCondition;
204   int           m_autoScrollMoveTime;   // time between to moves
205   unsigned int  m_autoScrollDelayTime;  // current offset into the delay
206   bool          m_autoScrollIsReversed; // scroll backwards
207 
208   unsigned int m_lastRenderTime;
209 
210 private:
211   bool OnContextMenu();
212 
213   int m_cursor;
214   int m_offset;
215   int m_cacheItems;
216   CStopWatch m_scrollTimer;
217   CStopWatch m_lastScrollStartTimer;
218   CStopWatch m_pageChangeTimer;
219 
220   CGUIAction m_clickActions;
221   CGUIAction m_focusActions;
222   CGUIAction m_unfocusActions;
223 
224   // letter match searching
225   CStopWatch m_matchTimer;
226   std::string m_match;
227   float m_scrollItemsPerFrame;
228   static const int letter_match_timeout = 1000;
229 
230   bool m_gestureActive = false;
231 
232   // early inertial scroll cancellation
233   bool m_waitForScrollEnd = false;
234   float m_lastScrollValue = 0.0f;
235 };
236 
237 
238