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