1 /*
2  *  Copyright (C) 2012-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 #include "XBDateTime.h"
12 #include "guilib/DirtyRegion.h"
13 #include "guilib/GUIControl.h"
14 #include "guilib/GUIListItemLayout.h"
15 #include "guilib/GUITexture.h"
16 #include "guilib/IGUIContainer.h"
17 #include "threads/CriticalSection.h"
18 #include "utils/Geometry.h"
19 
20 #include <memory>
21 #include <string>
22 #include <utility>
23 #include <vector>
24 
25 class CFileItem;
26 class CFileItemList;
27 class CGUIListItem;
28 class CGUIListItemLayout;
29 
30 namespace PVR
31 {
32   class CPVRChannel;
33   class CPVRChannelNumber;
34 
35   class CGUIEPGGridContainerModel;
36 
37   class CGUIEPGGridContainer : public IGUIContainer
38   {
39   public:
40     CGUIEPGGridContainer(int parentID, int controlID, float posX, float posY, float width, float height,
41                          ORIENTATION orientation, int scrollTime, int preloadItems, int minutesPerPage,
42                          int rulerUnit, const CTextureInfo& progressIndicatorTexture);
43     CGUIEPGGridContainer(const CGUIEPGGridContainer& other);
44 
Clone()45     CGUIEPGGridContainer* Clone() const override { return new CGUIEPGGridContainer(*this); }
46 
47     /*!
48      * @brief Check whether the control currently holds data.
49      * @return true if the control has data, false otherwise.
50      */
51     bool HasData() const;
52 
53     void AllocResources() override;
54     void FreeResources(bool immediately) override;
55 
56     bool OnAction(const CAction& action) override;
57     void OnDown() override;
58     void OnUp() override;
59     void OnLeft() override;
60     void OnRight() override;
61     bool OnMouseOver(const CPoint& point) override;
62     bool OnMessage(CGUIMessage& message) override;
63     void SetFocus(bool focus) override;
64     std::string GetDescription() const override;
65     EVENT_RESULT OnMouseEvent(const CPoint& point, const CMouseEvent& event) override;
66 
67     void Process(unsigned int currentTime, CDirtyRegionList& dirtyregions) override;
68     void Render() override;
69 
70     CGUIListItemPtr GetListItem(int offset, unsigned int flag = 0) const override;
71     std::string GetLabel(int info) const override;
72 
73     std::shared_ptr<CFileItem> GetSelectedGridItem(int offset = 0) const;
74     std::shared_ptr<CPVRChannel> GetSelectedChannel() const;
75     CDateTime GetSelectedDate() const;
76 
77     void LoadLayout(TiXmlElement* layout);
78     void SetPageControl(int id);
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 
87     void JumpToNow();
88     void JumpToDate(const CDateTime& date);
89 
90     void GoToBegin();
91     void GoToEnd();
92     void GoToNow();
93     void GoToDate(const CDateTime& date);
94 
95     void GoToFirstChannel();
96     void GoToLastChannel();
97 
98     void GoToTop();
99     void GoToBottom();
100     void GoToMostLeft();
101     void GoToMostRight();
102 
103     void SetTimelineItems(const std::unique_ptr<CFileItemList>& items,
104                           const CDateTime& gridStart,
105                           const CDateTime& gridEnd);
106 
107     std::unique_ptr<CFileItemList> GetCurrentTimeLineItems() const;
108 
109     /*!
110      * @brief Set the control's selection to the given channel and set the control's view port to show the channel.
111      * @param channel the channel.
112      * @return true if the selection was set to the given channel, false otherwise.
113      */
114     bool SetChannel(const std::shared_ptr<CPVRChannel>& channel);
115 
116     /*!
117      * @brief Set the control's selection to the given channel and set the control's view port to show the channel.
118      * @param channel the channel's path.
119      * @return true if the selection was set to the given channel, false otherwise.
120      */
121     bool SetChannel(const std::string& channel);
122 
123     /*!
124      * @brief Set the control's selection to the given channel and set the control's view port to show the channel.
125      * @param channelNumber the channel's number.
126      * @return true if the selection was set to the given channel, false otherwise.
127      */
128     bool SetChannel(const CPVRChannelNumber& channelNumber);
129 
130   private:
131     bool OnClick(int actionID);
132     bool SelectItemFromPoint(const CPoint& point, bool justGrid = true);
133 
134     void SetChannel(int channel);
135 
136     void SetBlock(int block, bool bUpdateBlockTravelAxis = true);
137     void UpdateBlock(bool bUpdateBlockTravelAxis = true);
138 
139     void ChannelScroll(int amount);
140     void ProgrammesScroll(int amount);
141     void ValidateOffset();
142     void UpdateLayout();
143 
144     void SetItem(const std::pair<std::shared_ptr<CFileItem>, int>& itemInfo);
145     bool SetItem(const std::shared_ptr<CFileItem>& item, int channelIndex, int blockIndex);
146     std::shared_ptr<CFileItem> GetItem() const;
147     std::pair<std::shared_ptr<CFileItem>, int> GetNextItem() const;
148     std::pair<std::shared_ptr<CFileItem>, int> GetPrevItem() const;
149     void UpdateItem();
150 
151     void MoveToRow(int row);
152 
153     CGUIListItemLayout* GetFocusedLayout() const;
154 
155     void ScrollToBlockOffset(int offset);
156     void ScrollToChannelOffset(int offset);
157     void GoToBlock(int blockIndex);
158     void GoToChannel(int channelIndex);
159     void UpdateScrollOffset(unsigned int currentTime);
160     void ProcessItem(float posX, float posY, const std::shared_ptr<CFileItem>& item, std::shared_ptr<CFileItem>& lastitem, bool focused, CGUIListItemLayout* normallayout, CGUIListItemLayout* focusedlayout, unsigned int currentTime, CDirtyRegionList& dirtyregions, float resize = -1.0f);
161     void RenderItem(float posX, float posY, CGUIListItem* item, bool focused);
162     void GetCurrentLayouts();
163 
164     void ProcessChannels(unsigned int currentTime, CDirtyRegionList& dirtyregions);
165     void ProcessRuler(unsigned int currentTime, CDirtyRegionList& dirtyregions);
166     void ProcessRulerDate(unsigned int currentTime, CDirtyRegionList& dirtyregions);
167     void ProcessProgrammeGrid(unsigned int currentTime, CDirtyRegionList& dirtyregions);
168     void ProcessProgressIndicator(unsigned int currentTime, CDirtyRegionList& dirtyregions);
169     void RenderChannels();
170     void RenderRulerDate();
171     void RenderRuler();
172     void RenderProgrammeGrid();
173     void RenderProgressIndicator();
174 
175     CPoint m_renderOffset; ///< \brief render offset of the first item in the list \sa SetRenderOffset
176 
177     ORIENTATION m_orientation;
178 
179     std::vector<CGUIListItemLayout> m_channelLayouts;
180     std::vector<CGUIListItemLayout> m_focusedChannelLayouts;
181     std::vector<CGUIListItemLayout> m_focusedProgrammeLayouts;
182     std::vector<CGUIListItemLayout> m_programmeLayouts;
183     std::vector<CGUIListItemLayout> m_rulerLayouts;
184     std::vector<CGUIListItemLayout> m_rulerDateLayouts;
185 
186     CGUIListItemLayout* m_channelLayout;
187     CGUIListItemLayout* m_focusedChannelLayout;
188     CGUIListItemLayout* m_programmeLayout;
189     CGUIListItemLayout* m_focusedProgrammeLayout;
190     CGUIListItemLayout* m_rulerLayout;
191     CGUIListItemLayout* m_rulerDateLayout;
192 
193     int m_pageControl;
194 
195     void GetChannelCacheOffsets(int& cacheBefore, int& cacheAfter);
196     void GetProgrammeCacheOffsets(int& cacheBefore, int& cacheAfter);
197 
198   private:
199     bool OnMouseClick(int dwButton, const CPoint& point);
200     bool OnMouseDoubleClick(int dwButton, const CPoint& point);
201     bool OnMouseWheel(char wheel, const CPoint& point);
202 
203     void HandleChannels(bool bRender, unsigned int currentTime, CDirtyRegionList& dirtyregions);
204     void HandleRuler(bool bRender, unsigned int currentTime, CDirtyRegionList& dirtyregions);
205     void HandleRulerDate(bool bRender, unsigned int currentTime, CDirtyRegionList& dirtyregions);
206     void HandleProgrammeGrid(bool bRender, unsigned int currentTime, CDirtyRegionList& dirtyregions);
207 
208     float GetCurrentTimePositionOnPage() const;
209     float GetProgressIndicatorWidth() const;
210     float GetProgressIndicatorHeight() const;
211 
212     void UpdateItems();
213 
214     float GetChannelScrollOffsetPos() const;
215     float GetProgrammeScrollOffsetPos() const;
216     int GetChannelScrollOffset(CGUIListItemLayout* layout) const;
217     int GetProgrammeScrollOffset() const;
218 
219     int m_rulerUnit; //! number of blocks that makes up one element of the ruler
220     int m_channelsPerPage;
221     int m_programmesPerPage;
222     int m_channelCursor;
223     int m_channelOffset;
224     int m_blocksPerPage;
225     int m_blockCursor;
226     int m_blockOffset;
227     int m_blockTravelAxis;
228     int m_cacheChannelItems;
229     int m_cacheProgrammeItems;
230     int m_cacheRulerItems;
231 
232     float m_rulerDateHeight; //! height of ruler date item
233     float m_rulerDateWidth; //! width of ruler date item
234     float m_rulerPosX; //! X position of first ruler item
235     float m_rulerPosY; //! Y position of first ruler item
236     float m_rulerHeight; //! height of the scrolling timeline above the ruler items
237     float m_rulerWidth; //! width of each element of the ruler
238     float m_channelPosX; //! X position of first channel row
239     float m_channelPosY; //! Y position of first channel row
240     float m_channelHeight; //! height of the channel item
241     float m_channelWidth; //! width of the channel item
242     float m_gridPosX; //! X position of first grid item
243     float m_gridPosY; //! Y position of first grid item
244     float m_gridWidth; //! width of the epg grid control
245     float m_gridHeight; //! height of the epg grid control
246     float m_blockSize; //! a block's width in pixels
247     float m_analogScrollCount;
248 
249     std::unique_ptr<CGUITexture> m_guiProgressIndicatorTexture;
250 
251     std::shared_ptr<CFileItem> m_lastItem;
252     std::shared_ptr<CFileItem> m_lastChannel;
253 
254     bool m_bEnableProgrammeScrolling = true;
255     bool m_bEnableChannelScrolling = true;
256 
257     int m_scrollTime;
258 
259     int m_programmeScrollLastTime;
260     float m_programmeScrollSpeed;
261     float m_programmeScrollOffset;
262 
263     int m_channelScrollLastTime;
264     float m_channelScrollSpeed;
265     float m_channelScrollOffset;
266 
267     mutable CCriticalSection m_critSection;
268     std::unique_ptr<CGUIEPGGridContainerModel> m_gridModel;
269     std::unique_ptr<CGUIEPGGridContainerModel> m_updatedGridModel;
270 
271     int m_itemStartBlock = 0;
272   };
273 }
274