/*
* CentralMapExtraFragment.java
* Copyright (C) 2015 Nicholas Killewald
*
* This file is distributed under the terms of the BSD license.
* The source package should have a LICENSE file at the toplevel.
*/
package net.exclaimindustries.geohashdroid.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import com.google.android.gms.location.LocationListener;
import net.exclaimindustries.geohashdroid.activities.DetailedInfoActivity;
import net.exclaimindustries.geohashdroid.activities.WikiActivity;
import net.exclaimindustries.geohashdroid.util.Info;
import net.exclaimindustries.geohashdroid.util.PermissionsDeniedListener;
/**
* This is the base class from which the two extra Fragments {@link net.exclaimindustries.geohashdroid.activities.CentralMap}
* can use derive. It simply allows better communication between them and
* {@link net.exclaimindustries.geohashdroid.util.ExpeditionMode}.
*/
public abstract class CentralMapExtraFragment
extends BaseGHDThemeFragment
implements LocationListener, PermissionsDeniedListener {
/**
* The various types of CentralMapExtraFragment that can exist. It's either
* this or a mess of instanceof checks to see what's currently showing.
*/
public enum FragmentType {
/** The Detailed Info fragment. */
DETAILS,
/** The Wiki fragment. */
WIKI
}
/** The bundle key for the Info. */
public final static String INFO = "info";
/**
* The bundle key for if permissions were explicitly denied coming into the
* fragment.
*/
public final static String PERMISSIONS_DENIED = "permissionsDenied";
/**
* Now, what you've got here is your garden-variety interface that something
* ought to implement to handle the close button on this here fragment.
*/
public interface CloseListener {
/**
* Called when the user clicks the close button. Use this opportunity
* to either dismiss the fragment or close the activity that contains
* it.
*
* @param fragment the CentralMapExtraFragment that is about to be closed
*/
void extraFragmentClosing(CentralMapExtraFragment fragment);
/**
* Called during onDestroy(). ExpeditionMode needs this so it knows
* when the user backed out of the fragment, as opposed to just the
* close button.
*
* @param fragment the CentralMapExtraFragment that is being destroyed
*/
void extraFragmentDestroying(CentralMapExtraFragment fragment);
}
protected CloseListener mCloseListener;
protected Info mInfo;
protected boolean mPermissionsDenied;
/**
* Sets what'll be listening for the close button and/or an onDestroy event.
*
* @param listener some CloseListener somewhere
*/
public void setCloseListener(CloseListener listener) {
mCloseListener = listener;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// First, see if there's an instance state.
if(savedInstanceState != null) {
// If so, use what's in there.
mInfo = savedInstanceState.getParcelable(INFO);
mPermissionsDenied = savedInstanceState.getBoolean(PERMISSIONS_DENIED, false);
} else {
// If not, go to the arguments.
Bundle args = getArguments();
if(args != null) {
mInfo = args.getParcelable(INFO);
mPermissionsDenied = args.getBoolean(PERMISSIONS_DENIED, false);
}
}
}
@Override
public void onDestroy() {
// The parent needs to know when this fragment is destroyed so it can
// make the FrameLayout go away.
if(mCloseListener != null)
mCloseListener.extraFragmentDestroying(this);
super.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Remember that last info. Owing to how ExpeditionMode works, it might
// have changed since arguments time. If it DIDN'T change, well, it'll
// be the same as the arguments anyway.
outState.putParcelable(INFO, mInfo);
outState.putBoolean(PERMISSIONS_DENIED, mPermissionsDenied);
}
/**
* Registers a button (or, well, a {@link View} in general) to act as the
* close button, calling the close method on the CloseListener.
*
* @param v the View that will act as the close button
*/
protected void registerCloseButton(@NonNull View v) {
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mCloseListener != null)
mCloseListener.extraFragmentClosing(CentralMapExtraFragment.this);
}
});
}
/**
* Sets the Info for this fragment, to whatever degree that's useful for it.
* Whatever gets set here will override any arguments originally passed in
* if and when onSaveInstanceState is needed.
*
* @param info that new Info
*/
public void setInfo(@Nullable final Info info) {
mInfo = info;
}
/**
* Gets what type of CentralMapExtraFragment this is so you don't have to
* keep using instanceof. Stop that.
*
* @return a FragmentType enum
*/
@NonNull
public abstract FragmentType getType();
/**
* Static factory that makes an Intent for a given FragmentType's Activity
* container. This happens if the user's on a phone.
*
* @param type the type
* @return one factory-direct Intent
*/
@NonNull
public static Intent makeIntentForType(Context c, FragmentType type) {
switch(type) {
case DETAILS:
return new Intent(c, DetailedInfoActivity.class);
case WIKI:
return new Intent(c, WikiActivity.class);
}
throw new RuntimeException("I don't know what sort of FragmentType " + type + " is supposed to be!");
}
/**
* Static factory that makes a Fragment for a given FragmentType. This
* happens if the user's on a tablet.
*
* @param type the type
* @return a fragment
*/
public static CentralMapExtraFragment makeFragmentForType(FragmentType type) {
switch(type) {
case DETAILS:
return new DetailedInfoFragment();
case WIKI:
return new WikiFragment();
}
throw new RuntimeException("I don't know what sort of FragmentType " + type + " is supposed to be!");
}
}