android: Use Activity as context for VpnProfileAdapter to fix theme
[strongswan.git] / src / frontends / android / app / src / main / java / org / strongswan / android / ui / VpnProfileListFragment.java
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 package org.strongswan.android.ui;
19
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.List;
23
24 import org.strongswan.android.R;
25 import org.strongswan.android.data.VpnProfile;
26 import org.strongswan.android.data.VpnProfileDataSource;
27 import org.strongswan.android.ui.adapter.VpnProfileAdapter;
28
29 import android.app.Activity;
30 import android.app.Fragment;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.res.TypedArray;
34 import android.os.Bundle;
35 import android.util.AttributeSet;
36 import android.view.ActionMode;
37 import android.view.LayoutInflater;
38 import android.view.Menu;
39 import android.view.MenuInflater;
40 import android.view.MenuItem;
41 import android.view.View;
42 import android.view.ViewGroup;
43 import android.widget.AbsListView.MultiChoiceModeListener;
44 import android.widget.AdapterView;
45 import android.widget.AdapterView.OnItemClickListener;
46 import android.widget.ListView;
47 import android.widget.Toast;
48
49 public class VpnProfileListFragment extends Fragment
50 {
51 private static final int ADD_REQUEST = 1;
52 private static final int EDIT_REQUEST = 2;
53
54 private List<VpnProfile> mVpnProfiles;
55 private VpnProfileDataSource mDataSource;
56 private VpnProfileAdapter mListAdapter;
57 private ListView mListView;
58 private OnVpnProfileSelectedListener mListener;
59 private boolean mReadOnly;
60
61 /**
62 * The activity containing this fragment should implement this interface
63 */
64 public interface OnVpnProfileSelectedListener {
65 public void onVpnProfileSelected(VpnProfile profile);
66 }
67
68 @Override
69 public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)
70 {
71 super.onInflate(activity, attrs, savedInstanceState);
72 TypedArray a = activity.obtainStyledAttributes(attrs, R.styleable.Fragment);
73 mReadOnly = a.getBoolean(R.styleable.Fragment_read_only, false);
74 a.recycle();
75 }
76
77 @Override
78 public View onCreateView(LayoutInflater inflater, ViewGroup container,
79 Bundle savedInstanceState)
80 {
81 View view = inflater.inflate(R.layout.profile_list_fragment, null);
82
83 mListView = (ListView)view.findViewById(R.id.profile_list);
84 mListView.setAdapter(mListAdapter);
85 mListView.setEmptyView(view.findViewById(R.id.profile_list_empty));
86 mListView.setOnItemClickListener(mVpnProfileClicked);
87
88 if (!mReadOnly)
89 {
90 mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
91 mListView.setMultiChoiceModeListener(mVpnProfileSelected);
92 }
93 return view;
94 }
95
96 @Override
97 public void onCreate(Bundle savedInstanceState)
98 {
99 super.onCreate(savedInstanceState);
100
101 Bundle args = getArguments();
102 if (args != null)
103 {
104 mReadOnly = args.getBoolean("read_only", mReadOnly);
105 }
106
107 if (!mReadOnly)
108 {
109 setHasOptionsMenu(true);
110 }
111
112 mDataSource = new VpnProfileDataSource(this.getActivity());
113 mDataSource.open();
114
115 /* cached list of profiles used as backend for the ListView */
116 mVpnProfiles = mDataSource.getAllVpnProfiles();
117
118 mListAdapter = new VpnProfileAdapter(getActivity(), R.layout.profile_list_item, mVpnProfiles);
119 }
120
121 @Override
122 public void onDestroy()
123 {
124 super.onDestroy();
125 mDataSource.close();
126 }
127
128 @Override
129 public void onAttach(Activity activity)
130 {
131 super.onAttach(activity);
132
133 if (activity instanceof OnVpnProfileSelectedListener)
134 {
135 mListener = (OnVpnProfileSelectedListener)activity;
136 }
137 }
138
139 @Override
140 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
141 {
142 inflater.inflate(R.menu.profile_list, menu);
143 }
144
145 @Override
146 public boolean onOptionsItemSelected(MenuItem item)
147 {
148 switch (item.getItemId())
149 {
150 case R.id.add_profile:
151 Intent connectionIntent = new Intent(getActivity(),
152 VpnProfileDetailActivity.class);
153 startActivityForResult(connectionIntent, ADD_REQUEST);
154 return true;
155 default:
156 return super.onOptionsItemSelected(item);
157 }
158 }
159
160 @Override
161 public void onActivityResult(int requestCode, int resultCode, Intent data)
162 {
163 switch (requestCode)
164 {
165 case ADD_REQUEST:
166 case EDIT_REQUEST:
167 if (resultCode != Activity.RESULT_OK)
168 {
169 return;
170 }
171 long id = data.getLongExtra(VpnProfileDataSource.KEY_ID, 0);
172 VpnProfile profile = mDataSource.getVpnProfile(id);
173 if (profile != null)
174 { /* in case this was an edit, we remove it first */
175 mVpnProfiles.remove(profile);
176 mVpnProfiles.add(profile);
177 mListAdapter.notifyDataSetChanged();
178 }
179 return;
180 }
181 super.onActivityResult(requestCode, resultCode, data);
182 }
183
184 private final OnItemClickListener mVpnProfileClicked = new OnItemClickListener() {
185 @Override
186 public void onItemClick(AdapterView<?> a, View v, int position, long id)
187 {
188 if (mListener != null)
189 {
190 mListener.onVpnProfileSelected((VpnProfile)a.getItemAtPosition(position));
191 }
192 }
193 };
194
195 private final MultiChoiceModeListener mVpnProfileSelected = new MultiChoiceModeListener() {
196 private HashSet<Integer> mSelected;
197 private MenuItem mEditProfile;
198
199 @Override
200 public boolean onPrepareActionMode(ActionMode mode, Menu menu)
201 {
202 return false;
203 }
204
205 @Override
206 public void onDestroyActionMode(ActionMode mode)
207 {
208 }
209
210 @Override
211 public boolean onCreateActionMode(ActionMode mode, Menu menu)
212 {
213 MenuInflater inflater = mode.getMenuInflater();
214 inflater.inflate(R.menu.profile_list_context, menu);
215 mEditProfile = menu.findItem(R.id.edit_profile);
216 mSelected = new HashSet<Integer>();
217 mode.setTitle(R.string.select_profiles);
218 return true;
219 }
220
221 @Override
222 public boolean onActionItemClicked(ActionMode mode, MenuItem item)
223 {
224 switch (item.getItemId())
225 {
226 case R.id.edit_profile:
227 {
228 int position = mSelected.iterator().next();
229 VpnProfile profile = (VpnProfile)mListView.getItemAtPosition(position);
230 Intent connectionIntent = new Intent(getActivity(), VpnProfileDetailActivity.class);
231 connectionIntent.putExtra(VpnProfileDataSource.KEY_ID, profile.getId());
232 startActivityForResult(connectionIntent, EDIT_REQUEST);
233 break;
234 }
235 case R.id.delete_profile:
236 {
237 ArrayList<VpnProfile> profiles = new ArrayList<VpnProfile>();
238 for (int position : mSelected)
239 {
240 profiles.add((VpnProfile)mListView.getItemAtPosition(position));
241 }
242 for (VpnProfile profile : profiles)
243 {
244 mDataSource.deleteVpnProfile(profile);
245 mVpnProfiles.remove(profile);
246 }
247 mListAdapter.notifyDataSetChanged();
248 Toast.makeText(VpnProfileListFragment.this.getActivity(),
249 R.string.profiles_deleted, Toast.LENGTH_SHORT).show();
250 break;
251 }
252 default:
253 return false;
254 }
255 mode.finish();
256 return true;
257 }
258
259 @Override
260 public void onItemCheckedStateChanged(ActionMode mode, int position,
261 long id, boolean checked)
262 {
263 if (checked)
264 {
265 mSelected.add(position);
266 }
267 else
268 {
269 mSelected.remove(position);
270 }
271 final int checkedCount = mSelected.size();
272 mEditProfile.setEnabled(checkedCount == 1);
273 switch (checkedCount)
274 {
275 case 0:
276 mode.setSubtitle(R.string.no_profile_selected);
277 break;
278 case 1:
279 mode.setSubtitle(R.string.one_profile_selected);
280 break;
281 default:
282 mode.setSubtitle(String.format(getString(R.string.x_profiles_selected), checkedCount));
283 break;
284 }
285 }
286 };
287 }