package com.barcicki.trio.core; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.widget.RelativeLayout; import com.barcicki.trio.R; import com.barcicki.trio.views.CardView; public class CardGrid extends RelativeLayout { private static int ID_OFFSET = 3123; private static int DEFAULT_NO_OF_COLUMNS = 4; private static int MAX_DEFAULT_NO_OF_COLUMNS = 5; private ArrayList<CardView> mCardViews = new ArrayList<CardView>(); private OnClickListener mOnClickListener = null; private CardList mCards = new CardList(); private boolean mForceColumns = false; private int mForcedColumns = 0; private boolean mRenderedViews = false; private int mWidth = 0; private int mHeight = 0; private AnimationListener mRevealCardAnimationListener; private int mOnMeasured = 0; public CardGrid(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public CardGrid(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public CardGrid(Context context) { super(context); // TODO Auto-generated constructor stub } public void setOnItemClickListener(OnClickListener listener) { mOnClickListener = listener; updateListener(); } public void clearCards() { mCards.clear(); mCardViews.clear(); removeAllViews(); } public void setCards(CardList cards) { mCards.clear(); mCardViews.clear(); removeAllViews(); if (cards != null) { mCards.addAll(cards); } int id = 1; for (Card card : cards) { CardView cardView = new CardView(getContext()); cardView.setId(ID_OFFSET + id++); cardView.setCard(card); cardView.setImageResource(R.drawable.square_reverse); cardView.setOnClickListener(mOnClickListener); addView(cardView); mCardViews.add(cardView); } // requestLayout(); // invalidate(); // if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) { // render(); // } else { // requestLayout(); // invalidate(); // refreshDrawableState(); // } // invalidate(); // refreshDrawableState(); } public void setCards(ArrayList<CardList> cards) { // mCards.clear(); // mCardViews.clear(); CardList sum = new CardList(); for (CardList list : cards) { sum.addAll(list); } setCards(sum); } public CardList getCards() { if (mCards == null) mCards = new CardList(); return mCards; } public CardList getCardsFromViews() { CardList set = new CardList(); for (CardView cv : mCardViews) { set.add(cv.getCard()); } return set; } public void forceColumnSize(Integer value) { if (value == null) { mForceColumns = false; } else { mForceColumns = true; mForcedColumns = value; } } public void render() { mRenderedViews = false; renderCards(getMeasuredWidth(), getMeasuredHeight()); } public int getColmuns() { if (mForceColumns) { return mForcedColumns; } else { return getDesiredColumnSize(getCards().size()); } } public void updateGrid(final CardList updatedCards) { CardList updated = new CardList(updatedCards); ArrayList<CardView> replaceable = new ArrayList<CardView>(); for (CardView cv : mCardViews) { Card c = cv.getCard(); if (!updated.contains(c)) { replaceable.add(cv); } else { updated.remove(c); } } if (Trio.LOCAL_LOGV) { Log.v("Classic Game", "Updated " + updated.size() + " " + updated.toString() + "; Replaceable " + replaceable.size()); } if (replaceable.size() == updated.size()) { for (int i = 0; i < replaceable.size(); i++) { CardView cv = replaceable.get(i); cv.animateSwitchCard(updated.get(i)); } } else { final Animation hide = AnimationUtils.loadAnimation(getContext(), R.anim.grid_hide); final Animation show = AnimationUtils.loadAnimation(getContext(), R.anim.grid_show); hide.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub setCards(updatedCards); render(); startAnimation(show); } }); startAnimation(hide); } } public void showReverse() { if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Hid " + mCardViews.size() + " cards"); for (CardView cv : mCardViews) { cv.setOverdraw(false); cv.invalidate(); cv.refreshDrawableState(); cv.setOnClickListener(null); } } public void hideReverse() { for (CardView cv : mCardViews) { cv.setOverdraw(true); cv.invalidate(); cv.refreshDrawableState(); cv.setOnClickListener(mOnClickListener); } } public CardView select(Card card) { for (CardView cv : mCardViews) { if (cv.getCard().equals(card)) { cv.setSelected(true); cv.invalidate(); cv.refreshDrawableState(); return cv; } } return null; } public void deselectAll() { for (CardView cv : mCardViews) { cv.setSelected(false); cv.invalidate(); cv.refreshDrawableState(); } } public void setResourceImageForAll(int resId) { for (CardView cv : mCardViews) { cv.setImageResource(resId); cv.invalidate(); cv.refreshDrawableState(); } } public void setRevealCardListener(AnimationListener animationListener) { mRevealCardAnimationListener = animationListener; } public void revealCard(CardList cardList) { int size = cardList.size(); int position = 0; while (position + size <= mCardViews.size()) { if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Try to reveal cards at " + position); List<CardView> cardViews = mCardViews.subList(position, position + size); CardList row = new CardList(); for (CardView cv : cardViews) { row.add(cv.getCard()); } if (CardList.areEqual(row, cardList)) { if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Found and revealing " + row); cardViews.get(0).setRevealAnimationListener( mRevealCardAnimationListener); for (CardView cv : cardViews) { cv.animateReveal(); } return; } position += size; } } public static int getDesiredColumnSize(int size) { if (size > Trio.DEFUALT_TABLE_SIZE) { return MAX_DEFAULT_NO_OF_COLUMNS; } else { return DEFAULT_NO_OF_COLUMNS; } } private void updateListener() { for (CardView cv : mCardViews) { cv.setOnClickListener(mOnClickListener); } } private int renderCards(int width, int height) { if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Render called: " + width + "x" + height); if (!mRenderedViews || mWidth != width || mHeight != height) { int cards_size = mCardViews.size(); if (cards_size > 0) { CardGridSize gridSize = CardGridSize.getGridSize(cards_size); int column_size = gridSize.getMaxRowSize(); int rows = gridSize.getRowsSize(); int size_by_height = (height / rows); int size_by_width = (width / column_size); int card_container = Math.min(size_by_height, size_by_width); int padding = (int) (5f / 100 * card_container); int card_size = card_container - 2 * padding; int available_width = width - card_container * column_size; int available_height = height - card_container * rows; int padding_horizontal = padding; int padding_vertical = padding; if (available_width > 0) { padding_horizontal += available_width / (2 * column_size); } if (available_height > 0) { padding_vertical += available_height / (2 * rows); } if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Size: " + card_size + " Padding Top/Bottom: " + padding_vertical + " Padding Left/Right: " + padding_horizontal); int position = 0; for (CardView cv : mCardViews) { int row = gridSize.getRow(position); int column = gridSize.getColumn(position); if (Trio.LOCAL_LOGD) Log.d("CardGrid", "Row: " + row + " Columnd: " + column); position++; // int real_padding_horizontal = padding_horizontal; if (!gridSize.isRowFull(row)) { int row_size = gridSize.getRowSize(row); real_padding_horizontal = padding + ((width - card_container * row_size) / (2 * row_size)); } LayoutParams params = new LayoutParams(card_size, card_size); params.addRule(ALIGN_PARENT_LEFT, TRUE); params.addRule(ALIGN_PARENT_TOP, TRUE); params.setMargins( real_padding_horizontal + (column * (2 * real_padding_horizontal + card_size)), padding_vertical + (row * (2 * padding_vertical + card_size)), real_padding_horizontal, padding_vertical); cv.setLayoutParams(params); } mHeight = height; mWidth = width; mRenderedViews = true; return card_size; } } return -1; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (Trio.LOCAL_LOGD) Log.d("CardGrid", "onMeasure " + widthSize + "x" + heightSize + " called " + (++mOnMeasured) + " time"); setMeasuredDimension(widthSize, heightSize); renderCards(widthSize, heightSize); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public void setEmptyCardList(int quantity) { mCards.clear(); mCardViews.clear(); removeAllViews(); int id = 1; for (int i = 0; i < quantity; i++) { CardView cardView = new CardView(getContext()); cardView.setId(ID_OFFSET + id++); cardView.setCard(null); cardView.setImageResource(R.drawable.square_reverse); cardView.setOnClickListener(mOnClickListener); addView(cardView); mCardViews.add(cardView); } } public void setCardsToCardViews(CardList cards, int startIndex) { int size = cards.size(); for (int i = 0; i < size; i++) { mCardViews.get(i + startIndex).setCard(cards.get(i)); } } }