Update theme submodule
[platform/upstream/gstreamer.git] / tutorials / android-tutorial-5 / src / com / lamerman / FileDialog.java
1 // Based on http://code.google.com/p/android-file-dialog/
2 //
3 // Copyright (c) 2011, 2012, Alexander Ponomarev <alexander.ponomarev.1@gmail.com>
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without modification,
7 // are permitted provided that the following conditions are met:
8 // 
9 // Redistributions of source code must retain the above copyright notice, this list
10 // of conditions and the following disclaimer. Redistributions in binary form must
11 // reproduce the above copyright notice, this list of conditions and the following
12 // disclaimer in the documentation and/or other materials provided with the distribution.
13 // Neither the name of the <ORGANIZATION> nor the names of its contributors may be used
14 // to endorse or promote products derived from this software without specific prior
15 // written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 // DAMAGE.
27
28 package com.lamerman;
29
30 import java.io.File;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.TreeMap;
35
36 import android.app.AlertDialog;
37 import android.app.ListActivity;
38 import android.content.DialogInterface;
39 import android.os.Bundle;
40 import android.view.KeyEvent;
41 import android.view.View;
42 import android.view.View.OnClickListener;
43 import android.widget.Button;
44 import android.widget.ListView;
45 import android.widget.SimpleAdapter;
46 import android.widget.TextView;
47
48 import com.gst_sdk_tutorials.tutorial_5.R;
49
50 /**
51  * Activity para escolha de arquivos/diretorios.
52  * 
53  * @author android
54  * 
55  */
56 public class FileDialog extends ListActivity {
57
58     /**
59      * Chave de um item da lista de paths.
60      */
61     private static final String ITEM_KEY = "key";
62
63     /**
64      * Imagem de um item da lista de paths (diretorio ou arquivo).
65      */
66     private static final String ITEM_IMAGE = "image";
67
68     /**
69      * Diretorio raiz.
70      */
71     private static final String ROOT = "/";
72
73     /**
74      * Parametro de entrada da Activity: path inicial. Padrao: ROOT.
75      */
76     public static final String START_PATH = "START_PATH";
77
78     /**
79      * Parametro de entrada da Activity: filtro de formatos de arquivos. Padrao:
80      * null.
81      */
82     public static final String FORMAT_FILTER = "FORMAT_FILTER";
83
84     /**
85      * Parametro de saida da Activity: path escolhido. Padrao: null.
86      */
87     public static final String RESULT_PATH = "RESULT_PATH";
88
89     private List<String> path = null;
90     private TextView myPath;
91     private ArrayList<HashMap<String, Object>> mList;
92
93     private Button selectButton;
94
95     private String parentPath;
96     private String currentPath = ROOT;
97
98     private String[] formatFilter = null;
99
100     private File selectedFile;
101     private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>();
102
103     /**
104      * Called when the activity is first created. Configura todos os parametros
105      * de entrada e das VIEWS..
106      */
107     @Override
108     public void onCreate(Bundle savedInstanceState) {
109         super.onCreate(savedInstanceState);
110         setResult(RESULT_CANCELED, getIntent());
111
112         setContentView(R.layout.file_dialog_main);
113         myPath = (TextView) findViewById(R.id.path);
114
115         selectButton = (Button) findViewById(R.id.fdButtonSelect);
116         selectButton.setEnabled(false);
117         selectButton.setOnClickListener(new OnClickListener() {
118
119             public void onClick(View v) {
120                 if (selectedFile != null) {
121                     getIntent().putExtra(RESULT_PATH, selectedFile.getPath());
122                     setResult(RESULT_OK, getIntent());
123                     finish();
124                 }
125             }
126         });
127
128         formatFilter = getIntent().getStringArrayExtra(FORMAT_FILTER);
129
130         final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel);
131         cancelButton.setOnClickListener(new OnClickListener() {
132
133             public void onClick(View v) {
134                 setResult(RESULT_CANCELED);
135                 finish();
136             }
137
138         });
139
140         String startPath;
141         if (savedInstanceState != null) {
142             startPath = savedInstanceState.getString("currentPath");
143         } else {
144             startPath = getIntent().getStringExtra(START_PATH);
145         }
146         startPath = startPath != null ? startPath : ROOT;
147         getDir(startPath);
148
149         ListView lv = (ListView) findViewById(android.R.id.list);
150         lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
151     }
152
153     private void getDir(String dirPath) {
154
155         boolean useAutoSelection = dirPath.length() < currentPath.length();
156
157         Integer position = lastPositions.get(parentPath);
158
159         getDirImpl(dirPath);
160
161         if (position != null && useAutoSelection) {
162             getListView().setSelection(position);
163         }
164
165     }
166
167     /**
168      * Monta a estrutura de arquivos e diretorios filhos do diretorio fornecido.
169      *
170      * @param dirPath
171      *            Diretorio pai.
172      */
173     private void getDirImpl(final String dirPath) {
174
175         currentPath = dirPath;
176
177         final List<String> item = new ArrayList<String>();
178         path = new ArrayList<String>();
179         mList = new ArrayList<HashMap<String, Object>>();
180
181         File f = new File(currentPath);
182         File[] files = f.listFiles();
183         if (files == null) {
184             currentPath = ROOT;
185             f = new File(currentPath);
186             files = f.listFiles();
187         }
188         myPath.setText(getText(R.string.location) + ": " + currentPath);
189
190         if (!currentPath.equals(ROOT)) {
191
192             item.add(ROOT);
193             addItem(ROOT, R.drawable.folder);
194             path.add(ROOT);
195
196             item.add("../");
197             addItem("../", R.drawable.folder);
198             path.add(f.getParent());
199             parentPath = f.getParent();
200
201         }
202
203         TreeMap<String, String> dirsMap = new TreeMap<String, String>();
204         TreeMap<String, String> dirsPathMap = new TreeMap<String, String>();
205         TreeMap<String, String> filesMap = new TreeMap<String, String>();
206         TreeMap<String, String> filesPathMap = new TreeMap<String, String>();
207         for (File file : files) {
208             if (file.isDirectory()) {
209                 String dirName = file.getName();
210                 dirsMap.put(dirName, dirName);
211                 dirsPathMap.put(dirName, file.getPath());
212             } else {
213                 final String fileName = file.getName();
214                 final String fileNameLwr = fileName.toLowerCase();
215                 // se ha um filtro de formatos, utiliza-o
216                 if (formatFilter != null) {
217                     boolean contains = false;
218                     for (int i = 0; i < formatFilter.length; i++) {
219                         final String formatLwr = formatFilter[i].toLowerCase();
220                         if (fileNameLwr.endsWith(formatLwr)) {
221                             contains = true;
222                             break;
223                         }
224                     }
225                     if (contains) {
226                         filesMap.put(fileName, fileName);
227                         filesPathMap.put(fileName, file.getPath());
228                     }
229                     // senao, adiciona todos os arquivos
230                 } else {
231                     filesMap.put(fileName, fileName);
232                     filesPathMap.put(fileName, file.getPath());
233                 }
234             }
235         }
236         item.addAll(dirsMap.tailMap("").values());
237         item.addAll(filesMap.tailMap("").values());
238         path.addAll(dirsPathMap.tailMap("").values());
239         path.addAll(filesPathMap.tailMap("").values());
240
241         SimpleAdapter fileList = new SimpleAdapter(this, mList,
242                 R.layout.file_dialog_row,
243                 new String[] { ITEM_KEY, ITEM_IMAGE }, new int[] {
244                         R.id.fdrowtext, R.id.fdrowimage });
245
246         for (String dir : dirsMap.tailMap("").values()) {
247             addItem(dir, R.drawable.folder);
248         }
249
250         for (String file : filesMap.tailMap("").values()) {
251             addItem(file, R.drawable.file);
252         }
253
254         fileList.notifyDataSetChanged();
255
256         setListAdapter(fileList);
257
258     }
259
260     private void addItem(String fileName, int imageId) {
261         HashMap<String, Object> item = new HashMap<String, Object>();
262         item.put(ITEM_KEY, fileName);
263         item.put(ITEM_IMAGE, imageId);
264         mList.add(item);
265     }
266
267     /**
268      * Quando clica no item da lista, deve-se: 1) Se for diretorio, abre seus
269      * arquivos filhos; 2) Se puder escolher diretorio, define-o como sendo o
270      * path escolhido. 3) Se for arquivo, define-o como path escolhido. 4) Ativa
271      * botao de selecao.
272      */
273     @Override
274     protected void onListItemClick(ListView l, View v, int position, long id) {
275
276         File file = new File(path.get(position));
277
278         if (file.isDirectory()) {
279             selectButton.setEnabled(false);
280             if (file.canRead()) {
281                 lastPositions.put(currentPath, position);
282                 getDir(path.get(position));
283             } else {
284                 new AlertDialog.Builder(this)
285                         .setIcon(android.R.drawable.stat_sys_warning)
286                         .setTitle(
287                                 "[" + file.getName() + "] "
288                                         + getText(R.string.cant_read_folder))
289                         .setPositiveButton("OK",
290                                 new DialogInterface.OnClickListener() {
291
292                                     public void onClick(DialogInterface dialog,
293                                             int which) {
294
295                                     }
296                                 }).show();
297             }
298         } else {
299             if (selectedFile != null
300                     && selectedFile.getPath().equals(file.getPath())) {
301                 getIntent().putExtra(RESULT_PATH, selectedFile.getPath());
302                 setResult(RESULT_OK, getIntent());
303                 finish();
304             }
305             selectedFile = file;
306             l.setItemChecked(position, true);
307             selectButton.setEnabled(true);
308         }
309     }
310
311     @Override
312     public boolean onKeyDown(int keyCode, KeyEvent event) {
313         if ((keyCode == KeyEvent.KEYCODE_BACK)) {
314             selectButton.setEnabled(false);
315
316             if (!currentPath.equals(ROOT)) {
317                 getDir(parentPath);
318             } else {
319                 return super.onKeyDown(keyCode, event);
320             }
321
322             return true;
323         } else {
324             return super.onKeyDown(keyCode, event);
325         }
326     }
327
328     @Override
329     protected void onSaveInstanceState(Bundle outState) {
330         outState.putString("currentPath", currentPath);
331         super.onSaveInstanceState(outState);
332     }
333
334 }