11fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi/* 21fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Copyright (C) 2015 The Android Open Source Project 31fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 41fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 51fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * you may not use this file except in compliance with the License. 61fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * You may obtain a copy of the License at 71fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 81fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 91fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 101fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 111fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 121fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * See the License for the specific language governing permissions and 141fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * limitations under the License. 151fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 161fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 17737af724eb31f513386e91ee5510cc6991350937Jorim Jaggipackage com.android.internal.policy; 181fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 191fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport android.content.Context; 2019cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.content.res.Configuration; 21737af724eb31f513386e91ee5510cc6991350937Jorim Jaggiimport android.content.res.Resources; 2281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggiimport android.graphics.Rect; 2319cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.hardware.display.DisplayManager; 24df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggiimport android.util.Log; 2519cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.view.Display; 2619cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.view.DisplayInfo; 271fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 281fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport java.util.ArrayList; 291fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 301fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi/** 311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Calculates the snap targets and the snap position given a position and a velocity. All positions 321fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * here are to be interpreted as the left/top edge of the divider rectangle. 33737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * 34737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * @hide 351fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 361fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggipublic class DividerSnapAlgorithm { 371fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 38df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_FLING_VELOCITY_DP_PER_SECOND = 400; 39df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_DISMISS_VELOCITY_DP_PER_SECOND = 600; 40df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 4281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: left/top has 16:9 ratio (for videos), 1:1, and right/bottom has 16:9 ratio 4381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 4481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_MODE_16_9 = 0; 4581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 4681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 4781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio) 4881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 4981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_FIXED_RATIO = 1; 5081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 5181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 5281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 1 snap target: 1:1 5381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 5481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_ONLY_1_1 = 2; 5581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 56e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng /** 57e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng * 1 snap target: minimized height, (1 - minimized height) 58e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng */ 59e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng private static final int SNAP_MODE_MINIMIZED = 3; 60e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 61737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi private final float mMinFlingVelocityPxPerSecond; 62df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float mMinDismissVelocityPxPerSecond; 6381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayWidth; 6481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayHeight; 651fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final int mDividerSize; 6681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final ArrayList<SnapTarget> mTargets = new ArrayList<>(); 6781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final Rect mInsets = new Rect(); 6881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mSnapMode; 6919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private final int mMinimalSizeResizableTask; 70e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng private final int mTaskHeightInMinimizedMode; 7181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final float mFixedRatio; 721b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private boolean mIsHorizontalDivision; 731fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 741fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The first target which is still splitting the screen */ 751fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mFirstSplitTarget; 761fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 771fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The last target which is still splitting the screen */ 781fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mLastSplitTarget; 791fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 801fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissStartTarget; 811fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissEndTarget; 82d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi private final SnapTarget mMiddleTarget; 831fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 8419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi public static DividerSnapAlgorithm create(Context ctx, Rect insets) { 8519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi DisplayInfo displayInfo = new DisplayInfo(); 8619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi ctx.getSystemService(DisplayManager.class).getDisplay( 8719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo); 8819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int dividerWindowWidth = ctx.getResources().getDimensionPixelSize( 8919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.docked_stack_divider_thickness); 9019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int dividerInsets = ctx.getResources().getDimensionPixelSize( 9119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.docked_stack_divider_insets); 9219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi return new DividerSnapAlgorithm(ctx.getResources(), 9319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi displayInfo.logicalWidth, displayInfo.logicalHeight, 9419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi dividerWindowWidth - 2 * dividerInsets, 959832f8f463a7d5448af2294bce05eac85f4dbef0Winson ctx.getApplicationContext().getResources().getConfiguration().orientation 9619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi == Configuration.ORIENTATION_PORTRAIT, 9719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi insets); 9819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 9919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 100df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 101df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi boolean isHorizontalDivision, Rect insets) { 102e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets, false); 103e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng } 104e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 105e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 106e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng boolean isHorizontalDivision, Rect insets, boolean isMinimizedMode) { 107df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinFlingVelocityPxPerSecond = 108df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 109df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinDismissVelocityPxPerSecond = 110df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_DISMISS_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 1111fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDividerSize = dividerSize; 11281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayWidth = displayWidth; 11381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayHeight = displayHeight; 1141b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi mIsHorizontalDivision = isHorizontalDivision; 11581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mInsets.set(insets); 116e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mSnapMode = isMinimizedMode ? SNAP_MODE_MINIMIZED : 117e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng res.getInteger(com.android.internal.R.integer.config_dockedStackDividerSnapMode); 118737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi mFixedRatio = res.getFraction( 11981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1); 12019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi mMinimalSizeResizableTask = res.getDimensionPixelSize( 12119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.default_minimal_size_resizable_task); 122e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mTaskHeightInMinimizedMode = res.getDimensionPixelSize( 123e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng com.android.internal.R.dimen.task_height_of_minimized_mode); 12481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi calculateTargets(isHorizontalDivision); 1251fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mFirstSplitTarget = mTargets.get(1); 1261fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mLastSplitTarget = mTargets.get(mTargets.size() - 2); 1271fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissStartTarget = mTargets.get(0); 1281fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissEndTarget = mTargets.get(mTargets.size() - 1); 129d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi mMiddleTarget = mTargets.get(mTargets.size() / 2); 1301fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 13219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi /** 13319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * @return whether it's feasible to enable split screen in the current configuration, i.e. when 13419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * snapping in the middle both tasks are larger than the minimal task size. 13519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi */ 13619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi public boolean isSplitScreenFeasible() { 13719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int statusBarSize = mInsets.top; 13819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right; 13919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int size = mIsHorizontalDivision 14019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi ? mDisplayHeight 14119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi : mDisplayWidth; 14219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int availableSpace = size - navBarSize - statusBarSize - mDividerSize; 14319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi return availableSpace / 2 >= mMinimalSizeResizableTask; 14419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 14519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 1461fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity) { 147df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return calculateSnapTarget(position, velocity, true /* hardDismiss */); 148df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 149df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 150df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 151df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param position the top/left position of the divider 152df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param velocity current dragging velocity 153df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param hardDismiss if set, make it a bit harder to get reach the dismiss targets 154df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 155df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity, boolean hardDismiss) { 156df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position < mFirstSplitTarget.position && velocity < -mMinDismissVelocityPxPerSecond) { 1571fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissStartTarget; 1581fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 159df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position > mLastSplitTarget.position && velocity > mMinDismissVelocityPxPerSecond) { 1601fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissEndTarget; 1611fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 162df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (Math.abs(velocity) < mMinFlingVelocityPxPerSecond) { 163df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return snap(position, hardDismiss); 164df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 1651fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (velocity < 0) { 1661fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mFirstSplitTarget; 1671fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } else { 1681fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mLastSplitTarget; 1691fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1701fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1711fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 172737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi public SnapTarget calculateNonDismissingSnapTarget(int position) { 173df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = snap(position, false /* hardDismiss */); 174737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi if (target == mDismissStartTarget) { 175737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mFirstSplitTarget; 176737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else if (target == mDismissEndTarget) { 177737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mLastSplitTarget; 178737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else { 179737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return target; 180737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 181737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 182737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi 1835098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public float calculateDismissingFraction(int position) { 1845098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi if (position < mFirstSplitTarget.position) { 1851b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return 1f - (float) (position - getStartInset()) 1861b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi / (mFirstSplitTarget.position - getStartInset()); 1875098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else if (position > mLastSplitTarget.position) { 1885098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return (float) (position - mLastSplitTarget.position) 18981ba11eccbc2519338782100c13cf4a5909ad6beJorim Jaggi / (mDismissEndTarget.position - mLastSplitTarget.position - mDividerSize); 1905098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1915098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return 0f; 1925098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1935098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 1945098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public SnapTarget getClosestDismissTarget(int position) { 1958f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi if (position < mFirstSplitTarget.position) { 1968f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissStartTarget; 1978f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position > mLastSplitTarget.position) { 1988f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissEndTarget; 1998f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position - mDismissStartTarget.position 2008f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi < mDismissEndTarget.position - position) { 2015098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissStartTarget; 2025098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else { 2035098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissEndTarget; 2045098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2055098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2065098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 207e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getFirstSplitTarget() { 208e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mFirstSplitTarget; 209e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 210e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 211e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getLastSplitTarget() { 212e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mLastSplitTarget; 213e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 214e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 215e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissStartTarget() { 216e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissStartTarget; 217e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 218e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 219e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissEndTarget() { 220e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissEndTarget; 221e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 222e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 2231b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getStartInset() { 2241b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 2251b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.top; 2261b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 2271b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.left; 2281b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2291b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2301b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 2311b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getEndInset() { 2321b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 2331b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.bottom; 2341b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 2351b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.right; 2361b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2371b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2381b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 239df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private SnapTarget snap(int position, boolean hardDismiss) { 2401fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int minIndex = -1; 241df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float minDistance = Float.MAX_VALUE; 2421fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int size = mTargets.size(); 2431fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi for (int i = 0; i < size; i++) { 244df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = mTargets.get(i); 245df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float distance = Math.abs(position - target.position); 246df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (hardDismiss) { 247df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi distance /= target.distanceMultiplier; 248df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 2491fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (distance < minDistance) { 2501fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minIndex = i; 2511fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minDistance = distance; 2521fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2531fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2541fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mTargets.get(minIndex); 2551fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2561fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 25781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void calculateTargets(boolean isHorizontalDivision) { 25881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.clear(); 2591fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int dividerMax = isHorizontalDivision 26081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight 26181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth; 262e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right; 2638563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START, 2648563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 0.35f)); 26581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi switch (mSnapMode) { 26681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_MODE_16_9: 26719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addRatio16_9Targets(isHorizontalDivision, dividerMax); 26881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 26981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_FIXED_RATIO: 27019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addFixedDivisionTargets(isHorizontalDivision, dividerMax); 27181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 27281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_ONLY_1_1: 27381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addMiddleTarget(isHorizontalDivision); 27481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 275e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng case SNAP_MODE_MINIMIZED: 276e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng addMinimizedTarget(isHorizontalDivision); 277e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng break; 27881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 2798563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax, 2808563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi SnapTarget.FLAG_DISMISS_END, 0.35f)); 28181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 2821fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 28319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition, 28419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int bottomPosition, int dividerMax) { 28519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi maybeAddTarget(topPosition, topPosition - mInsets.top); 28619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addMiddleTarget(isHorizontalDivision); 28719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom 28819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi - (bottomPosition + mDividerSize)); 28919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 2908563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 29119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) { 29281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 29381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 29481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 29581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 2968563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int size = (int) (mFixedRatio * (end - start)) - mDividerSize / 2; 2978563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int topPosition = start + size; 2988563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int bottomPosition = end - size - mDividerSize; 29919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); 30081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 30181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 30219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) { 30381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 30481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 30581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 30681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 30781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int startOther = isHorizontalDivision ? mInsets.left : mInsets.top; 30881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int endOther = isHorizontalDivision 30981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayWidth - mInsets.right 31081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayHeight - mInsets.bottom; 31181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi float size = 9.0f / 16.0f * (endOther - startOther); 31281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int sizeInt = (int) Math.floor(size); 31319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int topPosition = start + sizeInt; 31419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int bottomPosition = end - sizeInt - mDividerSize; 31519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); 31619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 31719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 31819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi /** 31919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * Adds a target at {@param position} but only if the area with size of {@param smallerSize} 32019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * meets the minimal size requirement. 32119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi */ 32219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void maybeAddTarget(int position, int smallerSize) { 32319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi if (smallerSize >= mMinimalSizeResizableTask) { 3248563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 32519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 32681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 32781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 32881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void addMiddleTarget(boolean isHorizontalDivision) { 3298563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 3308563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mInsets, mDisplayWidth, mDisplayHeight, mDividerSize); 3318563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 332e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng } 333e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 334e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng private void addMinimizedTarget(boolean isHorizontalDivision) { 3357ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng // In portrait offset the position by the statusbar height, in landscape add the statusbar 3367ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng // height as well to match portrait offset 3377ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng int position = mTaskHeightInMinimizedMode + mInsets.top; 3387ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng if (!isHorizontalDivision) { 3397ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng position += mInsets.left; 3407ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng } 341e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 3421fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 3431fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 344d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi public SnapTarget getMiddleTarget() { 345d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi return mMiddleTarget; 346d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi } 347d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi 34850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getNextTarget(SnapTarget snapTarget) { 34950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 35050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index < mTargets.size() - 1) { 35150cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index + 1); 35250cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 35350cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 35450cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 35550cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 35650cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getPreviousTarget(SnapTarget snapTarget) { 35750cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 35850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index > 0) { 35950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index - 1); 36050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 36150cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 36250cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 36350cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 364ce9630da86342c7bf30f00d1ced34a1d051c55baWinson public boolean isFirstSplitTargetAvailable() { 365ce9630da86342c7bf30f00d1ced34a1d051c55baWinson return mFirstSplitTarget != mMiddleTarget; 366ce9630da86342c7bf30f00d1ced34a1d051c55baWinson } 367ce9630da86342c7bf30f00d1ced34a1d051c55baWinson 368ce9630da86342c7bf30f00d1ced34a1d051c55baWinson public boolean isLastSplitTargetAvailable() { 369ce9630da86342c7bf30f00d1ced34a1d051c55baWinson return mLastSplitTarget != mMiddleTarget; 370ce9630da86342c7bf30f00d1ced34a1d051c55baWinson } 371ce9630da86342c7bf30f00d1ced34a1d051c55baWinson 3721fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** 373a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left 374a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li * if {@param increment} is negative and moves right otherwise. 375a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li */ 376a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li public SnapTarget cycleNonDismissTarget(SnapTarget snapTarget, int increment) { 377a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li int index = mTargets.indexOf(snapTarget); 378a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li if (index != -1) { 379a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li SnapTarget newTarget = mTargets.get((index + mTargets.size() + increment) 380a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li % mTargets.size()); 381a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li if (newTarget == mDismissStartTarget) { 382a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return mLastSplitTarget; 383a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } else if (newTarget == mDismissEndTarget) { 384a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return mFirstSplitTarget; 385a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } else { 386a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return newTarget; 387a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 388a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 389a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return snapTarget; 390a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 391a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li 392a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li /** 3931fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Represents a snap target for the divider. 3941fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 3951fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static class SnapTarget { 3961fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_NONE = 0; 3971fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 3981fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the left/top task should be dismissed. */ 3991fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_START = 1; 4001fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 4011fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the right/bottom task should be dismissed */ 4021fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_END = 2; 4031fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 4048563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi /** Position of this snap target. The right/bottom edge of the top/left task snaps here. */ 4051fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int position; 4068563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 4078563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi /** 4088563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi * Like {@link #position}, but used to calculate the task bounds which might be different 4098563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi * from the stack bounds. 4108563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi */ 4118563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public final int taskPosition; 4128563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 4131fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int flag; 4141fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 415df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 416df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * Multiplier used to calculate distance to snap position. The lower this value, the harder 417df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * it's to snap on this target 418df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 419df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float distanceMultiplier; 420df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4218563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public SnapTarget(int position, int taskPosition, int flag) { 4228563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi this(position, taskPosition, flag, 1f); 423df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 424df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4258563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public SnapTarget(int position, int taskPosition, int flag, float distanceMultiplier) { 4261fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.position = position; 4278563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi this.taskPosition = taskPosition; 4281fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.flag = flag; 429df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi this.distanceMultiplier = distanceMultiplier; 4301fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 4311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 4321fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi} 433