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