1/*
2 * Copyright (C) 2013 DroidDriver committers
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 */
16package io.appium.droiddriver.scroll;
17
18import static io.appium.droiddriver.scroll.Direction.PhysicalDirection.DOWN;
19import static io.appium.droiddriver.scroll.Direction.PhysicalDirection.LEFT;
20import static io.appium.droiddriver.scroll.Direction.PhysicalDirection.RIGHT;
21import static io.appium.droiddriver.scroll.Direction.PhysicalDirection.UP;
22
23/**
24 * A namespace to hold interfaces and constants for scroll directions.
25 */
26public class Direction {
27  /** Logical directions */
28  public enum LogicalDirection {
29    FORWARD {
30      @Override
31      public LogicalDirection reverse() {
32        return BACKWARD;
33      }
34    },
35    BACKWARD {
36      @Override
37      public LogicalDirection reverse() {
38        return FORWARD;
39      }
40    };
41    public abstract LogicalDirection reverse();
42  }
43
44  /** Physical directions */
45  public enum PhysicalDirection {
46    UP {
47      @Override
48      public PhysicalDirection reverse() {
49        return DOWN;
50      }
51
52      @Override
53      public Axis axis() {
54        return Axis.VERTICAL;
55      }
56    },
57    DOWN {
58      @Override
59      public PhysicalDirection reverse() {
60        return UP;
61      }
62
63      @Override
64      public Axis axis() {
65        return Axis.VERTICAL;
66      }
67    },
68    LEFT {
69      @Override
70      public PhysicalDirection reverse() {
71        return RIGHT;
72      }
73
74      @Override
75      public Axis axis() {
76        return Axis.HORIZONTAL;
77      }
78    },
79    RIGHT {
80      @Override
81      public PhysicalDirection reverse() {
82        return LEFT;
83      }
84
85      @Override
86      public Axis axis() {
87        return Axis.HORIZONTAL;
88      }
89    };
90    public abstract PhysicalDirection reverse();
91
92    public abstract Axis axis();
93  }
94
95  public enum Axis {
96    HORIZONTAL {
97      private final PhysicalDirection[] directions = {LEFT, RIGHT};
98
99      @Override
100      public PhysicalDirection[] getPhysicalDirections() {
101        return directions;
102      }
103    },
104    VERTICAL {
105      private final PhysicalDirection[] directions = {UP, DOWN};
106
107      @Override
108      public PhysicalDirection[] getPhysicalDirections() {
109        return directions;
110      }
111    };
112
113    public abstract PhysicalDirection[] getPhysicalDirections();
114  }
115
116  /**
117   * Converts between PhysicalDirection and LogicalDirection. It's possible to
118   * override this for RTL (right-to-left) views, for example.
119   */
120  public static abstract class DirectionConverter {
121
122    /** Follows standard convention: up-to-down, left-to-right */
123    public static final DirectionConverter STANDARD_CONVERTER = new DirectionConverter() {
124      @Override
125      public PhysicalDirection horizontalForwardDirection() {
126        return RIGHT;
127      }
128
129      @Override
130      public PhysicalDirection verticalForwardDirection() {
131        return DOWN;
132      }
133    };
134
135    /** Follows RTL convention: up-to-down, right-to-left */
136    public static final DirectionConverter RTL_CONVERTER = new DirectionConverter() {
137      @Override
138      public PhysicalDirection horizontalForwardDirection() {
139        return LEFT;
140      }
141
142      @Override
143      public PhysicalDirection verticalForwardDirection() {
144        return DOWN;
145      }
146    };
147
148    public abstract PhysicalDirection horizontalForwardDirection();
149
150    public abstract PhysicalDirection verticalForwardDirection();
151
152    public final PhysicalDirection horizontalBackwardDirection() {
153      return horizontalForwardDirection().reverse();
154    }
155
156    public final PhysicalDirection verticalBackwardDirection() {
157      return verticalForwardDirection().reverse();
158    }
159
160    /** Converts PhysicalDirection to LogicalDirection */
161    public final LogicalDirection toLogicalDirection(PhysicalDirection physicalDirection) {
162      LogicalDirection forward = LogicalDirection.FORWARD;
163      if (toPhysicalDirection(physicalDirection.axis(), forward) == physicalDirection) {
164        return forward;
165      }
166      return forward.reverse();
167    }
168
169    /** Converts LogicalDirection to PhysicalDirection */
170    public final PhysicalDirection toPhysicalDirection(Axis axis, LogicalDirection logicalDirection) {
171      switch (axis) {
172        case HORIZONTAL:
173          switch (logicalDirection) {
174            case BACKWARD:
175              return horizontalBackwardDirection();
176            case FORWARD:
177              return horizontalForwardDirection();
178          }
179          break;
180        case VERTICAL:
181          switch (logicalDirection) {
182            case BACKWARD:
183              return verticalBackwardDirection();
184            case FORWARD:
185              return verticalForwardDirection();
186          }
187      }
188      return null;
189    }
190  }
191
192  private Direction() {}
193}
194