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 
BluetoothMapSettingsAdapter(Activity act, ExpandableListView listView, LinkedHashMap<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> groupsList, int enabledAccountsCounts)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
getChild(int groupPosition, int childPosition)95     public BluetoothMapAccountItem getChild(int groupPosition, int childPosition) {
96         BluetoothMapAccountItem item = mMainGroup.get(groupPosition);
97         return mProupList.get(item).get(childPosition);
98     }
getChild(BluetoothMapAccountItem group)99     private ArrayList<BluetoothMapAccountItem> getChild(BluetoothMapAccountItem group) {
100         return mProupList.get(group);
101     }
102 
103     @Override
getChildId(int groupPosition, int childPosition)104     public long getChildId(int groupPosition, int childPosition) {
105         return 0;
106     }
107 
108     @Override
getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent)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
getChildrenCount(int groupPosition)198     public int getChildrenCount(int groupPosition) {
199         BluetoothMapAccountItem item = mMainGroup.get(groupPosition);
200         return mProupList.get(item).size();
201     }
202 
203     @Override
getGroup(int groupPosition)204     public BluetoothMapAccountItem getGroup(int groupPosition) {
205         return mMainGroup.get(groupPosition);
206     }
207 
208     @Override
getGroupCount()209     public int getGroupCount() {
210         return mMainGroup.size();
211     }
212 
213     @Override
onGroupCollapsed(int groupPosition)214     public void onGroupCollapsed(int groupPosition) {
215         super.onGroupCollapsed(groupPosition);
216     }
217 
218     @Override
onGroupExpanded(int groupPosition)219     public void onGroupExpanded(int groupPosition) {
220         super.onGroupExpanded(groupPosition);
221     }
222 
223     @Override
getGroupId(int groupPosition)224     public long getGroupId(int groupPosition) {
225         return 0;
226     }
227 
228     @Override
getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)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
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 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     }
updateAccount(BluetoothMapAccountItem account)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     }
updateSlotCounter(boolean isChecked)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     }
showWarning(String text)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