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