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.testingcamera2;
18 
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.view.LayoutInflater;
22 import android.view.View;
23 import android.widget.Button;
24 import android.widget.LinearLayout;
25 import android.widget.TextView;
26 import android.widget.ToggleButton;
27 
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30 
31 /**
32  * A base control pane, with standard abilities to collapse or remove itself.
33  */
34 public class ControlPane extends LinearLayout {
35 
36     private final StatusListener mStatusListener;
37     private String mPaneName = "unnamed";
38 
39     protected final PaneTracker mPaneTracker;
40 
41     private View[] mHeaderViews;
42 
43     private OnClickListener mRemoveButtonListener = new OnClickListener() {
44         @Override
45         public void onClick(View v) {
46             remove();
47         }
48     };
49 
50     private OnClickListener mCollapseButtonListener = new OnClickListener() {
51         private boolean mCollapsed = false;
52 
53         @Override
54         public void onClick(View v) {
55             if (mCollapsed) {
56                 mCollapsed = false;
57                 // Unhide all pane items
58                 for (int i = 0; i < ControlPane.this.getChildCount(); i++) {
59                     ControlPane.this.getChildAt(i).setVisibility(VISIBLE);
60                 }
61             } else {
62                 mCollapsed = true;
63                 // Hide all pane items
64                 for (int i = 0; i < ControlPane.this.getChildCount(); i++) {
65                     ControlPane.this.getChildAt(i).setVisibility(GONE);
66                 }
67                 // Except for the header
68                 for (int i = 0; i < mHeaderViews.length; i++) {
69                     mHeaderViews[i].setVisibility(VISIBLE);
70                 }
71             }
72         }
73     };
74 
ControlPane(Context context, AttributeSet attrs, StatusListener listener, PaneTracker paneTracker)75     public ControlPane(Context context, AttributeSet attrs, StatusListener listener,
76             PaneTracker paneTracker) {
77         super(context, attrs);
78         mStatusListener = listener;
79         mPaneTracker = paneTracker;  // Parent takes care of adding pane to tracking
80 
81         this.setOrientation(VERTICAL);
82 
83         LayoutInflater inflater = (LayoutInflater)context.getSystemService
84                 (Context.LAYOUT_INFLATER_SERVICE);
85 
86         inflater.inflate(R.layout.control_pane_header, this);
87 
88         // Add all header views into list to manage collapsing pane correctly
89         mHeaderViews = new View[getChildCount()];
90         for (int i = 0; i < getChildCount(); i++) {
91             mHeaderViews[i] = getChildAt(i);
92         }
93 
94         // Set up the header controls
95         ToggleButton collapseButton = (ToggleButton)
96                 findViewById(R.id.control_pane_collapse_button);
97         collapseButton.setOnClickListener(mCollapseButtonListener);
98 
99         Button removeButton = (Button) findViewById(R.id.control_pane_remove_button);
100         removeButton.setOnClickListener(mRemoveButtonListener);
101     }
102 
103     /**
104      * Add to pane tracking when the pane becomes part of the UI
105      */
106     @Override
onAttachedToWindow()107     public void onAttachedToWindow() {
108         super.onAttachedToWindow();
109         if (mPaneTracker != null) {
110             mPaneTracker.addPane(this);
111         }
112     }
113 
114     /**
115      * Remove this pane from its list and clean up its state
116      */
remove()117     public void remove() {
118         if (mStatusListener != null) {
119             mStatusListener.onRemoveRequested(ControlPane.this);
120         }
121         if (mPaneTracker != null ) {
122             mPaneTracker.removePane(this);
123         }
124     }
125 
126     /**
127      * Get a nice name for this pane.
128      */
getPaneName()129     public String getPaneName() {
130         return mPaneName;
131     }
132 
133     /**
134      * Listener to be implemented by an application service that handles removing this
135      * pane from the UI. Called when the pane is ready to be destroyed.
136      */
137     public interface StatusListener {
onRemoveRequested(ControlPane p)138         public void onRemoveRequested(ControlPane p);
139     }
140 
141     /**
142      * Set the name for this pane, also used as the header title.
143      */
setName(String name)144     protected void setName(String name) {
145         mPaneName = name;
146         ((TextView) findViewById(R.id.control_pane_title_text)).setText(name);
147     }
148 
149     /**
150      * Get an XML attribute as a integer; if the attribute does not exist, return the default value.
151      *
152      * @throws XmlPullParserException if parser not at a START_TAG event, or the attribute is not
153      *   formatted as a string.
154      */
getAttributeInt(XmlPullParser configParser, String attributeName, int defaultValue)155     protected static int getAttributeInt(XmlPullParser configParser,
156             String attributeName, int defaultValue) throws XmlPullParserException {
157         String value = configParser.getAttributeValue(null, attributeName);
158         if (value == null ) return defaultValue;
159 
160         try {
161             int v = Integer.parseInt(value);
162             return v;
163         } catch (NumberFormatException e) {
164             throw new XmlPullParserException("Expected integer attribute",
165                     configParser, e);
166         }
167     }
168 
169     /**
170      * Get an XML attribute as a String; if the attribute does not exist, return the default value.
171      *
172      * @throws XmlPullParserException if parser not at a START_TAG event.
173      */
getAttributeString( XmlPullParser configParser, String attributeName, String defaultValue)174     protected static String getAttributeString(
175             XmlPullParser configParser,
176             String attributeName, String defaultValue) throws XmlPullParserException {
177         String value = configParser.getAttributeValue(null, attributeName);
178         return (value == null) ? defaultValue : value;
179     }
180 
181     /**
182      * Called when other panes want to inform the rest of the app of interesting events
183      *
184      * @param sourcePane the source pane of the event
185      * @param event the type of event
186      */
notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event)187     public void notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event) {
188         // Default empty implementation
189     }
190 
191     /**
192      * Called when the app's UI orientation changes.
193      *
194      * @param orientation one of the Surface.ROTATION_* constants
195      */
onOrientationChange(int orientation)196     public void onOrientationChange(int orientation) {
197         // Default empty implementation
198     }
199 
200 }
201