merge/sync with trunk. rev. 12385.
[xbmc:xbmc-antiquated.git] / guilib / GUIListItemLayout.cpp
1 #include "include.h"\r
2 #include "GUIListItemLayout.h"\r
3 #include "GUIListItem.h"\r
4 #include "GuiControlFactory.h"\r
5 #include "GUIFontManager.h"\r
6 #include "XMLUtils.h"\r
7 #include "SkinInfo.h"\r
8 #include "../xbmc/utils/GUIInfoManager.h"\r
9 #include "../xbmc/utils/CharsetConverter.h"\r
10 #include "../xbmc/FileItem.h"\r
11 \r
12 using namespace std;\r
13 \r
14 CGUIListItemLayout::CListBase::CListBase()\r
15 {\r
16 }\r
17 \r
18 CGUIListItemLayout::CListBase::~CListBase()\r
19 {\r
20 }\r
21 \r
22 CGUIListItemLayout::CListLabel::CListLabel(float posX, float posY, float width, float height, int visibleCondition, const CLabelInfo &label, bool alwaysScroll, const CGUIInfoLabel &content, const vector<CAnimation> &animations)\r
23 : CGUIListItemLayout::CListBase(),\r
24   m_label(0, 0, posX, posY, width, height, label, alwaysScroll)\r
25 {\r
26   m_type = LIST_LABEL;\r
27   m_label.SetAnimations(animations);\r
28   m_info = content;\r
29   m_label.SetVisibleCondition(visibleCondition, false);\r
30 }\r
31 \r
32 CGUIListItemLayout::CListLabel::~CListLabel()\r
33 {\r
34 }\r
35 \r
36 CGUIListItemLayout::CListSelectLabel::CListSelectLabel(float posX, float posY, float width, float height, int visibleCondition, const CImage &imageFocus, const CImage &imageNoFocus, const CLabelInfo &label, const CGUIInfoLabel &content, const vector<CAnimation> &animations)\r
37 : CGUIListItemLayout::CListBase(),\r
38   m_label(0, 0, posX, posY, width, height, imageFocus, imageNoFocus, label, CGUIInfoLabel(""))\r
39 {\r
40   m_type = LIST_SELECT_LABEL;\r
41   m_info = content;\r
42   m_label.SetAnimations(animations);\r
43   m_label.SetVisibleCondition(visibleCondition, false);\r
44 }\r
45 \r
46 CGUIListItemLayout::CListSelectLabel::~CListSelectLabel()\r
47 {\r
48 }\r
49 \r
50 \r
51 CGUIListItemLayout::CListTexture::CListTexture(float posX, float posY, float width, float height, int visibleCondition, const CImage &image, const CImage &borderImage, const FRECT &borderSize, const CGUIImage::CAspectRatio &aspectRatio, const CGUIInfoColor &colorDiffuse, const vector<CAnimation> &animations)\r
52 : CGUIListItemLayout::CListBase(),\r
53   m_image(0, 0, posX, posY, width, height, image, borderImage, borderSize)\r
54 {\r
55   m_type = LIST_TEXTURE;\r
56   m_image.SetAspectRatio(aspectRatio);\r
57   m_image.SetAnimations(animations);\r
58   m_image.SetColorDiffuse(colorDiffuse);\r
59   m_image.SetVisibleCondition(visibleCondition, false);\r
60 }\r
61 \r
62 CGUIListItemLayout::CListTexture::~CListTexture()\r
63 {\r
64   m_image.FreeResources();\r
65 }\r
66 \r
67 CGUIListItemLayout::CListImage::CListImage(float posX, float posY, float width, float height, int visibleCondition, const CImage &image, const CImage &borderImage, const FRECT &borderSize, const CGUIImage::CAspectRatio &aspectRatio, const CGUIInfoColor &colorDiffuse, const CGUIInfoLabel &content, const vector<CAnimation> &animations)\r
68 : CGUIListItemLayout::CListTexture(posX, posY, width, height, visibleCondition, image, borderImage, borderSize, aspectRatio, colorDiffuse, animations)\r
69 {\r
70   m_info = content;\r
71   m_type = LIST_IMAGE;\r
72 }\r
73 \r
74 CGUIListItemLayout::CListImage::~CListImage()\r
75 {\r
76 }\r
77 \r
78 CGUIListItemLayout::CGUIListItemLayout()\r
79 {\r
80   m_width = 0;\r
81   m_height = 0;\r
82   m_condition = 0;\r
83   m_focused = false;\r
84   m_invalidated = true;\r
85   m_isPlaying = false;\r
86 }\r
87 \r
88 CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout &from)\r
89 {\r
90   m_width = from.m_width;\r
91   m_height = from.m_height;\r
92   m_focused = from.m_focused;\r
93   m_condition = from.m_condition;\r
94   // copy across our controls\r
95   for (ciControls it = from.m_controls.begin(); it != from.m_controls.end(); ++it)\r
96   {\r
97     CListBase *item = *it;\r
98     if (item->m_type == CListBase::LIST_LABEL)\r
99       m_controls.push_back(new CListLabel(*(CListLabel *)item));\r
100     else if (item->m_type ==  CListBase::LIST_IMAGE)\r
101       m_controls.push_back(new CListImage(*(CListImage *)item));\r
102     else if (item->m_type ==  CListBase::LIST_TEXTURE)\r
103       m_controls.push_back(new CListTexture(*(CListTexture *)item));\r
104     else if (item->m_type == CListBase::LIST_SELECT_LABEL)\r
105       m_controls.push_back(new CListSelectLabel(*(CListSelectLabel *)item));\r
106   }\r
107   m_invalidated = true;\r
108   m_isPlaying = false;\r
109 }\r
110 \r
111 CGUIListItemLayout::~CGUIListItemLayout()\r
112 {\r
113   for (iControls it = m_controls.begin(); it != m_controls.end(); ++it)\r
114     delete *it;\r
115 }\r
116 \r
117 float CGUIListItemLayout::Size(ORIENTATION orientation) const\r
118 {\r
119   return (orientation == HORIZONTAL) ? m_width : m_height;\r
120 }\r
121 \r
122 bool CGUIListItemLayout::IsAnimating(ANIMATION_TYPE animType)\r
123 {\r
124   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
125   {\r
126     CListBase *layoutItem = *it;\r
127     if (layoutItem->m_type == CListBase::LIST_LABEL)\r
128     {\r
129       CGUIListLabel &label = ((CListLabel *)layoutItem)->m_label;\r
130       if (label.IsAnimating(animType))\r
131         return true;\r
132     }\r
133     else if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
134     {\r
135       if (((CListSelectLabel *)layoutItem)->m_label.IsAnimating(animType))\r
136         return true;\r
137     }\r
138     else\r
139     {\r
140       if (((CListTexture *)layoutItem)->m_image.IsAnimating(animType))\r
141         return true;\r
142     }\r
143   }\r
144   return false;\r
145 }\r
146 \r
147 void CGUIListItemLayout::ResetAnimation(ANIMATION_TYPE animType)\r
148 {\r
149   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
150   {\r
151     CListBase *layoutItem = *it;\r
152     if (layoutItem->m_type == CListBase::LIST_LABEL)\r
153     {\r
154       CGUIListLabel &label = ((CListLabel *)layoutItem)->m_label;\r
155       label.ResetAnimation(animType);\r
156     }\r
157     else if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
158     {\r
159       ((CListSelectLabel *)layoutItem)->m_label.ResetAnimation(animType);\r
160     }\r
161     else\r
162     {\r
163       ((CListTexture *)layoutItem)->m_image.ResetAnimation(animType);\r
164     }\r
165   }\r
166 }\r
167 \r
168 void CGUIListItemLayout::Render(CGUIListItem *item, DWORD parentID, DWORD time)\r
169 {\r
170   if (m_invalidated)\r
171   { // need to update our item\r
172     // could use a dynamic cast here if RTTI was enabled.  As it's not,\r
173     // let's use a static cast with a virtual base function\r
174     CFileItem *fileItem = item->IsFileItem() ? (CFileItem *)item : new CFileItem(*item);\r
175     Update(fileItem, parentID);\r
176     // delete our temporary fileitem\r
177     if (!item->IsFileItem())\r
178       delete fileItem;\r
179   }\r
180 \r
181   // and render\r
182   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
183   {\r
184     CListBase *layoutItem = *it;\r
185     if (layoutItem->m_type == CListBase::LIST_LABEL)\r
186     {\r
187       CGUIListLabel &label = ((CListLabel *)layoutItem)->m_label;\r
188       label.SetSelected(item->IsSelected() || m_isPlaying);\r
189       label.SetScrolling(m_focused);\r
190       label.UpdateVisibility(item);\r
191       label.DoRender(time);\r
192     }\r
193     else if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
194     {\r
195       ((CListSelectLabel *)layoutItem)->m_label.UpdateVisibility(item);\r
196       ((CListSelectLabel *)layoutItem)->m_label.DoRender(time);\r
197     }\r
198     else\r
199     {\r
200       ((CListTexture *)layoutItem)->m_image.UpdateVisibility(item);\r
201       ((CListTexture *)layoutItem)->m_image.DoRender(time);\r
202     }\r
203   }\r
204 }\r
205 \r
206 void CGUIListItemLayout::Update(CFileItem *item, DWORD parentID)\r
207 {\r
208   // check for boolean conditions\r
209   m_isPlaying = g_infoManager.GetBool(LISTITEM_ISPLAYING, parentID, item);\r
210   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
211     UpdateItem(*it, item, parentID);\r
212   // now we have to check our overlapping label pairs\r
213   for (unsigned int i = 0; i < m_controls.size(); i++)\r
214   {\r
215     if (m_controls[i]->m_type == CListBase::LIST_LABEL && ((CListLabel *)m_controls[i])->m_label.IsVisible())\r
216     {\r
217       CGUIListLabel &label1 = ((CListLabel *)m_controls[i])->m_label;\r
218       CRect rect1(label1.GetRenderRect());\r
219       for (unsigned int j = i + 1; j < m_controls.size(); j++)\r
220       {\r
221         if (m_controls[j]->m_type == CListBase::LIST_LABEL && ((CListLabel *)m_controls[j])->m_label.IsVisible())\r
222         { // ok, now check if they overlap\r
223           CGUIListLabel &label2 = ((CListLabel *)m_controls[j])->m_label;\r
224           if (!rect1.Intersect(label2.GetRenderRect()).IsEmpty())\r
225           { // overlap vertically and horizontally - check alignment\r
226             CGUIListLabel &left = label1.GetRenderRect().x1 < label2.GetRenderRect().x1 ? label1 : label2;\r
227             CGUIListLabel &right = label1.GetRenderRect().x1 < label2.GetRenderRect().x1 ? label2 : label1;\r
228             if ((left.GetLabelInfo().align & 3) == 0 && right.GetLabelInfo().align & XBFONT_RIGHT)\r
229             {\r
230               float chopPoint = (left.GetXPosition() + left.GetWidth() + right.GetXPosition() - right.GetWidth()) * 0.5f;\r
231 // [1       [2...[2  1].|..........1]         2]\r
232 // [1       [2.....[2   |      1]..1]         2]\r
233 // [1       [2..........|.[2   1]..1]         2]\r
234               CRect leftRect(left.GetRenderRect());\r
235               CRect rightRect(right.GetRenderRect());\r
236               if (rightRect.x1 > chopPoint)\r
237                 chopPoint = rightRect.x1 - 5;\r
238               else if (leftRect.x2 < chopPoint)\r
239                 chopPoint = leftRect.x2 + 5;\r
240               leftRect.x2 = chopPoint - 5;\r
241               rightRect.x1 = chopPoint + 5;\r
242               left.SetRenderRect(leftRect);\r
243               right.SetRenderRect(rightRect);\r
244             }\r
245           }\r
246         }\r
247       }\r
248     }\r
249   }\r
250   m_invalidated = false;\r
251 }\r
252 \r
253 void CGUIListItemLayout::UpdateItem(CGUIListItemLayout::CListBase *control, CFileItem *item, DWORD parentID)\r
254 {\r
255   if (control->m_type == CListBase::LIST_IMAGE && item)\r
256   {\r
257     CListImage *image = (CListImage *)control;\r
258     if (!image->m_info.IsConstant())\r
259       image->m_image.SetFileName(image->m_info.GetItemLabel(item, true));\r
260   }\r
261   else if (control->m_type == CListBase::LIST_LABEL)\r
262   {\r
263     CListLabel *label = (CListLabel *)control;\r
264     label->m_label.SetLabel(label->m_info.GetItemLabel(item));\r
265   }\r
266   else if (control->m_type == CListBase::LIST_SELECT_LABEL)\r
267   {\r
268     CListSelectLabel *label = (CListSelectLabel *)control;\r
269     label->m_label.UpdateText(label->m_info.GetItemLabel(item));\r
270   }\r
271 }\r
272 \r
273 void CGUIListItemLayout::ResetScrolling()\r
274 {\r
275   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
276   {\r
277     CListBase *layoutItem = (*it);\r
278     if (layoutItem->m_type == CListBase::LIST_LABEL)\r
279       ((CListLabel *)layoutItem)->m_label.SetScrolling(false);\r
280   }\r
281 }\r
282 \r
283 void CGUIListItemLayout::SetFocus(unsigned int focus)\r
284 {\r
285   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
286   {\r
287     CListBase *layoutItem = (*it);\r
288     if (layoutItem->m_type == CListBase::LIST_IMAGE ||\r
289         layoutItem->m_type == CListBase::LIST_TEXTURE)\r
290       ((CListTexture *)layoutItem)->m_image.SetFocus(focus > 0);\r
291     else if (layoutItem->m_type == CListBase::LIST_LABEL)\r
292       ((CListLabel *)layoutItem)->m_label.SetFocus(focus > 0);\r
293     else if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
294       ((CListSelectLabel *)layoutItem)->m_label.SetFocusedItem(focus);\r
295   }\r
296 }\r
297 \r
298 unsigned int CGUIListItemLayout::GetFocus() const\r
299 {\r
300   for (vector<CListBase*>::const_iterator it = m_controls.begin(); it != m_controls.end(); it++)\r
301   {\r
302     CListBase *layoutItem = (*it);\r
303     if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
304       return ((CListSelectLabel *)layoutItem)->m_label.GetFocusedItem();\r
305   }\r
306   return 0;\r
307 }\r
308 \r
309 void CGUIListItemLayout::SelectItemFromPoint(const CPoint &point)\r
310 {\r
311   for (vector<CListBase*>::const_iterator it = m_controls.begin(); it != m_controls.end(); it++)\r
312   {\r
313     CListBase *layoutItem = (*it);\r
314     if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
315       return ((CListSelectLabel *)layoutItem)->m_label.SelectItemFromPoint(point);\r
316   }\r
317 }\r
318 \r
319 bool CGUIListItemLayout::MoveLeft()\r
320 {\r
321   for (vector<CListBase*>::const_iterator it = m_controls.begin(); it != m_controls.end(); it++)\r
322   {\r
323     CListBase *layoutItem = (*it);\r
324     if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
325       return ((CListSelectLabel *)layoutItem)->m_label.MoveLeft();\r
326   }\r
327   return false;\r
328 }\r
329 \r
330 bool CGUIListItemLayout::MoveRight()\r
331 {\r
332   for (vector<CListBase*>::const_iterator it = m_controls.begin(); it != m_controls.end(); it++)\r
333   {\r
334     CListBase *layoutItem = (*it);\r
335     if (layoutItem->m_type == CListBase::LIST_SELECT_LABEL)\r
336       return ((CListSelectLabel *)layoutItem)->m_label.MoveRight();\r
337   }\r
338   return false;\r
339 }\r
340 \r
341 CGUIListItemLayout::CListBase *CGUIListItemLayout::CreateItem(TiXmlElement *child)\r
342 {\r
343   // resolve any <include> tag's in this control\r
344   g_SkinInfo.ResolveIncludes(child);\r
345 \r
346   // grab the type...\r
347   CStdString type = CGUIControlFactory::GetType(child);\r
348 \r
349   // resolve again with strType set so that <default> tags are added\r
350   g_SkinInfo.ResolveIncludes(child, type);\r
351 \r
352   float posX = 0;\r
353   float posY = 0;\r
354   float width = 10;\r
355   float height = 10;\r
356   CStdString infoString;\r
357   CImage image, borderImage;\r
358   CImage imageFocus, imageNoFocus;\r
359   FRECT borderSize = { 0, 0, 0, 0 };\r
360   CLabelInfo label;\r
361   CGUIControlFactory::GetFloat(child, "posx", posX);\r
362   CGUIControlFactory::GetFloat(child, "posy", posY);\r
363   CGUIControlFactory::GetFloat(child, "width", width);\r
364   CGUIControlFactory::GetFloat(child, "height", height);\r
365   XMLUtils::GetString(child, "info", infoString);\r
366   CGUIControlFactory::GetInfoColor(child, "textcolor", label.textColor);\r
367   CGUIControlFactory::GetInfoColor(child, "selectedcolor", label.selectedColor);\r
368   CGUIControlFactory::GetInfoColor(child, "shadowcolor", label.shadowColor);\r
369   CGUIControlFactory::GetInfoColor(child, "focusedcolor", label.focusedColor);\r
370   CStdString fontName;\r
371   XMLUtils::GetString(child, "font", fontName);\r
372   label.font = g_fontManager.GetFont(fontName);\r
373   CGUIControlFactory::GetTexture(child, "texture", image);\r
374   // reset the info file for this image as we want to handle the updating\r
375   // when items change, rather than every frame\r
376   if (!image.file.IsConstant())\r
377     image.file = CGUIInfoLabel("");\r
378   // and get the <info> tag for this as well if available (GetTexture doesn't handle <info>)\r
379   CGUIInfoLabel infoTexture;\r
380   CGUIControlFactory::GetInfoLabel(child, "texture", infoTexture);\r
381   CGUIControlFactory::GetTexture(child, "texturefocus", imageFocus);\r
382   CGUIControlFactory::GetTexture(child, "texturenofocus", imageNoFocus);\r
383   CGUIControlFactory::GetAlignment(child, "align", label.align);\r
384   FRECT rect = { posX, posY, width, height };\r
385   vector<CAnimation> animations;\r
386   CGUIControlFactory::GetAnimations(child, rect, animations);\r
387   CGUIInfoColor colorDiffuse(0xffffffff);\r
388   CGUIControlFactory::GetInfoColor(child, "colordiffuse", colorDiffuse);\r
389   DWORD alignY = 0;\r
390   if (CGUIControlFactory::GetAlignmentY(child, "aligny", alignY))\r
391     label.align |= alignY;\r
392   CGUIInfoLabel infoLabel;\r
393   CGUIControlFactory::GetInfoLabel(child, "label", infoLabel);\r
394   CGUIImage::CAspectRatio aspectRatio(CGUIImage::CAspectRatio::AR_KEEP);\r
395   CGUIControlFactory::GetAspectRatio(child, "aspectratio", aspectRatio);\r
396   int visibleCondition = 0;\r
397   CGUIControlFactory::GetConditionalVisibility(child, visibleCondition);\r
398   XMLUtils::GetFloat(child, "angle", label.angle); label.angle *= -1;\r
399   bool scroll(false);\r
400   XMLUtils::GetBoolean(child, "scroll", scroll);\r
401   CGUIControlFactory::GetTexture(child, "bordertexture", borderImage);\r
402   CStdString borderStr;\r
403   if (XMLUtils::GetString(child, "bordersize", borderStr))\r
404     CGUIControlFactory::GetRectFromString(borderStr, borderSize);\r
405   if (type == "label")\r
406   { // info label\r
407     return new CListLabel(posX, posY, width, height, visibleCondition, label, scroll, infoLabel, animations);\r
408   }\r
409   else if (type == "multiselect")\r
410   {\r
411     return new CListSelectLabel(posX, posY, width, height, visibleCondition, imageFocus, imageNoFocus, label, infoLabel, animations);\r
412   }\r
413   else if (type == "image")\r
414   {\r
415     if (!infoTexture.IsConstant())\r
416       return new CListImage(posX, posY, width, height, visibleCondition, image, borderImage, borderSize, aspectRatio, colorDiffuse, infoTexture, animations);\r
417     else\r
418     {\r
419       // Due to old behaviour, we force aspectratio to stretch here\r
420       aspectRatio.ratio = CGUIImage::CAspectRatio::AR_STRETCH;\r
421       return new CListTexture(posX, posY, width, height, visibleCondition, image, borderImage, borderSize, aspectRatio, colorDiffuse, animations);\r
422     }\r
423   }\r
424   return NULL;\r
425 }\r
426 \r
427 void CGUIListItemLayout::LoadLayout(TiXmlElement *layout, bool focused)\r
428 {\r
429   m_focused = focused;\r
430   g_SkinInfo.ResolveConstant(layout->Attribute("width"), m_width);\r
431   g_SkinInfo.ResolveConstant(layout->Attribute("height"), m_height);\r
432   const char *condition = layout->Attribute("condition");\r
433   if (condition)\r
434     m_condition = g_infoManager.TranslateString(condition);\r
435   TiXmlElement *child = layout->FirstChildElement("control");\r
436   while (child)\r
437   {\r
438     CListBase *item = CreateItem(child);\r
439     if (item)\r
440       m_controls.push_back(item);\r
441     child = child->NextSiblingElement("control");\r
442   }\r
443 }\r
444 \r
445 //#ifdef PRE_SKIN_VERSION_2_1_COMPATIBILITY\r
446 void CGUIListItemLayout::CreateListControlLayouts(float width, float height, bool focused, const CLabelInfo &labelInfo, const CLabelInfo &labelInfo2, const CImage &texture, const CImage &textureFocus, float texHeight, float iconWidth, float iconHeight, int nofocusCondition, int focusCondition)\r
447 {\r
448   m_width = width;\r
449   m_height = height;\r
450   m_focused = focused;\r
451   vector<CAnimation> blankAnims;\r
452   CImage border;\r
453   FRECT borderRect = { 0, 0, 0, 0 };\r
454   CListTexture *tex = new CListTexture(0, 0, width, texHeight, nofocusCondition, texture, border, borderRect, CGUIImage::CAspectRatio(), 0xffffffff, blankAnims);\r
455   m_controls.push_back(tex);\r
456   if (focused)\r
457   {\r
458     CListTexture *tex = new CListTexture(0, 0, width, texHeight, focusCondition, textureFocus, border, borderRect, CGUIImage::CAspectRatio(), 0xffffffff, blankAnims);\r
459     m_controls.push_back(tex);\r
460   }\r
461   CListImage *image = new CListImage(8, 0, iconWidth, texHeight, 0, CImage(""), border, borderRect, CGUIImage::CAspectRatio(CGUIImage::CAspectRatio::AR_KEEP), 0xffffffff, CGUIInfoLabel("$INFO[ListItem.Icon]"), blankAnims);\r
462   m_controls.push_back(image);\r
463   float x = iconWidth + labelInfo.offsetX + 10;\r
464   CListLabel *label = new CListLabel(x, labelInfo.offsetY, width - x - 18, height, 0, labelInfo, false, CGUIInfoLabel("$INFO[ListItem.Label]"), blankAnims);\r
465   m_controls.push_back(label);\r
466   x = labelInfo2.offsetX ? labelInfo2.offsetX : m_width - 16;\r
467   label = new CListLabel(x, labelInfo2.offsetY, x - iconWidth - 20, height, 0, labelInfo2, false, CGUIInfoLabel("$INFO[ListItem.Label2]"), blankAnims);\r
468   m_controls.push_back(label);\r
469 }\r
470 \r
471 void CGUIListItemLayout::CreateThumbnailPanelLayouts(float width, float height, bool focused, const CImage &image, float texWidth, float texHeight, float thumbPosX, float thumbPosY, float thumbWidth, float thumbHeight, DWORD thumbAlign, const CGUIImage::CAspectRatio &thumbAspect, const CLabelInfo &labelInfo, bool hideLabels)\r
472 {\r
473   m_width = width;\r
474   m_height = height;\r
475   m_focused = focused;\r
476   float centeredPosX = (m_width - texWidth)*0.5f;\r
477   CImage border;\r
478   FRECT borderRect = { 0, 0, 0, 0 };\r
479   // background texture\r
480   vector<CAnimation> blankAnims;\r
481   CListTexture *tex = new CListTexture(centeredPosX, 0, texWidth, texHeight, 0, image, border, borderRect, CGUIImage::CAspectRatio(), 0xffffffff, blankAnims);\r
482   m_controls.push_back(tex);\r
483   // thumbnail\r
484   float xOff = 0;\r
485   float yOff = 0;\r
486   if (thumbAlign != 0)\r
487   {\r
488     xOff += (texWidth - thumbWidth) * 0.5f;\r
489     yOff += (texHeight - thumbHeight) * 0.5f;\r
490     //if thumbPosX or thumbPosX != 0 the thumb will be bumped off-center\r
491   }\r
492   CListImage *thumb = new CListImage(thumbPosX + centeredPosX + xOff, thumbPosY + yOff, thumbWidth, thumbHeight, 0, CImage(""), border, borderRect, thumbAspect, 0xffffffff, CGUIInfoLabel("$INFO[ListItem.Icon]"), blankAnims);\r
493   m_controls.push_back(thumb);\r
494   // overlay\r
495   CListImage *overlay = new CListImage(thumbPosX + centeredPosX + xOff + thumbWidth - 32, thumbPosY + yOff + thumbHeight - 32, 32, 32, 0, CImage(""), border, borderRect, thumbAspect, 0xffffffff, CGUIInfoLabel("$INFO[ListItem.Overlay]"), blankAnims);\r
496   m_controls.push_back(overlay);\r
497   // label\r
498   if (hideLabels) return;\r
499   CListLabel *label = new CListLabel(width*0.5f, texHeight, width, height, 0, labelInfo, false, CGUIInfoLabel("$INFO[ListItem.Label]"), blankAnims);\r
500   m_controls.push_back(label);\r
501 }\r
502 //#endif\r
503 \r
504 #ifdef _DEBUG\r
505 void CGUIListItemLayout::DumpTextureUse()\r
506 {\r
507   for (iControls it = m_controls.begin(); it != m_controls.end(); it++)\r
508   {\r
509     CListBase *layoutItem = (*it);\r
510     if (layoutItem->m_type == CListBase::LIST_IMAGE || layoutItem->m_type == CListBase::LIST_TEXTURE)\r
511       ((CListTexture *)layoutItem)->m_image.DumpTextureUse();\r
512   }\r
513 }\r
514 #endif\r