Elementary: DnD work

- Genlist default animation test functional
 - Some callbacks are still missing
This commit is contained in:
Kai Huuhko 2013-10-10 05:42:39 +03:00
parent 40d5c4250a
commit 87ee22d559
3 changed files with 223 additions and 97 deletions

View File

@ -1,5 +1,6 @@
from efl.elementary.enums cimport Elm_Sel_Type, Elm_Sel_Format, \
Elm_Xdnd_Action
from efl.utils.conversions cimport python_list_objects_to_eina_list
cdef extern from "Elementary.h":
struct _Elm_Selection_Data:
@ -78,7 +79,7 @@ cdef class SelectionData(object):
property data:
def __get__(self):
# TODO: void *
return None
return <const_char *>self.sel_data.data
property len:
""":type: size_t"""
@ -103,6 +104,8 @@ cdef Eina_Bool py_elm_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *
:param ev: struct holding information about selected data
"""
print("in drop_cb")
assert data != NULL, "data is NULL"
cdef:
SelectionData sd = SelectionData.__new__(SelectionData)
bint ret
@ -146,10 +149,10 @@ cdef Elm_Object_Item *py_elm_xy_item_get_cb(Evas_Object *obj, Evas_Coord x, Evas
if xpos1 is not None:
xpos2 = xpos1
xposret = &xpos2
xposret[0] = xpos2
if ypos1 is not None:
ypos2 = ypos1
yposret = &ypos2
yposret[0] = ypos2
return it.item
@ -181,6 +184,40 @@ cdef Evas_Object *py_elm_drag_icon_create_cb(
"""
print("in drag_icon_create_cb")
assert data != NULL, "data is NULL"
cdef:
evasObject win1 = object_from_instance(win)
evasObject icon
object xoff1 = None, yoff1 = None
Evas_Coord xoff2, yoff2
createicon, createdata = <object>data
if xoff != NULL:
xoff1 = xoff[0]
if yoff != NULL:
yoff1 = yoff[0]
try:
ret = createicon(win1, xoff1, yoff1, createdata)
except:
traceback.print_exc()
return NULL
if ret is None:
return NULL
icon, xoff1, yoff1 = ret
if xoff1 is not None:
xoff2 = xoff1
xoff[0] = xoff2
if yoff1 is not None:
yoff2 = yoff1
yoff[0] = yoff2
return icon.obj
cdef void py_elm_drag_state_cb(void *data, Evas_Object *obj) with gil:
"""Callback called when a drag is finished, enters, or leaves an object
@ -192,6 +229,28 @@ cdef void py_elm_drag_state_cb(void *data, Evas_Object *obj) with gil:
"""
print("in drag_state_cb")
cdef void py_elm_drag_done_cb(void *data, Evas_Object *obj, Eina_Bool accepted) with gil:
"""Callback called when a drag is finished.
@param data Application specific data
@param obj The object where the drag started
@param accepted TRUE if the droppped-data is accepted on drop
:since: 1.8
"""
print("in drag_done_cb")
assert data != NULL, "data is NULL"
cdef:
evasObject o = object_from_instance(obj)
donecb, donedata = <object>data
try:
donecb(o, <bint>accepted, donedata)
except:
traceback.print_exc()
cdef void py_elm_drag_accept_cb(void *data, Evas_Object *obj, Eina_Bool doaccept) with gil:
"""Callback called when a drag is responded to with an accept or deny
@ -215,7 +274,17 @@ cdef void py_elm_drag_pos_cb(void *data, Evas_Object *obj,
"""
print("in drag_pos_cb")
assert data != NULL, "data is NULL"
cdef:
evasObject o = object_from_instance(obj)
dragpos, dragdata = <object>data
try:
dragpos(o, x, y, action, dragdata)
except:
traceback.print_exc()
cdef void py_elm_drag_item_container_pos(
void *data, Evas_Object *cont, Elm_Object_Item *it,
@ -254,7 +323,26 @@ cdef Eina_Bool py_elm_drop_item_container_cb(
"""
print("in drop_item_container_cb")
assert obj != NULL, "obj is NULL"
cdef:
evasObject o = object_from_instance(obj)
ObjectItem item = _object_item_to_python(it)
SelectionData evdata = SelectionData.__new__(SelectionData)
object cbdata = None
evdata.sel_data = ev
cb = o.data["drop_item_container_cb"]
if data != NULL:
cbdata = <object>data
try:
ret = cb(o, item, evdata, xposret, yposret, cbdata)
except:
traceback.print_exc()
return 0
cdef class DragUserInfo(object):
"""
@ -277,8 +365,21 @@ cdef class DragUserInfo(object):
@param donecbdata Application data to pass to @p dragdone (output)
"""
cdef:
public Elm_Sel_Format format
public Elm_Xdnd_Action action
public list icons
public object createicon, createdata, dragpos, dragdata
public object acceptcb, acceptdata, dragdone, donecbdata
const_char *_data
cdef Elm_Drag_User_Info *info
property data:
def __get__(self):
return _ctouni(self._data)
def __set__(self, value):
if isinstance(value, unicode): value = PyUnicode_AsUTF8String(value)
self._data = value
# Elm_Sel_Format format;
# const char *data;
@ -306,3 +407,44 @@ cdef Eina_Bool py_elm_item_container_data_get_cb(
"""
print("in item_container_data_get_cb")
cdef:
DragUserInfo ret
evasObject o = object_from_instance(obj)
ObjectItem item = _object_item_to_python(it)
try:
ret = <DragUserInfo?>o.data["item_container_data_get_cb"](o, item)
except:
traceback.print_exc()
return 0
if ret is not None:
print("populating info")
info.format = ret.format
info.data = ret._data
info.icons = python_list_objects_to_eina_list(ret.icons)
if ret.createicon is not None:
info.createicon = py_elm_drag_icon_create_cb
createdata = (ret.createicon, ret.createdata)
Py_INCREF(createdata)
info.createdata = <void *>createdata
if ret.dragpos is not None:
info.dragpos = py_elm_drag_pos_cb
dragdata = (ret.dragpos, ret.dragdata)
Py_INCREF(dragdata)
info.dragdata = <void *>dragdata
if ret.acceptcb is not None:
info.acceptcb = py_elm_drag_accept_cb
acceptdata = (ret.acceptcb, ret.acceptdata)
Py_INCREF(acceptdata)
info.acceptdata = <void *>acceptdata
if ret.dragdone is not None:
info.dragdone =py_elm_drag_done_cb
donecbdata = (ret.dragdone, ret.donecbdata)
Py_INCREF(donecbdata)
info.donecbdata = <void *>donecbdata
return 1
else:
print("ret is None")
return 0

View File

@ -694,6 +694,8 @@ cdef class Genlist(Object):
raise TypeError("itemgetcb must be callable.")
self.data["xy_item_get_cb"] = itemgetcb
self.data["item_container_data_get_cb"] = data_get
if not elm_drag_item_container_add(self.obj,
tm_to_anim,
tm_to_drag,
@ -742,17 +744,20 @@ cdef class Genlist(Object):
raise TypeError("itemgetcb must be callable.")
self.data["xy_item_get_cb"] = itemgetcb
self.data["drag_item_container_pos"] = poscb
self.data["drop_item_container_cb"] = dropcb
if not elm_drop_item_container_add(self.obj,
format,
<Elm_Xy_Item_Get_Cb>py_elm_xy_item_get_cb if itemgetcb is not None else NULL,
<Elm_Drag_State>py_elm_drag_state_cb if entercb is not None else NULL,
<void *>enterdata,
<void *>enterdata if enterdata is not None else NULL,
<Elm_Drag_State>py_elm_drag_state_cb if leavecb is not None else NULL,
<void *>leavedata,
<void *>leavedata if leavedata is not None else NULL,
<Elm_Drag_Item_Container_Pos>py_elm_drag_item_container_pos if poscb is not None else NULL,
<void *>posdata,
<void *>posdata if posdata is not None else NULL,
<Elm_Drop_Item_Container_Cb>py_elm_drop_item_container_cb if dropcb is not None else NULL,
<void *>cbdata):
<void *>cbdata if cbdata is not None else NULL):
raise RuntimeError
def drop_item_container_del(self):

View File

@ -7,7 +7,7 @@ from efl.elementary.box import Box
from efl.elementary.window import StandardWindow
from efl.elementary.icon import Icon
from efl.elementary.genlist import Genlist, GenlistItemClass, \
ELM_SEL_FORMAT_TARGETS, ELM_GENLIST_ITEM_NONE
ELM_SEL_FORMAT_TARGETS, ELM_GENLIST_ITEM_NONE, DragUserInfo
img = (
"panel_01.jpg",
@ -39,19 +39,12 @@ img = (
DRAG_TIMEOUT = 0.3
ANIM_TIME = 0.5
def item_ptr_cmp(d1, d2):
return (d1 - d2)
#static Elm_Genlist_Item_Class *itc1
#static Elm_Gengrid_Item_Class *gic
class DndItemClass(GenlistItemClass):
def text_get(self, obj, part, data, *args):
return data
def content_get(self, obj, part, data, *args):
if not part == "elm.swallow.icon":
if part == "elm.swallow.icon":
icon = Icon(obj)
icon.file = data
icon.size_hint_aspect = evas.EVAS_ASPECT_CONTROL_VERTICAL, 1, 1
@ -59,8 +52,10 @@ class DndItemClass(GenlistItemClass):
return icon
return None
itc1 = DndItemClass()
def win_del(obj, data):
#print("<%s> <%d> will del <%p>\n", __func__, __LINE__, data)
print("will del <%s>" % data)
data.drop_item_container_del()
data.drag_item_container_del()
@ -73,12 +68,11 @@ def win_del(obj, data):
def gl_item_getcb(gl, x, y):
# This function returns pointer to item under (x,y) coords
#print("<%s> <%d> obj=<%p>\n", __func__, __LINE__, gl)
gli, yposret = gl.at_xy_item_get(x, y)
if gli is not None:
print("over <%s>, gli=<%s> yposret %i\n" % (gli.part_text_get("elm.text"), gli, yposret))
print("over <%s>, gli=<%s> yposret %i" % (gli.part_text_get("elm.text"), gli, yposret))
else:
print("over none, yposret %i\n", yposret)
print("over none, yposret %i" % yposret)
return gli, None, yposret
# def grid_item_getcb(obj, x, y, int *xposret, int *yposret):
@ -92,42 +86,33 @@ def gl_item_getcb(gl, x, y):
# print("over none, xposret %i yposret %i\n", *xposret, *yposret)
# return item
def gl_dropcb(data, obj, it,
ev, # Elm_Selection_Data *
xposret, yposret):
def gl_dropcb(obj, it, ev, xposret, yposret, data):
# This function is called when data is dropped on the genlist
#print("<%s> <%d> str=<%s>\n", __func__, __LINE__, (char *) ev->data)
if ev.data is None:
return False
p = ev.data
p = strchr(p, '#')
while p is not None:
p += 1
p2 = strchr(p, '#')
if p2 is not None:
p2 = '\0'
print("Item %s\n", p)
if yposret == -1:
obj.item_insert_before(itc1, p, before=it,
flags=ELM_GENLIST_ITEM_NONE)
elif yposret == 0 or yposret == 1:
if not it:
it = obj.last_item
if it:
it = obj.item_insert_after(itc1, p, None, it,
ELM_GENLIST_ITEM_NONE)
else:
it = obj.item_append(itc1, p, None,
ELM_GENLIST_ITEM_NONE)
wh0rdlist = p.split("#")
wh0rdlist.pop(0)
wh0rdlist.pop()
for wh0rd in wh0rdlist:
print("Item %s" % wh0rd)
if yposret == -1:
obj.item_insert_before(itc1, wh0rd, before_item=it, flags=ELM_GENLIST_ITEM_NONE)
elif yposret == 0 or yposret == 1:
if not it:
it = obj.last_item
if it:
it = obj.item_insert_after(itc1, wh0rd, after_item=it, flags=ELM_GENLIST_ITEM_NONE)
else:
return False
p = p2
it = obj.item_append(itc1, wh0rd, flags=ELM_GENLIST_ITEM_NONE)
else:
p = None
return False
return True
@ -284,44 +269,43 @@ def gl_dropcb(data, obj, it,
# # END - Handling drag start animation
def gl_dragdone(obj, doaccept, data):
#print("<%s> <%d> data=<%p> doaccept=<%d>\n", __func__, __LINE__, data, doaccept)
if doaccept:
# Remove items dragged out (accepted by target)
for it in data:
it.delete()
def gl_createicon(data, win, xoff, yoff):
def gl_createicon(win, xoff, yoff, data):
#print("<%s> <%d>\n", __func__, __LINE__)
it = data
o = it.part_content_get("elm.swallow.icon")
if o is not None:
w = h = 30
if o is None:
return
f, g = o.file
w = h = 30
xm, ym = o.evas.pointer_canvas_xy
f, g = o.file
if xoff is not None:
xoff = xm - (w/2)
if yoff is not None:
yoff = ym - (h/2)
xm, ym = o.evas.pointer_canvas_xy
icon = Icon(win)
icon.file = f, g
icon.size_hint_align = evas.EVAS_HINT_FILL, evas.EVAS_HINT_FILL
icon.size_hint_weight = evas.EVAS_HINT_EXPAND, evas.EVAS_HINT_EXPAND
if xoff is not None:
xoff = xm - (w/2)
if yoff is not None:
yoff = ym - (h/2)
if xoff is not None and yoff is not None:
icon.move(xoff, yoff)
icon.resize(w, h)
icon = Icon(win)
icon.file = f, g
icon.size_hint_align = evas.EVAS_HINT_FILL, evas.EVAS_HINT_FILL
icon.size_hint_weight = evas.EVAS_HINT_EXPAND, evas.EVAS_HINT_EXPAND
return icon
if (xoff is not None) and (yoff is not None):
icon.move(xoff, yoff)
icon.resize(w, h)
return icon, xoff, yoff
def gl_icons_get(data):
# Start icons animation before actually drag-starts
#print("<%s> <%d>\n", __func__, __LINE__)
gl = data
yposret = 0
@ -329,18 +313,17 @@ def gl_icons_get(data):
icons = []
xm, ym = gl.evas.pointer_canvas_xy
items = gl.selected_items
gli = gl.at_xy_item_get(xm, ym, yposret)
items = list(gl.selected_items)
gli, yposret = gl.at_xy_item_get(xm, ym)
if gli is not None:
# Add the item mouse is over to the list if NOT seleced
p = eina_list_search_unsorted(items, _item_ptr_cmp, gli)
if p is not None:
items = eina_list_append(items, gli)
if not gli in items:
items.append(gli)
for gli in items:
for it in items:
# Now add icons to animation window
o = gli.part_content_get("elm.swallow.icon")
o = it.part_content_get("elm.swallow.icon")
if o is not None:
f, g = o.file
@ -356,22 +339,19 @@ def gl_icons_get(data):
icons.append(ic)
eina_list_free(items)
return icons
def gl_get_drag_data(gl, it, items):
def gl_get_drag_data(gl, it):
# Construct a string of dragged info, user frees returned string
drag_data = None
#print("<%s> <%d>\n", __func__, __LINE__)
items = gl.selected_items
items = list(gl.selected_items)
if it is not None:
# Add the item mouse is over to the list if NOT seleced
p = eina_list_search_unsorted(items, _item_ptr_cmp, it)
if p is None:
items = eina_list_append(items, it)
if not it in items:
items.append(it)
if items:
if items is not None:
# Now we can actually compose string to send and start dragging
drag_data = "file://"
@ -383,9 +363,9 @@ def gl_get_drag_data(gl, it, items):
drag_data += "#"
#print("<%s> <%d> Sending <%s>\n", __func__, __LINE__, drag_data)
print("Sending <%s>" % drag_data)
return drag_data
return drag_data, items
# def grid_get_drag_data(gg, it, Eina_List **items):
# # Construct a string of dragged info, user frees returned string
@ -432,26 +412,25 @@ def gl_get_drag_data(gl, it, items):
# return drag_data
def gl_dnd_default_anim_data_getcb(gl, it,
info # Elm_Drag_User_Info *
):
def gl_dnd_default_anim_data_getcb(gl, it):
# This called before starting to drag, mouse-down was on it
info = DragUserInfo()
info.format = ELM_SEL_FORMAT_TARGETS
info.createicon = _gl_createicon
info.createicon = gl_createicon
info.createdata = it
info.icons = _gl_icons_get(obj)
info.dragdone = _gl_dragdone
info.icons = gl_icons_get(gl)
info.dragdone = gl_dragdone
# Now, collect data to send for drop from ALL selected items
# Save list pointer to remove items after drop and free list on done
info.data = _gl_get_drag_data(obj, it, info.donecbdata)
#print("%s - data = %s\n", __FUNCTION__, info->data)
info.data, info.donecbdata = gl_get_drag_data(gl, it)
info.acceptdata = info.donecbdata
if info.data is not None:
return True
return info
else:
return False
return
# def gl_data_getcb(gl, it,
# Elm_Drag_User_Info *info):
@ -563,7 +542,7 @@ def dnd_genlist_default_anim_clicked(*args):
bxx.pack_end(gl)
gl.show()
itc1 = DndItemClass()
#itc1 = DndItemClass()
for i in range (20):
gl.item_append(itc1, "images/{0}".format(img[i % 9]), flags=ELM_GENLIST_ITEM_NONE)