package com.orgzly.android.ui.fragments; import android.content.Context; import android.os.Bundle; import android.support.design.widget.TextInputLayout; import android.support.v4.app.Fragment; import android.support.v4.util.LongSparseArray; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.ViewFlipper; import com.orgzly.BuildConfig; import com.orgzly.R; import com.orgzly.android.Filter; import com.orgzly.android.provider.clients.FiltersClient; import com.orgzly.android.ui.FragmentListener; import com.orgzly.android.ui.util.ActivityUtils; import com.orgzly.android.util.LogUtils; public class FilterFragment extends Fragment { private static final String TAG = FilterFragment.class.getName(); private static final String ARG_ID = "id"; /** Name used for {@link android.app.FragmentManager}. */ public static final String FRAGMENT_TAG = FilterFragment.class.getName(); private FilterFragmentListener mListener; private ViewFlipper mViewFlipper; private TextInputLayout nameInputLayout; private EditText mName; private TextInputLayout queryInputLayout; private EditText mQuery; public static FilterFragment getInstance() { return new FilterFragment(); } public static FilterFragment getInstance(long id) { FilterFragment fragment = new FilterFragment(); Bundle args = new Bundle(); args.putLong(ARG_ID, id); fragment.setArguments(args); return fragment; } /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). */ public FilterFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* Would like to add items to the Options Menu. * Required (for fragments only) to receive onCreateOptionsMenu() call. */ setHasOptionsMenu(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_filter, container, false); mViewFlipper = (ViewFlipper) view.findViewById(R.id.fragment_filter_flipper); nameInputLayout = (TextInputLayout) view.findViewById(R.id.fragment_filter_name_input_layout); mName = (EditText) view.findViewById(R.id.fragment_filter_name); queryInputLayout = (TextInputLayout) view.findViewById(R.id.fragment_filter_query_input_layout); mQuery = (EditText) view.findViewById(R.id.fragment_filter_query); setViewsFromArgument(); return view; } private void setViewsFromArgument() { View viewToFocus = null; if (isEditingExistingFilter()) { /* Existing filter. */ long id = getArguments().getLong(ARG_ID); Filter filter = FiltersClient.get(getActivity(), id); if (filter != null) { mName.setText(filter.getName()); mQuery.setText(filter.getQuery()); mViewFlipper.setDisplayedChild(0); viewToFocus = mQuery; } else { mViewFlipper.setDisplayedChild(1); } } else { /* New filter. */ viewToFocus = mName; } /* * Open a soft keyboard. * For new filters focus on name, for existing focus on query. */ if (viewToFocus != null && getActivity() != null) { ActivityUtils.openSoftKeyboard(getActivity(), viewToFocus); } } @Override public void onResume() { if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG); super.onResume(); announceChangesToActivity(); } private void announceChangesToActivity() { if (isEditingExistingFilter()) { mListener.announceChanges(FRAGMENT_TAG, getString(R.string.search), null, 0); } else { mListener.announceChanges(FRAGMENT_TAG, getString(R.string.new_search), null, 0); } } private boolean isEditingExistingFilter() { return getArguments() != null && getArguments().containsKey(ARG_ID); } @Override public void onAttach(Context context) { super.onAttach(context); /* This makes sure that the container activity has implemented * the callback interface. If not, it throws an exception */ try { mListener = (FilterFragmentListener) getActivity(); } catch (ClassCastException e) { throw new ClassCastException(getActivity().toString() + " must implement " + FilterFragmentListener.class); } } @Override public void onDetach() { super.onDetach(); mListener = null; } /** * Callback for options menu. */ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, menu, inflater); inflater.inflate(R.menu.done_or_close, menu); /* Remove search item. */ menu.removeItem(R.id.activity_action_search); } /** * Callback for options menu. */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.close: if (mListener != null) { mListener.onFilterCancelRequest(); } return true; case R.id.done: save(); return true; default: return super.onOptionsItemSelected(item); } } /** * Sends current values to listener. */ private void save() { String name = mName.getText().toString(); String query = mQuery.getText().toString(); boolean canSave = true; /* Validate name. */ if (TextUtils.isEmpty(name)) { nameInputLayout.setError(getString(R.string.can_not_be_empty)); canSave = false; } else if (sameNameFilterExists(name)) { nameInputLayout.setError(getString(R.string.filter_name_already_exists)); canSave = false; } else { nameInputLayout.setError(null); } /* Validate query. */ if (TextUtils.isEmpty(query)) { queryInputLayout.setError(getString(R.string.can_not_be_empty)); canSave = false; } else { queryInputLayout.setError(null); } if (! canSave) { return; } Filter filter = new Filter(name, query); /* Editing existing record. */ if (isEditingExistingFilter()) { long id = getArguments().getLong(ARG_ID); if (mListener != null) { mListener.onFilterUpdateRequest(id, filter); } } else { if (mListener != null) { mListener.onFilterCreateRequest(filter); } } } /** * Checks if filter with the same name (ignoring case) already exists. */ private boolean sameNameFilterExists(String name) { LongSparseArray<Filter> filters = FiltersClient.getByNameIgnoreCase(getContext(), name); if (isEditingExistingFilter()) { long id = getArguments().getLong(ARG_ID); for (int i = 0; i < filters.size(); i++) { long filterId = filters.keyAt(i); Filter filter = filters.get(filterId); // Ignore currently edited filter if (name.equalsIgnoreCase(filter.getName()) && id != filterId) { return true; } } return false; } else { // New filter return filters.size() > 0; } } public interface FilterFragmentListener extends FragmentListener { void onFilterCreateRequest(Filter filter); void onFilterUpdateRequest(long id, Filter filter); void onFilterCancelRequest(); } }