module Calabash module Cucumber module Automator # @!visibility private class Coordinates require "calabash-cucumber/map" require "calabash-cucumber/status_bar_helpers" include Calabash::Cucumber::StatusBarHelpers # @!visibility private attr_reader :element # @!visibility private def initialize(element) @element = element end # @!visibility private def self.left_point_for_full_screen_pan coordinates = Coordinates.instance_without_element { x: coordinates.send(:min_x), y: coordinates.send(:window)[:center_y] } end # @!visibility private def self.right_point_for_full_screen_pan coordinates = Coordinates.instance_without_element { x: coordinates.send(:max_x), y: coordinates.send(:window)[:center_y] } end # @!visibility private def self.top_point_for_full_screen_pan coordinates = Coordinates.instance_without_element { x: coordinates.send(:window)[:center_x], y: coordinates.send(:min_y) } end # @!visibility private def self.bottom_point_for_full_screen_pan coordinates = Coordinates.instance_without_element { x: coordinates.send(:window)[:center_x], y: coordinates.send(:max_y) } end # @!visibility private def self.points_for_full_screen_pan(direction) case direction when :left start_point = Coordinates.right_point_for_full_screen_pan end_point = Coordinates.left_point_for_full_screen_pan when :right start_point = Coordinates.left_point_for_full_screen_pan end_point = Coordinates.right_point_for_full_screen_pan when :up start_point = Coordinates.bottom_point_for_full_screen_pan end_point = Coordinates.top_point_for_full_screen_pan when :down start_point = Coordinates.top_point_for_full_screen_pan end_point = Coordinates.bottom_point_for_full_screen_pan else raise ArgumentError, "Direction #{direction} is not supported; use :left, :right, :top, :bottom" end { start: start_point, end: end_point } end # @!visibility private def left_point_for_full_view_pan { x: [min_x, element_origin[:x] + 10].max, y: element_center[:y] } end # @!visibility private def right_point_for_full_view_pan { x: [max_x, element_origin[:x] + element_size[:width] - 10].min, y: element_center[:y] } end # @!visibility private def top_point_for_full_view_pan { x: element_center[:x], y: [min_y, (element_origin[:y] + 10)].max } end # @!visibility private def bottom_point_for_full_view_pan { x: element_center[:x], y: [max_y, (element_origin[:y] + element_size[:height] - 10)].min } end # @!visibility private def points_for_full_view_pan(direction) case direction when :left start_point = right_point_for_full_view_pan end_point = left_point_for_full_view_pan when :right start_point = left_point_for_full_view_pan end_point = right_point_for_full_view_pan when :up start_point = bottom_point_for_full_view_pan end_point = top_point_for_full_view_pan when :down start_point = top_point_for_full_view_pan end_point = bottom_point_for_full_view_pan else raise ArgumentError, "Direction #{direction} is not supported; use :left, :right, :top, :bottom" end { start: start_point, end: end_point } end # @!visibility private def left_point_for_half_view_pan { x: [min_x, element_center[:x] - (element_size[:width]/4.0)].max, y: element_center[:y] } end # @!visibility private def right_point_for_half_view_pan { x: [max_x, element_center[:x] + (element_size[:width]/4.0)].min, y: element_center[:y] } end # @!visibility private def top_point_for_half_view_pan { x: element_center[:x], y: [min_y, element_center[:y] - (element_size[:height]/4.0)].max } end # @!visibility private def bottom_point_for_half_view_pan { x: element_center[:x], y: [max_y, element_center[:y] + (element_size[:height]/4.0)].min } end # @!visibility private def points_for_half_view_pan(direction) case direction when :left start_point = right_point_for_half_view_pan end_point = left_point_for_half_view_pan when :right start_point = left_point_for_half_view_pan end_point = right_point_for_half_view_pan when :up start_point = bottom_point_for_half_view_pan end_point = top_point_for_half_view_pan when :down start_point = top_point_for_half_view_pan end_point = bottom_point_for_half_view_pan else raise ArgumentError, "Direction #{direction} is not supported; use :left, :right, :top, :bottom" end { start: start_point, end: end_point } end # @!visibility private def left_point_for_small_view_pan { x: [min_x, element_center[:x] - (element_size[:width]/6.0)].max, y: element_center[:y] } end # @!visibility private def right_point_for_small_view_pan { x: [max_x, element_center[:x] + (element_size[:width]/6.0)].min, y: element_center[:y] } end # @!visibility private def top_point_for_small_view_pan { x: element_center[:x], y: [min_y, element_center[:y] - (element_size[:height]/6.0)].max } end # @!visibility private def bottom_point_for_small_view_pan { x: element_center[:x], y: [max_y, element_center[:y] + (element_size[:height]/6.0)].min } end # @!visibility private def points_for_small_view_pan(direction) case direction when :left start_point = right_point_for_small_view_pan end_point = left_point_for_small_view_pan when :right start_point = left_point_for_small_view_pan end_point = right_point_for_small_view_pan when :up start_point = bottom_point_for_small_view_pan end_point = top_point_for_small_view_pan when :down start_point = top_point_for_small_view_pan end_point = bottom_point_for_small_view_pan else raise ArgumentError, "Direction #{direction} is not supported; use :left, :right, :top, :bottom" end { start: start_point, end: end_point } end # @!visibility private def self.end_point_for_swipe(dir, element, force) case dir when :left degrees = 0 when :up degrees = 90 when :right degrees = 180 when :down degrees = 270 end radians = degrees * Math::PI / 180.0 case force when :light scale_radius_by = 0.25 when :normal scale_radius_by = 0.333 when :strong scale_radius_by = 0.5 end element_width = element["rect"]["width"] element_height = element["rect"]["height"] x_center = element["rect"]["center_x"] y_center = element["rect"]["center_y"] radius = ([element_width, element_height].min) * scale_radius_by to_x = x_center - (radius * Math.cos(radians)) to_y = y_center - (radius * Math.sin(radians)) { :x => to_x, :y => to_y } end private # @!visibility private def self.instance_without_element Coordinates.new(nil) end # @!visibility private def element_center @element_center ||= begin { x: element["rect"]["center_x"], y: element["rect"]["center_y"] } end end # @!visibility private def element_origin @element_origin ||= begin { x: element["rect"]["x"], y: element["rect"]["y"] } end end # @!visibility private def element_size @element_size ||= begin { height: element["rect"]["height"], width: element["rect"]["width"] } end end # @!visibility private def query_wrapper(query, *args) Calabash::Cucumber::Map.map(query, :query, *args) end # @!visibility private def height_for_view(view_class) element = query_wrapper(view_class).first if element element["rect"]["height"] else 0 end end # @!visibility private def status_bar_height @status_bar_height ||= status_bar_details["frame"]["height"] end # @!visibility private def nav_bar_height @nav_bar_height ||= height_for_view("UINavigationBar") end # @!visibility private def tab_bar_height @tab_bar_height ||= height_for_view("UITabBar") end # @!visibility private def toolbar_height @toolbar_height ||= height_for_view("UIToolbar") end # @!visibility private def window @window ||= begin element = query_wrapper("*").first { :height => element["rect"]["height"], :width => element["rect"]["width"], :center_x => element["rect"]["center_x"], :center_y => element["rect"]["center_y"] } end end # @!visibility private def min_y @min_y ||= status_bar_height + nav_bar_height + 16 end # @!visibility private def max_y @max_y ||= window[:height] - (tab_bar_height + toolbar_height + 16) end # @!visibility private def min_x 2 end # @!visibility private def max_x @max_x ||= window[:width] - 2 end end end end end