package org.sana.android.procedure;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import org.sana.R;
import org.sana.android.Constants;
import org.w3c.dom.Node;
import android.content.Context;
import android.preference.PreferenceManager;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;
/**
* BinaryUploadElement is a ProcedureElement that is created when a "BINARYFILE"
* element is inserted into an XML procedure description. It allows a user to
* select a binary file stored on the phone for upload. The path of where the
* selectable files reside is set in the Sana settings dialog. By default, the
* most recent file modified in the folder is selected.
*
* A refresh button allows the following example interaction to occur:
* <ol>
* <li>page with binaryuploadelement comes up on phone</li>
* <li>healthworker uses external ultrasound which automatically stores an MPG
* file on the SD card</li>
* <li> if is Sana still on the screen, the healthworker hits the refresh file
* list button to automatically re-source the files on the SD card and
* automatically select the file that was just created.
* </li>
* </ol>
* <p/>
* <ul type="none">
* <li><b>Clinical Use </b> Defined by subclasses.</li>
* <li><b>Collects </b> name of a binary file to upload.</li>
* </ul>
*
* @author Sana Dev Team
*/
public class BinaryUploadElement extends ProcedureElement implements
OnClickListener, OnItemSelectedListener
{
private Button refresh;
private TextView tvBinary;
private TextView result;
private Spinner spin;
private List<String> sdfiles = new ArrayList<String>();
File[] filelist;
private ArrayAdapter<String> adapter;
private Context context;
/** {@inheritDoc} */
@Override
public ElementType getType() {
return ElementType.BINARYFILE;
}
/** {@inheritDoc} */
protected View createView(Context c) {
LinearLayout binaryContainer = new LinearLayout(c);
binaryContainer.setOrientation(LinearLayout.VERTICAL);
context = c;
if(question == null) {
question = c.getString(R.string.question_standard_binary_element);
}
tvBinary = new TextView(c);
tvBinary.setText(question);
tvBinary.setGravity(Gravity.CENTER);
tvBinary.setTextAppearance(c, android.R.style.TextAppearance_Medium);
binaryContainer.addView(tvBinary, new LinearLayout.LayoutParams(-1,-1,
0.1f));
refresh = new Button(c);
refresh.setText("Refresh file list");
refresh.setOnClickListener(this);
spin = new Spinner(c);
spin.setOnItemSelectedListener(this);
updateSdList();
binaryContainer.addView(spin, new LinearLayout.LayoutParams(-1,-1,
0.1f));
binaryContainer.addView(refresh, new LinearLayout.LayoutParams(-1,-1,
0.1f));
result = new TextView(c);
result.setText("Folder is empty!");
result.setGravity(Gravity.CENTER);
result.setTextAppearance(c, android.R.style.TextAppearance_Small);
binaryContainer.addView(result, new LinearLayout.LayoutParams(-1,-1,
0.1f));
return binaryContainer;
}
// updates the list of files available
private void updateSdList() {
File folder = new File(PreferenceManager.getDefaultSharedPreferences(
context).getString(Constants.PREFERENCE_STORAGE_DIRECTORY,
Constants.DEFAULT_BINARY_FILE_FOLDER));
// we may want to add a filename filter here if we want to restrict to
// certain types i.e. mpg files
FileFilter nofolders = new FileFilter() {
public boolean accept(File f) {
return !f.isDirectory();
}
};
filelist = folder.listFiles(nofolders);
int lastModifiedFileIndex = -1;
sdfiles = new ArrayList<String>();
if (filelist.length > 0) {
lastModifiedFileIndex = 0;
for (int i=0; i < filelist.length; i++) {
sdfiles.add(filelist[i].getName());
if (filelist[i].lastModified() >
filelist[lastModifiedFileIndex].lastModified())
{
lastModifiedFileIndex = i;
}
}
}
adapter = new ArrayAdapter<String>(context,
android.R.layout.simple_spinner_item,
sdfiles);
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adapter);
if (lastModifiedFileIndex != -1) {
spin.setSelection(lastModifiedFileIndex);
}
}
/** {@inheritDoc} */
@Override
public void onClick(View v) {
if (v == refresh) {
updateSdList();
if (spin.getCount() == 0)
result.setText("Folder is empty!");
}
}
/** {@inheritDoc} */
public void setAnswer(String answer) {
this.answer = answer;
}
/**
* Gets the text representation of the answer
*
* @return the path of the selected file for upload, or empty string if no
* file was selected.
*/
public String getAnswer() {
if(!isViewActive())
return answer;
if (spin.getCount() > 0)
return filelist[spin.getSelectedItemPosition()].getAbsolutePath();
else
return "";
}
/** {@inheritDoc} */
public void buildXML(StringBuilder sb) {
sb.append("<Element type=\"" + getType().name() + "\" id=\"" + id);
sb.append("\" answer=\"" + getAnswer());
sb.append("\" concept=\"" + getConcept());
sb.append("\"/>\n");
}
private BinaryUploadElement(String id, String question, String answer,
String concept, String figure, String audio)
{
super(id, question, answer, concept, figure, audio);
}
/** @see ProcedureElement#fromXML(String, String, String, String, String, String, Node) */
public static BinaryUploadElement fromXML(String id, String question,
String answer, String concept, String figure, String audio,
Node node) throws ProcedureParseException
{
return new BinaryUploadElement(id, question, answer, concept, figure,
audio);
}
/** {@inheritDoc} */
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String loadedFileResult = "\nloaded successfully";
loadedFileResult = spin.getSelectedItem() + loadedFileResult;
result.setText(loadedFileResult);
}
/** {@inheritDoc} */
public void onNothingSelected(AdapterView<?> arg0) {
}
}