--- /dev/null
+/*\r
+ * The Alphanum Algorithm is an improved sorting algorithm for strings\r
+ * containing numbers. Instead of sorting numbers in ASCII order like\r
+ * a standard sort, this algorithm sorts numbers in numeric order.\r
+ *\r
+ * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com\r
+ *\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
+ *\r
+ */\r
+\r
+/*\r
+ * Subsequently this code had been hacked up to make it genericized and support\r
+ * folding upper/lower case.\r
+ */\r
+package net.sf.openrocket.android.filebrowser;\r
+\r
+import java.text.Collator;\r
+import java.util.Comparator;\r
+\r
+/**\r
+ * This is an updated version with enhancements made by Daniel Migowski,\r
+ * Andre Bogus, and David Koelle\r
+ *\r
+ * To convert to use Templates (Java 1.5+):\r
+ * - Change "implements Comparator" to "implements Comparator<String>"\r
+ * - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"\r
+ * - Remove the type checking and casting in compare().\r
+ *\r
+ * To use this class:\r
+ * Use the static "sort" method from the java.util.Collections class:\r
+ * Collections.sort(your list, new AlphanumComparator());\r
+ */\r
+public class AlphanumComparator implements Comparator<String>\r
+{\r
+ \r
+ private static final Collator sorter = Collator.getInstance();\r
+ static {\r
+ sorter.setStrength(Collator.TERTIARY);\r
+ sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION);\r
+ }\r
+\r
+ private final boolean isDigit(char ch)\r
+ {\r
+ return ch >= 48 && ch <= 57;\r
+ }\r
+\r
+ /** Length of string is passed in for improved efficiency (only need to calculate it once) **/\r
+ private final String getChunk(String s, int slength, int marker)\r
+ {\r
+ StringBuilder chunk = new StringBuilder();\r
+ char c = s.charAt(marker);\r
+ chunk.append(c);\r
+ marker++;\r
+ if (isDigit(c))\r
+ {\r
+ while (marker < slength)\r
+ {\r
+ c = s.charAt(marker);\r
+ if (!isDigit(c))\r
+ break;\r
+ chunk.append(c);\r
+ marker++;\r
+ }\r
+ } else\r
+ {\r
+ while (marker < slength)\r
+ {\r
+ c = s.charAt(marker);\r
+ if (isDigit(c))\r
+ break;\r
+ chunk.append(c);\r
+ marker++;\r
+ }\r
+ }\r
+ return chunk.toString();\r
+ }\r
+\r
+ public int compare(String s1, String s2)\r
+ {\r
+\r
+ int thisMarker = 0;\r
+ int thatMarker = 0;\r
+ int s1Length = s1.length();\r
+ int s2Length = s2.length();\r
+\r
+ while (thisMarker < s1Length && thatMarker < s2Length)\r
+ {\r
+ String thisChunk = getChunk(s1, s1Length, thisMarker);\r
+ thisMarker += thisChunk.length();\r
+\r
+ String thatChunk = getChunk(s2, s2Length, thatMarker);\r
+ thatMarker += thatChunk.length();\r
+\r
+ // If both chunks contain numeric characters, sort them numerically\r
+ int result = 0;\r
+ if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))\r
+ {\r
+ // Simple chunk comparison by length.\r
+ int thisChunkLength = thisChunk.length();\r
+ result = thisChunkLength - thatChunk.length();\r
+ // If equal, the first different number counts\r
+ if (result == 0)\r
+ {\r
+ for (int i = 0; i < thisChunkLength; i++)\r
+ {\r
+ result = thisChunk.charAt(i) - thatChunk.charAt(i);\r
+ if (result != 0)\r
+ {\r
+ return result;\r
+ }\r
+ }\r
+ }\r
+ } else\r
+ {\r
+ result = sorter.compare(thisChunk, thatChunk);\r
+ }\r
+\r
+ if (result != 0)\r
+ return result;\r
+ }\r
+\r
+ return s1Length - s2Length;\r
+ }\r
+}\r
import android.app.AlertDialog;\r
import android.content.DialogInterface;\r
import android.content.Intent;\r
+import android.content.SharedPreferences;\r
+import android.content.res.Resources;\r
import android.net.Uri;\r
import android.os.Bundle;\r
import android.os.Environment;\r
+import android.preference.PreferenceManager;\r
import android.view.View;\r
-import android.widget.ArrayAdapter;\r
+import android.view.ViewGroup;\r
+import android.widget.BaseAdapter;\r
+import android.widget.ImageView;\r
import android.widget.ListView;\r
+import android.widget.TextView;\r
\r
public class SimpleFileBrowser extends ActionBarListActivity {\r
\r
- private List<String> item = null;\r
- private List<String> path = null;\r
- private String root = "/";\r
+ private List<File> path = null;\r
+ private final static File root = new File("/");\r
\r
+ private String baseDirPrefKey;\r
+ private String baseDirName;\r
+\r
+ private boolean showOnlyOrkFiles;\r
+ \r
private static final OrkFileFilter filter = new OrkFileFilter();\r
- private static final Collator sorter = Collator.getInstance();\r
- static {\r
- sorter.setStrength(Collator.TERTIARY);\r
- sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION);\r
- }\r
+ private static final Comparator<String> sorter = new AlphanumComparator();\r
\r
/** Called when the activity is first created. */\r
@Override\r
public void onCreate(Bundle savedInstanceState) {\r
super.onCreate(savedInstanceState);\r
setContentView(R.layout.simplefilebrowser);\r
- getDir( Environment.getExternalStorageDirectory().getAbsolutePath() );\r
+\r
+ Resources resources = this.getResources();\r
+ baseDirPrefKey = resources.getString(R.string.PreferenceFileBrowserBaseDirectory);\r
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r
+\r
+ String showOnlyOrkFilesKey = resources.getString(R.string.PreferenceShowOnlyOrkFiles);\r
+ showOnlyOrkFiles = pref.getBoolean(showOnlyOrkFilesKey, false);\r
+\r
+ baseDirName = pref.getString(baseDirPrefKey, Environment.getExternalStorageDirectory().getAbsolutePath() );\r
+ getDir( new File(baseDirName) );\r
}\r
\r
private static class OrkFileFilter implements FileFilter {\r
if ( arg0.isDirectory() ) { \r
return true;\r
}\r
+ return isOrk(arg0);\r
+ }\r
+\r
+ public boolean isOrk(File arg0) {\r
if ( arg0.getName().endsWith(".ork") ) {\r
return true;\r
}\r
return false;\r
}\r
-\r
}\r
\r
private static class FileComparator implements Comparator<File> {\r
\r
}\r
\r
- private void getDir(String dirPath) {\r
- setTitle(dirPath);\r
- item = new ArrayList<String>();\r
- path = new ArrayList<String>();\r
+ private void getDir(File dirPath) {\r
+ setTitle(dirPath.getAbsolutePath());\r
+ path = new ArrayList<File>();\r
\r
- File f = new File(dirPath);\r
- File[] files = f.listFiles(filter);\r
+ File[] files = dirPath.listFiles((showOnlyOrkFiles) ? filter : null );\r
\r
- if (!dirPath.equals(root)) {\r
- item.add(root);\r
+ boolean hasUp = false;\r
+ if ( !dirPath.getAbsolutePath().equals("/")) {\r
path.add(root);\r
- item.add("../");\r
- path.add(f.getParent());\r
+ path.add( dirPath.getParentFile() );\r
+ hasUp = true;\r
}\r
\r
Arrays.sort(files, new FileComparator() );\r
- for (int i = 0; i < files.length; i++) {\r
- File file = files[i];\r
- path.add(file.getPath());\r
- if (file.isDirectory())\r
- item.add(file.getName() + "/");\r
- else\r
- item.add(file.getName());\r
+ for( File file : files ) {\r
+ path.add(file);\r
}\r
\r
- ArrayAdapter<String> fileList = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, item);\r
+ DirectoryList fileList = new DirectoryList(hasUp, path);\r
setListAdapter(fileList);\r
\r
}\r
\r
@Override\r
protected void onListItemClick(ListView l, View v, int position, long id) {\r
- final File file = new File(path.get(position));\r
+ final File file = path.get(position);\r
if (file.isDirectory()) {\r
if (file.canRead())\r
getDir(path.get(position));\r
finish();\r
}\r
}\r
+\r
+ private class DirectoryList extends BaseAdapter {\r
+\r
+ List<File> listing;\r
+ boolean hasUp;\r
+\r
+ DirectoryList( boolean hasUp ,List<File> listing ) {\r
+ this.listing = listing;\r
+ this.hasUp = hasUp;\r
+ }\r
+\r
+ @Override\r
+ public int getCount() {\r
+ return listing.size();\r
+ }\r
+\r
+ @Override\r
+ public Object getItem(int arg0) {\r
+ return listing.get(arg0);\r
+ }\r
+\r
+ @Override\r
+ public long getItemId(int position) {\r
+ return position;\r
+ }\r
+\r
+ @Override\r
+ public View getView(int position, View convertView, ViewGroup parent) {\r
+ if ( convertView == null ) {\r
+ convertView = getLayoutInflater().inflate(R.layout.filebrowser_list_item, parent, false);\r
+ }\r
+\r
+ File file = (File) getItem(position);\r
+\r
+ // Set the name of the field.\r
+ {\r
+ String fileName = file.getName();\r
+ if ( hasUp ) {\r
+ if (position == 0 ) {\r
+ fileName = root.getAbsolutePath();\r
+ } else if (position == 1) {\r
+ fileName = "..";\r
+ }\r
+ }\r
+\r
+ ((TextView) convertView.findViewById(R.id.filebrowser_list_item_name)).setText(fileName);\r
+ }\r
+ \r
+ // Set the "type icon" directory, ork file, or none.\r
+ {\r
+ ImageView v = (ImageView) (convertView.findViewById(R.id.filebrowser_list_item_typeicon));\r
+ if ( file.isDirectory() ) {\r
+ v.setVisibility(View.VISIBLE);\r
+ v.setImageResource(R.drawable.ic_directory);\r
+ } else if ( filter.isOrk( file ) ) {\r
+ v.setVisibility(View.VISIBLE);\r
+ v.setImageResource(R.drawable.or_launcher);\r
+ } else {\r
+ v.setVisibility(View.INVISIBLE);\r
+ }\r
+ }\r
+\r
+ // Set the "base directory" thing.\r
+ {\r
+ ImageView v = (ImageView) (convertView.findViewById(R.id.filebrowser_list_item_homeicon));\r
+ if ( !file.isDirectory() ) {\r
+ v.setVisibility(View.INVISIBLE);\r
+ v.setClickable(false);\r
+ } else {\r
+ v.setVisibility(View.VISIBLE);\r
+ if ( baseDirName.equals( file.getAbsolutePath() ) ) {\r
+ v.setSelected(true);\r
+ } else {\r
+ v.setSelected(false);\r
+ v.setClickable(true);\r
+ v.setOnClickListener( new ChangeBaseDirectory(file.getAbsolutePath()));\r
+ }\r
+ }\r
+ }\r
+ return convertView;\r
+ }\r
+ }\r
+\r
+ private class ChangeBaseDirectory implements View.OnClickListener {\r
+\r
+ private final String dirname;\r
+ \r
+ ChangeBaseDirectory ( String dirname ) {\r
+ this.dirname = dirname;\r
+ }\r
+ \r
+ @Override\r
+ public void onClick(View v) {\r
+ if ( v.isSelected() == false ) {\r
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(SimpleFileBrowser.this);\r
+ baseDirName = dirname;\r
+ pref.edit().putString(baseDirPrefKey, dirname).apply();\r
+ SimpleFileBrowser.this.getDir(new File(dirname));\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
}\r