package de.westnordost.streetcomplete.location;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Animatable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.widget.ImageButton;
import java.util.Arrays;
import de.westnordost.streetcomplete.R;
/**
* An image button which shows the current location state
*/
public class LocationStateButton extends ImageButton
{
// must be defined in the same order as the LocationState enum (but minus the first)
private static final int[] STATES = {
R.attr.state_allowed,
R.attr.state_enabled,
R.attr.state_searching,
R.attr.state_updating,
};
// must also be defined in the same order as LocationState enum (but minus the first)
private static final int[] STYLEABLES = {
R.styleable.LocationStateButton_state_allowed,
R.styleable.LocationStateButton_state_enabled,
R.styleable.LocationStateButton_state_searching,
R.styleable.LocationStateButton_state_updating,
};
private LocationState state;
private ColorStateList tint;
public LocationStateButton(Context context)
{
this(context, null);
}
public LocationStateButton(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public LocationStateButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LocationStateButton);
state = determineStateFrom(a);
tint = a.getColorStateList(R.styleable.LocationStateButton_tint);
a.recycle();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LocationStateButton(Context context, AttributeSet attrs, int defStyle, int defStyleRes)
{
super(context, attrs, defStyle, defStyleRes);
TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.LocationStateButton,
defStyle, defStyleRes);
state = determineStateFrom(a);
a.recycle();
refreshDrawableState();
}
private LocationState determineStateFrom(TypedArray a)
{
for(int i=STYLEABLES.length-1; i>=0; --i)
{
if(a.getBoolean(STYLEABLES[i], false)) return LocationState.values()[i+1];
}
return LocationState.DENIED;
}
@Override protected void drawableStateChanged()
{
super.drawableStateChanged();
// autostart
if(getDrawable().getCurrent() instanceof Animatable)
{
Animatable animatable = (Animatable) getDrawable().getCurrent();
if(!animatable.isRunning()) animatable.start();
}
if (tint != null && tint.isStateful())
{
setColorFilter(tint.getColorForState(getDrawableState(), 0));
}
}
public void setState(LocationState state)
{
if(state == this.state) return;
this.state = state;
refreshDrawableState();
}
public LocationState getState()
{
if(state == null) return LocationState.DENIED;
return state;
}
@Override
public int[] onCreateDrawableState(int extraSpace)
{
final int[] drawableState = super.onCreateDrawableState(extraSpace + STATES.length);
int arrPos = getState().ordinal();
if (arrPos > 0)
{
mergeDrawableStates(drawableState, Arrays.copyOf(STATES, arrPos));
}
return drawableState;
}
@Override
public Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.state = getState();
ss.activated = isActivated();
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable s)
{
SavedState ss = (SavedState) s;
super.onRestoreInstanceState(ss.getSuperState());
this.state = ss.state;
setActivated(ss.activated);
requestLayout();
}
static class SavedState extends BaseSavedState
{
LocationState state;
boolean activated;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in)
{
super(in);
state = LocationState.valueOf(in.readString());
activated = in.readInt() == 1;
}
@Override public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeString(state.name());
out.writeInt(activated ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}