/**
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 pl.llp.aircasting.Intents;
import pl.llp.aircasting.R;
import pl.llp.aircasting.event.sensor.ThresholdSetEvent;
import pl.llp.aircasting.helper.SettingsHelper;
import pl.llp.aircasting.model.Sensor;
import pl.llp.aircasting.model.internal.MeasurementLevel;
import android.app.Application;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.common.eventbus.EventBus;
import com.google.inject.Inject;
import roboguice.inject.InjectView;
import static java.lang.String.valueOf;
public class ThresholdsActivity extends DialogActivity implements View.OnClickListener, View.OnFocusChangeListener, SeekBar.OnSeekBarChangeListener
{
@InjectView(R.id.color_scale_very_loud) EditText veryLoudEdit;
@InjectView(R.id.color_scale_too_loud) EditText tooLoudEdit;
@InjectView(R.id.color_scale_average) EditText averageEdit;
@InjectView(R.id.color_scale_quiet) EditText quietEdit;
@InjectView(R.id.color_scale_loud) EditText loudEdit;
@InjectView(R.id.color_scale_very_loud_slider) SeekBar veryLoudSlider;
@InjectView(R.id.color_scale_average_slider) SeekBar averageSlider;
@InjectView(R.id.color_scale_loud_slider) SeekBar loudSlider;
@InjectView(R.id.top_bar_very_high) TextView topBarTooLoud;
@InjectView(R.id.top_bar_very_low) TextView topBarQuiet;
@InjectView(R.id.top_bar_high) TextView topBarVeryLoud;
@InjectView(R.id.top_bar_low) TextView topBarAverage;
@InjectView(R.id.top_bar_mid) TextView topBarLoud;
@InjectView(R.id.reset) Button reset;
@InjectView(R.id.save) Button save;
@Inject SettingsHelper settingsHelper;
@Inject Application context;
@Inject EventBus eventBus;
private int veryLoud;
private int tooLoud;
private int average;
private int loud;
private int quiet;
private Sensor sensor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.color_scale);
sensor = (Sensor) getIntent().getSerializableExtra(Intents.EXTRA_SENSOR);
tooLoudEdit.setText(valueOf(settingsHelper.getThreshold(sensor, MeasurementLevel.VERY_HIGH)));
veryLoudEdit.setText(valueOf(settingsHelper.getThreshold(sensor, MeasurementLevel.HIGH)));
loudEdit.setText(valueOf(settingsHelper.getThreshold(sensor, MeasurementLevel.MID)));
averageEdit.setText(valueOf(settingsHelper.getThreshold(sensor, MeasurementLevel.LOW)));
quietEdit.setText(valueOf(settingsHelper.getThreshold(sensor, MeasurementLevel.VERY_LOW)));
veryLoudEdit.setOnFocusChangeListener(this);
loudEdit.setOnFocusChangeListener(this);
averageEdit.setOnFocusChangeListener(this);
tooLoudEdit.setOnFocusChangeListener(this);
quietEdit.setOnFocusChangeListener(this);
veryLoudSlider.setOnSeekBarChangeListener(this);
loudSlider.setOnSeekBarChangeListener(this);
averageSlider.setOnSeekBarChangeListener(this);
save.setOnClickListener(this);
reset.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.save:
saveThresholds();
break;
case R.id.reset:
finish();
resetThresholds();
break;
}
}
private void resetThresholds()
{
for (MeasurementLevel level : MeasurementLevel.OBTAINABLE_LEVELS)
{
eventBus.post(new ThresholdSetEvent(sensor, level, sensor.getThreshold(level)));
}
settingsHelper.resetThresholds(sensor);
}
void saveThresholds() {
calculateThresholds();
fixThresholds();
eventBus.post(new ThresholdSetEvent(sensor, MeasurementLevel.VERY_HIGH, tooLoud));
eventBus.post(new ThresholdSetEvent(sensor, MeasurementLevel.HIGH, veryLoud));
eventBus.post(new ThresholdSetEvent(sensor, MeasurementLevel.MID, loud));
eventBus.post(new ThresholdSetEvent(sensor, MeasurementLevel.LOW, average));
eventBus.post(new ThresholdSetEvent(sensor, MeasurementLevel.VERY_LOW, quiet));
finish();
}
void fixThresholds() {
View focus = getCurrentFocus();
int id = focus == null ? 0 : focus.getId();
MeasurementLevel measurementLevel = toSoundLevel(id);
fixThresholds(measurementLevel);
}
private void calculateThresholds() {
try {
tooLoud = tooLoudEdit.getText().length() == 0 ? 0 : Integer.parseInt(tooLoudEdit.getText().toString());
veryLoud = veryLoudEdit.getText().length() == 0 ? 0 : Integer.parseInt(veryLoudEdit.getText().toString());
loud = loudEdit.getText().length() == 0 ? 0 : Integer.parseInt(loudEdit.getText().toString());
average = averageEdit.getText().length() == 0 ? 0 : Integer.parseInt(averageEdit.getText().toString());
quiet = quietEdit.getText().length() == 0 ? 0 : Integer.parseInt(quietEdit.getText().toString());
} catch (NumberFormatException e) {
updateEdits();
Toast.makeText(context, R.string.setting_error, Toast.LENGTH_LONG).show();
}
}
private void updateEdits() {
tooLoudEdit.setText(valueOf(tooLoud));
veryLoudEdit.setText(valueOf(veryLoud));
loudEdit.setText(valueOf(loud));
averageEdit.setText(valueOf(average));
quietEdit.setText(valueOf(quiet));
}
private MeasurementLevel toSoundLevel(int id) {
switch (id) {
case R.id.color_scale_quiet:
return MeasurementLevel.VERY_LOW;
case R.id.color_scale_average:
case R.id.color_scale_average_slider:
return MeasurementLevel.LOW;
case R.id.color_scale_loud:
case R.id.color_scale_loud_slider:
return MeasurementLevel.MID;
case R.id.color_scale_very_loud:
case R.id.color_scale_very_loud_slider:
return MeasurementLevel.HIGH;
default:
return MeasurementLevel.VERY_HIGH;
}
}
private void fixThresholds(MeasurementLevel fixed) {
switch (fixed) {
case VERY_LOW:
if (average <= quiet) average = quiet + 1;
case LOW:
if (loud <= average) loud = average + 1;
case MID:
if (veryLoud <= loud) veryLoud = loud + 1;
case HIGH:
if (tooLoud <= veryLoud) tooLoud = veryLoud + 1;
}
switch (fixed) {
case VERY_HIGH:
if (veryLoud >= tooLoud) veryLoud = tooLoud - 1;
case HIGH:
if (loud >= veryLoud) loud = veryLoud - 1;
case MID:
if (average >= loud) average = loud - 1;
case LOW:
if (quiet >= average) quiet = average - 1;
}
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
calculateThresholds();
fixThresholds(toSoundLevel(view.getId()));
updateViews();
}
private void updateViews() {
updateSliders();
updateEdits();
updateTopBar();
}
private void updateTopBar() {
topBarQuiet.setText(valueOf(quiet));
topBarAverage.setText(valueOf(average));
topBarLoud.setText(valueOf(loud));
topBarVeryLoud.setText(valueOf(veryLoud));
topBarTooLoud.setText(valueOf(tooLoud));
}
private void updateSliders() {
veryLoudSlider.setProgress((int) (veryLoudSlider.getMax() * project(veryLoud)));
loudSlider.setProgress((int) (loudSlider.getMax() * project(loud)));
averageSlider.setProgress((int) (averageSlider.getMax() * project(average)));
}
private double project(double value) {
return (value - quiet) / (tooLoud - quiet);
}
@Override
public void onProgressChanged(SeekBar bar, int i, boolean b) {
int value = unProject(bar.getProgress(), bar.getMax());
MeasurementLevel measurementLevel = toSoundLevel(bar.getId());
switch (measurementLevel) {
case LOW:
averageEdit.setText(valueOf(value));
break;
case MID:
loudEdit.setText(valueOf(value));
break;
case HIGH:
veryLoudEdit.setText(valueOf(value));
break;
}
}
private int unProject(int progress, int max) {
return (int) (quiet + progress / (double) max * (tooLoud - quiet));
}
@Override
public void onStartTrackingTouch(SeekBar bar) {
bar.requestFocus();
}
@Override
public void onStopTrackingTouch(SeekBar bar) {
calculateThresholds();
MeasurementLevel measurementLevel = toSoundLevel(bar.getId());
fixThresholds(measurementLevel);
updateViews();
}
}