blob: 000eee74562d6b4e84bb8422b56ac63d5e289ea8 [file] [log] [blame]
Adam Powell70e11e52012-06-12 16:59:45 -07001/*
2 * Copyright (C) 2012 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.internal.app;
18
19import com.android.internal.R;
20
21import android.app.Activity;
22import android.app.DialogFragment;
23import android.app.MediaRouteActionProvider;
24import android.app.MediaRouteButton;
25import android.content.Context;
26import android.media.MediaRouter;
27import android.media.MediaRouter.RouteCategory;
28import android.media.MediaRouter.RouteGroup;
29import android.media.MediaRouter.RouteInfo;
30import android.os.Bundle;
31import android.text.TextUtils;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35import android.widget.AdapterView;
36import android.widget.BaseAdapter;
37import android.widget.ListView;
38import android.widget.TextView;
39
40import java.util.ArrayList;
41
42/**
43 * This class implements the route chooser dialog for {@link MediaRouter}.
44 *
45 * @see MediaRouteButton
46 * @see MediaRouteActionProvider
47 */
48public class MediaRouteChooserDialogFragment extends DialogFragment {
49 private static final String TAG = "MediaRouteChooserDialogFragment";
50 public static final String FRAGMENT_TAG = "android:MediaRouteChooserDialogFragment";
51
52 MediaRouter mRouter;
53 private int mRouteTypes;
54
55 private LauncherListener mLauncherListener;
56 private View.OnClickListener mExtendedSettingsListener;
57 private RouteAdapter mAdapter;
58 private ListView mListView;
59
60 public MediaRouteChooserDialogFragment() {
61 setStyle(STYLE_NO_TITLE, R.style.Theme_DeviceDefault_Dialog);
62 }
63
64 public void setLauncherListener(LauncherListener listener) {
65 mLauncherListener = listener;
66 }
67
68 @Override
69 public void onAttach(Activity activity) {
70 super.onAttach(activity);
71 mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
72 }
73
74 @Override
75 public void onDetach() {
76 super.onDetach();
77 if (mLauncherListener != null) {
78 mLauncherListener.onDetached(this);
79 }
80 if (mAdapter != null) {
81 mRouter.removeCallback(mAdapter);
82 mAdapter = null;
83 }
84 mRouter = null;
85 }
86
87 /**
88 * Implemented by the MediaRouteButton that launched this dialog
89 */
90 public interface LauncherListener {
91 public void onDetached(MediaRouteChooserDialogFragment detachedFragment);
92 }
93
94 public void setExtendedSettingsClickListener(View.OnClickListener listener) {
95 mExtendedSettingsListener = listener;
96 }
97
98 public void setRouteTypes(int types) {
99 mRouteTypes = types;
100 }
101
102 @Override
103 public View onCreateView(LayoutInflater inflater, ViewGroup container,
104 Bundle savedInstanceState) {
105 final View layout = inflater.inflate(R.layout.media_route_chooser_layout, container, false);
106 final View extendedSettingsButton = layout.findViewById(R.id.extended_settings);
107
108 if (mExtendedSettingsListener != null) {
109 extendedSettingsButton.setVisibility(View.VISIBLE);
110 extendedSettingsButton.setOnClickListener(mExtendedSettingsListener);
111 }
112
113 final ListView list = (ListView) layout.findViewById(R.id.list);
114 list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
115 list.setAdapter(mAdapter = new RouteAdapter(inflater));
116 list.setItemChecked(mAdapter.getSelectedRoutePosition(), true);
117 list.setOnItemClickListener(mAdapter);
118
119 mListView = list;
120 mRouter.addCallback(mRouteTypes, mAdapter);
121
122 return layout;
123 }
124
125 private static final int[] ITEM_LAYOUTS = new int[] {
126 R.layout.media_route_list_item_top_header,
127 R.layout.media_route_list_item_section_header,
128 R.layout.media_route_list_item
129 };
130
131 private class RouteAdapter extends BaseAdapter implements MediaRouter.Callback,
132 ListView.OnItemClickListener {
133 private static final int VIEW_TOP_HEADER = 0;
134 private static final int VIEW_SECTION_HEADER = 1;
135 private static final int VIEW_ROUTE = 2;
136
137 private int mSelectedItemPosition;
138 private final ArrayList<Object> mItems = new ArrayList<Object>();
139 private final LayoutInflater mInflater;
140
141 RouteAdapter(LayoutInflater inflater) {
142 mInflater = inflater;
143 update();
144 }
145
146 void update() {
147 // TODO this is kind of naive, but our data sets are going to be
148 // fairly small on average.
149 mItems.clear();
150
151 final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
152
153 final ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
154 final int catCount = mRouter.getCategoryCount();
155 for (int i = 0; i < catCount; i++) {
156 final RouteCategory cat = mRouter.getCategoryAt(i);
157 cat.getRoutes(routes);
158
159 mItems.add(cat);
160
161 final int routeCount = routes.size();
162 for (int j = 0; j < routeCount; j++) {
163 final RouteInfo info = routes.get(j);
164 if (info == selectedRoute) {
165 mSelectedItemPosition = mItems.size();
166 }
167 mItems.add(info);
168 }
169 }
170
171 notifyDataSetChanged();
172 if (mListView != null) {
173 mListView.setItemChecked(mSelectedItemPosition, true);
174 }
175 }
176
177 @Override
178 public int getCount() {
179 return mItems.size();
180 }
181
182 @Override
183 public int getViewTypeCount() {
184 return 3;
185 }
186
187 @Override
188 public int getItemViewType(int position) {
189 final Object item = getItem(position);
190 if (item instanceof RouteCategory) {
191 return position == 0 ? VIEW_TOP_HEADER : VIEW_SECTION_HEADER;
192 } else {
193 return VIEW_ROUTE;
194 }
195 }
196
197 @Override
198 public boolean areAllItemsEnabled() {
199 return false;
200 }
201
202 @Override
203 public boolean isEnabled(int position) {
204 return getItemViewType(position) == VIEW_ROUTE;
205 }
206
207 @Override
208 public Object getItem(int position) {
209 return mItems.get(position);
210 }
211
212 @Override
213 public long getItemId(int position) {
214 return position;
215 }
216
217 @Override
218 public View getView(int position, View convertView, ViewGroup parent) {
219 final int viewType = getItemViewType(position);
220
221 ViewHolder holder;
222 if (convertView == null) {
223 convertView = mInflater.inflate(ITEM_LAYOUTS[viewType], parent, false);
224 holder = new ViewHolder();
225 holder.text1 = (TextView) convertView.findViewById(R.id.text1);
226 holder.text2 = (TextView) convertView.findViewById(R.id.text2);
227 convertView.setTag(holder);
228 } else {
229 holder = (ViewHolder) convertView.getTag();
230 }
231
232 if (viewType == VIEW_ROUTE) {
233 bindItemView(position, holder);
234 } else {
235 bindHeaderView(position, holder);
236 }
237
238 return convertView;
239 }
240
241 void bindItemView(int position, ViewHolder holder) {
242 RouteInfo info = (RouteInfo) mItems.get(position);
243 holder.text1.setText(info.getName());
244 final CharSequence status = info.getStatus();
245 if (TextUtils.isEmpty(status)) {
246 holder.text2.setVisibility(View.GONE);
247 } else {
248 holder.text2.setVisibility(View.VISIBLE);
249 holder.text2.setText(status);
250 }
251 }
252
253 void bindHeaderView(int position, ViewHolder holder) {
254 RouteCategory cat = (RouteCategory) mItems.get(position);
255 holder.text1.setText(cat.getName());
256 }
257
258 public int getSelectedRoutePosition() {
259 return mSelectedItemPosition;
260 }
261
262 @Override
263 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
264 update();
265 }
266
267 @Override
268 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
269 update();
270 }
271
272 @Override
273 public void onRouteAdded(MediaRouter router, RouteInfo info) {
274 update();
275 }
276
277 @Override
278 public void onRouteRemoved(MediaRouter router, RouteInfo info) {
279 update();
280 }
281
282 @Override
283 public void onRouteChanged(MediaRouter router, RouteInfo info) {
284 notifyDataSetChanged();
285 }
286
287 @Override
288 public void onRouteGrouped(MediaRouter router, RouteInfo info,
289 RouteGroup group, int index) {
290 update();
291 }
292
293 @Override
294 public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
295 update();
296 }
297
298 @Override
299 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
300 ListView lv = (ListView) parent;
301 final Object item = getItem(lv.getCheckedItemPosition());
302 if (!(item instanceof RouteInfo)) {
303 // Oops. Stale event running around? Skip it.
304 return;
305 }
306 mRouter.selectRoute(mRouteTypes, (RouteInfo) item);
307 dismiss();
308 }
309 }
310
311 private static class ViewHolder {
312 public TextView text1;
313 public TextView text2;
314 }
315
316 private class GroupAdapter extends BaseAdapter {
317 @Override
318 public int getCount() {
319 // TODO Auto-generated method stub
320 return 0;
321 }
322
323 @Override
324 public Object getItem(int position) {
325 // TODO Auto-generated method stub
326 return null;
327 }
328
329 @Override
330 public long getItemId(int position) {
331 // TODO Auto-generated method stub
332 return 0;
333 }
334
335 @Override
336 public View getView(int position, View convertView, ViewGroup parent) {
337 // TODO Auto-generated method stub
338 return null;
339 }
340 }
341}