From cf590114d7e43b6be70f5188401598ed4ad73f32 Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Tue, 14 Feb 2012 18:33:31 +0000 Subject: [PATCH] Rework the filebrowser some to add some functionality. A "hidden" preference now stores the default directory to open. This directory is marked with a gold star. To change the default directory, you touch on a star. Added icon for directories. Added preference to control if only ork files are shown in the file browser. Changed the sort order to do the fancy "logical" sort to compare number components numerically. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@415 180e2498-e6e9-4542-8430-84ac67f01cd8 --- android/res/drawable-mdpi/ic_directory.png | Bin 0 -> 1354 bytes android/res/drawable-mdpi/ic_star_select.png | Bin 0 -> 964 bytes .../res/drawable-mdpi/ic_star_unselected.png | Bin 0 -> 993 bytes android/res/drawable/filebrowser_home.xml | 7 + android/res/layout/filebrowser_list_item.xml | 30 +++ android/res/values/pref_strings.xml | 2 + android/res/values/strings.xml | 4 + android/res/xml/preferences.xml | 17 +- .../filebrowser/AlphanumComparator.java | 138 ++++++++++++++ .../filebrowser/SimpleFileBrowser.java | 174 +++++++++++++++--- 10 files changed, 341 insertions(+), 31 deletions(-) create mode 100644 android/res/drawable-mdpi/ic_directory.png create mode 100644 android/res/drawable-mdpi/ic_star_select.png create mode 100644 android/res/drawable-mdpi/ic_star_unselected.png create mode 100644 android/res/drawable/filebrowser_home.xml create mode 100644 android/res/layout/filebrowser_list_item.xml create mode 100644 android/src/net/sf/openrocket/android/filebrowser/AlphanumComparator.java diff --git a/android/res/drawable-mdpi/ic_directory.png b/android/res/drawable-mdpi/ic_directory.png new file mode 100644 index 0000000000000000000000000000000000000000..a4599e37a063394c74fd83c3d255918431941641 GIT binary patch literal 1354 zcmV-Q1-1H#P)`6pHRCwC#S>EU5HO5hL&7%XpV*!5}StB>BVvHg(m$M3MHE!3Wc0{XfHkWl8|29Lklsu zhb;-L3<-GYww0WfSA8>j($2~neb~u{P>npy+mUAUe(!r^EeHa5m0Jy7@m2w-08{`f z057-cig}H|=``j6<;i4>-KTNe&pD1W z-~Fch-rAM5pU9ko63mau^n5bO@ks#8u?7R%w1JOk9^f(;EWFU9z|f7*Z2WMZH_NwR zP#?hF-rk$tuex&xaD-hj!SM2gLew;}eR$)u8$ToU4}l*Q5kOWH3MGuq#Y->?A@c$R z2c=KuIn5Y@-s9e8uh#?Db7Sp@5%THv57+yhw>xVapKjbIEgT*fKxo@|F_?ge9hMma zTm+EOWu3F2eXb4O-=S1FP;&5ieHtB&gQtUe=ZW(<-nvMZZ~_4Skth@T0!rCznA`Ys zJIR1BG5*^$rT`ai3&2hA0I5^N!JHJ)QX^ZY2E-N-kcMEs-+rUL)p@J4OZKTf=cpLv zlP2Y%L-K_KResS6$0`J3+qPi-))%){G2*=QqGG#nY%l)#SF6>!d-Kbichj_xX+mNn zKX&FHmd`KmZf$ODI!~R|$PZ#?l*f}aKlCa7$3ry_2E9Lf7x?=nE#w1`na2dh?fO@` zb;&+!gY}vf-jf_XqSNMz(rImf$n&D`i&{A!pe)NTlbL;bS<|*`;mjfuNeo9!#B)BI zfGk1-OBI3$Afdl$#mi~gfytb(KAIOVWNZq$EXk=ky(FD7^7}{+Rb@u4kV7GW%kN*_ z#sp=HGJ+%*-HS#UEZ1DLJ_4qsNy}+#$**=PA_e6V8E$0aHSh-$=KP6@W#*Hh#4~<& z`7lK*)=D{PTuKA+2B9N!3BbcY9xe)dl{ZgnE1|jMUa9k0Yq?+=Y+F^}WUL;>AhgjKmpR4&ut#!8bsJstIo1+Sa2Cz(C#Gq8%5A>90l4k@zd%Zhy zVddSGN2(KAEieA>yZhXfhEaWQ>gH6boLM&e1?c<$FqEW!j6^o@VCVOp#p|D3|A^N_ zLV8qAap{P&z{rh%3qT{H<#`nyJrC3K@j0Y!D3e$*6T&C3`V`Dt4QnF#1oIInV}x^c zHy-2XR5XDQ&%^XQ)WiK$(l3^YO_QI%Qj=GjDajIzHI+qY?8TpBO?47enNT1W=rC2{ z%4gtGQAb5*`GPc$nvXtN21Nnz1#g6i zK2_=p{O-zym1}7G-{HxtIrC4>6L8?5F7Kz${xpQupX1 z*MaI2i>CNDYc274U4z-TvGj3E8HKd!|HKu53P1&*0`R{E@Sgw!0E4eF`dICuasU7T M07*qoM6N<$g28)?i~s-t literal 0 HcmV?d00001 diff --git a/android/res/drawable-mdpi/ic_star_select.png b/android/res/drawable-mdpi/ic_star_select.png new file mode 100644 index 0000000000000000000000000000000000000000..4c479314f33be30f568a3a8036eaad797e43451d GIT binary patch literal 964 zcmV;#13UbQP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyV; z0tyB(ie#7o00TrxL_t(&-tC&pYZFlvhrgSqCbnoaC{=4}wbdpd1YC%;o7ROD1Yawq zb|Xch;zG17;$PsRE?N`{r5mH@O5>{0MZ1ZLpx`@dQBi!<`if9VOeWWbj$qAWZj)=L z&;!|JW`5uK-E;3b!w4xQvpF2h@|Xjd11K__x^A2v5lzxT2Y|>h=xmWu9nTS3cA<#y z8VmUF2PVmDSBqRdYnD*TP48beyYR)sqGNVAAVirFCHc>i(&R$P9Y~Ebn6=n6xlmdM za%5kp3y%MheVs0p&H*7@MwH2d+iQtkD47HC%d}fMcwG3>BcjQ60PcmHu=-yELbd{k zhee0eh0pQ@lIl{qP*e?=A`A#2saAV3Z^~dFKrwAbK>$s^4JR8zW@>8O}XjKWN22-s;>AASDxS~t@3l;8c4b6HInSLjriX+lQC$E zC)i!Eh~M931At7EvC|J={2n_B0(}2O%8rAJ2~n^HP7ARou$|+Z4zkWp05=DC8jH}= znUKQ;ccC+GvDM$oNxMMg5})%R>rBYuScION13a~}_=4wv>BPqU)X#+YTSJWH6JM~E zFrBzH#F!n$Tk3^o0>Y|zrC!KfP8;^IMyL2YA)Z?muhfm2PTUFc+%Dpk+v(1P99|LR zsxAOk@!H-CO*h&uvQqUL|eZOx&lzvqSSlHs3>yE(aXt__dFe6<%s} z0Zb=3Y5)=8)ma16Nsbagwt=G5p*rj<74f^G%l`>;jp^l(U`y0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyV; z5EC&Cl^>A+00Uu3L_t(&-tC$}OB+EH$6qqpt)OdIPi@kKN$oZY1)(B>f&_)&K?o@* zEjBm5L93SR!Rp0{L}Ju#x6c6p6pO``iHV6++W;tv z($mq=@uPCB>v{kHd~LIZIF5@}U-LZgiO1t}Z2>SmJd6-Rk=py6ot+=s0$^!rY2~{6 ztg2wYi|n(kg8eSC&$0^kCT9PEQTAC?p=kh%i;EF6&+$C(NhA`ZmII*4Y^hZGYAJwt zJU++syoX|myIEDRHR1;_)a=P z2qggk&d<+NU0q%KX5g*>D2md`77B&8!C>&O;ThmKE}GBhUt35# z0DxQ9_1VkI%a=EHqX!2EFMK{9=(=9CQs0jdvS%`x5CE(gRv??r7OZGo>Lv8b8Ne97 z3IqZlW@cudSqWf$eLa&(rQWNmx@owD2q9~dBxM2MlT{$oEkO-(&vDSl&P~iG zKJLO8JB`+hq8J2#c_siZm#f!=@Smb6ekOz*SAF~rV>}?sas*>MGCe)rD+mIA-Fs*) zZNon?RSO4zRYJ&ao#%D|U>9RN5RFC`#>U2;4-E}HtOXGS!NUxI5R$8Gfs2cad^(*z zNhXuujfB?$nUy4Ia(jC_QVWt!r%z}!QH>Tc#`75CFaW^e;o%>I&?;^7RU48dP3pQH z@p`?!GT;|N$Ql!XGQ>btCYut2gM-eqvom~pdYaQTjWDZ#732P|2Ca_&U#YjtAG_v- P00000NkvXXu0mjfe^;w- literal 0 HcmV?d00001 diff --git a/android/res/drawable/filebrowser_home.xml b/android/res/drawable/filebrowser_home.xml new file mode 100644 index 00000000..1ca0fef6 --- /dev/null +++ b/android/res/drawable/filebrowser_home.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/android/res/layout/filebrowser_list_item.xml b/android/res/layout/filebrowser_list_item.xml new file mode 100644 index 00000000..9e8de5e7 --- /dev/null +++ b/android/res/layout/filebrowser_list_item.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/res/values/pref_strings.xml b/android/res/values/pref_strings.xml index 5bf18212..07eaa47d 100644 --- a/android/res/values/pref_strings.xml +++ b/android/res/values/pref_strings.xml @@ -4,6 +4,8 @@ PreferenceMotorBrowserGroupingOption PreferenceUseInternalFileBrowserOpion + PreferenceFileBrowserBaseDirectory + PreferenceShowOnlyOrkFiles 0 diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 46a5104f..f1202d31 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -93,9 +93,13 @@ Series 2 Motor Browser Grouping + Use Internal File Browser Check to use built in file browser instead of external file browser + Show only ORK files in Internal File Browser + Check to show only .ork files in internal file browser + Millimeters Centimeters diff --git a/android/res/xml/preferences.xml b/android/res/xml/preferences.xml index 77b1cdef..2c1a667f 100644 --- a/android/res/xml/preferences.xml +++ b/android/res/xml/preferences.xml @@ -17,7 +17,22 @@ android:key="@string/PreferenceUseInternalFileBrowserOption" android:summary="@string/useinternalfilebrowsersummary" /> - + + + + + " + * - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)" + * - Remove the type checking and casting in compare(). + * + * To use this class: + * Use the static "sort" method from the java.util.Collections class: + * Collections.sort(your list, new AlphanumComparator()); + */ +public class AlphanumComparator implements Comparator +{ + + private static final Collator sorter = Collator.getInstance(); + static { + sorter.setStrength(Collator.TERTIARY); + sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + } + + private final boolean isDigit(char ch) + { + return ch >= 48 && ch <= 57; + } + + /** Length of string is passed in for improved efficiency (only need to calculate it once) **/ + private final String getChunk(String s, int slength, int marker) + { + StringBuilder chunk = new StringBuilder(); + char c = s.charAt(marker); + chunk.append(c); + marker++; + if (isDigit(c)) + { + while (marker < slength) + { + c = s.charAt(marker); + if (!isDigit(c)) + break; + chunk.append(c); + marker++; + } + } else + { + while (marker < slength) + { + c = s.charAt(marker); + if (isDigit(c)) + break; + chunk.append(c); + marker++; + } + } + return chunk.toString(); + } + + public int compare(String s1, String s2) + { + + int thisMarker = 0; + int thatMarker = 0; + int s1Length = s1.length(); + int s2Length = s2.length(); + + while (thisMarker < s1Length && thatMarker < s2Length) + { + String thisChunk = getChunk(s1, s1Length, thisMarker); + thisMarker += thisChunk.length(); + + String thatChunk = getChunk(s2, s2Length, thatMarker); + thatMarker += thatChunk.length(); + + // If both chunks contain numeric characters, sort them numerically + int result = 0; + if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) + { + // Simple chunk comparison by length. + int thisChunkLength = thisChunk.length(); + result = thisChunkLength - thatChunk.length(); + // If equal, the first different number counts + if (result == 0) + { + for (int i = 0; i < thisChunkLength; i++) + { + result = thisChunk.charAt(i) - thatChunk.charAt(i); + if (result != 0) + { + return result; + } + } + } + } else + { + result = sorter.compare(thisChunk, thatChunk); + } + + if (result != 0) + return result; + } + + return s1Length - s2Length; + } +} diff --git a/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java b/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java index 1c4ff406..f7204de4 100644 --- a/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java +++ b/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java @@ -13,32 +13,47 @@ import net.sf.openrocket.android.actionbarcompat.ActionBarListActivity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; import android.os.Environment; +import android.preference.PreferenceManager; import android.view.View; -import android.widget.ArrayAdapter; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; import android.widget.ListView; +import android.widget.TextView; public class SimpleFileBrowser extends ActionBarListActivity { - private List item = null; - private List path = null; - private String root = "/"; + private List path = null; + private final static File root = new File("/"); + private String baseDirPrefKey; + private String baseDirName; + + private boolean showOnlyOrkFiles; + private static final OrkFileFilter filter = new OrkFileFilter(); - private static final Collator sorter = Collator.getInstance(); - static { - sorter.setStrength(Collator.TERTIARY); - sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION); - } + private static final Comparator sorter = new AlphanumComparator(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simplefilebrowser); - getDir( Environment.getExternalStorageDirectory().getAbsolutePath() ); + + Resources resources = this.getResources(); + baseDirPrefKey = resources.getString(R.string.PreferenceFileBrowserBaseDirectory); + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); + + String showOnlyOrkFilesKey = resources.getString(R.string.PreferenceShowOnlyOrkFiles); + showOnlyOrkFiles = pref.getBoolean(showOnlyOrkFilesKey, false); + + baseDirName = pref.getString(baseDirPrefKey, Environment.getExternalStorageDirectory().getAbsolutePath() ); + getDir( new File(baseDirName) ); } private static class OrkFileFilter implements FileFilter { @@ -51,12 +66,15 @@ public class SimpleFileBrowser extends ActionBarListActivity { if ( arg0.isDirectory() ) { return true; } + return isOrk(arg0); + } + + public boolean isOrk(File arg0) { if ( arg0.getName().endsWith(".ork") ) { return true; } return false; } - } private static class FileComparator implements Comparator { @@ -84,39 +102,32 @@ public class SimpleFileBrowser extends ActionBarListActivity { } - private void getDir(String dirPath) { - setTitle(dirPath); - item = new ArrayList(); - path = new ArrayList(); + private void getDir(File dirPath) { + setTitle(dirPath.getAbsolutePath()); + path = new ArrayList(); - File f = new File(dirPath); - File[] files = f.listFiles(filter); + File[] files = dirPath.listFiles((showOnlyOrkFiles) ? filter : null ); - if (!dirPath.equals(root)) { - item.add(root); + boolean hasUp = false; + if ( !dirPath.getAbsolutePath().equals("/")) { path.add(root); - item.add("../"); - path.add(f.getParent()); + path.add( dirPath.getParentFile() ); + hasUp = true; } Arrays.sort(files, new FileComparator() ); - for (int i = 0; i < files.length; i++) { - File file = files[i]; - path.add(file.getPath()); - if (file.isDirectory()) - item.add(file.getName() + "/"); - else - item.add(file.getName()); + for( File file : files ) { + path.add(file); } - ArrayAdapter fileList = new ArrayAdapter(this, android.R.layout.simple_list_item_1, item); + DirectoryList fileList = new DirectoryList(hasUp, path); setListAdapter(fileList); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { - final File file = new File(path.get(position)); + final File file = path.get(position); if (file.isDirectory()) { if (file.canRead()) getDir(path.get(position)); @@ -140,4 +151,107 @@ public class SimpleFileBrowser extends ActionBarListActivity { finish(); } } + + private class DirectoryList extends BaseAdapter { + + List listing; + boolean hasUp; + + DirectoryList( boolean hasUp ,List listing ) { + this.listing = listing; + this.hasUp = hasUp; + } + + @Override + public int getCount() { + return listing.size(); + } + + @Override + public Object getItem(int arg0) { + return listing.get(arg0); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if ( convertView == null ) { + convertView = getLayoutInflater().inflate(R.layout.filebrowser_list_item, parent, false); + } + + File file = (File) getItem(position); + + // Set the name of the field. + { + String fileName = file.getName(); + if ( hasUp ) { + if (position == 0 ) { + fileName = root.getAbsolutePath(); + } else if (position == 1) { + fileName = ".."; + } + } + + ((TextView) convertView.findViewById(R.id.filebrowser_list_item_name)).setText(fileName); + } + + // Set the "type icon" directory, ork file, or none. + { + ImageView v = (ImageView) (convertView.findViewById(R.id.filebrowser_list_item_typeicon)); + if ( file.isDirectory() ) { + v.setVisibility(View.VISIBLE); + v.setImageResource(R.drawable.ic_directory); + } else if ( filter.isOrk( file ) ) { + v.setVisibility(View.VISIBLE); + v.setImageResource(R.drawable.or_launcher); + } else { + v.setVisibility(View.INVISIBLE); + } + } + + // Set the "base directory" thing. + { + ImageView v = (ImageView) (convertView.findViewById(R.id.filebrowser_list_item_homeicon)); + if ( !file.isDirectory() ) { + v.setVisibility(View.INVISIBLE); + v.setClickable(false); + } else { + v.setVisibility(View.VISIBLE); + if ( baseDirName.equals( file.getAbsolutePath() ) ) { + v.setSelected(true); + } else { + v.setSelected(false); + v.setClickable(true); + v.setOnClickListener( new ChangeBaseDirectory(file.getAbsolutePath())); + } + } + } + return convertView; + } + } + + private class ChangeBaseDirectory implements View.OnClickListener { + + private final String dirname; + + ChangeBaseDirectory ( String dirname ) { + this.dirname = dirname; + } + + @Override + public void onClick(View v) { + if ( v.isSelected() == false ) { + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(SimpleFileBrowser.this); + baseDirName = dirname; + pref.edit().putString(baseDirPrefKey, dirname).apply(); + SimpleFileBrowser.this.getDir(new File(dirname)); + } + } + + } + } -- 2.47.2