[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / guilib / GUIScrollBarControl.cpp
blob9178ce6e7512cd96266e04ccba67151af5bcad16
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 "GUIScrollBarControl.h"
11 #include "GUIMessage.h"
12 #include "input/actions/Action.h"
13 #include "input/actions/ActionIDs.h"
14 #include "input/mouse/MouseEvent.h"
15 #include "input/mouse/MouseStat.h"
16 #include "utils/StringUtils.h"
18 using namespace KODI;
20 #define MIN_NIB_SIZE 4.0f
22 GUIScrollBarControl::GUIScrollBarControl(int parentID,
23 int controlID,
24 float posX,
25 float posY,
26 float width,
27 float height,
28 const CTextureInfo& backGroundTexture,
29 const CTextureInfo& barTexture,
30 const CTextureInfo& barTextureFocus,
31 const CTextureInfo& nibTexture,
32 const CTextureInfo& nibTextureFocus,
33 ORIENTATION orientation,
34 bool showOnePage)
35 : CGUIControl(parentID, controlID, posX, posY, width, height),
36 m_guiBackground(CGUITexture::CreateTexture(posX, posY, width, height, backGroundTexture)),
37 m_guiBarNoFocus(CGUITexture::CreateTexture(posX, posY, width, height, barTexture)),
38 m_guiBarFocus(CGUITexture::CreateTexture(posX, posY, width, height, barTextureFocus)),
39 m_guiNibNoFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTexture)),
40 m_guiNibFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTextureFocus))
42 m_guiNibNoFocus->SetAspectRatio(CAspectRatio::AR_CENTER);
43 m_guiNibFocus->SetAspectRatio(CAspectRatio::AR_CENTER);
44 m_numItems = 100;
45 m_offset = 0;
46 m_pageSize = 10;
47 ControlType = GUICONTROL_SCROLLBAR;
48 m_orientation = orientation;
49 m_showOnePage = showOnePage;
52 GUIScrollBarControl::GUIScrollBarControl(const GUIScrollBarControl& control)
53 : CGUIControl(control),
54 m_guiBackground(control.m_guiBackground->Clone()),
55 m_guiBarNoFocus(control.m_guiBarNoFocus->Clone()),
56 m_guiBarFocus(control.m_guiBarFocus->Clone()),
57 m_guiNibNoFocus(control.m_guiNibNoFocus->Clone()),
58 m_guiNibFocus(control.m_guiNibFocus->Clone()),
59 m_numItems(control.m_numItems),
60 m_pageSize(control.m_pageSize),
61 m_offset(control.m_offset),
62 m_showOnePage(control.m_showOnePage),
63 m_orientation(control.m_orientation)
67 void GUIScrollBarControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
69 bool changed = false;
71 if (m_bInvalidated)
72 changed |= UpdateBarSize();
74 changed |= m_guiBackground->Process(currentTime);
75 changed |= m_guiBarNoFocus->Process(currentTime);
76 changed |= m_guiBarFocus->Process(currentTime);
77 changed |= m_guiNibNoFocus->Process(currentTime);
78 changed |= m_guiNibFocus->Process(currentTime);
80 if (changed)
81 MarkDirtyRegion();
83 CGUIControl::Process(currentTime, dirtyregions);
86 void GUIScrollBarControl::Render()
88 m_guiBackground->Render();
89 if (m_bHasFocus)
91 m_guiBarFocus->Render();
92 m_guiNibFocus->Render();
94 else
96 m_guiBarNoFocus->Render();
97 m_guiNibNoFocus->Render();
100 CGUIControl::Render();
103 bool GUIScrollBarControl::OnMessage(CGUIMessage& message)
105 switch (message.GetMessage())
107 case GUI_MSG_ITEM_SELECT:
108 SetValue(message.GetParam1());
109 return true;
110 case GUI_MSG_LABEL_RESET:
111 SetRange(message.GetParam1(), message.GetParam2());
112 return true;
113 case GUI_MSG_PAGE_UP:
114 Move(-1);
115 return true;
116 case GUI_MSG_PAGE_DOWN:
117 Move(1);
118 return true;
120 return CGUIControl::OnMessage(message);
123 bool GUIScrollBarControl::OnAction(const CAction &action)
125 switch ( action.GetID() )
127 case ACTION_MOVE_LEFT:
128 if (m_orientation == HORIZONTAL)
130 if(Move( -1))
131 return true;
133 break;
135 case ACTION_MOVE_RIGHT:
136 if (m_orientation == HORIZONTAL)
138 if(Move(1))
139 return true;
141 break;
142 case ACTION_MOVE_UP:
143 if (m_orientation == VERTICAL)
145 if(Move(-1))
146 return true;
148 break;
150 case ACTION_MOVE_DOWN:
151 if (m_orientation == VERTICAL)
153 if(Move(1))
154 return true;
156 break;
158 return CGUIControl::OnAction(action);
161 bool GUIScrollBarControl::Move(int numSteps)
163 if (numSteps < 0 && m_offset == 0) // we are at the beginning - can't scroll up/left anymore
164 return false;
165 if (numSteps > 0 && m_offset == std::max(m_numItems - m_pageSize, 0)) // we are at the end - we can't scroll down/right anymore
166 return false;
168 m_offset += numSteps * m_pageSize;
169 if (m_offset > m_numItems - m_pageSize) m_offset = m_numItems - m_pageSize;
170 if (m_offset < 0) m_offset = 0;
171 CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetParentID(), GetID(), GUI_MSG_PAGE_CHANGE, m_offset);
172 SendWindowMessage(message);
173 SetInvalid();
174 return true;
177 void GUIScrollBarControl::SetRange(int pageSize, int numItems)
179 if (m_pageSize != pageSize || m_numItems != numItems)
181 m_pageSize = pageSize;
182 m_numItems = numItems;
183 m_offset = 0;
184 SetInvalid();
188 void GUIScrollBarControl::SetValue(int value)
190 if (m_offset != value)
192 m_offset = value;
193 SetInvalid();
197 void GUIScrollBarControl::FreeResources(bool immediately)
199 CGUIControl::FreeResources(immediately);
200 m_guiBackground->FreeResources(immediately);
201 m_guiBarNoFocus->FreeResources(immediately);
202 m_guiBarFocus->FreeResources(immediately);
203 m_guiNibNoFocus->FreeResources(immediately);
204 m_guiNibFocus->FreeResources(immediately);
207 void GUIScrollBarControl::DynamicResourceAlloc(bool bOnOff)
209 CGUIControl::DynamicResourceAlloc(bOnOff);
210 m_guiBackground->DynamicResourceAlloc(bOnOff);
211 m_guiBarNoFocus->DynamicResourceAlloc(bOnOff);
212 m_guiBarFocus->DynamicResourceAlloc(bOnOff);
213 m_guiNibNoFocus->DynamicResourceAlloc(bOnOff);
214 m_guiNibFocus->DynamicResourceAlloc(bOnOff);
217 void GUIScrollBarControl::AllocResources()
219 CGUIControl::AllocResources();
220 m_guiBackground->AllocResources();
221 m_guiBarNoFocus->AllocResources();
222 m_guiBarFocus->AllocResources();
223 m_guiNibNoFocus->AllocResources();
224 m_guiNibFocus->AllocResources();
227 void GUIScrollBarControl::SetInvalid()
229 CGUIControl::SetInvalid();
230 m_guiBackground->SetInvalid();
231 m_guiBarFocus->SetInvalid();
232 m_guiBarFocus->SetInvalid();
233 m_guiNibNoFocus->SetInvalid();
234 m_guiNibFocus->SetInvalid();
237 bool GUIScrollBarControl::UpdateBarSize()
239 bool changed = false;
241 // scale our textures to suit
242 if (m_orientation == VERTICAL)
244 // calculate the height to display the nib at
245 float percent = (m_numItems == 0) ? 0 : (float)m_pageSize / m_numItems;
246 float nibSize = GetHeight() * percent;
247 if (nibSize < m_guiNibFocus->GetTextureHeight() + 2 * MIN_NIB_SIZE)
248 nibSize = m_guiNibFocus->GetTextureHeight() + 2 * MIN_NIB_SIZE;
249 if (nibSize > GetHeight()) nibSize = GetHeight();
251 changed |= m_guiBarNoFocus->SetHeight(nibSize);
252 changed |= m_guiBarFocus->SetHeight(nibSize);
253 changed |= m_guiNibNoFocus->SetHeight(nibSize);
254 changed |= m_guiNibFocus->SetHeight(nibSize);
255 // nibSize may be altered by the border size of the nib (and bar).
256 nibSize = std::max(m_guiBarFocus->GetHeight(), m_guiNibFocus->GetHeight());
258 // and the position
259 percent = (m_numItems == m_pageSize) ? 0 : (float)m_offset / (m_numItems - m_pageSize);
260 float nibPos = (GetHeight() - nibSize) * percent;
261 if (nibPos < 0) nibPos = 0;
262 if (nibPos > GetHeight() - nibSize) nibPos = GetHeight() - nibSize;
264 changed |= m_guiBarNoFocus->SetPosition(GetXPosition(), GetYPosition() + nibPos);
265 changed |= m_guiBarFocus->SetPosition(GetXPosition(), GetYPosition() + nibPos);
266 changed |= m_guiNibNoFocus->SetPosition(GetXPosition(), GetYPosition() + nibPos);
267 changed |= m_guiNibFocus->SetPosition(GetXPosition(), GetYPosition() + nibPos);
269 else
271 // calculate the height to display the nib at
272 float percent = (m_numItems == 0) ? 0 : (float)m_pageSize / m_numItems;
273 float nibSize = GetWidth() * percent + 0.5f;
274 if (nibSize < m_guiNibFocus->GetTextureWidth() + 2 * MIN_NIB_SIZE)
275 nibSize = m_guiNibFocus->GetTextureWidth() + 2 * MIN_NIB_SIZE;
276 if (nibSize > GetWidth()) nibSize = GetWidth();
278 changed |= m_guiBarNoFocus->SetWidth(nibSize);
279 changed |= m_guiBarFocus->SetWidth(nibSize);
280 changed |= m_guiNibNoFocus->SetWidth(nibSize);
281 changed |= m_guiNibFocus->SetWidth(nibSize);
283 // and the position
284 percent = (m_numItems == m_pageSize) ? 0 : (float)m_offset / (m_numItems - m_pageSize);
285 float nibPos = (GetWidth() - nibSize) * percent;
286 if (nibPos < 0) nibPos = 0;
287 if (nibPos > GetWidth() - nibSize) nibPos = GetWidth() - nibSize;
289 changed |= m_guiBarNoFocus->SetPosition(GetXPosition() + nibPos, GetYPosition());
290 changed |= m_guiBarFocus->SetPosition(GetXPosition() + nibPos, GetYPosition());
291 changed |= m_guiNibNoFocus->SetPosition(GetXPosition() + nibPos, GetYPosition());
292 changed |= m_guiNibFocus->SetPosition(GetXPosition() + nibPos, GetYPosition());
295 return changed;
298 void GUIScrollBarControl::SetFromPosition(const CPoint &point)
300 float fPercent;
301 if (m_orientation == VERTICAL)
302 fPercent = (point.y - m_guiBackground->GetYPosition() - 0.5f * m_guiBarFocus->GetHeight()) /
303 (m_guiBackground->GetHeight() - m_guiBarFocus->GetHeight());
304 else
305 fPercent = (point.x - m_guiBackground->GetXPosition() - 0.5f * m_guiBarFocus->GetWidth()) /
306 (m_guiBackground->GetWidth() - m_guiBarFocus->GetWidth());
307 if (fPercent < 0) fPercent = 0;
308 if (fPercent > 1) fPercent = 1;
310 int offset = (int)(floor(fPercent * (m_numItems - m_pageSize) + 0.5f));
312 if (m_offset != offset)
314 m_offset = offset;
315 CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetParentID(), GetID(), GUI_MSG_PAGE_CHANGE, m_offset);
316 SendWindowMessage(message);
317 SetInvalid();
321 EVENT_RESULT GUIScrollBarControl::OnMouseEvent(const CPoint& point, const MOUSE::CMouseEvent& event)
323 if (event.m_id == ACTION_MOUSE_DRAG || event.m_id == ACTION_MOUSE_DRAG_END)
325 if (static_cast<HoldAction>(event.m_state) == HoldAction::DRAG)
326 { // we want exclusive access
327 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
328 SendWindowMessage(msg);
330 else if (static_cast<HoldAction>(event.m_state) == HoldAction::DRAG_END)
331 { // we're done with exclusive access
332 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
333 SendWindowMessage(msg);
335 SetFromPosition(point);
336 return EVENT_RESULT_HANDLED;
338 else if (event.m_id == ACTION_MOUSE_LEFT_CLICK && m_guiBackground->HitTest(point))
340 SetFromPosition(point);
341 return EVENT_RESULT_HANDLED;
343 else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
345 Move(-1);
346 return EVENT_RESULT_HANDLED;
348 else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
350 Move(1);
351 return EVENT_RESULT_HANDLED;
353 else if (event.m_id == ACTION_GESTURE_NOTIFY)
355 return (m_orientation == HORIZONTAL) ? EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA : EVENT_RESULT_PAN_VERTICAL_WITHOUT_INERTIA;
357 else if (event.m_id == ACTION_GESTURE_BEGIN)
358 { // grab exclusive access
359 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
360 SendWindowMessage(msg);
361 return EVENT_RESULT_HANDLED;
363 else if (event.m_id == ACTION_GESTURE_PAN)
364 { // do the drag
365 SetFromPosition(point);
366 return EVENT_RESULT_HANDLED;
368 else if (event.m_id == ACTION_GESTURE_END || event.m_id == ACTION_GESTURE_ABORT)
369 { // release exclusive access
370 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
371 SendWindowMessage(msg);
372 return EVENT_RESULT_HANDLED;
375 return EVENT_RESULT_UNHANDLED;
378 std::string GUIScrollBarControl::GetDescription() const
380 return StringUtils::Format("{}/{}", m_offset, m_numItems);
383 bool GUIScrollBarControl::UpdateColors(const CGUIListItem* item)
385 bool changed = CGUIControl::UpdateColors(nullptr);
386 changed |= m_guiBackground->SetDiffuseColor(m_diffuseColor);
387 changed |= m_guiBarNoFocus->SetDiffuseColor(m_diffuseColor);
388 changed |= m_guiBarFocus->SetDiffuseColor(m_diffuseColor);
389 changed |= m_guiNibNoFocus->SetDiffuseColor(m_diffuseColor);
390 changed |= m_guiNibFocus->SetDiffuseColor(m_diffuseColor);
392 return changed;
395 bool GUIScrollBarControl::IsVisible() const
397 // page controls can be optionally disabled if the number of pages is 1
398 if (m_numItems <= m_pageSize && !m_showOnePage)
399 return false;
400 return CGUIControl::IsVisible();