package org.sana.android.procedure;
import java.io.IOException;
import java.util.ArrayList;
import org.sana.R;
import org.sana.android.ImagePreviewDialog;
import org.sana.android.ScalingImageAdapter;
import org.sana.android.db.SanaDB;
import org.sana.android.db.SanaDB.ImageSQLFormat;
import org.sana.util.UUIDUtil;
import org.w3c.dom.Node;
import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* PictureElement is a ProcedureElement that allows a user to take photos. It
* displays thumbnails of images that have been taken, allows a user to bring
* up the camera to take new ones, and allows a user to click on a thumbnail to
* bring up a dialog allowing for closer image review and examination.
* <p/>
* <ul type="none">
* <li><b>Clinical Use </b>This element is useful in clinical scenarios wherever
* images will aid in diagnosis.</li>
* <li><b>Collects </b>Zero or more images returned as a comma separated list of
* integer picture ids.</li>
* </ul>
*
* @author Sana Development Team
*/
public class PictureElement extends ProcedureElement implements OnClickListener,
OnItemClickListener, OnItemLongClickListener
{
public static String TAG = PictureElement.class.getSimpleName();
public static final String PARAMS_NAME = "keys";
private ScalingImageAdapter imageAdapter;
private static final int THUMBNAIL_SCALE_FACTOR = 5;
private Button cameraButton;
private GridView imageGrid;
private ImagePreviewDialog imageReview;
private Intent imageCaptureIntent;
/** {@inheritDoc} */
@Override
public ElementType getType() {
return ElementType.PICTURE;
}
/** {@inheritDoc} */
@Override
protected View createView(Context c) {
imageGrid = new GridView(c);
Log.i(TAG, "Looking up for encounter: " + getProcedure().getInstanceUri());
String procedureId =
getProcedure().getInstanceUri().getLastPathSegment();
Log.w(TAG, "PictureELement: Encounter id " + procedureId);
String whereStr;
if(!UUIDUtil.isValid(procedureId))
whereStr = ImageSQLFormat.ENCOUNTER_ID + " = ? AND "
+ ImageSQLFormat.ELEMENT_ID + " = ? AND "
+ ImageSQLFormat.FILE_VALID + " = ?";
else
whereStr = ImageSQLFormat.ENCOUNTER_ID + " = '?' AND "
+ ImageSQLFormat.ELEMENT_ID + " = ? AND "
+ ImageSQLFormat.FILE_VALID + " = ?";
Cursor cursor = c.getContentResolver().query(
SanaDB.ImageSQLFormat.CONTENT_URI,
new String[] { ImageSQLFormat._ID }, whereStr,
new String[] { procedureId, id, "1" }, null);
// HAXMODE -- if we don't do this we leak the Cursor
if (c instanceof Activity) {
((Activity)c).startManagingCursor(cursor);
}
imageAdapter = new ScalingImageAdapter(c, cursor,
THUMBNAIL_SCALE_FACTOR);
imageGrid.setAdapter(imageAdapter);
imageGrid.setNumColumns(3);
imageGrid.setVerticalSpacing(5);
imageGrid.setPadding(5, 0, 0, 0);
imageGrid.setOnItemClickListener(this);
imageGrid.setOnItemLongClickListener(this);
//imageGrid.setTranscriptMode(imageGrid.TRANSCRIPT_MODE_ALWAYS_SCROLL);
cameraButton = new Button(c);
cameraButton.setText(R.string.btn_add_photo);
cameraButton.setOnClickListener(this);
imageReview = new ImagePreviewDialog(c);
LinearLayout picContainer = new LinearLayout(c);
picContainer.setOrientation(LinearLayout.VERTICAL);
if(question == null) {
question = c.getString(R.string.question_standard_picture_element);
}
//Set question
TextView tv = new TextView(c);
tv.setText(String.format("%s: %s", id, question));
tv.setGravity(Gravity.CENTER);
tv.setTextAppearance(c, android.R.style.TextAppearance_Medium);
//Add to layout
picContainer.addView(tv, new LinearLayout.LayoutParams(-1,-1,0.1f));
//picContainer.addView(imageView, new LinearLayout.LayoutParams(-1,-1,0.1f));
//Add button
picContainer.addView(cameraButton,
new LinearLayout.LayoutParams(-1,-1,0.1f));
picContainer.addView(imageGrid,
new LinearLayout.LayoutParams(-1, 210)); //LayoutParams(-1,-1,0.8f));
picContainer.setWeightSum(1.0f);
return picContainer;
}
/**
* Sends an Intent to ProcedureRunner with the procedure id and element
* id as parameters.
* */
@Override
public void onClick(View v) {
if (v == cameraButton) {
String procedureId =
getProcedure().getInstanceUri().getLastPathSegment(); //which procedure its part of
String[] params = {procedureId, id, String.valueOf(imageAdapter.getCount() + 1)};
imageCaptureIntent = new Intent(getContext(), ((Activity) getContext()).getClass());
imageCaptureIntent.putExtra(PARAMS_NAME, params)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra("intentKey", 0);
((Activity) getContext()).startActivity(imageCaptureIntent);
}
}
/** Toggles the image as selected */
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Log.i(TAG, "onItemClick pos:" + position + " id:" + id);
imageAdapter.toggleSelection(id);
//v.postInvalidate();
v.invalidate();
//SelectableImageView view = (SelectableImageView) v;
//view.toggleMultiSelected();
//view.invalidate();
//iadapter.notifyDataSetChanged();
//parent.invalidate();
}
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemLongClickListener#onItemLongClick(android.widget.AdapterView, android.view.View, int, long)
*/
/** Opens Image view dialog. */
@Override
public boolean onItemLongClick(AdapterView<?> parent, View v, int position,
long id) {
Log.i(TAG, "" + position);
long imageId = imageAdapter.getItemId(position);
Uri imageUri = ContentUris.withAppendedId(ImageSQLFormat.CONTENT_URI,
imageId);
try {
// hack for in-emulator demo, commented out here, but use to load a
// static image
// imageReview.showImage(getContext().getContentResolver().openInputStream(Uri.parse("android.resource://org.sana/"
// + R.drawable.incision2)));
imageReview.showImage(imageUri);
imageReview.show();
} catch (IOException e) {
Log.e(TAG, "Can't open the image file for uri " + imageUri);
}
return false;
}
/** {@inheritDoc} */
@Override
public void setAnswer(String answer) {
if(!isViewActive()) {
this.answer = answer;
} else {
// TODO : Fix this so that it works! We have the id # of the picture, and we need to reset 'selected' to match this such that
// iadapter.getItemId(selected) == the answer we have here.
String[] ids = answer.split(",");
for(String id : ids) {
imageAdapter.setSelected(Long.parseLong(id), true);
}
}
}
/** {@inheritDoc} */
@Override
public String getAnswer() {
if(!isViewActive())
return answer;
ArrayList<String> answerz = new ArrayList<String>();
/*for(Entry<Long,SelectableImageView> e : iadapter.getViewMap().entrySet()) {
Log.i(TAG, "getAnswer -- item " + e.getKey());
if(e.getValue().isMultiSelected()) {
answerz.add(Long.toString(e.getKey()));
Log.i(TAG, "getAnswer -- item selected" + e.getKey());
}
}*/
for (int i = 0; i < imageAdapter.getCount(); i++) {
Long id = imageAdapter.getItemId(i);
Log.i(TAG, "Considering element " + id + " for selection.");
if (imageAdapter.isSelected(id)) {
Log.i(TAG, "Element " + id + " is selected.");
answerz.add(Long.toString(id));
}
}
if (answerz.size() > 0) {
StringBuilder csv = new StringBuilder(answerz.get(0));
for (int i=1; i<answerz.size(); i++) {
csv.append(",");
csv.append(answerz.get(i));
}
Log.i(TAG, "getAnswers is returning " + csv.toString());
return csv.toString();
} else {
Log.i(TAG, "getAnswers is returning blank");
return "";
}
}
/** {@inheritDoc} */
@Override
public void buildXML(StringBuilder sb) {
sb.append("<Element type=\"" + getType().name() + "\" id=\""
+ id);
sb.append("\" question=\"" + question);
sb.append("\" answer=\"" + getAnswer());
sb.append("\" concept=\"" + getConcept());
sb.append("\"/>\n");
}
/** Default Constructor */
private PictureElement(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 PictureElement fromXML(String id, String question,
String answer, String concept, String figure, String audio,
Node node) throws ProcedureParseException
{
return new PictureElement(id, question, answer, concept, figure, audio);
}
}