fb684b53dafed08d1fa34df817c2de2beee952f0
[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 Context context = getActivity().getApplicationContext();
113
114 mDataSource = new VpnProfileDataSource(this.getActivity());
115 mDataSource.open();
116
117 /* cached list of profiles used as backend for the ListView */
118 mVpnProfiles = mDataSource.getAllVpnProfiles();
119
120 mListAdapter = new VpnProfileAdapter(context, R.layout.profile_list_item, mVpnProfiles);
121 }
122
123 @Override
124 public void onDestroy()
125 {
126 super.onDestroy();
127 mDataSource.close();
128 }
129
130 @Override
131 public void onAttach(Activity activity)
132 {
133 super.onAttach(activity);
134
135 if (activity instanceof OnVpnProfileSelectedListener)
136 {
137 mListener = (OnVpnProfileSelectedListener)activity;
138 }
139 }
140
141 @Override
142 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
143 {
144 inflater.inflate(R.menu.profile_list, menu);
145 }
146
147 @Override
148 public boolean onOptionsItemSelected(MenuItem item)
149 {
150 switch (item.getItemId())
151 {
152 case R.id.add_profile:
153 Intent connectionIntent = new Intent(getActivity(),
154 VpnProfileDetailActivity.class);
155 startActivityForResult(connectionIntent, ADD_REQUEST);
156 return true;
157 default:
158 return super.onOptionsItemSelected(item);
159 }
160 }
161
162 @Override
163 public void onActivityResult(int requestCode, int resultCode, Intent data)
164 {
165 switch (requestCode)
166 {
167 case ADD_REQUEST:
168 case EDIT_REQUEST:
169 if (resultCode != Activity.RESULT_OK)
170 {
171 return;
172 }
173 long id = data.getLongExtra(VpnProfileDataSource.KEY_ID, 0);
174 VpnProfile profile = mDataSource.getVpnProfile(id);
175 if (profile != null)
176 { /* in case this was an edit, we remove it first */
177 mVpnProfiles.remove(profile);
178 mVpnProfiles.add(profile);
179 mListAdapter.notifyDataSetChanged();
180 }
181 return;
182 }
183 super.onActivityResult(requestCode, resultCode, data);
184 }
185
186 private final OnItemClickListener mVpnProfileClicked = new OnItemClickListener() {
187 @Override
188 public void onItemClick(AdapterView<?> a, View v, int position, long id)
189 {
190 if (mListener != null)
191 {
192 mListener.onVpnProfileSelected((VpnProfile)a.getItemAtPosition(position));
193 }
194 }
195 };
196
197 private final MultiChoiceModeListener mVpnProfileSelected = new MultiChoiceModeListener() {
198 private HashSet<Integer> mSelected;
199 private MenuItem mEditProfile;
200
201 @Override
202 public boolean onPrepareActionMode(ActionMode mode, Menu menu)
203 {
204 return false;
205 }
206
207 @Override
208 public void onDestroyActionMode(ActionMode mode)
209 {
210 }
211
212 @Override
213 public boolean onCreateActionMode(ActionMode mode, Menu menu)
214 {
215 MenuInflater inflater = mode.getMenuInflater();
216 inflater.inflate(R.menu.profile_list_context, menu);
217 mEditProfile = menu.findItem(R.id.edit_profile);
218 mSelected = new HashSet<Integer>();
219 mode.setTitle(R.string.select_profiles);
220 return true;
221 }
222
223 @Override
224 public boolean onActionItemClicked(ActionMode mode, MenuItem item)
225 {
226 switch (item.getItemId())
227 {
228 case R.id.edit_profile:
229 {
230 int position = mSelected.iterator().next();
231 VpnProfile profile = (VpnProfile)mListView.getItemAtPosition(position);
232 Intent connectionIntent = new Intent(getActivity(), VpnProfileDetailActivity.class);
233 connectionIntent.putExtra(VpnProfileDataSource.KEY_ID, profile.getId());
234 startActivityForResult(connectionIntent, EDIT_REQUEST);
235 break;
236 }
237 case R.id.delete_profile:
238 {
239 ArrayList<VpnProfile> profiles = new ArrayList<VpnProfile>();
240 for (int position : mSelected)
241 {
242 profiles.add((VpnProfile)mListView.getItemAtPosition(position));
243 }
244 for (VpnProfile profile : profiles)
245 {
246 mDataSource.deleteVpnProfile(profile);
247 mVpnProfiles.remove(profile);
248 }
249 mListAdapter.notifyDataSetChanged();
250 Toast.makeText(VpnProfileListFragment.this.getActivity(),
251 R.string.profiles_deleted, Toast.LENGTH_SHORT).show();
252 break;
253 }
254 default:
255 return false;
256 }
257 mode.finish();
258 return true;
259 }
260
261 @Override
262 public void onItemCheckedStateChanged(ActionMode mode, int position,
263 long id, boolean checked)
264 {
265 if (checked)
266 {
267 mSelected.add(position);
268 }
269 else
270 {
271 mSelected.remove(position);
272 }
273 final int checkedCount = mSelected.size();
274 mEditProfile.setEnabled(checkedCount == 1);
275 switch (checkedCount)
276 {
277 case 0:
278 mode.setSubtitle(R.string.no_profile_selected);
279 break;
280 case 1:
281 mode.setSubtitle(R.string.one_profile_selected);
282 break;
283 default:
284 mode.setSubtitle(String.format(getString(R.string.x_profiles_selected), checkedCount));
285 break;
286 }
287 }
288 };
289 }