/* This file is part of ZamiaDroid. * * ZamiaDroid 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 * (at your option) any later version. * * ZamiaDroid 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 ZamiaDroid. If not, see <http://www.gnu.org/licenses/>. */ package uni.projecte.Activities.Citations; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Hashtable; import java.util.Iterator; import java.util.Map.Entry; import uni.projecte.Main; import uni.projecte.R; import uni.projecte.Activities.Projects.ProjectManagement; import uni.projecte.Activities.RemoteDBs.TaxonRemoteTab; import uni.projecte.controler.CitationControler; import uni.projecte.controler.CitationSecondLevelControler; import uni.projecte.controler.DataTypeControler; import uni.projecte.controler.MultiPhotoControler; import uni.projecte.controler.PolygonControler; import uni.projecte.controler.PreferencesControler; import uni.projecte.controler.ProjectControler; import uni.projecte.controler.ThesaurusControler; import uni.projecte.dataLayer.ThesaurusManager.ListAdapters.ThesaurusAutoCompleteAdapter; import uni.projecte.dataLayer.utils.PhotoUtils; import uni.projecte.dataTypes.ProjectField; import uni.projecte.dataTypes.SecondLevelFieldHandler; import uni.projecte.dataTypes.Utilities; import uni.projecte.hardware.gps.MainLocationListener; import uni.projecte.maps.GoogleMapsAPI; import uni.projecte.maps.UTMDisplay; import uni.projecte.maps.utils.LatLon; import uni.projecte.maps.utils.LatLonParcel; import uni.projecte.ui.multiphoto.MultiPhotoFieldForm; import uni.projecte.ui.multiphoto.PhotoFieldForm; import uni.projecte.ui.multiphoto.SimplePhotoFieldForm; import uni.projecte.ui.polygon.PolygonField; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.MutableContextWrapper; import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Color; import android.location.LocationListener; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Vibrator; import android.provider.MediaStore; import android.text.Html; import android.text.InputType; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import edu.ub.bio.biogeolib.CoordConverter; import edu.ub.bio.biogeolib.CoordinateLatLon; import edu.ub.bio.biogeolib.CoordinateUTM; public class Sampling extends Activity { /*dataBase helpers*/ private ProjectControler projCnt; private ThesaurusControler tC; private CitationControler citCnt; private MultiPhotoControler multiPhotoCnt; public final static int SUCCESS_RETURN_CODE = 1; public static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 3; public static final int LOAD_REMOTE_TAB = 6; public static final int POLYGON_EDIT = 7; public static final int NEW_PROJECT = 8; public static final int ENABLE_GPS=Menu.FIRST; public static final int REPEATED_VALUES=Menu.FIRST+1; public static final int SHOW_TAXON_INFO=Menu.FIRST+2; public static final int SHOW_CITATIONS=Menu.FIRST+3; private SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_hhmmss"); private SecondLevelFieldHandler sCLH; private long projId=-1; private PreferencesControler prefCnt; private TextView tvProjectName; private TextView mLocationDisplay; private TextView mAltitudeDisplay; private TextView mLocationLabel; private TextView mTimeStampDisplay; private String thName; private String projType; private String thType; private boolean hasThesaurusField=false; /*top date Display*/ private TextView mDateDisplay; private int mYear; private int mMonth; private int mDay; private ArrayList<View> elementsList; private int n; private Double lat; private Double longitude; private Double elevation; private String presettedDate; private long altitudeFieldId=-1; private long citationIdCopy=-1; private boolean thStatus; private String fileName=""; private Uri imageUri; private String photoPath; private String lastPhotoField; private Button bUpdateLoc; private boolean predefinedLocation=false; private AutoCompleteTextView thElem; private TextView altitudeTv; private ThesaurusAutoCompleteAdapter elements; private Hashtable<String, Integer> complexValuesList; private Hashtable<String, Boolean> repetedValuesList; private Hashtable<String, String> repetedValuesLabelList; private Hashtable<String, PhotoFieldForm> photoFieldsList; private PolygonField polygonField; private ProjectField oldPhotoField; private LocationManager mLocationManager; private MainLocationListener mLocationListener; private ProgressDialog pdMovePhotos; private boolean tempGPS=false; private boolean uniqueCitationEntry; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Utilities.setLocale(this); setContentView(R.layout.citation_capture); /*DB access*/ projCnt=new ProjectControler(this); tC= new ThesaurusControler(this); prefCnt= new PreferencesControler(this); citCnt= new CitationControler(this); multiPhotoCnt = new MultiPhotoControler(this); /* button Listeners*/ Button bCreateSample = (Button)findViewById(R.id.bCreateSample); bCreateSample.setOnClickListener(bCreateCitationListener); bUpdateLoc = (Button)findViewById(R.id.bUpdateLocation); bUpdateLoc.setOnClickListener(bUpdateLocationListener); /* instances of main view elements */ mDateDisplay = (TextView) findViewById(R.id.dateDisplay); mLocationDisplay = (TextView) findViewById(R.id.tvLocation); mLocationLabel = (TextView) findViewById(R.id.tvCoordinatesLabel); mAltitudeDisplay = (TextView) findViewById(R.id.tvAltitude); mTimeStampDisplay = (TextView) findViewById(R.id.tvSettedDate); tvProjectName = (TextView)findViewById(R.id.projectName); projId=getIntent().getExtras().getLong("id"); projCnt.loadProjectInfoById(projId); tvProjectName.setText(projCnt.getName()); tvProjectName.setOnClickListener(changeProject); lat=getIntent().getExtras().getDouble("latitude"); longitude=getIntent().getExtras().getDouble("longitude"); elevation=getIntent().getExtras().getDouble("altitude"); presettedDate=getIntent().getExtras().getString("timestamp"); citationIdCopy=getIntent().getExtras().getLong("citationId"); uniqueCitationEntry=getIntent().getExtras().getBoolean("uniqueCitation"); if(lat==0.0 && longitude==0.0){ lat=null; longitude=null; } //we'll create a citation with a pre-setted location and/or date if(lat!=null && longitude!=null){ predefinedLocation=true; uniqueCitationEntry=true; bUpdateLoc.setVisibility(View.INVISIBLE); if(elevation==null || elevation==0.0){ GoogleMapsAPI googleAP= new GoogleMapsAPI(); elevation=googleAP.getElevationFromGoogleMaps(longitude, lat); } if(presettedDate!=null){ CitationControler citCnt=new CitationControler(this); presettedDate=citCnt.getAvailableTimestamp(projId,presettedDate); } updateDisplay(); } else{ if(prefCnt.gpsNeeded()){ callGPS(); } } if(prefCnt.isUTM()){ mLocationLabel.setText(Html.fromHtml("<b>UTM:</b>")); } createFieldForm(projId); updateDisplay(); if(projCnt.hasOldPhotoField(projId)) { updatePhotoField(); } } @Override protected void onStop(){ super.onStop(); tC.closeCursors(); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { lat= mLocationListener.getLatitude(); longitude= mLocationListener.getLongitude(); elevation= mLocationListener.getElevation(); if(lat==0.0 && longitude==0.0){ lat=null; longitude=null; } else{ mLocationManager.removeUpdates(mLocationListener); tempGPS=false; if(polygonField!=null && polygonField.isWaitingGPS()) polygonField.addPoint(lat,longitude,elevation); updateDisplay(); } } }; private void callGPS(){ mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { mLocationListener = new MainLocationListener(mLocationManager,handler,prefCnt.getGeoidCorrection()); mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, (LocationListener) mLocationListener); tempGPS=true; updateDisplay(); } else{ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.enableGPSQuestion) .setCancelable(false) .setPositiveButton(R.string.enableGPS, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(callGPSSettingIntent); } }) .setNegativeButton(R.string.noGPS, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // finish(); prefCnt.setGPSNeeded(false); } }); AlertDialog alert = builder.create(); alert.show(); } } private void updatePhotoField() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.dialogChangePhotoField) .setCancelable(false) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { updatePhotoFieldDialog(); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); AlertDialog alert = builder.create(); alert.show(); } private void updatePhotoFieldDialog(){ pdMovePhotos = new ProgressDialog(this); pdMovePhotos.setCancelable(false); pdMovePhotos.setMessage(getString(R.string.dialogUpdatePhotoFieldTitle)); pdMovePhotos.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pdMovePhotos.setProgress(0); Thread thread = new Thread() { @Override public void run() { multiPhotoCnt.updatePhotoField(projId, oldPhotoField,handlerUpdatePhotoField); } }; thread.start(); } private Handler handlerUpdatePhotoField = new Handler() { @Override public void handleMessage(Message msg) { if(msg.what==-1){ pdMovePhotos.incrementProgressBy(1); } else if(msg.what==0){ pdMovePhotos.dismiss(); Utilities.showToast(getString(R.string.changePhotosFinished), getBaseContext()); finish(); } else if(msg.what>0){ pdMovePhotos.setProgress(msg.what); pdMovePhotos.show(); } else{ } } }; public boolean onCreateOptionsMenu(Menu menu) { if(prefCnt.gpsNeeded()) menu.add(0, ENABLE_GPS, 0,R.string.mDesactivateGPS).setIcon(android.R.drawable.ic_menu_mylocation); else menu.add(0, ENABLE_GPS, 0,R.string.mActivateGPS).setIcon(android.R.drawable.ic_menu_mylocation); menu.add(0, REPEATED_VALUES, 0,R.string.mRepeatedField).setIcon(android.R.drawable.ic_menu_preferences); if(hasThesaurusField) menu.add(0, SHOW_TAXON_INFO, 0,R.string.mShowTaxonInfo).setIcon(android.R.drawable.ic_dialog_info); menu.add(0, SHOW_CITATIONS, 0,R.string.bSampleManagement).setIcon(android.R.drawable.ic_menu_agenda); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case ENABLE_GPS: if(prefCnt.gpsNeeded()){ prefCnt.setGPSNeeded(false); } else{ prefCnt.setGPSNeeded(true); callGPS(); } break; case REPEATED_VALUES: showRepetedValuesList(); break; case SHOW_CITATIONS: Intent intent = new Intent(getBaseContext(), CitationManager.class); Bundle b = new Bundle(); b = new Bundle(); b.putLong("id", projId); intent.putExtras(b); startActivity(intent); break; case SHOW_TAXON_INFO: if (!emptyThesaurus()){ Toast.makeText(getBaseContext(), R.string.fieldMissing, Toast.LENGTH_SHORT).show(); } else{ if(thStatus){ String taxonName=thElem.getText().toString(); if(tC.checkTaxonBelongs(taxonName)){ loadBiologicalRemoteCard(taxonName); } else{ Toast.makeText(getBaseContext(), R.string.toastTaxonNotExists, Toast.LENGTH_SHORT).show(); } } else{ Toast.makeText(getBaseContext(), R.string.toastNotThesarus, Toast.LENGTH_SHORT).show(); } } break; } return super.onOptionsItemSelected(item); } private void showRepetedValuesList() { int elements=repetedValuesList.size(); boolean[] states= new boolean[elements]; final CharSequence[] items= new CharSequence[elements]; int i=0; for (Entry<String, Boolean> s : repetedValuesList.entrySet()) { states[i]=s.getValue(); items[i]=s.getKey(); i++; } AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.repeatedFieldTitle)); builder.setMultiChoiceItems(items, states, new DialogInterface.OnMultiChoiceClickListener(){ public void onClick(DialogInterface dialogInterface, int item, boolean state) { repetedValuesList.remove(items[item]); repetedValuesList.put(items[item].toString(),state); } }); builder.create().show(); } /* * * */ private void loadBiologicalRemoteCard(String taxonName){ String filum=Utilities.translateThTypeToFilumLetter(this, thType); if(filum!=null){ Intent intent = new Intent(getBaseContext(), TaxonRemoteTab.class); intent.putExtra("filumLetter", filum); intent.putExtra("taxon",taxonName); intent.putExtra("projId",projId); startActivityForResult(intent,LOAD_REMOTE_TAB); } } /* * When backButton is pressed a dialog is shown showing an alert. * The alert advises the user that it will lose data if it finishes the activity. * * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent) */ public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { if(!filledFields()){ endActivity(); finish(); } else{ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.backFromCitationMessage) .setCancelable(false) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { endActivity(); finish(); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } return true; } return false; } public void endActivity(){ prefCnt.setGPSNeeded(true); if(tempGPS && prefCnt.gpsNeeded() && mLocationManager!=null && mLocationListener !=null) mLocationManager.removeUpdates(mLocationListener); sCLH.removeSecondLevelFields(); //removing stored multiPhotos Iterator<String> photoFields=photoFieldsList.keySet().iterator(); while(photoFields.hasNext()){ PhotoFieldForm tmpField=photoFieldsList.get(photoFields.next()); if(tmpField instanceof MultiPhotoFieldForm) ((MultiPhotoFieldForm) tmpField).removeAllPhotos(); } tC.closeThReader(); } /* * It takes the date of the system and location and shows it. * */ private void updateDisplay() { final Calendar c = Calendar.getInstance(); mYear = c.get(Calendar.YEAR); mMonth = c.get(Calendar.MONTH); mDay = c.get(Calendar.DAY_OF_MONTH); mDateDisplay.setText( new StringBuilder() // Month is 0 based so add 1 .append(mDay).append("-") .append(mMonth + 1).append("-") .append(mYear).append(" ") /* .append(" - ") .append(pad(mHour)).append(":") .append(pad(mMinute))*/); if(presettedDate!=null) { mTimeStampDisplay.setVisibility(View.VISIBLE); mTimeStampDisplay.setText(" | "+presettedDate); mTimeStampDisplay.setTextColor(Color.GREEN); } else mTimeStampDisplay.setVisibility(View.GONE); if(lat==null || longitude==null){ //pm.setGPSNeeded(false); //mLocationDisplay.setText(R.string.gps_disabled); mLocationDisplay.setText(""); bUpdateLoc.setVisibility(Button.INVISIBLE); } else{ if(prefCnt.isUTM()){ CoordinateUTM utm = CoordConverter.getInstance().toUTM(new CoordinateLatLon(lat,longitude)); if(utm.getShortForm().length()<15){ mLocationDisplay.setText(utm.getShortForm()); } else{ String utmP=UTMDisplay.convertUTM(utm.getShortForm(),"1m",true); mLocationDisplay.setText(utmP); } } else { mLocationDisplay.setText(lat.toString().subSequence(0, 7)+" - "+longitude.toString().subSequence(0, 7)); } mAltitudeDisplay.setText(""+(int)elevation.doubleValue()); if(altitudeTv!=null) altitudeTv.setText(""+(int)elevation.doubleValue()); if(!predefinedLocation) bUpdateLoc.setVisibility(Button.VISIBLE); if(tempGPS){ mLocationDisplay.setTextColor(Color.RED); mAltitudeDisplay.setTextColor(Color.RED); } else { mLocationDisplay.setTextColor(Color.GREEN); mAltitudeDisplay.setTextColor(Color.GREEN); } } } /* * Listener of the citation creation button. * * The thesaurus is mandatory. When no geo-location button is check, GPS activity won't be called. * */ private OnClickListener bCreateCitationListener = new OnClickListener() { public void onClick(View v) { //if the thesaurus is not chosen when can't create a citation if (!emptyThesaurus()){ Toast.makeText(getBaseContext(), R.string.fieldMissing, Toast.LENGTH_SHORT).show(); } else{ if(tvProjectName.length()==0){ Toast.makeText(getBaseContext(), R.string.projNameMissing, Toast.LENGTH_SHORT).show(); } else { if(prefCnt.gpsNeeded()&& tempGPS){ if(lat==null && longitude==null){ Utilities.showToast(getString(R.string.toastGPSWorking), getBaseContext()); } else{ AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); builder.setMessage(R.string.waitingForGPS) .setCancelable(false) .setPositiveButton(R.string.lastKnownLocation, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); createSample(lat, longitude); } }) .setNegativeButton(R.string.waitForLocation, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } } else{ if(lat==null && longitude==null){ createSample(100, 190); } else{ //GPS Activity that will give back the latitude and longitude createSample(lat, longitude); } } } } } }; private OnClickListener bUpdateLocationListener = new OnClickListener() { public void onClick(View v) { if(prefCnt.gpsNeeded()){ callGPS(); } } }; /* * It checks if the thesaurus field is filled * */ private boolean emptyThesaurus(){ boolean notEmpty=true; for (int i=0;i<n;i++){ View vi=elementsList.get(i); if((vi instanceof AutoCompleteTextView)){ if (((AutoCompleteTextView)vi).length()==0) notEmpty=false; } } return notEmpty; } private boolean filledFields(){ boolean filled=false; for (int i=0;i<n && !filled;i++){ View vi=elementsList.get(i); if((vi instanceof TextView)){ if (((TextView)vi).length()!=0) filled=true; } } return filled; } /* * * This method clears the form for the next citation * */ private void removeAttributes(){ n=elementsList.size(); for (int i=0;i<n;i++){ View et=elementsList.get(i); if (et instanceof EditText){ Boolean repeat=false; String label=repetedValuesLabelList.get(et.getTag().toString()); if(label!=null) repeat=repetedValuesList.get(label); if(repeat==null || !repeat) ((TextView) et).setText(""); } else if(et instanceof CheckBox){ ((CheckBox) et).setChecked(false); } else if(et instanceof Spinner){ int pos=complexValuesList.get(et.getTag()); if(pos>-1) ((Spinner) et).setSelection(pos); } else if(et instanceof ListView){ polygonField.clearForm(); } else if(et instanceof TextView){ createRandomIdSecondLevelField(et); } } //iterate over all photos Iterator<String> photoFields=photoFieldsList.keySet().iterator(); while(photoFields.hasNext()){ PhotoFieldForm tmpField=photoFieldsList.get(photoFields.next()); tmpField.clearForm(); } } private void createRandomIdSecondLevelField(View et) { String secLevId=sCLH.replaceSecondLevelField(et.getId(), (String) et.getTag()); ((TextView) et).setText(secLevId); } /* * This method takes the values filled by the user in the form and store them into the DB * For each type of field the retrieval of the value will be different * */ private void addFieldValues(long idSample, CitationControler smplCntr){ boolean isMultiPhotoField=false; boolean isPolygon=false; n=elementsList.size(); smplCntr.startTransaction(); for (int i=0;i<n;i++){ String value=""; String label=""; long citationValueId=-1; View et=elementsList.get(i); if(et instanceof CheckBox){ if (((CheckBox) et).isChecked()) value="true"; else value="false"; label=et.getTag().toString(); } else if (et instanceof EditText){ value= ((EditText) et).getText().toString(); label= ((EditText) et).getTag().toString(); } else if(et instanceof TextView){ value= ((TextView) et).getText().toString(); label= ((TextView) et).getTag().toString(); } else if(et instanceof HorizontalScrollView){ //multiPhotoElement MultiPhotoFieldForm multiPhoto=(MultiPhotoFieldForm) photoFieldsList.get(et.getTag()); value=multiPhoto.getSecondLevelId(); label=(String) et.getTag(); isMultiPhotoField=true; } else if(et instanceof ListView){ value=polygonField.getSecondLevelId(); label=polygonField.getFieldLabel(); } else { Spinner sp=(Spinner)et; if(sp.getSelectedItem()==null) value=""; else value =((Spinner) et).getSelectedItem().toString(); label= ((Spinner) et).getTag().toString(); } /*if value is empty we don't add the value into the database*/ if(value.compareTo("")==0){ } else{ Log.i("Citation","Action-> created citationValue("+idSample+") : Label: "+label+" Value: "+value+" FieldId: "+et.getId()); citationValueId=smplCntr.addCitationField(projId,idSample,et.getId(),label, value); if(isMultiPhotoField){ MultiPhotoFieldForm multiPhoto=(MultiPhotoFieldForm) photoFieldsList.get(et.getTag()); multiPhoto.setCitationId(citationValueId); isMultiPhotoField=false; } if(isPolygon){ polygonField.setCitationId(citationValueId); isPolygon=false; } } } smplCntr.addObservationAuthor(projId,idSample); if(altitudeFieldId>0 && elevation!=0.0) smplCntr.addCitationField(projId,idSample,altitudeFieldId,"altitude", String.valueOf((int)elevation.doubleValue())); smplCntr.EndTransaction(); } private void addCitationSubFields(long parentId) { //Adding MultiPhoto: photoList MultiPhotoControler multiProjCnt= new MultiPhotoControler(this); Iterator<String> photoFields=photoFieldsList.keySet().iterator(); while(photoFields.hasNext()){ PhotoFieldForm tmpField=photoFieldsList.get(photoFields.next()); if(tmpField instanceof MultiPhotoFieldForm){ long subFieldId=multiProjCnt.getMultiPhotoSubFieldId(((MultiPhotoFieldForm) tmpField).getFieldId()); multiProjCnt.addPhotosList((MultiPhotoFieldForm) tmpField,subFieldId,projId,parentId); } } //Adding Polygon if(polygonField!=null){ PolygonControler polygonCnt= new PolygonControler(this); polygonCnt.addPolygonList(polygonField,projId,parentId); } } /* * * This method stores the citation in the DB. Getting location and projectId * It also calls the addFildValues method for the insertion of the filled fields. * */ private long createSample(double latPoint, double longPoint){ CitationControler sampleCntr=new CitationControler(this); long idSample=-1; // Sample Creation with lat,long, comment and rsId if(presettedDate==null) idSample=sampleCntr.createCitation(projId, latPoint, longPoint, ""); else idSample=sampleCntr.createCitationWithDate(projId, latPoint, longPoint, "",presettedDate); Log.d("Citation","Action -> Create New Citation"); ((Vibrator)getSystemService(VIBRATOR_SERVICE)).vibrate(300); addFieldValues(idSample, sampleCntr); Log.d("Citation","Action -> Fields Added"); addCitationSubFields(idSample); Log.d("Citation","Action -> MutliFields Added"); Toast.makeText(getBaseContext(), getString(R.string.bSuccessCitationCreation), Toast.LENGTH_SHORT).show(); Log.d("Citation","Action -> Citation Created: "+tvProjectName.getText().toString()+":"+idSample+"|"+latPoint+":"+longPoint); tempGPS=true; removeAttributes(); if(uniqueCitationEntry) { finish(); } else{ if(prefCnt.gpsNeeded()){ updateDisplay(); callGPS(); } elementsList.get(0).requestFocus(); } return idSample; } private OnItemClickListener synonimThListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(prefCnt.getSynonymCheck()){ View syno=((LinearLayout) view).getChildAt(0); View name=((LinearLayout) view).getChildAt(1); final View icodeView=((LinearLayout) view).getChildAt(2); int visible=syno.getVisibility(); if(visible>0){ AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); String question = String.format(getString(R.string.synonymQuestion), ((TextView)name).getText()); builder.setMessage(question) .setCancelable(false) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { String icode=((TextView) icodeView).getText().toString(); thElem.setText(tC.fetchThesaurusSynonymous(icode)); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } } // update gps status if(prefCnt.gpsNeeded() && prefCnt.isTaxonUpdate()){ callGPS(); } } }; /* * This method creates the project fields form. * For each field it creates a TextView with the field label and also another * view that will be field with data provided by the user. * * Type: * simple -> EditText * thesaurus -> AutoCompleteEditText * bool -> CheckBox * complex -> Spinner or (dropdowList in other languages) * */ private void createFieldForm(final long projId){ //list where items will the hold elementsList=new ArrayList<View>(); complexValuesList= new Hashtable<String, Integer>(); repetedValuesList= new Hashtable<String, Boolean>(); repetedValuesLabelList= new Hashtable<String, String>(); photoFieldsList = new Hashtable<String, PhotoFieldForm>(); sCLH=new SecondLevelFieldHandler(this); DataTypeControler dtH=new DataTypeControler(this); LinearLayout lPhoto=null; LinearLayout llsL=null; //main layout that will include the form LinearLayout l= (LinearLayout)findViewById(R.id.fieldsLay); if(l.getChildCount()>0) l.removeAllViews(); ProjectControler rsC=new ProjectControler(this); citCnt.startTransaction(); rsC.loadProjectInfoById(projId); //we load the Th reader that will help to create the autocomplete view with the items of the provided thName. thName=rsC.getThName(); projType=rsC.getProjType(); thStatus=tC.initThReader(thName); Cursor thInfo=tC.getThInfo(thName); thInfo.moveToFirst(); if(thInfo.getCount()>0){ thType=Utilities.translateThTypeToCurrentLanguage(this, thInfo.getString(4)); } ArrayList<ProjectField> projFieldList=rsC.getProjFields(projId); Iterator<ProjectField> it=projFieldList.iterator(); int i=0; //for each field we will create the TextView with the label and an "special" view where the user will provide the field value while(it.hasNext()){ LinearLayout llField=new LinearLayout(this); TextView t=new TextView(getBaseContext()); ProjectField att=it.next(); String fieldType =att.getType(); String fieldLabel= att.getLabel(); t.setText(fieldLabel); llField.addView(t); llField.setPadding(4, 4, 4, 4); //when the field is Simple we create an EditText if (fieldType.equals("simple") || fieldType.equals("number")){ EditText etFieldValue=(EditText) new EditText(getBaseContext()); int idD= (int) att.getId(); String tag=att.getName(); checkAutoField(att); if(att.getValue()!=null && att.getValue().length()>0) { etFieldValue.setText(att.getValue()); } if(citationIdCopy>0) { String pred=citCnt.getFieldValue(citationIdCopy,att.getId()); etFieldValue.setText(pred); } etFieldValue.setTag(tag); etFieldValue.setId(idD); if(fieldType.equals("number")){ etFieldValue.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); } else{ etFieldValue.setImeOptions(EditorInfo.IME_ACTION_NEXT); } if(att.getName().equals("altitude")) altitudeTv=etFieldValue; etFieldValue.setLayoutParams(new LayoutParams (ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams. WRAP_CONTENT)); llField.addView(etFieldValue); elementsList.add(etFieldValue); repetedValuesList.put(att.getLabel(), false); repetedValuesLabelList.put(att.getName(), att.getLabel()); } //when the field is boolean we create a CheckBox else if (fieldType.equals("boolean")){ CheckBox e=(CheckBox) new CheckBox(getBaseContext()); int idD= (int) att.getId(); e.setId(idD); e.setTag(att.getName()); llField.addView(e); elementsList.add(e); if(citationIdCopy>0) { String pred=citCnt.getFieldValue(citationIdCopy,att.getId()); if(pred.equals("true")) e.setChecked(true); } } //when the field is photo we show photo Interface else if (fieldType.equals("photo")){ oldPhotoField=att; SimplePhotoFieldForm photoFieldForm = new SimplePhotoFieldForm(this,projId,att,llField); elementsList.add(photoFieldForm.getEtPhotoPath()); lPhoto=photoFieldForm.getlPhoto(); llField=photoFieldForm.getLlField(); photoFieldForm.setAddPhotoEvent(takePicture); photoFieldForm.setRemoveEvent(removePicture); photoFieldsList.put(att.getName(), photoFieldForm); } else if(fieldType.equals("polygon")){ polygonField= new PolygonField(this, projId, att, llField,PolygonField.CREATE_MODE); polygonField.setAddPointListener(capturePoint); elementsList.add(new ListView(this)); } else if(fieldType.equals("multiPhoto")){ MultiPhotoFieldForm multiPhotoFieldForm = new MultiPhotoFieldForm(this, projId, att, llField,MultiPhotoFieldForm.CREATE_MODE); multiPhotoFieldForm.setAddPhotoEvent(takePicture); photoFieldsList.put(att.getName(), multiPhotoFieldForm); elementsList.add(multiPhotoFieldForm.getImageScroll()); llField.setOrientation(LinearLayout.VERTICAL); } //when the field is a thesaurus we create an AutoCompleteView and we fill it with the items provided by the ThesaurusControler else if(fieldType.equals("thesaurus")){ String tag=att.getName(); View e; if(thStatus){ e=(AutoCompleteTextView) new AutoCompleteTextView(getBaseContext()); elements = tC.fillData((AutoCompleteTextView) e); ((AutoCompleteTextView) e).setAdapter(elements); ((AutoCompleteTextView) e).setOnItemClickListener(synonimThListener); thElem=((AutoCompleteTextView) e); hasThesaurusField=true; } else{ e=(EditText) new EditText(getBaseContext()); } ((TextView) e).setImeOptions(EditorInfo.IME_ACTION_NEXT); ((TextView) e).setHint(getString(R.string.thHint)); e.setTag(tag); int idD= (int) att.getId(); e.setId(idD); e.setLayoutParams(new LayoutParams (ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams. WRAP_CONTENT)); llField.addView(e); elementsList.add(e); } else if(fieldType.equals("secondLevel")){ Button showList=(Button) new Button(getBaseContext()); showList.setText(this.getString(R.string.slShowElem)); Button addSubFields=(Button) new Button(getBaseContext()); addSubFields.setText(this.getString(R.string.slAddElem)); TextView et= (TextView) new TextView(getBaseContext()); TextView numElements=new TextView(this); int idD= (int) att.getId(); et.setId(idD); et.setTag(att.getName()); String subLevelIdentifiear=sCLH.addSecondLevelField(idD, att.getName(),numElements); addSubFields.setTag(subLevelIdentifiear); et.setText(Html.fromHtml("<b>"+subLevelIdentifiear+"</b>")); addSubFields.setId(idD); showList.setId(idD); et.setPadding(3,3,3,10); et.setImeOptions(EditorInfo.IME_ACTION_NEXT); showList.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent myIntent = new Intent(v.getContext(), SecondLevelList.class); myIntent.putExtra("id", projId); myIntent.putExtra("subProjId", (long)v.getId()); String subLevelTag=sCLH.getSecLevelIdByFieldId(v.getId()); myIntent.putExtra("subLevelTag", subLevelTag); startActivityForResult(myIntent, 5); } }); addSubFields.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent myIntent = new Intent(v.getContext(), SecondLevelSampling.class); myIntent.putExtra("id", projId); myIntent.putExtra("subProjId", (long)v.getId()); String subLevelTag=sCLH.getSecLevelIdByFieldId(v.getId()); myIntent.putExtra("subLevelTag", subLevelTag); startActivityForResult(myIntent, 4); } }); numElements.setText("0"); llField.addView(et); llsL= new LinearLayout(this); llsL.setOrientation(LinearLayout.HORIZONTAL); llsL.addView(showList); llsL.addView(addSubFields); llsL.addView(numElements); //l.addView(ll); elementsList.add(et); } else{ String[] items=dtH.getItemsbyFieldId(att.getId()); Spinner e=(Spinner)new Spinner(this); e.setPrompt(getString(R.string.chooseItem)); e.setLayoutParams(new LayoutParams (ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams. WRAP_CONTENT)); ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item,items); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); e.setAdapter(adapter); if(att.getValue()!=null && att.getValue().length()>0) complexValuesList.put(att.getName(),setDefaultSpinnerItem(e,att.getValue(),items)); else complexValuesList.put(att.getName(), 0); int idD= (int) att.getId(); e.setId(idD); e.setTag(att.getName()); if(citationIdCopy>0) { String pred=citCnt.getFieldValue(citationIdCopy,att.getId()); Utilities.setDefaultSpinnerItem(e, pred, items); } llField.addView(e); elementsList.add(e); } if (fieldType.equals("photo")){ LinearLayout ll= new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); ll.setPadding(3,3,3,3); ll.addView(llField); ll.addView(lPhoto); ll.setBackgroundColor(Color.parseColor("#ff333333")); l.addView(ll); } else if(fieldType.equals("secondLevel")){ LinearLayout ll= new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); ll.setPadding(3,3,3,3); ll.addView(llField); ll.addView(llsL); ll.setBackgroundColor(Color.parseColor("#ff333333")); l.addView(ll); } else l.addView(llField,i); i++; } n=i; if(elementsList.size()>1){ if(elementsList.get(n-1) instanceof TextView) { ((TextView) elementsList.get(n-1)).setImeOptions(EditorInfo.IME_ACTION_DONE); } } //if altitude is not visible get need fieldId if(altitudeTv==null){ altitudeFieldId=rsC.getFieldIdByName(projId, "altitude"); } citCnt.EndTransaction(); } private OnClickListener changeProject = new OnClickListener() { public void onClick(View v) { if(!filledFields()){ endActivity(); Intent projActivity = new Intent(getBaseContext(),ProjectManagement.class); projActivity.putExtra("tab", 0); projActivity.putExtra("changeProject",true); startActivityForResult(projActivity,NEW_PROJECT); } else{ AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); builder.setMessage(R.string.backFromCitationMessage) .setCancelable(false) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { endActivity(); Intent projActivity = new Intent(getBaseContext(),ProjectManagement.class); projActivity.putExtra("tab", 0); projActivity.putExtra("changeProject",true); startActivityForResult(projActivity,NEW_PROJECT); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); } } }; private OnClickListener removePicture = new OnClickListener() { public void onClick(View v) { PhotoFieldForm photoField=photoFieldsList.get(v.getTag()); photoField.removePhoto(); PhotoUtils.removePhoto(Environment.getExternalStorageDirectory()+"/"+prefCnt.getDefaultPath()+"/Photos/"+fileName); } }; private OnClickListener capturePoint = new OnClickListener() { public void onClick(View v) { polygonField.setWaitingGPS(true); if(!tempGPS) callGPS(); } }; private OnClickListener takePicture = new OnClickListener() { public void onClick(View v) { String projName=tvProjectName.getText().toString(); String currentTime = formatter.format(new Date()); projName=projName.replace(" ", "_"); fileName = projName + currentTime + ".jpg"; prefCnt.setLastPhotoPath(fileName); lastPhotoField=(String) v.getTag(); //create parameters for Intent with filename ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, fileName); String imageDesc=String.format(getString(R.string.photoDescription),projName); values.put(MediaStore.Images.Media.DESCRIPTION,imageDesc); //imageUri is the current activity attribute, define and save it for later usage (also in onSaveInstanceState) photoPath=Environment.getExternalStorageDirectory() + "/zamiaDroid/Photos/"+fileName; File file = new File( photoPath ); imageUri = Uri.fromFile( file ); //create new Intent Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra( MediaStore.EXTRA_OUTPUT, imageUri ); intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE); } }; private void checkAutoField(ProjectField att) { if(prefCnt.isAutoFieldEnabled(att.getName().toLowerCase())){ att.setValue(prefCnt.getAutoFieldEnabled(att.getName().toLowerCase())); } } /* * This method sets the default spinner item using defValue parameter provided. * If the spinner doesn't contain the value, spinner is not modified. * */ private int setDefaultSpinnerItem(Spinner e, String defaultValue, String[] items){ int n=items.length; boolean found=false; int pos=-1; int i; for(i=0; i<n && !found;i++){ if (items[i].compareTo(defaultValue)==0){ found=true; pos=i;} } if(found) e.setSelection(pos); return pos; } protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // super.onActivityResult(requestCode, resultCode, intent); switch(requestCode) { case LOAD_REMOTE_TAB : elements = tC.fillData((AutoCompleteTextView) thElem); ((AutoCompleteTextView) thElem).setAdapter(elements); ((AutoCompleteTextView) thElem).setOnItemClickListener(synonimThListener); break; case NEW_PROJECT : SharedPreferences preferences= getSharedPreferences(Main.PREF_FILE_NAME, MODE_PRIVATE); projId = preferences.getLong("predProjectId", -1); projCnt.loadProjectInfoById(projId); tvProjectName.setText(projCnt.getName()); createFieldForm(projId); updateDisplay(); break; case 2 : //back from GPS Activity if(intent!=null){ Bundle ext = intent.getExtras(); lat= ext.getDouble("latitude"); longitude= ext.getDouble("longitude"); elevation= ext.getDouble("elevation"); //it can be 0 and 0 when it's located in the south of nigeria. It has to be improved. if (lat==0 || longitude ==0){ Toast.makeText(getBaseContext(), getBaseContext().getString(R.string.gps_missing), Toast.LENGTH_SHORT).show(); } else{ prefCnt.setGPSNeeded(true); updateDisplay(); } } break; case 4 : //back from GPS Activity if(intent!=null){ Bundle ext = intent.getExtras(); int numSecCitations=ext.getInt("numSecCit"); Long subProjId=ext.getLong("subProjId"); sCLH.updateNumCitations(subProjId.intValue(), numSecCitations); TextView counter=sCLH.getSecLevelCounterByFieldId(subProjId.intValue()); int numSec= sCLH.getSecLevelChildrenByFieldId(subProjId.intValue()); counter.setText(""+numSec); } break; case 5 : //back from GPS Activity if(intent!=null){ Bundle ext = intent.getExtras(); int numSecCitations=ext.getInt("numSecCit"); Long subProjId=ext.getLong("subProjId"); sCLH.setNumCitations(subProjId.intValue(), numSecCitations); TextView counter=sCLH.getSecLevelCounterByFieldId(subProjId.intValue()); int numSec= sCLH.getSecLevelChildrenByFieldId(subProjId.intValue()); counter.setText(""+numSec); } break; case CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE : if (resultCode == RESULT_OK) { if(photoPath==null){ String fileName=prefCnt.getLastPhotoPath(); photoPath=Environment.getExternalStorageDirectory().toString(); photoPath=photoPath + "/zamiaDroid/Photos/"+ fileName; } PhotoFieldForm photoFieldForm=photoFieldsList.get(lastPhotoField); photoFieldForm.addPhoto(photoPath); break; } else if (resultCode == RESULT_CANCELED) { Utilities.showToast("Picture was not taken", this); } else { Utilities.showToast("Picture was not taken", this); } break; case POLYGON_EDIT : if(resultCode != RESULT_CANCELED){ ArrayList<LatLonParcel> pointsExtra = intent.getParcelableArrayListExtra("polygon_path"); if(polygonField!=null) polygonField.updatePath(pointsExtra); } break; default: } } }