lib/base/console.cpp: fix eConsoleAppContainer write (when called with one string...
[enigma2.git] / lib / gui / elistboxcontent.cpp
index bf183f990ebbbf0dfc37424a716ba9778aa85944..1d0323cf9b1d2db5aeab9a4a8daca5914d470564 100644 (file)
@@ -49,7 +49,8 @@ int iListboxContent::currentCursorSelectable()
 
 DEFINE_REF(eListboxPythonStringContent);
 
-eListboxPythonStringContent::eListboxPythonStringContent(): m_itemheight(25)
+eListboxPythonStringContent::eListboxPythonStringContent()
+       :m_cursor(0), m_itemheight(25)
 {
 }
 
@@ -142,6 +143,7 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
        style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
 
        eListboxStyle *local_style = 0;
+       bool cursorValid = this->cursorValid();
 
                /* get local listbox style, if present */
        if (m_listbox)
@@ -173,25 +175,25 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
        if (!local_style || !local_style->m_transparent_background)
        {
                        /* blit background picture, if available (otherwise, clear only) */
-               if (local_style && local_style->m_background)
+               if (local_style && local_style->m_background && cursorValid)
                        painter.blit(local_style->m_background, offset, eRect(), 0);
                else
                        painter.clear();
        } else
        {
-               if (local_style->m_background)
+               if (local_style->m_background && cursorValid)
                        painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
                else if (selected && !local_style->m_selection)
                        painter.clear();
        }
 
-       if (m_list && cursorValid())
+       if (m_list && cursorValid)
        {
                int gray = 0;
                ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
                painter.setFont(fnt);
 
-                       /* the user can supply tuples, in this case the first one will be displayed. */         
+                       /* the user can supply tuples, in this case the first one will be displayed. */
                if (PyTuple_Check(item))
                {
                        if (PyTuple_Size(item) == 1)
@@ -275,6 +277,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
        ePtr<gFont> fnt2 = new gFont("Regular", 16);
        eRect itemrect(offset, m_itemsize);
        eListboxStyle *local_style = 0;
+       bool cursorValid = this->cursorValid();
 
        painter.clip(itemrect);
        style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
@@ -309,19 +312,19 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                /* if we have no transparent background */
        {
                /* blit background picture, if available (otherwise, clear only) */
-               if (local_style && local_style->m_background)
+               if (local_style && local_style->m_background && cursorValid)
                        painter.blit(local_style->m_background, offset, eRect(), 0);
                else
                        painter.clear();
        } else
        {
-               if (local_style->m_background)
+               if (local_style->m_background && cursorValid)
                        painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
                else if (selected && !local_style->m_selection)
                        painter.clear();
        }
 
-       if (m_list && cursorValid())
+       if (m_list && cursorValid)
        {
                        /* get current list item */
                ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
@@ -333,14 +336,13 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
 
                        /* the first tuple element is a string for the left side.
                           the second one will be called, and the result shall be an tuple.
-                          
+
                           of this tuple,
                           the first one is the type (string).
                           the second one is the value. */
                if (PyTuple_Check(item))
                {
                                /* handle left part. get item from tuple, convert to string, display. */
-                               
                        text = PyTuple_GET_ITEM(item, 0);
                        text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
                        const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
@@ -348,35 +350,37 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                        eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
                        painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
                        Py_XDECREF(text);
-                       
-                               /* when we have no label, align value to the left. (FIXME: 
+
+                               /* when we have no label, align value to the left. (FIXME:
                                   don't we want to specifiy this individually?) */
                        int value_alignment_left = !*string;
-                       
+
                                /* now, handle the value. get 2nd part from tuple*/
-                       value = PyTuple_GET_ITEM(item, 1);
+                       if (PyTuple_Size(item) >= 2) // when no 2nd entry is in tuple this is a non selectable entry without config part
+                               value = PyTuple_GET_ITEM(item, 1);
+
                        if (value)
                        {
                                ePyObject args = PyTuple_New(1);
                                PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
-                               
+
                                        /* CallObject will call __call__ which should return the value tuple */
                                value = PyObject_CallObject(value, args);
-                               
+
                                if (PyErr_Occurred())
                                        PyErr_Print();
 
                                Py_DECREF(args);
                                        /* the PyInt was stolen. */
                        }
-                       
+
                                /*  check if this is really a tuple */
                        if (value && PyTuple_Check(value))
                        {
                                        /* convert type to string */
                                ePyObject type = PyTuple_GET_ITEM(value, 0);
                                const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
-                               
+
                                if (atype)
                                {
                                        if (!strcmp(atype, "text"))
@@ -394,21 +398,21 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                                        {
                                                ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
                                                ePyObject psize = PyTuple_GET_ITEM(value, 2);
-                                               
+
                                                        /* convert value to Long. fallback to -1 on error. */
                                                int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
                                                int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
-                                               
+
                                                        /* calc. slider length */
                                                int width = item_right.width() * value / size;
                                                int height = item_right.height();
-                                               
-                                                                                               
+
+
                                                        /* draw slider */
                                                //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
                                                //hack - make it customizable
                                                painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
-                                               
+
                                                        /* pvalue is borrowed */
                                        } else if (!strcmp(atype, "mtext"))
                                        {
@@ -420,24 +424,24 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                                                para->renderString(text, 0);
                                                para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
                                                int glyphs = para->size();
-                                               
+
                                                ePyObject plist;
-                                               
+
                                                if (PyTuple_Size(value) >= 3)
                                                        plist = PyTuple_GET_ITEM(value, 2);
-                                               
+
                                                int entries = 0;
 
                                                if (plist && PyList_Check(plist))
                                                        entries = PyList_Size(plist);
-                                               
+
                                                int left=0, right=0, last=-1;
                                                eRect bbox;
                                                for (int i = 0; i < entries; ++i)
                                                {
                                                        ePyObject entry = PyList_GET_ITEM(plist, i);
                                                        int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
-                                                       
+
                                                        if ((num < 0) || (num >= glyphs))
                                                                eWarning("glyph index %d in PythonConfigList out of bounds!", num);
                                                        else
@@ -465,7 +469,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                                        }
                                }
                                        /* type is borrowed */
-                       } else
+                       } else if (value)
                                eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
                        if (value)
                                Py_DECREF(value);
@@ -474,7 +478,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                if (selected && (!local_style || !local_style->m_selection))
                        style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
        }
-       
+
        painter.clippop();
 }
 
@@ -512,7 +516,55 @@ void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
                m_listbox->entryChanged(m_cursor);
 }
 
-static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
+static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid)
+{
+       if (pbackColor)
+       {
+               unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
+               painter.setBackgroundColor(gRGB(color));
+       }
+       else if (local_style)
+       {
+               if (local_style && local_style->m_background_color_set)
+                       painter.setBackgroundColor(local_style->m_background_color);
+               if (local_style->m_background && cursorValid)
+               {
+                       if (local_style->m_transparent_background)
+                               painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
+                       else
+                               painter.blit(local_style->m_background, offset, eRect(), 0);
+                       return;
+               }
+               else if (local_style->m_transparent_background)
+                       return;
+       }
+       painter.clear();
+}
+
+static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
+{
+       if (pbackColorSelected)
+       {
+               unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
+               painter.setBackgroundColor(gRGB(color));
+       }
+       else if (local_style)
+       {
+               if (local_style && local_style->m_background_color_selected_set)
+                       painter.setBackgroundColor(local_style->m_background_color_selected);
+               if (local_style->m_background && cursorValid)
+               {
+                       if (local_style->m_transparent_background)
+                               painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
+                       else
+                               painter.blit(local_style->m_background, offset, eRect(), 0);
+                       return;
+               }
+       }
+       painter.clear();
+}
+
+static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip, const ePoint &offset, bool cursorValid)
 {
        if (selected && sel_clip.valid())
        {
@@ -521,18 +573,7 @@ static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *l
                {
                        painter.clip(part);
                        style.setStyle(painter, eWindowStyle::styleListboxNormal);
-                       if (pbackColor)
-                       {
-                               unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
-                               painter.setBackgroundColor(gRGB(color));
-                       } // transparent background?
-                       // if we have a local background color set, use that. 
-                       else if (local_style && local_style->m_background_color_set)
-                               painter.setBackgroundColor(local_style->m_background_color);
-                       if (!pbackColor && local_style && local_style->m_transparent_background)
-                               ;
-                       else
-                               painter.clear();
+                       clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
                        painter.clippop();
                        selected = 0;
                }
@@ -541,49 +582,24 @@ static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *l
                {
                        painter.clip(part);
                        style.setStyle(painter, eWindowStyle::styleListboxSelected);
-                       if (pbackColorSelected)
-                       {
-                               unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
-                               painter.setBackgroundColor(gRGB(color));
-                       }
-                       else if (local_style && local_style->m_background_color_selected_set)
-                               painter.setBackgroundColor(local_style->m_background_color_selected);
-                       painter.clear();
+                       clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
                        painter.clippop();
                        selected = 1;
                }
        }
+       else if (selected)
+       {
+               style.setStyle(painter, eWindowStyle::styleListboxSelected);
+               clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
+               if (local_style && local_style->m_selection)
+                       painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
+       }
        else
        {
-               if (selected)
-               {
-                       style.setStyle(painter, eWindowStyle::styleListboxSelected);
-                       if (pbackColorSelected)
-                       {
-                               unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
-                               painter.setBackgroundColor(gRGB(color));
-                       }
-                       else if (local_style && local_style->m_background_color_selected_set)
-                               painter.setBackgroundColor(local_style->m_background_color_selected);
-                       painter.clear();
-               }
-               else
-               {
-                       style.setStyle(painter, eWindowStyle::styleListboxNormal);
-                       if (pbackColor)
-                       {
-                               unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
-                               painter.setBackgroundColor(gRGB(color));
-                       }/* if we have a local background color set, use that. */
-                       else if (local_style && local_style->m_background_color_set)
-                               painter.setBackgroundColor(local_style->m_background_color);
-                       /* if we have no transparent background */
-                       if (!pbackColor && local_style && local_style->m_transparent_background)
-                               ;
-                       else
-                               painter.clear();
-               }
+               style.setStyle(painter, eWindowStyle::styleListboxNormal);
+               clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
        }
+
        if (selected)
        {
                if (pforeColorSelected)
@@ -637,6 +653,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
        gRegion itemregion(eRect(offset, m_itemsize));
        eListboxStyle *local_style = 0;
        eRect sel_clip(m_selection_clip);
+       bool cursorValid = this->cursorValid();
        if (sel_clip.valid())
                sel_clip.moveBy(offset);
 
@@ -645,11 +662,11 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
                local_style = m_listbox->getLocalStyle();
 
        painter.clip(itemregion);
-       clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
+       clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
 
        ePyObject items, buildfunc_ret;
 
-       if (m_list && cursorValid())
+       if (m_list && cursorValid)
        {
                        /* a multicontent list can be used in two ways:
                                either each item is a list of (TYPE,...)-tuples,
@@ -803,7 +820,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
 
                                {
                                        gRegion rc(rect);
-                                       clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
+                                       clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
                                }
 
                                painter.setFont(m_font[fnt]);
@@ -894,6 +911,10 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
 
                                if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
                                        filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
+                                       
+                                                       /* don't do anything if percent out of range */
+                               if ((filled < 0) || (filled > 100))
+                                       continue;
 
                                int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
 
@@ -902,7 +923,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
 
                                {
                                        gRegion rc(rect);
-                                       clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
+                                       clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
                                }
 
                                // border
@@ -926,6 +947,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
 
                                break;
                        }
+                       case TYPE_PIXMAP_ALPHABLEND:
                        case TYPE_PIXMAP_ALPHATEST:
                        case TYPE_PIXMAP: // pixmap
                        {
@@ -975,10 +997,10 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
 
                                {
                                        gRegion rc(rect);
-                                       clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
+                                       clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
                                }
 
-                               painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
+                               painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
                                painter.clippop();
                                break;
                        }
@@ -989,7 +1011,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
                }
        }
 
-       if (selected)
+       if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
                style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
 
 error_out:
@@ -1028,7 +1050,7 @@ int eListboxPythonMultiContent::currentCursorSelectable()
                                {
                                        bool retval = ret == Py_True;
                                        Py_DECREF(ret);
-                                       return ret;
+                                       return retval;
                                }
                                eDebug("call m_selectableFunc failed!!! assume not callable");
                        }