Merge pull request #22816 from CastagnaIT/fix_tx3g
[xbmc.git] / xbmc / guilib / GUIWrappingListContainer.cpp
blobe1bc3c0fb8e804df756cf7ca072317c17a967dd2
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUIWrappingListContainer.h"
11 #include "FileItem.h"
12 #include "GUIListItemLayout.h"
13 #include "GUIMessage.h"
14 #include "input/Key.h"
16 CGUIWrappingListContainer::CGUIWrappingListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems, int fixedPosition)
17 : CGUIBaseContainer(parentID, controlID, posX, posY, width, height, orientation, scroller, preloadItems)
19 SetCursor(fixedPosition);
20 ControlType = GUICONTAINER_WRAPLIST;
21 m_type = VIEW_TYPE_LIST;
22 m_extraItems = 0;
25 CGUIWrappingListContainer::~CGUIWrappingListContainer(void) = default;
27 void CGUIWrappingListContainer::UpdatePageControl(int offset)
29 if (m_pageControl)
30 { // tell our pagecontrol (scrollbar or whatever) to update (offset it by our cursor position)
31 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, GetNumItems() ? CorrectOffset(offset, GetCursor()) % GetNumItems() : 0);
32 SendWindowMessage(msg);
36 bool CGUIWrappingListContainer::OnAction(const CAction &action)
38 switch (action.GetID())
40 case ACTION_PAGE_UP:
41 Scroll(-m_itemsPerPage);
42 return true;
43 case ACTION_PAGE_DOWN:
44 Scroll(m_itemsPerPage);
45 return true;
46 // smooth scrolling (for analog controls)
47 case ACTION_SCROLL_UP:
49 m_analogScrollCount += action.GetAmount() * action.GetAmount();
50 bool handled = false;
51 while (m_analogScrollCount > 0.4f)
53 handled = true;
54 m_analogScrollCount -= 0.4f;
55 Scroll(-1);
57 return handled;
59 break;
60 case ACTION_SCROLL_DOWN:
62 m_analogScrollCount += action.GetAmount() * action.GetAmount();
63 bool handled = false;
64 while (m_analogScrollCount > 0.4f)
66 handled = true;
67 m_analogScrollCount -= 0.4f;
68 Scroll(1);
70 return handled;
72 break;
74 return CGUIBaseContainer::OnAction(action);
77 bool CGUIWrappingListContainer::OnMessage(CGUIMessage& message)
79 if (message.GetControlId() == GetID() )
81 if (message.GetMessage() == GUI_MSG_PAGE_CHANGE)
83 if (message.GetSenderId() == m_pageControl && IsVisible())
84 { // offset by our cursor position
85 message.SetParam1(message.GetParam1() - GetCursor());
89 return CGUIBaseContainer::OnMessage(message);
92 bool CGUIWrappingListContainer::MoveUp(bool wrapAround)
94 Scroll(-1);
95 return true;
98 bool CGUIWrappingListContainer::MoveDown(bool wrapAround)
100 Scroll(+1);
101 return true;
104 // scrolls the said amount
105 void CGUIWrappingListContainer::Scroll(int amount)
107 ScrollToOffset(GetOffset() + amount);
110 bool CGUIWrappingListContainer::GetOffsetRange(int &minOffset, int &maxOffset) const
112 return false;
115 void CGUIWrappingListContainer::ValidateOffset()
117 // our minimal amount of items - we need to take into account extra items to display wrapped items when scrolling
118 unsigned int minItems = (unsigned int)m_itemsPerPage + ScrollCorrectionRange() + GetCacheCount() / 2;
119 if (minItems <= m_items.size())
120 return;
122 // no need to check the range here, but we need to check we have
123 // more items than slots.
124 ResetExtraItems();
125 if (m_items.size())
127 size_t numItems = m_items.size();
128 while (m_items.size() < minItems)
130 // add additional copies of items, as we require extras at render time
131 for (unsigned int i = 0; i < numItems; i++)
133 m_items.push_back(CGUIListItemPtr(m_items[i]->Clone()));
134 m_extraItems++;
140 int CGUIWrappingListContainer::CorrectOffset(int offset, int cursor) const
142 if (m_items.size())
144 int correctOffset = (offset + cursor) % (int)m_items.size();
145 if (correctOffset < 0) correctOffset += m_items.size();
146 return correctOffset;
148 return 0;
151 int CGUIWrappingListContainer::GetSelectedItem() const
153 if (m_items.size() > m_extraItems)
155 int numItems = (int)(m_items.size() - m_extraItems);
156 int correctOffset = (GetOffset() + GetCursor()) % numItems;
157 if (correctOffset < 0) correctOffset += numItems;
158 return correctOffset;
160 return 0;
163 bool CGUIWrappingListContainer::SelectItemFromPoint(const CPoint &point)
165 if (!m_focusedLayout || !m_layout)
166 return false;
168 const float mouse_scroll_speed = 0.05f;
169 const float mouse_max_amount = 1.0f; // max speed: 1 item per frame
170 float sizeOfItem = m_layout->Size(m_orientation);
171 // see if the point is either side of our focused item
172 float start = GetCursor() * sizeOfItem;
173 float end = start + m_focusedLayout->Size(m_orientation);
174 float pos = (m_orientation == VERTICAL) ? point.y : point.x;
175 if (pos < start - 0.5f * sizeOfItem)
176 { // scroll backward
177 if (!InsideLayout(m_layout, point))
178 return false;
179 float amount = std::min((start - pos) / sizeOfItem, mouse_max_amount);
180 m_analogScrollCount += amount * amount * mouse_scroll_speed;
181 if (m_analogScrollCount > 1)
183 Scroll(-1);
184 m_analogScrollCount-=1.0f;
186 return true;
188 else if (pos > end + 0.5f * sizeOfItem)
189 { // scroll forward
190 if (!InsideLayout(m_layout, point))
191 return false;
193 float amount = std::min((pos - end) / sizeOfItem, mouse_max_amount);
194 m_analogScrollCount += amount * amount * mouse_scroll_speed;
195 if (m_analogScrollCount > 1)
197 Scroll(1);
198 m_analogScrollCount-=1.0f;
200 return true;
202 return InsideLayout(m_focusedLayout, point);
205 void CGUIWrappingListContainer::SelectItem(int item)
207 if (item >= 0 && item < (int)m_items.size())
208 ScrollToOffset(item - GetCursor());
211 void CGUIWrappingListContainer::ResetExtraItems()
213 // delete any extra items
214 if (m_extraItems)
215 m_items.erase(m_items.begin() + m_items.size() - m_extraItems, m_items.end());
216 m_extraItems = 0;
219 void CGUIWrappingListContainer::Reset()
221 ResetExtraItems();
222 CGUIBaseContainer::Reset();
225 int CGUIWrappingListContainer::GetCurrentPage() const
227 int offset = CorrectOffset(GetOffset(), GetCursor());
228 if (offset + m_itemsPerPage - GetCursor() >= (int)GetRows()) // last page
229 return (GetRows() + m_itemsPerPage - 1) / m_itemsPerPage;
230 return offset / m_itemsPerPage + 1;
233 void CGUIWrappingListContainer::SetPageControlRange()
235 if (m_pageControl)
237 CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), m_pageControl, m_itemsPerPage, GetNumItems());
238 SendWindowMessage(msg);