/*
Copyright (C) 2011 Haowen Ning
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.liberty.android.fantastischmemo.ui;
import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.liberty.android.fantastischmemo.common.AMEnv;
import org.liberty.android.fantastischmemo.R;
import org.liberty.android.fantastischmemo.common.BaseFragment;
import org.liberty.android.fantastischmemo.entity.Setting;
import org.liberty.android.fantastischmemo.utils.CardTextUtil;
import java.io.File;
import java.io.Serializable;
/*
* This class display a side of the card and export necessary callbacks.
*/
public class CardFragment extends BaseFragment {
public static final String EXTRA_CARD_TEXT = "cardText";
private String mCardText;
private LinearLayout rootView;
private TextView cardTextView;
private String fontFile = null;
private OnClickListener cardOnClickListener = null;
private OnLongClickListener cardOnLongClickListener = null;
private OnClickListener textOnClickListener = null;
private OnLongClickListener textOnLongClickListener = null;
private int fontSize = 24;
private Integer textColor = null;
private Integer backgroundColor = null;
private Setting.Align textAlignment = Setting.Align.CENTER;
private boolean displayInHtml = true;
private boolean htmlLinebreakConversion = false;
private CardTextUtil cardTextUtil;
private String[] imageSearchPaths = {AMEnv.DEFAULT_IMAGE_PATH};
// The dummy animation is used to handle the nested fragment animation disappearing bug
// See solution here:
// http://stackoverflow.com/questions/14900738/nested-fragments-disappear-during-transition-animation
private static final Animation dummyAnimation = new AlphaAnimation(1,1);
static {
dummyAnimation.setDuration(500);
}
public CardFragment() { }
// The argument set in the factory will stored in the private variable here.
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
mCardText = getArguments().getString(EXTRA_CARD_TEXT);
cardTextUtil = new CardTextUtil(appComponents(), imageSearchPaths);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.card_layout, container, false);
cardTextView = (TextView) v.findViewById(R.id.card_text_view);
rootView = (LinearLayout) v.findViewById(R.id.root);
cardTextView.setText(cardTextUtil.getSpannableText(mCardText, displayInHtml, htmlLinebreakConversion));
// Uncomment the line below for the text field to handle links.
// The line is commented out because it is not well tested.
// cardTextView.setMovementMethod(LinkMovementMethod.getInstance());
if (cardOnClickListener != null) {
rootView.setOnClickListener(cardOnClickListener);
}
if (cardOnLongClickListener != null) {
rootView.setOnLongClickListener(cardOnLongClickListener);
}
if (textOnClickListener != null) {
cardTextView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Make sure the link (set for text view autoLink="web") is not recognized as a click
if (((TextView) v).getSelectionStart() == -1 && ((TextView) v).getSelectionEnd() == -1) {
textOnClickListener.onClick(v);
}
}
});
}
if (textOnLongClickListener != null) {
cardTextView.setOnLongClickListener(textOnLongClickListener);
}
if (textColor != null) {
cardTextView.setTextColor(textColor);
}
if (backgroundColor != null) {
rootView.setBackgroundColor(backgroundColor);
}
if (fontFile != null && new File(fontFile).exists()) {
Typeface qt = Typeface.createFromFile(fontFile);
cardTextView.setTypeface(qt);
}
cardTextView.setTextSize(fontSize);
// It is tricky to set up the alignment of the text.
switch (textAlignment) {
case CENTER:
cardTextView.setGravity(Gravity.CENTER);
rootView.setGravity(Gravity.CENTER);
break;
case RIGHT:
cardTextView.setGravity(Gravity.RIGHT);
rootView.setGravity(Gravity.NO_GRAVITY);
break;
case LEFT:
cardTextView.setGravity(Gravity.LEFT);
rootView.setGravity(Gravity.NO_GRAVITY);
break;
case CENTER_LEFT:
cardTextView.setGravity(Gravity.LEFT);
rootView.setGravity(Gravity.CENTER);
break;
case CENTER_RIGHT:
cardTextView.setGravity(Gravity.RIGHT);
rootView.setGravity(Gravity.CENTER);
break;
default:
cardTextView.setGravity(Gravity.CENTER);
rootView.setGravity(Gravity.CENTER);
}
return v;
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
// Override onCreateAnimation to work around the nested fragment disappearing issue
// See solution here:
// http://stackoverflow.com/questions/14900738/nested-fragments-disappear-during-transition-animation
if(!enter && getParentFragment() != null){
return dummyAnimation;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
public static interface OnClickListener extends View.OnClickListener {
// No definitions, inherrited void onClick(View v)
}
public static interface OnLongClickListener extends View.OnLongClickListener{
// No definitions, inherrited void onClick(View v)
}
public static class Builder implements Serializable {
private static final long serialVersionUID = -3698059438530591747L;
private String text = null;
private transient OnClickListener cardOnClickListener = null;
private transient OnLongClickListener cardOnLongClickListener = null;
private transient OnClickListener textOnClickListener = null;
private transient OnLongClickListener textOnLongClickListener = null;
private Integer textColor = null;
private Integer backgroundColor = null;
private Integer fontSize = null;
private String fontFile = null;
private Setting.Align textAlignment = Setting.Align.CENTER;
private boolean displayInHtml = true;
private boolean htmlLinebreakConversion = false;
private String[] imageSearchPaths = {AMEnv.DEFAULT_IMAGE_PATH};
public Builder(String text) {
this.text = text;
}
/* Set the click listener on the card */
public Builder setCardOnClickListener(OnClickListener l) {
this.cardOnClickListener = l;
return this;
}
/* Set the click listener on the card text */
public Builder setCardOnLongClickListener(OnLongClickListener l) {
this.cardOnLongClickListener = l;
return this;
}
/* Set the click listener on the card text */
public Builder setTextOnClickListener(OnClickListener l) {
this.textOnClickListener = l;
return this;
}
/* Set the long click listener on the card text */
public Builder setTextOnLongClickListener(OnLongClickListener l) {
this.textOnLongClickListener = l;
return this;
}
/* Set the card text's color */
public Builder setTextColor(Integer color) {
this.textColor = color;
return this;
}
/* Set the font from a font file */
public Builder setTypefaceFromFile(String fontFile) {
this.fontFile = fontFile;
return this;
}
/* Set the card background color */
public Builder setBackgroundColor(Integer color){
this.backgroundColor = color;
return this;
}
public Builder setTextFontSize(int size) {
this.fontSize = size;
return this;
}
public Builder setDisplayInHtml(boolean displayInHtml) {
this.displayInHtml = displayInHtml;
return this;
}
public Builder setHtmlLinebreakConversion(boolean htmlLinebreakConversion) {
this.htmlLinebreakConversion = htmlLinebreakConversion;
return this;
}
public Builder setImageSearchPaths(String[] imageSearchPaths) {
this.imageSearchPaths = imageSearchPaths;
return this;
}
/*
* Set up the alignment of the text in the card.
* The parameter gravity is from Gravity.*
*/
public Builder setTextAlignment(Setting.Align align) {
this.textAlignment = align;
return this;
}
public CardFragment build() {
CardFragment fragment = new CardFragment();
Bundle b = new Bundle(1);
b.putString(EXTRA_CARD_TEXT, text);
fragment.setArguments(b);
if (fontFile != null) {
fragment.fontFile = fontFile;
}
if (cardOnClickListener != null) {
fragment.cardOnClickListener = cardOnClickListener;
}
if (cardOnLongClickListener != null) {
fragment.cardOnLongClickListener = cardOnLongClickListener;
}
if (textOnClickListener != null) {
fragment.textOnClickListener = textOnClickListener;
}
if (textOnLongClickListener != null) {
fragment.textOnLongClickListener = textOnLongClickListener;
}
if (fontSize != null) {
fragment.fontSize = fontSize;
}
if (textColor != null) {
fragment.textColor = textColor;
}
if (backgroundColor != null) {
fragment.backgroundColor = backgroundColor;
}
if (textAlignment != null) {
fragment.textAlignment = textAlignment;
}
fragment.htmlLinebreakConversion = htmlLinebreakConversion;
fragment.displayInHtml = displayInHtml;
fragment.imageSearchPaths = imageSearchPaths;
return fragment;
}
}
}