/* * Copyright (C) 2015 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.tv.ui.sidepanel; import android.media.tv.TvContract.Channels; import android.os.Bundle; import android.support.v17.leanback.widget.VerticalGridView; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.android.tv.MainActivity; import com.android.tv.R; import com.android.tv.data.Channel; import com.android.tv.data.ChannelNumber; import com.android.tv.ui.OnRepeatedKeyInterceptListener; import com.android.tv.util.TvInputManagerHelper; import com.android.tv.util.Utils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Iterator; public class CustomizeChannelListFragment extends SideFragment { private static final int GROUP_BY_SOURCE = 0; private static final int GROUP_BY_HD_SD = 1; private static final String TRACKER_LABEL = "customize channel list"; private final List mChannels = new ArrayList<>(); private final long mInitialChannelId; private long mLastFocusedChannelId = Channel.INVALID_ID; private int mGroupingType = GROUP_BY_SOURCE; private TvInputManagerHelper mInputManager; private Channel.DefaultComparator mChannelComparator; private boolean mGroupByFragmentRunning; private final List mItems = new ArrayList<>(); public CustomizeChannelListFragment() { this(Channel.INVALID_ID); } public CustomizeChannelListFragment(long initialChannelId) { mInitialChannelId = initialChannelId; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mInputManager = getMainActivity().getTvInputManagerHelper(); mChannelComparator = new Channel.DefaultComparator(getActivity(), mInputManager); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); VerticalGridView listView = (VerticalGridView) view.findViewById(R.id.side_panel_list); listView.setOnKeyInterceptListener(new OnRepeatedKeyInterceptListener(listView) { @Override public boolean onInterceptKeyEvent(KeyEvent event) { // In order to send tune operation once for continuous channel up/down events, // we only call the moveToChannel method on ACTION_UP event of channel switch keys. if (event.getAction() == KeyEvent.ACTION_UP) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: if (mLastFocusedChannelId != Channel.INVALID_ID) { getMainActivity().tuneToChannel( getChannelDataManager().getChannel(mLastFocusedChannelId)); } break; } } return super.onInterceptKeyEvent(event); } }); if (!mGroupByFragmentRunning) { getMainActivity().startShrunkenTvView(false, true); int initialChannelPosition = INVALID_POSITION; int i = 0; for (Item item : mItems) { if (item instanceof ChannelItem && ((ChannelItem) item).getChannel().getId() == mInitialChannelId) { initialChannelPosition = i; break; } ++i; } if (initialChannelPosition != INVALID_POSITION) { setSelectedPosition(initialChannelPosition); } else { setSelectedPosition(0); } mLastFocusedChannelId = mInitialChannelId; MainActivity tvActivity = getMainActivity(); if (mLastFocusedChannelId != Channel.INVALID_ID && mLastFocusedChannelId != tvActivity.getCurrentChannelId()) { tvActivity.tuneToChannel(getChannelDataManager().getChannel(mLastFocusedChannelId)); } } mGroupByFragmentRunning = false; return view; } @Override public void onDestroyView() { getChannelDataManager().applyUpdatedValuesToDb(); if (!mGroupByFragmentRunning) { getMainActivity().endShrunkenTvView(); } super.onDestroyView(); } @Override protected String getTitle() { return getString(R.string.side_panel_title_edit_channels_for_an_input); } @Override public String getTrackerLabel() { return TRACKER_LABEL; } @Override protected List getItemList() { mItems.clear(); mChannels.clear(); mChannels.addAll(getChannelDataManager().getChannelList()); if (mGroupingType == GROUP_BY_SOURCE) { addItemForGroupBySource(mItems); } else { // GROUP_BY_HD_SD addItemForGroupByHdSd(mItems); } return mItems; } private void cleanUpOneChannelGroupItem(List items) { Iterator iter = items.iterator(); while (iter.hasNext()) { Item item = iter.next(); if (item instanceof SelectGroupItem) { SelectGroupItem selectGroupItem = (SelectGroupItem) item; if (selectGroupItem.mChannelItemsInGroup.size() == 1) { selectGroupItem.mChannelItemsInGroup.get(0).mSelectGroupItem = null; iter.remove(); } } } } private void addItemForGroupBySource(List items) { items.add(new GroupBySubMenu(getString(R.string.edit_channels_group_by_sources))); SelectGroupItem selectGroupItem = null; ArrayList channels = new ArrayList<>(mChannels); Collections.sort(channels, mChannelComparator); String inputId = null; for (Channel channel: channels) { if (!channel.getInputId().equals(inputId)) { inputId = channel.getInputId(); String inputLabel = Utils.loadLabel(getActivity(), mInputManager.getTvInputInfo(inputId)); items.add(new DividerItem(inputLabel)); selectGroupItem = new SelectGroupItem(); items.add(selectGroupItem); } ChannelItem channelItem = new ChannelItem(channel, selectGroupItem); items.add(channelItem); selectGroupItem.addChannelItem(channelItem); } cleanUpOneChannelGroupItem(items); } private void addItemForGroupByHdSd(List items) { items.add(new GroupBySubMenu(getString(R.string.edit_channels_group_by_hd_sd))); SelectGroupItem selectGroupItem = null; ArrayList channels = new ArrayList<>(mChannels); Collections.sort(channels, new Comparator() { @Override public int compare(Channel lhs, Channel rhs) { boolean lhsHd = isHdChannel(lhs); boolean rhsHd = isHdChannel(rhs); if (lhsHd == rhsHd) { return ChannelNumber.compare(lhs.getDisplayNumber(), rhs.getDisplayNumber()); } else { return lhsHd ? -1 : 1; } } }); Boolean isHdGroup = null; for (Channel channel: channels) { boolean isHd = isHdChannel(channel); if (isHdGroup == null || isHd != isHdGroup) { isHdGroup = isHd; items.add(new DividerItem(isHd ? getString(R.string.edit_channels_group_divider_for_hd) : getString(R.string.edit_channels_group_divider_for_sd))); selectGroupItem = new SelectGroupItem(); items.add(selectGroupItem); } ChannelItem channelItem = new ChannelItem(channel, selectGroupItem); items.add(channelItem); selectGroupItem.addChannelItem(channelItem); } cleanUpOneChannelGroupItem(items); } private static boolean isHdChannel(Channel channel) { String videoFormat = channel.getVideoFormat(); return videoFormat != null && (Channels.VIDEO_FORMAT_720P.equals(videoFormat) || Channels.VIDEO_FORMAT_1080I.equals(videoFormat) || Channels.VIDEO_FORMAT_1080P.equals(videoFormat) || Channels.VIDEO_FORMAT_2160P.equals(videoFormat) || Channels.VIDEO_FORMAT_4320P.equals(videoFormat)); } private class SelectGroupItem extends ActionItem { private final List mChannelItemsInGroup = new ArrayList<>(); private TextView mTextView; private boolean mAllChecked; public SelectGroupItem() { super(null); } private void addChannelItem(ChannelItem channelItem) { mChannelItemsInGroup.add(channelItem); } @Override protected void onBind(View view) { super.onBind(view); mTextView = (TextView) view.findViewById(R.id.title); } @Override protected void onUpdate() { super.onUpdate(); mAllChecked = true; for (ChannelItem channelItem : mChannelItemsInGroup) { if (!channelItem.getChannel().isBrowsable()) { mAllChecked = false; break; } } mTextView.setText(getString(mAllChecked ? R.string.edit_channels_item_deselect_group : R.string.edit_channels_item_select_group)); } @Override protected void onSelected() { for (ChannelItem channelItem : mChannelItemsInGroup) { Channel channel = channelItem.getChannel(); if (channel.isBrowsable() == mAllChecked) { getChannelDataManager().updateBrowsable(channel.getId(), !mAllChecked, true); channelItem.notifyUpdated(); } } getChannelDataManager().notifyChannelBrowsableChanged(); mAllChecked = !mAllChecked; mTextView.setText(getString(mAllChecked ? R.string.edit_channels_item_deselect_group : R.string.edit_channels_item_select_group)); } } private class ChannelItem extends ChannelCheckItem { private SelectGroupItem mSelectGroupItem; public ChannelItem(Channel channel, SelectGroupItem selectGroupItem) { super(channel, getChannelDataManager(), getProgramDataManager()); mSelectGroupItem = selectGroupItem; } @Override protected void onUpdate() { super.onUpdate(); setChecked(getChannel().isBrowsable()); } @Override protected void onSelected() { super.onSelected(); getChannelDataManager().updateBrowsable(getChannel().getId(), isChecked()); if (mSelectGroupItem != null) { mSelectGroupItem.notifyUpdated(); } } @Override protected void onFocused() { super.onFocused(); mLastFocusedChannelId = getChannel().getId(); } } private class GroupBySubMenu extends SubMenuItem { private static final String TRACKER_LABEL = "Group by"; public GroupBySubMenu(String description) { super(getString(R.string.edit_channels_item_group_by), description, getMainActivity().getOverlayManager().getSideFragmentManager()); } @Override protected SideFragment getFragment() { return new SideFragment() { @Override protected String getTitle() { return getString(R.string.side_panel_title_group_by); } @Override public String getTrackerLabel() { return GroupBySubMenu.TRACKER_LABEL; } @Override protected List getItemList() { List items = new ArrayList<>(); items.add(new RadioButtonItem( getString(R.string.edit_channels_group_by_sources)) { @Override protected void onSelected() { super.onSelected(); mGroupingType = GROUP_BY_SOURCE; closeFragment(); } }); items.add(new RadioButtonItem( getString(R.string.edit_channels_group_by_hd_sd)) { @Override protected void onSelected() { super.onSelected(); mGroupingType = GROUP_BY_HD_SD; closeFragment(); } }); ((RadioButtonItem) items.get(mGroupingType)).setChecked(true); return items; } }; } @Override protected void onSelected() { mGroupByFragmentRunning = true; super.onSelected(); } } }