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