1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.widget.espresso;
18
19import static android.support.test.espresso.action.ViewActions.actionWithAssertions;
20
21import android.view.View;
22
23import android.support.test.espresso.ViewAction;
24import android.support.test.espresso.action.CoordinatesProvider;
25import android.support.test.espresso.action.GeneralClickAction;
26import android.support.test.espresso.action.Press;
27import android.support.test.espresso.action.Tap;
28
29import com.android.internal.util.Preconditions;
30
31/**
32 * A collection of view actions.
33 */
34public final class CustomViewActions {
35
36    /**
37     * Returns an action that long presses on a view at coordinates relative to the view's
38     * location on screen.
39     *
40     * @param hRef LEFT, RIGHT, CENTER to specify an x reference
41     * @param hDelta number of pixels relative to the hRef point
42     * @param vRef TOP, BOTTOM, CENTER to specify a y reference
43     * @param vDelta number of pixels relative to the vRef point
44     */
45    public static ViewAction longPressAtRelativeCoordinates(
46            final RelativeCoordinatesProvider.HorizontalReference hRef, final int hDelta,
47            final RelativeCoordinatesProvider.VerticalReference vRef, final int vDelta) {
48        Preconditions.checkNotNull(hRef);
49        Preconditions.checkNotNull(vRef);
50        return actionWithAssertions(
51                new GeneralClickAction(
52                        Tap.LONG,
53                        new RelativeCoordinatesProvider(hRef, hDelta, vRef, vDelta),
54                        Press.FINGER));
55    }
56
57    /**
58     * A provider of x, y coordinates relative to a view's boundaries.
59     */
60    public static final class RelativeCoordinatesProvider implements CoordinatesProvider {
61
62        public enum VerticalReference {
63            TOP, BOTTOM, CENTER
64        }
65
66        public enum HorizontalReference {
67            LEFT, RIGHT, CENTER
68        }
69
70        private final HorizontalReference hRef;
71        private final VerticalReference vRef;
72        private final int hDelta;
73        private final int vDelta;
74
75        private RelativeCoordinatesProvider(
76                final HorizontalReference hRef, final int hDelta,
77                final VerticalReference vRef, final int vDelta) {
78            this.hRef = Preconditions.checkNotNull(hRef);
79            this.vRef = Preconditions.checkNotNull(vRef);
80            this.hDelta = hDelta;
81            this.vDelta = vDelta;
82        }
83
84        @Override
85        public float[] calculateCoordinates(View view) {
86            int[] xy = view.getLocationOnScreen();
87            int w = view.getWidth();
88            int h = view.getHeight();
89            int x = 0;
90            switch (hRef) {
91                case LEFT:
92                    x = xy[0] + hDelta;
93                    break;
94                case RIGHT:
95                    x = xy[0] + w + hDelta;
96                    break;
97                case CENTER:
98                    x = xy[0] + w / 2 + hDelta;
99                    break;
100            }
101            int y = 0;
102            switch (vRef) {
103                case TOP:
104                    y = xy[1] + vDelta;
105                    break;
106                case BOTTOM:
107                    y = xy[1] + h + vDelta;
108                    break;
109                case CENTER:
110                    y = xy[1] + h / 2 + vDelta;
111                    break;
112            }
113            return new float[]{x, y};
114        }
115    }
116}
117