/** * Copyright (C) 2013 - 2015 the enviroCar community * * This file is part of the enviroCar app. * * The enviroCar app 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. * * The enviroCar app 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 the enviroCar app. If not, see http://www.gnu.org/licenses/. */ package org.envirocar.app.view.obdselection; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.support.v7.widget.AppCompatRadioButton; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; import org.envirocar.app.R; import butterknife.ButterKnife; import butterknife.InjectView; /** * @author dewall */ public class OBDDeviceListAdapter extends ArrayAdapter<BluetoothDevice> { /** * callback interface for the selection callback. */ protected interface OnOBDListActionCallback { /** * Called when a device has been selected as OBD device. * * @param device the selected bluetooth device. */ void onOBDDeviceSelected(BluetoothDevice device); /** * Called when a device should be deleted. * * @param device the device to delete. */ void onDeleteOBDDevice(BluetoothDevice device); } private final boolean mIsPairedList; private final OnOBDListActionCallback mCallback; private BluetoothDevice mSelectedBluetoothDevice; private AppCompatRadioButton mSelectedRadioButton; /** * Constructor. * * @param context the context of the current scope. * @param pairedList is this a list showing the paired elements? */ public OBDDeviceListAdapter(Context context, boolean pairedList) { super(context, -1); mIsPairedList = pairedList; mCallback = null; } /** * Constructor. * * @param context The context of the current scope. * @param pairedList */ public OBDDeviceListAdapter(Context context, boolean pairedList, OnOBDListActionCallback callback) { super(context, -1); mIsPairedList = pairedList; mCallback = callback; } /** * Constructor. * * @param context The context of the current scope. * @param pairedList true if this should show a radio button. * @param defaultDevice The selected */ public OBDDeviceListAdapter(Context context, boolean pairedList, OnOBDListActionCallback callback, BluetoothDevice defaultDevice) { this(context, pairedList, callback); mSelectedBluetoothDevice = defaultDevice; } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get the item from the given poosition final BluetoothDevice device = getItem(position); ViewHolder holder; // Check if an existing view is being reused, otherwise inflate the view if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout .activity_obd_selection_layout_paired_list_entry, parent, false); holder = new ViewHolder(convertView); // if this list is used for a paired list then we show an addition radio button for // the selection if (mIsPairedList) { holder.mRadioButton.setVisibility(View.VISIBLE); holder.mDeleteButton.setVisibility(View.VISIBLE); } convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.mTextView.setText(device.getName()); holder.mRadioButton.setChecked(false); // If there exists an already selected bluetooth device and the device of this entry // matches the selected device, then set it to checked. if (mSelectedBluetoothDevice != null) { if (mSelectedBluetoothDevice.getName().equals(device.getName())) { mSelectedRadioButton = holder.mRadioButton; mSelectedRadioButton.setChecked(true); mSelectedBluetoothDevice = device; } } holder.mDeleteButton.setOnClickListener(v -> mCallback.onDeleteOBDDevice(device)); // Set the radiobutton on click listener. holder.mRadioButton.setOnClickListener(v -> { // When the clicked radio button corresponds to the bluetooth device that is // already selected, then do nothing. if (mSelectedBluetoothDevice != null && mSelectedBluetoothDevice.getAddress() .equals(device.getAddress())) return; if (mSelectedRadioButton != null) { mSelectedRadioButton.setChecked(false); // Bug. This needs to happen.. dont know why exactly. notifyDataSetInvalidated(); } mSelectedRadioButton = holder.mRadioButton; mSelectedRadioButton.setChecked(true); mSelectedBluetoothDevice = device; // Callback. mCallback.onOBDDeviceSelected(device); }); return convertView; } @Override public BluetoothDevice getItem(int position) { return super.getItem(position); } /** * Updates the selected Bluetooth device and checks the new one. * * @param device the selected Bluetooth device to check. */ public void setSelectedBluetoothDevice(BluetoothDevice device) { // If this is not a list of paired devices or the input device is null, then return. if(device == null || !mIsPairedList) return; // If there is any other bluetooth device selected, then uncheck it first... if(mSelectedRadioButton != null){ mSelectedRadioButton.setChecked(false); mSelectedRadioButton = null; mSelectedBluetoothDevice = null; } // and set the new bluetooth device. mSelectedBluetoothDevice = device; notifyDataSetInvalidated(); } /** * Checks if a given device is already in this adapter. * * @param device the device to check if it is in the adapter. * @return true if the device is in this adapter. */ public boolean contains(BluetoothDevice device) { for (int i = 0, size = getCount(); i != size; i++) { if (getItem(i).equals(device)) return true; } return false; } /** * View holder class holding all views of a single row of the adapter. */ static class ViewHolder { public final View mContentView; // All the views of a row to lookup for. @InjectView(R.id.activity_obd_selection_layout_paired_list_entry_image) protected ImageView mImageView; @InjectView(R.id.activity_obd_selection_layout_paired_list_entry_text) protected TextView mTextView; @InjectView(R.id.activity_obd_selection_layout_paired_list_entry_delete) protected ImageButton mDeleteButton; @InjectView(R.id.activity_obd_selection_layout_paired_list_entry_radio) protected AppCompatRadioButton mRadioButton; /** * Constructor. * * @param content the parent view of the listrow. */ ViewHolder(View content) { this.mContentView = content; // Inject the annotated views. ButterKnife.inject(this, content); } } }