Adam Powell | 70e11e5 | 2012-06-12 16:59:45 -0700 | [diff] [blame^] | 1 | /* |
| 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 | |
| 17 | package com.android.internal.app; |
| 18 | |
| 19 | import com.android.internal.R; |
| 20 | |
| 21 | import android.app.Activity; |
| 22 | import android.app.DialogFragment; |
| 23 | import android.app.MediaRouteActionProvider; |
| 24 | import android.app.MediaRouteButton; |
| 25 | import android.content.Context; |
| 26 | import android.media.MediaRouter; |
| 27 | import android.media.MediaRouter.RouteCategory; |
| 28 | import android.media.MediaRouter.RouteGroup; |
| 29 | import android.media.MediaRouter.RouteInfo; |
| 30 | import android.os.Bundle; |
| 31 | import android.text.TextUtils; |
| 32 | import android.view.LayoutInflater; |
| 33 | import android.view.View; |
| 34 | import android.view.ViewGroup; |
| 35 | import android.widget.AdapterView; |
| 36 | import android.widget.BaseAdapter; |
| 37 | import android.widget.ListView; |
| 38 | import android.widget.TextView; |
| 39 | |
| 40 | import java.util.ArrayList; |
| 41 | |
| 42 | /** |
| 43 | * This class implements the route chooser dialog for {@link MediaRouter}. |
| 44 | * |
| 45 | * @see MediaRouteButton |
| 46 | * @see MediaRouteActionProvider |
| 47 | */ |
| 48 | public 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 | } |