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.tv.dvr.ui; 18 19 import android.app.FragmentManager; 20 import android.content.Context; 21 import android.graphics.Typeface; 22 import android.os.Bundle; 23 import android.support.v17.leanback.app.GuidedStepFragment; 24 import android.support.v17.leanback.widget.GuidanceStylist.Guidance; 25 import android.support.v17.leanback.widget.GuidedAction; 26 import android.support.v17.leanback.widget.GuidedActionsStylist; 27 import android.view.View; 28 import android.widget.ImageView; 29 import android.widget.TextView; 30 31 import com.android.tv.R; 32 import com.android.tv.TvApplication; 33 import com.android.tv.dvr.DvrDataManager; 34 import com.android.tv.dvr.DvrManager; 35 import com.android.tv.dvr.DvrScheduleManager; 36 import com.android.tv.dvr.SeriesRecording; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 /** 42 * Fragment for DVR series recording settings. 43 */ 44 public class PrioritySettingsFragment extends GuidedStepFragment { 45 /** 46 * Name of series recording id starting the fragment. 47 * Type: Long 48 */ 49 public static final String COME_FROM_SERIES_RECORDING_ID = "series_recording_id"; 50 51 private static final int ONE_TIME_RECORDING_ID = 0; 52 // button action's IDs are negative. 53 private static final long ACTION_ID_SAVE = -100L; 54 55 private final List<SeriesRecording> mSeriesRecordings = new ArrayList<>(); 56 57 private SeriesRecording mSelectedRecording; 58 private SeriesRecording mComeFromSeriesRecording; 59 private float mSelectedActionElevation; 60 private int mActionColor; 61 private int mSelectedActionColor; 62 63 @Override onAttach(Context context)64 public void onAttach(Context context) { 65 super.onAttach(context); 66 mSeriesRecordings.clear(); 67 mSeriesRecordings.add(new SeriesRecording.Builder() 68 .setTitle(getString(R.string.dvr_priority_action_one_time_recording)) 69 .setPriority(Long.MAX_VALUE) 70 .setId(ONE_TIME_RECORDING_ID) 71 .build()); 72 DvrDataManager dvrDataManager = TvApplication.getSingletons(context).getDvrDataManager(); 73 long comeFromSeriesRecordingId = 74 getArguments().getLong(COME_FROM_SERIES_RECORDING_ID, -1); 75 for (SeriesRecording series : dvrDataManager.getSeriesRecordings()) { 76 if (series.getState() == SeriesRecording.STATE_SERIES_NORMAL 77 || series.getId() == comeFromSeriesRecordingId) { 78 mSeriesRecordings.add(series); 79 } 80 } 81 mSeriesRecordings.sort(SeriesRecording.PRIORITY_COMPARATOR); 82 mComeFromSeriesRecording = dvrDataManager.getSeriesRecording(comeFromSeriesRecordingId); 83 mSelectedActionElevation = getResources().getDimension(R.dimen.card_elevation_normal); 84 mActionColor = getResources().getColor(R.color.dvr_guided_step_action_text_color, null); 85 mSelectedActionColor = 86 getResources().getColor(R.color.dvr_guided_step_action_text_color_selected, null); 87 } 88 89 @Override onResume()90 public void onResume() { 91 super.onResume(); 92 setSelectedActionPosition(mComeFromSeriesRecording == null ? 1 93 : mSeriesRecordings.indexOf(mComeFromSeriesRecording)); 94 } 95 96 @Override onCreateGuidance(Bundle savedInstanceState)97 public Guidance onCreateGuidance(Bundle savedInstanceState) { 98 String breadcrumb = mComeFromSeriesRecording == null ? null 99 : mComeFromSeriesRecording.getTitle(); 100 return new Guidance(getString(R.string.dvr_priority_title), 101 getString(R.string.dvr_priority_description), breadcrumb, null); 102 } 103 104 @Override onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)105 public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { 106 int position = 0; 107 for (SeriesRecording seriesRecording : mSeriesRecordings) { 108 actions.add(new GuidedAction.Builder(getActivity()) 109 .id(position++) 110 .title(seriesRecording.getTitle()) 111 .build()); 112 } 113 } 114 115 @Override onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState)116 public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) { 117 actions.add(new GuidedAction.Builder(getActivity()) 118 .id(ACTION_ID_SAVE) 119 .title(getString(R.string.dvr_priority_button_action_save)) 120 .build()); 121 actions.add(new GuidedAction.Builder(getActivity()) 122 .clickAction(GuidedAction.ACTION_ID_CANCEL) 123 .build()); 124 } 125 126 @Override onGuidedActionClicked(GuidedAction action)127 public void onGuidedActionClicked(GuidedAction action) { 128 long actionId = action.getId(); 129 if (actionId == ACTION_ID_SAVE) { 130 DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager(); 131 int size = mSeriesRecordings.size(); 132 for (int i = 1; i < size; ++i) { 133 long priority = DvrScheduleManager.suggestSeriesPriority(size - i); 134 SeriesRecording seriesRecording = mSeriesRecordings.get(i); 135 if (seriesRecording.getPriority() != priority) { 136 dvrManager.updateSeriesRecording(SeriesRecording.buildFrom(seriesRecording) 137 .setPriority(priority).build()); 138 } 139 } 140 FragmentManager fragmentManager = getFragmentManager(); 141 fragmentManager.popBackStack(); 142 } else if (actionId == GuidedAction.ACTION_ID_CANCEL) { 143 FragmentManager fragmentManager = getFragmentManager(); 144 fragmentManager.popBackStack(); 145 } else if (mSelectedRecording == null) { 146 mSelectedRecording = mSeriesRecordings.get((int) actionId); 147 for (int i = 0; i < mSeriesRecordings.size(); ++i) { 148 updateItem(i); 149 } 150 } else { 151 mSelectedRecording = null; 152 for (int i = 0; i < mSeriesRecordings.size(); ++i) { 153 updateItem(i); 154 } 155 } 156 } 157 158 @Override onGuidedActionFocused(GuidedAction action)159 public void onGuidedActionFocused(GuidedAction action) { 160 super.onGuidedActionFocused(action); 161 if (mSelectedRecording == null) { 162 return; 163 } 164 if (action.getId() < 0) { 165 int selectedPosition = mSeriesRecordings.indexOf(mSelectedRecording); 166 mSelectedRecording = null; 167 for (int i = 0; i < mSeriesRecordings.size(); ++i) { 168 updateItem(i); 169 } 170 return; 171 } 172 int position = (int) action.getId(); 173 int previousPosition = mSeriesRecordings.indexOf(mSelectedRecording); 174 mSeriesRecordings.remove(mSelectedRecording); 175 mSeriesRecordings.add(position, mSelectedRecording); 176 updateItem(previousPosition); 177 updateItem(position); 178 notifyActionChanged(previousPosition); 179 notifyActionChanged(position); 180 } 181 182 @Override onCreateButtonActionsStylist()183 public GuidedActionsStylist onCreateButtonActionsStylist() { 184 return new DvrGuidedActionsStylist(true); 185 } 186 187 @Override onCreateActionsStylist()188 public GuidedActionsStylist onCreateActionsStylist() { 189 return new DvrGuidedActionsStylist(false) { 190 @Override 191 public void onBindViewHolder(ViewHolder vh, GuidedAction action) { 192 super.onBindViewHolder(vh, action); 193 updateItem(vh.itemView, (int) action.getId()); 194 } 195 196 @Override 197 public int onProvideItemLayoutId() { 198 return R.layout.priority_settings_action_item; 199 } 200 }; 201 } 202 203 private void updateItem(int position) { 204 View itemView = getActionItemView(position); 205 if (itemView == null) { 206 return; 207 } 208 updateItem(itemView, position); 209 } 210 211 private void updateItem(View itemView, int position) { 212 GuidedAction action = getActions().get(position); 213 action.setTitle(mSeriesRecordings.get(position).getTitle()); 214 boolean selected = mSelectedRecording != null 215 && mSeriesRecordings.indexOf(mSelectedRecording) == position; 216 TextView titleView = (TextView) itemView.findViewById(R.id.guidedactions_item_title); 217 ImageView imageView = (ImageView) itemView.findViewById(R.id.guidedactions_item_tail_image); 218 if (position == 0) { 219 // one-time recording 220 itemView.setBackgroundResource(R.drawable.setup_selector_background); 221 imageView.setVisibility(View.GONE); 222 itemView.setFocusable(false); 223 itemView.setElevation(0); 224 // strings.xml <i> tag doesn't work. 225 titleView.setTypeface(titleView.getTypeface(), Typeface.ITALIC); 226 } else if (mSelectedRecording == null) { 227 titleView.setTextColor(mActionColor); 228 itemView.setBackgroundResource(R.drawable.setup_selector_background); 229 imageView.setImageResource(R.drawable.ic_draggable_white); 230 imageView.setVisibility(View.VISIBLE); 231 itemView.setFocusable(true); 232 itemView.setElevation(0); 233 titleView.setTypeface(titleView.getTypeface(), Typeface.NORMAL); 234 } else if (selected) { 235 titleView.setTextColor(mSelectedActionColor); 236 itemView.setBackgroundResource(R.drawable.priority_settings_action_item_selected); 237 imageView.setImageResource(R.drawable.ic_dragging_grey); 238 imageView.setVisibility(View.VISIBLE); 239 itemView.setFocusable(true); 240 itemView.setElevation(mSelectedActionElevation); 241 titleView.setTypeface(titleView.getTypeface(), Typeface.NORMAL); 242 } else { 243 titleView.setTextColor(mActionColor); 244 itemView.setBackgroundResource(R.drawable.setup_selector_background); 245 imageView.setVisibility(View.INVISIBLE); 246 itemView.setFocusable(true); 247 itemView.setElevation(0); 248 titleView.setTypeface(titleView.getTypeface(), Typeface.NORMAL); 249 } 250 } 251 } 252