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.testingcamera2;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.view.LayoutInflater;
22import android.view.View;
23import android.widget.Button;
24import android.widget.LinearLayout;
25import android.widget.TextView;
26import android.widget.ToggleButton;
27
28import org.xmlpull.v1.XmlPullParser;
29import org.xmlpull.v1.XmlPullParserException;
30
31/**
32 * A base control pane, with standard abilities to collapse or remove itself.
33 */
34public 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
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
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     */
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     */
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 {
138        public void onRemoveRequested(ControlPane p);
139    }
140
141    /**
142     * Set the name for this pane, also used as the header title.
143     */
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     */
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     */
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     */
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     */
196    public void onOrientationChange(int orientation) {
197        // Default empty implementation
198    }
199
200}
201