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