void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) { painter.clip(eRect(offset, m_itemsize)); int marked = 0; if (m_current_marked && selected) marked = 2; else if (cursorValid() && isMarked(*m_cursor)) { if (selected) marked = 2; else marked = 1; } else style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); eListboxStyle *local_style = 0; /* get local listbox style, if present */ if (m_listbox) local_style = m_listbox->getLocalStyle(); if (marked == 1) // marked { style.setStyle(painter, eWindowStyle::styleListboxMarked); if (m_color_set[markedForeground]) painter.setForegroundColor(m_color[markedForeground]); if (m_color_set[markedBackground]) painter.setBackgroundColor(m_color[markedBackground]); } else if (marked == 2) // marked and selected { style.setStyle(painter, eWindowStyle::styleListboxMarkedAndSelected); if (m_color_set[markedForegroundSelected]) painter.setForegroundColor(m_color[markedForegroundSelected]); if (m_color_set[markedBackgroundSelected]) painter.setBackgroundColor(m_color[markedBackgroundSelected]); } else if (local_style) { if (selected) { /* if we have a local background color set, use that. */ if (local_style->m_background_color_selected_set) painter.setBackgroundColor(local_style->m_background_color_selected); /* same for foreground */ if (local_style->m_foreground_color_selected_set) painter.setForegroundColor(local_style->m_foreground_color_selected); } else { /* if we have a local background color set, use that. */ if (local_style->m_background_color_set) painter.setBackgroundColor(local_style->m_background_color); /* same for foreground */ if (local_style->m_foreground_color_set) painter.setForegroundColor(local_style->m_foreground_color); } } if (!local_style || !local_style->m_transparent_background) /* if we have no transparent background */ { /* blit background picture, if available (otherwise, clear only) */ if (local_style && local_style->m_background) painter.blit(local_style->m_background, offset, eRect(), 0); else painter.clear(); } else { if (local_style->m_background) painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST); else if (selected && !local_style->m_selection) painter.clear(); } if (cursorValid()) { /* get service information */ ePtr<iStaticServiceInformation> service_info; m_service_center->info(*m_cursor, service_info); eServiceReference ref = *m_cursor; bool isMarker = ref.flags & eServiceReference::isMarker; bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker); ePtr<eServiceEvent> evt; bool serviceAvail = true; #ifndef FORCE_SERVICEAVAIL if (!marked && isPlayable && service_info && m_is_playable_ignore.valid() && !service_info->isPlayable(*m_cursor, m_is_playable_ignore)) { if (m_color_set[serviceNotAvail]) painter.setForegroundColor(m_color[serviceNotAvail]); else painter.setForegroundColor(gRGB(0xbbbbbb)); serviceAvail = false; } #endif if (selected && local_style && local_style->m_selection) painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST); int xoffset=0; // used as offset when painting the folder/marker symbol or the serviceevent progress time_t now = time(0); for (int e = 0; e != celServiceTypePixmap; ++e) { if (m_element_font[e]) { int flags=gPainter::RT_VALIGN_CENTER; int yoffs = 0; eRect &area = m_element_position[e]; std::string text = "<n/a>"; switch (e) { case celServiceNumber: { if (area.width() <= 0) continue; // no point in going on if we won't paint anything if( m_cursor->getChannelNum() == 0 ) continue; char buffer[15]; snprintf(buffer, sizeof(buffer), "%d", m_cursor->getChannelNum() ); text = buffer; flags|=gPainter::RT_HALIGN_RIGHT; break; } case celServiceName: { if (service_info) service_info->getName(*m_cursor, text); break; } case celServiceInfo: { if ( isPlayable && service_info && !service_info->getEvent(*m_cursor, evt) ) { std::string name = evt->getEventName(); if (name.empty()) continue; text = evt->getEventName(); if (serviceAvail) { if (!selected && m_color_set[eventForeground]) painter.setForegroundColor(m_color[eventForeground]); else if (selected && m_color_set[eventForegroundSelected]) painter.setForegroundColor(m_color[eventForegroundSelected]); else painter.setForegroundColor(gRGB(0xe7b53f)); } break; } continue; } case celServiceEventProgressbar: { if (area.width() > 0 && isPlayable && service_info && !service_info->getEvent(*m_cursor, evt)) { char buffer[15]; snprintf(buffer, sizeof(buffer), "%d %%", (int)(100 * (now - evt->getBeginTime()) / evt->getDuration())); text = buffer; flags|=gPainter::RT_HALIGN_RIGHT; break; } continue; } } eRect tmp = area; int xoffs = 0; ePtr<gPixmap> piconPixmap; if (e == celServiceName) { //picon stuff if (isPlayable && PyCallable_Check(m_GetPiconNameFunc)) { ePyObject pArgs = PyTuple_New(1); PyTuple_SET_ITEM(pArgs, 0, PyString_FromString(ref.toString().c_str())); ePyObject pRet = PyObject_CallObject(m_GetPiconNameFunc, pArgs); Py_DECREF(pArgs); if (pRet) { if (PyString_Check(pRet)) { std::string piconFilename = PyString_AS_STRING(pRet); if (!piconFilename.empty()) loadPNG(piconPixmap, piconFilename.c_str()); } Py_DECREF(pRet); } } xoffs = xoffset; tmp.setWidth(((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? tmp.width() : m_column_width) - xoffs); } eTextPara *para = new eTextPara(tmp); para->setFont(m_element_font[e]); para->renderString(text.c_str()); if (e == celServiceName) { eRect bbox = para->getBoundBox(); int servicenameWidth = ((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? bbox.width() : m_column_width); m_element_position[celServiceInfo].setLeft(area.left() + servicenameWidth + 8 + xoffs); m_element_position[celServiceInfo].setTop(area.top()); m_element_position[celServiceInfo].setWidth(area.width() - (servicenameWidth + 8 + xoffs)); m_element_position[celServiceInfo].setHeight(area.height()); if (isPlayable) { //picon stuff if (PyCallable_Check(m_GetPiconNameFunc) and (m_column_width || piconPixmap)) { eRect area = m_element_position[celServiceInfo]; /* PIcons are usually about 100:60. Make it a * bit wider in case the icons are diffently * shaped, and to add a bit of margin between * icon and text. */ const int iconWidth = area.height() * 9 / 5; m_element_position[celServiceInfo].setLeft(area.left() + iconWidth); m_element_position[celServiceInfo].setWidth(area.width() - iconWidth); area = m_element_position[celServiceName]; xoffs += iconWidth; if (piconPixmap) { area.moveBy(offset); painter.clip(area); painter.blitScale(piconPixmap, eRect(area.left(), area.top(), iconWidth, area.height()), area, gPainter::BT_ALPHABLEND | gPainter::BT_KEEP_ASPECT_RATIO); painter.clippop(); } } //service type marker stuff if (m_servicetype_icon_mode) { int orbpos = m_cursor->getUnsignedData(4) >> 16; const char *filename = ref.path.c_str(); ePtr<gPixmap> &pixmap = (m_cursor->flags & eServiceReference::isGroup) ? m_pixmaps[picServiceGroup] : (strstr(filename, "://")) ? m_pixmaps[picStream] : (orbpos == 0xFFFF) ? m_pixmaps[picDVB_C] : (orbpos == 0xEEEE) ? m_pixmaps[picDVB_T] : m_pixmaps[picDVB_S]; if (pixmap) { eSize pixmap_size = pixmap->size(); eRect area = m_element_position[celServiceInfo]; m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + 8); m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - 8); int offs = 0; if (m_servicetype_icon_mode == 1) { area = m_element_position[celServiceName]; offs = xoffs; xoffs += pixmap_size.width() + 8; } else if (m_crypto_icon_mode == 1 && m_pixmaps[picCrypto]) offs = offs + m_pixmaps[picCrypto]->size().width() + 8; int correction = (area.height() - pixmap_size.height()) / 2; area.moveBy(offset); painter.clip(area); painter.blit(pixmap, ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST); painter.clippop(); } } //crypto icon stuff if (m_crypto_icon_mode && m_pixmaps[picCrypto]) { eSize pixmap_size = m_pixmaps[picCrypto]->size(); eRect area = m_element_position[celServiceInfo]; int offs = 0; if (m_crypto_icon_mode == 1) { m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + 8); m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - 8); area = m_element_position[celServiceName]; offs = xoffs; xoffs += pixmap_size.width() + 8; } int correction = (area.height() - pixmap_size.height()) / 2; area.moveBy(offset); if (service_info->isCrypted(*m_cursor)) { if (m_crypto_icon_mode == 2) { m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + 8); m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - 8); } painter.clip(area); painter.blit(m_pixmaps[picCrypto], ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST); painter.clippop(); } } } } if (flags & gPainter::RT_HALIGN_RIGHT) para->realign(eTextPara::dirRight); else if (flags & gPainter::RT_HALIGN_CENTER) para->realign(eTextPara::dirCenter); else if (flags & gPainter::RT_HALIGN_BLOCK) para->realign(eTextPara::dirBlock); if (flags & gPainter::RT_VALIGN_CENTER) { eRect bbox = para->getBoundBox(); yoffs = (area.height() - bbox.height()) / 2 - bbox.top(); } painter.renderPara(para, offset+ePoint(xoffs, yoffs)); } else if ((e == celFolderPixmap && m_cursor->flags & eServiceReference::isDirectory) || (e == celMarkerPixmap && m_cursor->flags & eServiceReference::isMarker && !(m_cursor->flags & eServiceReference::isNumberedMarker))) { ePtr<gPixmap> &pixmap = (e == celFolderPixmap) ? m_pixmaps[picFolder] : m_pixmaps[picMarker]; if (pixmap) { eSize pixmap_size = pixmap->size(); eRect area = m_element_position[e == celFolderPixmap ? celServiceName: celServiceNumber]; int correction = (area.height() - pixmap_size.height()) / 2; if (e == celFolderPixmap) xoffset = pixmap_size.width() + 8; area.moveBy(offset); painter.clip(area); painter.blit(pixmap, ePoint(area.left(), offset.y() + correction), area, gPainter::BT_ALPHATEST); painter.clippop(); } } }
void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) { gRegion itemregion(eRect(offset, m_itemsize)); eListboxStyle *local_style = 0; eRect sel_clip(m_selection_clip); bool cursorValid = this->cursorValid(); gRGB border_color; int border_size = 0; if (sel_clip.valid()) sel_clip.moveBy(offset); /* get local listbox style, if present */ if (m_listbox) { local_style = m_listbox->getLocalStyle(); border_size = local_style->m_border_size; border_color = local_style->m_border_color; } painter.clip(itemregion); clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid); ePyObject items, buildfunc_ret; if (m_list && cursorValid) { /* a multicontent list can be used in two ways: either each item is a list of (TYPE,...)-tuples, or there is a template defined, which is a list of (TYPE,...)-tuples, and the list is an unformatted tuple. The template then references items from the list. */ items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference! if (m_buildFunc) { if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it { if (PyTuple_Check(items)) buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items); else eDebug("[eListboxPythonMultiContent] items is no tuple"); } else eDebug("[eListboxPythonMultiContent] buildfunc is not callable"); } if (!items) { eDebug("[eListboxPythonMultiContent] error getting item %d", m_cursor); goto error_out; } if (!m_template) { if (!PyList_Check(items)) { eDebug("[eListboxPythonMultiContent] list entry %d is not a list (non-templated)", m_cursor); goto error_out; } } else { if (!PyTuple_Check(items)) { eDebug("[eListboxPythonMultiContent] list entry %d is not a tuple (templated)", m_cursor); goto error_out; } } ePyObject data; /* if we have a template, use the template for the actual formatting. we will later detect that "data" is present, and refer to that, instead of the immediate value. */ int start = 1; if (m_template) { data = items; items = m_template; start = 0; } int size = PyList_Size(items); for (int i = start; i < size; ++i) { ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference! if (!item) { eDebug("[eListboxPythonMultiContent] ?"); goto error_out; } if (!PyTuple_Check(item)) { eDebug("[eListboxPythonMultiContent] did not receive a tuple."); goto error_out; } int size = PyTuple_Size(item); if (!size) { eDebug("[eListboxPythonMultiContent] receive empty tuple."); goto error_out; } int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0)); switch (type) { case TYPE_TEXT: // text { /* (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] ) */ ePyObject px = PyTuple_GET_ITEM(item, 1), py = PyTuple_GET_ITEM(item, 2), pwidth = PyTuple_GET_ITEM(item, 3), pheight = PyTuple_GET_ITEM(item, 4), pfnt = PyTuple_GET_ITEM(item, 5), pflags = PyTuple_GET_ITEM(item, 6), pstring = PyTuple_GET_ITEM(item, 7), pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor; if (!(px && py && pwidth && pheight && pfnt && pflags && pstring)) { eDebug("[eListboxPythonMultiContent] received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])"); goto error_out; } if (size > 8) pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data); if (size > 9) pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data); if (size > 10) pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data); if (size > 11) pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data); if (size > 12) { pborderWidth = PyTuple_GET_ITEM(item, 12); if (pborderWidth == Py_None) pborderWidth=ePyObject(); } if (size > 13) pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data); if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */ pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring)); /* don't do anything if we have 'None' as string */ if (pstring == Py_None) continue; const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>"; int x = PyInt_AsLong(px) + offset.x(); int y = PyInt_AsLong(py) + offset.y(); int width = PyInt_AsLong(pwidth); int height = PyInt_AsLong(pheight); int flags = PyInt_AsLong(pflags); int fnt = PyInt_AsLong(pfnt); int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0; if (m_font.find(fnt) == m_font.end()) { eDebug("[eListboxPythonMultiContent] specified font %d was not found!", fnt); goto error_out; } eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2); painter.clip(rect); { gRegion rc(rect); bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear); } painter.setFont(m_font[fnt]); painter.renderText(rect, string, flags, border_color, border_size); painter.clippop(); // draw border if (bwidth) { eRect rect(eRect(x, y, width, height)); painter.clip(rect); if (pborderColor) { unsigned int color = PyInt_AsUnsignedLongMask(pborderColor); painter.setForegroundColor(gRGB(color)); } rect.setRect(x, y, width, bwidth); painter.fill(rect); rect.setRect(x, y+bwidth, bwidth, height-bwidth); painter.fill(rect); rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth); painter.fill(rect); rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth); painter.fill(rect); painter.clippop(); } break; } case TYPE_PROGRESS_PIXMAP: // Progress /* (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, foreColorSelected, backColor, backColorSelected] ) */ case TYPE_PROGRESS: // Progress { /* (1, x, y, width, height, filled_percent [, borderWidth, foreColor, foreColorSelected, backColor, backColorSelected] ) */ ePyObject px = PyTuple_GET_ITEM(item, 1), py = PyTuple_GET_ITEM(item, 2), pwidth = PyTuple_GET_ITEM(item, 3), pheight = PyTuple_GET_ITEM(item, 4), pfilled_perc = PyTuple_GET_ITEM(item, 5), ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected; int idx = 6; if (type == TYPE_PROGRESS) { if (!(px && py && pwidth && pheight && pfilled_perc)) { eDebug("[eListboxPythonMultiContent] received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))"); goto error_out; } } else { ppixmap = PyTuple_GET_ITEM(item, idx++); if (ppixmap == Py_None) continue; if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap)) { eDebug("[eListboxPythonMultiContent] received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))"); goto error_out; } } if (size > idx) { pborderWidth = PyTuple_GET_ITEM(item, idx++); if (pborderWidth == Py_None) pborderWidth = ePyObject(); } if (size > idx) { pforeColor = PyTuple_GET_ITEM(item, idx++); if (pforeColor == Py_None) pforeColor = ePyObject(); } if (size > idx) { pforeColorSelected = PyTuple_GET_ITEM(item, idx++); if (pforeColorSelected == Py_None) pforeColorSelected=ePyObject(); } if (size > idx) { pbackColor = PyTuple_GET_ITEM(item, idx++); if (pbackColor == Py_None) pbackColor=ePyObject(); } if (size > idx) { pbackColorSelected = PyTuple_GET_ITEM(item, idx++); if (pbackColorSelected == Py_None) pbackColorSelected=ePyObject(); } int x = PyInt_AsLong(px) + offset.x(); int y = PyInt_AsLong(py) + offset.y(); int width = PyInt_AsLong(pwidth); int height = PyInt_AsLong(pheight); int filled = PyInt_AsLong(pfilled_perc); 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; eRect rect(x, y, width, height); painter.clip(rect); { gRegion rc(rect); bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear); } // border if (bwidth) { rect.setRect(x, y, width, bwidth); painter.fill(rect); rect.setRect(x, y+bwidth, bwidth, height-bwidth); painter.fill(rect); rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth); painter.fill(rect); rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth); painter.fill(rect); } rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2); // progress if (ppixmap) { ePtr<gPixmap> pixmap; if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */ ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap)); if (SwigFromPython(pixmap, ppixmap)) { eDebug("[eListboxPythonMultiContent] (Pixmap) get pixmap failed"); painter.clippop(); continue; } painter.blit(pixmap, rect.topLeft(), rect, 0); } else painter.fill(rect); painter.clippop(); break; } case TYPE_PIXMAP_ALPHABLEND: case TYPE_PIXMAP_ALPHATEST: case TYPE_PIXMAP: // pixmap { /* (2, x, y, width, height, pixmap [, backColor, backColorSelected] ) */ ePyObject px = PyTuple_GET_ITEM(item, 1), py = PyTuple_GET_ITEM(item, 2), pwidth = PyTuple_GET_ITEM(item, 3), pheight = PyTuple_GET_ITEM(item, 4), ppixmap = PyTuple_GET_ITEM(item, 5), pbackColor, pbackColorSelected; if (!(px && py && pwidth && pheight && ppixmap)) { eDebug("[eListboxPythonMultiContent] received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))"); goto error_out; } if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */ ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap)); /* don't do anything if we have 'None' as pixmap */ if (ppixmap == Py_None) continue; int x = PyInt_AsLong(px) + offset.x(); int y = PyInt_AsLong(py) + offset.y(); int width = PyInt_AsLong(pwidth); int height = PyInt_AsLong(pheight); int flags = 0; ePtr<gPixmap> pixmap; if (SwigFromPython(pixmap, ppixmap)) { eDebug("[eListboxPythonMultiContent] (Pixmap) get pixmap failed"); goto error_out; } if (size > 6) pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data); if (size > 7) pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data); if (size > 8) flags = PyInt_AsLong(PyTuple_GET_ITEM(item, 8)); eRect rect(x, y, width, height); painter.clip(rect); { gRegion rc(rect); bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear); } flags |= (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0; if (flags & gPainter::BT_SCALE) painter.blitScale(pixmap, rect, rect, flags); else painter.blit(pixmap, rect.topLeft(), rect, flags); painter.clippop(); break; } default: eWarning("[eListboxPythonMultiContent] received unknown type (%d)", type); goto error_out; } } } if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection)) style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry); error_out: if (buildfunc_ret) Py_DECREF(buildfunc_ret); painter.clippop(); }