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.dialer.app.list;
18 
19 import android.os.Build.VERSION;
20 import android.os.Build.VERSION_CODES;
21 import android.view.View;
22 import java.util.ArrayList;
23 import java.util.List;
24 
25 /**
26  * Class that handles and combines drag events generated from multiple views, and then fires off
27  * events to any OnDragDropListeners that have registered for callbacks.
28  */
29 public class DragDropController {
30 
31   private final List<OnDragDropListener> mOnDragDropListeners = new ArrayList<OnDragDropListener>();
32   private final DragItemContainer mDragItemContainer;
33   private final int[] mLocationOnScreen = new int[2];
34 
DragDropController(DragItemContainer dragItemContainer)35   public DragDropController(DragItemContainer dragItemContainer) {
36     mDragItemContainer = dragItemContainer;
37   }
38 
39   /** @return True if the drag is started, false if the drag is cancelled for some reason. */
handleDragStarted(View v, int x, int y)40   boolean handleDragStarted(View v, int x, int y) {
41     int screenX = x;
42     int screenY = y;
43     // The coordinates in dragEvent of DragEvent.ACTION_DRAG_STARTED before NYC is window-related.
44     // This is fixed in NYC.
45     if (VERSION.SDK_INT >= VERSION_CODES.N) {
46       v.getLocationOnScreen(mLocationOnScreen);
47       screenX = x + mLocationOnScreen[0];
48       screenY = y + mLocationOnScreen[1];
49     }
50     final PhoneFavoriteSquareTileView tileView =
51         mDragItemContainer.getViewForLocation(screenX, screenY);
52     if (tileView == null) {
53       return false;
54     }
55     for (int i = 0; i < mOnDragDropListeners.size(); i++) {
56       mOnDragDropListeners.get(i).onDragStarted(screenX, screenY, tileView);
57     }
58 
59     return true;
60   }
61 
handleDragHovered(View v, int x, int y)62   public void handleDragHovered(View v, int x, int y) {
63     v.getLocationOnScreen(mLocationOnScreen);
64     final int screenX = x + mLocationOnScreen[0];
65     final int screenY = y + mLocationOnScreen[1];
66     final PhoneFavoriteSquareTileView view =
67         mDragItemContainer.getViewForLocation(screenX, screenY);
68     for (int i = 0; i < mOnDragDropListeners.size(); i++) {
69       mOnDragDropListeners.get(i).onDragHovered(screenX, screenY, view);
70     }
71   }
72 
handleDragFinished(int x, int y, boolean isRemoveView)73   public void handleDragFinished(int x, int y, boolean isRemoveView) {
74     if (isRemoveView) {
75       for (int i = 0; i < mOnDragDropListeners.size(); i++) {
76         mOnDragDropListeners.get(i).onDroppedOnRemove();
77       }
78     }
79 
80     for (int i = 0; i < mOnDragDropListeners.size(); i++) {
81       mOnDragDropListeners.get(i).onDragFinished(x, y);
82     }
83   }
84 
addOnDragDropListener(OnDragDropListener listener)85   public void addOnDragDropListener(OnDragDropListener listener) {
86     if (!mOnDragDropListeners.contains(listener)) {
87       mOnDragDropListeners.add(listener);
88     }
89   }
90 
removeOnDragDropListener(OnDragDropListener listener)91   public void removeOnDragDropListener(OnDragDropListener listener) {
92     if (mOnDragDropListeners.contains(listener)) {
93       mOnDragDropListeners.remove(listener);
94     }
95   }
96 
97   /**
98    * Callback interface used to retrieve views based on the current touch coordinates of the drag
99    * event. The {@link DragItemContainer} houses the draggable views that this {@link
100    * DragDropController} controls.
101    */
102   public interface DragItemContainer {
103 
getViewForLocation(int x, int y)104     PhoneFavoriteSquareTileView getViewForLocation(int x, int y);
105   }
106 }
107