18872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/*
28872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Copyright (C) 2009 The Android Open Source Project
38872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
48872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * you may not use this file except in compliance with the License.
68872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * You may obtain a copy of the License at
78872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
88872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Unless required by applicable law or agreed to in writing, software
118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * See the License for the specific language governing permissions and
148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * limitations under the License.
158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpackage com.android.camera;
188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
19e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newbergerimport android.app.Activity;
208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Context;
218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.graphics.PixelFormat;
228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.os.Handler;
238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.Gravity;
248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.LayoutInflater;
258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.View;
268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.WindowManager;
278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.widget.TextView;
288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
295596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log;
308e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R;
3154987e8d3af88214ce4f3aed0b5c4e9ded5b1392John Reck
328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/**
338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * A on-screen hint is a view containing a little message for the user and will
348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * be shown on the screen continuously.  This class helps you create and show
358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * those.
368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * <p>
388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * When the view is shown to the user, appears as a floating view over the
398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * application.
408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * <p>
418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * The easiest way to use this class is to call one of the static methods that
428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * constructs everything you need and returns a new {@code OnScreenHint} object.
438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpublic class OnScreenHint {
455596b4c902dcb685928b43678f428746ca5ffd08Angus Kong    static final Log.Tag TAG = new Log.Tag("OnScreenHint");
468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    int mX, mY;
498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    float mHorizontalMargin;
508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    float mVerticalMargin;
518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    View mView;
528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    View mNextView;
538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private final WindowManager.LayoutParams mParams =
558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            new WindowManager.LayoutParams();
568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private final WindowManager mWM;
578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private final Handler mHandler = new Handler();
588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    /**
608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * Construct an empty OnScreenHint object.
618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *
628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * @param context  The context to use.  Usually your
638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *                 {@link android.app.Application} or
648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *                 {@link android.app.Activity} object.
658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     */
66e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger    private OnScreenHint(Activity activity) {
67e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger        mWM = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
68e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger        mY = activity.getResources().getDimensionPixelSize(
698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                R.dimen.hint_y_offset);
708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.format = PixelFormat.TRANSLUCENT;
768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.windowAnimations = R.style.Animation_OnScreenHint;
778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mParams.setTitle("OnScreenHint");
798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    /**
828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * Show the view on the screen.
838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     */
848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void show() {
858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mNextView == null) {
868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            throw new RuntimeException("View is not initialized");
878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mHandler.post(mShow);
898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    /**
928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * Close the view if it's showing.
938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     */
948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void cancel() {
958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mHandler.post(mHide);
968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    /**
998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * Make a standard hint that just contains a text view.
1008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *
1018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * @param context  The context to use.  Usually your
1028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *                 {@link android.app.Application} or
1038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *                 {@link android.app.Activity} object.
1048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * @param text     The text to show.  Can be formatted text.
1058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     *
1068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     */
107e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger    public static OnScreenHint makeText(Activity activity, CharSequence text) {
108e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger        OnScreenHint result = new OnScreenHint(activity);
1098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        LayoutInflater inflate =
111e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger                (LayoutInflater) activity.getSystemService(
1128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                Context.LAYOUT_INFLATER_SERVICE);
1138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        View v = inflate.inflate(R.layout.on_screen_hint, null);
1148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        TextView tv = (TextView) v.findViewById(R.id.message);
1158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        tv.setText(text);
1168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        result.mNextView = v;
1188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return result;
1208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    /**
1238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * Update the text in a OnScreenHint that was previously created using one
1248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * of the makeText() methods.
1258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     * @param s The new text for the OnScreenHint.
1268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb     */
1278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void setText(CharSequence s) {
1288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mNextView == null) {
1298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            throw new RuntimeException("This OnScreenHint was not "
1308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    + "created with OnScreenHint.makeText()");
1318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        TextView tv = (TextView) mNextView.findViewById(R.id.message);
1338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (tv == null) {
1348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            throw new RuntimeException("This OnScreenHint was not "
1358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    + "created with OnScreenHint.makeText()");
1368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        tv.setText(s);
1388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private synchronized void handleShow() {
1418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mView != mNextView) {
1428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // remove the old view if necessary
1438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            handleHide();
1448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mView = mNextView;
1458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            final int gravity = mGravity;
1468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mParams.gravity = gravity;
1478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK)
1488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    == Gravity.FILL_HORIZONTAL) {
1498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mParams.horizontalWeight = 1.0f;
1508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK)
1528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    == Gravity.FILL_VERTICAL) {
1538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mParams.verticalWeight = 1.0f;
1548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mParams.x = mX;
1568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mParams.y = mY;
1578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mParams.verticalMargin = mVerticalMargin;
1588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mParams.horizontalMargin = mHorizontalMargin;
1598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mView.getParent() != null) {
1608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mWM.removeView(mView);
1618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mWM.addView(mView, mParams);
1638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private synchronized void handleHide() {
1678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mView != null) {
1688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // note: checking parent() just to make sure the view has
1698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // been added...  i have seen cases where we get here when
1708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // the view isn't yet added, so let's try not to crash.
1718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mView.getParent() != null) {
1728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                mWM.removeView(mView);
1738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mView = null;
1758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private final Runnable mShow = new Runnable() {
1798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void run() {
1818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            handleShow();
1828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    };
1848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private final Runnable mHide = new Runnable() {
1868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void run() {
1888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            handleHide();
1898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    };
1918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb}
192