diff --git a/app/src/main/java/com/mooshim/mooshimeter/main/ScanActivity.java b/app/src/main/java/com/mooshim/mooshimeter/main/ScanActivity.java index 8684de7..fba895e 100644 --- a/app/src/main/java/com/mooshim/mooshimeter/main/ScanActivity.java +++ b/app/src/main/java/com/mooshim/mooshimeter/main/ScanActivity.java @@ -23,7 +23,6 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; @@ -37,10 +36,8 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.widget.AdapterView; -import android.widget.BaseAdapter; import android.widget.Button; -import android.widget.ListView; +import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -70,22 +67,24 @@ public class ScanActivity extends FragmentActivity { private static final List mMeterList = new ArrayList(); private static final Map mMeterDict = new HashMap(); + private static final List mTileList = new ArrayList(); // Housekeeping private static final Lock utilLock = new ReentrantLock(); private static final Condition scanThreadCondition = utilLock.newCondition(); // GUI Widgets - private DeviceListAdapter mDeviceAdapter = null; private TextView mEmptyMsg; private TextView mStatus; private Button mBtnScan = null; - private ListView mDeviceListView = null; + private LinearLayout mDeviceScrollView = null; // Flags for the scan logic thread private static boolean mScanOngoing = false; private static MooshimeterDevice mConnectionRequester = null; + private LayoutInflater mInflater; + @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); @@ -112,31 +111,16 @@ public void onCreate(Bundle savedInstanceState) { setContentView(R.layout.fragment_scan); // Initialize widgets - mStatus = (TextView) findViewById(R.id.status); - mBtnScan = (Button) findViewById(R.id.btn_scan); - mDeviceListView = (ListView) findViewById(R.id.device_list); - mEmptyMsg = (TextView) findViewById(R.id.no_device); + mStatus = (TextView) findViewById(R.id.status); + mBtnScan = (Button) findViewById(R.id.btn_scan); + mDeviceScrollView = (LinearLayout) findViewById(R.id.device_list); + mEmptyMsg = (TextView) findViewById(R.id.no_device); - mDeviceListView.setClickable(true); - mDeviceListView.setOnItemClickListener(mDeviceClickListener); + mDeviceScrollView.setClickable(true); - mDeviceAdapter = new DeviceListAdapter(this); - mDeviceListView.setAdapter(mDeviceAdapter); + mInflater = LayoutInflater.from(this); } - private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View view, int pos, long id) { - final MooshimeterDevice m = mMeterList.get(pos); - if( m.mConnectionState == BluetoothProfile.STATE_CONNECTED - || m.mConnectionState == BluetoothProfile.STATE_CONNECTING ) { - startSingleMeterActivity(m); - } else { - final Button bv = (Button)view.findViewById(R.id.btnConnect); - toggleConnectionState(bv,m); - } - } - }; - @Override public void onResume() { super.onResume(); @@ -214,7 +198,7 @@ void updateScanningButton(boolean scanning) { mBtnScan.setText("Scan"); mBtnScan.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_refresh, 0); mEmptyMsg.setText(R.string.scan_advice); - mDeviceAdapter.notifyDataSetChanged(); + refreshAllMeterTiles(); } if(mMeterDict.size() == 0) { mEmptyMsg.setVisibility(View.VISIBLE); @@ -246,19 +230,125 @@ public void run() { }); } - private void addDevice(MooshimeterDevice d) { + private void addDevice(final MooshimeterDevice d) { mEmptyMsg.setVisibility(View.GONE); + if(mMeterList.contains(d)) { + // The meter as already been added + Log.e(TAG, "Tried to add the same meter twice"); + return; + } + mMeterList.add(d); mMeterDict.put(d.getAddress(), d); - mDeviceAdapter.notifyDataSetChanged(); + final LinearLayout wrapper = new LinearLayout(this); + wrapper.setOrientation(LinearLayout.VERTICAL); + wrapper.setLayoutParams(mDeviceScrollView.getLayoutParams()); + + wrapper.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if( d.mConnectionState == BluetoothProfile.STATE_CONNECTED + || d.mConnectionState == BluetoothProfile.STATE_CONNECTING ) { + startSingleMeterActivity(d); + } else { + final Button bv = (Button)view.findViewById(R.id.btnConnect); + toggleConnectionState(bv,d); + } + } + }); + + wrapper.addView(mInflater.inflate(R.layout.element_mm_titlebar, wrapper, false)); + //wrapper.setTag(Integer.valueOf(R.layout.element_mm_titlebar)); + + refreshMeterTile(d, wrapper); + mDeviceScrollView.addView(wrapper); + mTileList.add(wrapper); + if (mMeterList.size() > 1) setStatus(mMeterList.size() + " devices"); else setStatus("1 device"); } + private void refreshMeterTile(final MooshimeterDevice d, final ViewGroup wrapper) { + if(wrapper.getChildCount()==0) { + Log.e(TAG,"Received empty wrapper"); + } + if(wrapper.getChildCount()>0) { + // Update the title bar + int rssi = d.mRssi; + String name; + String build; + if(d.mOADMode) { + name = "Bootloader"; + } else { + name = d.getBLEDevice().getName(); + if (name == null) { + name = new String("Unknown device"); + } + } + + if(d.mBuildTime == 0) { + build = "Invalid firmware"; + } else { + build = "Build: "+d.mBuildTime; + } + + String descr = name + "\n" + build + "\nRssi: " + rssi + " dBm"; + ((TextView) wrapper.findViewById(R.id.descr)).setText(descr); + + final Button bv = (Button)wrapper.findViewById(R.id.btnConnect); + + int bgid = d.mConnectionState==BluetoothProfile.STATE_CONNECTED ? R.drawable.connected:R.drawable.disconnected; + bv.setBackground(getResources().getDrawable(bgid)); + + // Set the click listeners + bv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + toggleConnectionState(bv,d); + } + }); + } + if(d.mInitialized && !d.isInOADMode()) { + // We are representing a connected meter + if(wrapper.getChildCount() != 2) { + // We need to create a new value pane + wrapper.addView(mInflater.inflate(R.layout.element_mm_readingsbar, mDeviceScrollView, false)); + } + if(!d.isNotificationEnabled(d.getChar(MooshimeterDevice.mUUID.METER_SAMPLE))) { + // We need to enable notifications + d.playSampleStream(new Runnable() { + @Override + public void run() { + TextView ch1 = (TextView)wrapper.findViewById(R.id.ch1_value_label); + TextView ch2 = (TextView)wrapper.findViewById(R.id.ch2_value_label); + TextView ch1_unit = (TextView)wrapper.findViewById(R.id.ch1_unit_label); + TextView ch2_unit = (TextView)wrapper.findViewById(R.id.ch2_unit_label); + valueLabelRefresh(0,d, ch1, ch1_unit); + valueLabelRefresh(1,d, ch2, ch2_unit); + } + }); + } + } else { + //We are representing a disconnected meter or a meter in OAD mode + if(wrapper.getChildCount() == 2) { + // We need to eliminate a pane + wrapper.removeViewAt(1); + } + } + } + + private void refreshAllMeterTiles() { + for(int i = 0; i < mDeviceScrollView.getChildCount(); i++) { + final ViewGroup vg = mTileList.get(i); + final MooshimeterDevice d = mMeterList.get(i); + refreshMeterTile(d,vg); + } + } + ///////////////////////////// // Data Structure Manipulation ///////////////////////////// @@ -386,7 +476,7 @@ else if(field_id == 0) { m.mRssi = rssi; m.mOADMode = oad_mode; m.mBuildTime = build_time; - mDeviceAdapter.notifyDataSetChanged(); + refreshAllMeterTiles(); } } }); @@ -412,10 +502,12 @@ public synchronized void startScan() { } } for(MooshimeterDevice m : remove) { + mDeviceScrollView.removeView(mTileList.remove(mMeterList.indexOf(m))); mMeterList.remove(m); mMeterDict.remove(m.getAddress()); } - mDeviceAdapter.notifyDataSetChanged(); + refreshAllMeterTiles(); + final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if( !bluetoothAdapter.startLeScan(mLeScanCallback) ) { // Starting the scan failed! @@ -516,114 +608,4 @@ public void run() { } }); } - - class DeviceListAdapter extends BaseAdapter { - private LayoutInflater mInflater; - private Map mViews; - - public DeviceListAdapter(Context context) { - mInflater = LayoutInflater.from(context); - mViews = new HashMap(); - } - - public int getCount() { - return mMeterDict.size(); - } - - public Object getItem(int position) { - return mMeterList.get(position); - } - - public long getItemId(int position) { - return position; - } - - @Override - public int getViewTypeCount() { - return 2; // Count of different layouts - } - - @Override - public int getItemViewType(int position) { - final MooshimeterDevice m = mMeterList.get(position); - if(m.mInitialized && !m.isInOADMode()) { - return 1; - } else { - return 0; - } - } - - public View getView(final int position, View convertView, ViewGroup parent) { - final ViewGroup vg; - - final MooshimeterDevice m = mMeterList.get(position); - - //final int desired_view_id = getItemViewType(position)==1?R.layout.element_mm_full:R.layout.element_mm_titlebar; - - if(m.mInitialized && !m.isInOADMode()) { - vg = (ViewGroup) mInflater.inflate(R.layout.element_mm_full, parent, false); - vg.setTag(Integer.valueOf(R.layout.element_mm_full)); - View tmp = mViews.get(position); - if(tmp != null) { - // Copy the text over from the last incarnation - ((TextView)vg.findViewById(R.id.ch1_value_label)).setText(((TextView)mViews.get(position).findViewById(R.id.ch1_value_label)).getText()); - ((TextView)vg.findViewById(R.id.ch2_value_label)).setText(((TextView)mViews.get(position).findViewById(R.id.ch2_value_label)).getText()); - ((TextView)vg.findViewById(R.id.ch1_unit_label)).setText(((TextView)mViews.get(position).findViewById(R.id.ch1_unit_label)).getText()); - ((TextView)vg.findViewById(R.id.ch2_unit_label)).setText(((TextView)mViews.get(position).findViewById(R.id.ch2_unit_label)).getText()); - } - mViews.put(position,vg); - if(!m.isNotificationEnabled(m.getChar(MooshimeterDevice.mUUID.METER_SAMPLE))) { - m.playSampleStream(new Runnable() { - @Override - public void run() { - TextView ch1 = (TextView)mViews.get(position).findViewById(R.id.ch1_value_label); - TextView ch2 = (TextView)mViews.get(position).findViewById(R.id.ch2_value_label); - TextView ch1_unit = (TextView)mViews.get(position).findViewById(R.id.ch1_unit_label); - TextView ch2_unit = (TextView)mViews.get(position).findViewById(R.id.ch2_unit_label); - valueLabelRefresh(0,m, ch1, ch1_unit); - valueLabelRefresh(1,m, ch2, ch2_unit); - } - }); - } - } else { - vg = (ViewGroup) mInflater.inflate(R.layout.element_mm_titlebar, parent, false); - vg.setTag(Integer.valueOf(R.layout.element_mm_titlebar)); - } - - int rssi = m.mRssi; - String name; - String build; - if(m.mOADMode) { - name = "Bootloader"; - } else { - name = m.getBLEDevice().getName(); - if (name == null) { - name = new String("Unknown device"); - } - } - - if(m.mBuildTime == 0) { - build = "Invalid firmware"; - } else { - build = "Build: "+m.mBuildTime; - } - - String descr = name + "\n" + build + "\nRssi: " + rssi + " dBm"; - ((TextView) vg.findViewById(R.id.descr)).setText(descr); - - final Button bv = (Button)vg.findViewById(R.id.btnConnect); - - int bgid = m.mConnectionState==BluetoothProfile.STATE_CONNECTED ? R.drawable.connected:R.drawable.disconnected; - bv.setBackground(getResources().getDrawable(bgid)); - - // Set the click listeners - bv.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - toggleConnectionState(bv,m); - } - }); - return vg; - } - } } diff --git a/app/src/main/res/layout/element_mm_full.xml b/app/src/main/res/layout/element_mm_full.xml deleted file mode 100644 index 76fa679..0000000 --- a/app/src/main/res/layout/element_mm_full.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/element_mm_readingsbar.xml b/app/src/main/res/layout/element_mm_readingsbar.xml index 432f9ef..929bc9c 100644 --- a/app/src/main/res/layout/element_mm_readingsbar.xml +++ b/app/src/main/res/layout/element_mm_readingsbar.xml @@ -51,7 +51,7 @@ android:layout_height="wrap_content" android:layout_gravity="left|center_vertical" android:textAppearance="?android:attr/textAppearanceLarge" - android:text="OVERLOAD" + android:text="UNITS" android:id="@+id/ch1_unit_label" android:textSize="24dp" android:layout_weight="2.36" @@ -86,7 +86,7 @@ android:layout_height="wrap_content" android:layout_gravity="left|center_vertical" android:textAppearance="?android:attr/textAppearanceLarge" - android:text="OVERLOAD" + android:text="UNITS" android:id="@+id/ch2_unit_label" android:textSize="24dp" android:layout_weight="2.36" diff --git a/app/src/main/res/layout/fragment_scan.xml b/app/src/main/res/layout/fragment_scan.xml index aa329c7..9c7def7 100644 --- a/app/src/main/res/layout/fragment_scan.xml +++ b/app/src/main/res/layout/fragment_scan.xml @@ -10,18 +10,28 @@ android:padding="0dp" tools:context=".MainActivity" > - + android:layout_marginLeft="0dp" > + + + +