]> Pileus Git - ~andy/freeotp/blob - src/org/fedorahosted/freeotp/adapters/ReorderableBaseAdapter.java
Ignore warning
[~andy/freeotp] / src / org / fedorahosted / freeotp / adapters / ReorderableBaseAdapter.java
1 /*
2  * FreeOTP
3  *
4  * Authors: Nathaniel McCallum <npmccallum@redhat.com>
5  *
6  * Copyright (C) 2013  Nathaniel McCallum, Red Hat
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 package org.fedorahosted.freeotp.adapters;
22
23 import java.util.WeakHashMap;
24
25 import android.content.ClipData;
26 import android.view.DragEvent;
27 import android.view.View;
28 import android.view.View.DragShadowBuilder;
29 import android.view.View.OnDragListener;
30 import android.view.View.OnLongClickListener;
31 import android.view.ViewParent;
32
33 public abstract class ReorderableBaseAdapter extends BaseAdapter implements OnLongClickListener, OnDragListener {
34         private final WeakHashMap<View, Integer> mPositions = new WeakHashMap<View, Integer>();
35         private class Reference<T> {
36                 public Reference(T t) { reference = t; }
37                 T reference;
38         }
39
40         @Override
41         public void notifyDataSetChanged() {
42                 mPositions.clear();
43                 super.notifyDataSetChanged();
44         }
45
46         @Override
47         public void notifyDataSetInvalidated() {
48                 mPositions.clear();
49                 super.notifyDataSetInvalidated();
50         }
51
52         @Override
53         protected void bindView(View view, int position) {
54                 mPositions.put(view, position);
55         }
56
57         @Override
58         public boolean onDrag(View dstView, DragEvent event) {
59                 @SuppressWarnings("unchecked")
60                 Reference<View> ref = (Reference<View>) event.getLocalState();
61                 final View srcView = ref.reference;
62
63                 switch (event.getAction()) {
64                 case DragEvent.ACTION_DRAG_ENTERED:
65                         srcView.setVisibility(View.VISIBLE);
66                         dstView.setVisibility(View.INVISIBLE);
67
68                         Integer src = mPositions.get(srcView);
69                         Integer dst = mPositions.get(dstView);
70                         if (src != null && dst != null)
71                                 move(src, dst);
72
73                         ref.reference = dstView;
74                         break;
75
76                 case DragEvent.ACTION_DRAG_ENDED:
77                     srcView.post(new Runnable() {
78                                 @Override
79                                 public void run() {
80                                         srcView.setVisibility(View.VISIBLE);
81                                 }
82                         });
83                         break;
84                 }
85
86                 return true;
87         }
88
89         @Override
90         public boolean onLongClick(final View view) {
91                 // Force a reset of any states
92                 notifyDataSetChanged();
93
94                 // Start the drag on the main loop to allow
95                 // the above state reset to settle.
96                 view.post(new Runnable() {
97                         @Override
98                         public void run() {
99                                 ClipData data = ClipData.newPlainText("", "");
100                                 DragShadowBuilder sb = new View.DragShadowBuilder(view);
101                                 view.startDrag(data, sb, new Reference<View>(view), 0);
102                         }
103                 });
104
105                 return true;
106         }
107
108         @Override
109         protected void processView(View view, int type) {
110                 view.setOnDragListener(this);
111                 view.setOnLongClickListener(this);
112         }
113
114         protected int getPositionFromView(View view) {
115                 while(true) {
116                         Integer position = mPositions.get(view);
117                         if (position != null)
118                                 return position;
119
120                         ViewParent vp = view.getParent();
121                         if (vp == null || !(vp instanceof View))
122                                 break;
123
124                         view = (View) vp;
125                 }
126
127                 return -1;
128         }
129
130         public abstract void move(int fromPosition, int toPosition);
131 }