1/* 2 * Copyright (C) 2015 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.systemui.recents; 18 19import android.app.AlertDialog; 20import android.app.Dialog; 21import android.app.DialogFragment; 22import android.app.FragmentManager; 23import android.content.Context; 24import android.content.DialogInterface; 25import android.graphics.Rect; 26import android.os.Bundle; 27import android.util.Pair; 28import android.view.LayoutInflater; 29import android.view.View; 30import android.widget.Button; 31import com.android.systemui.R; 32import com.android.systemui.recents.misc.SystemServicesProxy; 33import com.android.systemui.recents.model.RecentsTaskLoader; 34import com.android.systemui.recents.model.Task; 35import com.android.systemui.recents.RecentsActivity; 36import com.android.systemui.recents.views.RecentsView; 37 38import java.util.ArrayList; 39 40/** 41 * A helper for the dialogs that show when task debugging is on. 42 */ 43public class RecentsResizeTaskDialog extends DialogFragment { 44 45 static final String TAG = "RecentsResizeTaskDialog"; 46 47 // The various window arrangements we can handle. 48 private static final int PLACE_LEFT = 1; 49 private static final int PLACE_RIGHT = 2; 50 private static final int PLACE_TOP = 3; 51 private static final int PLACE_BOTTOM = 4; 52 private static final int PLACE_TOP_LEFT = 5; 53 private static final int PLACE_TOP_RIGHT = 6; 54 private static final int PLACE_BOTTOM_LEFT = 7; 55 private static final int PLACE_BOTTOM_RIGHT = 8; 56 private static final int PLACE_FULL = 9; 57 58 // The button resource ID combined with the arrangement command. 59 private static final int[][] BUTTON_DEFINITIONS = 60 {{R.id.place_left, PLACE_LEFT}, 61 {R.id.place_right, PLACE_RIGHT}, 62 {R.id.place_top, PLACE_TOP}, 63 {R.id.place_bottom, PLACE_BOTTOM}, 64 {R.id.place_top_left, PLACE_TOP_LEFT}, 65 {R.id.place_top_right, PLACE_TOP_RIGHT}, 66 {R.id.place_bottom_left, PLACE_BOTTOM_LEFT}, 67 {R.id.place_bottom_right, PLACE_BOTTOM_RIGHT}, 68 {R.id.place_full, PLACE_FULL}}; 69 70 // The task we want to resize. 71 private FragmentManager mFragmentManager; 72 private View mResizeTaskDialogContent; 73 private RecentsActivity mRecentsActivity; 74 private RecentsView mRecentsView; 75 private SystemServicesProxy mSsp; 76 private Rect[] mBounds = {new Rect(), new Rect(), new Rect(), new Rect()}; 77 private Task[] mTasks = {null, null, null, null}; 78 79 public RecentsResizeTaskDialog(FragmentManager mgr, RecentsActivity activity) { 80 mFragmentManager = mgr; 81 mRecentsActivity = activity; 82 mSsp = RecentsTaskLoader.getInstance().getSystemServicesProxy(); 83 } 84 85 /** Shows the resize-task dialog. */ 86 void showResizeTaskDialog(Task mainTask, RecentsView rv) { 87 mTasks[0] = mainTask; 88 mRecentsView = rv; 89 90 show(mFragmentManager, TAG); 91 } 92 93 /** Creates a new resize-task dialog. */ 94 private void createResizeTaskDialog(final Context context, LayoutInflater inflater, 95 AlertDialog.Builder builder) { 96 builder.setTitle(R.string.recents_caption_resize); 97 mResizeTaskDialogContent = 98 inflater.inflate(R.layout.recents_task_resize_dialog, null, false); 99 100 for (int i = 0; i < BUTTON_DEFINITIONS.length; i++) { 101 Button b = (Button)mResizeTaskDialogContent.findViewById(BUTTON_DEFINITIONS[i][0]); 102 if (b != null) { 103 final int action = BUTTON_DEFINITIONS[i][1]; 104 b.setOnClickListener( 105 new View.OnClickListener() { 106 public void onClick(View v) { 107 placeTasks(action); 108 } 109 }); 110 } 111 } 112 113 builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 114 @Override 115 public void onClick(DialogInterface dialog, int which) { 116 dismiss(); 117 } 118 }); 119 120 builder.setView(mResizeTaskDialogContent); 121 } 122 123 /** Helper function to place window(s) on the display according to an arrangement request. */ 124 private void placeTasks(int arrangement) { 125 Rect rect = mSsp.getWindowRect(); 126 for (int i = 0; i < mBounds.length; ++i) { 127 mBounds[i].set(rect); 128 if (i != 0) { 129 mTasks[i] = null; 130 } 131 } 132 int additionalTasks = 0; 133 switch (arrangement) { 134 case PLACE_LEFT: 135 mBounds[0].right = mBounds[0].centerX(); 136 mBounds[1].left = mBounds[0].right; 137 additionalTasks = 1; 138 break; 139 case PLACE_RIGHT: 140 mBounds[1].right = mBounds[1].centerX(); 141 mBounds[0].left = mBounds[1].right; 142 additionalTasks = 1; 143 break; 144 case PLACE_TOP: 145 mBounds[0].bottom = mBounds[0].centerY(); 146 mBounds[1].top = mBounds[0].bottom; 147 additionalTasks = 1; 148 break; 149 case PLACE_BOTTOM: 150 mBounds[1].bottom = mBounds[1].centerY(); 151 mBounds[0].top = mBounds[1].bottom; 152 additionalTasks = 1; 153 break; 154 case PLACE_TOP_LEFT: // TL, TR, BL, BR 155 mBounds[0].right = mBounds[0].centerX(); 156 mBounds[0].bottom = mBounds[0].centerY(); 157 mBounds[1].left = mBounds[0].right; 158 mBounds[1].bottom = mBounds[0].bottom; 159 mBounds[2].right = mBounds[0].right; 160 mBounds[2].top = mBounds[0].bottom; 161 mBounds[3].left = mBounds[0].right; 162 mBounds[3].top = mBounds[0].bottom; 163 additionalTasks = 3; 164 break; 165 case PLACE_TOP_RIGHT: // TR, TL, BR, BL 166 mBounds[0].left = mBounds[0].centerX(); 167 mBounds[0].bottom = mBounds[0].centerY(); 168 mBounds[1].right = mBounds[0].left; 169 mBounds[1].bottom = mBounds[0].bottom; 170 mBounds[2].left = mBounds[0].left; 171 mBounds[2].top = mBounds[0].bottom; 172 mBounds[3].right = mBounds[0].left; 173 mBounds[3].top = mBounds[0].bottom; 174 additionalTasks = 3; 175 break; 176 case PLACE_BOTTOM_LEFT: // BL, BR, TL, TR 177 mBounds[0].right = mBounds[0].centerX(); 178 mBounds[0].top = mBounds[0].centerY(); 179 mBounds[1].left = mBounds[0].right; 180 mBounds[1].top = mBounds[0].top; 181 mBounds[2].right = mBounds[0].right; 182 mBounds[2].bottom = mBounds[0].top; 183 mBounds[3].left = mBounds[0].right; 184 mBounds[3].bottom = mBounds[0].top; 185 additionalTasks = 3; 186 break; 187 case PLACE_BOTTOM_RIGHT: // BR, BL, TR, TL 188 mBounds[0].left = mBounds[0].centerX(); 189 mBounds[0].top = mBounds[0].centerY(); 190 mBounds[1].right = mBounds[0].left; 191 mBounds[1].top = mBounds[0].top; 192 mBounds[2].left = mBounds[0].left; 193 mBounds[2].bottom = mBounds[0].top; 194 mBounds[3].right = mBounds[0].left; 195 mBounds[3].bottom = mBounds[0].top; 196 additionalTasks = 3; 197 break; 198 case PLACE_FULL: 199 // Nothing to change. 200 break; 201 } 202 203 // Get the other tasks. 204 for (int i = 1; i <= additionalTasks && mTasks[i - 1] != null; ++i) { 205 mTasks[i] = mRecentsView.getNextTaskOrTopTask(mTasks[i - 1]); 206 // Do stop if we circled back to the first item. 207 if (mTasks[i] == mTasks[0]) { 208 mTasks[i] = null; 209 } 210 } 211 212 // Get rid of the dialog. 213 dismiss(); 214 mRecentsActivity.dismissRecentsToHomeWithoutTransitionAnimation(); 215 216 // Resize all tasks beginning from the "oldest" one. 217 for (int i = additionalTasks; i >= 0; --i) { 218 if (mTasks[i] != null) { 219 mSsp.resizeTask(mTasks[i].key.id, mBounds[i]); 220 } 221 } 222 223 // Show tasks as they might not be currently visible - beginning with the oldest so that 224 // the focus ends on the selected one. 225 for (int i = additionalTasks; i >= 0; --i) { 226 if (mTasks[i] != null) { 227 mRecentsView.launchTask(mTasks[i]); 228 } 229 } 230 } 231 232 @Override 233 public Dialog onCreateDialog(Bundle args) { 234 final Context context = this.getActivity(); 235 LayoutInflater inflater = getActivity().getLayoutInflater(); 236 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 237 createResizeTaskDialog(context, inflater, builder); 238 return builder.create(); 239 } 240} 241