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