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.util.AttributeSet;
21import android.util.SparseArray;
22import android.view.View;
23import android.widget.ImageButton;
24
25import com.android.camera.app.CameraAppUI;
26import com.android.camera.debug.Log;
27import com.android.camera2.R;
28
29/**
30 * This is a custom image button that launches an external viewer. It changes its
31 * image resource based on the current viewer type (photosphere, refocus, etc).
32 * Also, it tracks whether it is shown by tracking the visibility change of all
33 * its ancestors, and keep the visibility of the clings that are registered to the
34 * button in sync.
35 */
36public class ExternalViewerButton extends ImageButton {
37    private static final Log.Tag TAG = new Log.Tag("ExtViewerButton");
38    private int mState = CameraAppUI.BottomPanel.VIEWER_NONE;
39    private final SparseArray<Cling> mClingMap;
40
41    public ExternalViewerButton(Context context, AttributeSet attrs) {
42        super(context, attrs);
43        mClingMap = new SparseArray<Cling>();
44        updateClingVisibility();
45    }
46
47    @Override
48    protected void onVisibilityChanged(View v, int visibility) {
49        super.onVisibilityChanged(v, visibility);
50        if (mClingMap == null) {
51            return;
52        }
53        updateClingVisibility();
54    }
55
56    /**
57     * Sets cling of the given viewer type for external viewer button.
58     */
59    public void setClingForViewer(int viewerType, Cling cling) {
60        if (cling == null) {
61            Log.w(TAG, "Cannot set a null cling for viewer");
62            return;
63        }
64        mClingMap.put(viewerType, cling);
65        cling.setReferenceView(this);
66    }
67
68    /**
69     * Clears cling of the given viewer type for external viewer button.
70     */
71    public void clearClingForViewer(int viewerType) {
72        Cling cling = mClingMap.get(viewerType);
73        if (cling == null) {
74            Log.w(TAG, "Cling does not exist for the given viewer type: " + viewerType);
75        }
76        cling.setReferenceView(null);
77        mClingMap.remove(viewerType);
78    }
79
80    /**
81     * Returns a cling for the specified viewer type.
82     */
83    public Cling getClingForViewer(int viewerType) {
84        return mClingMap.get(viewerType);
85    }
86
87    /**
88     * Sets the current state of the button, which affects the visibility and image
89     * resource of the button.
90     */
91    public void setState(int state) {
92        mState = state;
93        int newVisibility;
94        if (state == CameraAppUI.BottomPanel.VIEWER_NONE) {
95            newVisibility = View.GONE;
96        } else {
97            setImageResource(getViewButtonResource(state));
98            newVisibility = View.VISIBLE;
99        }
100
101        if (newVisibility != getVisibility()) {
102            setVisibility(newVisibility);
103        } else if (newVisibility == View.VISIBLE){
104            // If visibility has changed, cling visibility was updated already,
105            // so only need to update it when visibility has not changed.
106            updateClingVisibility();
107        }
108    }
109
110    /**
111     * Sets all the clings to be invisible.
112     */
113    public void hideClings() {
114        for (int i = 0; i < mClingMap.size(); i++) {
115            mClingMap.valueAt(i).setVisibility(View.INVISIBLE);
116        }
117    }
118
119    /**
120     * Gets the image resource for a specific state.
121     */
122    private int getViewButtonResource(int state) {
123        switch (state) {
124            case CameraAppUI.BottomPanel.VIEWER_REFOCUS:
125                return R.drawable.ic_refocus_normal;
126            case CameraAppUI.BottomPanel.VIEWER_PHOTO_SPHERE:
127                return R.drawable.ic_view_photosphere;
128            default:
129                return R.drawable.ic_control_play;
130        }
131    }
132
133    /**
134     * Updates the visibility of clings based on whether the button is currently
135     * shown.
136     */
137    public void updateClingVisibility() {
138        hideClings();
139        if (isShown()) {
140            Cling cling = mClingMap.get(mState);
141            if (cling != null) {
142                cling.adjustPosition();
143                cling.setVisibility(View.VISIBLE);
144            }
145        }
146    }
147}
148