blob: 69e90cc724f3598725b364cb287c25c1230c1904 [file] [log] [blame]
/*
* Copyright (C) 2015 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.systemui.stackdivider;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.DisplayInfo;
import com.android.systemui.statusbar.FlingAnimationUtils;
import java.util.ArrayList;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
/**
* Calculates the snap targets and the snap position given a position and a velocity. All positions
* here are to be interpreted as the left/top edge of the divider rectangle.
*/
public class DividerSnapAlgorithm {
private final Context mContext;
private final FlingAnimationUtils mFlingAnimationUtils;
private final int mDividerSize;
private final ArrayList<SnapTarget> mTargets;
/** The first target which is still splitting the screen */
private final SnapTarget mFirstSplitTarget;
/** The last target which is still splitting the screen */
private final SnapTarget mLastSplitTarget;
private final SnapTarget mDismissStartTarget;
private final SnapTarget mDismissEndTarget;
public DividerSnapAlgorithm(Context ctx, FlingAnimationUtils flingAnimationUtils,
int dividerSize, boolean isHorizontalDivision) {
mContext = ctx;
mFlingAnimationUtils = flingAnimationUtils;
mDividerSize = dividerSize;
mTargets = calculateTargets(isHorizontalDivision);
mFirstSplitTarget = mTargets.get(1);
mLastSplitTarget = mTargets.get(mTargets.size() - 2);
mDismissStartTarget = mTargets.get(0);
mDismissEndTarget = mTargets.get(mTargets.size() - 1);
}
public SnapTarget calculateSnapTarget(int position, float velocity) {
if (Math.abs(velocity) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
return snap(position);
}
if (position < mFirstSplitTarget.position && velocity < 0) {
return mDismissStartTarget;
}
if (position > mLastSplitTarget.position && velocity > 0) {
return mDismissEndTarget;
}
if (velocity < 0) {
return mFirstSplitTarget;
} else {
return mLastSplitTarget;
}
}
private SnapTarget snap(int position) {
int minIndex = -1;
int minDistance = Integer.MAX_VALUE;
int size = mTargets.size();
for (int i = 0; i < size; i++) {
int distance = Math.abs(position - mTargets.get(i).position);
if (distance < minDistance) {
minIndex = i;
minDistance = distance;
}
}
return mTargets.get(minIndex);
}
private ArrayList<SnapTarget> calculateTargets(boolean isHorizontalDivision) {
ArrayList<SnapTarget> targets = new ArrayList<>();
DisplayMetrics info = mContext.getResources().getDisplayMetrics();
int dividerMax = isHorizontalDivision
? info.heightPixels
: info.widthPixels;
// TODO: Better calculation
targets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START));
targets.add(new SnapTarget((int) (0.38f * dividerMax) - mDividerSize / 2,
SnapTarget.FLAG_NONE));
targets.add(new SnapTarget(dividerMax / 2 - mDividerSize / 2, SnapTarget.FLAG_NONE));
targets.add(new SnapTarget((int) (0.62f * dividerMax) - mDividerSize / 2,
SnapTarget.FLAG_NONE));
targets.add(new SnapTarget(dividerMax, SnapTarget.FLAG_DISMISS_END));
return targets;
}
/**
* Represents a snap target for the divider.
*/
public static class SnapTarget {
public static final int FLAG_NONE = 0;
/** If the divider reaches this value, the left/top task should be dismissed. */
public static final int FLAG_DISMISS_START = 1;
/** If the divider reaches this value, the right/bottom task should be dismissed */
public static final int FLAG_DISMISS_END = 2;
public final int position;
public final int flag;
public SnapTarget(int position, int flag) {
this.position = position;
this.flag = flag;
}
}
}