2 * Copyright (C) 2019 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.
9 #include "GUIRangesControl.h"
11 #include "GUIInfoManager.h"
12 #include "ServiceBroker.h"
13 #include "utils/StringUtils.h"
14 #include "utils/log.h"
18 CGUIRangesControl::CGUIRange::CGUIRange(float fPosX
,
22 const CTextureInfo
& lowerTextureInfo
,
23 const CTextureInfo
& fillTextureInfo
,
24 const CTextureInfo
& upperTextureInfo
,
25 const std::pair
<float, float>& percentages
)
26 : m_guiLowerTexture(CGUITexture::CreateTexture(fPosX
, fPosY
, fWidth
, fHeight
, lowerTextureInfo
)),
27 m_guiFillTexture(CGUITexture::CreateTexture(fPosX
, fPosY
, fWidth
, fHeight
, fillTextureInfo
)),
28 m_guiUpperTexture(CGUITexture::CreateTexture(fPosX
, fPosY
, fWidth
, fHeight
, upperTextureInfo
)),
29 m_percentValues(percentages
)
33 CGUIRangesControl::CGUIRange::CGUIRange(const CGUIRange
& range
)
34 : m_guiLowerTexture(range
.m_guiLowerTexture
->Clone()),
35 m_guiFillTexture(range
.m_guiFillTexture
->Clone()),
36 m_guiUpperTexture(range
.m_guiUpperTexture
->Clone()),
37 m_percentValues(range
.m_percentValues
)
41 void CGUIRangesControl::CGUIRange::AllocResources()
43 m_guiFillTexture
->AllocResources();
44 m_guiUpperTexture
->AllocResources();
45 m_guiLowerTexture
->AllocResources();
47 m_guiFillTexture
->SetHeight(20);
48 m_guiUpperTexture
->SetHeight(20);
49 m_guiLowerTexture
->SetHeight(20);
52 void CGUIRangesControl::CGUIRange::FreeResources(bool bImmediately
)
54 m_guiFillTexture
->FreeResources(bImmediately
);
55 m_guiUpperTexture
->FreeResources(bImmediately
);
56 m_guiLowerTexture
->FreeResources(bImmediately
);
59 void CGUIRangesControl::CGUIRange::DynamicResourceAlloc(bool bOnOff
)
61 m_guiFillTexture
->DynamicResourceAlloc(bOnOff
);
62 m_guiUpperTexture
->DynamicResourceAlloc(bOnOff
);
63 m_guiLowerTexture
->DynamicResourceAlloc(bOnOff
);
66 void CGUIRangesControl::CGUIRange::SetInvalid()
68 m_guiFillTexture
->SetInvalid();
69 m_guiUpperTexture
->SetInvalid();
70 m_guiLowerTexture
->SetInvalid();
73 bool CGUIRangesControl::CGUIRange::SetDiffuseColor(const KODI::GUILIB::GUIINFO::CGUIInfoColor
& color
)
75 bool bChanged
= false;
76 bChanged
|= m_guiFillTexture
->SetDiffuseColor(color
);
77 bChanged
|= m_guiUpperTexture
->SetDiffuseColor(color
);
78 bChanged
|= m_guiLowerTexture
->SetDiffuseColor(color
);
82 bool CGUIRangesControl::CGUIRange::Process(unsigned int currentTime
)
84 bool bChanged
= false;
85 bChanged
|= m_guiFillTexture
->Process(currentTime
);
86 bChanged
|= m_guiUpperTexture
->Process(currentTime
);
87 bChanged
|= m_guiLowerTexture
->Process(currentTime
);
91 void CGUIRangesControl::CGUIRange::Render()
93 if (m_guiLowerTexture
->GetFileName().empty() && m_guiUpperTexture
->GetFileName().empty())
95 if (m_guiFillTexture
->GetWidth() > 0)
96 m_guiFillTexture
->Render();
100 m_guiLowerTexture
->Render();
102 if (m_guiFillTexture
->GetWidth() > 0)
103 m_guiFillTexture
->Render();
105 m_guiUpperTexture
->Render();
109 bool CGUIRangesControl::CGUIRange::UpdateLayout(float fBackgroundTextureHeight
,
110 float fPosX
, float fPosY
, float fWidth
,
111 float fScaleX
, float fScaleY
)
113 bool bChanged
= false;
115 if (m_guiLowerTexture
->GetFileName().empty() && m_guiUpperTexture
->GetFileName().empty())
117 // rendering without left and right image - fill the mid image completely
118 float width
= (m_percentValues
.second
- m_percentValues
.first
) * fWidth
* 0.01f
;
119 float offsetX
= m_percentValues
.first
* fWidth
* 0.01f
;
120 float offsetY
= std::fabs(fScaleY
* 0.5f
*
121 (m_guiFillTexture
->GetTextureHeight() - fBackgroundTextureHeight
));
122 bChanged
|= m_guiFillTexture
->SetPosition(fPosX
+ (offsetX
> 0 ? offsetX
: 0),
123 fPosY
+ (offsetY
> 0 ? offsetY
: 0));
124 bChanged
|= m_guiFillTexture
->SetHeight(fScaleY
* m_guiFillTexture
->GetTextureHeight());
125 bChanged
|= m_guiFillTexture
->SetWidth(width
);
130 m_percentValues
.first
* fWidth
* 0.01f
- m_guiLowerTexture
->GetTextureWidth() * 0.5f
;
131 float offsetY
= std::fabs(fScaleY
* 0.5f
*
132 (m_guiLowerTexture
->GetTextureHeight() - fBackgroundTextureHeight
));
133 bChanged
|= m_guiLowerTexture
->SetPosition(fPosX
+ (offsetX
> 0 ? offsetX
: 0),
134 fPosY
+ (offsetY
> 0 ? offsetY
: 0));
135 bChanged
|= m_guiLowerTexture
->SetHeight(fScaleY
* m_guiLowerTexture
->GetTextureHeight());
136 bChanged
|= m_guiLowerTexture
->SetWidth(m_percentValues
.first
== 0.0f
137 ? m_guiLowerTexture
->GetTextureWidth() * 0.5f
138 : m_guiLowerTexture
->GetTextureWidth());
140 if (m_percentValues
.first
!= m_percentValues
.second
)
142 float width
= (m_percentValues
.second
- m_percentValues
.first
) * fWidth
* 0.01f
-
143 m_guiLowerTexture
->GetTextureWidth() * 0.5f
-
144 m_guiUpperTexture
->GetTextureWidth() * 0.5f
;
146 offsetX
+= m_guiLowerTexture
->GetTextureWidth();
147 offsetY
= std::fabs(fScaleY
* 0.5f
*
148 (m_guiFillTexture
->GetTextureHeight() - fBackgroundTextureHeight
));
150 m_guiFillTexture
->SetPosition(fPosX
+ offsetX
, fPosY
+ (offsetY
> 0 ? offsetY
: 0));
151 bChanged
|= m_guiFillTexture
->SetHeight(fScaleY
* m_guiFillTexture
->GetTextureHeight());
152 bChanged
|= m_guiFillTexture
->SetWidth(width
);
155 offsetY
= std::fabs(fScaleY
* 0.5f
*
156 (m_guiUpperTexture
->GetTextureHeight() - fBackgroundTextureHeight
));
158 m_guiUpperTexture
->SetPosition(fPosX
+ offsetX
, fPosY
+ (offsetY
> 0 ? offsetY
: 0));
159 bChanged
|= m_guiUpperTexture
->SetHeight(fScaleY
* m_guiUpperTexture
->GetTextureHeight());
160 bChanged
|= m_guiUpperTexture
->SetWidth(m_percentValues
.first
== 100.0f
161 ? m_guiUpperTexture
->GetTextureWidth() * 0.5f
162 : m_guiUpperTexture
->GetTextureWidth());
166 // render only lower texture if range is zero
167 bChanged
|= m_guiFillTexture
->SetVisible(false);
168 bChanged
|= m_guiUpperTexture
->SetVisible(false);
174 CGUIRangesControl::CGUIRangesControl(int iParentID
,
180 const CTextureInfo
& backGroundTextureInfo
,
181 const CTextureInfo
& lowerTextureInfo
,
182 const CTextureInfo
& fillTextureInfo
,
183 const CTextureInfo
& upperTextureInfo
,
184 const CTextureInfo
& overlayTextureInfo
,
186 : CGUIControl(iParentID
, iControlID
, fPosX
, fPosY
, fWidth
, fHeight
),
188 CGUITexture::CreateTexture(fPosX
, fPosY
, fWidth
, fHeight
, backGroundTextureInfo
)),
189 m_guiOverlay(CGUITexture::CreateTexture(fPosX
, fPosY
, fWidth
, fHeight
, overlayTextureInfo
)),
190 m_guiLowerTextureInfo(lowerTextureInfo
),
191 m_guiFillTextureInfo(fillTextureInfo
),
192 m_guiUpperTextureInfo(upperTextureInfo
),
195 ControlType
= GUICONTROL_RANGES
;
198 CGUIRangesControl::CGUIRangesControl(const CGUIRangesControl
& control
)
199 : CGUIControl(control
),
200 m_guiBackground(control
.m_guiBackground
->Clone()),
201 m_guiOverlay(control
.m_guiOverlay
->Clone()),
202 m_guiLowerTextureInfo(control
.m_guiLowerTextureInfo
),
203 m_guiFillTextureInfo(control
.m_guiFillTextureInfo
),
204 m_guiUpperTextureInfo(control
.m_guiUpperTextureInfo
),
205 m_ranges(control
.m_ranges
),
206 m_iInfoCode(control
.m_iInfoCode
),
207 m_prevRanges(control
.m_prevRanges
)
211 void CGUIRangesControl::SetPosition(float fPosX
, float fPosY
)
213 // everything is positioned based on the background image position
214 CGUIControl::SetPosition(fPosX
, fPosY
);
215 m_guiBackground
->SetPosition(fPosX
, fPosY
);
218 void CGUIRangesControl::Process(unsigned int iCurrentTime
, CDirtyRegionList
& dirtyregions
)
220 bool bChanged
= false;
223 bChanged
|= UpdateLayout();
225 bChanged
|= m_guiBackground
->Process(iCurrentTime
);
226 bChanged
|= m_guiOverlay
->Process(iCurrentTime
);
228 for (auto& range
: m_ranges
)
229 bChanged
|= range
.Process(iCurrentTime
);
234 CGUIControl::Process(iCurrentTime
, dirtyregions
);
237 void CGUIRangesControl::Render()
241 m_guiBackground
->Render();
243 for (auto& range
: m_ranges
)
246 m_guiOverlay
->Render();
249 CGUIControl::Render();
253 bool CGUIRangesControl::CanFocus() const
259 void CGUIRangesControl::SetRanges(const std::vector
<std::pair
<float, float>>& ranges
)
262 for (const auto& range
: ranges
)
263 m_ranges
.emplace_back(m_posX
, m_posY
, m_width
, m_height
, m_guiLowerTextureInfo
,
264 m_guiFillTextureInfo
, m_guiUpperTextureInfo
, range
);
266 for (auto& range
: m_ranges
)
267 range
.AllocResources(); // note: we need to alloc the instance actually inserted into the vector; hence the second loop.
270 void CGUIRangesControl::ClearRanges()
272 for (auto& range
: m_ranges
)
273 range
.FreeResources(true);
276 m_prevRanges
.clear();
279 void CGUIRangesControl::FreeResources(bool bImmediately
/* = false */)
281 CGUIControl::FreeResources(bImmediately
);
283 m_guiBackground
->FreeResources(bImmediately
);
284 m_guiOverlay
->FreeResources(bImmediately
);
286 for (auto& range
: m_ranges
)
287 range
.FreeResources(bImmediately
);
290 void CGUIRangesControl::DynamicResourceAlloc(bool bOnOff
)
292 CGUIControl::DynamicResourceAlloc(bOnOff
);
294 m_guiBackground
->DynamicResourceAlloc(bOnOff
);
295 m_guiOverlay
->DynamicResourceAlloc(bOnOff
);
297 for (auto& range
: m_ranges
)
298 range
.DynamicResourceAlloc(bOnOff
);
301 void CGUIRangesControl::AllocResources()
303 CGUIControl::AllocResources();
305 m_guiBackground
->AllocResources();
306 m_guiOverlay
->AllocResources();
308 m_guiBackground
->SetHeight(25);
309 m_guiOverlay
->SetHeight(20);
311 for (auto& range
: m_ranges
)
312 range
.AllocResources();
315 void CGUIRangesControl::SetInvalid()
317 CGUIControl::SetInvalid();
319 m_guiBackground
->SetInvalid();
320 m_guiOverlay
->SetInvalid();
322 for (auto& range
: m_ranges
)
326 bool CGUIRangesControl::UpdateColors(const CGUIListItem
* item
)
328 bool bChanged
= CGUIControl::UpdateColors(nullptr);
330 bChanged
|= m_guiBackground
->SetDiffuseColor(m_diffuseColor
);
331 bChanged
|= m_guiOverlay
->SetDiffuseColor(m_diffuseColor
);
333 for (auto& range
: m_ranges
)
334 bChanged
|= range
.SetDiffuseColor(m_diffuseColor
);
339 bool CGUIRangesControl::UpdateLayout()
341 bool bChanged
= false;
344 m_width
= m_guiBackground
->GetTextureWidth();
347 m_height
= m_guiBackground
->GetTextureHeight();
349 bChanged
|= m_guiBackground
->SetHeight(m_height
);
350 bChanged
|= m_guiBackground
->SetWidth(m_width
);
353 m_guiBackground
->GetTextureWidth() ? m_width
/ m_guiBackground
->GetTextureWidth() : 1.0f
;
355 m_guiBackground
->GetTextureHeight() ? m_height
/ m_guiBackground
->GetTextureHeight() : 1.0f
;
357 float posX
= m_guiBackground
->GetXPosition();
358 float posY
= m_guiBackground
->GetYPosition();
360 for (auto& range
: m_ranges
)
361 bChanged
|= range
.UpdateLayout(m_guiBackground
->GetTextureHeight(), posX
, posY
, m_width
,
364 float offset
= std::fabs(
365 fScaleY
* 0.5f
* (m_guiOverlay
->GetTextureHeight() - m_guiBackground
->GetTextureHeight()));
366 if (offset
> 0) // Center texture to the background if necessary
367 bChanged
|= m_guiOverlay
->SetPosition(m_guiBackground
->GetXPosition(),
368 m_guiBackground
->GetYPosition() + offset
);
371 m_guiOverlay
->SetPosition(m_guiBackground
->GetXPosition(), m_guiBackground
->GetYPosition());
373 bChanged
|= m_guiOverlay
->SetHeight(fScaleY
* m_guiOverlay
->GetTextureHeight());
374 bChanged
|= m_guiOverlay
->SetWidth(fScaleX
* m_guiOverlay
->GetTextureWidth());
379 void CGUIRangesControl::UpdateInfo(const CGUIListItem
* item
/* = nullptr */)
381 if (!IsDisabled() && m_iInfoCode
)
383 const std::string value
= CServiceBroker::GetGUI()->GetInfoManager().GetLabel(m_iInfoCode
, m_parentID
);
384 if (value
!= m_prevRanges
)
386 std::vector
<std::pair
<float, float>> ranges
;
388 // Parse csv string into ranges...
389 const std::vector
<std::string
> values
= StringUtils::Split(value
, ',');
391 // we must have an even number of values
392 if (values
.size() % 2 == 0)
394 for (auto it
= values
.begin(); it
!= values
.end();)
396 float first
= std::stof(*it
, nullptr);
398 float second
= std::stof(*it
, nullptr);
402 ranges
.emplace_back(first
, second
);
404 CLog::Log(LOGERROR
, "CGUIRangesControl::UpdateInfo - malformed ranges csv string (end element must be larger or equal than start element)");
408 CLog::Log(LOGERROR
, "CGUIRangesControl::UpdateInfo - malformed ranges csv string (string must contain even number of elements)");
411 m_prevRanges
= value
;