python-efl/examples/elementary/test_gesture_layer.py

332 lines
9.6 KiB
Python

from efl import elementary
from efl import evas
from efl.elementary.window import Window, ELM_WIN_BASIC
from efl.elementary.transit import Transit
from efl.elementary.gesture_layer import GestureLayer, ELM_GESTURE_ZOOM, \
ELM_GESTURE_MOMENTUM, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE, \
ELM_GESTURE_STATE_END, ELM_GESTURE_STATE_ABORT, ELM_GESTURE_STATE_START
from efl.elementary.background import Background
from efl.elementary.layout import Layout
from efl.elementary.entry import Entry, ELM_WRAP_MIXED
from efl.elementary.icon import Icon
from efl.evas import Map, EVAS_HINT_EXPAND, EVAS_EVENT_FLAG_NONE
#We zoom out to this value so we'll be able to use map and have a nice
#resolution when zooming in.
BASE_ZOOM = 0.5
#The amount of zoom to do when "lifting" objects.
LIFT_FACTOR = 1.3
#The base size of the shadow image.
SHADOW_W = 118
SHADOW_H = 118
zoom_out_animation_duration = 0.4
class Photo_Object(object):
ic = None
shadow = None
hit = None
gl = None
zoom_out = None
# bx, by - current wanted coordinates of the photo object.
# bw, bh - original size of the "ic" object.
# dx, dy - Used to indicate the distance between the center point
# where we put down our fingers (when started moving the item) to
# the coords of the object, so we'll be able to calculate movement
# correctly.
bx, by, bw, bh, dx, dy = None, None, None, None, None, None
# Because gesture layer only knows the amount of rotation/zoom we do
# per gesture, we have to keep the current rotate/zoom factor and the
# one that was before we started the gesture.
base_rotate, rotate = None, None
base_zoom, zoom = None, None
shadow_zoom = None
def apply_changes(po):
"""
This function applies the information from the Photo_Object to the actual
evas objects. Zoom/rotate factors and etc.
"""
map = evas.Map(4)
map.point_coord_set(0, po.bx, po.by, 0)
map.point_coord_set(1, po.bx + po.bw, po.by, 0)
map.point_coord_set(2, po.bx + po.bw, po.by + po.bh, 0)
map.point_coord_set(3, po.bx, po.by + po.bh, 0)
map.point_image_uv_set(0, 0, 0)
map.point_image_uv_set(1, po.bw, 0)
map.point_image_uv_set(2, po.bw, po.bh)
map.point_image_uv_set(3, 0, po.bh)
map.util_rotate(po.rotate, po.bx + po.bw / 2, po.by + po.bh /2)
map.util_zoom(po.zoom, po.zoom, po.bx + po.bw / 2, po.by + po.bh /2)
po.ic.map_enabled = True
po.ic.map = map
shadow_map = Map(4)
shadow_map.point_coord_set(0, po.bx, po.by, 0)
shadow_map.point_coord_set(1, po.bx + po.bw, po.by, 0)
shadow_map.point_coord_set(2, po.bx + po.bw, po.by + po.bh, 0)
shadow_map.point_coord_set(3, po.bx, po.by + po.bh, 0)
shadow_map.point_image_uv_set(0, 0, 0)
shadow_map.point_image_uv_set(1, SHADOW_W, 0)
shadow_map.point_image_uv_set(2, SHADOW_W, SHADOW_H)
shadow_map.point_image_uv_set(3, 0, SHADOW_H)
shadow_map.util_rotate(po.rotate, po.bx + po.bw / 2, po.by + po.bh /2)
shadow_map.util_zoom(po.zoom * po.shadow_zoom,
po.zoom * po.shadow_zoom,
po.bx + (po.bw / 2), po.by + (po.bh / 2))
po.shadow.map_enabled = True
po.shadow.map = shadow_map
#evas_map_free(shadow_map);
# Update the position of the hit box
po.hit.points_clear()
minx, miny, minz = map.point_coord_get(0)
maxx = minx
maxy = miny
po.hit.point_add(minx, miny)
for i in range(1, 3):
x, y, z = map.point_coord_get(i)
po.hit.point_add(x, y)
if x < minx:
minx = x
elif x > maxx:
maxx = x
if y < miny:
miny = y
elif y > maxy:
maxy = y
po.shadow.raise_()
po.ic.raise_()
po.hit.raise_()
#evas_map_free(map);
def zoom_out_animation_operation(transit, *args, **kwargs):
"""Zoom out animation"""
po, progress = args
po.zoom = BASE_ZOOM + ((po.base_zoom - BASE_ZOOM) * (1.0 - progress))
apply_changes(po)
def zoom_out_animation_end(transit, *args, **kwargs):
po = args[0]
po.base_zoom = po.zoom = BASE_ZOOM
apply_changes(po)
po.zoom_out = None
def rotate_move(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("rotate move <%d,%d> base=<%f> <%f>" % (p.x, p.y, p.base_angle, p.angle))
po.rotate = po.base_rotate + p.angle - p.base_angle
if po.rotate < 0:
po.rotate += 360
apply_changes(po)
return EVAS_EVENT_FLAG_NONE
def rotate_end(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("rotate end/abort <%d,%d> base=<%f> <%f>" % (p.x, p.y, p.base_angle, p.angle))
po.base_rotate += p.angle - p.base_angle
if po.rotate < 0:
po.rotate += 360
return EVAS_EVENT_FLAG_NONE
def zoom_start(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("zoom start <%d,%d> <%f>" % (p.x, p.y, p.zoom))
# If there's an active animator, stop it
if po.zoom_out:
elm_transit_del(po.zoom_out)
po.zoom_out = None
# Give it a "lift" effect right from the start
po.base_zoom = BASE_ZOOM * LIFT_FACTOR
po.zoom = po.base_zoom
po.shadow_zoom = 1.7
apply_changes(po)
return EVAS_EVENT_FLAG_NONE
def zoom_move(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("zoom move <%d,%d> <%f>" % (p.x, p.y, p.zoom))
po.zoom = po.base_zoom * p.zoom
apply_changes(po);
return EVAS_EVENT_FLAG_NONE
def zoom_end(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("zoom end/abort <%d,%d> <%f>" % (p.x, p.y, p.zoom))
# Apply the zoom out animator
po.shadow_zoom = 1.3
po.base_zoom = po.zoom
po.zoom_out = Transit()
po.zoom_out.duration = zoom_out_animation_duration
po.zoom_out.effect_add(zoom_out_animation_operation, po, zoom_out_animation_end)
po.zoom_out.go()
return EVAS_EVENT_FLAG_NONE
def momentum_start(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("momentum_start <%d,%d>" % (p.x2, p.y2))
po.dx = p.x2 - po.bx
po.dy = p.y2 - po.by
apply_changes(po)
return EVAS_EVENT_FLAG_NONE
def momentum_move(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("momentum move <%d,%d>" % (p.x2, p.y2))
po.bx = p.x2 - po.dx
po.by = p.y2 - po.dy
apply_changes(po)
return EVAS_EVENT_FLAG_NONE
def momentum_end(event_info, *args, **kwargs):
po = args[0]
p = event_info
print("momentum end/abort <%d,%d> <%d,%d>" % (p.x2, p.y2, p.mx, p.my))
#(void) po;
#(void) p;
# Make sure middle is in the screen, if not, fix it.
# FIXME: Use actual window sizes instead of the hardcoded
# values
mx = po.bx + (po.bw / 2)
my = po.by + (po.bh / 2)
if mx < 0:
po.bx = 0 - (po.bw / 2)
elif mx > 480:
po.bx = 480 - (po.bw / 2)
if my < 0:
po.by = 0 - (po.bw / 2)
elif my > 800:
po.by = 800 - (po.bh / 2)
apply_changes(po)
return EVAS_EVENT_FLAG_NONE
def photo_object_add(parent, ic, icon, x, y, w, h, angle):
po = Photo_Object()
po.base_zoom = po.zoom = BASE_ZOOM
if ic:
po.ic = ic
else:
po.ic = Icon(parent)
po.ic.file = icon
po.bx = x
po.by = y
po.bw = w
po.bh = h
# Add shadow
po.shadow = Icon(po.ic)
po.shadow.file = "images/pol_shadow.png"
po.shadow.size = SHADOW_W, SHADOW_H
po.shadow.show()
po.hit = evas.Polygon(parent.evas)
po.hit.precise_is_inside = True
po.hit.repeat_events = True
po.hit.color = 0, 0, 0, 0
po.ic.pos = 0, 0
po.ic.size = po.bw, po.bh
po.ic.show()
po.hit.show()
po.gl = GestureLayer(po.ic)
po.gl.hold_events = True
po.gl.attach(po.hit)
# FIXME: Add a po.rotate start so we take the first angle!!!!
po.gl.cb_set(ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE, rotate_move, po)
po.gl.cb_set(ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END, rotate_end, po)
po.gl.cb_set(ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT, rotate_end, po)
po.gl.cb_set(ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, zoom_start, po)
po.gl.cb_set(ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, zoom_move, po)
po.gl.cb_set(ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, zoom_end, po)
po.gl.cb_set(ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, zoom_end, po)
po.gl.cb_set(ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START, momentum_start, po)
po.gl.cb_set(ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE, momentum_move, po)
po.gl.cb_set(ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END, momentum_end, po)
po.gl.cb_set(ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_ABORT, momentum_end, po)
po.rotate = po.base_rotate = angle
po.shadow_zoom = 1.3
apply_changes(po)
return po
def gesture_layer_clicked(obj):
w = 480
h = 800
win = Window("gesture-layer", ELM_WIN_BASIC)
win.title = "Gesture Layer"
win.autodel = True
win.size = w, h
bg = Background(win)
bg.file = "images/wood_01.jpg"
bg.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
win.resize_object_add(bg)
bg.show()
photos = []
photos.append(photo_object_add(win, None, "images/pol_sky.png", 200, 200, 365, 400, 0))
photos.append(photo_object_add(win, None, "images/pol_twofish.png", 40, 300, 365, 400, 45))
en = Entry(win)
en.text = "You can use whatever object you want, even entries like this."
en.line_wrap = ELM_WRAP_MIXED
postit = Layout(win)
postit.file = "postit_ent.edj", "main"
postit.part_content_set("ent", en)
photos.append(photo_object_add(win, postit, None, 50, 50, 382, 400, 355))
win.callback_delete_request_add(lambda o: elementary.exit())
win.show()
if __name__ == "__main__":
elementary.init()
gesture_layer_clicked(None)
elementary.run()
elementary.shutdown()