]> Pileus Git - ~andy/freeotp/blob - src/org/fedorahosted/freeotp/adapters/ReorderableBaseAdapter.java
Don't use anonymous classes in ReorderableBaseAdapter
[~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                 Reference<View> ref = (Reference<View>) event.getLocalState();
60                 final View srcView = ref.reference;
61
62                 switch (event.getAction()) {
63                 case DragEvent.ACTION_DRAG_ENTERED:
64                         srcView.setVisibility(View.VISIBLE);
65                         dstView.setVisibility(View.INVISIBLE);
66
67                         Integer src = mPositions.get(srcView);
68                         Integer dst = mPositions.get(dstView);
69                         if (src != null && dst != null)
70                                 move(src, dst);
71
72                         ref.reference = dstView;
73                         break;
74
75                 case DragEvent.ACTION_DRAG_ENDED:
76                     srcView.post(new Runnable() {
77                                 @Override
78                                 public void run() {
79                                         srcView.setVisibility(View.VISIBLE);
80                                 }
81                         });
82                         break;
83                 }
84
85                 return true;
86         }
87
88         @Override
89         public boolean onLongClick(final View view) {
90                 // Force a reset of any states
91                 notifyDataSetChanged();
92
93                 // Start the drag on the main loop to allow
94                 // the above state reset to settle.
95                 view.post(new Runnable() {
96                         @Override
97                         public void run() {
98                                 ClipData data = ClipData.newPlainText("", "");
99                                 DragShadowBuilder sb = new View.DragShadowBuilder(view);
100                                 view.startDrag(data, sb, new Reference<View>(view), 0);
101                         }
102                 });
103
104                 return true;
105         }
106
107         @Override
108         protected void processView(View view, int type) {
109                 view.setOnDragListener(this);
110                 view.setOnLongClickListener(this);
111         }
112
113         protected int getPositionFromView(View view) {
114                 while(true) {
115                         Integer position = mPositions.get(view);
116                         if (position != null)
117                                 return position;
118
119                         ViewParent vp = view.getParent();
120                         if (vp == null || !(vp instanceof View))
121                                 break;
122
123                         view = (View) vp;
124                 }
125
126                 return -1;
127         }
128
129         public abstract void move(int fromPosition, int toPosition);
130 }