1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/*
2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License.
6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at
7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and
14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License.
15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera;
18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
19b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
20b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.PixelFormat;
21b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Gravity;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.LayoutInflater;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
28e480f77352d670b2892a9b7b7cd503838b71ca9fRomain Guyimport com.android.camera.R;
293889cf31101cfd4d336f1ce5ae5122c2cb3c0fdcChih-Chung Chang
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/**
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * A on-screen hint is a view containing a little message for the user and will
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * be shown on the screen continuously.  This class helps you create and show
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * those.
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * <p>
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * When the view is shown to the user, appears as a floating view over the
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * application.
38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * <p>
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * The easiest way to use this class is to call one of the static methods that
40271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * constructs everything you need and returns a new {@code OnScreenHint} object.
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class OnScreenHint {
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static final String TAG = "OnScreenHint";
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mX, mY;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    float mHorizontalMargin;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    float mVerticalMargin;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mView;
50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mNextView;
51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
52b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang    private final WindowManager.LayoutParams mParams =
53b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            new WindowManager.LayoutParams();
54bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final WindowManager mWM;
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final Handler mHandler = new Handler();
56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
58b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * Construct an empty OnScreenHint object.  You must call {@link #setView}
59b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * before you can call {@link #show}.
60b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
61b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * @param context  The context to use.  Usually your
62b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Application} or
63b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Activity} object.
64b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
65b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public OnScreenHint(Context context) {
66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
67b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        mY = context.getResources().getDimensionPixelSize(
68b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                R.dimen.hint_y_offset);
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.format = PixelFormat.TRANSLUCENT;
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.windowAnimations = R.style.Animation_OnScreenHint;
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.setTitle("OnScreenHint");
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Show the view on the screen.
82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void show() {
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mNextView == null) {
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            throw new RuntimeException("setView must have been called");
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(mShow);
88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Close the view if it's showing.
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void cancel() {
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(mHide);
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Make a standard hint that just contains a text view.
99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
100b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * @param context  The context to use.  Usually your
101b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Application} or
102b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Activity} object.
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @param text     The text to show.  Can be formatted text.
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
106b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static OnScreenHint makeText(Context context, CharSequence text) {
107b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        OnScreenHint result = new OnScreenHint(context);
108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
109b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        LayoutInflater inflate =
110b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                (LayoutInflater) context.getSystemService(
111b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                Context.LAYOUT_INFLATER_SERVICE);
112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        View v = inflate.inflate(R.layout.on_screen_hint, null);
113b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        TextView tv = (TextView) v.findViewById(R.id.message);
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        tv.setText(text);
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        result.mNextView = v;
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
122b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * Update the text in a OnScreenHint that was previously created using one
123b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * of the makeText() methods.
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @param s The new text for the OnScreenHint.
125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void setText(CharSequence s) {
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mNextView == null) {
128b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            throw new RuntimeException("This OnScreenHint was not "
129b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    + "created with OnScreenHint.makeText()");
130b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        TextView tv = (TextView) mNextView.findViewById(R.id.message);
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (tv == null) {
133b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            throw new RuntimeException("This OnScreenHint was not "
134b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    + "created with OnScreenHint.makeText()");
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        tv.setText(s);
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private synchronized void handleShow() {
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mView != mNextView) {
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // remove the old view if necessary
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleHide();
143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mView = mNextView;
144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            final int gravity = mGravity;
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.gravity = gravity;
146b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK)
147b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    == Gravity.FILL_HORIZONTAL) {
148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mParams.horizontalWeight = 1.0f;
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
150b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK)
151b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    == Gravity.FILL_VERTICAL) {
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mParams.verticalWeight = 1.0f;
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.x = mX;
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.y = mY;
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.verticalMargin = mVerticalMargin;
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.horizontalMargin = mHorizontalMargin;
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mView.getParent() != null) {
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mWM.removeView(mView);
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWM.addView(mView, mParams);
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private synchronized void handleHide() {
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mView != null) {
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // note: checking parent() just to make sure the view has
168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // been added...  i have seen cases where we get here when
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // the view isn't yet added, so let's try not to crash.
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mView.getParent() != null) {
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mWM.removeView(mView);
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mView = null;
174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
177bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final Runnable mShow = new Runnable() {
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void run() {
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleShow();
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
183bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final Runnable mHide = new Runnable() {
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void run() {
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleHide();
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
190