[ExecString] combine SplitParameters with identical function of CUtil
[xbmc.git] / xbmc / guilib / GUIWrappingListContainer.cpp
blob2ac2d179b145396193b259382192077fec3bde65
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/actions/Action.h"
15 #include "input/actions/ActionIDs.h"
17 CGUIWrappingListContainer::CGUIWrappingListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems, int fixedPosition)
18 : CGUIBaseContainer(parentID, controlID, posX, posY, width, height, orientation, scroller, preloadItems)
20 SetCursor(fixedPosition);
21 ControlType = GUICONTAINER_WRAPLIST;
22 m_type = VIEW_TYPE_LIST;
23 m_extraItems = 0;
26 CGUIWrappingListContainer::~CGUIWrappingListContainer(void) = default;
28 void CGUIWrappingListContainer::UpdatePageControl(int offset)
30 if (m_pageControl)
31 { // tell our pagecontrol (scrollbar or whatever) to update (offset it by our cursor position)
32 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, GetNumItems() ? CorrectOffset(offset, GetCursor()) % GetNumItems() : 0);
33 SendWindowMessage(msg);
37 bool CGUIWrappingListContainer::OnAction(const CAction &action)
39 switch (action.GetID())
41 case ACTION_PAGE_UP:
42 Scroll(-m_itemsPerPage);
43 return true;
44 case ACTION_PAGE_DOWN:
45 Scroll(m_itemsPerPage);
46 return true;
47 // smooth scrolling (for analog controls)
48 case ACTION_SCROLL_UP:
50 m_analogScrollCount += action.GetAmount() * action.GetAmount();
51 bool handled = false;
52 while (m_analogScrollCount > 0.4f)
54 handled = true;
55 m_analogScrollCount -= 0.4f;
56 Scroll(-1);
58 return handled;
60 break;
61 case ACTION_SCROLL_DOWN:
63 m_analogScrollCount += action.GetAmount() * action.GetAmount();
64 bool handled = false;
65 while (m_analogScrollCount > 0.4f)
67 handled = true;
68 m_analogScrollCount -= 0.4f;
69 Scroll(1);
71 return handled;
73 break;
75 return CGUIBaseContainer::OnAction(action);
78 bool CGUIWrappingListContainer::OnMessage(CGUIMessage& message)
80 if (message.GetControlId() == GetID() )
82 if (message.GetMessage() == GUI_MSG_PAGE_CHANGE)
84 if (message.GetSenderId() == m_pageControl && IsVisible())
85 { // offset by our cursor position
86 message.SetParam1(message.GetParam1() - GetCursor());
90 return CGUIBaseContainer::OnMessage(message);
93 bool CGUIWrappingListContainer::MoveUp(bool wrapAround)
95 Scroll(-1);
96 return true;
99 bool CGUIWrappingListContainer::MoveDown(bool wrapAround)
101 Scroll(+1);
102 return true;
105 // scrolls the said amount
106 void CGUIWrappingListContainer::Scroll(int amount)
108 ScrollToOffset(GetOffset() + amount);
111 bool CGUIWrappingListContainer::GetOffsetRange(int &minOffset, int &maxOffset) const
113 return false;
116 void CGUIWrappingListContainer::ValidateOffset()
118 // our minimal amount of items - we need to take into account extra items to display wrapped items when scrolling
119 unsigned int minItems = (unsigned int)m_itemsPerPage + ScrollCorrectionRange() + GetCacheCount() / 2;
120 if (minItems <= m_items.size())
121 return;
123 // no need to check the range here, but we need to check we have
124 // more items than slots.
125 ResetExtraItems();
126 if (m_items.size())
128 size_t numItems = m_items.size();
129 while (m_items.size() < minItems)
131 // add additional copies of items, as we require extras at render time
132 for (unsigned int i = 0; i < numItems; i++)
134 m_items.push_back(std::shared_ptr<CGUIListItem>(m_items[i]->Clone()));
135 m_extraItems++;
141 int CGUIWrappingListContainer::CorrectOffset(int offset, int cursor) const
143 if (m_items.size())
145 int correctOffset = (offset + cursor) % (int)m_items.size();
146 if (correctOffset < 0) correctOffset += m_items.size();
147 return correctOffset;
149 return 0;
152 int CGUIWrappingListContainer::GetSelectedItem() const
154 if (m_items.size() > m_extraItems)
156 int numItems = (int)(m_items.size() - m_extraItems);
157 int correctOffset = (GetOffset() + GetCursor()) % numItems;
158 if (correctOffset < 0) correctOffset += numItems;
159 return correctOffset;
161 return 0;
164 bool CGUIWrappingListContainer::SelectItemFromPoint(const CPoint &point)
166 if (!m_focusedLayout || !m_layout)
167 return false;
169 const float mouse_scroll_speed = 0.05f;
170 const float mouse_max_amount = 1.0f; // max speed: 1 item per frame
171 float sizeOfItem = m_layout->Size(m_orientation);
172 // see if the point is either side of our focused item
173 float start = GetCursor() * sizeOfItem;
174 float end = start + m_focusedLayout->Size(m_orientation);
175 float pos = (m_orientation == VERTICAL) ? point.y : point.x;
176 if (pos < start - 0.5f * sizeOfItem)
177 { // scroll backward
178 if (!InsideLayout(m_layout, point))
179 return false;
180 float amount = std::min((start - pos) / sizeOfItem, mouse_max_amount);
181 m_analogScrollCount += amount * amount * mouse_scroll_speed;
182 if (m_analogScrollCount > 1)
184 Scroll(-1);
185 m_analogScrollCount-=1.0f;
187 return true;
189 else if (pos > end + 0.5f * sizeOfItem)
190 { // scroll forward
191 if (!InsideLayout(m_layout, point))
192 return false;
194 float amount = std::min((pos - end) / sizeOfItem, mouse_max_amount);
195 m_analogScrollCount += amount * amount * mouse_scroll_speed;
196 if (m_analogScrollCount > 1)
198 Scroll(1);
199 m_analogScrollCount-=1.0f;
201 return true;
203 return InsideLayout(m_focusedLayout, point);
206 void CGUIWrappingListContainer::SelectItem(int item)
208 if (item >= 0 && item < (int)m_items.size())
209 ScrollToOffset(item - GetCursor());
212 void CGUIWrappingListContainer::ResetExtraItems()
214 // delete any extra items
215 if (m_extraItems)
216 m_items.erase(m_items.begin() + m_items.size() - m_extraItems, m_items.end());
217 m_extraItems = 0;
220 void CGUIWrappingListContainer::Reset()
222 ResetExtraItems();
223 CGUIBaseContainer::Reset();
226 int CGUIWrappingListContainer::GetCurrentPage() const
228 int offset = CorrectOffset(GetOffset(), GetCursor());
229 if (offset + m_itemsPerPage - GetCursor() >= (int)GetRows()) // last page
230 return (GetRows() + m_itemsPerPage - 1) / m_itemsPerPage;
231 return offset / m_itemsPerPage + 1;
234 void CGUIWrappingListContainer::SetPageControlRange()
236 if (m_pageControl)
238 CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), m_pageControl, m_itemsPerPage, GetNumItems());
239 SendWindowMessage(msg);