/* This file is part of RateBeer For Android. RateBeer for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RateBeer for Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RateBeer for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.ratebeer.android.gui.components; import android.view.View; import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.googlecode.androidannotations.annotations.Bean; import com.googlecode.androidannotations.annotations.EBean; import com.ratebeer.android.R; import com.ratebeer.android.api.ApiException; import com.ratebeer.android.api.Command; import com.ratebeer.android.api.CommandFailureResult; import com.ratebeer.android.api.CommandSuccessResult; import com.ratebeer.android.api.UserSettings; import com.ratebeer.android.api.command.SignOutCommand; import com.ratebeer.android.app.ApplicationSettings; import com.ratebeer.android.gui.SignIn_; import com.ratebeer.android.gui.components.helpers.Log; import com.ratebeer.android.gui.components.helpers.RateBeerTaskCaller; import com.ratebeer.android.gui.fragments.UserViewFragment_; import de.neofonie.mobile.app.android.widget.crouton.Crouton; import de.neofonie.mobile.app.android.widget.crouton.Style; @EBean public abstract class RateBeerFragment extends SherlockFragment implements RateBeerTaskCaller { // Action bar items provided by RateBeerFragment public static final int MENU_SIGNIN = 9801; public static final int MENU_SIGNOUT = 9802; protected boolean showSignInMenuItem = true; @Bean protected Log Log; @Bean protected ApplicationSettings applicationSettings = null; public RateBeerFragment() { setHasOptionsMenu(true); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Provide sign in/my profile action option // Note: text and action is not set until onPrepareOptionsMenu MenuItem signin = menu.add(Menu.NONE, MENU_SIGNIN, MENU_SIGNIN, ""); signin.setIcon(R.drawable.ic_action_signin); signin.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM|MenuItem.SHOW_AS_ACTION_WITH_TEXT); // Provide sign out option (always shown in (overflow) menu) // Note: action is not shown until onPrepareOptionsMenu MenuItem signout = menu.add(Menu.NONE, MENU_SIGNOUT, MENU_SIGNOUT, R.string.signin_signout); signout.setIcon(R.drawable.ic_menu_signout); signout.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); super.onCreateOptionsMenu(menu, inflater); } @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); // Add user sign in/out item MenuItem signIn = menu.findItem(MENU_SIGNIN); MenuItem signOut = menu.findItem(MENU_SIGNOUT); if (showSignInMenuItem && getActivity() != null) { String userText = getUser() == null? getString(R.string.signin_signin): getUser().getUsername(); signIn.setVisible(true); signIn.setTitle(userText); signOut.setVisible(getUser() != null); } else { signIn.setVisible(false); signOut.setVisible(false); } // If there is an action bar item representing MENU_REFRESH and we have tasks in progress, show custom view with an undetermined progress indicator if (getActivity() != null && getRateBeerActivity().isInProgress()) { for (int i = 0; i < menu.size(); i++) { if (menu.getItem(i).getItemId() == R.id.menu_refresh) { View view = getRateBeerActivity().getLayoutInflater().inflate(R.layout.actionbar_progressitem, null); menu.getItem(i).setActionView(view); } } } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_SIGNIN: if (getUser() == null) { SignIn_.intent(getActivity()).start(); } else { load(UserViewFragment_.builder().userId(getUser().getUserID()).userName(getUser().getUsername()).build()); } return true; case MENU_SIGNOUT: getRateBeerActivity().execute(signOutHandler, new SignOutCommand(getUser())); return true; } return super.onOptionsItemSelected(item); } private RateBeerTaskCaller signOutHandler = new RateBeerTaskCaller() { @Override public void onTaskSuccessResult(CommandSuccessResult result) { if (getActivity() == null) { // No longer visible return; } // Successfully signed out Crouton.makeText(getActivity(), R.string.signin_signoutsuccess, Style.CONFIRM).show(); applicationSettings.saveUserSettings(null); getActivity().supportInvalidateOptionsMenu(); } @Override public void onTaskFailureResult(CommandFailureResult result) { if (getActivity() == null) { // No longer visible return; } // Sign out failure publishException(null, result.getException()); } @Override public boolean isBound() { return true; } }; /** * Convenience method that calls load(fragment, true) on the attached RateBeerActivity * @param fragment The fragment to show */ public void load(RateBeerFragment fragment) { getRateBeerActivity().load(fragment, true); } /** * Convenience method that calls load(fragment, true) on the attached RateBeerActivity * @param fragment The fragment to show * @param addToBackStack Whether to also add this fragment to the backstack */ public void load(RateBeerFragment fragment, boolean addToBackStack) { getRateBeerActivity().load(fragment, addToBackStack); } /** * Convenience method that start the command execution in this fragment's activity * @param command The command to execute */ protected void execute(Command command) { if (getRateBeerActivity() != null) getRateBeerActivity().execute(this, command); } @Override public boolean isBound() { return getActivity() != null; } @Override public void onTaskFailureResult(CommandFailureResult result) {} @Override public void onTaskSuccessResult(CommandSuccessResult result) {} /** * Publish an exception that occurred during the execution of a forum command * @param textview The TextView to show the error on, or null if not applicable * @param exception The exception that occurred */ protected void publishException(TextView textview, ApiException exception) { String message = ""; switch (exception.getType()) { case Offline: message = getText(R.string.error_offline).toString(); break; case AuthenticationFailed: message = getText(R.string.error_authenticationfailed).toString(); break; case CommandFailed: message = getText(R.string.error_commandfailed).toString(); break; case ConnectionError: message = getText(R.string.error_connectionfailure).toString(); break; } publishException(textview, message); } /** * Publish an exception to the user as a toast and possibly to a text * view as well. * @param textview The TextView to show the error on, or null if not applicable * @param message The (readily translated) message to show */ protected void publishException(TextView textview, String message) { // Show a toast message with the error Crouton.makeText(getActivity(), message, Style.INFO).show(); // Show the error on the given TextView as well if (textview != null) { textview.setText(message); } } protected ApplicationSettings getSettings() { return applicationSettings; } protected UserSettings getUser() { if (applicationSettings == null) return null; return applicationSettings.getUserSettings(); } private RateBeerActivity getRateBeerActivity() { return (RateBeerActivity) getActivity(); } }