/* * Copyright (C) 2013 The WLANAudit project contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.glasspixel.wlanaudit.fragments; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.ListView; import android.widget.Toast; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.ActionMode.Callback; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.github.rtyley.android.sherlock.roboguice.fragment.RoboSherlockListFragment; import org.orman.mapper.Model; import java.util.ArrayList; import java.util.List; import es.glasspixel.wlanaudit.R; import es.glasspixel.wlanaudit.adapters.SavedNetworksAdapter; import es.glasspixel.wlanaudit.database.entities.Network; import es.glasspixel.wlanaudit.interfaces.OnDataSourceModifiedListener; import roboguice.inject.InjectView; public class SavedNetworksFragment extends RoboSherlockListFragment implements OnDataSourceModifiedListener { /** * Interface to pass fragment callbacks to parent activity. Parent activity * must implement this to be aware of the events of the fragment. */ public interface SavedNetworkFragmentListener extends OnDataSourceModifiedListener { /** * Observers must implement this method to be notified of which network * was selected on this fragment. * * @param networkData The network data of the selected item. */ public void onNetworkSelected(Network networkData); /** * Fragments which use a shared datasource with other fragments, should * notify them using this method. */ public void dataSourceShouldRefresh(); } /** * Dummy callback object, this is meant to be a dummy callback object when an * activity is not attached to the fragment to avoid calls on a null object. */ private SavedNetworkFragmentListener sDummyCallback = new SavedNetworkFragmentListener() { @Override public void onNetworkSelected(Network networkData) { } @Override public void dataSourceShouldRefresh() { } }; /** * Real callback, this object is assigned to a real callback when an * activity attaches to the fragment, when the activity detaches it has * to be replaced with the dummy callback object in order to avoid continuous * nullity checks. This solution is used by Google in their I/0 2012 app. */ private SavedNetworkFragmentListener mCallback = sDummyCallback; protected ActionMode mActionMode; protected int context_menu_item_position; private List<Network> mSavedNetworks; protected Network mSelectedNetwork; @InjectView(android.R.id.list) private ListView mNetworkListView; private SavedNetworksAdapter mListAdapter; protected MenuItem copyMenuItem; @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallback = (SavedNetworkFragmentListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnDataSourceModifiedListener"); } } @Override public void onDetach() { super.onDetach(); mCallback = sDummyCallback; } @Override public void onResume() { super.onResume(); mSavedNetworks = Model.fetchAll(Network.class); mListAdapter = new SavedNetworksAdapter(getSherlockActivity(), R.layout.key_saved_list_element, mSavedNetworks); setListAdapter(mListAdapter); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); return inflater.inflate(R.layout.saved_keys_fragment, container, false); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mNetworkListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB) { mNetworkListView.setItemsCanFocus(false); mNetworkListView .setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (mActionMode != null) { return false; } context_menu_item_position = position; // Start the CAB using the ActionMode.Callback // defined // above mActionMode = getSherlockActivity() .startActionMode(mActionCallBack); mSelectedNetwork = mSavedNetworks.get(position); view.setSelected(true); mNetworkListView.getCheckedItemPositions().put(0, true); mActionMode.setTitle(String.valueOf(1) + " " + getResources() .getString( R.string.context_menu_selected_count_unico)); mActionMode.getMenu().getItem(0).setVisible(true); mNetworkListView .setOnItemClickListener(new OnItemClickListener() { private SparseBooleanArray checked; @Override public void onItemClick( AdapterView<?> arg0, View arg1, int arg2, long arg3) { mNetworkListView .getCheckedItemPositions() .put(0, !mNetworkListView .getCheckedItemPositions() .get(arg2)); int checked_count = 0; checked = mNetworkListView .getCheckedItemPositions(); boolean hasCheckedElement = false; for (int i = 0; i < checked.size() && !hasCheckedElement; i++) { if (checked.get(i)) { checked_count++; } hasCheckedElement = checked .valueAt(i); } arg1.setSelected(checked.get(arg2)); if (checked_count > 1) { mActionMode.getMenu() .getItem(0) .setVisible(false); mActionMode.setTitle(String .valueOf(checked_count) + " " + getResources() .getString( R.string.context_menu_selected_count_multiple)); } else if (checked_count == 1) { mActionMode.setTitle(String .valueOf(checked_count) + " " + getResources() .getString( R.string.context_menu_selected_count_unico)); mActionMode.getMenu() .getItem(0) .setVisible(true); } else { mActionMode.finish(); } } }); return true; } }); } else { mNetworkListView .setMultiChoiceModeListener(new ListView.MultiChoiceModeListener() { ArrayList<Network> mCheckedItems; android.view.MenuItem copy_item; @Override public boolean onActionItemClicked( android.view.ActionMode mode, android.view.MenuItem item) { switch (item.getItemId()) { case R.id.delete_context_menu: for (Network n : mCheckedItems) { n.delete(); } mCallback.dataSourceShouldRefresh(); mode.finish(); break; default: break; } mode.finish(); return true; } @Override public boolean onCreateActionMode( android.view.ActionMode mode, android.view.Menu menu) { android.view.MenuInflater inflater = mode .getMenuInflater(); inflater.inflate( R.menu.saved_keys_elements_context_menu, menu); copy_item = menu.getItem(0); if (mCheckedItems == null) { mCheckedItems = new ArrayList<Network>(); } return true; } @Override public void onDestroyActionMode( android.view.ActionMode mode) { mCheckedItems = null; } @Override public boolean onPrepareActionMode( android.view.ActionMode mode, android.view.Menu menu) { if (mCheckedItems == null) { mCheckedItems = new ArrayList<Network>(); } return true; } @Override public void onItemCheckedStateChanged( android.view.ActionMode mode, int position, long id, boolean checked) { final int count = mNetworkListView .getCheckedItemCount(); if (count > 1) { copy_item.setVisible(false); mode.setTitle(String.valueOf(count) + " " + getResources() .getString( R.string.context_menu_selected_count_multiple)); } else { mode.setTitle(String.valueOf(count) + " " + getResources() .getString( R.string.context_menu_selected_count_unico)); copy_item.setVisible(true); } if (checked) { mCheckedItems.add(mSavedNetworks.get(position)); } else { mCheckedItems.remove(mSavedNetworks .get(position)); } } }); } mNetworkListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mCallback.onNetworkSelected((Network) parent .getItemAtPosition(position)); } }); } private ActionMode.Callback mActionCallBack = new Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.saved_keys_elements_context_menu, menu); copyMenuItem = menu.getItem(0); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.delete_context_menu: SparseBooleanArray s = mNetworkListView .getCheckedItemPositions(); for (int i = 0; i < s.size(); i++) { if (s.get(i)) { mSavedNetworks.get(i).delete(); } } mCallback.dataSourceShouldRefresh(); mode.finish(); return true; default: return true; } } @SuppressWarnings("unused") public void setCopyMenuItemVisible(boolean visibility) { } @Override public void onDestroyActionMode(ActionMode mode) { mActionMode = null; } }; @SuppressWarnings("deprecation") @SuppressLint("NewApi") private void copyClipboard(CharSequence text) { int sdk = android.os.Build.VERSION.SDK_INT; if (sdk >= android.os.Build.VERSION_CODES.HONEYCOMB) { android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity() .getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData .newPlainText("text label", text); clipboard.setPrimaryClip(clip); } else { android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity() .getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText(text); } Toast.makeText(getActivity(), getResources().getString(R.string.key_copy_success), Toast.LENGTH_SHORT).show(); } @Override public void dataSourceShouldRefresh() { mSavedNetworks = Model.fetchAll(Network.class); mListAdapter.clear(); for (Network n : mSavedNetworks) { mListAdapter.add(n); } mListAdapter.notifyDataSetChanged(); } }