1 package org.easyrpg.player;
2 
3 import java.io.File;
4 import java.io.FilenameFilter;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.LinkedList;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 
12 import android.app.AlertDialog;
13 import android.content.Context;
14 import android.content.DialogInterface;
15 import android.content.DialogInterface.OnClickListener;
16 import android.util.Log;
17 import android.view.View;
18 import android.widget.AdapterView;
19 import android.widget.ArrayAdapter;
20 import android.widget.Button;
21 import android.widget.EditText;
22 import android.widget.ListView;
23 import android.widget.Toast;
24 
25 
26 public class DirectoryChooser {
27     private static String selected_path;
28 
29     AlertDialog.Builder builder;
30     AlertDialog dialog;
31     ListView listView;
32     Context context;
33 
34     LinkedList<String> currentDirPath = new LinkedList<String>();
35     List<String> dir_list;
36 
37 
DirectoryChooser(final Context context, String path, final Runnable runnable)38     public DirectoryChooser(final Context context, String path, final Runnable runnable) {
39         this.context = context;
40         this.builder = new AlertDialog.Builder(context);
41         this.listView = new ListView(context);
42 
43         builder.setPositiveButton(R.string.ok, null);
44         builder.setNeutralButton(R.string.quick_access, null);
45         builder.setView(listView);
46 
47         // Current directory
48         if (path != null) {
49             currentDirPath.addAll(Arrays.asList(path.split("/")));
50         }
51 
52         //Display the folder's list first
53         dialog = builder.create();
54         displayItemList();
55 
56         // Set up action to button (after the dialog creation to avoid automatic closing)
57         // (Android "logic")
58         dialog.setOnShowListener(new DialogInterface.OnShowListener() {
59             @Override
60             public void onShow(DialogInterface d) {
61                 //OK's button
62                 Button b = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
63                 b.setOnClickListener(new View.OnClickListener() {
64                     @Override
65                     public void onClick(View view) {
66                         selected_path = dirListToPath(currentDirPath);
67                         runnable.run();
68 
69                         // Dismiss once everything is OK.
70                         dialog.dismiss();
71                     }
72                 });
73 
74                 //Create Quick access button
75                 Button b2 = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
76                 b2.setOnClickListener(new View.OnClickListener() {
77                     @Override
78                     public void onClick(View view) {
79                         quickAccess();
80                     }
81                 });
82             }
83         });
84 
85         dialog.show();
86     }
87 
quickAccess()88     public void quickAccess() {
89         final ListView lv = new ListView(context);
90 
91         AlertDialog.Builder builder = new AlertDialog.Builder(context);
92         builder
93                 .setTitle(R.string.quick_access)
94                 .setView(lv)
95                 .setCancelable(true);
96 
97         final AlertDialog quickDialog = builder.create();
98 
99         final Map<String, File> allLocations = ExternalStorage.getAllStorageLocations();
100         final String[] keySet = allLocations.keySet().toArray(new String[allLocations.size()]);
101         lv.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, keySet));
102 
103         // When clicking on an item, the list display the new path
104         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
105 
106             public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) {
107                 String newPath = allLocations.get(keySet[pos]).getAbsolutePath();
108 
109                 if (isReadable(newPath)) {
110                     currentDirPath.clear();
111                     currentDirPath.addAll(Arrays.asList(newPath.split("/")));
112 
113                     displayItemList();
114                 } else {
115                     String msg = context.getString(R.string.path_not_readable).replace("$PATH", newPath);
116                     Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
117                 }
118 
119                 quickDialog.dismiss();
120             }
121         });
122 
123         quickDialog.show();
124     }
125 
126     /**
127      * Returns the folder's list of path
128      */
listDir(String path)129     public List<String> listDir(String path) {
130         List<String> dirList = new ArrayList<String>();
131 
132         // Add the ".." item if we're not at the root
133         if (!path.equals("/")) {
134             dirList.add("..");
135         }
136 
137         // List the directories in "path"
138         File dir = new File(path);
139         String[] directories = dir.list(new FilenameFilter() {
140             @Override
141             public boolean accept(File current, String name) {
142                 File newFile = new File(current, name);
143                 return newFile.isDirectory() && !newFile.isHidden();
144             }
145         });
146 
147         if (directories != null) {
148             Arrays.sort(directories);
149             dirList.addAll(new ArrayList<String>(Arrays.asList(directories)));
150         }
151 
152         return dirList;
153     }
154 
displayItemList()155     public void displayItemList() {
156         // Retrieve the folder's list to display
157         String path = dirListToPath(currentDirPath);
158         dir_list = listDir(path);
159         dialog.setTitle(path);
160 
161         listView.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, dir_list));
162 
163         // When clicking on an item, the list display the new path
164         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
165 
166             public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) {
167                 String dirName = dir_list.get(pos);
168 
169                 // Updating the current directory
170                 if (dirName.equals("..")) {
171                     currentDirPath.removeLast();
172                 } else {
173                     String newPath = dirListToPath(currentDirPath) + "/" + dir_list.get(pos);
174 
175                     if (isReadable(newPath)) {
176                         currentDirPath.add(dir_list.get(pos));
177                     } else {
178                         String msg = context.getString(R.string.path_not_readable).replace("$PATH", newPath);
179                         Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
180                     }
181                 }
182 
183                 displayItemList();
184             }
185         });
186     }
187 
dirListToPath(LinkedList<String> l)188     public static String dirListToPath(LinkedList<String> l) {
189         if (l.size() <= 1)
190             return "/";
191 
192         StringBuilder s = new StringBuilder();
193         for (int i = 0; i < l.size(); i++) {
194             if (i > 0) {
195                 s.append("/");
196             }
197             s.append(l.get(i));
198         }
199 
200         return s.toString();
201     }
202 
isReadable(String path)203     public boolean isReadable(String path) {
204         File file = new File(path);
205         boolean canRead = file.canRead();
206         if (!canRead) {
207             Log.e("isReadable", "Current context not allowed to read : " + path);
208         }
209         return canRead;
210     }
211 
getSelectedPath()212     public static String getSelectedPath() {
213         return selected_path;
214     }
215 }
216