package com.airlocksoftware.hackernews.view;
import java.util.Collection;
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.airlocksoftware.hackernews.R;
import com.airlocksoftware.hackernews.data.ConnectionManager;
import com.airlocksoftware.hackernews.model.Comment;
import com.airlocksoftware.hackernews.model.ShareItem;
import com.airlocksoftware.hackernews.model.Story;
import com.airlocksoftware.holo.anim.AnimationParams;
import com.airlocksoftware.holo.anim.AnimationParams.Exclusivity;
import com.airlocksoftware.holo.anim.AnimationParams.FillType;
import com.airlocksoftware.holo.anim.OverlayManager;
import com.airlocksoftware.holo.checkable.CheckableView;
import com.airlocksoftware.holo.checkable.CheckableViewManager;
import com.airlocksoftware.holo.checkable.CheckableViewManager.OnCheckedViewChangedListener;
import com.airlocksoftware.holo.picker.share.ShareList;
import com.airlocksoftware.holo.type.FontText;
import com.airlocksoftware.holo.utils.Utils;
/**
* Uses HoloTheme class ShareList to display a popup with a list of sharing options. Also allows multiple options for
* what should be shared.
**/
public class SharePopup extends RelativeLayout {
Context mContext;
OverlayManager mOverlay;
ShareList mList;
FontText mTitle;
CheckableViewManager mCheckManager;
LinearLayout mCheckContainer;
private View mCancelButton;
private int mChildCount = 1;
OnCheckedViewChangedListener checkListener = new OnCheckedViewChangedListener() {
@Override
public void onCheckedViewChanged(CheckableViewManager manager, int newIndex, int oldIndex) {
ShareItem holder = (ShareItem) manager.getChildAt(newIndex)
.getTag();
updateIntent(holder.subject, holder.extraText);
}
};
OnClickListener cancelListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
close();
}
};
private static final int LAYOUT_RES = R.layout.vw_share_popup;
// CONSTRUCTORS
public SharePopup(Context context, AttributeSet attrs, OverlayManager overlayManager) {
super(context, attrs);
if (context == null || overlayManager == null) throw new NullPointerException(
"Passed a null context or overlayManager");
mOverlay = overlayManager;
mContext = context;
setId(R.id.share_popup);
// inflate & find views
LayoutInflater.from(context)
.inflate(LAYOUT_RES, this);
mList = (ShareList) findViewById(R.id.sharelist);
mCheckContainer = (LinearLayout) findViewById(R.id.cnt_btn);
mTitle = (FontText) findViewById(R.id.txt_share);
mCancelButton = findViewById(R.id.btn_cancel);
mCancelButton.setOnClickListener(cancelListener);
// setup intent type of ShareList (empty, to be filled in later)
mList.setIntentType(createShareIntent("", ""));
// setup check manager
mCheckManager = new CheckableViewManager();
mCheckManager.setOnCheckedChangedListener(checkListener);
// setup animation in the overlay
// get screen size (if < 3 inches tall, allow SharePopup to clip the ActionBar
PointF size = Utils.pixelsToInches(mContext, Utils.getScreenSize(mContext));
FillType fillType = size.y > 3 ? FillType.CLIP_CONTENT : FillType.FILL_SCREEN;
AnimationParams animParams = new AnimationParams(fillType).exclusivity(Exclusivity.EXCLUDE_ALL);
animParams.inAnimation(AnimationUtils.loadAnimation(context, R.anim.scale_in_up));
animParams.outAnimation(AnimationUtils.loadAnimation(context, R.anim.scale_out_down));
mOverlay.addView(this, animParams);
// set layout params & gravity
// get screen size
int maxWidth = Utils.getScreenSize(mContext).x - 40; // max width is screen width - 40
int shareWidth = Math.min(Utils.dpToPixels(mContext, 320), maxWidth); // 320dp is ideal size
int topMargin = Utils.dpToPixels(mContext, 30); // leave 30dp margin at top
int grav = Gravity.BOTTOM;
grav |= Gravity.RIGHT;
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(shareWidth, LayoutParams.WRAP_CONTENT, grav);
layoutParams.topMargin = topMargin;
setLayoutParams(layoutParams);
// set background
TypedValue tv = new TypedValue();
mContext.getTheme()
.resolveAttribute(R.attr.bgSharePopup, tv, true);
int background = tv.resourceId;
setBackgroundResource(background);
}
// PUBLIC METHODS
public void shareComment(Comment comment) {
title("Share comment");
String subject = "A comment by " + comment.username;
String extraText = ConnectionManager.itemIdToUrl(comment.commentId);
clearButtons();
addItem("link", subject, extraText);
addItem("text", subject, comment.generateSpannedHtml()
.toString());
updateIntent(subject, extraText);
open();
}
/** Updates the SharePopup to share the specified story. Sets the title, buttons, and intent. **/
public void shareStory(Story story) {
title("Share story");
String extraText = ConnectionManager.itemIdToUrl(story.storyId);
clearButtons();
if (StringUtils.isNotBlank(story.url)) addItem("article", story.title, story.url);
addItem("hn page", story.title, extraText);
updateIntent(story.title, story.url);
open();
}
// PRIVATE METHODS
/** Creates a sharing intent from a title and body text. (can be URL, String, etc) **/
private static Intent createShareIntent(String title, String extraText) {
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, title);
intent.putExtra(android.content.Intent.EXTRA_TEXT, extraText);
return intent;
}
/** Updates the intent that will be used when an item in the ShareList is clicked. **/
private void updateIntent(String title, String extraText) {
mList.setIntent(createShareIntent(title, extraText));
}
private void addAll(Collection<ShareItem> items) {
clearButtons();
for (ShareItem item : items) {
addItem(item);
}
}
/** Adds button to the checkable buttons at the top of the SharePopup (i.e. an intent) **/
private void addItem(String label, String subject, String extraText) {
ShareItem holder = new ShareItem();
holder.label = label;
holder.subject = subject;
holder.extraText = extraText;
addItem(holder);
}
/** Adds button to the checkable buttons at the top of the SharePopup (i.e. an intent) **/
private void addItem(ShareItem item) {
LayoutInflater inflater = LayoutInflater.from(mContext);
CheckableView chk = (CheckableView) inflater.inflate(R.layout.vw_btn_sharepopup, mCheckContainer, false);
FontText txt = (FontText) chk.findViewById(R.id.txt);
txt.setText(item.label);
chk.setId(mChildCount++); // first child will always have id of 1
chk.setTag(item);
mCheckContainer.addView(chk);
mCheckManager.register(chk);
// this means it's the first one added to the container
if (mChildCount == 2) {
mCheckManager.check(chk.getId());
chk.setChecked(true);
}
}
/** Removes all buttons from the check container **/
private void clearButtons() {
mCheckContainer.removeAllViews();
mCheckManager.deregisterAll();
mChildCount = 1;
}
/** Sets the title of the SharePopup **/
private void title(String title) {
mTitle.setText(title);
}
/** Display SharePopup (should only be called after the ShareList is populated). **/
private void open() {
mOverlay.showViewById(getId());
}
/** Close the SharePopup. Alternatively, clicking outside of the SharePopup will do the same thing. **/
private void close() {
mOverlay.hideAllViews();
}
}