1527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal/**
2527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * Copyright (C) 2015 The Android Open Source Project
3527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal *
4527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * you may not use this file except in compliance with the License.
6527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * You may obtain a copy of the License at
7527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal *
8527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal *
10527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * Unless required by applicable law or agreed to in writing, software
11527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * See the License for the specific language governing permissions and
14527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * limitations under the License.
15527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal */
16527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
17527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalpackage com.android.launcher3.util;
18527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
19b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyalimport android.util.Log;
20527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport android.view.View;
21527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport android.view.View.OnAttachStateChangeListener;
22527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport android.view.ViewTreeObserver.OnDrawListener;
23527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
24527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport com.android.launcher3.DeferredHandler;
25527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport com.android.launcher3.Launcher;
26527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
27527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport java.util.ArrayList;
28527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport java.util.concurrent.Executor;
29527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
30527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal/**
31527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal * An executor which runs all the tasks after the first onDraw is called on the target view.
32527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal */
33527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalpublic class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable,
34527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        OnAttachStateChangeListener {
35527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
36527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private final ArrayList<Runnable> mTasks = new ArrayList<>();
37527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private final DeferredHandler mHandler;
38527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
39527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private Launcher mLauncher;
40527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private View mAttachedView;
41527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private boolean mCompleted;
42527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
43b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    private boolean mLoadAnimationCompleted;
44b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    private boolean mFirstDrawCompleted;
45b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal
46527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public ViewOnDrawExecutor(DeferredHandler handler) {
47527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mHandler = handler;
48527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
49527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
50527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void attachTo(Launcher launcher) {
51527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mLauncher = launcher;
52527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mAttachedView = launcher.getWorkspace();
53527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mAttachedView.addOnAttachStateChangeListener(this);
54527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
55527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        attachObserver();
56527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
57527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
58527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    private void attachObserver() {
59527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        if (!mCompleted) {
60527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            mAttachedView.getViewTreeObserver().addOnDrawListener(this);
61527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        }
62527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
63527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
64527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Override
65527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void execute(Runnable command) {
66527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mTasks.add(command);
67527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
68527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
69527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Override
70527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void onViewAttachedToWindow(View v) {
71527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        attachObserver();
72527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
73527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
74527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Override
75527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void onViewDetachedFromWindow(View v) { }
76527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
77527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Override
78527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void onDraw() {
79b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        mFirstDrawCompleted = true;
80527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mAttachedView.post(this);
81527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
82527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
83b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    public void onLoadAnimationCompleted() {
84b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        mLoadAnimationCompleted = true;
85b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        if (mAttachedView != null) {
86b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            mAttachedView.post(this);
87b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        }
88b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    }
89b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal
90527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Override
91527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void run() {
92b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called.
93b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) {
94b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            for (final Runnable r : mTasks) {
95b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                mHandler.post(r);
96b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            }
97b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            markCompleted();
98527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        }
99527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
100527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
101527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    public void markCompleted() {
102527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        mTasks.clear();
103b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        mCompleted = true;
104527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        if (mAttachedView != null) {
105527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            mAttachedView.getViewTreeObserver().removeOnDrawListener(this);
106527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            mAttachedView.removeOnAttachStateChangeListener(this);
107527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        }
108527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        if (mLauncher != null) {
109527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            mLauncher.clearPendingExecutor(this);
110527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        }
111527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
112527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal}
113