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
17package com.android.car.radio;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.media.session.PlaybackState;
22import android.text.TextUtils;
23import android.view.View;
24import android.view.ViewStub;
25import android.widget.ImageView;
26import android.widget.TextView;
27
28/**
29 * Controller that controls the appearance state of various UI elements in the radio.
30 */
31public class RadioDisplayController {
32    private final Context mContext;
33
34    private TextView mChannelBand;
35    private TextView mChannelNumber;
36
37    private CarouselView mChannelList;
38
39    private TextView mCurrentSongTitle;
40    private TextView mCurrentSongArtistOrStation;
41
42    private ImageView mBackwardSeekButton;
43    private ImageView mForwardSeekButton;
44
45    private PlayPauseButton mPlayButton;
46    private PlayPauseButton mPresetPlayButton;
47
48    private ImageView mPresetsListButton;
49    private ImageView mAddPresetsButton;
50
51    public RadioDisplayController(Context context) {
52        mContext = context;
53    }
54
55    public void initialize(View container) {
56        // Note that the band and channel number can exist without the stub
57        // single_channel_view_stub. Refer to setSingleChannelDisplay() for more information.
58        mChannelBand = (TextView) container.findViewById(R.id.radio_station_band);
59        mChannelNumber = (TextView) container.findViewById(R.id.radio_station_channel);
60
61        mCurrentSongTitle = (TextView) container.findViewById(R.id.radio_station_song);
62        mCurrentSongArtistOrStation =
63                (TextView) container.findViewById(R.id.radio_station_artist_or_station);
64
65        mBackwardSeekButton = (ImageView) container.findViewById(R.id.radio_back_button);
66        mForwardSeekButton = (ImageView) container.findViewById(R.id.radio_forward_button);
67
68        mPlayButton = (PlayPauseButton) container.findViewById(R.id.radio_play_button);
69        mPresetPlayButton = (PlayPauseButton) container.findViewById(R.id.preset_radio_play_button);
70
71        mPresetsListButton = (ImageView) container.findViewById(R.id.radio_presets_list);
72        mAddPresetsButton = (ImageView) container.findViewById(R.id.radio_add_presets_button);
73    }
74
75    /**
76     * Sets this radio controller to display with a single box representing the current radio
77     * station.
78     */
79    public void setSingleChannelDisplay(View container) {
80        ViewStub stub = (ViewStub) container.findViewById(R.id.single_channel_view_stub);
81
82        if (stub != null) {
83            container = stub.inflate();
84        }
85
86        // Update references to the band and channel number.
87        mChannelBand = (TextView) container.findViewById(R.id.radio_station_band);
88        mChannelNumber = (TextView) container.findViewById(R.id.radio_station_channel);
89    }
90
91    /**
92     * Sets this controller to display a list of channels that include the current radio station as
93     * well as pre-scanned stations for the current band.
94     */
95    public void setChannelListDisplay(View container, PrescannedRadioStationAdapter adapter) {
96        ViewStub stub = (ViewStub) container.findViewById(R.id.channel_list_view_stub);
97
98        if (stub == null) {
99            return;
100        }
101
102        mChannelList = (CarouselView) stub.inflate();
103        mChannelList.setAdapter(adapter);
104
105        Resources res = mContext.getResources();
106        int topOffset = res.getDimensionPixelSize(R.dimen.lens_header_height)
107                + res.getDimensionPixelSize(R.dimen.car_radio_container_top_padding)
108                + res.getDimensionPixelSize(R.dimen.car_radio_station_top_margin);
109
110        mChannelList.setTopOffset(topOffset);
111    }
112
113    /**
114     * Set the given position as the radio station that should be be displayed first in the channel
115     * list controlled by this class.
116     */
117    public void setCurrentStationInList(int position) {
118        if (mChannelList != null) {
119            mChannelList.shiftToPosition(position);
120        }
121    }
122
123    /**
124     * Returns the View that is responsible for rendering the play/pause state.
125     */
126    public View getPlayButton() {
127        return mPlayButton;
128    }
129
130    /**
131     * Set whether or not the buttons controlled by this controller are enabled. If {@code false}
132     * is passed to this method, then no {@link View.OnClickListener}s will be
133     * triggered when the buttons are pressed. In addition, the look of the button wil be updated
134     * to reflect their disabled state.
135     */
136    public void setEnabled(boolean enabled) {
137        // Color the buttons so that they are grey in appearance if they are disabled.
138        int tint = enabled
139                ? mContext.getColor(R.color.car_radio_control_button)
140                : mContext.getColor(R.color.car_radio_control_button_disabled);
141
142        if (mPlayButton != null) {
143            // No need to tint the play button because its drawable already contains a disabled
144            // state.
145            mPlayButton.setEnabled(enabled);
146        }
147
148        if (mPresetPlayButton != null) {
149            // No need to tint the play button because its drawable already contains a disabled
150            // state.
151            mPresetPlayButton.setEnabled(enabled);
152        }
153
154        if (mForwardSeekButton != null) {
155            mForwardSeekButton.setEnabled(enabled);
156            mForwardSeekButton.setColorFilter(tint);
157        }
158
159        if (mBackwardSeekButton != null) {
160            mBackwardSeekButton.setEnabled(enabled);
161            mBackwardSeekButton.setColorFilter(tint);
162        }
163
164        if (mPresetsListButton != null) {
165            mPresetsListButton.setEnabled(enabled);
166            mPresetsListButton.setColorFilter(tint);
167        }
168
169        if (mAddPresetsButton != null) {
170            mAddPresetsButton.setEnabled(enabled);
171            mAddPresetsButton.setColorFilter(tint);
172        }
173    }
174
175    /**
176     * Sets the {@link android.view.View.OnClickListener} for the backwards seek button.
177     */
178    public void setBackwardSeekButtonListener(View.OnClickListener listener) {
179        if (mBackwardSeekButton != null) {
180            mBackwardSeekButton.setOnClickListener(listener);
181        }
182    }
183
184    /**
185     * Sets the {@link android.view.View.OnClickListener} for the forward seek button.
186     */
187    public void setForwardSeekButtonListener(View.OnClickListener listener) {
188        if (mForwardSeekButton != null) {
189            mForwardSeekButton.setOnClickListener(listener);
190        }
191    }
192
193    /**
194     * Sets the {@link android.view.View.OnClickListener} for the play button. Clicking on this
195     * button should toggle the radio from muted to un-muted.
196     */
197    public void setPlayButtonListener(View.OnClickListener listener) {
198        if (mPlayButton != null) {
199            mPlayButton.setOnClickListener(listener);
200        }
201
202        if (mPresetPlayButton != null) {
203            mPresetPlayButton.setOnClickListener(listener);
204        }
205    }
206
207    /**
208     * Sets the {@link android.view.View.OnClickListener} for the button that will add the current
209     * radio station to a list of stored presets.
210     */
211    public void setAddPresetButtonListener(View.OnClickListener listener) {
212        if (mAddPresetsButton != null) {
213            mAddPresetsButton.setOnClickListener(listener);
214        }
215    }
216
217    /**
218     * Sets the current radio channel (e.g. 88.5).
219     */
220    public void setChannelNumber(String channel) {
221        if (mChannelNumber != null) {
222            mChannelNumber.setText(channel);
223        }
224    }
225
226    /**
227     * Sets the radio channel band (e.g. FM).
228     */
229    public void setChannelBand(String channelBand) {
230        if (mChannelBand != null) {
231            mChannelBand.setText(channelBand);
232            mChannelBand.setVisibility(
233                    !TextUtils.isEmpty(channelBand) ? View.VISIBLE : View.GONE);
234        }
235    }
236
237    /**
238     * Sets the title of the currently playing song.
239     */
240    public void setCurrentSongTitle(String songTitle) {
241        if (mCurrentSongTitle != null) {
242            boolean isEmpty = TextUtils.isEmpty(songTitle);
243            mCurrentSongTitle.setText(isEmpty ? null : songTitle.trim());
244            mCurrentSongTitle.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
245        }
246    }
247
248    /**
249     * Sets the artist(s) of the currently playing song or current radio station information
250     * (e.g. KOIT).
251     */
252    public void setCurrentSongArtistOrStation(String songArtist) {
253        if (mCurrentSongArtistOrStation != null) {
254            boolean isEmpty = TextUtils.isEmpty(songArtist);
255            mCurrentSongArtistOrStation.setText(isEmpty ? null : songArtist.trim());
256            mCurrentSongArtistOrStation.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
257        }
258    }
259
260    /**
261     * Sets the current state of the play button. If the given {@code muted} value is {@code true},
262     * then the button display a play icon. If {@code false}, then the button will display a
263     * pause icon.
264     */
265    public void setPlayPauseButtonState(boolean muted) {
266        if (mPlayButton != null) {
267            mPlayButton.setPlayState(muted
268                    ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING);
269            mPlayButton.refreshDrawableState();
270        }
271
272        if (mPresetPlayButton != null) {
273            mPresetPlayButton.setPlayState(muted
274                    ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING);
275            mPresetPlayButton.refreshDrawableState();
276        }
277    }
278
279    /**
280     * Sets whether or not the current channel that is playing is a preset. If it is, then the
281     * icon in {@link #mPresetsListButton} will be updatd to reflect this state.
282     */
283    public void setChannelIsPreset(boolean isPreset) {
284        if (mAddPresetsButton != null) {
285            mAddPresetsButton.setImageResource(isPreset
286                    ? R.drawable.ic_star_filled
287                    : R.drawable.ic_star_empty);
288        }
289    }
290}
291