summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher2/LauncherModelOrientationHelper.java
blob: 6a9473d8618f6c622b0ec8e5be7cff6fd2592050 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher2;

import android.content.Context;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

public class LauncherModelOrientationHelper {

    static final String TAG = "LauncherModelOrientationHelper";

    public class Coordinates {
        public Coordinates(int newX, int newY) {
            x = newX;
            y = newY;
        }

        public int x;
        public int y;
    }

    private int mOrientation;
    private int mLocalDeviceWidth;
    private int mLocalDeviceHeight;
    private int mPreviousOrientation;
    private int mPreviousLocalDeviceWidth;
    private int mPreviousLocalDeviceHeight;
    private int mCanonicalDeviceWidth;
    private int mCanonicalDeviceHeight;

    protected LauncherModelOrientationHelper(Context ctx) {
        updateOrientation(ctx);
    }

    public int getCurrentOrientation() {
        return mOrientation;
    }

    public int getPreviousOrientationRelativeToCurrent() {
        int orientationDifference = -(mOrientation - mPreviousOrientation);

        if (Math.abs(orientationDifference) > 180) {
            orientationDifference = (int) -Math.signum(orientationDifference)
                    * (360 - Math.abs(orientationDifference));
        }
        return orientationDifference;
    }

    private void updateLocalDeviceDimensions() {
        mPreviousLocalDeviceHeight = mLocalDeviceHeight;
        mPreviousLocalDeviceWidth = mLocalDeviceWidth;

        if (mOrientation % 180 != 0) {
            mLocalDeviceWidth = mCanonicalDeviceHeight;
            mLocalDeviceHeight = mCanonicalDeviceWidth;
        } else {
            mLocalDeviceWidth = mCanonicalDeviceWidth;
            mLocalDeviceHeight = mCanonicalDeviceHeight;
        }
    }

    public void updateOrientation(Context ctx) {
        Display display = ((WindowManager) ctx
                .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

        mPreviousOrientation = mOrientation;
        switch (display.getRotation()) {
        case Surface.ROTATION_0:
            mOrientation = 0;
            break;
        case Surface.ROTATION_90:
            mOrientation = 90;
            break;
        case Surface.ROTATION_180:
            mOrientation = 180;
            break;
        case Surface.ROTATION_270:
            mOrientation = 270;
            break;
        }
        updateLocalDeviceDimensions();
    }

    public void updateDeviceDimensions(int deviceWidth, int deviceHeight) {
        mCanonicalDeviceWidth = deviceWidth;
        mCanonicalDeviceHeight = deviceHeight;

        updateLocalDeviceDimensions();
    }

    public Coordinates getLocalCoordinatesFromPreviousLocalCoordinates(
            int cellX, int cellY, int spanX, int spanY) {
        return getTransformedLayoutParams(cellX, cellY, spanX, spanY,
                getPreviousOrientationRelativeToCurrent(),
                mPreviousLocalDeviceWidth, mPreviousLocalDeviceHeight);
    }

    public Coordinates getCanonicalCoordinates(ItemInfo localItem) {
        return getTransformedLayoutParams(localItem.cellX, localItem.cellY,
                localItem.spanX, localItem.spanY, mOrientation,
                mLocalDeviceWidth, mLocalDeviceHeight);
    }

    public Coordinates getCanonicalCoordinates(int cellX, int cellY,
            int spanX, int spanY) {
        return getTransformedLayoutParams(cellX, cellY, spanX, spanY,
                mOrientation, mLocalDeviceWidth, mLocalDeviceHeight);
    }

    public Coordinates getLocalCoordinates(int cellX, int cellY, int spanX,
            int spanY) {
        return getTransformedLayoutParams(cellX, cellY, spanX, spanY,
                -mOrientation, mCanonicalDeviceWidth, mCanonicalDeviceHeight);
    }

    public int getLocalDeviceWidth() {
        return mLocalDeviceWidth;
    }

    public int getLocalDeviceHeight() {
        return mLocalDeviceHeight;
    }

    /**
     * Transform the coordinates based on the current device rotation
     */
    private Coordinates getTransformedLayoutParams(int cellX, int cellY,
            int spanX, int spanY, int deviceRotationClockwise,
            int initialDeviceWidth, int initialDeviceHeight) {
        if (LauncherApplication.isScreenXLarge()) {
            int x = cellX;
            int y = cellY;
            int width = spanX;
            int height = spanY;
            int finalDeviceWidth = initialDeviceWidth;
            int finalDeviceHeight = initialDeviceHeight;

            // item rotation is opposite of device rotation to maintain an
            // absolute
            // spatial layout
            double phi = Math.toRadians(-deviceRotationClockwise);

            double x1 = x + width / 2.0f - initialDeviceWidth / 2.0f;
            double y1 = y + height / 2.0f - initialDeviceHeight / 2.0f;

            // multiply x and y by a clockwise rotation matrix
            double x2 = x1 * Math.cos(phi) + y1 * Math.sin(phi);
            double y2 = -x1 * Math.sin(phi) + y1 * Math.cos(phi);

            // Get the rotated device dimensions
            if (deviceRotationClockwise % 180 != 0) {
                finalDeviceWidth = initialDeviceHeight;
                finalDeviceHeight = initialDeviceWidth;
            }

            x2 = x2 + finalDeviceWidth / 2.0f - width / 2.0f;
            y2 = y2 + finalDeviceHeight / 2.0f - height / 2.0f;

            return new Coordinates((int) Math.round(x2), (int) Math.round(y2));
        } else {
            return new Coordinates(cellX, cellY);
        }
    }
}