1f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin/*
2f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * Copyright (C) 2013 DroidDriver committers
3f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin *
4f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * Licensed under the Apache License, Version 2.0 (the "License");
5f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * you may not use this file except in compliance with the License.
6f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * You may obtain a copy of the License at
7f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin *
8f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin *      http://www.apache.org/licenses/LICENSE-2.0
9f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin *
10f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * Unless required by applicable law or agreed to in writing, software
11f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * distributed under the License is distributed on an "AS IS" BASIS,
12f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * See the License for the specific language governing permissions and
14f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * limitations under the License.
15f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin */
164b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.scroll;
17f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
184b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport static io.appium.droiddriver.scroll.Direction.PhysicalDirection.DOWN;
194b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport static io.appium.droiddriver.scroll.Direction.PhysicalDirection.LEFT;
204b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport static io.appium.droiddriver.scroll.Direction.PhysicalDirection.RIGHT;
214b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport static io.appium.droiddriver.scroll.Direction.PhysicalDirection.UP;
22f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
23f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin/**
24b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin * A namespace to hold interfaces and constants for scroll directions.
25f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin */
26b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jinpublic class Direction {
27f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  /** Logical directions */
28f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  public enum LogicalDirection {
29b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    FORWARD {
30b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
31b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public LogicalDirection reverse() {
32b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return BACKWARD;
33b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
34b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    },
35b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    BACKWARD {
36b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
37b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public LogicalDirection reverse() {
38b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return FORWARD;
39b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
40b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    };
41b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public abstract LogicalDirection reverse();
42f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  }
43f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
4429d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  /** Physical directions */
4529d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  public enum PhysicalDirection {
46b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    UP {
47b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
48b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection reverse() {
49b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return DOWN;
50b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
51b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
52b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
53b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public Axis axis() {
54b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return Axis.VERTICAL;
55b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
56b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    },
57b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    DOWN {
58b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
59b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection reverse() {
60b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return UP;
61b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
62b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
63b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
64b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public Axis axis() {
65b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return Axis.VERTICAL;
66b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
67b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    },
68b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    LEFT {
69b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
70b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection reverse() {
71b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return RIGHT;
72b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
73b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
74b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
75b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public Axis axis() {
76b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return Axis.HORIZONTAL;
77b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
78b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    },
79b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    RIGHT {
80b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
81b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection reverse() {
82b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return LEFT;
83b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
84b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
85b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
86b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public Axis axis() {
87b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return Axis.HORIZONTAL;
88b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
89b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    };
90b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public abstract PhysicalDirection reverse();
91b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
92b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public abstract Axis axis();
9329d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  }
9429d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin
95f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  public enum Axis {
96f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    HORIZONTAL {
97b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      private final PhysicalDirection[] directions = {LEFT, RIGHT};
98f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
99f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      @Override
10029d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin      public PhysicalDirection[] getPhysicalDirections() {
101f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin        return directions;
102f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      }
103f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    },
104f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    VERTICAL {
105b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      private final PhysicalDirection[] directions = {UP, DOWN};
106f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
107f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      @Override
10829d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin      public PhysicalDirection[] getPhysicalDirections() {
109f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin        return directions;
110f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      }
111f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    };
112b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
11329d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin    public abstract PhysicalDirection[] getPhysicalDirections();
114f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  }
115f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
116f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  /**
117b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin   * Converts between PhysicalDirection and LogicalDirection. It's possible to
118b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin   * override this for RTL (right-to-left) views, for example.
119f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin   */
120b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin  public static abstract class DirectionConverter {
121f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin
12229d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin    /** Follows standard convention: up-to-down, left-to-right */
123b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public static final DirectionConverter STANDARD_CONVERTER = new DirectionConverter() {
124b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
125b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection horizontalForwardDirection() {
126b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return RIGHT;
127b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
128b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
129b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
130b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection verticalForwardDirection() {
131b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return DOWN;
132b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
133b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    };
134b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
135b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    /** Follows RTL convention: up-to-down, right-to-left */
136b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public static final DirectionConverter RTL_CONVERTER = new DirectionConverter() {
137b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
138b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection horizontalForwardDirection() {
139b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return LEFT;
140b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
141b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
142b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      @Override
143b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      public PhysicalDirection verticalForwardDirection() {
144b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return DOWN;
145f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      }
146f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    };
147b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
148b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public abstract PhysicalDirection horizontalForwardDirection();
149b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
150b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public abstract PhysicalDirection verticalForwardDirection();
151b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
152b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public final PhysicalDirection horizontalBackwardDirection() {
153b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      return horizontalForwardDirection().reverse();
154b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    }
155b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
156b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public final PhysicalDirection verticalBackwardDirection() {
157b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      return verticalForwardDirection().reverse();
158b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    }
159b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
160b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    /** Converts PhysicalDirection to LogicalDirection */
161b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public final LogicalDirection toLogicalDirection(PhysicalDirection physicalDirection) {
162b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      LogicalDirection forward = LogicalDirection.FORWARD;
163b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      if (toPhysicalDirection(physicalDirection.axis(), forward) == physicalDirection) {
164b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        return forward;
165b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
166b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      return forward.reverse();
167b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    }
168b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
169b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    /** Converts LogicalDirection to PhysicalDirection */
170b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    public final PhysicalDirection toPhysicalDirection(Axis axis, LogicalDirection logicalDirection) {
171b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      switch (axis) {
172b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        case HORIZONTAL:
173b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin          switch (logicalDirection) {
174b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin            case BACKWARD:
175b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin              return horizontalBackwardDirection();
176b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin            case FORWARD:
177b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin              return horizontalForwardDirection();
178b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin          }
179b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin          break;
180b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin        case VERTICAL:
181b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin          switch (logicalDirection) {
182b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin            case BACKWARD:
183b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin              return verticalBackwardDirection();
184b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin            case FORWARD:
185b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin              return verticalForwardDirection();
186b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin          }
187b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      }
188b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin      return null;
189b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin    }
190f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin  }
191b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin
192b5194043e9f0a1319dc7251f829febab3c76e277Kevin Jin  private Direction() {}
193f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin}
194