Skip to content
This repository has been archived by the owner on Mar 1, 2019. It is now read-only.

Commit

Permalink
support ui dump in ide, which looks very nice
Browse files Browse the repository at this point in the history
  • Loading branch information
shengxiang committed Mar 17, 2016
1 parent 791f1fc commit 09eb546
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 13 deletions.
23 changes: 22 additions & 1 deletion atx/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,32 @@
log.setLevel(logging.DEBUG)
FindPoint = collections.namedtuple('FindPoint', ['pos', 'confidence', 'method', 'matched'])
UINode = collections.namedtuple('UINode', ['bounds', 'checkable', 'class_name', 'text', 'resource_id', 'package'])
Bounds = collections.namedtuple('Bounds', ['left', 'top', 'right', 'bottom'])
# Bounds = collections.namedtuple('Bounds', ['left', 'top', 'right', 'bottom'])

__dir__ = os.path.dirname(os.path.abspath(__file__))
__tmp__ = os.path.join(__dir__, '__cache__')

DISPLAY_RE = re.compile(
'.*DisplayViewport{valid=true, .*orientation=(?P<orientation>\d+), .*deviceWidth=(?P<width>\d+), deviceHeight=(?P<height>\d+).*')

__boundstuple = collections.namedtuple('Bounds', ['left', 'top', 'right', 'bottom'])

class Bounds(__boundstuple):
def __init__(self, *args, **kwargs):
super(Bounds, self).__init__(*args, **kwargs)
self._area = None

def is_inside(self, x, y):
v = self
return x > v.left and x < v.right and y > v.top and y < v.bottom

@property
def area(self):
if not self._area:
v = self
self._area = (v.right-v.left) * (v.bottom-v.top)
return self._area


class Pattern(object):
def __init__(self, image, offset=(0, 0), anchor=0):
Expand Down Expand Up @@ -637,6 +655,9 @@ def convstr(v):
f = parsers.get(key)
if f:
ks[key] = f(value)
for key in parsers.keys():
ks[key] = ks.get(key)

return UINode(**ks)

def dump_nodes(self):
Expand Down
42 changes: 32 additions & 10 deletions atx/tkgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ def __init__(self, title='AirtestX Basic GUI', device=None):
self._tkimage = None # keep reference
self._image = None
self._ratio = 0.5
self._uinodes = [] # ui dump

self._init_vars()

def _init_items(self):
root = self._root
Expand All @@ -90,7 +93,7 @@ def _init_items(self):
frm_ctrl_code = tk.Frame(frm_control)
frm_ctrl_code.grid(column=0, row=2, sticky=tk.EW)

self._btn_refresh = tk.Button(frm_ctrl_btns, textvariable=self._refresh_text, command=self._redraw)
self._btn_refresh = tk.Button(frm_ctrl_btns, textvariable=self._refresh_text, command=self._refresh_screen)
self._btn_refresh.grid(column=0, row=0, sticky=tk.W)
tk.Button(frm_ctrl_btns, text="Wakeup", command=self._device.wakeup).grid(column=0, row=1, sticky=tk.W)
tk.Button(frm_ctrl_btns, text="Save cropped", command=self._save_crop).grid(column=0, row=2, sticky=tk.W)
Expand All @@ -110,6 +113,11 @@ def _init_items(self):
self.canvas.bind("<Button-1>", self._stroke_start)
self.canvas.bind("<B1-Motion>", self._stroke_move)
self.canvas.bind("<B1-ButtonRelease>", self._stroke_done)
self.canvas.bind("<Motion>", self._mouse_move)

def _init_vars(self):
self.draw_image(self._device.screenshot())
self._uinodes = self._device.dump_nodes()

def _worker(self):
que = self._queue
Expand Down Expand Up @@ -140,7 +148,7 @@ def _init_refresh(self):
# print now
if not self._running and self._auto_refresh_var.get() == 1:
# print 'redraw'
self._redraw()
self._refresh_screen()
self._root.after(200, self._init_refresh)

def _fix_bounds(self, bounds):
Expand All @@ -161,9 +169,6 @@ def _fix_path(self, path):
return os.path.relpath(path, os.getcwd())
except:
return path
# if not relpath.startswith('..'):
# path = relpath
# return path

def _save_screenshot(self):
save_to = tkFileDialog.asksaveasfilename(**dict(
Expand Down Expand Up @@ -218,7 +223,7 @@ def _run_selectfile(self):
self._attachfile_text.set(filename)
print filename

def _redraw(self):
def _refresh_screen(self):
def foo():
self._running = True
image = self._device.screenshot()
Expand All @@ -231,10 +236,10 @@ def foo():
self._draw_bounds(self._bounds)
self.canvas.itemconfigure('boundsLine', width=2)
self._running = False
self._uinodes = self._device.dump_nodes()

self._run_async(foo)
self._refresh_text.set("Refreshing ...")
# self._reset()

def _reset(self):
self._bounds = None
Expand Down Expand Up @@ -267,7 +272,7 @@ def _stroke_done(self, event):
self._offset = (0, 0)
elif self._bounds is None:
# print x, y
self._gencode_text.set('click(%d, %d)' % (x/self._ratio, y/self._ratio))
self._gencode_text.set('d.click(%d, %d)' % (x/self._ratio, y/self._ratio))
elif self._bounds is not None:
(x0, y0, x1, y1) = self._fix_bounds(self._bounds)
cx, cy = (x/self._ratio, y/self._ratio)
Expand All @@ -279,6 +284,24 @@ def _stroke_done(self, event):
self.tag_point(x, y)
self.canvas.itemconfigure('boundsLine', width=2)

def _mouse_move(self, event):
c = self.canvas
x, y = c.canvasx(event.x), c.canvasy(event.y)
x, y = x/self._ratio, y/self._ratio
# print x, y
selected_node = None
min_area = 1000000000000000
for node in self._uinodes:
if node.bounds.is_inside(x, y):
if node.bounds.area < min_area:
selected_node = node
min_area = node.bounds.area
if selected_node:
args = [v*self._ratio for v in selected_node.bounds]
self.canvas.delete('ui-bounds')
self.canvas.create_rectangle(*args, outline='blue', tags='ui-bounds', width=2)#, fill="blue")
# print selected_node

def _draw_bounds(self, bounds):
c = self.canvas
(x0, y0, x1, y1) = self._bounds
Expand Down Expand Up @@ -313,8 +336,7 @@ def mainloop(self):

def main(serial, **kwargs):
d = atx.connect(serial, **kwargs)
gui = CropIDE('AirtestX IDE SN: %s' % serial, device=d) #screenshot=d.screenshot)
gui.draw_image(d.screenshot())
gui = CropIDE('AirtestX IDE SN: %s' % serial, device=d)
gui.mainloop()

def test():
Expand Down
5 changes: 3 additions & 2 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ def touch():
if __name__ == '__main__':

# # stop_app()
print 'inside'
screenshot()
#print 'inside'
#screenshot()
print d.dump_nodes()
# w.on('setting.png', atx.Watcher.ACTION_TOUCH)
# w.on('common.png', atx.Watcher.ACTION_TOUCH)

Expand Down

0 comments on commit 09eb546

Please sign in to comment.