[ExecString] combine SplitParameters with identical function of CUtil
[xbmc.git] / xbmc / guilib / GUIControlFactory.cpp
blob001537fb728e4caaa600ab9e4edd6b080d3332c9
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 "GUIControlFactory.h"
11 #include "GUIAction.h"
12 #include "GUIBorderedImage.h"
13 #include "GUIButtonControl.h"
14 #include "GUIColorButtonControl.h"
15 #include "GUIColorManager.h"
16 #include "GUIControlGroup.h"
17 #include "GUIControlGroupList.h"
18 #include "GUIEditControl.h"
19 #include "GUIFadeLabelControl.h"
20 #include "GUIFixedListContainer.h"
21 #include "GUIFontManager.h"
22 #include "GUIImage.h"
23 #include "GUIInfoManager.h"
24 #include "GUILabelControl.h"
25 #include "GUIListContainer.h"
26 #include "GUIListGroup.h"
27 #include "GUIListLabel.h"
28 #include "GUIMoverControl.h"
29 #include "GUIMultiImage.h"
30 #include "GUIPanelContainer.h"
31 #include "GUIProgressControl.h"
32 #include "GUIRSSControl.h"
33 #include "GUIRadioButtonControl.h"
34 #include "GUIRangesControl.h"
35 #include "GUIRenderingControl.h"
36 #include "GUIResizeControl.h"
37 #include "GUIScrollBarControl.h"
38 #include "GUISettingsSliderControl.h"
39 #include "GUISliderControl.h"
40 #include "GUISpinControl.h"
41 #include "GUISpinControlEx.h"
42 #include "GUITextBox.h"
43 #include "GUIToggleButtonControl.h"
44 #include "GUIVideoControl.h"
45 #include "GUIVisualisationControl.h"
46 #include "GUIWrappingListContainer.h"
47 #include "LocalizeStrings.h"
48 #include "addons/Skin.h"
49 #include "cores/RetroPlayer/guicontrols/GUIGameControl.h"
50 #include "games/controllers/guicontrols/GUIGameController.h"
51 #include "games/controllers/guicontrols/GUIGameControllerList.h"
52 #include "input/actions/ActionIDs.h"
53 #include "pvr/guilib/GUIEPGGridContainer.h"
54 #include "utils/CharsetConverter.h"
55 #include "utils/RssManager.h"
56 #include "utils/StringUtils.h"
57 #include "utils/XMLUtils.h"
58 #include "utils/log.h"
60 using namespace KODI;
61 using namespace KODI::GUILIB;
62 using namespace PVR;
64 typedef struct
66 const char* name;
67 CGUIControl::GUICONTROLTYPES type;
68 } ControlMapping;
70 static const ControlMapping controls[] = {
71 {"button", CGUIControl::GUICONTROL_BUTTON},
72 {"colorbutton", CGUIControl::GUICONTROL_COLORBUTTON},
73 {"edit", CGUIControl::GUICONTROL_EDIT},
74 {"epggrid", CGUIControl::GUICONTAINER_EPGGRID},
75 {"fadelabel", CGUIControl::GUICONTROL_FADELABEL},
76 {"fixedlist", CGUIControl::GUICONTAINER_FIXEDLIST},
77 {"gamecontroller", CGUIControl::GUICONTROL_GAMECONTROLLER},
78 {"gamecontrollerlist", CGUIControl::GUICONTROL_GAMECONTROLLERLIST},
79 {"gamewindow", CGUIControl::GUICONTROL_GAME},
80 {"group", CGUIControl::GUICONTROL_GROUP},
81 {"group", CGUIControl::GUICONTROL_LISTGROUP},
82 {"grouplist", CGUIControl::GUICONTROL_GROUPLIST},
83 {"image", CGUIControl::GUICONTROL_IMAGE},
84 {"image", CGUIControl::GUICONTROL_BORDEREDIMAGE},
85 {"label", CGUIControl::GUICONTROL_LABEL},
86 {"label", CGUIControl::GUICONTROL_LISTLABEL},
87 {"list", CGUIControl::GUICONTAINER_LIST},
88 {"mover", CGUIControl::GUICONTROL_MOVER},
89 {"multiimage", CGUIControl::GUICONTROL_MULTI_IMAGE},
90 {"panel", CGUIControl::GUICONTAINER_PANEL},
91 {"progress", CGUIControl::GUICONTROL_PROGRESS},
92 {"radiobutton", CGUIControl::GUICONTROL_RADIO},
93 {"ranges", CGUIControl::GUICONTROL_RANGES},
94 {"renderaddon", CGUIControl::GUICONTROL_RENDERADDON},
95 {"resize", CGUIControl::GUICONTROL_RESIZE},
96 {"rss", CGUIControl::GUICONTROL_RSS},
97 {"scrollbar", CGUIControl::GUICONTROL_SCROLLBAR},
98 {"slider", CGUIControl::GUICONTROL_SLIDER},
99 {"sliderex", CGUIControl::GUICONTROL_SETTINGS_SLIDER},
100 {"spincontrol", CGUIControl::GUICONTROL_SPIN},
101 {"spincontrolex", CGUIControl::GUICONTROL_SPINEX},
102 {"textbox", CGUIControl::GUICONTROL_TEXTBOX},
103 {"togglebutton", CGUIControl::GUICONTROL_TOGGLEBUTTON},
104 {"videowindow", CGUIControl::GUICONTROL_VIDEO},
105 {"visualisation", CGUIControl::GUICONTROL_VISUALISATION},
106 {"wraplist", CGUIControl::GUICONTAINER_WRAPLIST},
109 CGUIControl::GUICONTROLTYPES CGUIControlFactory::TranslateControlType(const std::string& type)
111 for (const ControlMapping& control : controls)
112 if (StringUtils::EqualsNoCase(type, control.name))
113 return control.type;
114 return CGUIControl::GUICONTROL_UNKNOWN;
117 std::string CGUIControlFactory::TranslateControlType(CGUIControl::GUICONTROLTYPES type)
119 for (const ControlMapping& control : controls)
120 if (type == control.type)
121 return control.name;
122 return "";
125 CGUIControlFactory::CGUIControlFactory(void) = default;
127 CGUIControlFactory::~CGUIControlFactory(void) = default;
129 bool CGUIControlFactory::GetIntRange(const TiXmlNode* pRootNode,
130 const char* strTag,
131 int& iMinValue,
132 int& iMaxValue,
133 int& iIntervalValue)
135 const TiXmlNode* pNode = pRootNode->FirstChild(strTag);
136 if (!pNode || !pNode->FirstChild())
137 return false;
138 iMinValue = atoi(pNode->FirstChild()->Value());
139 const char* maxValue = strchr(pNode->FirstChild()->Value(), ',');
140 if (maxValue)
142 maxValue++;
143 iMaxValue = atoi(maxValue);
145 const char* intervalValue = strchr(maxValue, ',');
146 if (intervalValue)
148 intervalValue++;
149 iIntervalValue = atoi(intervalValue);
153 return true;
156 bool CGUIControlFactory::GetFloatRange(const TiXmlNode* pRootNode,
157 const char* strTag,
158 float& fMinValue,
159 float& fMaxValue,
160 float& fIntervalValue)
162 const TiXmlNode* pNode = pRootNode->FirstChild(strTag);
163 if (!pNode || !pNode->FirstChild())
164 return false;
165 fMinValue = (float)atof(pNode->FirstChild()->Value());
166 const char* maxValue = strchr(pNode->FirstChild()->Value(), ',');
167 if (maxValue)
169 maxValue++;
170 fMaxValue = (float)atof(maxValue);
172 const char* intervalValue = strchr(maxValue, ',');
173 if (intervalValue)
175 intervalValue++;
176 fIntervalValue = (float)atof(intervalValue);
180 return true;
183 float CGUIControlFactory::ParsePosition(const char* pos, const float parentSize)
185 char* end = NULL;
186 float value = pos ? (float)strtod(pos, &end) : 0;
187 if (end)
189 if (*end == 'r')
190 value = parentSize - value;
191 else if (*end == '%')
192 value = value * parentSize / 100.0f;
194 return value;
197 bool CGUIControlFactory::GetPosition(const TiXmlNode* node,
198 const char* strTag,
199 const float parentSize,
200 float& value)
202 const TiXmlElement* pNode = node->FirstChildElement(strTag);
203 if (!pNode || !pNode->FirstChild())
204 return false;
206 value = ParsePosition(pNode->FirstChild()->Value(), parentSize);
207 return true;
210 bool CGUIControlFactory::GetDimension(const TiXmlNode* pRootNode,
211 const char* strTag,
212 const float parentSize,
213 float& value,
214 float& min)
216 const TiXmlElement* pNode = pRootNode->FirstChildElement(strTag);
217 if (!pNode || !pNode->FirstChild())
218 return false;
219 if (0 == StringUtils::CompareNoCase("auto", pNode->FirstChild()->Value(), 4))
220 { // auto-width - at least min must be set
221 value = ParsePosition(pNode->Attribute("max"), parentSize);
222 min = ParsePosition(pNode->Attribute("min"), parentSize);
223 if (!min)
224 min = 1;
225 return true;
227 value = ParsePosition(pNode->FirstChild()->Value(), parentSize);
228 return true;
231 bool CGUIControlFactory::GetDimensions(const TiXmlNode* node,
232 const char* leftTag,
233 const char* rightTag,
234 const char* centerLeftTag,
235 const char* centerRightTag,
236 const char* widthTag,
237 const float parentSize,
238 float& left,
239 float& width,
240 float& min_width)
242 float center = 0, right = 0;
244 // read from the XML
245 bool hasLeft = GetPosition(node, leftTag, parentSize, left);
246 bool hasCenter = GetPosition(node, centerLeftTag, parentSize, center);
247 if (!hasCenter && GetPosition(node, centerRightTag, parentSize, center))
249 center = parentSize - center;
250 hasCenter = true;
252 bool hasRight = false;
253 if (GetPosition(node, rightTag, parentSize, right))
255 right = parentSize - right;
256 hasRight = true;
258 bool hasWidth = GetDimension(node, widthTag, parentSize, width, min_width);
260 if (!hasLeft)
261 { // figure out position
262 if (hasCenter) // no left specified
264 if (hasWidth)
266 left = center - width / 2;
267 hasLeft = true;
269 else
271 if (hasRight)
273 width = (right - center) * 2;
274 left = right - width;
275 hasLeft = true;
279 else if (hasRight) // no left or centre
281 if (hasWidth)
283 left = right - width;
284 hasLeft = true;
288 if (!hasWidth)
290 if (hasRight)
292 width = std::max(0.0f, right - left); // if left=0, this fills to size of parent
293 hasLeft = true;
294 hasWidth = true;
296 else if (hasCenter)
298 if (hasLeft)
300 width = std::max(0.0f, (center - left) * 2);
301 hasWidth = true;
303 else if (center > 0 && center < parentSize)
304 { // centre given, so fill to edge of parent
305 width = std::max(0.0f, std::min(parentSize - center, center) * 2);
306 left = center - width / 2;
307 hasLeft = true;
308 hasWidth = true;
311 else if (hasLeft) // neither right nor center specified
313 width = std::max(0.0f, parentSize - left); // if left=0, this fills to parent
314 hasWidth = true;
317 return hasLeft && hasWidth;
320 bool CGUIControlFactory::GetAspectRatio(const TiXmlNode* pRootNode,
321 const char* strTag,
322 CAspectRatio& aspect)
324 std::string ratio;
325 const TiXmlElement* node = pRootNode->FirstChildElement(strTag);
326 if (!node || !node->FirstChild())
327 return false;
329 ratio = node->FirstChild()->Value();
330 if (StringUtils::EqualsNoCase(ratio, "keep"))
331 aspect.ratio = CAspectRatio::AR_KEEP;
332 else if (StringUtils::EqualsNoCase(ratio, "scale"))
333 aspect.ratio = CAspectRatio::AR_SCALE;
334 else if (StringUtils::EqualsNoCase(ratio, "center"))
335 aspect.ratio = CAspectRatio::AR_CENTER;
336 else if (StringUtils::EqualsNoCase(ratio, "stretch"))
337 aspect.ratio = CAspectRatio::AR_STRETCH;
339 const char* attribute = node->Attribute("align");
340 if (attribute)
342 std::string align(attribute);
343 if (StringUtils::EqualsNoCase(align, "center"))
344 aspect.align = ASPECT_ALIGN_CENTER | (aspect.align & ASPECT_ALIGNY_MASK);
345 else if (StringUtils::EqualsNoCase(align, "right"))
346 aspect.align = ASPECT_ALIGN_RIGHT | (aspect.align & ASPECT_ALIGNY_MASK);
347 else if (StringUtils::EqualsNoCase(align, "left"))
348 aspect.align = ASPECT_ALIGN_LEFT | (aspect.align & ASPECT_ALIGNY_MASK);
350 attribute = node->Attribute("aligny");
351 if (attribute)
353 std::string align(attribute);
354 if (StringUtils::EqualsNoCase(align, "center"))
355 aspect.align = ASPECT_ALIGNY_CENTER | (aspect.align & ASPECT_ALIGN_MASK);
356 else if (StringUtils::EqualsNoCase(align, "bottom"))
357 aspect.align = ASPECT_ALIGNY_BOTTOM | (aspect.align & ASPECT_ALIGN_MASK);
358 else if (StringUtils::EqualsNoCase(align, "top"))
359 aspect.align = ASPECT_ALIGNY_TOP | (aspect.align & ASPECT_ALIGN_MASK);
361 attribute = node->Attribute("scalediffuse");
362 if (attribute)
364 std::string scale(attribute);
365 if (StringUtils::EqualsNoCase(scale, "true") || StringUtils::EqualsNoCase(scale, "yes"))
366 aspect.scaleDiffuse = true;
367 else
368 aspect.scaleDiffuse = false;
370 return true;
373 bool CGUIControlFactory::GetInfoTexture(const TiXmlNode* pRootNode,
374 const char* strTag,
375 CTextureInfo& image,
376 GUIINFO::CGUIInfoLabel& info,
377 int parentID)
379 GetTexture(pRootNode, strTag, image);
380 image.filename = "";
381 GetInfoLabel(pRootNode, strTag, info, parentID);
382 return true;
385 bool CGUIControlFactory::GetTexture(const TiXmlNode* pRootNode,
386 const char* strTag,
387 CTextureInfo& image)
389 const TiXmlElement* pNode = pRootNode->FirstChildElement(strTag);
390 if (!pNode)
391 return false;
392 const char* border = pNode->Attribute("border");
393 if (border)
395 GetRectFromString(border, image.border);
396 const char* borderinfill = pNode->Attribute("infill");
397 image.m_infill = (!borderinfill || !StringUtils::EqualsNoCase(borderinfill, "false"));
399 image.orientation = 0;
400 const char* flipX = pNode->Attribute("flipx");
401 if (flipX && StringUtils::CompareNoCase(flipX, "true") == 0)
402 image.orientation = 1;
403 const char* flipY = pNode->Attribute("flipy");
404 if (flipY && StringUtils::CompareNoCase(flipY, "true") == 0)
405 image.orientation = 3 - image.orientation; // either 3 or 2
406 image.diffuse = XMLUtils::GetAttribute(pNode, "diffuse");
407 image.diffuseColor.Parse(XMLUtils::GetAttribute(pNode, "colordiffuse"), 0);
408 const char* background = pNode->Attribute("background");
409 if (background && StringUtils::CompareNoCase(background, "true", 4) == 0)
410 image.useLarge = true;
411 image.filename = pNode->FirstChild() ? pNode->FirstChild()->Value() : "";
412 return true;
415 void CGUIControlFactory::GetRectFromString(const std::string& string, CRect& rect)
417 // format is rect="left[,top,right,bottom]"
418 std::vector<std::string> strRect = StringUtils::Split(string, ',');
419 if (strRect.size() == 1)
421 rect.x1 = (float)atof(strRect[0].c_str());
422 rect.y1 = rect.x1;
423 rect.x2 = rect.x1;
424 rect.y2 = rect.x1;
426 else if (strRect.size() == 4)
428 rect.x1 = (float)atof(strRect[0].c_str());
429 rect.y1 = (float)atof(strRect[1].c_str());
430 rect.x2 = (float)atof(strRect[2].c_str());
431 rect.y2 = (float)atof(strRect[3].c_str());
435 bool CGUIControlFactory::GetAlignment(const TiXmlNode* pRootNode,
436 const char* strTag,
437 uint32_t& alignment)
439 const TiXmlNode* pNode = pRootNode->FirstChild(strTag);
440 if (!pNode || !pNode->FirstChild())
441 return false;
443 std::string strAlign = pNode->FirstChild()->Value();
444 if (strAlign == "right" || strAlign == "bottom")
445 alignment = XBFONT_RIGHT;
446 else if (strAlign == "center")
447 alignment = XBFONT_CENTER_X;
448 else if (strAlign == "justify")
449 alignment = XBFONT_JUSTIFIED;
450 else
451 alignment = XBFONT_LEFT;
452 return true;
455 bool CGUIControlFactory::GetAlignmentY(const TiXmlNode* pRootNode,
456 const char* strTag,
457 uint32_t& alignment)
459 const TiXmlNode* pNode = pRootNode->FirstChild(strTag);
460 if (!pNode || !pNode->FirstChild())
462 return false;
465 std::string strAlign = pNode->FirstChild()->Value();
467 alignment = 0;
468 if (strAlign == "center")
470 alignment = XBFONT_CENTER_Y;
473 return true;
476 bool CGUIControlFactory::GetConditionalVisibility(const TiXmlNode* control,
477 std::string& condition,
478 std::string& allowHiddenFocus)
480 const TiXmlElement* node = control->FirstChildElement("visible");
481 if (!node)
482 return false;
483 std::vector<std::string> conditions;
484 while (node)
486 const char* hidden = node->Attribute("allowhiddenfocus");
487 if (hidden)
488 allowHiddenFocus = hidden;
489 // add to our condition string
490 if (!node->NoChildren())
491 conditions.emplace_back(node->FirstChild()->Value());
492 node = node->NextSiblingElement("visible");
494 if (!conditions.size())
495 return false;
496 if (conditions.size() == 1)
497 condition = conditions[0];
498 else
499 { // multiple conditions should be anded together
500 condition = "[";
501 for (unsigned int i = 0; i < conditions.size() - 1; i++)
502 condition += conditions[i] + "] + [";
503 condition += conditions[conditions.size() - 1] + "]";
505 return true;
508 bool CGUIControlFactory::GetConditionalVisibility(const TiXmlNode* control, std::string& condition)
510 std::string allowHiddenFocus;
511 return GetConditionalVisibility(control, condition, allowHiddenFocus);
514 bool CGUIControlFactory::GetAnimations(TiXmlNode* control,
515 const CRect& rect,
516 int context,
517 std::vector<CAnimation>& animations)
519 TiXmlElement* node = control->FirstChildElement("animation");
520 bool ret = false;
521 if (node)
522 animations.clear();
523 while (node)
525 ret = true;
526 if (node->FirstChild())
528 CAnimation anim;
529 anim.Create(node, rect, context);
530 animations.push_back(anim);
531 if (StringUtils::CompareNoCase(node->FirstChild()->Value(), "VisibleChange") == 0)
532 { // add the hidden one as well
533 TiXmlElement hidden(*node);
534 hidden.FirstChild()->SetValue("hidden");
535 const char* start = hidden.Attribute("start");
536 const char* end = hidden.Attribute("end");
537 if (start && end)
539 std::string temp = end;
540 hidden.SetAttribute("end", start);
541 hidden.SetAttribute("start", temp.c_str());
543 else if (start)
544 hidden.SetAttribute("end", start);
545 else if (end)
546 hidden.SetAttribute("start", end);
547 CAnimation anim2;
548 anim2.Create(&hidden, rect, context);
549 animations.push_back(anim2);
552 node = node->NextSiblingElement("animation");
554 return ret;
557 bool CGUIControlFactory::GetActions(const TiXmlNode* pRootNode,
558 const char* strTag,
559 CGUIAction& actions)
561 actions.Reset();
562 const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag);
563 while (pElement)
565 if (pElement->FirstChild())
567 actions.Append(
568 {XMLUtils::GetAttribute(pElement, "condition"), pElement->FirstChild()->Value()});
570 pElement = pElement->NextSiblingElement(strTag);
572 return actions.HasAnyActions();
575 bool CGUIControlFactory::GetHitRect(const TiXmlNode* control, CRect& rect, const CRect& parentRect)
577 const TiXmlElement* node = control->FirstChildElement("hitrect");
578 if (node)
580 rect.x1 = ParsePosition(node->Attribute("x"), parentRect.Width());
581 rect.y1 = ParsePosition(node->Attribute("y"), parentRect.Height());
582 if (node->Attribute("w"))
583 rect.x2 = (float)atof(node->Attribute("w")) + rect.x1;
584 else if (node->Attribute("right"))
585 rect.x2 = std::min(ParsePosition(node->Attribute("right"), parentRect.Width()), rect.x1);
586 if (node->Attribute("h"))
587 rect.y2 = (float)atof(node->Attribute("h")) + rect.y1;
588 else if (node->Attribute("bottom"))
589 rect.y2 = std::min(ParsePosition(node->Attribute("bottom"), parentRect.Height()), rect.y1);
590 return true;
592 return false;
595 bool CGUIControlFactory::GetScroller(const TiXmlNode* control,
596 const std::string& scrollerTag,
597 CScroller& scroller)
599 const TiXmlElement* node = control->FirstChildElement(scrollerTag);
600 if (node)
602 unsigned int scrollTime;
603 if (XMLUtils::GetUInt(control, scrollerTag.c_str(), scrollTime))
605 scroller = CScroller(scrollTime, CAnimEffect::GetTweener(node));
606 return true;
609 return false;
612 bool CGUIControlFactory::GetColor(const TiXmlNode* control,
613 const char* strTag,
614 UTILS::COLOR::Color& value)
616 const TiXmlElement* node = control->FirstChildElement(strTag);
617 if (node && node->FirstChild())
619 value = CServiceBroker::GetGUI()->GetColorManager().GetColor(node->FirstChild()->Value());
620 return true;
622 return false;
625 bool CGUIControlFactory::GetInfoColor(const TiXmlNode* control,
626 const char* strTag,
627 GUIINFO::CGUIInfoColor& value,
628 int parentID)
630 const TiXmlElement* node = control->FirstChildElement(strTag);
631 if (node && node->FirstChild())
633 value.Parse(node->FirstChild()->ValueStr(), parentID);
634 return true;
636 return false;
639 void CGUIControlFactory::GetInfoLabel(const TiXmlNode* pControlNode,
640 const std::string& labelTag,
641 GUIINFO::CGUIInfoLabel& infoLabel,
642 int parentID)
644 std::vector<GUIINFO::CGUIInfoLabel> labels;
645 GetInfoLabels(pControlNode, labelTag, labels, parentID);
646 if (labels.size())
647 infoLabel = labels[0];
650 bool CGUIControlFactory::GetInfoLabelFromElement(const TiXmlElement* element,
651 GUIINFO::CGUIInfoLabel& infoLabel,
652 int parentID)
654 if (!element || !element->FirstChild())
655 return false;
657 std::string label = element->FirstChild()->Value();
658 if (label.empty())
659 return false;
661 std::string fallback = XMLUtils::GetAttribute(element, "fallback");
662 if (StringUtils::IsNaturalNumber(label))
663 label = g_localizeStrings.Get(atoi(label.c_str()));
664 if (StringUtils::IsNaturalNumber(fallback))
665 fallback = g_localizeStrings.Get(atoi(fallback.c_str()));
666 else
667 g_charsetConverter.unknownToUTF8(fallback);
668 infoLabel.SetLabel(label, fallback, parentID);
669 return true;
672 void CGUIControlFactory::GetInfoLabels(const TiXmlNode* pControlNode,
673 const std::string& labelTag,
674 std::vector<GUIINFO::CGUIInfoLabel>& infoLabels,
675 int parentID)
677 // we can have the following infolabels:
678 // 1. <number>1234</number> -> direct number
679 // 2. <label>number</label> -> lookup in localizestrings
680 // 3. <label fallback="blah">$LOCALIZE(blah) $INFO(blah)</label> -> infolabel with given fallback
681 // 4. <info>ListItem.Album</info> (uses <label> as fallback)
682 int labelNumber = 0;
683 if (XMLUtils::GetInt(pControlNode, "number", labelNumber))
685 std::string label = std::to_string(labelNumber);
686 infoLabels.emplace_back(label);
687 return; // done
689 const TiXmlElement* labelNode = pControlNode->FirstChildElement(labelTag);
690 while (labelNode)
692 GUIINFO::CGUIInfoLabel label;
693 if (GetInfoLabelFromElement(labelNode, label, parentID))
694 infoLabels.push_back(label);
695 labelNode = labelNode->NextSiblingElement(labelTag);
697 const TiXmlNode* infoNode = pControlNode->FirstChild("info");
698 if (infoNode)
699 { // <info> nodes override <label>'s (backward compatibility)
700 std::string fallback;
701 if (infoLabels.size())
702 fallback = infoLabels[0].GetLabel(0);
703 infoLabels.clear();
704 while (infoNode)
706 if (infoNode->FirstChild())
708 std::string info = StringUtils::Format("$INFO[{}]", infoNode->FirstChild()->Value());
709 infoLabels.emplace_back(info, fallback, parentID);
711 infoNode = infoNode->NextSibling("info");
716 // Convert a string to a GUI label, by translating/parsing the label for localisable strings
717 std::string CGUIControlFactory::FilterLabel(const std::string& label)
719 std::string viewLabel = label;
720 if (StringUtils::IsNaturalNumber(viewLabel))
721 viewLabel = g_localizeStrings.Get(atoi(label.c_str()));
722 else
723 g_charsetConverter.unknownToUTF8(viewLabel);
724 return viewLabel;
727 bool CGUIControlFactory::GetString(const TiXmlNode* pRootNode,
728 const char* strTag,
729 std::string& text)
731 if (!XMLUtils::GetString(pRootNode, strTag, text))
732 return false;
733 if (StringUtils::IsNaturalNumber(text))
734 text = g_localizeStrings.Get(atoi(text.c_str()));
735 return true;
738 std::string CGUIControlFactory::GetType(const TiXmlElement* pControlNode)
740 std::string type = XMLUtils::GetAttribute(pControlNode, "type");
741 if (type.empty()) // backward compatibility - not desired
742 XMLUtils::GetString(pControlNode, "type", type);
743 return type;
746 bool CGUIControlFactory::GetMovingSpeedConfig(const TiXmlNode* pRootNode,
747 const char* strTag,
748 UTILS::MOVING_SPEED::MapEventConfig& movingSpeedCfg)
750 const TiXmlElement* msNode = pRootNode->FirstChildElement(strTag);
751 if (!msNode)
752 return false;
754 float globalAccel{StringUtils::ToFloat(XMLUtils::GetAttribute(msNode, "acceleration"))};
755 float globalMaxVel{StringUtils::ToFloat(XMLUtils::GetAttribute(msNode, "maxvelocity"))};
756 uint32_t globalResetTimeout{
757 StringUtils::ToUint32(XMLUtils::GetAttribute(msNode, "resettimeout"))};
758 float globalDelta{StringUtils::ToFloat(XMLUtils::GetAttribute(msNode, "delta"))};
760 const TiXmlElement* configElement{msNode->FirstChildElement("eventconfig")};
761 while (configElement)
763 const char* eventType = configElement->Attribute("type");
764 if (!eventType)
766 CLog::LogF(LOGERROR, "Failed to parse XML \"eventconfig\" tag missing \"type\" attribute");
767 continue;
770 const char* accelerationStr{configElement->Attribute("acceleration")};
771 float acceleration = accelerationStr ? StringUtils::ToFloat(accelerationStr) : globalAccel;
773 const char* maxVelocityStr{configElement->Attribute("maxvelocity")};
774 float maxVelocity = maxVelocityStr ? StringUtils::ToFloat(maxVelocityStr) : globalMaxVel;
776 const char* resetTimeoutStr{configElement->Attribute("resettimeout")};
777 uint32_t resetTimeout =
778 resetTimeoutStr ? StringUtils::ToUint32(resetTimeoutStr) : globalResetTimeout;
780 const char* deltaStr{configElement->Attribute("delta")};
781 float delta = deltaStr ? StringUtils::ToFloat(deltaStr) : globalDelta;
783 UTILS::MOVING_SPEED::EventCfg eventCfg{acceleration, maxVelocity, resetTimeout, delta};
784 movingSpeedCfg.emplace(UTILS::MOVING_SPEED::ParseEventType(eventType), eventCfg);
786 configElement = configElement->NextSiblingElement("eventconfig");
788 return true;
791 CGUIControl* CGUIControlFactory::Create(int parentID,
792 const CRect& rect,
793 TiXmlElement* pControlNode,
794 bool insideContainer)
796 // get the control type
797 std::string strType = GetType(pControlNode);
798 CGUIControl::GUICONTROLTYPES type = TranslateControlType(strType);
800 int id = 0;
801 float posX = 0, posY = 0;
802 float width = 0, height = 0;
803 float minHeight = 0, minWidth = 0;
805 CGUIControl::ActionMap actions;
807 int pageControl = 0;
808 GUIINFO::CGUIInfoColor colorDiffuse(0xFFFFFFFF);
809 GUIINFO::CGUIInfoColor colorBox(0xFF000000);
810 int defaultControl = 0;
811 bool defaultAlways = false;
812 std::string strTmp;
813 int singleInfo = 0;
814 int singleInfo2 = 0;
815 std::string strLabel;
816 int iUrlSet = 0;
817 std::string toggleSelect;
819 float spinWidth = 16;
820 float spinHeight = 16;
821 float spinPosX = 0, spinPosY = 0;
822 std::string strSubType;
823 int iType = SPIN_CONTROL_TYPE_TEXT;
824 int iMin = 0;
825 int iMax = 100;
826 int iInterval = 1;
827 float fMin = 0.0f;
828 float fMax = 1.0f;
829 float fInterval = 0.1f;
830 bool bReverse = true;
831 bool bReveal = false;
832 CTextureInfo textureBackground, textureLeft, textureRight, textureMid, textureOverlay;
833 CTextureInfo textureNib, textureNibFocus, textureNibDisabled, textureBar, textureBarFocus,
834 textureBarDisabled;
835 CTextureInfo textureUp, textureDown;
836 CTextureInfo textureUpFocus, textureDownFocus;
837 CTextureInfo textureUpDisabled, textureDownDisabled;
838 CTextureInfo texture, borderTexture;
839 GUIINFO::CGUIInfoLabel textureFile;
840 CTextureInfo textureFocus, textureNoFocus;
841 CTextureInfo textureAltFocus, textureAltNoFocus;
842 CTextureInfo textureRadioOnFocus, textureRadioOnNoFocus;
843 CTextureInfo textureRadioOffFocus, textureRadioOffNoFocus;
844 CTextureInfo textureRadioOnDisabled, textureRadioOffDisabled;
845 CTextureInfo textureProgressIndicator;
846 CTextureInfo textureColorMask, textureColorDisabledMask;
848 GUIINFO::CGUIInfoLabel texturePath;
849 CRect borderSize;
851 float sliderWidth = 150, sliderHeight = 16;
852 CPoint offset;
854 bool bHasPath = false;
855 CGUIAction clickActions;
856 CGUIAction altclickActions;
857 CGUIAction focusActions;
858 CGUIAction unfocusActions;
859 CGUIAction textChangeActions;
860 std::string strTitle = "";
861 std::string strRSSTags = "";
863 float buttonGap = 5;
864 int iMovementRange = 0;
865 CAspectRatio aspect;
866 std::string allowHiddenFocus;
867 std::string enableCondition;
869 std::vector<CAnimation> animations;
871 CGUIControl::GUISCROLLVALUE scrollValue = CGUIControl::FOCUS;
872 bool bPulse = true;
873 unsigned int timePerImage = 0;
874 unsigned int fadeTime = 0;
875 unsigned int timeToPauseAtEnd = 0;
876 bool randomized = false;
877 bool loop = true;
878 bool wrapMultiLine = false;
879 ORIENTATION orientation = VERTICAL;
880 bool showOnePage = true;
881 bool scrollOut = true;
882 int preloadItems = 0;
884 CLabelInfo labelInfo, labelInfoMono;
886 GUIINFO::CGUIInfoColor hitColor(0xFFFFFFFF);
887 GUIINFO::CGUIInfoColor textColor3;
888 GUIINFO::CGUIInfoColor headlineColor;
890 float radioWidth = 0;
891 float radioHeight = 0;
892 float radioPosX = 0;
893 float radioPosY = 0;
895 float colorWidth = 0;
896 float colorHeight = 0;
897 float colorPosX = 0;
898 float colorPosY = 0;
900 std::string altLabel;
901 std::string strLabel2;
902 std::string action;
904 int focusPosition = 0;
905 int scrollTime = 200;
906 int timeBlocks = 36;
907 int rulerUnit = 12;
908 bool useControlCoords = false;
909 bool renderFocusedLast = false;
911 CRect hitRect;
912 CPoint camera;
913 float stereo = 0.f;
914 bool hasCamera = false;
915 bool resetOnLabelChange = true;
916 bool bPassword = false;
917 std::string visibleCondition;
919 UTILS::MOVING_SPEED::MapEventConfig movingSpeedCfg;
921 /////////////////////////////////////////////////////////////////////////////
922 // Read control properties from XML
925 if (!pControlNode->Attribute("id", &id))
926 XMLUtils::GetInt(pControlNode, "id", id); // backward compatibility - not desired
927 //! @todo Perhaps we should check here whether id is valid for focusable controls
928 //! such as buttons etc. For labels/fadelabels/images it does not matter
930 GetAlignment(pControlNode, "align", labelInfo.align);
931 if (!GetDimensions(pControlNode, "left", "right", "centerleft", "centerright", "width",
932 rect.Width(), posX, width, minWidth))
933 { // didn't get 2 dimensions, so test for old <posx> as well
934 if (GetPosition(pControlNode, "posx", rect.Width(), posX))
935 { // <posx> available, so use it along with any hacks we used to support
936 if (!insideContainer && type == CGUIControl::GUICONTROL_LABEL &&
937 (labelInfo.align & XBFONT_RIGHT))
938 posX -= width;
940 if (!width) // no width specified, so compute from parent
941 width = std::max(rect.Width() - posX, 0.0f);
943 if (!GetDimensions(pControlNode, "top", "bottom", "centertop", "centerbottom", "height",
944 rect.Height(), posY, height, minHeight))
946 GetPosition(pControlNode, "posy", rect.Height(), posY);
947 if (!height)
948 height = std::max(rect.Height() - posY, 0.0f);
951 XMLUtils::GetFloat(pControlNode, "offsetx", offset.x);
952 XMLUtils::GetFloat(pControlNode, "offsety", offset.y);
954 hitRect.SetRect(posX, posY, posX + width, posY + height);
955 GetHitRect(pControlNode, hitRect, rect);
957 GetInfoColor(pControlNode, "hitrectcolor", hitColor, parentID);
959 GetActions(pControlNode, "onup", actions[ACTION_MOVE_UP]);
960 GetActions(pControlNode, "ondown", actions[ACTION_MOVE_DOWN]);
961 GetActions(pControlNode, "onleft", actions[ACTION_MOVE_LEFT]);
962 GetActions(pControlNode, "onright", actions[ACTION_MOVE_RIGHT]);
963 GetActions(pControlNode, "onnext", actions[ACTION_NEXT_CONTROL]);
964 GetActions(pControlNode, "onprev", actions[ACTION_PREV_CONTROL]);
965 GetActions(pControlNode, "onback", actions[ACTION_NAV_BACK]);
966 GetActions(pControlNode, "oninfo", actions[ACTION_SHOW_INFO]);
968 if (XMLUtils::GetInt(pControlNode, "defaultcontrol", defaultControl))
970 const char* always = pControlNode->FirstChildElement("defaultcontrol")->Attribute("always");
971 if (always && StringUtils::CompareNoCase(always, "true", 4) == 0)
972 defaultAlways = true;
974 XMLUtils::GetInt(pControlNode, "pagecontrol", pageControl);
976 GetInfoColor(pControlNode, "colordiffuse", colorDiffuse, parentID);
977 GetInfoColor(pControlNode, "colorbox", colorBox, parentID);
979 GetConditionalVisibility(pControlNode, visibleCondition, allowHiddenFocus);
980 XMLUtils::GetString(pControlNode, "enable", enableCondition);
982 CRect animRect(posX, posY, posX + width, posY + height);
983 GetAnimations(pControlNode, animRect, parentID, animations);
985 GetInfoColor(pControlNode, "textcolor", labelInfo.textColor, parentID);
986 GetInfoColor(pControlNode, "focusedcolor", labelInfo.focusedColor, parentID);
987 GetInfoColor(pControlNode, "disabledcolor", labelInfo.disabledColor, parentID);
988 GetInfoColor(pControlNode, "shadowcolor", labelInfo.shadowColor, parentID);
989 GetInfoColor(pControlNode, "selectedcolor", labelInfo.selectedColor, parentID);
990 GetInfoColor(pControlNode, "invalidcolor", labelInfo.invalidColor, parentID);
991 XMLUtils::GetFloat(pControlNode, "textoffsetx", labelInfo.offsetX);
992 XMLUtils::GetFloat(pControlNode, "textoffsety", labelInfo.offsetY);
993 int angle = 0; // use the negative angle to compensate for our vertically flipped cartesian plane
994 if (XMLUtils::GetInt(pControlNode, "angle", angle))
995 labelInfo.angle = (float)-angle;
996 std::string strFont, strMonoFont;
997 if (XMLUtils::GetString(pControlNode, "font", strFont))
998 labelInfo.font = g_fontManager.GetFont(strFont);
999 XMLUtils::GetString(pControlNode, "monofont", strMonoFont);
1000 uint32_t alignY = 0;
1001 if (GetAlignmentY(pControlNode, "aligny", alignY))
1002 labelInfo.align |= alignY;
1003 if (XMLUtils::GetFloat(pControlNode, "textwidth", labelInfo.width))
1004 labelInfo.align |= XBFONT_TRUNCATED;
1006 GetActions(pControlNode, "onclick", clickActions);
1007 GetActions(pControlNode, "ontextchange", textChangeActions);
1008 GetActions(pControlNode, "onfocus", focusActions);
1009 GetActions(pControlNode, "onunfocus", unfocusActions);
1010 focusActions.EnableSendThreadMessageMode();
1011 unfocusActions.EnableSendThreadMessageMode();
1012 GetActions(pControlNode, "altclick", altclickActions);
1014 std::string infoString;
1015 if (XMLUtils::GetString(pControlNode, "info", infoString))
1016 singleInfo = CServiceBroker::GetGUI()->GetInfoManager().TranslateString(infoString);
1017 if (XMLUtils::GetString(pControlNode, "info2", infoString))
1018 singleInfo2 = CServiceBroker::GetGUI()->GetInfoManager().TranslateString(infoString);
1020 GetTexture(pControlNode, "texturefocus", textureFocus);
1021 GetTexture(pControlNode, "texturenofocus", textureNoFocus);
1022 GetTexture(pControlNode, "alttexturefocus", textureAltFocus);
1023 GetTexture(pControlNode, "alttexturenofocus", textureAltNoFocus);
1025 XMLUtils::GetString(pControlNode, "usealttexture", toggleSelect);
1026 XMLUtils::GetString(pControlNode, "selected", toggleSelect);
1028 XMLUtils::GetBoolean(pControlNode, "haspath", bHasPath);
1030 GetTexture(pControlNode, "textureup", textureUp);
1031 GetTexture(pControlNode, "texturedown", textureDown);
1032 GetTexture(pControlNode, "textureupfocus", textureUpFocus);
1033 GetTexture(pControlNode, "texturedownfocus", textureDownFocus);
1034 GetTexture(pControlNode, "textureupdisabled", textureUpDisabled);
1035 GetTexture(pControlNode, "texturedowndisabled", textureDownDisabled);
1037 XMLUtils::GetFloat(pControlNode, "spinwidth", spinWidth);
1038 XMLUtils::GetFloat(pControlNode, "spinheight", spinHeight);
1039 XMLUtils::GetFloat(pControlNode, "spinposx", spinPosX);
1040 XMLUtils::GetFloat(pControlNode, "spinposy", spinPosY);
1042 XMLUtils::GetFloat(pControlNode, "sliderwidth", sliderWidth);
1043 XMLUtils::GetFloat(pControlNode, "sliderheight", sliderHeight);
1044 if (!GetTexture(pControlNode, "textureradioonfocus", textureRadioOnFocus) ||
1045 !GetTexture(pControlNode, "textureradioonnofocus", textureRadioOnNoFocus))
1047 GetTexture(pControlNode, "textureradiofocus", textureRadioOnFocus); // backward compatibility
1048 GetTexture(pControlNode, "textureradioon", textureRadioOnFocus);
1049 textureRadioOnNoFocus = textureRadioOnFocus;
1051 if (!GetTexture(pControlNode, "textureradioofffocus", textureRadioOffFocus) ||
1052 !GetTexture(pControlNode, "textureradiooffnofocus", textureRadioOffNoFocus))
1054 GetTexture(pControlNode, "textureradionofocus", textureRadioOffFocus); // backward compatibility
1055 GetTexture(pControlNode, "textureradiooff", textureRadioOffFocus);
1056 textureRadioOffNoFocus = textureRadioOffFocus;
1058 GetTexture(pControlNode, "textureradioondisabled", textureRadioOnDisabled);
1059 GetTexture(pControlNode, "textureradiooffdisabled", textureRadioOffDisabled);
1060 GetTexture(pControlNode, "texturesliderbackground", textureBackground);
1061 GetTexture(pControlNode, "texturesliderbar", textureBar);
1062 GetTexture(pControlNode, "texturesliderbarfocus", textureBarFocus);
1063 if (!GetTexture(pControlNode, "texturesliderbardisabled", textureBarDisabled))
1064 GetTexture(pControlNode, "texturesliderbar", textureBarDisabled); // backward compatibility
1065 GetTexture(pControlNode, "textureslidernib", textureNib);
1066 GetTexture(pControlNode, "textureslidernibfocus", textureNibFocus);
1067 if (!GetTexture(pControlNode, "textureslidernibdisabled", textureNibDisabled))
1068 GetTexture(pControlNode, "textureslidernib", textureNibDisabled); // backward compatibility
1070 GetTexture(pControlNode, "texturecolormask", textureColorMask);
1071 GetTexture(pControlNode, "texturecolordisabledmask", textureColorDisabledMask);
1073 XMLUtils::GetString(pControlNode, "title", strTitle);
1074 XMLUtils::GetString(pControlNode, "tagset", strRSSTags);
1075 GetInfoColor(pControlNode, "headlinecolor", headlineColor, parentID);
1076 GetInfoColor(pControlNode, "titlecolor", textColor3, parentID);
1078 if (XMLUtils::GetString(pControlNode, "subtype", strSubType))
1080 StringUtils::ToLower(strSubType);
1082 if (strSubType == "int")
1083 iType = SPIN_CONTROL_TYPE_INT;
1084 else if (strSubType == "page")
1085 iType = SPIN_CONTROL_TYPE_PAGE;
1086 else if (strSubType == "float")
1087 iType = SPIN_CONTROL_TYPE_FLOAT;
1088 else
1089 iType = SPIN_CONTROL_TYPE_TEXT;
1092 if (!GetIntRange(pControlNode, "range", iMin, iMax, iInterval))
1094 GetFloatRange(pControlNode, "range", fMin, fMax, fInterval);
1097 XMLUtils::GetBoolean(pControlNode, "reverse", bReverse);
1098 XMLUtils::GetBoolean(pControlNode, "reveal", bReveal);
1100 GetTexture(pControlNode, "texturebg", textureBackground);
1101 GetTexture(pControlNode, "lefttexture", textureLeft);
1102 GetTexture(pControlNode, "midtexture", textureMid);
1103 GetTexture(pControlNode, "righttexture", textureRight);
1104 GetTexture(pControlNode, "overlaytexture", textureOverlay);
1106 // the <texture> tag can be overridden by the <info> tag
1107 GetInfoTexture(pControlNode, "texture", texture, textureFile, parentID);
1109 GetTexture(pControlNode, "bordertexture", borderTexture);
1111 // fade label can have a whole bunch, but most just have one
1112 std::vector<GUIINFO::CGUIInfoLabel> infoLabels;
1113 GetInfoLabels(pControlNode, "label", infoLabels, parentID);
1115 GetString(pControlNode, "label", strLabel);
1116 GetString(pControlNode, "altlabel", altLabel);
1117 GetString(pControlNode, "label2", strLabel2);
1119 XMLUtils::GetBoolean(pControlNode, "wrapmultiline", wrapMultiLine);
1120 XMLUtils::GetInt(pControlNode, "urlset", iUrlSet);
1122 if (XMLUtils::GetString(pControlNode, "orientation", strTmp))
1124 StringUtils::ToLower(strTmp);
1125 if (strTmp == "horizontal")
1126 orientation = HORIZONTAL;
1128 XMLUtils::GetFloat(pControlNode, "itemgap", buttonGap);
1129 XMLUtils::GetInt(pControlNode, "movement", iMovementRange);
1130 GetAspectRatio(pControlNode, "aspectratio", aspect);
1132 bool alwaysScroll;
1133 if (XMLUtils::GetBoolean(pControlNode, "scroll", alwaysScroll))
1134 scrollValue = alwaysScroll ? CGUIControl::ALWAYS : CGUIControl::NEVER;
1136 XMLUtils::GetBoolean(pControlNode, "pulseonselect", bPulse);
1137 XMLUtils::GetInt(pControlNode, "timeblocks", timeBlocks);
1138 XMLUtils::GetInt(pControlNode, "rulerunit", rulerUnit);
1139 GetTexture(pControlNode, "progresstexture", textureProgressIndicator);
1141 GetInfoTexture(pControlNode, "imagepath", texture, texturePath, parentID);
1143 XMLUtils::GetUInt(pControlNode, "timeperimage", timePerImage);
1144 XMLUtils::GetUInt(pControlNode, "fadetime", fadeTime);
1145 XMLUtils::GetUInt(pControlNode, "pauseatend", timeToPauseAtEnd);
1146 XMLUtils::GetBoolean(pControlNode, "randomize", randomized);
1147 XMLUtils::GetBoolean(pControlNode, "loop", loop);
1148 XMLUtils::GetBoolean(pControlNode, "scrollout", scrollOut);
1150 XMLUtils::GetFloat(pControlNode, "radiowidth", radioWidth);
1151 XMLUtils::GetFloat(pControlNode, "radioheight", radioHeight);
1152 XMLUtils::GetFloat(pControlNode, "radioposx", radioPosX);
1153 XMLUtils::GetFloat(pControlNode, "radioposy", radioPosY);
1155 XMLUtils::GetFloat(pControlNode, "colorwidth", colorWidth);
1156 XMLUtils::GetFloat(pControlNode, "colorheight", colorHeight);
1157 XMLUtils::GetFloat(pControlNode, "colorposx", colorPosX);
1158 XMLUtils::GetFloat(pControlNode, "colorposy", colorPosY);
1160 std::string borderStr;
1161 if (XMLUtils::GetString(pControlNode, "bordersize", borderStr))
1162 GetRectFromString(borderStr, borderSize);
1164 XMLUtils::GetBoolean(pControlNode, "showonepage", showOnePage);
1165 XMLUtils::GetInt(pControlNode, "focusposition", focusPosition);
1166 XMLUtils::GetInt(pControlNode, "scrolltime", scrollTime);
1167 XMLUtils::GetInt(pControlNode, "preloaditems", preloadItems, 0, 2);
1169 XMLUtils::GetBoolean(pControlNode, "usecontrolcoords", useControlCoords);
1170 XMLUtils::GetBoolean(pControlNode, "renderfocusedlast", renderFocusedLast);
1171 XMLUtils::GetBoolean(pControlNode, "resetonlabelchange", resetOnLabelChange);
1173 XMLUtils::GetBoolean(pControlNode, "password", bPassword);
1175 // view type
1176 VIEW_TYPE viewType = VIEW_TYPE_NONE;
1177 std::string viewLabel;
1178 if (type == CGUIControl::GUICONTAINER_PANEL)
1180 viewType = VIEW_TYPE_ICON;
1181 viewLabel = g_localizeStrings.Get(536);
1183 else if (type == CGUIControl::GUICONTAINER_LIST)
1185 viewType = VIEW_TYPE_LIST;
1186 viewLabel = g_localizeStrings.Get(535);
1188 else
1190 viewType = VIEW_TYPE_WRAP;
1191 viewLabel = g_localizeStrings.Get(541);
1193 TiXmlElement* itemElement = pControlNode->FirstChildElement("viewtype");
1194 if (itemElement && itemElement->FirstChild())
1196 std::string type = itemElement->FirstChild()->Value();
1197 if (type == "list")
1198 viewType = VIEW_TYPE_LIST;
1199 else if (type == "icon")
1200 viewType = VIEW_TYPE_ICON;
1201 else if (type == "biglist")
1202 viewType = VIEW_TYPE_BIG_LIST;
1203 else if (type == "bigicon")
1204 viewType = VIEW_TYPE_BIG_ICON;
1205 else if (type == "wide")
1206 viewType = VIEW_TYPE_WIDE;
1207 else if (type == "bigwide")
1208 viewType = VIEW_TYPE_BIG_WIDE;
1209 else if (type == "wrap")
1210 viewType = VIEW_TYPE_WRAP;
1211 else if (type == "bigwrap")
1212 viewType = VIEW_TYPE_BIG_WRAP;
1213 else if (type == "info")
1214 viewType = VIEW_TYPE_INFO;
1215 else if (type == "biginfo")
1216 viewType = VIEW_TYPE_BIG_INFO;
1217 const char* label = itemElement->Attribute("label");
1218 if (label)
1219 viewLabel = GUIINFO::CGUIInfoLabel::GetLabel(FilterLabel(label), INFO::DEFAULT_CONTEXT);
1222 TiXmlElement* cam = pControlNode->FirstChildElement("camera");
1223 if (cam)
1225 hasCamera = true;
1226 camera.x = ParsePosition(cam->Attribute("x"), width);
1227 camera.y = ParsePosition(cam->Attribute("y"), height);
1230 if (XMLUtils::GetFloat(pControlNode, "depth", stereo))
1231 stereo = std::max(-1.f, std::min(1.f, stereo));
1233 XMLUtils::GetInt(pControlNode, "scrollspeed", labelInfo.scrollSpeed);
1235 GetString(pControlNode, "scrollsuffix", labelInfo.scrollSuffix);
1237 XMLUtils::GetString(pControlNode, "action", action);
1239 GetMovingSpeedConfig(pControlNode, "movingspeed", movingSpeedCfg);
1241 /////////////////////////////////////////////////////////////////////////////
1242 // Instantiate a new control using the properties gathered above
1245 CGUIControl* control = NULL;
1246 switch (type)
1248 case CGUIControl::GUICONTROL_GROUP:
1250 if (insideContainer)
1252 control = new CGUIListGroup(parentID, id, posX, posY, width, height);
1254 else
1256 control = new CGUIControlGroup(parentID, id, posX, posY, width, height);
1257 static_cast<CGUIControlGroup*>(control)->SetDefaultControl(defaultControl, defaultAlways);
1258 static_cast<CGUIControlGroup*>(control)->SetRenderFocusedLast(renderFocusedLast);
1260 break;
1262 case CGUIControl::GUICONTROL_GROUPLIST:
1264 CScroller scroller;
1265 GetScroller(pControlNode, "scrolltime", scroller);
1267 control =
1268 new CGUIControlGroupList(parentID, id, posX, posY, width, height, buttonGap, pageControl,
1269 orientation, useControlCoords, labelInfo.align, scroller);
1270 static_cast<CGUIControlGroup*>(control)->SetDefaultControl(defaultControl, defaultAlways);
1271 static_cast<CGUIControlGroup*>(control)->SetRenderFocusedLast(renderFocusedLast);
1272 static_cast<CGUIControlGroupList*>(control)->SetMinSize(minWidth, minHeight);
1274 break;
1276 case CGUIControl::GUICONTROL_LABEL:
1278 static const GUIINFO::CGUIInfoLabel empty;
1279 const GUIINFO::CGUIInfoLabel& content = !infoLabels.empty() ? infoLabels[0] : empty;
1280 if (insideContainer)
1281 { // inside lists we use CGUIListLabel
1282 control = new CGUIListLabel(parentID, id, posX, posY, width, height, labelInfo, content,
1283 scrollValue);
1285 else
1287 control = new CGUILabelControl(parentID, id, posX, posY, width, height, labelInfo,
1288 wrapMultiLine, bHasPath);
1289 static_cast<CGUILabelControl*>(control)->SetInfo(content);
1290 static_cast<CGUILabelControl*>(control)->SetWidthControl(
1291 minWidth, (scrollValue == CGUIControl::ALWAYS));
1294 break;
1296 case CGUIControl::GUICONTROL_EDIT:
1298 control = new CGUIEditControl(parentID, id, posX, posY, width, height, textureFocus,
1299 textureNoFocus, labelInfo, strLabel);
1301 GUIINFO::CGUIInfoLabel hint_text;
1302 GetInfoLabel(pControlNode, "hinttext", hint_text, parentID);
1303 static_cast<CGUIEditControl*>(control)->SetHint(hint_text);
1305 if (bPassword)
1306 static_cast<CGUIEditControl*>(control)->SetInputType(CGUIEditControl::INPUT_TYPE_PASSWORD,
1308 static_cast<CGUIEditControl*>(control)->SetTextChangeActions(textChangeActions);
1310 break;
1312 case CGUIControl::GUICONTROL_VIDEO:
1314 control = new CGUIVideoControl(parentID, id, posX, posY, width, height);
1315 break;
1317 case CGUIControl::GUICONTROL_GAME:
1319 control = new RETRO::CGUIGameControl(parentID, id, posX, posY, width, height);
1321 GUIINFO::CGUIInfoLabel videoFilter;
1322 GetInfoLabel(pControlNode, "videofilter", videoFilter, parentID);
1323 static_cast<RETRO::CGUIGameControl*>(control)->SetVideoFilter(videoFilter);
1325 GUIINFO::CGUIInfoLabel stretchMode;
1326 GetInfoLabel(pControlNode, "stretchmode", stretchMode, parentID);
1327 static_cast<RETRO::CGUIGameControl*>(control)->SetStretchMode(stretchMode);
1329 GUIINFO::CGUIInfoLabel rotation;
1330 GetInfoLabel(pControlNode, "rotation", rotation, parentID);
1331 static_cast<RETRO::CGUIGameControl*>(control)->SetRotation(rotation);
1333 GUIINFO::CGUIInfoLabel pixels;
1334 GetInfoLabel(pControlNode, "pixels", pixels, parentID);
1335 static_cast<RETRO::CGUIGameControl*>(control)->SetPixels(pixels);
1337 break;
1339 case CGUIControl::GUICONTROL_FADELABEL:
1341 control =
1342 new CGUIFadeLabelControl(parentID, id, posX, posY, width, height, labelInfo, scrollOut,
1343 timeToPauseAtEnd, resetOnLabelChange, randomized);
1345 static_cast<CGUIFadeLabelControl*>(control)->SetInfo(infoLabels);
1347 // check whether or not a scroll tag was specified.
1348 if (scrollValue != CGUIControl::FOCUS)
1349 static_cast<CGUIFadeLabelControl*>(control)->SetScrolling(scrollValue ==
1350 CGUIControl::ALWAYS);
1352 break;
1354 case CGUIControl::GUICONTROL_RSS:
1356 control = new CGUIRSSControl(parentID, id, posX, posY, width, height, labelInfo, textColor3,
1357 headlineColor, strRSSTags);
1358 RssUrls::const_iterator iter = CRssManager::GetInstance().GetUrls().find(iUrlSet);
1359 if (iter != CRssManager::GetInstance().GetUrls().end())
1360 static_cast<CGUIRSSControl*>(control)->SetUrlSet(iUrlSet);
1362 break;
1364 case CGUIControl::GUICONTROL_BUTTON:
1366 control = new CGUIButtonControl(parentID, id, posX, posY, width, height, textureFocus,
1367 textureNoFocus, labelInfo, wrapMultiLine);
1369 CGUIButtonControl* bcontrol = static_cast<CGUIButtonControl*>(control);
1370 bcontrol->SetLabel(strLabel);
1371 bcontrol->SetLabel2(strLabel2);
1372 bcontrol->SetMinWidth(minWidth);
1373 bcontrol->SetClickActions(clickActions);
1374 bcontrol->SetFocusActions(focusActions);
1375 bcontrol->SetUnFocusActions(unfocusActions);
1377 break;
1379 case CGUIControl::GUICONTROL_TOGGLEBUTTON:
1381 control = new CGUIToggleButtonControl(parentID, id, posX, posY, width, height, textureFocus,
1382 textureNoFocus, textureAltFocus, textureAltNoFocus,
1383 labelInfo, wrapMultiLine);
1385 CGUIToggleButtonControl* tcontrol = static_cast<CGUIToggleButtonControl*>(control);
1386 tcontrol->SetLabel(strLabel);
1387 tcontrol->SetAltLabel(altLabel);
1388 tcontrol->SetMinWidth(minWidth);
1389 tcontrol->SetClickActions(clickActions);
1390 tcontrol->SetAltClickActions(altclickActions);
1391 tcontrol->SetFocusActions(focusActions);
1392 tcontrol->SetUnFocusActions(unfocusActions);
1393 tcontrol->SetToggleSelect(toggleSelect);
1395 break;
1397 case CGUIControl::GUICONTROL_RADIO:
1399 control = new CGUIRadioButtonControl(
1400 parentID, id, posX, posY, width, height, textureFocus, textureNoFocus, labelInfo,
1401 textureRadioOnFocus, textureRadioOnNoFocus, textureRadioOffFocus, textureRadioOffNoFocus,
1402 textureRadioOnDisabled, textureRadioOffDisabled);
1404 CGUIRadioButtonControl* rcontrol = static_cast<CGUIRadioButtonControl*>(control);
1405 rcontrol->SetLabel(strLabel);
1406 rcontrol->SetLabel2(strLabel2);
1407 rcontrol->SetRadioDimensions(radioPosX, radioPosY, radioWidth, radioHeight);
1408 rcontrol->SetToggleSelect(toggleSelect);
1409 rcontrol->SetClickActions(clickActions);
1410 rcontrol->SetFocusActions(focusActions);
1411 rcontrol->SetUnFocusActions(unfocusActions);
1413 break;
1415 case CGUIControl::GUICONTROL_SPIN:
1417 control = new CGUISpinControl(parentID, id, posX, posY, width, height, textureUp, textureDown,
1418 textureUpFocus, textureDownFocus, textureUpDisabled,
1419 textureDownDisabled, labelInfo, iType);
1421 CGUISpinControl* scontrol = static_cast<CGUISpinControl*>(control);
1422 scontrol->SetReverse(bReverse);
1424 if (iType == SPIN_CONTROL_TYPE_INT)
1426 scontrol->SetRange(iMin, iMax);
1428 else if (iType == SPIN_CONTROL_TYPE_PAGE)
1430 scontrol->SetRange(iMin, iMax);
1431 scontrol->SetShowRange(true);
1432 scontrol->SetReverse(false);
1433 scontrol->SetShowOnePage(showOnePage);
1435 else if (iType == SPIN_CONTROL_TYPE_FLOAT)
1437 scontrol->SetFloatRange(fMin, fMax);
1438 scontrol->SetFloatInterval(fInterval);
1441 break;
1443 case CGUIControl::GUICONTROL_SLIDER:
1445 control = new CGUISliderControl(
1446 parentID, id, posX, posY, width, height, textureBar, textureBarDisabled, textureNib,
1447 textureNibFocus, textureNibDisabled, SLIDER_CONTROL_TYPE_PERCENTAGE, orientation);
1449 static_cast<CGUISliderControl*>(control)->SetInfo(singleInfo);
1450 static_cast<CGUISliderControl*>(control)->SetAction(action);
1452 break;
1454 case CGUIControl::GUICONTROL_SETTINGS_SLIDER:
1456 control = new CGUISettingsSliderControl(
1457 parentID, id, posX, posY, width, height, sliderWidth, sliderHeight, textureFocus,
1458 textureNoFocus, textureBar, textureBarDisabled, textureNib, textureNibFocus,
1459 textureNibDisabled, labelInfo, SLIDER_CONTROL_TYPE_PERCENTAGE);
1461 static_cast<CGUISettingsSliderControl*>(control)->SetText(strLabel);
1462 static_cast<CGUISettingsSliderControl*>(control)->SetInfo(singleInfo);
1464 break;
1466 case CGUIControl::GUICONTROL_SCROLLBAR:
1468 control = new GUIScrollBarControl(parentID, id, posX, posY, width, height, textureBackground,
1469 textureBar, textureBarFocus, textureNib, textureNibFocus,
1470 orientation, showOnePage);
1471 break;
1473 case CGUIControl::GUICONTROL_PROGRESS:
1475 control =
1476 new CGUIProgressControl(parentID, id, posX, posY, width, height, textureBackground,
1477 textureLeft, textureMid, textureRight, textureOverlay, bReveal);
1479 static_cast<CGUIProgressControl*>(control)->SetInfo(singleInfo, singleInfo2);
1481 break;
1483 case CGUIControl::GUICONTROL_RANGES:
1485 control =
1486 new CGUIRangesControl(parentID, id, posX, posY, width, height, textureBackground,
1487 textureLeft, textureMid, textureRight, textureOverlay, singleInfo);
1488 break;
1490 case CGUIControl::GUICONTROL_IMAGE:
1492 // use a bordered texture if we have <bordersize> or <bordertexture> specified.
1493 if (borderTexture.filename.empty() && borderStr.empty())
1494 control = new CGUIImage(parentID, id, posX, posY, width, height, texture);
1495 else
1496 control = new CGUIBorderedImage(parentID, id, posX, posY, width, height, texture,
1497 borderTexture, borderSize);
1498 CGUIImage* icontrol = static_cast<CGUIImage*>(control);
1499 icontrol->SetInfo(textureFile);
1500 icontrol->SetAspectRatio(aspect);
1501 icontrol->SetCrossFade(fadeTime);
1503 break;
1505 case CGUIControl::GUICONTROL_MULTI_IMAGE:
1507 control = new CGUIMultiImage(parentID, id, posX, posY, width, height, texture, timePerImage,
1508 fadeTime, randomized, loop, timeToPauseAtEnd);
1509 static_cast<CGUIMultiImage*>(control)->SetInfo(texturePath);
1510 static_cast<CGUIMultiImage*>(control)->SetAspectRatio(aspect);
1512 break;
1514 case CGUIControl::GUICONTAINER_LIST:
1516 CScroller scroller;
1517 GetScroller(pControlNode, "scrolltime", scroller);
1519 control = new CGUIListContainer(parentID, id, posX, posY, width, height, orientation,
1520 scroller, preloadItems);
1521 CGUIListContainer* lcontrol = static_cast<CGUIListContainer*>(control);
1522 lcontrol->LoadLayout(pControlNode);
1523 lcontrol->LoadListProvider(pControlNode, defaultControl, defaultAlways);
1524 lcontrol->SetType(viewType, viewLabel);
1525 lcontrol->SetPageControl(pageControl);
1526 lcontrol->SetRenderOffset(offset);
1527 lcontrol->SetAutoScrolling(pControlNode);
1528 lcontrol->SetClickActions(clickActions);
1529 lcontrol->SetFocusActions(focusActions);
1530 lcontrol->SetUnFocusActions(unfocusActions);
1532 break;
1534 case CGUIControl::GUICONTAINER_WRAPLIST:
1536 CScroller scroller;
1537 GetScroller(pControlNode, "scrolltime", scroller);
1539 control = new CGUIWrappingListContainer(parentID, id, posX, posY, width, height, orientation,
1540 scroller, preloadItems, focusPosition);
1541 CGUIWrappingListContainer* wcontrol = static_cast<CGUIWrappingListContainer*>(control);
1542 wcontrol->LoadLayout(pControlNode);
1543 wcontrol->LoadListProvider(pControlNode, defaultControl, defaultAlways);
1544 wcontrol->SetType(viewType, viewLabel);
1545 wcontrol->SetPageControl(pageControl);
1546 wcontrol->SetRenderOffset(offset);
1547 wcontrol->SetAutoScrolling(pControlNode);
1548 wcontrol->SetClickActions(clickActions);
1549 wcontrol->SetFocusActions(focusActions);
1550 wcontrol->SetUnFocusActions(unfocusActions);
1552 break;
1554 case CGUIControl::GUICONTAINER_EPGGRID:
1556 CGUIEPGGridContainer* epgGridContainer =
1557 new CGUIEPGGridContainer(parentID, id, posX, posY, width, height, orientation, scrollTime,
1558 preloadItems, timeBlocks, rulerUnit, textureProgressIndicator);
1559 control = epgGridContainer;
1560 epgGridContainer->LoadLayout(pControlNode);
1561 epgGridContainer->SetRenderOffset(offset);
1562 epgGridContainer->SetType(viewType, viewLabel);
1563 epgGridContainer->SetPageControl(pageControl);
1565 break;
1567 case CGUIControl::GUICONTAINER_FIXEDLIST:
1569 CScroller scroller;
1570 GetScroller(pControlNode, "scrolltime", scroller);
1572 control = new CGUIFixedListContainer(parentID, id, posX, posY, width, height, orientation,
1573 scroller, preloadItems, focusPosition, iMovementRange);
1574 CGUIFixedListContainer* fcontrol = static_cast<CGUIFixedListContainer*>(control);
1575 fcontrol->LoadLayout(pControlNode);
1576 fcontrol->LoadListProvider(pControlNode, defaultControl, defaultAlways);
1577 fcontrol->SetType(viewType, viewLabel);
1578 fcontrol->SetPageControl(pageControl);
1579 fcontrol->SetRenderOffset(offset);
1580 fcontrol->SetAutoScrolling(pControlNode);
1581 fcontrol->SetClickActions(clickActions);
1582 fcontrol->SetFocusActions(focusActions);
1583 fcontrol->SetUnFocusActions(unfocusActions);
1585 break;
1587 case CGUIControl::GUICONTAINER_PANEL:
1589 CScroller scroller;
1590 GetScroller(pControlNode, "scrolltime", scroller);
1592 control = new CGUIPanelContainer(parentID, id, posX, posY, width, height, orientation,
1593 scroller, preloadItems);
1594 CGUIPanelContainer* pcontrol = static_cast<CGUIPanelContainer*>(control);
1595 pcontrol->LoadLayout(pControlNode);
1596 pcontrol->LoadListProvider(pControlNode, defaultControl, defaultAlways);
1597 pcontrol->SetType(viewType, viewLabel);
1598 pcontrol->SetPageControl(pageControl);
1599 pcontrol->SetRenderOffset(offset);
1600 pcontrol->SetAutoScrolling(pControlNode);
1601 pcontrol->SetClickActions(clickActions);
1602 pcontrol->SetFocusActions(focusActions);
1603 pcontrol->SetUnFocusActions(unfocusActions);
1605 break;
1607 case CGUIControl::GUICONTROL_TEXTBOX:
1609 if (!strMonoFont.empty())
1611 labelInfoMono = labelInfo;
1612 labelInfoMono.font = g_fontManager.GetFont(strMonoFont);
1614 control = new CGUITextBox(parentID, id, posX, posY, width, height, labelInfo, scrollTime,
1615 strMonoFont.empty() ? nullptr : &labelInfoMono);
1617 CGUITextBox* tcontrol = static_cast<CGUITextBox*>(control);
1619 tcontrol->SetPageControl(pageControl);
1620 if (infoLabels.size())
1621 tcontrol->SetInfo(infoLabels[0]);
1622 tcontrol->SetAutoScrolling(pControlNode);
1623 tcontrol->SetMinHeight(minHeight);
1625 break;
1627 case CGUIControl::GUICONTROL_MOVER:
1629 control = new CGUIMoverControl(parentID, id, posX, posY, width, height, textureFocus,
1630 textureNoFocus, movingSpeedCfg);
1631 break;
1633 case CGUIControl::GUICONTROL_RESIZE:
1635 control = new CGUIResizeControl(parentID, id, posX, posY, width, height, textureFocus,
1636 textureNoFocus, movingSpeedCfg);
1637 break;
1639 case CGUIControl::GUICONTROL_SPINEX:
1641 control = new CGUISpinControlEx(parentID, id, posX, posY, width, height, spinWidth,
1642 spinHeight, labelInfo, textureFocus, textureNoFocus,
1643 textureUp, textureDown, textureUpFocus, textureDownFocus,
1644 textureUpDisabled, textureDownDisabled, labelInfo, iType);
1646 CGUISpinControlEx* scontrol = static_cast<CGUISpinControlEx*>(control);
1647 scontrol->SetSpinPosition(spinPosX);
1648 scontrol->SetText(strLabel);
1649 scontrol->SetReverse(bReverse);
1651 break;
1653 case CGUIControl::GUICONTROL_VISUALISATION:
1655 control = new CGUIVisualisationControl(parentID, id, posX, posY, width, height);
1656 break;
1658 case CGUIControl::GUICONTROL_RENDERADDON:
1660 control = new CGUIRenderingControl(parentID, id, posX, posY, width, height);
1661 break;
1663 case CGUIControl::GUICONTROL_GAMECONTROLLER:
1665 control = new GAME::CGUIGameController(parentID, id, posX, posY, width, height, texture);
1667 GAME::CGUIGameController* gcontrol = static_cast<GAME::CGUIGameController*>(control);
1669 // Set texture
1670 gcontrol->SetInfo(textureFile);
1672 // Set aspect ratio
1673 gcontrol->SetAspectRatio(aspect);
1675 // Set controller ID
1676 GUIINFO::CGUIInfoLabel controllerId;
1677 GetInfoLabel(pControlNode, "controllerid", controllerId, parentID);
1678 gcontrol->SetControllerID(controllerId);
1680 // Set controller address
1681 GUIINFO::CGUIInfoLabel controllerAddress;
1682 GetInfoLabel(pControlNode, "controlleraddress", controllerAddress, parentID);
1683 gcontrol->SetControllerAddress(controllerAddress);
1685 // Set controller diffuse color
1686 GUIINFO::CGUIInfoColor controllerDiffuse(0xFFFFFFFF);
1687 GetInfoColor(pControlNode, "controllerdiffuse", controllerDiffuse, parentID);
1688 gcontrol->SetControllerDiffuse(controllerDiffuse);
1690 // Set port address
1691 GUIINFO::CGUIInfoLabel portAddress;
1692 GetInfoLabel(pControlNode, "portaddress", portAddress, parentID);
1693 gcontrol->SetPortAddress(portAddress);
1695 // Set peripheral location
1696 GUIINFO::CGUIInfoLabel peripheralLocation;
1697 GetInfoLabel(pControlNode, "peripherallocation", peripheralLocation, parentID);
1698 gcontrol->SetPeripheralLocation(peripheralLocation);
1700 break;
1702 case CGUIControl::GUICONTROL_GAMECONTROLLERLIST:
1704 CScroller scroller;
1705 GetScroller(pControlNode, "scrolltime", scroller);
1707 control = new GAME::CGUIGameControllerList(parentID, id, posX, posY, width, height,
1708 orientation, labelInfo.align, scroller);
1710 GAME::CGUIGameControllerList* lcontrol = static_cast<GAME::CGUIGameControllerList*>(control);
1712 lcontrol->LoadLayout(pControlNode);
1713 lcontrol->LoadListProvider(pControlNode, defaultControl, defaultAlways);
1714 lcontrol->SetType(viewType, viewLabel);
1715 lcontrol->SetPageControl(pageControl);
1716 lcontrol->SetRenderOffset(offset);
1717 lcontrol->SetAutoScrolling(pControlNode);
1718 lcontrol->SetClickActions(clickActions);
1719 lcontrol->SetFocusActions(focusActions);
1720 lcontrol->SetUnFocusActions(unfocusActions);
1722 break;
1724 case CGUIControl::GUICONTROL_COLORBUTTON:
1726 control = new CGUIColorButtonControl(parentID, id, posX, posY, width, height, textureFocus,
1727 textureNoFocus, labelInfo, textureColorMask,
1728 textureColorDisabledMask);
1730 CGUIColorButtonControl* rcontrol = static_cast<CGUIColorButtonControl*>(control);
1731 rcontrol->SetLabel(strLabel);
1732 rcontrol->SetImageBoxColor(colorBox);
1733 rcontrol->SetColorDimensions(colorPosX, colorPosY, colorWidth, colorHeight);
1734 rcontrol->SetClickActions(clickActions);
1735 rcontrol->SetFocusActions(focusActions);
1736 rcontrol->SetUnFocusActions(unfocusActions);
1738 break;
1740 default:
1741 break;
1744 // things that apply to all controls
1745 if (control)
1747 control->SetHitRect(hitRect, hitColor);
1748 control->SetVisibleCondition(visibleCondition, allowHiddenFocus);
1749 control->SetEnableCondition(enableCondition);
1750 control->SetAnimations(animations);
1751 control->SetColorDiffuse(colorDiffuse);
1752 control->SetActions(actions);
1753 control->SetPulseOnSelect(bPulse);
1754 if (hasCamera)
1755 control->SetCamera(camera);
1756 control->SetStereoFactor(stereo);
1758 return control;