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 
17 package com.android.camera.widget;
18 
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.util.SparseArray;
22 import android.view.View;
23 import android.widget.ImageButton;
24 
25 import com.android.camera.app.CameraAppUI;
26 import com.android.camera.debug.Log;
27 import 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  */
36 public 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 
ExternalViewerButton(Context context, AttributeSet attrs)41     public ExternalViewerButton(Context context, AttributeSet attrs) {
42         super(context, attrs);
43         mClingMap = new SparseArray<Cling>();
44         updateClingVisibility();
45     }
46 
47     @Override
onVisibilityChanged(View v, int visibility)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      */
setClingForViewer(int viewerType, Cling cling)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      */
clearClingForViewer(int viewerType)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      */
getClingForViewer(int viewerType)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      */
setState(int state)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      */
hideClings()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      */
getViewButtonResource(int state)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      */
updateClingVisibility()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