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 */ 16package com.android.systemui.recents.tv.views; 17 18import android.animation.Animator; 19import android.animation.AnimatorSet; 20import android.content.Context; 21import android.support.v17.leanback.widget.HorizontalGridView; 22import android.util.AttributeSet; 23import android.view.View; 24 25import com.android.systemui.R; 26import com.android.systemui.recents.RecentsActivity; 27import com.android.systemui.recents.events.EventBus; 28import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; 29import com.android.systemui.recents.model.Task; 30import com.android.systemui.recents.model.TaskStack; 31import com.android.systemui.recents.model.TaskStack.TaskStackCallbacks; 32import com.android.systemui.recents.views.AnimationProps; 33 34/** 35 * Horizontal Grid View Implementation to show the Task Stack for TV. 36 */ 37public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks { 38 private static final int ANIMATION_DELAY_MS = 50; 39 private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100; 40 private TaskStack mStack; 41 private Task mFocusedTask; 42 private AnimatorSet mRecentsRowFocusAnimation; 43 44 public TaskStackHorizontalGridView(Context context) { 45 this(context, null); 46 } 47 48 public TaskStackHorizontalGridView(Context context, AttributeSet attrs) { 49 super(context, attrs); 50 } 51 52 @Override 53 protected void onAttachedToWindow() { 54 EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1); 55 setWindowAlignment(WINDOW_ALIGN_NO_EDGE); 56 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 57 super.onAttachedToWindow(); 58 } 59 60 @Override 61 protected void onDetachedFromWindow() { 62 super.onDetachedFromWindow(); 63 EventBus.getDefault().unregister(this); 64 } 65 66 /** 67 * Initializes the grid view. 68 * @param stack 69 */ 70 public void init(TaskStack stack) { 71 // Set new stack 72 mStack = stack; 73 if (mStack != null) { 74 mStack.setCallbacks(this); 75 } 76 } 77 78 /** 79 * @return Returns the task stack. 80 */ 81 public TaskStack getStack() { 82 return mStack; 83 } 84 85 /** 86 * @return - The focused task. 87 */ 88 public Task getFocusedTask() { 89 if (findFocus() != null) { 90 mFocusedTask = ((TaskCardView)findFocus()).getTask(); 91 } 92 return mFocusedTask; 93 } 94 95 /** 96 * @param task 97 * @return Child view for given task 98 */ 99 public TaskCardView getChildViewForTask(Task task) { 100 for (int i = 0; i < getChildCount(); i++) { 101 TaskCardView tv = (TaskCardView) getChildAt(i); 102 if (tv.getTask() == task) { 103 return tv; 104 } 105 } 106 return null; 107 } 108 109 110 /** 111 * Starts the Recents row's focus gain animation. 112 */ 113 public void startFocusGainAnimation() { 114 for (int i = 0; i < getChildCount(); i++) { 115 TaskCardView v = (TaskCardView) getChildAt(i); 116 if (v.hasFocus()) { 117 v.getViewFocusAnimator().changeSize(true); 118 } 119 v.getRecentsRowFocusAnimationHolder().startFocusGainAnimation(); 120 } 121 } 122 123 /** 124 * Starts the Recents row's focus loss animation. 125 */ 126 public void startFocusLossAnimation() { 127 for (int i = 0; i < getChildCount(); i++) { 128 TaskCardView v = (TaskCardView) getChildAt(i); 129 if (v.hasFocus()) { 130 v.getViewFocusAnimator().changeSize(false); 131 } 132 v.getRecentsRowFocusAnimationHolder().startFocusLossAnimation(); 133 } 134 } 135 136 @Override 137 public void onStackTaskAdded(TaskStack stack, Task newTask) { 138 ((TaskStackHorizontalViewAdapter) getAdapter()).addTaskAt(newTask, 139 stack.indexOfStackTask(newTask)); 140 } 141 142 @Override 143 public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask, 144 AnimationProps animation, boolean fromDockGesture) { 145 ((TaskStackHorizontalViewAdapter) getAdapter()).removeTask(removedTask); 146 if (mFocusedTask == removedTask) { 147 mFocusedTask = null; 148 } 149 // If there are no remaining tasks, then just close recents 150 if (mStack.getStackTaskCount() == 0) { 151 boolean shouldFinishActivity = (mStack.getStackTaskCount() == 0); 152 if (shouldFinishActivity) { 153 EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture 154 ? R.string.recents_empty_message 155 : R.string.recents_empty_message_dismissed_all)); 156 } 157 } 158 } 159 160 @Override 161 public void onStackTasksRemoved(TaskStack stack) { 162 // Do nothing 163 } 164 165 @Override 166 public void onStackTasksUpdated(TaskStack stack) { 167 // Do nothing 168 } 169} 170