1514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi/*
2514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Copyright (C) 2015 The Android Open Source Project
3514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi *
4514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
5514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * you may not use this file except in compliance with the License.
6514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * You may obtain a copy of the License at
7514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi *
8514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
9514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi *
10514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Unless required by applicable law or agreed to in writing, software
11514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
12514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * See the License for the specific language governing permissions and
14514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * limitations under the License.
15514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi */
16514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
17514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggipackage com.android.systemui.stackdivider;
18514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
19514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.Animator;
20514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.AnimatorListenerAdapter;
21514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.AnimatorSet;
22514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.ObjectAnimator;
23514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.annotation.Nullable;
24514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.content.Context;
25514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.graphics.Canvas;
26514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.graphics.Paint;
27514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.util.AttributeSet;
28514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.util.Property;
2988afd020b696af24332547f203eaa2538618ac9eJorim Jaggiimport android.view.View;
30514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
31ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggiimport com.android.systemui.Interpolators;
32514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport com.android.systemui.R;
33514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
34514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi/**
35514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * View for the handle in the docked stack divider.
36514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi */
3788afd020b696af24332547f203eaa2538618ac9eJorim Jaggipublic class DividerHandleView extends View {
38514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
39514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
40514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            = new Property<DividerHandleView, Integer>(Integer.class, "width") {
41514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
42514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
43514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public Integer get(DividerHandleView object) {
44514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            return object.mCurrentWidth;
45514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
46514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
47514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
48514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public void set(DividerHandleView object, Integer value) {
49514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.mCurrentWidth = value;
50514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.invalidate();
51514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
52514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    };
53514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
54514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY
55514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            = new Property<DividerHandleView, Integer>(Integer.class, "height") {
56514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
57514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
58514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public Integer get(DividerHandleView object) {
59514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            return object.mCurrentHeight;
60514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
61514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
62514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
63514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public void set(DividerHandleView object, Integer value) {
64514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.mCurrentHeight = value;
65514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.invalidate();
66514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
67514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    };
68514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
69514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final Paint mPaint = new Paint();
70514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mWidth;
71514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mHeight;
72514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mCircleDiameter;
73514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private int mCurrentWidth;
74514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private int mCurrentHeight;
75514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private AnimatorSet mAnimator;
76e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi    private boolean mTouching;
77514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
78514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
79514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        super(context, attrs);
80514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
81514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mPaint.setAntiAlias(true);
82514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
83514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
84514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCurrentWidth = mWidth;
85514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCurrentHeight = mHeight;
86514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCircleDiameter = (mWidth + mHeight) / 3;
87514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
88514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
89514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    public void setTouching(boolean touching, boolean animate) {
90e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi        if (touching == mTouching) {
91e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi            return;
92e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi        }
93514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        if (mAnimator != null) {
94514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            mAnimator.cancel();
95514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            mAnimator = null;
96514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
97514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        if (!animate) {
98514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            if (touching) {
99514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentWidth = mCircleDiameter;
100514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentHeight = mCircleDiameter;
101514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            } else {
102514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentWidth = mWidth;
103514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentHeight = mHeight;
104514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            }
105514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            invalidate();
106514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        } else {
107514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            animateToTarget(touching ? mCircleDiameter : mWidth,
108514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                    touching ? mCircleDiameter : mHeight, touching);
109514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
110e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi        mTouching = touching;
111514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
112514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
113514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
114514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY,
115514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentWidth, targetWidth);
116514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY,
117514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentHeight, targetHeight);
118514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator = new AnimatorSet();
119514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.playTogether(widthAnimator, heightAnimator);
120514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.setDuration(touching
121514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                ? DividerView.TOUCH_ANIMATION_DURATION
122514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
123514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.setInterpolator(touching
124ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggi                ? Interpolators.TOUCH_RESPONSE
125ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggi                : Interpolators.FAST_OUT_SLOW_IN);
126514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.addListener(new AnimatorListenerAdapter() {
127514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            @Override
128514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            public void onAnimationEnd(Animator animation) {
129514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mAnimator = null;
130514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            }
131514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        });
132514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.start();
133514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
134514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
135514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    @Override
136514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    protected void onDraw(Canvas canvas) {
137514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int left = getWidth() / 2 - mCurrentWidth / 2;
138514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int top = getHeight() / 2 - mCurrentHeight / 2;
139514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2;
140514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
141514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                radius, radius, mPaint);
142514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
14342625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi
14442625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi    @Override
14542625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi    public boolean hasOverlappingRendering() {
14642625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi        return false;
14742625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi    }
148514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi}
149