New 1.18 API: elm Genlist reusable content functionality

with a FAILING test (failing also in C)

(I love to implement broken stuff)
This commit is contained in:
Davide Andreoli 2016-08-09 15:39:35 +02:00
parent 99113cd990
commit c11a7cf227
5 changed files with 142 additions and 6 deletions

View File

@ -62,6 +62,30 @@ cdef Evas_Object *_py_elm_genlist_item_content_get(void *data, Evas_Object *obj,
else:
return NULL
cdef Evas_Object *_py_elm_genlist_item_reusable_content_get(void *data, Evas_Object *obj, const char *part, Evas_Object *old) with gil:
cdef:
GenlistItem item = <GenlistItem>data
unicode u = _ctouni(part)
evasObject icon
func = item.item_class._reusable_content_get_func
if func is None:
return NULL
o = object_from_instance(obj)
old_content = object_from_instance(old)
try:
icon = func(o, u, item.item_data, old_content)
except Exception:
traceback.print_exc()
return NULL
if icon is not None:
return icon.obj
else:
return NULL
cdef Eina_Bool _py_elm_genlist_item_state_get(void *data, Evas_Object *obj, const char *part) with gil:
cdef:
GenlistItem item = <GenlistItem>data

View File

@ -62,15 +62,17 @@ cdef extern from "Elementary.h":
pass
ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Eina_Bool (*GenlistItemFilterGetFunc) (void *data, Evas_Object *obj, void *key)
ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
ctypedef char *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Evas_Object *(*GenlistItemIconGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Evas_Object *(*GenlistItemReusableIconGetFunc)(void *data, Evas_Object *obj, const char *part, Evas_Object *old)
ctypedef Eina_Bool (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part)
ctypedef Eina_Bool (*GenlistItemFilterGetFunc) (void *data, Evas_Object *obj, void *key)
ctypedef void (*GenlistItemDelFunc) (void *data, Evas_Object *obj)
ctypedef struct Elm_Genlist_Item_Class_Func:
GenlistItemLabelGetFunc text_get
GenlistItemIconGetFunc content_get
GenlistItemReusableIconGetFunc reusable_content_get
GenlistItemStateGetFunc state_get
GenlistItemFilterGetFunc filter_get
GenlistItemDelFunc del_ "del"

View File

@ -18,6 +18,7 @@ cdef class GenlistItemClass(object):
Elm_Genlist_Item_Class *cls
object _text_get_func
object _content_get_func
object _reusable_content_get_func
object _state_get_func
object _filter_get_func
object _del_func
@ -29,6 +30,7 @@ cdef class GenlistItemClass(object):
self.cls = elm_genlist_item_class_new()
self.cls.func.text_get = _py_elm_genlist_item_text_get
self.cls.func.content_get = _py_elm_genlist_item_content_get
self.cls.func.reusable_content_get = _py_elm_genlist_item_reusable_content_get
self.cls.func.state_get = _py_elm_genlist_item_state_get
self.cls.func.filter_get = _py_elm_genlist_item_filter_get
# In C the struct member is del but we rename it to del_ in pxd
@ -41,7 +43,8 @@ cdef class GenlistItemClass(object):
def __init__(self, item_style=None, text_get_func=None,
content_get_func=None, state_get_func=None, del_func=None,
decorate_item_style=None, decorate_all_item_style=None,
filter_get_func=None, *args, **kwargs):
filter_get_func=None, reusable_content_get_func=None,
*args, **kwargs):
"""GenlistItemClass constructor.
@ -76,6 +79,14 @@ cdef class GenlistItemClass(object):
and similar. This function should have the signature:
``func(obj, part, item_data)``
:param reusable_content_get_func: if provided will override the behavior
defined by :py:func:`reusable_content_get()` in this class.
Its purpose is to return the icon object to be used (swallowed) by a
given part and row. This can be used to reuse (cache) contents
(since 1.18)
This function should have the signature:
``func(obj, part, item_data, old_content) -> obj``
.. note:: In all these signatures, 'obj' means Genlist and
'item_data' is the value given to Genlist item append/prepend
methods, it should represent your row model as you want.
@ -100,6 +111,14 @@ cdef class GenlistItemClass(object):
else:
self._content_get_func = self.content_get
if reusable_content_get_func is not None:
if callable(reusable_content_get_func):
self._reusable_content_get_func = reusable_content_get_func
else:
raise TypeError("reusable_content_get_func is not callable!")
else:
self._reusable_content_get_func = self.reusable_content_get
if state_get_func is not None:
if callable(state_get_func):
self._state_get_func = state_get_func
@ -236,6 +255,20 @@ cdef class GenlistItemClass(object):
"""
return None
def reusable_content_get(self, evasObject obj, part, item_data, old_content):
"""To be called by Genlist for each row to get its icon.
:param obj: the Genlist instance
:param part: the part that is being handled.
:param item_data: the value given to genlist append/prepend.
:param old_content: the old (if available) content that can be used
instead of creating a new object every time.
:return: icon object to be used and swallowed.
:rtype: evas Object or None
"""
return None
def state_get(self, evasObject obj, part, item_data):
"""To be called by Genlist for each row to get its state.

View File

@ -181,6 +181,7 @@ items = [
("Genlist Decorate All Mode", "test_genlist_decorate_all", "test_genlist_decorate_all"),
("Genlist Search by Text", "test_genlist_search", "test_genlist_search"),
("Genlist Reorder Mode", "test_genlist_reorder", "test_genlist_reorder"),
("Genlist Reusable Contents", "test_genlist_reusable", "test_genlist_reusable"),
]),
("Lists - List", [
("List", "test_list", "list_clicked"),

View File

@ -0,0 +1,76 @@
#!/usr/bin/env python
# encoding: utf-8
from efl.evas import EXPAND_BOTH, EXPAND_HORIZ, FILL_BOTH
from efl import elementary as elm
class MyItemClass(elm.GenlistItemClass):
def __init__(self):
elm.GenlistItemClass.__init__(self, item_style='default')
def text_get(self, obj, part, item_data):
return 'Item # %i' % item_data
def content_get(self, obj, part, item_data):
if part == 'elm.swallow.icon':
return elm.Icon(obj, standard='user-home')
if part == 'elm.swallow.end':
print('Creating NEW content for item #%d' % item_data)
txt = '<warning>Content for item %i</warning>' % item_data
return elm.Label(obj, text=txt)
return None
def reusable_content_get(self, obj, part, item_data, old_content):
if part == 'elm.swallow.end' and old_content:
if obj.data['reusable_enabled'] == True:
print('REUSING content for item # %i' % item_data)
return old_content
return None
itc = MyItemClass()
def check_changed_cb(ck, gl):
gl.data['reusable_enabled'] = ck.state
gl.realized_items_update()
def test_genlist_reusable(parent):
win = elm.StandardWindow('GenlistReusable', 'Genlist Reusable Contents',
size=(400, 400), autodel=True)
# main vertical box
box = elm.Box(win, size_hint_weight=EXPAND_BOTH)
win.resize_object_add(box)
box.show()
# info frame
fr = elm.Frame(win, text='Information', size_hint_expand=EXPAND_HORIZ,
size_hint_fill=FILL_BOTH)
fr.content = elm.Label(fr, text='Numbers on the left should always match the one on the right')
box.pack_end(fr)
fr.show()
# genlist
gl = elm.Genlist(win, homogeneous=True, mode=elm.ELM_LIST_COMPRESS,
size_hint_expand=EXPAND_BOTH, size_hint_fill=FILL_BOTH)
box.pack_end(gl)
for i in range(0, 2000):
gl.item_append(itc, i)
gl.show()
gl.data['reusable_enabled'] = True
# buttons
ck = elm.Check(win, text='Enable reusable contents', state=True)
ck.callback_changed_add(check_changed_cb, gl)
box.pack_end(ck)
ck.show()
win.show()
if __name__ == '__main__':
elm.policy_set(elm.ELM_POLICY_QUIT, elm.ELM_POLICY_QUIT_LAST_WINDOW_CLOSED)
test_genlist_reusable(None)
elm.run()