/** AirCasting - Share your Air! Copyright (C) 2011-2012 HabitatMap, Inc. This program 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. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. You can contact the authors by email at <info@habitatmap.org> */ package pl.llp.aircasting.activity; import android.net.Uri; import pl.llp.aircasting.Intents; import pl.llp.aircasting.R; import pl.llp.aircasting.activity.events.SessionChangeEvent; import pl.llp.aircasting.activity.task.SimpleProgressTask; import pl.llp.aircasting.android.Logger; import pl.llp.aircasting.event.sensor.AudioReaderErrorEvent; import pl.llp.aircasting.event.sensor.ThresholdSetEvent; import pl.llp.aircasting.event.ui.StreamUpdateEvent; import pl.llp.aircasting.event.ui.ViewStreamEvent; import pl.llp.aircasting.helper.FormatHelper; import pl.llp.aircasting.helper.GaugeHelper; import pl.llp.aircasting.helper.PhotoHelper; import pl.llp.aircasting.helper.ResourceHelper; import pl.llp.aircasting.helper.SelectSensorHelper; import pl.llp.aircasting.helper.TopBarHelper; import pl.llp.aircasting.model.Note; import pl.llp.aircasting.model.Sensor; import pl.llp.aircasting.model.SensorManager; import pl.llp.aircasting.model.Session; import pl.llp.aircasting.model.events.MeasurementEvent; import pl.llp.aircasting.model.events.SensorEvent; import pl.llp.aircasting.storage.UnfinishedSessionChecker; import android.app.Dialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; import android.widget.Toast; import com.google.common.eventbus.Subscribe; import com.google.inject.Inject; import roboguice.inject.InjectView; import java.io.File; import java.text.NumberFormat; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static pl.llp.aircasting.Intents.triggerSync; public abstract class AirCastingActivity extends ButtonsActivity implements View.OnClickListener { public static final String NOTE_INDEX = "noteIndex"; @InjectView(R.id.gauge_container) View gauges; @InjectView(R.id.note_right) ImageButton noteRight; @InjectView(R.id.note_number) TextView noteNumber; @InjectView(R.id.note_left) ImageButton noteLeft; @InjectView(R.id.note_delete) Button noteDelete; @InjectView(R.id.note_viewer) View noteViewer; @InjectView(R.id.note_date) TextView noteDate; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.note_save) Button noteSave; @InjectView(R.id.view_photo) View viewPhoto; @InjectView(R.id.top_bar) View topBar; @Inject SelectSensorHelper selectSensorHelper; @Inject ResourceHelper resourceHelper; @Inject SensorManager sensorManager; @Inject TopBarHelper topBarHelper; @Inject PhotoHelper photoHelper; @Inject GaugeHelper gaugeHelper; NumberFormat numberFormat = NumberFormat.getInstance(); private boolean initialized = false; int noteIndex = -1; Note currentNote; int noteTotal; final AtomicBoolean noUpdateInProgress = new AtomicBoolean(true); @Override protected void onResume() { super.onResume(); initialize(); initializeNoteViewer(); updateGauges(); updateKeepScreenOn(); topBarHelper.updateTopBar(sensorManager.getVisibleSensor(), topBar); Intents.startIOIO(context); Intents.startDatabaseWriterService(context); } private void initialize() { if (!initialized) { zoomOut.setOnClickListener(this); zoomIn.setOnClickListener(this); topBar.setOnClickListener(this); noteDelete.setOnClickListener(this); noteRight.setOnClickListener(this); viewPhoto.setOnClickListener(this); noteLeft.setOnClickListener(this); noteSave.setOnClickListener(this); gauges.setOnClickListener(this); initialized = true; } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(NOTE_INDEX, noteIndex); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); noteIndex = savedInstanceState.getInt(NOTE_INDEX, -1); } private void updateKeepScreenOn() { if (settingsHelper.isKeepScreenOn()) { getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } else { getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } protected void updateGauges() { final Sensor visibleSensor = sensorManager.getVisibleSensor(); updateGaugeFaces(visibleSensor); } private void updateGaugeFaces(final Sensor visibleSensor) { if(noUpdateInProgress.get()) { noUpdateInProgress.set(false); runOnUiThread(new Runnable() { @Override public void run() { gaugeHelper.updateGauges(visibleSensor, gauges); noUpdateInProgress.set(true); } }); } } @Subscribe public void onEvent(MeasurementEvent event) { updateGauges(); } @Subscribe public void onEvent(SessionChangeEvent event) { updateGauges(); } @Subscribe public void onEvent(SensorEvent event) { updateGauges(); } @Subscribe public void onEvent(ThresholdSetEvent event) { updateGauges(); } @Subscribe public void onEvent(AudioReaderErrorEvent event) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.mic_error, Toast.LENGTH_LONG).show(); } }); } @Subscribe public void onEvent(StreamUpdateEvent event) { topBarHelper.updateTopBar(event.getSensor(), topBar); updateGauges(); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.top_bar: Intents.thresholdsEditor(this, sensorManager.getVisibleSensor()); break; case R.id.note_save: saveNote(); break; case R.id.note_delete: deleteNote(); break; case R.id.note_left: noteClicked(noteIndex - 1); break; case R.id.note_right: noteClicked(noteIndex + 1); break; case R.id.gauge_container: showDialog(SelectSensorHelper.DIALOG_ID); break; case R.id.view_photo: Intents.viewPhoto(this, photoUri()); break; default: super.onClick(view); break; } } @Override protected Dialog onCreateDialog(int id) { switch(id){ case SelectSensorHelper.DIALOG_ID: return selectSensorHelper.chooseSensor(this); default: return super.onCreateDialog(id); } } public void noteClicked(int index) { int total = sessionManager.getNoteCount(); if (total == 0) return; index = ((index % total) + total) % total; currentNote = sessionManager.getNote(index); showNoteViewer(); String title = FormatHelper.dateTime(currentNote.getDate()).toString(); noteDate.setText(title); noteText.setText(currentNote.getText()); noteNumber.setText(numberFormat.format(index + 1) + "/" + numberFormat.format(total)); viewPhoto.setVisibility(photoHelper.photoExists(currentNote) ? View.VISIBLE : View.GONE); noteIndex = index; noteTotal = total; } private void showNoteViewer() { noteViewer.setVisibility(View.VISIBLE); } protected void initializeNoteViewer() { if (noteIndex == -1) { hideNoteViewer(); } else { noteClicked(noteIndex); } } protected void hideNoteViewer() { noteViewer.setVisibility(View.INVISIBLE); } @Override public void onBackPressed() { if (noteViewer.getVisibility() == View.VISIBLE) { hideNoteViewer(); } else { super.onBackPressed(); } } private void saveNote() { String text = noteText.getText().toString(); currentNote.setText(text); //noinspection unchecked new SimpleProgressTask<Void, Void, Void>(this) { @Override protected Void doInBackground(Void... voids) { if (sessionManager.isSessionSaved()) { sessionManager.updateNote(currentNote); triggerSync(context); } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); hideNoteViewer(); } }.execute(); } private void deleteNote() { //noinspection unchecked new SimpleProgressTask<Void, Void, Void>(this) { @Override protected Void doInBackground(Void... voids) { sessionManager.deleteNote(currentNote); triggerSync(context); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); refreshNotes(); hideNoteViewer(); } }.execute(); } private Uri photoUri() { if (photoHelper.photoExistsLocally(currentNote)) { File file = new File(currentNote.getPhotoPath()); return Uri.fromFile(file); } else { return Uri.parse(currentNote.getPhotoPath()); } } protected abstract void refreshNotes(); }