package org.droidplanner.android.view.spinnerWheel;
import java.util.LinkedList;
import java.util.List;
import org.beyene.sius.unit.Unit;
import org.droidplanner.android.R;
import org.droidplanner.android.view.spinnerWheel.adapters.AbstractWheelTextAdapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
* Wraps the horizontal spinner wheel, and its title within a view.
*/
public class CardWheelHorizontalView<T> extends LinearLayout implements OnWheelChangedListener,
OnWheelClickedListener, OnWheelScrollListener {
private final static String TAG = CardWheelHorizontalView.class.getSimpleName();
public interface OnCardWheelScrollListener<T> {
void onScrollingStarted(CardWheelHorizontalView cardWheel, T startValue);
void onScrollingUpdate(CardWheelHorizontalView cardWheel, T oldValue, T newValue);
void onScrollingEnded(CardWheelHorizontalView cardWheel, T startValue, T endValue);
}
private final List<OnCardWheelScrollListener<T>> mScrollingListeners = new LinkedList<>();
private View mVerticalDivider;
private View mHorizontalDivider;
private TextView mTitleView;
private EditText mNumberInputText;
private WheelHorizontalView<T> mSpinnerWheel;
private T scrollingStartValue;
public CardWheelHorizontalView(Context context) {
this(context, null);
}
public CardWheelHorizontalView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CardWheelHorizontalView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(context, attrs);
}
private void initialize(final Context context, AttributeSet attrs) {
final TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.CardWheelHorizontalView, 0, 0);
try {
// Setup the container view.
setBackgroundResource(R.drawable.bg_cell_white);
// Setup the children views
final LayoutInflater inflater = LayoutInflater.from(context);
// Setup the divider view
mVerticalDivider = inflater.inflate(R.layout.card_title_vertical_divider, this, false);
mHorizontalDivider = inflater.inflate(R.layout.card_title_horizontal_divider, this, false);
// Setup the title view
mTitleView = (TextView) inflater.inflate(R.layout.card_wheel_horizontal_view_title, this, false);
mTitleView.setText(a.getString(R.styleable.CardWheelHorizontalView_android_text));
final int orientation = a.getInt(R.styleable.CardWheelHorizontalView_android_orientation, VERTICAL);
if (orientation == HORIZONTAL) {
setOrientation(HORIZONTAL);
} else {
setOrientation(VERTICAL);
}
updateTitleLayout();
// Setup the spinnerwheel view
final View spinnerWheelFrame = inflater.inflate(R.layout.card_wheel_horizontal_view, this, false);
addView(spinnerWheelFrame);
mSpinnerWheel = (WheelHorizontalView) spinnerWheelFrame.findViewById(R.id.horizontalSpinnerWheel);
mSpinnerWheel.addChangingListener(this);
mSpinnerWheel.addClickingListener(this);
mSpinnerWheel.addScrollingListener(this);
mNumberInputText = (EditText) spinnerWheelFrame.findViewById(R.id.numberInputText);
mNumberInputText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
mNumberInputText.selectAll();
} else {
hideSoftInput();
}
}
});
mNumberInputText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
hideSoftInput();
final CharSequence input = v.getText();
if (input != null) {
AbstractWheelTextAdapter<T> viewAdapter = mSpinnerWheel.getViewAdapter();
final T update = viewAdapter.parseItemText(input);
final int updateIndex = viewAdapter.getItemIndex(update);
if (updateIndex == -1) {
Toast.makeText(context, "Entered value is outside of the allowed range.",
Toast.LENGTH_LONG).show();
} else {
setCurrentItemIndex(updateIndex, true);
}
}
return true;
}
return false;
}
});
} finally {
a.recycle();
}
}
/**
* Called after the orientation, and/or title is set in order to update the
* view layout.
*/
private void updateTitleLayout() {
if (mTitleView == null || mVerticalDivider == null || mHorizontalDivider == null) {
return;
}
final int childCount = getChildCount();
if (mTitleView.length() > 0) {
final View divider = getOrientation() == VERTICAL ? mVerticalDivider : mHorizontalDivider;
if (childCount <= 1) {
addView(mTitleView, 0);
addView(divider, 1);
} else {
if (getChildAt(1) != divider) {
removeViewAt(1);
addView(divider, 1);
}
}
} else if (childCount > 1) {
removeViewAt(0);
removeViewAt(1);
}
}
@Override
public void setOrientation(int orientation) {
super.setOrientation(orientation);
updateTitleLayout();
}
public void setViewAdapter(AbstractWheelTextAdapter<T> adapter) {
mSpinnerWheel.setViewAdapter(adapter);
}
public void setCurrentValue(T value) {
mSpinnerWheel.setCurrentItem(mSpinnerWheel.getViewAdapter().getItemIndex(value));
}
public T getCurrentValue() {
return mSpinnerWheel.getViewAdapter().getItem(mSpinnerWheel.getCurrentItem());
}
private T getValue(int valueIndex) {
return mSpinnerWheel.getViewAdapter().getItem(valueIndex);
}
private void setCurrentItemIndex(int index, boolean animated) {
mSpinnerWheel.setCurrentItem(index, animated);
}
public void setText(CharSequence title) {
mTitleView.setText(title);
updateTitleLayout();
}
public void setText(int titleRes) {
mTitleView.setText(titleRes);
updateTitleLayout();
}
public CharSequence getText() {
return mTitleView.getText();
}
public void addScrollListener(OnCardWheelScrollListener<T> listener) {
mScrollingListeners.add(listener);
}
public void removeChangingListener(OnCardWheelScrollListener<T> listener) {
mScrollingListeners.remove(listener);
}
@Override
public void onChanged(AbstractWheel wheel, int oldIndex, int newIndex) {
final T oldValue = getValue(oldIndex);
final T newValue = getValue(newIndex);
for (OnCardWheelScrollListener<T> listener : mScrollingListeners) {
listener.onScrollingUpdate(this, oldValue, newValue);
}
}
@Override
public void onItemClicked(AbstractWheel wheel, int itemIndex, boolean isCurrentItem) {
if (isCurrentItem) {
final T currentValue = mSpinnerWheel.getViewAdapter().getItem(itemIndex);
showSoftInput(currentValue);
} else {
hideSoftInput();
setCurrentItemIndex(itemIndex, true);
}
}
@Override
public void onScrollingStarted(AbstractWheel wheel) {
hideSoftInput();
scrollingStartValue = getCurrentValue();
for(OnCardWheelScrollListener<T> listener: mScrollingListeners){
listener.onScrollingStarted(this, scrollingStartValue);
}
}
@Override
public void onScrollingFinished(AbstractWheel wheel) {
final T endValue = getCurrentValue();
for (OnCardWheelScrollListener<T> listener : mScrollingListeners) {
listener.onScrollingEnded(this, scrollingStartValue, endValue);
}
}
private void showSoftInput(T currentValue) {
final Context context = getContext();
final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
if(currentValue instanceof Unit)
mNumberInputText.setText(String.valueOf(((Unit)currentValue).getValue()));
else{
mNumberInputText.setText(currentValue.toString());
}
mNumberInputText.setVisibility(VISIBLE);
mNumberInputText.requestFocus();
imm.showSoftInput(mNumberInputText, 0);
}
}
private void hideSoftInput() {
final Context context = getContext();
final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null && imm.isActive(mNumberInputText)) {
imm.hideSoftInputFromWindow(mNumberInputText.getWindowToken(), 0);
mNumberInputText.setVisibility(INVISIBLE);
}
}
}