blob: 9f52abdad287f9a6946c8a0fb61be69d38972948 [file] [log] [blame]
/*
* Copyright (C) 2016 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.systemui.recents.tv.views;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.R;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.model.TaskStack.TaskStackCallbacks;
import com.android.systemui.recents.views.AnimationProps;
/**
* Horizontal Grid View Implementation to show the Task Stack for TV.
*/
public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
private static final int ANIMATION_DELAY_MS = 50;
private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_START_RECENT_ROW_FOCUS_ANIMATION) {
startRecentsRowFocusAnimation(msg.arg1 == 1);
}
}
};
private TaskStack mStack;
private Task mFocusedTask;
private AnimatorSet mRecentsRowFocusAnimation;
public TaskStackHorizontalGridView(Context context) {
this(context, null);
}
public TaskStackHorizontalGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
setWindowAlignment(WINDOW_ALIGN_NO_EDGE);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
/**
* Resets this view for reuse.
*/
public void reset() {
for (int i = 0; i < getChildCount(); i++) {
((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder().reset();
}
if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
mRecentsRowFocusAnimation.cancel();
}
mHandler.removeCallbacksAndMessages(null);
requestLayout();
}
/**
* @param task - Task to reset
*/
private void resetFocusedTask(Task task) {
mFocusedTask = null;
}
/**
* Sets the task stack.
* @param stack
*/
public void setStack(TaskStack stack) {
//Set new stack
mStack = stack;
if (mStack != null) {
mStack.setCallbacks(this);
}
//Layout with new stack
requestLayout();
}
/**
* @return Returns the task stack.
*/
public TaskStack getStack() {
return mStack;
}
/**
* @return - The focused task.
*/
public Task getFocusedTask() {
if (findFocus() != null) {
mFocusedTask = ((TaskCardView)findFocus()).getTask();
}
return mFocusedTask;
}
/**
* @return - The focused task card view.
*/
public TaskCardView getFocusedTaskCardView() {
return ((TaskCardView)findFocus());
}
/**
* @param task
* @return Child view for given task
*/
public TaskCardView getChildViewForTask(Task task) {
for (int i = 0; i < getChildCount(); i++) {
TaskCardView tv = (TaskCardView) getChildAt(i);
if (tv.getTask() == task) {
return tv;
}
}
return null;
}
/**
* Starts the focus change animation.
*/
public void startRecentsRowFocusAnimation(final boolean hasFocus) {
if (getChildCount() == 0) {
// Animation request may happen before view is attached.
// Post again with small dealy so animation can be run again later.
if (getAdapter().getItemCount() > 0) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(
MSG_START_RECENT_ROW_FOCUS_ANIMATION, hasFocus ? 1 : 0),
ANIMATION_DELAY_MS);
}
return;
}
if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
mRecentsRowFocusAnimation.cancel();
}
Animator animator = ((TaskCardView) getChildAt(0)).getRecentsRowFocusAnimationHolder()
.getFocusChangeAnimator(hasFocus);
mRecentsRowFocusAnimation = new AnimatorSet();
AnimatorSet.Builder builder = mRecentsRowFocusAnimation.play(animator);
for (int i = 1; i < getChildCount(); i++) {
builder.with(((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder()
.getFocusChangeAnimator(hasFocus));
}
mRecentsRowFocusAnimation.start();
}
@Override
public void onStackTaskAdded(TaskStack stack, Task newTask) {
((TaskStackHorizontalViewAdapter) getAdapter()).addTaskAt(newTask,
stack.indexOfStackTask(newTask));
}
@Override
public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
((TaskStackHorizontalViewAdapter) getAdapter()).removeTask(removedTask);
if (mFocusedTask == removedTask) {
resetFocusedTask(removedTask);
}
// If there are no remaining tasks, then just close recents
if (mStack.getStackTaskCount() == 0) {
boolean shouldFinishActivity = (mStack.getStackTaskCount() == 0);
if (shouldFinishActivity) {
EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
? R.string.recents_empty_message
: R.string.recents_empty_message_dismissed_all));
}
}
}
@Override
public void onStackTasksRemoved(TaskStack stack) {
// Do nothing
}
@Override
public void onStackTasksUpdated(TaskStack stack) {
// Do nothing
}
}