ca.ualberta.cmput301w14t08.geochan.activities.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for ca.ualberta.cmput301w14t08.geochan.activities.MainActivity.java

Source

/*
 * Copyright 2014 Artem Chikin
 * Copyright 2014 Artem Herasymchuk
 * Copyright 2014 Tom Krywitsky
 * Copyright 2014 Henry Pabst
 * Copyright 2014 Bradley Simons
 * 
 * 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 ca.ualberta.cmput301w14t08.geochan.activities;

import java.util.List;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import ca.ualberta.cmput301w14t08.geochan.R;
import ca.ualberta.cmput301w14t08.geochan.fragments.CustomLocationFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.EditFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.FavouritesFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.MapViewFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.PostFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.ThreadListFragment;
import ca.ualberta.cmput301w14t08.geochan.helpers.ConnectivityHelper;
import ca.ualberta.cmput301w14t08.geochan.helpers.Toaster;
import ca.ualberta.cmput301w14t08.geochan.managers.CacheManager;
import ca.ualberta.cmput301w14t08.geochan.managers.PreferencesManager;
import ca.ualberta.cmput301w14t08.geochan.managers.ThreadManager;
import ca.ualberta.cmput301w14t08.geochan.models.GeoLocationLog;

/**
 * Inflates the default fragment and handles some of the crucial controller methods.
 * Initializes most of our singleton classes so attempting to fetch an instance of 
 * one does not return null.
 * 
 * @author Artem Chikin
 * @author Henry Pabst
 * @author Artem Herasymchuk
 */
public class MainActivity extends FragmentActivity implements OnBackStackChangedListener {

    /**
     * Sets up the initial state of the activity. Initializes singleton classes
     * and a ThreadListFragment to view the app's thread list.
     * @param savedInstanceState the saved instance state bundle
     */

    // TODO Fix logic in fragments
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState != null) {
            return;
        }
        // DO NOT DELETE THE LINES BELOW OR THIS APP WILL CRASH, THESE SINGLETON
        // CLASSES HAVE TO BE INITIALIZED BEFORE ANYTHING ELSE.
        ConnectivityHelper.generateInstance(this);
        Toaster.generateInstance(this);
        PreferencesManager.generateInstance(this);
        CacheManager.generateInstance(this);
        GeoLocationLog.generateInstance(this);
        ThreadManager.generateInstance(this);
        ThreadListFragment fragment = new ThreadListFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, fragment, "threadListFrag")
                .commit();
        getSupportFragmentManager().addOnBackStackChangedListener(this);
    }

    /**
     * Inflates this activity's action bar options.
     * @param menu the menu
     * @return the result
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /**
     * Handles the selection of specific action bar items according
     * to which item was selected.
     * @param item the item selected
     * @return the result
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_settings:
            Intent intent = new Intent(this.getBaseContext(), PreferencesActivity.class);
            startActivity(intent);
            return true;

        case R.id.action_favourites:
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new FavouritesFragment(), "favouritesFrag")
                    .addToBackStack(null).commit();

            // This next line is necessary for JUnit to see fragments
            getSupportFragmentManager().executePendingTransactions();
            return true;

        case R.id.action_add_thread:
            PostFragment frag = new PostFragment();
            Bundle bundle = new Bundle();
            bundle.putLong("id", -1);
            frag.setArguments(bundle);
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, frag, "postFrag")
                    .addToBackStack(null).commit();

            // This next line is necessary for JUnit to see fragments
            getSupportFragmentManager().executePendingTransactions();
            return true;

        case android.R.id.home:
            if (!returnBackStackImmediate(getSupportFragmentManager())) {
                getSupportFragmentManager().popBackStack();
            }
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Re-registers the OnBackStackChangedListener as it does not survive
     * the destruction of the Activity. 
     */
    @Override
    public void onResume() {
        super.onResume();
        getSupportFragmentManager().addOnBackStackChangedListener(this);
        checkActionBar();
    }

    /**
     * Checks the back stack for fragments and enables/disables the back button
     * in the action bar accordingly
     */
    @Override
    public void onBackStackChanged() {
        checkActionBar();
    }

    /**
     * Overrides the back button to work with nested fragments
     */
    @Override
    public void onBackPressed() {
        if (!returnBackStackImmediate(getSupportFragmentManager())) {
            super.onBackPressed();
        }
    }

    /**
     * Checks the back stack for fragments and enables/disables the back button
     * in the action bar accordingly
     */
    private void checkActionBar() {
        int count = getSupportFragmentManager().getBackStackEntryCount();
        if (count > 0) {
            getActionBar().setDisplayHomeAsUpEnabled(true);
        } else {
            getActionBar().setDisplayHomeAsUpEnabled(false);
        }
    }

    /**
     * Propagates a back button press down to our nested fragment manager
     * and its fragments.
     * @param fm the Fragment Manager
     * @return true if the back stack was returned from successfully,
     * false if not
     */
    private boolean returnBackStackImmediate(FragmentManager fm) {
        // HACK: propagate back button press to child fragments.
        // This might not work properly when you have multiple fragments adding
        // multiple children to the back stack.
        // (in our case, only one child fragments adds fragments to the back stack,
        // so we're fine with this)
        //
        // This code was taken from the web site:
        // http://android.joao.jp/2013/09/back-stack-with-nested-fragments-back.html
        // Accessed on March 21, 2014
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null && fragments.size() > 0) {
            for (Fragment fragment : fragments) {
                if (fragment != null && fragment.getChildFragmentManager() != null) {
                    if (fragment.getChildFragmentManager().getBackStackEntryCount() > 0) {
                        if (fragment.getChildFragmentManager().popBackStackImmediate()) {
                            return true;
                        } else {
                            return returnBackStackImmediate(fragment.getChildFragmentManager());
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * Calls the respective post new thread method in the fragment.
     * 
     * @param view
     *            View passed to the activity to check which button was pressed
     */
    public void post(View view) {
        getSupportFragmentManager();
        PostFragment fragment = (PostFragment) getSupportFragmentManager().findFragmentByTag("postFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (PostFragment) favFrag.getChildFragmentManager().findFragmentByTag("postFrag");
        }
        fragment.post(view);
    }

    /**
     * Calls the respective attach image method in the running PostFragment.
     * @param view View passed to the activity to check which button was pressed.
     */
    public void attachImage(View view) {
        PostFragment fragment = (PostFragment) getSupportFragmentManager().findFragmentByTag("postFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (PostFragment) favFrag.getChildFragmentManager().findFragmentByTag("postFrag");
        }
        fragment.attachImage(view);
    }

    /**
     * Method called when the Edit Image button is pressed in EditFragment. Finds the
     * appropriate fragment and calls editImage on it.
     * @param view The View passed to the activity to check which button was pressed.
     */
    public void editImage(View view) {
        EditFragment fragment = (EditFragment) getSupportFragmentManager().findFragmentByTag("editFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (EditFragment) favFrag.getChildFragmentManager().findFragmentByTag("editFrag");
        }
        fragment.editImage(view);
    }

    /**
     * Method called when the Post Edit button is pressed in EditFragment.
     * Finds the appropriate fragment and calls makeEdit on it.
     * @param view
     */
    public void makeEdit(View view) {
        EditFragment fragment = (EditFragment) getSupportFragmentManager().findFragmentByTag("editFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (EditFragment) favFrag.getChildFragmentManager().findFragmentByTag("editFrag");
        }
        fragment.makeEdit(view);
    }

    /**
     * Calls the respective change location method in the fragment.
     * 
     * @param view
     *            View passed to the activity to check which button was pressed
     */
    public void changeLocation(View view) {
        Bundle args = new Bundle();
        if (view.getId() == R.id.location_button) {
            args.putInt("postType", CustomLocationFragment.POST);
        } else if (view.getId() == R.id.edit_location_button) {
            args.putInt("postType", CustomLocationFragment.EDIT);
        }
        CustomLocationFragment frag = new CustomLocationFragment();
        frag.setArguments(args);
        FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                .findFragmentByTag("favouritesFrag");
        if (favFrag != null) {
            //This bit here solves the issue of a crash when changing location
            //in a reply to a comment in a favourited thread.
            FragmentManager childMan = favFrag.getChildFragmentManager();
            childMan.beginTransaction().replace(R.id.container, frag, "customLocFrag").addToBackStack(null)
                    .commit();
        } else {
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, frag, "customLocFrag")
                    .addToBackStack(null).commit();
            getSupportFragmentManager().executePendingTransactions();
        }
    }

    /**
     * Calls the respective submit location method in the fragment.
     * 
     * @param view
     *            View passed to the activity to check which button was pressed
     */
    public void submitLocation(View view) {
        CustomLocationFragment fragment = (CustomLocationFragment) getSupportFragmentManager()
                .findFragmentByTag("customLocFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (CustomLocationFragment) favFrag.getChildFragmentManager()
                    .findFragmentByTag("customLocFrag");
        }
        fragment.submitNewLocation(view);
    }

    /**
     * Calls the respective submit location method in the fragment.
     * 
     * @param view
     *            View passed to the activity to check which button was pressed
     */
    public void submitCurrentLocation(View view) {
        CustomLocationFragment fragment = (CustomLocationFragment) getSupportFragmentManager()
                .findFragmentByTag("customLocFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (CustomLocationFragment) favFrag.getChildFragmentManager()
                    .findFragmentByTag("customLocFrag");
        }
        fragment.submitCurrentLocation(view);
    }

    /**
     * Called when the get_directions_button is clicked in MapViewFragment. Finds the
     * fragment where the button was clicked and calls getDirections on it.
     * @param view View passed to the activity to determine which button was pressed.
     */
    public void getDirections(View view) {
        MapViewFragment fragment = (MapViewFragment) getSupportFragmentManager().findFragmentByTag("mapFrag");
        if (fragment == null) {
            FavouritesFragment favFrag = (FavouritesFragment) getSupportFragmentManager()
                    .findFragmentByTag("favouritesFrag");
            fragment = (MapViewFragment) favFrag.getChildFragmentManager().findFragmentByTag("mapFrag");
        }
        fragment.getDirections();
    }
}