1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "GUIListGroup.h"
10 
11 #include "GUIListLabel.h"
12 #include "utils/log.h"
13 
CGUIListGroup(int parentID,int controlID,float posX,float posY,float width,float height)14 CGUIListGroup::CGUIListGroup(int parentID, int controlID, float posX, float posY, float width, float height)
15 : CGUIControlGroup(parentID, controlID, posX, posY, width, height)
16 {
17   m_item = NULL;
18   ControlType = GUICONTROL_LISTGROUP;
19 }
20 
CGUIListGroup(const CGUIListGroup & right)21 CGUIListGroup::CGUIListGroup(const CGUIListGroup &right)
22 : CGUIControlGroup(right)
23 {
24   m_item = NULL;
25   ControlType = GUICONTROL_LISTGROUP;
26 }
27 
~CGUIListGroup(void)28 CGUIListGroup::~CGUIListGroup(void)
29 {
30   FreeResources();
31 }
32 
AddControl(CGUIControl * control,int position)33 void CGUIListGroup::AddControl(CGUIControl *control, int position /*= -1*/)
34 {
35   if (control)
36   {
37     if (!(control->GetControlType() == CGUIControl::GUICONTROL_LISTLABEL ||
38           control->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP ||
39           control->GetControlType() == CGUIControl::GUICONTROL_IMAGE ||
40           control->GetControlType() == CGUIControl::GUICONTROL_BORDEREDIMAGE ||
41           control->GetControlType() == CGUIControl::GUICONTROL_MULTI_IMAGE ||
42           control->GetControlType() == CGUIControl::GUICONTROL_TEXTBOX ||
43           control->GetControlType() == CGUIControl::GUICONTROL_PROGRESS))
44       CLog::Log(LOGWARNING, "Trying to add unsupported control type %d", control->GetControlType());
45   }
46   CGUIControlGroup::AddControl(control, position);
47 }
48 
Process(unsigned int currentTime,CDirtyRegionList & dirtyregions)49 void CGUIListGroup::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
50 {
51   CServiceBroker::GetWinSystem()->GetGfxContext().SetOrigin(m_posX, m_posY);
52 
53   CRect rect;
54   for (iControls it = m_children.begin(); it != m_children.end(); ++it)
55   {
56     CGUIControl *control = *it;
57     control->UpdateVisibility(m_item);
58     unsigned int oldDirty = dirtyregions.size();
59     control->DoProcess(currentTime, dirtyregions);
60     if (control->IsVisible() || (oldDirty != dirtyregions.size())) // visible or dirty (was visible?)
61       rect.Union(control->GetRenderRegion());
62   }
63 
64   CServiceBroker::GetWinSystem()->GetGfxContext().RestoreOrigin();
65   CGUIControl::Process(currentTime, dirtyregions);
66   m_renderRegion = rect;
67   m_item = NULL;
68 }
69 
ResetAnimation(ANIMATION_TYPE type)70 void CGUIListGroup::ResetAnimation(ANIMATION_TYPE type)
71 {
72   CGUIControl::ResetAnimation(type);
73   for (iControls it = m_children.begin(); it != m_children.end(); ++it)
74     (*it)->ResetAnimation(type);
75 }
76 
UpdateVisibility(const CGUIListItem * item)77 void CGUIListGroup::UpdateVisibility(const CGUIListItem *item)
78 {
79   CGUIControlGroup::UpdateVisibility(item);
80   m_item = item;
81 }
82 
UpdateInfo(const CGUIListItem * item)83 void CGUIListGroup::UpdateInfo(const CGUIListItem *item)
84 {
85   for (iControls it = m_children.begin(); it != m_children.end(); it++)
86   {
87     (*it)->UpdateInfo(item);
88     (*it)->UpdateVisibility(item);
89   }
90   // now we have to check our overlapping label pairs
91   for (unsigned int i = 0; i < m_children.size(); i++)
92   {
93     if (m_children[i]->GetControlType() == CGUIControl::GUICONTROL_LISTLABEL && m_children[i]->IsVisible())
94     {
95       for (unsigned int j = i + 1; j < m_children.size(); j++)
96       {
97         if (m_children[j]->GetControlType() == CGUIControl::GUICONTROL_LISTLABEL && m_children[j]->IsVisible())
98           CGUIListLabel::CheckAndCorrectOverlap(*static_cast<CGUIListLabel*>(m_children[i]), *static_cast<CGUIListLabel*>(m_children[j]));
99       }
100     }
101   }
102 }
103 
EnlargeWidth(float difference)104 void CGUIListGroup::EnlargeWidth(float difference)
105 {
106   // Alters the width of the controls that have an ID of 1 to 14
107   for (iControls it = m_children.begin(); it != m_children.end(); it++)
108   {
109     CGUIControl *child = *it;
110     if (child->GetID() >= 1 && child->GetID() <= 14)
111     {
112       if (child->GetID() == 1)
113       {
114         child->SetWidth(child->GetWidth() + difference);
115         child->SetVisible(child->GetWidth() > 10);
116       }
117       else
118       {
119         child->SetWidth(child->GetWidth() + difference);
120       }
121     }
122   }
123   SetInvalid();
124 }
125 
EnlargeHeight(float difference)126 void CGUIListGroup::EnlargeHeight(float difference)
127 {
128   // Alters the height of the controls that have an ID of 1 to 14
129   for (iControls it = m_children.begin(); it != m_children.end(); it++)
130   {
131     CGUIControl *child = *it;
132     if (child->GetID() >= 1 && child->GetID() <= 14)
133     {
134       if (child->GetID() == 1)
135       {
136         child->SetHeight(child->GetHeight() + difference);
137         child->SetVisible(child->GetHeight() > 10);
138       }
139       else
140       {
141         child->SetHeight(child->GetHeight() + difference);
142       }
143     }
144   }
145   SetInvalid();
146 }
147 
SetInvalid()148 void CGUIListGroup::SetInvalid()
149 {
150   if (!m_bInvalidated)
151   { // this can be triggered by an item change, so all children need invalidating rather than just the group
152     for (iControls it = m_children.begin(); it != m_children.end(); ++it)
153       (*it)->SetInvalid();
154     CGUIControlGroup::SetInvalid();
155   }
156 }
157 
SetFocusedItem(unsigned int focus)158 void CGUIListGroup::SetFocusedItem(unsigned int focus)
159 {
160   for (iControls it = m_children.begin(); it != m_children.end(); it++)
161   {
162     if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP)
163       ((CGUIListGroup *)(*it))->SetFocusedItem(focus);
164     else
165       (*it)->SetFocus(focus > 0);
166   }
167   SetFocus(focus > 0);
168 }
169 
GetFocusedItem() const170 unsigned int CGUIListGroup::GetFocusedItem() const
171 {
172   for (ciControls it = m_children.begin(); it != m_children.end(); it++)
173   {
174     if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP && ((CGUIListGroup *)(*it))->GetFocusedItem())
175       return ((CGUIListGroup *)(*it))->GetFocusedItem();
176   }
177   return m_bHasFocus ? 1 : 0;
178 }
179 
MoveLeft()180 bool CGUIListGroup::MoveLeft()
181 {
182   for (iControls it = m_children.begin(); it != m_children.end(); it++)
183   {
184     if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP && ((CGUIListGroup *)(*it))->MoveLeft())
185       return true;
186   }
187   return false;
188 }
189 
MoveRight()190 bool CGUIListGroup::MoveRight()
191 {
192   for (iControls it = m_children.begin(); it != m_children.end(); it++)
193   {
194     if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP && ((CGUIListGroup *)(*it))->MoveRight())
195       return true;
196   }
197   return false;
198 }
199 
SetState(bool selected,bool focused)200 void CGUIListGroup::SetState(bool selected, bool focused)
201 {
202   for (iControls it = m_children.begin(); it != m_children.end(); it++)
203   {
204     if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTLABEL)
205     {
206       CGUIListLabel *label = (CGUIListLabel *)(*it);
207       label->SetSelected(selected);
208     }
209     else if ((*it)->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP)
210       ((CGUIListGroup *)(*it))->SetState(selected, focused);
211   }
212 }
213 
SelectItemFromPoint(const CPoint & point)214 void CGUIListGroup::SelectItemFromPoint(const CPoint &point)
215 {
216   CPoint controlCoords(point);
217   m_transform.InverseTransformPosition(controlCoords.x, controlCoords.y);
218   for (iControls it = m_children.begin(); it != m_children.end(); ++it)
219   {
220     CGUIControl *child = *it;
221     if (child->GetControlType() == CGUIControl::GUICONTROL_LISTGROUP)
222       static_cast<CGUIListGroup*>(child)->SelectItemFromPoint(point);
223   }
224 }
225