/*
* 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();
}
}