package pl.llp.aircasting.activity.adapter; import android.util.Log; import android.widget.AbsListView; import android.widget.RelativeLayout; import com.google.common.collect.ComparisonChain; import pl.llp.aircasting.Intents; import pl.llp.aircasting.R; import pl.llp.aircasting.activity.ButtonsActivity; import pl.llp.aircasting.event.ui.ViewStreamEvent; import pl.llp.aircasting.helper.GaugeHelper; import pl.llp.aircasting.helper.NoOp; import pl.llp.aircasting.helper.StreamViewHelper; import pl.llp.aircasting.helper.TopBarHelper; import pl.llp.aircasting.model.Sensor; import pl.llp.aircasting.model.SensorManager; import pl.llp.aircasting.model.SessionManager; import pl.llp.aircasting.model.events.SensorEvent; import android.app.AlertDialog; import android.content.DialogInterface; import android.view.View; import android.view.ViewGroup; import android.widget.SimpleAdapter; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import org.jetbrains.annotations.Nullable; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.common.collect.Maps.newHashMap; import static java.util.Collections.sort; public class StreamAdapter extends SimpleAdapter implements View.OnClickListener { public static final String QUANTITY = "quantity"; public static final String SENSOR_NAME = "sensorName"; public static final String SENSOR = "sensor"; private static final String[] FROM = new String[]{ QUANTITY, SENSOR_NAME }; private static final int[] TO = new int[]{ R.id.quantity, R.id.sensor_name }; private final Comparator<Map<String, Object>> titleComparator = new Comparator<Map<String, Object>>() { @Override public int compare(@Nullable Map<String, Object> left, @Nullable Map<String, Object> right) { String rightTitle = right.get(QUANTITY).toString(); String leftTitle = left.get(QUANTITY).toString(); Sensor leftSensor = (Sensor) left.get(SENSOR); Sensor rightSensor = (Sensor) right.get(SENSOR); return ComparisonChain.start() .compare(leftSensor.isEnabled() ? 0 : 1, rightSensor.isEnabled() ? 0 : 1) .compare(getPosition(left), getPosition(right)) .compare(leftTitle, rightTitle).result(); } }; SessionManager sessionManager; SensorManager sensorManager; StreamViewHelper streamViewHelper; ButtonsActivity context; EventBus eventBus; private List<Map<String, Object>> data; private Map<String, Map<String, Object>> sensors = newHashMap(); // these are static to retain after activity recreation private static Map<String, Integer> positions = newHashMap(); private static boolean firstStatsVisible = false; private static Map<String, Boolean> statsVisibility = newHashMap(); private static int lastStreamsNumber = -1; private Map<String, Integer> oldPositions = newHashMap(); private int invisiblePosition = -1; public StreamAdapter(ButtonsActivity context, List<Map<String, Object>> data, EventBus eventBus, StreamViewHelper streamViewHelper, SensorManager sensorManager, SessionManager sessionManager) { super(context, data, R.layout.stream, FROM, TO); this.data = data; this.eventBus = eventBus; this.context = context; this.sensorManager = sensorManager; this.sessionManager = sessionManager; this.streamViewHelper = streamViewHelper; } /** * Start updating the adapter */ public void start() { eventBus.register(this); } /** * Stop updating the adapter */ public void stop() { eventBus.unregister(this); } @Subscribe public void onEvent(SensorEvent event) { context.runOnUiThread(new Runnable() { @Override public void run() { update(); } }); } public void startReorder() { for (Map<String, Object> stream : data) { Sensor s = (Sensor) stream.get(SENSOR); oldPositions.put(s.toString(), getPosition(stream)); } } public void cancelReorder() { for (Map<String, Object> stream : data) { Sensor s = (Sensor) stream.get(SENSOR); positions.put(s.toString(), getPosition(stream, oldPositions)); } update(); } public void commitReorder() { oldPositions = newHashMap(); } public void swapPositions(int pos1, int pos2) { Sensor s1 = (Sensor) data.get(pos1).get(SENSOR); Sensor s2 = (Sensor) data.get(pos2).get(SENSOR); positions.put(s1.toString(), pos2); positions.put(s2.toString(), pos1); update(); } private int getPosition(Map<String, Object> stream, Map<String, Integer> positions) { Sensor sensor = (Sensor) stream.get(SENSOR); Integer position = positions.get(sensor.toString()); if (position == null) { return 0; } return position.intValue(); } private int getPosition(Map<String, Object> stream) { return getPosition(stream, positions); } public void toggleStatsVisibility(Sensor sensor) { Boolean currentVisibility = statsVisibility.get(sensor.toString()); if (currentVisibility == null) { currentVisibility = false; } statsVisibility.put(sensor.toString(), !currentVisibility && !firstStatsVisible); firstStatsVisible = false; update(); } public void setInvisiblePosition(int position) { invisiblePosition = position; update(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); Map<String, Object> state = data.get(position); Sensor sensor = (Sensor) state.get(SENSOR); Boolean statsVisible = statsVisibility.get(sensor.toString()); if (statsVisible == null) statsVisible = false; streamViewHelper.updateMeasurements(sensor, view, firstStatsVisible || statsVisible); initializeButtons(view, sensor); view.setOnClickListener(this); view.setClickable(true); view.setFocusable(true); view.setTag(sensor); if (position == invisiblePosition) { view.setVisibility(View.INVISIBLE); } else { view.setVisibility(View.VISIBLE); } return view; } private void initializeButtons(View view, Sensor sensor) { View deleteButton = view.findViewById(R.id.delete_stream); deleteButton.setTag(sensor); deleteButton.setOnClickListener(this); if (sensorManager.isSessionBeingRecorded()) { deleteButton.setVisibility(View.GONE); } else if (sensorManager.isSessionBeingViewed()) { deleteButton.setVisibility(View.VISIBLE); } else { deleteButton.setVisibility(View.GONE); } } private void update() { data.clear(); List<Sensor> sensors = sensorManager.getSensors(); for (Sensor sensor : sensors) { Map<String, Object> map = prepareItem(sensor); map.put(QUANTITY, sensor.getMeasurementType() + " - " + sensor.getSymbol()); map.put(SENSOR_NAME, sensor.getSensorName()); map.put(SENSOR, sensor); data.add(map); } sort(data, titleComparator); int currentPosition = 0; for (Map<String, Object> map : data) { Sensor sensor = (Sensor) map.get(SENSOR); positions.put(sensor.toString(), Integer.valueOf(currentPosition)); currentPosition++; } if (data.size() == 1 && lastStreamsNumber != 1) { firstStatsVisible = true; } else if (data.size() > 1) { firstStatsVisible = false; } lastStreamsNumber = data.size(); notifyDataSetChanged(); } private Map<String, Object> prepareItem(Sensor sensor) { String name = sensor.getSensorName(); if (!sensors.containsKey(name)) { HashMap<String, Object> map = new HashMap<String, Object>(); sensors.put(name, map); } return sensors.get(name); } @Override public void onClick(View view) { Sensor sensor = (Sensor) view.getTag(); switch (view.getId()) { case R.id.delete_stream: deleteStream(context, sensor); break; } context.suppressNextTap(); notifyDataSetChanged(); } private void deleteStream(ButtonsActivity context, Sensor sensor) { if (sessionManager.getSession().getActiveMeasurementStreams().size() > 1) { confirmDeletingStream(context, sensor); } else { confirmDeletingSession(context); } } private void confirmDeletingSession(final ButtonsActivity context) { AlertDialog.Builder b = new AlertDialog.Builder(context); b.setMessage("This is the only stream, delete session?"). setCancelable(true). setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { sessionManager.deleteSession(); Intents.triggerSync(context); Intents.sessions(context, context); } }).setNegativeButton("No", NoOp.dialogOnClick()); AlertDialog dialog = b.create(); dialog.show(); } private void confirmDeletingStream(final ButtonsActivity context, final Sensor sensor) { AlertDialog.Builder b = new AlertDialog.Builder(context); b.setMessage("Delete stream?"). setCancelable(true). setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { sensorManager.deleteSensorFromCurrentSession(sensor); update(); Intents.triggerSync(context); } }).setNegativeButton("No", NoOp.dialogOnClick()); AlertDialog dialog = b.create(); dialog.show(); } }