content: /*
   * Copyright (C) 2013 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.internal.app;
  
  import com.android.internal.R;
  
  import android.app.Dialog;
  import android.content.Context;
  import android.media.MediaRouter;
  import android.media.MediaRouter.RouteInfo;
  import android.os.Bundle;
  import android.text.TextUtils;
  import android.util.TypedValue;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.Window;
  import android.widget.AdapterView;
  import android.widget.ArrayAdapter;
  import android.widget.Button;
  import android.widget.ListView;
  import android.widget.TextView;
  
  import java.util.Comparator;
  
  /**
   * This class implements the route chooser dialog for {@link MediaRouter}.
   * <p>
   * This dialog allows the user to choose a route that matches a given selector.
   * </p>
   *
   * @see MediaRouteButton
   * @see MediaRouteActionProvider
   *
   * TODO: Move this back into the API, as in the support library media router.
   */
  public class MediaRouteChooserDialog extends Dialog {
      private final MediaRouter mRouter;
      private final MediaRouterCallback mCallback;
  
      private int mRouteTypes;
      private View.OnClickListener mExtendedSettingsClickListener;
      private RouteAdapter mAdapter;
      private ListView mListView;
      private Button mExtendedSettingsButton;
      private boolean mAttachedToWindow;
  
      public MediaRouteChooserDialog(Context context, int theme) {
          super(context, theme);
  
          mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
          mCallback = new MediaRouterCallback();
      }
  
      /**
       * Gets the media route types for filtering the routes that the user can
       * select using the media route chooser dialog.
       *
       * @return The route types.
       */
      public int getRouteTypes() {
          return mRouteTypes;
      }
  
      /**
       * Sets the types of routes that will be shown in the media route chooser dialog
       * launched by this button.
       *
       * @param types The route types to match.
       */
      public void setRouteTypes(int types) {
          if (mRouteTypes != types) {
              mRouteTypes = types;
  
              if (mAttachedToWindow) {
                  mRouter.removeCallback(mCallback);
                  mRouter.addCallback(types, mCallback,
                          MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
              }
  
              refreshRoutes();
          }
      }
  
      public void setExtendedSettingsClickListener(View.OnClickListener listener) {
          if (listener != mExtendedSettingsClickListener) {
              mExtendedSettingsClickListener = listener;
              updateExtendedSettingsButton();
          }
      }
  
      /**
       * Returns true if the route should be included in the list.
       * <p>
       * The default implementation returns true for enabled non-default routes that
       * match the route types.  Subclasses can override this method to filter routes
       * differently.
       * </p>
       *
       * @param route The route to consider, never null.
       * @return True if the route should be included in the chooser dialog.
       */
      public boolean onFilterRoute(MediaRouter.RouteInfo route) {
          return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes);
      }
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
  
          setContentView(R.layout.media_route_chooser_dialog);
          setTitle(mRouteTypes == MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY
                  ? R.string.media_route_chooser_title_for_remote_display
                  : R.string.media_route_chooser_title);
  
          // Must be called after setContentView.
          getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
                  isLightTheme(getContext()) ? R.drawable.ic_media_route_off_holo_light
                      : R.drawable.ic_media_route_off_holo_dark);
  
          mAdapter = new RouteAdapter(getContext());
          mListView = (ListView)findViewById(R.id.media_route_list);
          mListView.setAdapter(mAdapter);
          mListView.setOnItemClickListener(mAdapter);
          mListView.setEmptyView(findViewById(android.R.id.empty));
  
          mExtendedSettingsButton = (Button)findViewById(R.id.media_route_extended_settings_button);
          updateExtendedSettingsButton();
      }
  
      private void updateExtendedSettingsButton() {
          if (mExtendedSettingsButton != null) {
              mExtendedSettingsButton.setOnClickListener(mExtendedSettingsClickListener);
              mExtendedSettingsButton.setVisibility(
                      mExtendedSettingsClickListener != null ? View.VISIBLE : View.GONE);
          }
      }
  
      @Override
      public void onAttachedToWindow() {
          super.onAttachedToWindow();
  
          mAttachedToWindow = true;
          mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
          refreshRoutes();
      }
  
      @Override
      public void onDetachedFromWindow() {
          mAttachedToWindow = false;
          mRouter.removeCallback(mCallback);
  
          super.onDetachedFromWindow();
      }
  
      /**
       * Refreshes the list of routes that are shown in the chooser dialog.
       */
      public void refreshRoutes() {
          if (mAttachedToWindow) {
              mAdapter.update();
          }
      }
  
      static boolean isLightTheme(Context context) {
          TypedValue value = new TypedValue();
          return context.getTheme().resolveAttribute(R.attr.isLightTheme, value, true)
                  && value.data != 0;
      }
  
      private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
              implements ListView.OnItemClickListener {
          private final LayoutInflater mInflater;
  
          public RouteAdapter(Context context) {
              super(context, 0);
              mInflater = LayoutInflater.from(context);
          }
  
          public void update() {
              clear();
              final int count = mRouter.getRouteCount();
              for (int i = 0; i < count; i++) {
                  MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
                  if (onFilterRoute(route)) {
                      add(route);
                  }
              }
              sort(RouteComparator.sInstance);
              notifyDataSetChanged();
          }
  
          @Override
          public boolean areAllItemsEnabled() {
              return false;
          }
  
          @Override
          public boolean isEnabled(int position) {
              return getItem(position).isEnabled();
          }
  
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              View view = convertView;
              if (view == null) {
                  view = mInflater.inflate(R.layout.media_route_list_item, parent, false);
              }
              MediaRouter.RouteInfo route = getItem(position);
              TextView text1 = (TextView)view.findViewById(android.R.id.text1);
              TextView text2 = (TextView)view.findViewById(android.R.id.text2);
              text1.setText(route.getName());
              CharSequence description = route.getDescription();
              if (TextUtils.isEmpty(description)) {
                  text2.setVisibility(View.GONE);
                  text2.setText("");
              } else {
                  text2.setVisibility(View.VISIBLE);
                  text2.setText(description);
              }
              view.setEnabled(route.isEnabled());
              return view;
          }
  
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
              MediaRouter.RouteInfo route = getItem(position);
              if (route.isEnabled()) {
                  route.select();
                  dismiss();
              }
          }
      }
  
      private final class MediaRouterCallback extends MediaRouter.SimpleCallback {
          @Override
          public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
              refreshRoutes();
          }
  
          @Override
          public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
              refreshRoutes();
          }
  
          @Override
          public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
              refreshRoutes();
          }
  
          @Override
          public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
              dismiss();
          }
      }
  
      private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> {
          public static final RouteComparator sInstance = new RouteComparator();
  
          @Override
          public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) {
              return lhs.getName().toString().compareTo(rhs.getName().toString());
          }
      }
  }
  