Home | History | Annotate | Download | only in radio
      1 /*
      2  * Copyright (C) 2016 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.car.radio;
     18 
     19 import android.support.annotation.Nullable;
     20 import android.util.Log;
     21 import android.view.LayoutInflater;
     22 import android.view.View;
     23 import android.view.ViewGroup;
     24 import android.widget.TextView;
     25 
     26 import com.android.car.radio.service.RadioStation;
     27 
     28 import java.util.List;
     29 
     30 /**
     31  * A {@link com.android.car.radio.CarouselView.Adapter} that supplies the views to be displayed
     32  * from a list of {@link RadioStation}s.
     33  */
     34 public class PrescannedRadioStationAdapter extends CarouselView.Adapter {
     35     private static final String TAG = "PreScanAdapter";
     36 
     37     private List<RadioStation> mStations;
     38     private int mCurrentPosition;
     39 
     40     /**
     41      * Sets the {@link RadioStation}s that will be used to bind to the views to be displayed.
     42      */
     43     public void setStations(List<RadioStation> stations) {
     44         mStations = stations;
     45         notifyDataSetChanged();
     46     }
     47 
     48     /**
     49      * Sets the the station within the list passed to {@link #setStations(List)} that should be
     50      * the first station displayed. A station is identified by the channel number and band.
     51      *
     52      * @return The index within the list of stations passed to {@link #setStations(List)} that the
     53      * starting station can be found at.
     54      */
     55     public int setStartingStation(int channelNumber, int band) {
     56         getIndexOrInsertForStation(channelNumber, band);
     57         return mCurrentPosition;
     58     }
     59 
     60     /**
     61      * Returns the station that is currently the first station to be displayed. This value can be
     62      * different from the value returned by {@link #setStartingStation(int, int)} if either
     63      * {@link #getPrevStation()} or {@link #getNextStation()} have been called.
     64      */
     65     public int getCurrentPosition() {
     66         return mCurrentPosition;
     67     }
     68 
     69     /**
     70      * Returns the previous station in the list based off the value returned by
     71      * {@link #getCurrentPosition()}. After calling this method, the current position returned by
     72      * that method will be the index of the {@link RadioStation} returned by this method.
     73      */
     74     @Nullable
     75     public RadioStation getPrevStation() {
     76         if (mStations == null) {
     77             return null;
     78         }
     79 
     80         if (--mCurrentPosition < 0) {
     81             mCurrentPosition = mStations.size() - 1;
     82         }
     83 
     84         return mStations.get(mCurrentPosition);
     85     }
     86 
     87     /**
     88      * Returns the next station in the list based off the value returned by
     89      * {@link #getCurrentPosition()}. After calling this method, the current position returned by
     90      * that method will be the index of the {@link RadioStation} returned by this method.
     91      */
     92     @Nullable
     93     public RadioStation getNextStation() {
     94         if (mStations == null) {
     95             return null;
     96         }
     97 
     98         if (++mCurrentPosition >= mStations.size()) {
     99             mCurrentPosition = 0;
    100         }
    101 
    102         return mStations.get(mCurrentPosition);
    103     }
    104 
    105     /**
    106      * Returns the index in the list set in {@link #setStations(List)} that corresponds to the
    107      * given channel number and band. If the given combination does not exist within the list, then
    108      * it will be inserted in ascending order.
    109      *
    110      * @return An index into the list or -1 if no list of stations has been set.
    111      */
    112     public int getIndexOrInsertForStation(int channelNumber, int band) {
    113         if (mStations == null) {
    114             mCurrentPosition = -1;
    115             return -1;
    116         }
    117 
    118         int indexToInsert = 0;
    119 
    120         for (int i = 0, size = mStations.size(); i < size; i++) {
    121             RadioStation station = mStations.get(i);
    122 
    123             if (channelNumber >= station.getChannelNumber()) {
    124                 // Need to add 1 to the index because the channel should be inserted after it.
    125                 indexToInsert = i + 1;
    126             }
    127 
    128             if (station.getChannelNumber() == channelNumber && station.getRadioBand() == band) {
    129                 mCurrentPosition = i;
    130                 return i;
    131             }
    132         }
    133 
    134         // If this path is reached, that means an exact match for the station was not found in
    135         // the given list. Instead, insert the station into the list and return that index.
    136         RadioStation stationToInsert = new RadioStation(channelNumber, 0 /* subChannel */,
    137                 band, null /* rds */);
    138         mStations.add(indexToInsert, stationToInsert);
    139         notifyDataSetChanged();
    140 
    141         mCurrentPosition = indexToInsert;
    142         return indexToInsert;
    143     }
    144 
    145     @Override
    146     public View createView(ViewGroup parent) {
    147         return LayoutInflater.from(parent.getContext()).inflate(R.layout.radio_channel, parent,
    148                 false);
    149     }
    150 
    151     @Override
    152     public void bindView(View view, int position, boolean isFirstView) {
    153         if (Log.isLoggable(TAG, Log.DEBUG)) {
    154             Log.d(TAG, "bindView(); position: " + position + "; isFirstView: " + isFirstView);
    155         }
    156 
    157         if (mStations == null || position < 0 || position >= mStations.size()) {
    158             return;
    159         }
    160 
    161         TextView radioChannel = view.findViewById(R.id.radio_list_station_channel);
    162         TextView radioBandView = view.findViewById(R.id.radio_list_station_band);
    163 
    164         RadioStation station = mStations.get(position);
    165 
    166         if (Log.isLoggable(TAG, Log.DEBUG)) {
    167             Log.d(TAG, "binding station: " + station);
    168         }
    169 
    170         int radioBand = station.getRadioBand();
    171 
    172         radioChannel.setText(RadioChannelFormatter.formatRadioChannel(radioBand,
    173                 station.getChannelNumber()));
    174 
    175         if (isFirstView) {
    176             radioBandView.setText(RadioChannelFormatter.formatRadioBand(view.getContext(),
    177                     radioBand));
    178         } else {
    179             radioBandView.setText(null);
    180         }
    181     }
    182 
    183     @Override
    184     public int getItemCount() {
    185         return mStations == null ? 0 : mStations.size();
    186     }
    187 }
    188