1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.widget;
18
19import android.content.Context;
20import android.graphics.Canvas;
21import android.util.AttributeSet;
22import android.view.View;
23import android.widget.TextView;
24
25/**
26 * This class defines a generic cling that provides on-screen instructions. A convenient
27 * method is provided here to automatically adjust the position of the cling to
28 * always be consistent with the reference view. The use of the convenient method
29 * is optional.
30 */
31public class Cling extends TextView {
32
33    private View mReferenceView = null;
34    private final int[] mLocation = new int[2];
35    private final OnLayoutChangeListener mLayoutChangeListener =
36            new OnLayoutChangeListener() {
37                @Override
38                public void onLayoutChange(View v, int left, int top, int right, int bottom,
39                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
40                    mDelayDrawingUntilNextLayout = false;
41                    // Reference view has changed layout.
42                    adjustPosition();
43                }
44            };
45    private boolean mDelayDrawingUntilNextLayout = false;
46
47    public Cling(Context context, AttributeSet attrs) {
48        super(context, attrs);
49    }
50
51    public Cling(Context context) {
52        super(context);
53    }
54
55    /**
56     * Layout on top of a reference view.
57     */
58    public void setReferenceView(View v) {
59        if (v == null) {
60            if (mReferenceView != null) {
61                // Clear up existing listeners
62                mReferenceView.removeOnLayoutChangeListener(mLayoutChangeListener);
63                mReferenceView = null;
64            }
65            return;
66        }
67        mReferenceView = v;
68        mReferenceView.addOnLayoutChangeListener(mLayoutChangeListener);
69        if (mReferenceView.getVisibility() == GONE) {
70            mDelayDrawingUntilNextLayout = true;
71        } else {
72            adjustPosition();
73        }
74    }
75
76    /**
77     * Adjust the translation of the cling to stay on top of the reference view.
78     */
79    public void adjustPosition() {
80        if (mReferenceView == null) {
81            return;
82        }
83        mReferenceView.getLocationInWindow(mLocation);
84        int refCenterX = mLocation[0] + mReferenceView.getWidth() / 2;
85        int refTopY = mLocation[1];
86        // Align center with the reference view and move on top
87        int left = refCenterX - getWidth() / 2;
88        int top = refTopY - getHeight();
89
90        getLocationInWindow(mLocation);
91        int currentLeft = mLocation[0] - (int) getTranslationX();
92        int currentTop = mLocation[1] - (int) getTranslationY();
93
94        setTranslationX(left - currentLeft);
95        setTranslationY(top - currentTop);
96    }
97
98    @Override
99    public void draw(Canvas canvas) {
100        if (mDelayDrawingUntilNextLayout) {
101            return;
102        }
103        super.draw(canvas);
104    }
105}
106