1144bfe739b93afdee0a1700a34806b0b287e5887Andy Huangpackage com.android.mail.utils;
2144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
3144bfe739b93afdee0a1700a34806b0b287e5887Andy Huangimport android.os.Handler;
4144bfe739b93afdee0a1700a34806b0b287e5887Andy Huangimport android.view.View;
5144bfe739b93afdee0a1700a34806b0b287e5887Andy Huangimport android.view.ViewTreeObserver;
6144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
7144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang/**
8144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang * Given a View to monitor draws on, an instance of this class will notify a listener of state
9144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang * changes between {@link #STATE_ACTIVE} and {@link #STATE_IDLE}.
10144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang * <p>
11144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang * Any drawing will instantly trigger {@link #STATE_ACTIVE}. {@link #STATE_IDLE} is only
12144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang * subsequently triggered if {@link #IDLE_WINDOW_MS} continuous milliseconds elapse with zero draws.
13144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang */
14144bfe739b93afdee0a1700a34806b0b287e5887Andy Huangpublic class DrawIdler {
15144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
16144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public static final int STATE_IDLE = 0;
17144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public static final int STATE_ACTIVE = 1;
18144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
19144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private static final int IDLE_WINDOW_MS = 100;
20144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
21144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private int mState = STATE_IDLE;
22144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
23144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private View mRoot;
24144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private IdleListener mListener;
25144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private final IdleReader mIdleReader = new IdleReader();
26144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private final Handler mHandler = new Handler();
27144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
28144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public interface IdleListener {
29144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        void onStateChanged(DrawIdler idler, int newState);
30144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
31144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
32144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public void setListener(IdleListener listener) {
33144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        mListener = listener;
34144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        if (mListener != null) {
35144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mListener.onStateChanged(this, mState);
36144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
37144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
38144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
39144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public void setRootView(View rootView) {
40144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        if (mRoot == rootView) {
41144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            return;
42144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        } else if (mRoot != null) {
43144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mRoot.getViewTreeObserver().removeOnPreDrawListener(mIdleReader);
44144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
45144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
46144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        mRoot = rootView;
47144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
48144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        if (mRoot != null) {
49144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mRoot.getViewTreeObserver().addOnPreDrawListener(mIdleReader);
50144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
51144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
52144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
53144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    public int getCurrentState() {
54144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        return mState;
55144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
56144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
57144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private void setState(int newState) {
58144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        if (mState == newState) {
59144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            return;
60144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
61144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        mState = newState;
62144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        if (mListener != null) {
63144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mListener.onStateChanged(this, newState);
64144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
65144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
66144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
67144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    // this inner class keeps implementation details private
68144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    // (we use OnPreDrawListener instead of OnDrawListener because the latter is only JB+)
69144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    private class IdleReader implements Runnable, ViewTreeObserver.OnPreDrawListener {
70144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
71144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        @Override
72144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        public void run() {
73144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            setState(STATE_IDLE);
74144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
75144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
76144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        @Override
77144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        public boolean onPreDraw() {
78144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            setState(STATE_ACTIVE);
79144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mHandler.removeCallbacks(this);
80144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            mHandler.postDelayed(this, IDLE_WINDOW_MS);
81144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang            return true; // always allow the draw; we're only here to observe
82144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang        }
83144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
84144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang    }
85144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang
86144bfe739b93afdee0a1700a34806b0b287e5887Andy Huang}
87