/**
* ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab.
*
* @author Robin Murray <robin5@pdx.edu> (code)
* @author Miguel Figliozzi <figliozzi@pdx.edu> and ORcycle team (general app
* design and features, report questionnaires and new ORcycle features)
*
* For more information on the project, go to
* http://www.pdx.edu/transportation-lab/orcycle and http://www.pdx.edu/transportation-lab/app-development
*
* Updated/modified for Oregon pilot study and app deployment.
*
* ORcycle is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version.
* ORcycle is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with
* ORcycle. If not, see <http://www.gnu.org/licenses/>.
*
*/
package edu.pdx.cecs.orcycle;
import java.text.SimpleDateFormat;
import java.util.Locale;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class NoteMapActivity extends Activity {
private enum NoteMapView { info, image, map};
public static final String EXTRA_NOTE_ID = "shownote";
private static final String MODULE_TAG = "NoteMapActivity";
private static final SimpleDateFormat reportDateFormatter = new SimpleDateFormat("EEEE, MM/dd/yyyy", Locale.US);
public GoogleMap map;
private MenuItem mnuInfo;
private MenuItem mnuImage;
private MenuItem mnuMap;
private ImageView imageView;
private Bitmap photo;
private View questionsView;
private boolean noteHasImage;
private NoteMapView currentView = NoteMapView.map;
private String[] accidentSeverities;
private String[] problemSeverity;
// *********************************************************************************
// * Fragment Handlers
// *********************************************************************************
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.activity_note_map);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
accidentSeverities = getResources().getStringArray(R.array.ara_a_severity_2);
problemSeverity = getResources().getStringArray(R.array.arsi_a_urgency_2);
imageView = (ImageView) findViewById(R.id.imageView);
imageView.setVisibility(View.INVISIBLE);
View accidentView = findViewById(R.id.report_accident_root_view);
accidentView.setVisibility(View.INVISIBLE);
View SafetyIssueView = findViewById(R.id.report_safety_issue_root_view);
SafetyIssueView.setVisibility(View.INVISIBLE);
// Set zoom controls
map = ((MapFragment) getFragmentManager().findFragmentById(
R.id.noteMap)).getMap();
Bundle cmds = getIntent().getExtras();
long noteId = cmds.getLong(EXTRA_NOTE_ID);
NoteData note = NoteData.fetchNote(this, noteId);
if (note.isAccident()) {
questionsView = accidentView;
}
else {
questionsView = SafetyIssueView;
}
// Show note details
TextView tvHeaderSeverity = (TextView) findViewById(R.id.tvHeaderSeverity);
TextView tvHeaderFancyStart = (TextView) findViewById(R.id.tvHeaderFancyStart);
TextView tvNmComment = (TextView) findViewById(R.id.tvNmComment);
TextView tvNmComment2 = (TextView) findViewById(R.id.tvNmComment2);
tvHeaderSeverity.setText(getNoteSeverityText(note.getNoteSeverity()));
tvHeaderFancyStart.setText(note.getFancyStart());
tvNmComment.setText(note.getNotedetails());
tvNmComment2.setText(note.getNotedetails());
TextView tvAccidentSeverity = (TextView) findViewById(R.id.tv_anm_a_severity_of_problem);
TextView tvAccidentObject = (TextView) findViewById(R.id.tv_anm_a_object);
TextView tvAccidentActions = (TextView) findViewById(R.id.tv_anm_a_actions);
TextView tvAccidentContrib = (TextView) findViewById(R.id.tv_anm_a_contrib);
TextView tvSafetyIssue = (TextView) findViewById(R.id.tv_anm_a_safety_issue);
TextView tvSafetyUrgency = (TextView) findViewById(R.id.tv_anm_a_urgency);
TextView tvIssueDate = (TextView) findViewById(R.id.tv_anm_a_issue_date);
TextView tvCrashDate = (TextView) findViewById(R.id.tv_anm_a_crash_date);
tvAccidentSeverity.setText("");
tvAccidentObject.setText("");
tvAccidentActions.setText("");
tvAccidentContrib.setText("");
tvSafetyIssue.setText("");
tvSafetyUrgency.setText("");
if (note.getReportDate() <= 0) {
tvIssueDate.setText("Not specified");
tvCrashDate.setText("Not specified");
}
else {
tvIssueDate.setText(reportDateFormatter.format(note.getReportDate()));
tvCrashDate.setText(reportDateFormatter.format(note.getReportDate()));
}
// Center & zoom the map
LatLng center = new LatLng(note.getLatitude() * 1E-6, note.getLongitude() * 1E-6);
try {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(center, 16));
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
// Add note marker to map
noteHasImage = false;
if (note != null) {
LatLng notePosition = new LatLng(note.getLatitude() * 1E-6, note.getLongitude() * 1E-6);
int noteDrawable = DbAnswers.getNoteSeverityMapImageResourceId(note.getNoteSeverity());
map.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(noteDrawable))
.anchor(0.0f, 1.0f) // Anchors the marker on the bottom left
.position(notePosition));
noteHasImage = note.hasImage();
}
// If image exist, add it to the imageView widget
if (noteHasImage) {
// Store photo error, retrieve error
photo = BitmapFactory.decodeByteArray(note.getImage(), 0, note.getImage().length);
if (photo.getHeight() > photo.getWidth()) {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView.setScaleType(ImageView.ScaleType.FIT_START);
}
imageView.setImageBitmap(photo);
}
getNoteResponses(note.getNoteId());
} catch (Exception ex) {
Log.e(MODULE_TAG, ex.toString());
}
currentView = NoteMapView.map;
}
@Override
public void onBackPressed() {
try {
transitionToTabsConfigActivity();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
try {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.note_map, menu);
mnuInfo = menu.getItem(0);
mnuImage = menu.getItem(1);
mnuMap = menu.getItem(2);
setCurrentView(currentView);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return true;
}
@Override
public void onResume() {
super.onResume();
try {
setCurrentView(currentView);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
private void setCurrentView(NoteMapView noteMapView) {
switch (noteMapView) {
case info:
if (noteHasImage) {
if (NoteMapView.image == currentView) {
Animation animFadeOut = AnimationUtils.loadAnimation(
getApplicationContext(), android.R.anim.fade_out);
imageView.setAnimation(animFadeOut);
}
imageView.setVisibility(View.INVISIBLE);
}
questionsView.setVisibility(View.VISIBLE);
if ((null != mnuInfo) && (null != mnuImage) && (null != mnuMap)) {
mnuInfo.setVisible(false);
mnuImage.setVisible(noteHasImage);
mnuMap.setVisible(true);
}
break;
case image:
questionsView.setVisibility(View.INVISIBLE);
Animation animFadeIn = AnimationUtils.loadAnimation(
getApplicationContext(), android.R.anim.fade_in);
imageView.setAnimation(animFadeIn);
imageView.setVisibility(View.VISIBLE);
if ((null != mnuInfo) && (null != mnuImage) && (null != mnuMap)) {
mnuInfo.setVisible(true);
mnuImage.setVisible(false);
mnuMap.setVisible(true);
}
break;
case map:
questionsView.setVisibility(View.INVISIBLE);
if (noteHasImage) {
if (NoteMapView.image == currentView) {
Animation animFadeOut = AnimationUtils.loadAnimation(
getApplicationContext(), android.R.anim.fade_out);
imageView.setAnimation(animFadeOut);
}
imageView.setVisibility(View.INVISIBLE);
}
if ((null != mnuInfo) && (null != mnuImage) && (null != mnuMap)) {
mnuInfo.setVisible(true);
mnuImage.setVisible(noteHasImage);
mnuMap.setVisible(false);
}
break;
}
currentView = noteMapView;
}
/* Handles item selections */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
try {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_note_map_view_info:
setCurrentView(NoteMapView.info);
return true;
case R.id.action_note_map_view_image:
setCurrentView(NoteMapView.image);
return true;
case R.id.action_note_map_view_map:
setCurrentView(NoteMapView.map);
return true;
case R.id.action_note_map_close:
// close -> go back to FragmentMainInput
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return super.onOptionsItemSelected(item);
}
private String getNoteSeverityText(int noteSeverity) {
int index;
if (-1 != (index = DbAnswers.findIndex(DbAnswers.accidentSeverity, noteSeverity))) {
return accidentSeverities[index + 1];
}
if (-1 != (index = DbAnswers.findIndex(DbAnswers.safetyUrgency, noteSeverity))) {
return problemSeverity[index + 1];
}
return "Unknown";
}
// *********************************************************************************
// * Transition Functions
// *********************************************************************************
private void transitionToTabsConfigActivity() {
Intent intent = new Intent(NoteMapActivity.this, TabsConfig.class);
intent.putExtra(TabsConfig.EXTRA_SHOW_FRAGMENT, TabsConfig.FRAG_INDEX_SAVED_NOTES);
startActivity(intent);
overridePendingTransition(android.R.anim.fade_in, R.anim.slide_out_down);
finish();
}
// *********************************************************************************
// * Helper Functions
// *********************************************************************************
private void getNoteResponses(long noteId) {
DbAdapter mDb = new DbAdapter(this);
mDb.openReadOnly();
try {
Cursor answers = mDb.fetchNoteAnswers(noteId);
int questionCol = answers.getColumnIndex(DbAdapter.K_NOTE_ANSWER_QUESTION_ID);
int answerCol = answers.getColumnIndex(DbAdapter.K_NOTE_ANSWER_ANSWER_ID);
int otherCol = answers.getColumnIndex(DbAdapter.K_NOTE_ANSWER_OTHER_TEXT);
StringBuilder sbAccidentSeverity = new StringBuilder();
StringBuilder sbAccidentObject = new StringBuilder();
StringBuilder sbAccidentAction = new StringBuilder();
StringBuilder sbAccidentContrib = new StringBuilder();
StringBuilder sbSafetyIssue = new StringBuilder();
StringBuilder sbSafetySeverity = new StringBuilder();
int questionId;
int answerId;
String otherText;
// Cycle thru the database entries
while (!answers.isAfterLast()) {
questionId = answers.getInt(questionCol);
answerId = answers.getInt(answerCol);
if (null != (otherText = answers.getString(otherCol))) {
otherText = otherText.trim();
}
try {
switch(questionId) {
case DbQuestions.ACCIDENT_SEVERITY:
append(sbAccidentSeverity, R.array.ara_a_severity, DbAnswers.accidentSeverity, answerId);
break;
case DbQuestions.ACCIDENT_OBJECT:
append(sbAccidentObject, R.array.ara_a_object, DbAnswers.accidentObject, answerId, otherText);
break;
case DbQuestions.ACCIDENT_ACTION:
append(sbAccidentAction, R.array.ara_a_actions, DbAnswers.accidentAction, answerId, otherText);
break;
case DbQuestions.ACCIDENT_CONTRIB:
append(sbAccidentContrib, R.array.ara_a_contributers, DbAnswers.accidentContrib, answerId, otherText);
break;
case DbQuestions.SAFETY_ISSUE:
append(sbSafetyIssue, R.array.arsi_a_safety_issues, DbAnswers.safetyIssue, answerId, otherText);
break;
case DbQuestions.SAFETY_URGENCY:
append(sbSafetySeverity, R.array.arsi_a_urgency, DbAnswers.safetyUrgency, answerId);
break;
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
// Move to next row
answers.moveToNext();
}
answers.close();
// Show note details
TextView tvAccidentSeverity = (TextView) findViewById(R.id.tv_anm_a_severity_of_problem);
TextView tvAccidentobject = (TextView) findViewById(R.id.tv_anm_a_object);
TextView tvAccidentActions = (TextView) findViewById(R.id.tv_anm_a_actions);
TextView tvAccidentContrib = (TextView) findViewById(R.id.tv_anm_a_contrib);
TextView tvSafetyIssue = (TextView) findViewById(R.id.tv_anm_a_safety_issue);
TextView tvSafetyUrgency = (TextView) findViewById(R.id.tv_anm_a_urgency);
tvAccidentSeverity.setText(sbAccidentSeverity.toString());
tvAccidentobject.setText(sbAccidentObject.toString());
tvAccidentActions.setText(sbAccidentAction.toString());
tvAccidentContrib.setText(sbAccidentContrib.toString());
tvSafetyIssue.setText(sbSafetyIssue.toString());
tvSafetyUrgency.setText(sbSafetySeverity.toString());
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
finally {
mDb.close();
}
}
private void append(StringBuilder sb, int textArrayId, int[] answers, int answerId) {
if (sb.length() > 0)
sb.append("\r\n");
sb.append(DbAnswers.getAnswerText(this, textArrayId, answers, answerId));
}
private void append(StringBuilder sb, int textArrayId, int[] answers, int answerId, String otherText) {
if ((null == otherText) || otherText.equals("")) {
if (sb.length() > 0)
sb.append("\r\n");
sb.append(DbAnswers.getAnswerText(this, textArrayId, answers, answerId));
}
else {
if (sb.length() > 0)
sb.append("\r\n");
sb.append(otherText);
}
}
}