/*
* DetailedInfoFragment.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.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import net.exclaimindustries.geohashdroid.R;
import net.exclaimindustries.geohashdroid.util.GHDConstants;
import net.exclaimindustries.geohashdroid.util.Info;
import net.exclaimindustries.geohashdroid.util.UnitConverter;
import java.text.DateFormat;
/**
* The DetailedInfoFragment shows us some detailed info. It's Javadocs like
* this that really sell the whole concept, I know.
*/
public class DetailedInfoFragment extends CentralMapExtraFragment {
private TextView mDate;
private TextView mYouLat;
private TextView mYouLon;
private TextView mDestLat;
private TextView mDestLon;
private TextView mDistance;
private TextView mAccuracy;
private View mYouBlock;
private View mDistanceBlock;
private int mDefaultTextColor;
private Location mLastLocation;
private ClipboardManager mClipManager;
private View.OnLongClickListener mYouListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// Only allow this if we actually HAVE data.
if(mLastLocation == null) {
Toast.makeText(getActivity(), R.string.details_toast_no_location, Toast.LENGTH_SHORT).show();
} else {
String clipText = UnitConverter.makeLatitudeCoordinateString(getActivity(), mLastLocation.getLatitude(), false, UnitConverter.OUTPUT_DETAILED)
+ " "
+ UnitConverter.makeLongitudeCoordinateString(getActivity(), mLastLocation.getLongitude(), false, UnitConverter.OUTPUT_DETAILED);
// Let's see if I know how the clipboard works...
ClipData clip = ClipData.newPlainText(getString(R.string.details_clip_your_location), clipText);
mClipManager.setPrimaryClip(clip);
Toast.makeText(getActivity(), R.string.details_toast_your_location, Toast.LENGTH_SHORT).show();
}
return true;
}
};
private View.OnLongClickListener mDestListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// Same deal, only this time with the final destination.
if(mInfo == null) {
Toast.makeText(getActivity(), R.string.details_toast_stand_by, Toast.LENGTH_SHORT).show();
} else {
String clipText = UnitConverter.makeLatitudeCoordinateString(getActivity(), mInfo.getLatitude(), false, UnitConverter.OUTPUT_DETAILED)
+ " "
+ UnitConverter.makeLongitudeCoordinateString(getActivity(), mInfo.getLongitude(), false, UnitConverter.OUTPUT_DETAILED);
ClipData clip = ClipData.newPlainText(getString(R.string.details_clip_final_location, DateFormat.getDateInstance(DateFormat.LONG)
.format(mInfo.getCalendar().getTime())), clipText);
mClipManager.setPrimaryClip(clip);
Toast.makeText(getActivity(), R.string.details_toast_final_location, Toast.LENGTH_SHORT).show();
}
return true;
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.detail, container, false);
// Clipboard!
mClipManager = (ClipboardManager)getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
// TextViews!
mDate = (TextView)layout.findViewById(R.id.detail_date);
mYouLat = (TextView)layout.findViewById(R.id.you_lat);
mYouLon = (TextView)layout.findViewById(R.id.you_lon);
mDestLat = (TextView)layout.findViewById(R.id.dest_lat);
mDestLon = (TextView)layout.findViewById(R.id.dest_lon);
mDistance = (TextView)layout.findViewById(R.id.distance);
mAccuracy = (TextView)layout.findViewById(R.id.accuracy);
mYouBlock = layout.findViewById(R.id.you_block);
mDistanceBlock = layout.findViewById(R.id.distance_block);
// Long clicks!
mYouLat.setOnLongClickListener(mYouListener);
mYouLon.setOnLongClickListener(mYouListener);
mDestLat.setOnLongClickListener(mDestListener);
mDestLon.setOnLongClickListener(mDestListener);
// A color!
mDefaultTextColor = ContextCompat.getColor(getActivity(), (isNightMode() ? android.R.color.secondary_text_dark : android.R.color.secondary_text_light));
// Button!
Button closeButton = (Button) layout.findViewById(R.id.close);
// Button does a thing!
if(closeButton != null) registerCloseButton(closeButton);
updateDisplay();
return layout;
}
/**
* Sets the Info. If null, this will make it go to standby. Whatever gets
* set here will override any arguments originally passed in if and when
* onSaveInstanceState is needed.
*
* @param info the new Info
*/
public void setInfo(@Nullable final Info info) {
super.setInfo(info);
updateDisplay();
}
private void updateDisplay() {
// Good! This is almost the same as the InfoBox. It just has more
// detail and such.
Activity activity = getActivity();
if(activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
float accuracy = 0.0f;
if(mLastLocation != null) accuracy = mLastLocation.getAccuracy();
// If we can't get to the user's current location due to
// pesky permissions perils, just hide the relevant blocks.
// I mean, it'll be a somewhat sparse fragment, but it'll at
// least not have ugly Stand By lines all over.
if(mPermissionsDenied) {
mYouBlock.setVisibility(View.GONE);
mDistanceBlock.setVisibility(View.GONE);
} else {
mYouBlock.setVisibility(View.VISIBLE);
mDistanceBlock.setVisibility(View.VISIBLE);
}
// One by one, just like InfoBox! I mean, not JUST like it.
// We split the coordinate parts into different TextViews
// here, and we have the date to display, but other than
// THAT...
if(mInfo == null) {
mDestLat.setText(R.string.standby_title);
mDestLon.setText("");
mDate.setText("");
} else {
mDestLat.setText(UnitConverter.makeLatitudeCoordinateString(getActivity(), mInfo.getFinalLocation().getLatitude(), false, UnitConverter.OUTPUT_DETAILED));
mDestLon.setText(UnitConverter.makeLongitudeCoordinateString(getActivity(), mInfo.getFinalLocation().getLongitude(), false, UnitConverter.OUTPUT_DETAILED));
mDate.setText(DateFormat.getDateInstance(DateFormat.LONG).format(
mInfo.getCalendar().getTime()));
}
// Location and accuracy!
if(mLastLocation == null) {
mYouLat.setText(R.string.standby_title);
mYouLon.setText("");
mAccuracy.setText("");
} else {
mYouLat.setText(UnitConverter.makeLatitudeCoordinateString(getActivity(), mLastLocation.getLatitude(), false, UnitConverter.OUTPUT_DETAILED));
mYouLon.setText(UnitConverter.makeLongitudeCoordinateString(getActivity(), mLastLocation.getLongitude(), false, UnitConverter.OUTPUT_DETAILED));
mAccuracy.setText(getString(R.string.details_accuracy,
UnitConverter.makeDistanceString(getActivity(),
GHDConstants.ACCURACY_FORMAT, mLastLocation.getAccuracy())));
}
// Distance!
if(mLastLocation == null || mInfo == null) {
mDistance.setText(R.string.standby_title);
mDistance.setTextColor(mDefaultTextColor);
} else {
float distance = mLastLocation.distanceTo(mInfo.getFinalLocation());
mDistance.setText(UnitConverter.makeDistanceString(getActivity(), GHDConstants.DIST_FORMAT, distance));
// Plus, if we're close enough AND accurate enough, make the
// text be green. We COULD do this with geofencing
// callbacks and all, but, I mean, we're already HERE,
// aren't we?
if(accuracy < GHDConstants.LOW_ACCURACY_THRESHOLD && distance <= accuracy)
mDistance.setTextColor(ContextCompat.getColor(getActivity(), R.color.details_in_range));
else
mDistance.setTextColor(mDefaultTextColor);
}
}
});
}
}
@NonNull
@Override
public FragmentType getType() {
return FragmentType.DETAILS;
}
@Override
public void onLocationChanged(Location location) {
// Ding!
mLastLocation = location;
updateDisplay();
}
@Override
public void permissionsDenied(boolean denied) {
// Dong!
mPermissionsDenied = denied;
updateDisplay();
}
}