[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / guilib / GUIListContainer.cpp
blob15612a9b49f2c34f9f1d10917e46e15a90633bb2
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 "GUIListContainer.h"
11 #include "GUIListItemLayout.h"
12 #include "GUIMessage.h"
13 #include "input/actions/Action.h"
14 #include "input/actions/ActionIDs.h"
15 #include "utils/StringUtils.h"
17 CGUIListContainer::CGUIListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems)
18 : CGUIBaseContainer(parentID, controlID, posX, posY, width, height, orientation, scroller, preloadItems)
20 ControlType = GUICONTAINER_LIST;
21 m_type = VIEW_TYPE_LIST;
24 CGUIListContainer::CGUIListContainer(const CGUIListContainer& other) : CGUIBaseContainer(other)
28 CGUIListContainer::~CGUIListContainer(void) = default;
30 bool CGUIListContainer::OnAction(const CAction &action)
32 switch (action.GetID())
34 case ACTION_PAGE_UP:
36 if (GetOffset() == 0)
37 { // already on the first page, so move to the first item
38 SetCursor(0);
40 else
41 { // scroll up to the previous page
42 Scroll( -m_itemsPerPage);
44 return true;
46 break;
47 case ACTION_PAGE_DOWN:
49 if (GetOffset() == (int)m_items.size() - m_itemsPerPage || (int)m_items.size() < m_itemsPerPage)
50 { // already at the last page, so move to the last item.
51 SetCursor(m_items.size() - GetOffset() - 1);
53 else
54 { // scroll down to the next page
55 Scroll(m_itemsPerPage);
57 return true;
59 break;
60 // smooth scrolling (for analog controls)
61 case ACTION_SCROLL_UP:
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 if (GetOffset() > 0 && GetCursor() <= m_itemsPerPage / 2)
71 Scroll(-1);
73 else if (GetCursor() > 0)
75 SetCursor(GetCursor() - 1);
78 return handled;
80 break;
81 case ACTION_SCROLL_DOWN:
83 m_analogScrollCount += action.GetAmount() * action.GetAmount();
84 bool handled = false;
85 while (m_analogScrollCount > 0.4f)
87 handled = true;
88 m_analogScrollCount -= 0.4f;
89 if (GetOffset() + m_itemsPerPage < (int)m_items.size() && GetCursor() >= m_itemsPerPage / 2)
91 Scroll(1);
93 else if (GetCursor() < m_itemsPerPage - 1 && GetOffset() + GetCursor() < (int)m_items.size() - 1)
95 SetCursor(GetCursor() + 1);
98 return handled;
100 break;
102 return CGUIBaseContainer::OnAction(action);
105 bool CGUIListContainer::OnMessage(CGUIMessage& message)
107 if (message.GetControlId() == GetID() )
109 if (message.GetMessage() == GUI_MSG_LABEL_RESET)
111 SetCursor(0);
112 SetOffset(0);
113 m_scroller.SetValue(0);
116 return CGUIBaseContainer::OnMessage(message);
119 bool CGUIListContainer::MoveUp(bool wrapAround)
121 if (GetCursor() > 0)
123 SetCursor(GetCursor() - 1);
125 else if (GetCursor() == 0 && GetOffset())
127 ScrollToOffset(GetOffset() - 1);
129 else if (wrapAround)
131 if (!m_items.empty())
132 { // move 2 last item in list, and set our container moving up
133 int offset = m_items.size() - m_itemsPerPage;
134 if (offset < 0) offset = 0;
135 SetCursor(m_items.size() - offset - 1);
136 ScrollToOffset(offset);
137 SetContainerMoving(-1);
140 else
141 return false;
142 return true;
145 bool CGUIListContainer::MoveDown(bool wrapAround)
147 if (GetOffset() + GetCursor() + 1 < (int)m_items.size())
149 if (GetCursor() + 1 < m_itemsPerPage)
151 SetCursor(GetCursor() + 1);
153 else
155 ScrollToOffset(GetOffset() + 1);
158 else if(wrapAround)
159 { // move first item in list, and set our container moving in the "down" direction
160 SetCursor(0);
161 ScrollToOffset(0);
162 SetContainerMoving(1);
164 else
165 return false;
166 return true;
169 // scrolls the said amount
170 void CGUIListContainer::Scroll(int amount)
172 // increase or decrease the offset
173 int offset = GetOffset() + amount;
174 if (offset > (int)m_items.size() - m_itemsPerPage)
176 offset = m_items.size() - m_itemsPerPage;
178 if (offset < 0) offset = 0;
179 ScrollToOffset(offset);
182 void CGUIListContainer::ValidateOffset()
184 if (!m_layout) return;
185 // first thing is we check the range of our offset
186 // don't validate offset if we are scrolling in case the tween image exceed <0, 1> range
187 int minOffset, maxOffset;
188 GetOffsetRange(minOffset, maxOffset);
189 if (GetOffset() > maxOffset || (!m_scroller.IsScrolling() && m_scroller.GetValue() > maxOffset * m_layout->Size(m_orientation)))
191 SetOffset(std::max(0, maxOffset));
192 m_scroller.SetValue(GetOffset() * m_layout->Size(m_orientation));
194 if (GetOffset() < 0 || (!m_scroller.IsScrolling() && m_scroller.GetValue() < 0))
196 SetOffset(0);
197 m_scroller.SetValue(0);
201 void CGUIListContainer::SetCursor(int cursor)
203 if (cursor > m_itemsPerPage - 1) cursor = m_itemsPerPage - 1;
204 if (cursor < 0) cursor = 0;
205 if (!m_wasReset)
206 SetContainerMoving(cursor - GetCursor());
207 CGUIBaseContainer::SetCursor(cursor);
210 void CGUIListContainer::SelectItem(int item)
212 // Check that our offset is valid
213 ValidateOffset();
214 // only select an item if it's in a valid range
215 if (item >= 0 && item < (int)m_items.size())
217 // Select the item requested
218 if (item >= GetOffset() && item < GetOffset() + m_itemsPerPage)
219 { // the item is on the current page, so don't change it.
220 SetCursor(item - GetOffset());
222 else if (item < GetOffset())
223 { // item is on a previous page - make it the first item on the page
224 SetCursor(0);
225 ScrollToOffset(item);
227 else // (item >= GetOffset()+m_itemsPerPage)
228 { // item is on a later page - make it the last item on the page
229 SetCursor(m_itemsPerPage - 1);
230 ScrollToOffset(item - GetCursor());
235 int CGUIListContainer::GetCursorFromPoint(const CPoint &point, CPoint *itemPoint) const
237 if (!m_focusedLayout || !m_layout)
238 return -1;
240 int row = 0;
241 float pos = (m_orientation == VERTICAL) ? point.y : point.x;
242 while (row < m_itemsPerPage + 1) // 1 more to ensure we get the (possible) half item at the end.
244 const CGUIListItemLayout *layout = (row == GetCursor()) ? m_focusedLayout : m_layout;
245 if (pos < layout->Size(m_orientation) && row + GetOffset() < (int)m_items.size())
246 { // found correct "row" -> check horizontal
247 if (!InsideLayout(layout, point))
248 return -1;
250 if (itemPoint)
251 *itemPoint = m_orientation == VERTICAL ? CPoint(point.x, pos) : CPoint(pos, point.y);
252 return row;
254 row++;
255 pos -= layout->Size(m_orientation);
257 return -1;
260 bool CGUIListContainer::SelectItemFromPoint(const CPoint &point)
262 CPoint itemPoint;
263 int row = GetCursorFromPoint(point, &itemPoint);
264 if (row < 0)
265 return false;
267 SetCursor(row);
268 CGUIListItemLayout *focusedLayout = GetFocusedLayout();
269 if (focusedLayout)
270 focusedLayout->SelectItemFromPoint(itemPoint);
271 return true;
274 //#ifdef GUILIB_PYTHON_COMPATIBILITY
275 CGUIListContainer::CGUIListContainer(int parentID, int controlID, float posX, float posY, float width, float height,
276 const CLabelInfo& labelInfo, const CLabelInfo& labelInfo2,
277 const CTextureInfo& textureButton, const CTextureInfo& textureButtonFocus,
278 float textureHeight, float itemWidth, float itemHeight, float spaceBetweenItems)
279 : CGUIBaseContainer(parentID, controlID, posX, posY, width, height, VERTICAL, 200, 0)
281 m_layouts.emplace_back();
282 m_layouts.back().CreateListControlLayouts(width, textureHeight + spaceBetweenItems, false, labelInfo, labelInfo2, textureButton, textureButtonFocus, textureHeight, itemWidth, itemHeight, "", "");
283 std::string condition = StringUtils::Format("control.hasfocus({})", controlID);
284 std::string condition2 = "!" + condition;
285 m_focusedLayouts.emplace_back();
286 m_focusedLayouts.back().CreateListControlLayouts(width, textureHeight + spaceBetweenItems, true, labelInfo, labelInfo2, textureButton, textureButtonFocus, textureHeight, itemWidth, itemHeight, condition2, condition);
287 m_height = floor(m_height / (textureHeight + spaceBetweenItems)) * (textureHeight + spaceBetweenItems);
288 ControlType = GUICONTAINER_LIST;
290 //#endif
292 bool CGUIListContainer::HasNextPage() const
294 return (GetOffset() != (int)m_items.size() - m_itemsPerPage && (int)m_items.size() >= m_itemsPerPage);
297 bool CGUIListContainer::HasPreviousPage() const
299 return (GetOffset() > 0);