1 /* 2 * Copyright (C) 2014 Samsung System LSI 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.android.bluetooth.map; 17 18 import android.app.Activity; 19 import android.content.ContentResolver; 20 import android.content.ContentValues; 21 import android.net.Uri; 22 import android.os.Handler; 23 import android.util.Log; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.BaseExpandableListAdapter; 28 import android.widget.CheckBox; 29 import android.widget.CompoundButton; 30 import android.widget.CompoundButton.OnCheckedChangeListener; 31 import android.widget.ExpandableListView; 32 import android.widget.ExpandableListView.OnGroupExpandListener; 33 import android.widget.ImageView; 34 import android.widget.TextView; 35 import android.widget.Toast; 36 37 import com.android.bluetooth.R; 38 import com.android.bluetooth.mapapi.BluetoothMapContract; 39 40 import java.util.ArrayList; 41 import java.util.LinkedHashMap; 42 import java.util.Map; 43 44 public class BluetoothMapSettingsAdapter extends BaseExpandableListAdapter { 45 private static final String TAG = "BluetoothMapSettingsAdapter"; 46 47 private boolean mCheckAll = true; 48 public LayoutInflater mInflater; 49 public Activity mActivity; 50 /*needed to prevent random checkbox toggles due to item reuse */ ArrayList<Boolean> 51 mPositionArray; 52 private LinkedHashMap<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> mProupList; 53 private ArrayList<BluetoothMapAccountItem> mMainGroup; 54 private int[] mGroupStatus; 55 /* number of accounts possible to share */ 56 private int mSlotsLeft = 10; 57 BluetoothMapSettingsAdapter( Activity act, ExpandableListView listView, LinkedHashMap<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> groupsList, int enabledAccountsCounts)58 public BluetoothMapSettingsAdapter( 59 Activity act, 60 ExpandableListView listView, 61 LinkedHashMap<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> groupsList, 62 int enabledAccountsCounts) { 63 mActivity = act; 64 this.mProupList = groupsList; 65 mInflater = act.getLayoutInflater(); 66 mGroupStatus = new int[groupsList.size()]; 67 mSlotsLeft = mSlotsLeft - enabledAccountsCounts; 68 69 listView.setOnGroupExpandListener( 70 new OnGroupExpandListener() { 71 72 @Override 73 public void onGroupExpand(int groupPosition) { 74 BluetoothMapAccountItem group = mMainGroup.get(groupPosition); 75 if (mProupList.get(group).size() > 0) { 76 mGroupStatus[groupPosition] = 1; 77 } 78 } 79 }); 80 mMainGroup = new ArrayList<BluetoothMapAccountItem>(); 81 for (Map.Entry<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> mapEntry : 82 mProupList.entrySet()) { 83 mMainGroup.add(mapEntry.getKey()); 84 } 85 } 86 87 @Override getChild(int groupPosition, int childPosition)88 public BluetoothMapAccountItem getChild(int groupPosition, int childPosition) { 89 BluetoothMapAccountItem item = mMainGroup.get(groupPosition); 90 return mProupList.get(item).get(childPosition); 91 } 92 getChild(BluetoothMapAccountItem group)93 private ArrayList<BluetoothMapAccountItem> getChild(BluetoothMapAccountItem group) { 94 return mProupList.get(group); 95 } 96 97 @Override getChildId(int groupPosition, int childPosition)98 public long getChildId(int groupPosition, int childPosition) { 99 return 0; 100 } 101 102 @Override getChildView( final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent)103 public View getChildView( 104 final int groupPosition, 105 final int childPosition, 106 boolean isLastChild, 107 View convertView, 108 ViewGroup parent) { 109 110 final ChildHolder holder; 111 if (convertView == null) { 112 convertView = mInflater.inflate(R.layout.bluetooth_map_settings_account_item, null); 113 holder = new ChildHolder(); 114 holder.cb = (CheckBox) convertView.findViewById(R.id.bluetooth_map_settings_item_check); 115 holder.title = 116 (TextView) convertView.findViewById(R.id.bluetooth_map_settings_item_text_view); 117 convertView.setTag(holder); 118 } else { 119 holder = (ChildHolder) convertView.getTag(); 120 } 121 final BluetoothMapAccountItem child = getChild(groupPosition, childPosition); 122 holder.cb.setOnCheckedChangeListener( 123 new OnCheckedChangeListener() { 124 125 @Override 126 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 127 BluetoothMapAccountItem parentGroup = 128 (BluetoothMapAccountItem) getGroup(groupPosition); 129 boolean oldIsChecked = 130 child.mIsChecked; // needed to prevent updates on UI redraw 131 child.mIsChecked = isChecked; 132 if (isChecked) { 133 ArrayList<BluetoothMapAccountItem> childList = getChild(parentGroup); 134 int childIndex = childList.indexOf(child); 135 boolean isAllChildClicked = true; 136 if (mSlotsLeft - childList.size() >= 0) { 137 138 for (int i = 0; i < childList.size(); i++) { 139 if (i != childIndex) { 140 BluetoothMapAccountItem siblings = childList.get(i); 141 if (!siblings.mIsChecked) { 142 isAllChildClicked = false; 143 BluetoothMapSettingsDataHolder.sCheckedChilds.put( 144 child.getName(), parentGroup.getName()); 145 break; 146 } 147 } 148 } 149 } else { 150 showWarning( 151 mActivity.getString( 152 R.string 153 .bluetooth_map_settings_no_account_slots_left)); 154 isAllChildClicked = false; 155 child.mIsChecked = false; 156 } 157 if (isAllChildClicked) { 158 parentGroup.mIsChecked = true; 159 if (!(BluetoothMapSettingsDataHolder.sCheckedChilds.containsKey( 160 child.getName()))) { 161 BluetoothMapSettingsDataHolder.sCheckedChilds.put( 162 child.getName(), parentGroup.getName()); 163 } 164 mCheckAll = false; 165 } 166 167 } else { 168 if (parentGroup.mIsChecked) { 169 parentGroup.mIsChecked = false; 170 mCheckAll = false; 171 BluetoothMapSettingsDataHolder.sCheckedChilds.remove( 172 child.getName()); 173 } else { 174 mCheckAll = true; 175 BluetoothMapSettingsDataHolder.sCheckedChilds.remove( 176 child.getName()); 177 } 178 // child.isChecked =false; 179 } 180 notifyDataSetChanged(); 181 if (child.mIsChecked != oldIsChecked) { 182 updateAccount(child); 183 } 184 } 185 }); 186 187 holder.cb.setChecked(child.mIsChecked); 188 holder.title.setText(child.getName()); 189 Log.v("children are", BluetoothMapSettingsDataHolder.sCheckedChilds.toString()); 190 return convertView; 191 } 192 193 @Override getChildrenCount(int groupPosition)194 public int getChildrenCount(int groupPosition) { 195 BluetoothMapAccountItem item = mMainGroup.get(groupPosition); 196 return mProupList.get(item).size(); 197 } 198 199 @Override getGroup(int groupPosition)200 public BluetoothMapAccountItem getGroup(int groupPosition) { 201 return mMainGroup.get(groupPosition); 202 } 203 204 @Override getGroupCount()205 public int getGroupCount() { 206 return mMainGroup.size(); 207 } 208 209 @Override onGroupCollapsed(int groupPosition)210 public void onGroupCollapsed(int groupPosition) { 211 super.onGroupCollapsed(groupPosition); 212 } 213 214 @Override onGroupExpanded(int groupPosition)215 public void onGroupExpanded(int groupPosition) { 216 super.onGroupExpanded(groupPosition); 217 } 218 219 @Override getGroupId(int groupPosition)220 public long getGroupId(int groupPosition) { 221 return 0; 222 } 223 224 @Override getGroupView( int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)225 public View getGroupView( 226 int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { 227 228 final GroupHolder holder; 229 230 if (convertView == null) { 231 convertView = mInflater.inflate(R.layout.bluetooth_map_settings_account_group, null); 232 holder = new GroupHolder(); 233 holder.cb = 234 (CheckBox) convertView.findViewById(R.id.bluetooth_map_settings_group_checkbox); 235 holder.imageView = 236 (ImageView) convertView.findViewById(R.id.bluetooth_map_settings_group_icon); 237 holder.title = 238 (TextView) 239 convertView.findViewById(R.id.bluetooth_map_settings_group_text_view); 240 convertView.setTag(holder); 241 } else { 242 holder = (GroupHolder) convertView.getTag(); 243 } 244 245 final BluetoothMapAccountItem groupItem = getGroup(groupPosition); 246 holder.imageView.setImageDrawable(groupItem.getIcon()); 247 248 holder.title.setText(groupItem.getName()); 249 250 holder.cb.setOnCheckedChangeListener( 251 new OnCheckedChangeListener() { 252 253 @Override 254 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 255 if (mCheckAll) { 256 ArrayList<BluetoothMapAccountItem> childItem = getChild(groupItem); 257 for (BluetoothMapAccountItem children : childItem) { 258 boolean oldIsChecked = children.mIsChecked; 259 if (mSlotsLeft > 0) { 260 children.mIsChecked = isChecked; 261 if (oldIsChecked != children.mIsChecked) { 262 updateAccount(children); 263 } 264 } else { 265 showWarning( 266 mActivity.getString( 267 R.string 268 .bluetooth_map_settings_no_account_slots_left)); 269 isChecked = false; 270 } 271 } 272 } 273 groupItem.mIsChecked = isChecked; 274 notifyDataSetChanged(); 275 new Handler() 276 .postDelayed( 277 new Runnable() { 278 279 @Override 280 public void run() { 281 if (!mCheckAll) { 282 mCheckAll = true; 283 } 284 } 285 }, 286 50); 287 } 288 }); 289 holder.cb.setChecked(groupItem.mIsChecked); 290 return convertView; 291 } 292 293 @Override hasStableIds()294 public boolean hasStableIds() { 295 return true; 296 } 297 298 @Override isChildSelectable(int groupPosition, int childPosition)299 public boolean isChildSelectable(int groupPosition, int childPosition) { 300 return true; 301 } 302 303 private static class GroupHolder { 304 public ImageView imageView; 305 public CheckBox cb; 306 public TextView title; 307 } 308 309 private static class ChildHolder { 310 public TextView title; 311 public CheckBox cb; 312 } 313 updateAccount(BluetoothMapAccountItem account)314 public void updateAccount(BluetoothMapAccountItem account) { 315 updateSlotCounter(account.mIsChecked); 316 Log.d( 317 TAG, 318 "Updating account settings for " 319 + account.getName() 320 + ". Value is:" 321 + account.mIsChecked); 322 ContentResolver mResolver = mActivity.getContentResolver(); 323 Uri uri = 324 Uri.parse(account.mBase_uri_no_account + "/" + BluetoothMapContract.TABLE_ACCOUNT); 325 ContentValues values = new ContentValues(); 326 values.put(BluetoothMapContract.AccountColumns.FLAG_EXPOSE, ((account.mIsChecked) ? 1 : 0)); 327 values.put(BluetoothMapContract.AccountColumns._ID, account.getId()); // get title 328 mResolver.update(uri, values, null, null); 329 } 330 updateSlotCounter(boolean isChecked)331 private void updateSlotCounter(boolean isChecked) { 332 if (isChecked) { 333 mSlotsLeft--; 334 } else { 335 mSlotsLeft++; 336 } 337 CharSequence text; 338 339 if (mSlotsLeft <= 0) { 340 text = mActivity.getString(R.string.bluetooth_map_settings_no_account_slots_left); 341 } else { 342 text = 343 mActivity.getString(R.string.bluetooth_map_settings_count) 344 + " " 345 + String.valueOf(mSlotsLeft); 346 } 347 348 int duration = Toast.LENGTH_SHORT; 349 350 Toast toast = Toast.makeText(mActivity, text, duration); 351 toast.show(); 352 } 353 showWarning(String text)354 private void showWarning(String text) { 355 int duration = Toast.LENGTH_SHORT; 356 357 Toast toast = Toast.makeText(mActivity, text, duration); 358 toast.show(); 359 } 360 } 361