/*
* Copyright (C) 2015 Hippo Seven
*
* 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 com.hippo.ehviewer.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.hippo.easyrecyclerview.EasyRecyclerView;
import com.hippo.easyrecyclerview.MarginItemDecoration;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.client.data.ListUrlBuilder;
import com.hippo.ehviewer.client.exception.EhException;
import com.hippo.ripple.Ripple;
import com.hippo.widget.RadioGridGroup;
import com.hippo.yorozuya.ViewUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnCheckedChangeListener,
View.OnClickListener, ImageSearchLayout.Helper {
@IntDef({SEARCH_MODE_NORMAL, SEARCH_MODE_IMAGE})
@Retention(RetentionPolicy.SOURCE)
private @interface SearchMode {}
private static final String STATE_KEY_SUPER = "super";
private static final String STATE_KEY_SEARCH_MODE = "search_mode";
private static final String STATE_KEY_ENABLE_ADVANCE = "enable_advance";
public static final int SEARCH_MODE_NORMAL = 0;
public static final int SEARCH_MODE_IMAGE = 1;
private static final int ITEM_TYPE_NORMAL = 0;
private static final int ITEM_TYPE_NORMAL_ADVANCE = 1;
private static final int ITEM_TYPE_IMAGE = 2;
private static final int ITEM_TYPE_ACTION = 3;
private static final int[] SEARCH_ITEM_COUNT_ARRAY = {
3, 2
};
private static final int[][] SEARCH_ITEM_TYPE = {
{ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION}, // SEARCH_MODE_NORMAL
{ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION}, // SEARCH_MODE_IMAGE
};
private LayoutInflater mInflater;
private int mSearchMode = SEARCH_MODE_NORMAL;
private boolean mEnableAdvance = false;
private View mNormalView;
private CategoryTable mCategoryTable;
private RadioGridGroup mNormalSearchMode;
private ImageView mNormalSearchModeHelp;
private SwitchCompat mEnableAdvanceSwitch;
private View mAdvanceView;
private AdvanceSearchTable mTableAdvanceSearch;
private ImageSearchLayout mImageView;
private View mActionView;
private TextView mAction;
private LinearLayoutManager mLayoutManager;
private SearchAdapter mAdapter;
private Helper mHelper;
public SearchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SearchLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
@SuppressLint("InflateParams")
private void init(Context context) {
Resources resources = context.getResources();
mInflater = LayoutInflater.from(context);
mLayoutManager = new LinearLayoutManager(context);
mAdapter = new SearchAdapter();
setLayoutManager(mLayoutManager);
setAdapter(mAdapter);
setHasFixedSize(true);
setClipToPadding(false);
int interval = resources.getDimensionPixelOffset(R.dimen.search_layout_interval);
int paddingH = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_h);
int paddingV = resources.getDimensionPixelOffset(R.dimen.search_layout_margin_v);
MarginItemDecoration decoration = new MarginItemDecoration(
interval, paddingH, paddingV, paddingH, paddingV);
addItemDecoration(decoration);
decoration.applyPaddings(this);
// Create normal view
View normalView = mInflater.inflate(R.layout.search_normal, null);
mNormalView = normalView;
mCategoryTable = (CategoryTable) normalView.findViewById(R.id.search_category_table);
mNormalSearchMode = (RadioGridGroup) normalView.findViewById(R.id.normal_search_mode);
mNormalSearchModeHelp = (ImageView) normalView.findViewById(R.id.normal_search_mode_help);
mEnableAdvanceSwitch = (SwitchCompat) normalView.findViewById(R.id.search_enable_advance);
mNormalSearchModeHelp.setOnClickListener(this);
Ripple.addRipple(mNormalSearchModeHelp, false);
mEnableAdvanceSwitch.setOnCheckedChangeListener(SearchLayout.this);
mEnableAdvanceSwitch.setSwitchPadding(resources.getDimensionPixelSize(R.dimen.switch_padding));
// Create advance view
mAdvanceView = mInflater.inflate(R.layout.search_advance, null);
mTableAdvanceSearch = (AdvanceSearchTable) mAdvanceView.findViewById(R.id.search_advance_search_table);
// Create image view
mImageView = (ImageSearchLayout) mInflater.inflate(R.layout.search_image, null);
mImageView.setHelper(this);
// Create action view
mActionView = mInflater.inflate(R.layout.search_action, null);
mAction = (TextView) mActionView.findViewById(R.id.action);
mAction.setOnClickListener(this);
}
public void setHelper(Helper helper) {
mHelper = helper;
}
public void scrollSearchContainerToTop() {
mLayoutManager.scrollToPositionWithOffset(0, 0);
}
public void setImageUri(Uri imageUri) {
mImageView.setImageUri(imageUri);
}
@Override
public void onSelectImage() {
if (mHelper != null) {
mHelper.onSelectImage();
}
}
@Override
protected void dispatchSaveInstanceState(@NonNull SparseArray<Parcelable> container) {
super.dispatchSaveInstanceState(container);
mNormalView.saveHierarchyState(container);
mAdvanceView.saveHierarchyState(container);
mImageView.saveHierarchyState(container);
mActionView.saveHierarchyState(container);
}
@Override
protected void dispatchRestoreInstanceState(@NonNull SparseArray<Parcelable> container) {
super.dispatchRestoreInstanceState(container);
mNormalView.restoreHierarchyState(container);
mAdvanceView.restoreHierarchyState(container);
mImageView.restoreHierarchyState(container);
mActionView.restoreHierarchyState(container);
}
@Override
public Parcelable onSaveInstanceState() {
final Bundle state = new Bundle();
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
state.putInt(STATE_KEY_SEARCH_MODE, mSearchMode);
state.putBoolean(STATE_KEY_ENABLE_ADVANCE, mEnableAdvance);
return state;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
final Bundle savedState = (Bundle) state;
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
mSearchMode = savedState.getInt(STATE_KEY_SEARCH_MODE);
mEnableAdvance = savedState.getBoolean(STATE_KEY_ENABLE_ADVANCE);
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView == mEnableAdvanceSwitch) {
mEnableAdvance = isChecked;
if (mSearchMode == SEARCH_MODE_NORMAL) {
if (isChecked) {
mAdapter.notifyItemInserted(1);
} else {
mAdapter.notifyItemRemoved(1);
}
if (mHelper != null) {
mHelper.onChangeSearchMode();
}
}
}
}
public boolean isSpecifyGallery() {
return R.id.search_specify_gallery == mNormalSearchMode.getCheckedRadioButtonId();
}
public void formatListUrlBuilder(ListUrlBuilder urlBuilder, String query) throws EhException {
urlBuilder.reset();
switch (mSearchMode) {
case SEARCH_MODE_NORMAL:
int nsMode = mNormalSearchMode.getCheckedRadioButtonId();
switch (nsMode) {
default:
case R.id.search_normal_search:
urlBuilder.setMode(ListUrlBuilder.MODE_NORMAL);
break;
case R.id.search_specify_uploader:
urlBuilder.setMode(ListUrlBuilder.MODE_UPLOADER);
break;
case R.id.search_specify_tag:
urlBuilder.setMode(ListUrlBuilder.MODE_TAG);
break;
}
urlBuilder.setKeyword(query);
urlBuilder.setCategory(mCategoryTable.getCategory());
if (mEnableAdvance) {
urlBuilder.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
urlBuilder.setMinRating(mTableAdvanceSearch.getMinRating());
}
break;
case SEARCH_MODE_IMAGE:
urlBuilder.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
mImageView.formatListUrlBuilder(urlBuilder);
break;
}
}
public void setSearchMode(@SearchMode int searchMode, boolean animation) {
if (mSearchMode != searchMode) {
int oldItemCount = mAdapter.getItemCount();
mSearchMode = searchMode;
int newItemCount = mAdapter.getItemCount();
if (animation) {
mAdapter.notifyItemRangeRemoved(0, oldItemCount - 1);
mAdapter.notifyItemRangeInserted(0, newItemCount - 1);
} else {
mAdapter.notifyDataSetChanged();
}
if (mHelper != null) {
mHelper.onChangeSearchMode();
}
}
}
public void toggleSearchMode() {
int oldItemCount = mAdapter.getItemCount();
mSearchMode++;
if (mSearchMode > SEARCH_MODE_IMAGE) {
mSearchMode = SEARCH_MODE_NORMAL;
}
int newItemCount = mAdapter.getItemCount();
mAdapter.notifyItemRangeRemoved(0, oldItemCount - 1);
mAdapter.notifyItemRangeInserted(0, newItemCount - 1);
// Update action text
int resId;
switch (mSearchMode) {
default:
case SEARCH_MODE_NORMAL:
resId = R.string.image_search;
break;
case SEARCH_MODE_IMAGE:
resId = R.string.keyword_search;
break;
}
mAction.setText(resId);
if (mHelper != null) {
mHelper.onChangeSearchMode();
}
}
@Override
public void onClick(View v) {
if (mNormalSearchModeHelp == v) {
new AlertDialog.Builder(getContext())
.setMessage(R.string.search_tip)
.show();
} else if (mAction == v) {
toggleSearchMode();
}
}
private class SimpleHolder extends RecyclerView.ViewHolder {
public SimpleHolder(View itemView) {
super(itemView);
}
}
private class SearchAdapter extends EasyRecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public int getItemCount() {
int count = SEARCH_ITEM_COUNT_ARRAY[mSearchMode];
if (mSearchMode == SEARCH_MODE_NORMAL && !mEnableAdvance) {
count--;
}
return count;
}
@Override
public int getItemViewType(int position) {
int type = SEARCH_ITEM_TYPE[mSearchMode][position];
if (mSearchMode == SEARCH_MODE_NORMAL && position == 1 && !mEnableAdvance) {
type = ITEM_TYPE_ACTION;
}
return type;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == ITEM_TYPE_ACTION) {
ViewUtils.removeFromParent(mActionView);
mActionView.setLayoutParams(new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
int resId;
switch (mSearchMode) {
default:
case SEARCH_MODE_NORMAL:
resId = R.string.image_search;
break;
case SEARCH_MODE_IMAGE:
resId = R.string.keyword_search;
break;
}
mAction.setText(resId);
view = mActionView;
} else {
view = mInflater.inflate(R.layout.search_category, parent, false);
TextView title = (TextView) view.findViewById(R.id.category_title);
FrameLayout content = (FrameLayout) view.findViewById(R.id.category_content);
switch (viewType) {
case ITEM_TYPE_NORMAL:
title.setText(R.string.search_normal);
ViewUtils.removeFromParent(mNormalView);
content.addView(mNormalView);
break;
case ITEM_TYPE_NORMAL_ADVANCE:
title.setText(R.string.search_advance);
ViewUtils.removeFromParent(mAdvanceView);
content.addView(mAdvanceView);
break;
case ITEM_TYPE_IMAGE:
title.setText(R.string.search_image);
ViewUtils.removeFromParent(mImageView);
content.addView(mImageView);
break;
}
}
return new SimpleHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Empty, bind view in create view
}
}
public interface Helper {
void onChangeSearchMode();
void onSelectImage();
}
}