From 31688e1b8f028059a700a92a8276c97928abd260 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 28 Jan 2005 23:58:27 +0000 Subject: [PATCH] - added ListBoxContents: based on std::list and PyList with Strings - used the last one as a test for menulist --- components.py | 12 ++ lib/gui/Makefile.am | 4 +- lib/gui/elistbox.cpp | 155 +-------------- lib/gui/elistbox.h | 3 +- lib/gui/elistboxcontent.cpp | 378 ++++++++++++++++++++++++++++++++++++ lib/gui/elistboxcontent.h | 106 ++++++++++ lib/python/enigma_python.i | 2 + screens.py | 5 +- 8 files changed, 512 insertions(+), 153 deletions(-) create mode 100644 lib/gui/elistboxcontent.cpp create mode 100644 lib/gui/elistboxcontent.h diff --git a/components.py b/components.py index 8115ecf4..20827180 100644 --- a/components.py +++ b/components.py @@ -228,6 +228,18 @@ class MenuList(HTMLComponent, GUIComponent): def __init__(self): GUIComponent.__init__(self) + def getCurrent(self): + return self.l.getCurrentSelection() + def GUIcreateInstance(self, priv, parent, skindata): g = eListbox(parent) + # BIG BIG HACK. :( we have to ensure that the eListboxPythonStringContent doesn't get destroyed. + # we really have to take a look at the GC stuff + self.l = eListboxPythonStringContent() + self.l.setList(["Test Object 1", "Item #2", "Item #3", "nun kommt eine Zahl:", 15, "Bla fasel", "lulabla"]) + g.setContent(self.l) return g + + def GUIdeleteInstance(self, g): + g.setContent(None) + del self.l diff --git a/lib/gui/Makefile.am b/lib/gui/Makefile.am index 670d15fc..375a9469 100644 --- a/lib/gui/Makefile.am +++ b/lib/gui/Makefile.am @@ -5,5 +5,7 @@ INCLUDES = \ noinst_LIBRARIES = libenigma_gui.a libenigma_gui_a_SOURCES = \ - ebutton.cpp elabel.cpp eslider.cpp ewidget.cpp ewidgetdesktop.cpp ewindow.cpp ewindowstyle.cpp elistbox.cpp + ebutton.cpp elabel.cpp eslider.cpp ewidget.cpp ewidgetdesktop.cpp \ + ewindow.cpp ewindowstyle.cpp elistbox.cpp elistboxcontent.cpp + diff --git a/lib/gui/elistbox.cpp b/lib/gui/elistbox.cpp index c2af3d32..96214aea 100644 --- a/lib/gui/elistbox.cpp +++ b/lib/gui/elistbox.cpp @@ -1,159 +1,18 @@ #include - -/* - The basic idea is to have an interface which gives all relevant list - processing functions, and can be used by the listbox to browse trough - the list. - - The listbox directly uses the implemented cursor. It tries hard to avoid - iterating trough the (possibly very large) list, so it should be O(1), - i.e. the performance should not be influenced by the size of the list. - - The list interface knows how to draw the current entry to a specified - offset. Different interfaces can be used to adapt different lists, - pre-filter lists on the fly etc. - - cursorSave/Restore is used to avoid re-iterating the list on redraw. - The current selection is always selected as cursor position, the - cursor is then positioned to the start, and then iterated. This gives - at most 2x m_items_per_page cursor movements per redraw, indepenent - of the size of the list. - - Although cursorSet is provided, it should be only used when there is no - other way, as it involves iterating trough the list. - */ - -class eListboxTestContent: public virtual iListboxContent -{ - DECLARE_REF; -public: - void cursorHome(); - void cursorEnd(); - int cursorMove(int count=1); - int cursorValid(); - int cursorSet(int n); - int cursorGet(); - - void cursorSave(); - void cursorRestore(); - int size(); - - RESULT connectItemChanged(const Slot0 &itemChanged, ePtr &connection); - - // void setOutputDevice ? (for allocating colors, ...) .. requires some work, though - void setSize(const eSize &size); - - /* the following functions always refer to the selected item */ - void paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected); -private: - int m_cursor, m_saved_cursor; - eSize m_size; -}; - -DEFINE_REF(eListboxTestContent); - -void eListboxTestContent::cursorHome() -{ - m_cursor = 0; -} - -void eListboxTestContent::cursorEnd() -{ - m_cursor = size(); -} - -int eListboxTestContent::cursorMove(int count) -{ - m_cursor += count; - - if (m_cursor < 0) - cursorHome(); - else if (m_cursor > size()) - cursorEnd(); - return 0; -} - -int eListboxTestContent::cursorValid() -{ - return m_cursor < size(); -} - -int eListboxTestContent::cursorSet(int n) -{ - m_cursor = n; - - if (m_cursor < 0) - cursorHome(); - else if (m_cursor > size()) - cursorEnd(); - return 0; -} - -int eListboxTestContent::cursorGet() -{ - return m_cursor; -} - -void eListboxTestContent::cursorSave() -{ - m_saved_cursor = m_cursor; -} - -void eListboxTestContent::cursorRestore() -{ - m_cursor = m_saved_cursor; -} - -int eListboxTestContent::size() -{ - return 10; -} - -RESULT eListboxTestContent::connectItemChanged(const Slot0 &itemChanged, ePtr &connection) -{ - return 0; -} - -void eListboxTestContent::setSize(const eSize &size) -{ - m_size = size; -} - -void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) -{ - ePtr fnt = new gFont("Arial", 14); - painter.clip(eRect(offset, m_size)); - style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); - painter.clear(); - - if (cursorValid()) - { - painter.setFont(fnt); - char string[10]; - sprintf(string, "%d.)", m_cursor); - - ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1)); - - painter.renderText(eRect(text_offset, m_size), string); - - if (selected) - style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry); - } - - painter.clippop(); -} +#include eListbox::eListbox(eWidget *parent): eWidget(parent) { - setContent(new eListboxTestContent()); - m_content->cursorHome(); - m_top = 0; - m_selected = 0; + setContent(new eListboxStringContent()); } void eListbox::setContent(iListboxContent *content) { m_content = content; + invalidate(); + m_content->cursorHome(); + m_top = 0; + m_selected = 0; } void eListbox::moveSelection(int dir) @@ -255,7 +114,9 @@ int eListbox::event(int event, void *data, void *data2) void eListbox::recalcSize() { + eDebug("recalc size"); m_itemheight = 20; m_content->setSize(eSize(size().width(), m_itemheight)); m_items_per_page = size().height() / m_itemheight; + eDebug("done!"); } diff --git a/lib/gui/elistbox.h b/lib/gui/elistbox.h index ac45a332..4c06e288 100644 --- a/lib/gui/elistbox.h +++ b/lib/gui/elistbox.h @@ -7,6 +7,8 @@ class iListboxContent: public iObject { public: + virtual ~iListboxContent()=0; + /* indices go from 0 to size(). the end is reached when the cursor is on size(), i.e. one after the last entry (this mimics @@ -62,5 +64,4 @@ private: ePtr m_content; }; - #endif diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp new file mode 100644 index 00000000..2f05f5dc --- /dev/null +++ b/lib/gui/elistboxcontent.cpp @@ -0,0 +1,378 @@ +#include +#include +#include + +/* + The basic idea is to have an interface which gives all relevant list + processing functions, and can be used by the listbox to browse trough + the list. + + The listbox directly uses the implemented cursor. It tries hard to avoid + iterating trough the (possibly very large) list, so it should be O(1), + i.e. the performance should not be influenced by the size of the list. + + The list interface knows how to draw the current entry to a specified + offset. Different interfaces can be used to adapt different lists, + pre-filter lists on the fly etc. + + cursorSave/Restore is used to avoid re-iterating the list on redraw. + The current selection is always selected as cursor position, the + cursor is then positioned to the start, and then iterated. This gives + at most 2x m_items_per_page cursor movements per redraw, indepenent + of the size of the list. + + Although cursorSet is provided, it should be only used when there is no + other way, as it involves iterating trough the list. + */ + +iListboxContent::~iListboxContent() +{ +} + + +DEFINE_REF(eListboxTestContent); + +void eListboxTestContent::cursorHome() +{ + m_cursor = 0; +} + +void eListboxTestContent::cursorEnd() +{ + m_cursor = size(); +} + +int eListboxTestContent::cursorMove(int count) +{ + m_cursor += count; + + if (m_cursor < 0) + cursorHome(); + else if (m_cursor > size()) + cursorEnd(); + return 0; +} + +int eListboxTestContent::cursorValid() +{ + return m_cursor < size(); +} + +int eListboxTestContent::cursorSet(int n) +{ + m_cursor = n; + + if (m_cursor < 0) + cursorHome(); + else if (m_cursor > size()) + cursorEnd(); + return 0; +} + +int eListboxTestContent::cursorGet() +{ + return m_cursor; +} + +void eListboxTestContent::cursorSave() +{ + m_saved_cursor = m_cursor; +} + +void eListboxTestContent::cursorRestore() +{ + m_cursor = m_saved_cursor; +} + +int eListboxTestContent::size() +{ + return 10; +} + +RESULT eListboxTestContent::connectItemChanged(const Slot0 &itemChanged, ePtr &connection) +{ + return 0; +} + +void eListboxTestContent::setSize(const eSize &size) +{ + m_size = size; +} + +void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) +{ + ePtr fnt = new gFont("Arial", 14); + painter.clip(eRect(offset, m_size)); + style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); + painter.clear(); + + if (cursorValid()) + { + painter.setFont(fnt); + char string[10]; + sprintf(string, "%d.)", m_cursor); + + ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1)); + + painter.renderText(eRect(text_offset, m_size), string); + + if (selected) + style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry); + } + + painter.clippop(); +} + +////////////////////////////////////// + +DEFINE_REF(eListboxStringContent); + +eListboxStringContent::eListboxStringContent() +{ + m_size = 0; + cursorHome(); +} + +void eListboxStringContent::cursorHome() +{ + m_cursor = m_list.begin(); + m_cursor_number = 0; +} + +void eListboxStringContent::cursorEnd() +{ + m_cursor = m_list.end(); + m_cursor_number = m_size; +} + +int eListboxStringContent::cursorMove(int count) +{ + if (count > 0) + { + while (count && (m_cursor != m_list.end())) + { + ++m_cursor; + ++m_cursor_number; + --count; + } + } else if (count < 0) + { + while (count && (m_cursor != m_list.begin())) + { + --m_cursor; + --m_cursor_number; + ++count; + } + } + + return 0; +} + +int eListboxStringContent::cursorValid() +{ + return m_cursor != m_list.end(); +} + +int eListboxStringContent::cursorSet(int n) +{ + cursorHome(); + cursorMove(n); + + return 0; +} + +int eListboxStringContent::cursorGet() +{ + return m_cursor_number; +} + +void eListboxStringContent::cursorSave() +{ + m_saved_cursor = m_cursor; + m_saved_cursor_number = m_cursor_number; +} + +void eListboxStringContent::cursorRestore() +{ + m_cursor = m_saved_cursor; + m_cursor_number = m_saved_cursor_number; +} + +int eListboxStringContent::size() +{ + return m_size; +} + +RESULT eListboxStringContent::connectItemChanged(const Slot0 &itemChanged, ePtr &connection) +{ + return 0; +} + +void eListboxStringContent::setSize(const eSize &size) +{ + m_itemsize = size; +} + +void eListboxStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) +{ + ePtr fnt = new gFont("Arial", 14); + painter.clip(eRect(offset, m_itemsize)); + style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); + painter.clear(); + + eDebug("item %d", m_cursor_number); + if (cursorValid()) + { + eDebug("is valid.."); + painter.setFont(fnt); + + ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1)); + + painter.renderText(eRect(text_offset, m_itemsize), *m_cursor); + + if (selected) + style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry); + } + + painter.clippop(); +} + +void eListboxStringContent::setList(std::list &list) +{ + m_list = list; + m_size = list.size(); + cursorHome(); +} + +////////////////////////////////////// + +DEFINE_REF(eListboxPythonStringContent); + +eListboxPythonStringContent::eListboxPythonStringContent() +{ + m_list = 0; +} + +eListboxPythonStringContent::~eListboxPythonStringContent() +{ +} + +void eListboxPythonStringContent::cursorHome() +{ + m_cursor = 0; +} + +void eListboxPythonStringContent::cursorEnd() +{ + m_cursor = size(); +} + +int eListboxPythonStringContent::cursorMove(int count) +{ + m_cursor += count; + + if (m_cursor < 0) + cursorHome(); + else if (m_cursor > size()) + cursorEnd(); + return 0; +} + +int eListboxPythonStringContent::cursorValid() +{ + return m_cursor < size(); +} + +int eListboxPythonStringContent::cursorSet(int n) +{ + m_cursor = n; + + if (m_cursor < 0) + cursorHome(); + else if (m_cursor > size()) + cursorEnd(); + return 0; +} + +int eListboxPythonStringContent::cursorGet() +{ + return m_cursor; +} + +void eListboxPythonStringContent::cursorSave() +{ + m_saved_cursor = m_cursor; +} + +void eListboxPythonStringContent::cursorRestore() +{ + m_cursor = m_saved_cursor; +} + +int eListboxPythonStringContent::size() +{ + if (!m_list) + return 0; + return PyList_Size(m_list); +} + +RESULT eListboxPythonStringContent::connectItemChanged(const Slot0 &itemChanged, ePtr &connection) +{ + return 0; +} + +void eListboxPythonStringContent::setSize(const eSize &size) +{ + m_itemsize = size; +} + +void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) +{ + ePtr fnt = new gFont("Arial", 14); + painter.clip(eRect(offset, m_itemsize)); + style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); + painter.clear(); + + if (m_list && cursorValid()) + { + PyObject *item = PyList_GetItem(m_list, m_cursor); // borrowed reference! + painter.setFont(fnt); + + const char *string = PyString_Check(item) ? PyString_AsString(item) : ""; + + ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1)); + + painter.renderText(eRect(text_offset, m_itemsize), string); + + if (selected) + style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry); + } + + painter.clippop(); +} + +void eListboxPythonStringContent::setList(PyObject *list) +{ + Py_XDECREF(m_list); + if (!PyList_Check(list)) + { + m_list = 0; + } else + { + m_list = list; + Py_INCREF(m_list); + } +} + +PyObject *eListboxPythonStringContent::getCurrentSelection() +{ + if (!m_list) + return 0; + if (!cursorValid()) + return 0; + PyObject *r = PyList_GetItem(m_list, m_cursor); + Py_XINCREF(r); + return r; +} + +////////////////////////////////////// diff --git a/lib/gui/elistboxcontent.h b/lib/gui/elistboxcontent.h new file mode 100644 index 00000000..6219cec6 --- /dev/null +++ b/lib/gui/elistboxcontent.h @@ -0,0 +1,106 @@ +#ifndef __lib_gui_elistboxcontent_h +#define __lib_gui_elistboxcontent_h + +#include + +class eListboxTestContent: public virtual iListboxContent +{ + DECLARE_REF; +public: + void cursorHome(); + void cursorEnd(); + int cursorMove(int count=1); + int cursorValid(); + int cursorSet(int n); + int cursorGet(); + + void cursorSave(); + void cursorRestore(); + int size(); + + RESULT connectItemChanged(const Slot0 &itemChanged, ePtr &connection); + + // void setOutputDevice ? (for allocating colors, ...) .. requires some work, though + void setSize(const eSize &size); + + /* the following functions always refer to the selected item */ + void paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected); +private: + int m_cursor, m_saved_cursor; + eSize m_size; +}; + +class eListboxStringContent: public virtual iListboxContent +{ + DECLARE_REF; +public: + eListboxStringContent(); + + void cursorHome(); + void cursorEnd(); + int cursorMove(int count=1); + int cursorValid(); + int cursorSet(int n); + int cursorGet(); + + void cursorSave(); + void cursorRestore(); + int size(); + + RESULT connectItemChanged(const Slot0 &itemChanged, ePtr &connection); + + // void setOutputDevice ? (for allocating colors, ...) .. requires some work, though + void setSize(const eSize &size); + + /* the following functions always refer to the selected item */ + void paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected); + + void setList(std::list &list); +private: + typedef std::list list; + + list m_list; + list::iterator m_cursor, m_saved_cursor; + + int m_cursor_number, m_saved_cursor_number; + int m_size; + + eSize m_itemsize; +}; + +class eListboxPythonStringContent: public virtual iListboxContent +{ + DECLARE_REF; +public: + eListboxPythonStringContent(); + ~eListboxPythonStringContent(); + void cursorHome(); + void cursorEnd(); + int cursorMove(int count=1); + int cursorValid(); + int cursorSet(int n); + int cursorGet(); + + void cursorSave(); + void cursorRestore(); + int size(); + + RESULT connectItemChanged(const Slot0 &itemChanged, ePtr &connection); + + // void setOutputDevice ? (for allocating colors, ...) .. requires some work, though + void setSize(const eSize &size); + + /* the following functions always refer to the selected item */ + void paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected); + + void setList(PyObject *list); + + PyObject *getCurrentSelection(); + +private: + PyObject *m_list; + int m_cursor, m_saved_cursor; + eSize m_itemsize; +}; + +#endif diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index cbfd3ece..b84dbd14 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -52,6 +52,7 @@ is usually caused by not marking PSignals as immutable. #include #include #include +#include extern void runMainloop(); @@ -81,6 +82,7 @@ extern PSignal1 &keyPressedSignal(); %include %include %include +%include template class PSignal0 { diff --git a/screens.py b/screens.py index 50a9ddac..cf1dac10 100644 --- a/screens.py +++ b/screens.py @@ -14,10 +14,7 @@ class Screen(dict, HTMLSkin, GUISkin): # a test dialog class testDialog(Screen): def testDialogClick(self): - if self.tries == 0: - self["title"].setText("Hihi - no, this doesn't work!") - else: - self["title"].setText("You tried it %d times without success now!" % self.tries ) + self["title"].setText(self["menu"].getCurrent()) self.tries += 1 -- 2.30.2