2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
24 #include "../XBPythonDll.h"
25 #include "guilib/GUIListContainer.h"
26 #include "guilib/GUIFontManager.h"
27 #include "guilib/GUIWindowManager.h"
28 #include "guilib/GUILabel.h"
35 #pragma code_seg("PY_TEXT")
36 #pragma data_seg("PY_DATA")
37 #pragma bss_seg("PY_BSS")
38 #pragma const_seg("PY_RDATA")
47 extern PyObject* ControlSpin_New(void);
49 PyObject* ControlList_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
51 static const char *keywords[] = {
52 "x", "y", "width", "height", "font",
53 "textColor", "buttonTexture", "buttonFocusTexture",
54 // maintain order of above items for backward compatibility
56 "imageWidth", "imageHeight",
57 "itemTextXOffset", "itemTextYOffset",
58 "itemHeight", "space", "alignmentY", NULL };//"shadowColor", NULL };
61 char *cTextColor = NULL;
62 char *cSelectedColor = NULL;
63 char *cTextureButton = NULL;
64 char *cTextureButtonFocus = NULL;
65 //char* cShadowColor = NULL;
66 self = (ControlList*)type->tp_alloc(type, 0);
67 if (!self) return NULL;
68 new(&self->strFont) string();
69 new(&self->strTextureButton) string();
70 new(&self->strTextureButtonFocus) string();
71 new(&self->vecItems) std::vector<PYXBMC::ListItem*>();
73 // create a python spin control
74 self->pControlSpin = (ControlSpin*)ControlSpin_New();
75 if (!self->pControlSpin)
81 // initialize default values
82 self->strFont = "font13";
83 self->textColor = 0xe0f0f0f0;
84 self->selectedColor = 0xffffffff;
85 self->imageHeight = 10;
86 self->imageWidth = 10;
87 self->itemHeight = 27;
89 self->itemTextOffsetX = CONTROL_TEXT_OFFSET_X;
90 self->itemTextOffsetY = CONTROL_TEXT_OFFSET_Y;
91 self->alignmentY = XBFONT_CENTER_Y;
92 //self->shadowColor = NULL;
94 if (!PyArg_ParseTupleAndKeywords(
97 (char*)"llll|ssssslllllll",//s",
106 &cTextureButtonFocus,
110 &self->itemTextOffsetX,
111 &self->itemTextOffsetY,
121 // set specified values
122 if (cFont) self->strFont = cFont;
125 sscanf( cTextColor, "%x", &self->textColor );
129 sscanf( cSelectedColor, "%x", &self->selectedColor );
131 //if (cShadowColor) sscanf( cShadowColor, "%x", &self->shadowColor );
133 self->strTextureButton = cTextureButton ? cTextureButton :
134 PyXBMCGetDefaultImage((char*)"listcontrol", (char*)"texturenofocus", (char*)"list-nofocus.png");
135 self->strTextureButtonFocus = cTextureButtonFocus ? cTextureButtonFocus :
136 PyXBMCGetDefaultImage((char*)"listcontrol", (char*)"texturefocus", (char*)"list-focus.png");
138 // default values for spin control
139 self->pControlSpin->dwPosX = self->dwWidth - 35;
140 self->pControlSpin->dwPosY = self->dwHeight - 15;
142 return (PyObject*)self;
145 void ControlList_Dealloc(ControlList* self)
147 // conditionally delete spincontrol
148 Py_XDECREF(self->pControlSpin);
150 // delete all ListItem from vector
151 vector<ListItem*>::iterator it = self->vecItems.begin();
152 while (it != self->vecItems.end())
154 ListItem* pListItem = *it;
155 Py_DECREF(pListItem);
158 self->vecItems.clear();
159 self->vecItems.~vector();
161 self->strFont.~string();
162 self->strTextureButton.~string();
163 self->strTextureButtonFocus.~string();
165 self->ob_type->tp_free((PyObject*)self);
168 CGUIControl* ControlList_Create(ControlList* pControl)
171 label.align = pControl->alignmentY;
172 label.font = g_fontManager.GetFont(pControl->strFont);
173 label.textColor = label.focusedColor = pControl->textColor;
174 //label.shadowColor = pControl->shadowColor;
175 label.selectedColor = pControl->selectedColor;
176 label.offsetX = (float)pControl->itemTextOffsetX;
177 label.offsetY = (float)pControl->itemTextOffsetY;
178 // Second label should have the same font, alignment, and colours as the first, but
179 // the offsets should be 0.
180 CLabelInfo label2 = label;
181 label2.offsetX = label2.offsetY = 0;
182 label2.align |= XBFONT_RIGHT;
184 pControl->pGUIControl = new CGUIListContainer(
186 pControl->iControlId,
187 (float)pControl->dwPosX,
188 (float)pControl->dwPosY,
189 (float)pControl->dwWidth,
190 (float)pControl->dwHeight - pControl->pControlSpin->dwHeight - 5,
192 (CStdString)pControl->strTextureButton,
193 (CStdString)pControl->strTextureButtonFocus,
194 (float)pControl->itemHeight,
195 (float)pControl->imageWidth, (float)pControl->imageHeight,
196 (float)pControl->space);
198 return pControl->pGUIControl;
202 * ControlList_AddItem
203 * (string label) / (ListItem)
204 * ListItem is added to vector
205 * For a string we create a new ListItem and add it to the vector
207 PyDoc_STRVAR(addItem__doc__,
208 "addItem(item) -- Add a new item to this list control.\n"
210 "item : string, unicode or ListItem - item to add.\n"
213 " - cList.addItem('Reboot XBMC')\n");
215 PyObject* ControlList_AddItem(ControlList *self, PyObject *args)
218 if (!PyArg_ParseTuple(args, (char*)"O", &pObject)) return NULL;
220 ListItem* pListItem = NULL;
221 if (ListItem_CheckExact(pObject))
223 // object is a listitem
224 pListItem = (ListItem*)pObject;
225 Py_INCREF(pListItem);
230 // object is probably a text item
231 if (!PyXBMCGetUnicodeString(strText, pObject, 1)) return NULL;
232 // object is a unicode string now, create a new ListItem
233 pListItem = ListItem_FromString(strText);
236 // add item to objects vector
237 self->vecItems.push_back(pListItem);
239 // construct a CFileItemList to pass 'em on to the list
240 CGUIListItemPtr items(new CFileItemList());
241 for (unsigned int i = 0; i < self->vecItems.size(); i++)
242 ((CFileItemList*)items.get())->Add(self->vecItems[i]->item);
244 CGUIMessage msg(GUI_MSG_LABEL_BIND, self->iParentId, self->iControlId, 0, 0, items);
245 msg.SetPointer(items.get());
246 g_windowManager.SendThreadMessage(msg, self->iParentId);
252 PyDoc_STRVAR(addItems__doc__,
253 "addItems(items) -- Adds a list of listitems or strings to this list control.\n"
255 "items : List - list of strings, unicode objects or ListItems to add.\n"
257 "*Note, You can use the above as keywords for arguments.\n"
259 " Large lists benefit considerably, than using the standard addItem()"
262 " - cList.addItems(items=listitems)\n");
264 PyObject* ControlList_AddItems(ControlList *self, PyObject *args, PyObject *kwds)
266 PyObject *pList = NULL;
267 static const char *keywords[] = { "items", NULL };
269 if (!PyArg_ParseTupleAndKeywords(
274 &pList) || pList == NULL || !PyObject_TypeCheck(pList, &PyList_Type))
276 PyErr_SetString(PyExc_TypeError, "Object should be of type List");
280 CGUIListItemPtr items(new CFileItemList());
281 for (int item = 0; item < PyList_Size(pList); item++)
283 PyObject *pItem = PyList_GetItem(pList, item);
285 ListItem* pListItem = NULL;
286 if (ListItem_CheckExact(pItem))
288 // object is a listitem
289 pListItem = (ListItem*)pItem;
290 Py_INCREF(pListItem);
295 // object is probably a text item
296 if (!PyXBMCGetUnicodeString(strText, pItem, 1)) return NULL;
297 // object is a unicode string now, create a new ListItem
298 pListItem = ListItem_FromString(strText);
301 // add item to objects vector
302 self->vecItems.push_back(pListItem);
303 ((CFileItemList*)items.get())->Add(pListItem->item);
307 CGUIMessage msg(GUI_MSG_LABEL_BIND, self->iParentId, self->iControlId, 0, 0, items);
308 msg.SetPointer(items.get());
309 g_windowManager.SendThreadMessage(msg, self->iParentId);
316 * ControlList_SelectItem(int item)
317 * Select an item by index
319 PyDoc_STRVAR(selectItem,
320 "selectItem(item) -- Select an item by index number.\n"
322 "item : integer - index number of the item to select.\n"
325 " - cList.selectItem(12)\n");
327 PyObject* ControlList_SelectItem(ControlList *self, PyObject *args)
331 if (!PyArg_ParseTuple(args, (char*)"l", &itemIndex)) return NULL;
334 CGUIMessage msg(GUI_MSG_ITEM_SELECT, self->iParentId, self->iControlId, itemIndex);
337 g_windowManager.SendThreadMessage(msg, self->iParentId);
344 PyDoc_STRVAR(reset__doc__,
345 "reset() -- Clear all ListItems in this control list.\n"
348 " - cList.reset()\n");
350 PyObject* ControlList_Reset(ControlList *self, PyObject *args)
353 ControlList *pControl = (ControlList*)self;
354 CGUIMessage msg(GUI_MSG_LABEL_RESET, pControl->iParentId, pControl->iControlId);
356 g_windowManager.SendThreadMessage(msg, pControl->iParentId);
358 // delete all items from vector
359 // delete all ListItem from vector
360 vector<ListItem*>::iterator it = self->vecItems.begin();
361 while (it != self->vecItems.end())
363 ListItem* pListItem = *it;
364 Py_DECREF(pListItem);
367 self->vecItems.clear();
373 // getSpinControl() method
374 PyDoc_STRVAR(getSpinControl__doc__,
375 "getSpinControl() -- returns the associated ControlSpin object.\n"
377 "*Note, Not working completely yet -\n"
378 " After adding this control list to a window it is not possible to change\n"
379 " the settings of this spin control.\n"
382 " - ctl = cList.getSpinControl()\n");
384 PyObject* ControlList_GetSpinControl(ControlList *self, PyObject *args)
386 Py_INCREF(self->pControlSpin);
387 return (PyObject*)self->pControlSpin;
390 // setImageDimensions() method
391 PyDoc_STRVAR(setImageDimensions__doc__,
392 "setImageDimensions(imageWidth, imageHeight) -- Sets the width/height of items icon or thumbnail.\n"
394 "imageWidth : [opt] integer - width of items icon or thumbnail.\n"
395 "imageHeight : [opt] integer - height of items icon or thumbnail.\n"
398 " - cList.setImageDimensions(18, 18)\n");
400 PyObject* ControlList_SetImageDimensions(ControlList *self, PyObject *args)
402 if (!PyArg_ParseTuple(args, (char*)"ll", &self->imageWidth, &self->imageHeight))
409 if (self->pGUIControl)
411 CGUIListControl* pListControl = (CGUIListControl*) self->pGUIControl;
412 pListControl->SetImageDimensions((float)self->dwImageWidth, (float)self->dwImageHeight );
420 // setItemHeight() method
421 PyDoc_STRVAR(setItemHeight__doc__,
422 "setItemHeight(itemHeight) -- Sets the height of items.\n"
424 "itemHeight : integer - height of items.\n"
427 " - cList.setItemHeight(25)\n");
429 PyObject* ControlList_SetItemHeight(ControlList *self, PyObject *args)
431 if (!PyArg_ParseTuple(args, (char*)"l", &self->itemHeight)) return NULL;
435 if (self->pGUIControl)
437 CGUIListControl* pListControl = (CGUIListControl*) self->pGUIControl;
438 pListControl->SetItemHeight((float)self->dwItemHeight);
447 // setPageControlVisible() method
448 PyDoc_STRVAR(setPageControlVisible__doc__,
449 "setPageControlVisible(visible) -- Sets the spin control's visible/hidden state.\n"
451 "visible : boolean - True=visible / False=hidden.\n"
454 " - cList.setPageControlVisible(True)\n");
456 PyObject* ControlList_SetPageControlVisible(ControlList *self, PyObject *args)
460 if (!PyArg_ParseTuple(args, (char*)"b", &isOn)) return NULL;
464 if (self->pGUIControl)
466 ((CGUIListControl*)self->pGUIControl)->SetPageControlVisible((bool)isOn );
476 PyDoc_STRVAR(setSpace__doc__,
477 "setSpace(space) -- Set's the space between items.\n"
479 "space : [opt] integer - space between items.\n"
482 " - cList.setSpace(5)\n");
484 PyObject* ControlList_SetSpace(ControlList *self, PyObject *args)
486 if (!PyArg_ParseTuple(args, (char*)"l", &self->space)) return NULL;
490 if (self->pGUIControl)
492 CGUIListControl* pListControl = (CGUIListControl*) self->pGUIControl;
493 pListControl->SetSpaceBetweenItems((float)self->dwSpace);
502 // getSelectedPosition() method
503 PyDoc_STRVAR(getSelectedPosition__doc__,
504 "getSelectedPosition() -- Returns the position of the selected item as an integer.\n"
506 "*Note, Returns -1 for empty lists.\n"
509 " - pos = cList.getSelectedPosition()\n");
511 PyObject* ControlList_GetSelectedPosition(ControlList *self, PyObject *args)
514 ControlList *pControl = (ControlList*)self;
515 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, pControl->iParentId, pControl->iControlId);
520 if ((self->vecItems.size() > 0) && pControl->pGUIControl)
522 pControl->pGUIControl->OnMessage(msg);
523 pos = msg.GetParam1();
527 return Py_BuildValue((char*)"l", pos);
530 // getSelectedItem() method
531 PyDoc_STRVAR(getSelectedItem__doc__,
532 "getSelectedItem() -- Returns the selected item as a ListItem object.\n"
534 "*Note, Same as getSelectedPosition(), but instead of an integer a ListItem object\n"
535 " is returned. Returns None for empty lists.\n"
536 " See windowexample.py on how to use this.\n"
539 " - item = cList.getSelectedItem()\n");
541 PyObject* ControlList_GetSelectedItem(ControlList *self, PyObject *args)
544 ControlList *pControl = (ControlList*)self;
545 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, pControl->iParentId, pControl->iControlId);
546 PyObject* pListItem = Py_None;
550 if ((self->vecItems.size() > 0) && pControl->pGUIControl)
552 pControl->pGUIControl->OnMessage(msg);
553 pListItem = (PyObject*)self->vecItems[msg.GetParam1()];
557 Py_INCREF(pListItem);
562 PyDoc_STRVAR(size__doc__,
563 "size() -- Returns the total number of items in this list control as an integer.\n"
566 " - cnt = cList.size()\n");
568 PyObject* ControlList_Size(ControlList *self)
570 return Py_BuildValue((char*)"l", self->vecItems.size());
573 // getListItem() method
574 PyDoc_STRVAR(getListItem__doc__,
575 "getListItem(index) -- Returns a given ListItem in this List.\n"
577 "index : integer - index number of item to return.\n"
579 "*Note, throws a ValueError if index is out of range.\n"
582 " - listitem = cList.getListItem(6)\n");
584 PyObject* ControlList_GetListItem(ControlList *self, PyObject *args)
587 if (!PyArg_ParseTuple(args, (char*)"i", &iPos)) return NULL;
589 if (iPos < 0 || iPos >= (int)self->vecItems.size())
591 PyErr_SetString(PyExc_ValueError, "Index out of range");
595 PyObject* pListItem = (PyObject*)self->vecItems[iPos];
597 Py_INCREF(pListItem);
601 // getItemHeight() Method
602 PyDoc_STRVAR(getItemHeight__doc__,
603 "getItemHeight() -- Returns the control's current item height as an integer.\n"
606 " - item_height = self.cList.getItemHeight()\n");
608 PyObject* ControlList_GetItemHeight(ControlList *self)
610 return Py_BuildValue((char*)"l", self->itemHeight);
614 PyDoc_STRVAR(getSpace__doc__,
615 "getSpace() -- Returns the control's space between items as an integer.\n"
618 " - gap = self.cList.getSpace()\n");
620 PyObject* ControlList_GetSpace(ControlList *self)
622 return Py_BuildValue((char*)"l", self->space);
625 PyDoc_STRVAR(setStaticContent__doc__,
626 "setStaticContent(items) -- Fills a static list with a list of listitems.\n"
628 "items : List - list of listitems to add.\n"
630 "*Note, You can use the above as keywords for arguments.\n"
633 " - cList.setStaticContent(items=listitems)\n");
635 PyObject* ControlList_SetStaticContent(ControlList *self, PyObject *args, PyObject *kwds)
637 PyObject *pList = NULL;
638 static const char *keywords[] = { "items", NULL };
640 if (!PyArg_ParseTupleAndKeywords(
645 &pList) || pList == NULL || !PyObject_TypeCheck(pList, &PyList_Type))
647 PyErr_SetString(PyExc_TypeError, "Object should be of type List");
651 vector<CGUIListItemPtr> items;
653 for (int item = 0; item < PyList_Size(pList); item++)
655 PyObject *pItem = PyList_GetItem(pList, item);
656 if (!ListItem_CheckExact(pItem))
658 PyErr_SetString(PyExc_TypeError, "Only ListItems can be passed");
661 // object is a listitem, and we set m_idpeth to 0 as this
662 // is used as the visibility condition for the item in the list
663 ListItem *listItem = (ListItem*)pItem;
664 listItem->item->m_idepth = 0;
666 items.push_back((CFileItemPtr &)listItem->item);
669 ((CGUIBaseContainer *)self->pGUIControl)->SetStaticContent(items);
675 PyMethodDef ControlList_methods[] = {
676 {(char*)"addItem", (PyCFunction)ControlList_AddItem, METH_VARARGS, addItem__doc__},
677 {(char*)"selectItem", (PyCFunction)ControlList_SelectItem, METH_VARARGS, selectItem},
678 {(char*)"reset", (PyCFunction)ControlList_Reset, METH_VARARGS, reset__doc__},
679 {(char*)"getSpinControl", (PyCFunction)ControlList_GetSpinControl, METH_VARARGS, getSpinControl__doc__},
680 {(char*)"getSelectedPosition", (PyCFunction)ControlList_GetSelectedPosition, METH_VARARGS, getSelectedPosition__doc__},
681 {(char*)"getSelectedItem", (PyCFunction)ControlList_GetSelectedItem, METH_VARARGS, getSelectedItem__doc__},
682 {(char*)"setImageDimensions", (PyCFunction)ControlList_SetImageDimensions, METH_VARARGS, setImageDimensions__doc__},
683 {(char*)"setItemHeight", (PyCFunction)ControlList_SetItemHeight, METH_VARARGS, setItemHeight__doc__},
684 {(char*)"setSpace", (PyCFunction)ControlList_SetSpace, METH_VARARGS, setSpace__doc__},
685 {(char*)"setPageControlVisible", (PyCFunction)ControlList_SetPageControlVisible, METH_VARARGS, setPageControlVisible__doc__},
686 {(char*)"size", (PyCFunction)ControlList_Size, METH_VARARGS, size__doc__},
687 {(char*)"getItemHeight", (PyCFunction)ControlList_GetItemHeight, METH_VARARGS, getItemHeight__doc__},
688 {(char*)"getSpace", (PyCFunction)ControlList_GetSpace, METH_VARARGS, getSpace__doc__},
689 {(char*)"getListItem", (PyCFunction)ControlList_GetListItem, METH_VARARGS, getListItem__doc__},
690 {(char*)"setStaticContent", (PyCFunction)ControlList_SetStaticContent, METH_VARARGS|METH_KEYWORDS, setStaticContent__doc__},
691 {(char*)"addItems", (PyCFunction)ControlList_AddItems, METH_VARARGS|METH_KEYWORDS, addItems__doc__},
692 {NULL, NULL, 0, NULL}
695 PyDoc_STRVAR(controlList__doc__,
696 "ControlList class.\n"
698 "ControlList(x, y, width, height[, font, textColor, buttonTexture, buttonFocusTexture,\n"
699 " selectedColor, imageWidth, imageHeight, itemTextXOffset, itemTextYOffset,\n"
700 " itemHeight, space, alignmentY])\n"//, shadowColor])\n"
702 "x : integer - x coordinate of control.\n"
703 "y : integer - y coordinate of control.\n"
704 "width : integer - width of control.\n"
705 "height : integer - height of control.\n"
706 "font : [opt] string - font used for items label. (e.g. 'font13')\n"
707 "textColor : [opt] hexstring - color of items label. (e.g. '0xFFFFFFFF')\n"
708 "buttonTexture : [opt] string - filename for focus texture.\n"
709 "buttonFocusTexture : [opt] string - filename for no focus texture.\n"
710 "selectedColor : [opt] integer - x offset of label.\n"
711 "imageWidth : [opt] integer - width of items icon or thumbnail.\n"
712 "imageHeight : [opt] integer - height of items icon or thumbnail.\n"
713 "itemTextXOffset : [opt] integer - x offset of items label.\n"
714 "itemTextYOffset : [opt] integer - y offset of items label.\n"
715 "itemHeight : [opt] integer - height of items.\n"
716 "space : [opt] integer - space between items.\n"
717 "alignmentY : [opt] integer - Y-axis alignment of items label - *Note, see xbfont.h\n"
718 //"shadowColor : [opt] hexstring - color of items label's shadow. (e.g. '0xFF000000')\n"
720 "*Note, You can use the above as keywords for arguments and skip certain optional arguments.\n"
721 " Once you use a keyword, all following arguments require the keyword.\n"
722 " After you create the control, you need to add it to the window with addControl().\n"
725 " - self.cList = xbmcgui.ControlList(100, 250, 200, 250, 'font14', space=5)\n"
728 // Restore code and data sections to normal.
736 PyTypeObject ControlList_Type;
738 void initControlList_Type()
740 PyXBMCInitializeTypeObject(&ControlList_Type);
742 ControlList_Type.tp_name = (char*)"xbmcgui.ControlList";
743 ControlList_Type.tp_basicsize = sizeof(ControlList);
744 ControlList_Type.tp_dealloc = (destructor)ControlList_Dealloc;
745 ControlList_Type.tp_compare = 0;
746 ControlList_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
747 ControlList_Type.tp_doc = controlList__doc__;
748 ControlList_Type.tp_methods = ControlList_methods;
749 ControlList_Type.tp_base = &Control_Type;
750 ControlList_Type.tp_new = ControlList_New;