package com.gettingmobile.goodnews.itemview;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.Log;
import android.view.*;
import android.widget.Toast;
import com.actionbarsherlock.view.Menu;
import com.gettingmobile.android.app.actions.Action;
import com.gettingmobile.android.app.actions.ActionContext;
import com.gettingmobile.android.app.settings.AbstractSettings;
import com.gettingmobile.android.app.settings.OnSettingChangeListener;
import com.gettingmobile.android.view.NookTouchKeyCodes;
import com.gettingmobile.goodnews.Activity;
import com.gettingmobile.goodnews.Application;
import com.gettingmobile.goodnews.R;
import com.gettingmobile.goodnews.settings.ItemViewSettingsHandler;
import com.gettingmobile.goodnews.settings.SettingsHandler;
import com.gettingmobile.google.reader.Item;
public final class ItemViewActivity extends Activity implements BrowseHistoryListener {
private static final String LOG_TAG = "goodnews.ItemViewActivity";
public static final String EXTRA_KEY_ELEMENT_KEY_LIST = EXTRA_KEY_BASE + "ELEMENT_KEY_LIST";
private static final int NORMAL_SCREEN_VIEW_TIMEOUT = 6000;
private GestureDetector gestureDetector;
private int currentItemIndex = -1;
private final ItemUrlSharer itemUrlSharer;
private final MessageHandler msgHandler = new MessageHandler();
private ItemPagerAdapter pagerAdapter = null;
private ItemViewContentPager pager = null;
private ItemViewContentFragment currentContentFragment = null;
public ItemViewActivity() {
super(R.integer.tip_group_item_view);
itemUrlSharer = new ActionProviderItemUrlSharer(this);
}
//
// life cycle management
//
@Override
public void onCreate() {
Log.i(LOG_TAG, "starting general initialization");
super.onCreate();
requestWindowFeature(com.actionbarsherlock.view.Window.FEATURE_PROGRESS);
setContentView(R.layout.item_view);
setTitle(getIntentElementTitle());
pagerAdapter = new ItemPagerAdapter(getSupportFragmentManager(), getIntentElementKeyList());
pager = (ItemViewContentPager) findViewById(R.id.content);
pager.setSettings(getApp().getSettings());
pager.setAdapter(pagerAdapter);
showItem(pagerAdapter.getItemIndex(getIntentElementKey()), false);
//
// init gesture detector
//
gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return onTap();
}
});
getApp().getSettings().registerChangeListener("item_view_full_screen", new OnSettingChangeListener() {
@Override
public void onSettingChanged(AbstractSettings settings, SharedPreferences sharedPreferences, String s) {
invalidateOptionsMenu();
}
});
//
// done
//
Log.i(LOG_TAG, "done with onCreate");
}
@Override
protected boolean shouldUpdateOnResume() {
return false;
}
@Override
protected void onResume() {
getWindow().setFlags(getApp().getSettings().keepItemScreenOn() ?
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
showFullScreenIfEnabled(true);
super.onResume();
}
//
// intent handling and helpers
//
public static Intent createItemViewIntent(Context ctx, String itemListTitle, long itemKey, long[] itemKeyList) {
final Intent intent = new Intent(ctx, ItemViewActivity.class);
if (itemListTitle != null)
intent.putExtra(EXTRA_KEY_ELEMENT_TITLE, itemListTitle);
intent.putExtra(EXTRA_KEY_ELEMENT_KEY, itemKey);
if (itemKeyList == null) {
itemKeyList = new long[] { itemKey };
}
intent.putExtra(EXTRA_KEY_ELEMENT_KEY_LIST, itemKeyList);
return intent;
}
public static void startItemViewActivity(Activity ctx, String itemListTitle, long itemKey, long[] itemKeyList) {
Log.i(LOG_TAG, "Triggering item view for item " + itemKey);
ctx.startActivity(createItemViewIntent(ctx, itemListTitle, itemKey, itemKeyList));
}
protected long[] getIntentElementKeyList() {
final long[] keys = getIntent().getExtras().getLongArray(EXTRA_KEY_ELEMENT_KEY_LIST);
return keys != null ? keys : new long[0];
}
protected boolean showItem(int itemIndex, boolean smoothScroll) {
if (itemIndex >= 0 && itemIndex < pagerAdapter.getCount()) {
pager.setCurrentItem(itemIndex, smoothScroll);
setCurrentItemIndex(itemIndex);
return true;
} else {
return false;
}
}
protected boolean hasPrevItem() {
return currentItemIndex > 0;
}
protected void showPrevItem() {
showFullScreenIfEnabled();
if (!showItem(currentItemIndex - 1, true))
noMoreItems();
}
protected boolean hasNextItem() {
return currentItemIndex < pagerAdapter.getCount();
}
protected void showNextItem() {
showFullScreenIfEnabled();
if (!showItem(currentItemIndex + 1, true))
noMoreItems();
}
protected void noMoreItems() {
Toast.makeText(this, R.string.toast_no_more_items, Toast.LENGTH_SHORT).show();
}
//
// event handling
//
protected boolean useVolumeKeysForItemNavigation() {
return getApp().getSettings().useVolumeKeysForItemNavigation();
}
private boolean handleVolumeKeys(KeyEvent event) {
if (useVolumeKeysForItemNavigation()) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (event.getAction() == KeyEvent.ACTION_DOWN)
showPrevItem();
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (event.getAction() == KeyEvent.ACTION_DOWN)
showNextItem();
return true;
}
}
return false;
}
private boolean handleStandardKeyOverriding(KeyEvent event) {
return (currentContentFragment != null && currentContentFragment.handleStandardKeyOverriding(event)) || handleVolumeKeys(event);
}
private boolean handleNookTouchKeys(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case NookTouchKeyCodes.LEFT_NEXT_PAGE:
case NookTouchKeyCodes.RIGHT_NEXT_PAGE:
showNextItem();
return true;
case NookTouchKeyCodes.LEFT_PREV_PAGE:
case NookTouchKeyCodes.RIGHT_PREV_PAGE:
showPrevItem();
return true;
}
}
return false;
}
private boolean handleAdditionalKeys(KeyEvent event) {
return (currentContentFragment != null && currentContentFragment.handleAdditionalKeys(event)) || handleNookTouchKeys(event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return handleStandardKeyOverriding(event) || super.dispatchKeyEvent(event) || handleAdditionalKeys(event);
}
protected Rect getViewScreenRect(View view) {
final int[] viewPos = new int[2];
view.getLocationOnScreen(viewPos);
return new Rect(viewPos[0], viewPos[1], viewPos[0] + view.getWidth(), viewPos[1] + view.getHeight());
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
gestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
private boolean onTap() {
if (isFullScreenMode()) {
msgHandler.sendShowFullScreenModeIfEnabled(false);
} else {
msgHandler.sendShowFullScreenModeIfEnabled(true);
}
return true;
}
//
// menu handling
//
@Override
protected void onRegisterActions() {
super.onRegisterActions();
registerAction(R.id.menu_item_share, new ItemUrlSharerAction(itemUrlSharer));
registerAction(R.id.menu_item_labels, new EditTagsAction());
registerAction(R.id.menu_item_browser, new OpenInBrowserAction());
registerAction(R.id.menu_item_load, new LoadContentAction());
registerAction(R.id.menu_item_prev, new ShowPrevItemAction());
registerAction(R.id.menu_item_next, new ShowNextItemAction());
registerAction(R.id.menu_full_screen, new FullScreenAction());
registerAction(R.id.menu_full_screen_disable, new DisableFullScreenAction());
registerAction(R.id.menu_feed_preferences, ItemFeedSettingsAction.class);
}
@Override
protected int getOptionsMenuResourceId() {
return R.menu.item_options;
}
@Override
protected Class<? extends SettingsHandler> getViewSettingsHandlerClass() {
return ItemViewSettingsHandler.class;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
itemUrlSharer.onPrepareMenu(menu.findItem(R.id.menu_item_share));
prepareActionItem(menu, R.id.menu_item_share, "share");
prepareActionItem(menu, R.id.menu_item_labels, "labels");
prepareActionItem(menu, R.id.menu_item_browser, "browser");
prepareActionItem(menu, R.id.menu_item_load, "load");
prepareActionItem(menu, R.id.menu_item_prev, "prev");
prepareActionItem(menu, R.id.menu_item_next, "next");
prepareActionItem(menu, R.id.menu_full_screen, "full_screen");
prepareActionItem(menu, R.id.menu_full_screen_disable, "full_screen");
return super.onPrepareOptionsMenu(menu);
}
//
// controls
//
private void prepareActionItem(Menu menu, int resId, String settingsKey) {
menu.findItem(resId).setShowAsAction(getApp().getSettings().getActionButtonVisibilityFlags(settingsKey));
}
protected boolean isFullScreenMode() {
return !getSupportActionBar().isShowing();
}
private void showFullScreenIfEnabled() {
showFullScreenIfEnabled(true);
}
private void showFullScreenIfEnabled(boolean fullScreen) {
if (getApp().getSettings().isArticleFullScreenEnabled()) {
showFullScreen(fullScreen);
//
// schedule full screen after some delay
//
if (!fullScreen) {
msgHandler.sendDelayedShowFullScreenModeIfEnabled(true);
}
} else {
showFullScreen(false);
}
}
private void showFullScreen(boolean fullScreen) {
if (fullScreen) {
getSupportActionBar().hide();
} else {
getSupportActionBar().show();
}
}
//
// actions
//
private abstract class ContentFragmentAction implements Action<Application> {
@Override
public int getState(ActionContext<? extends Application> context) {
return currentContentFragment != null ? getAction(currentContentFragment).getState(context) : DISABLED;
}
@Override
public boolean onFired(ActionContext<? extends Application> context) {
return currentContentFragment != null && getAction(currentContentFragment).onFired(context);
}
protected abstract Action<Application> getAction(ItemViewContentFragment fragment);
}
private final class EditTagsAction extends ContentFragmentAction {
@Override
protected Action<Application> getAction(ItemViewContentFragment fragment) {
return fragment.editTagsAction;
}
}
private final class LoadContentAction extends ContentFragmentAction {
@Override
protected Action<Application> getAction(ItemViewContentFragment fragment) {
return fragment.loadContentAction;
}
}
private final class OpenInBrowserAction extends ContentFragmentAction {
@Override
protected Action<Application> getAction(ItemViewContentFragment fragment) {
return fragment.openInBrowserAction;
}
}
final class ShowNextItemAction implements Action<Application> {
@Override
public int getState(ActionContext<? extends Application> actionContext) {
return hasNextItem() ? ENABLED : DISABLED;
}
@Override
public boolean onFired(ActionContext<? extends Application> actionContext) {
showNextItem();
return true;
}
}
final class ShowPrevItemAction implements Action<Application> {
@Override
public int getState(ActionContext<? extends Application> actionContext) {
return hasPrevItem() ? ENABLED : DISABLED;
}
@Override
public boolean onFired(ActionContext<? extends Application> actionContext) {
showPrevItem();
return true;
}
}
final class FullScreenAction implements Action<Application> {
@Override
public int getState(ActionContext<? extends Application> context) {
return context.getApp().getSettings().isArticleFullScreenEnabled() ? GONE : ENABLED;
}
@Override
public boolean onFired(ActionContext<? extends Application> context) {
getApp().getSettings().setArticleFullScreenEnabled(true);
showFullScreenIfEnabled(true);
return true;
}
}
final class DisableFullScreenAction implements Action<Application> {
@Override
public int getState(ActionContext<? extends Application> context) {
return context.getApp().getSettings().isArticleFullScreenEnabled() ? ENABLED : GONE;
}
@Override
public boolean onFired(ActionContext<? extends Application> context) {
getApp().getSettings().setArticleFullScreenEnabled(false);
showFullScreenIfEnabled(false);
return true;
}
}
//
// event handling
//
final class MessageHandler extends Handler {
private static final int WHAT = 1;
protected Message createMessage(boolean visible) {
return obtainMessage(WHAT, visible ? 1 : 0, 0);
}
public void sendShowFullScreenModeIfEnabled(boolean enable) {
if (getApp().getSettings().isArticleFullScreenEnabled()) {
removeMessages(WHAT);
sendMessage(createMessage(enable));
}
}
public void sendDelayedShowFullScreenModeIfEnabled(boolean enable) {
if (getApp().getSettings().isArticleFullScreenEnabled()) {
removeMessages(WHAT);
sendMessageDelayed(createMessage(enable), NORMAL_SCREEN_VIEW_TIMEOUT);
}
}
@Override
public void handleMessage(Message msg) {
if (msg.what == WHAT) {
showFullScreenIfEnabled(msg.arg1 > 0);
}
super.handleMessage(msg);
}
}
@Override
public void onBrowseHistoryChanged(BrowseHistory history) {
invalidateOptionsMenu();
showUnshownTipsIfApplicable();
}
//
// item handling
//
public Item getItem() {
return currentContentFragment != null ? currentContentFragment.getItem() : null;
}
public void updateLabels() {
currentContentFragment.updateLabels();
}
private void setCurrentItemIndex(int itemIndex) {
if (itemIndex != currentItemIndex) {
currentItemIndex = itemIndex;
setIntentElementKey(pagerAdapter.itemKeys[itemIndex]);
getSupportActionBar().setSubtitle(Integer.toString(itemIndex + 1) + " / " + pagerAdapter.getCount());
}
}
private void setCurrentContentFragment(ItemViewContentFragment currentContentFragment) {
if (this.currentContentFragment != currentContentFragment) {
if (this.currentContentFragment != null) {
this.currentContentFragment.unsetCurrent();
}
this.currentContentFragment = currentContentFragment;
if (currentContentFragment != null) {
currentContentFragment.setCurrent(itemUrlSharer);
} else {
}
invalidateOptionsMenu();
}
}
private class ItemPagerAdapter extends FragmentStatePagerAdapter {
protected final long[] itemKeys;
public ItemPagerAdapter(FragmentManager fragmentManager, long[] itemKeys) {
super(fragmentManager);
this.itemKeys = itemKeys;
}
public int getItemIndex(long key) {
for (int i = 0; i < itemKeys.length; ++i) {
if (itemKeys[i] == key)
return i;
}
return -1;
}
@Override
public Fragment getItem(int position) {
return ItemViewContentFragment.newInstance(itemKeys[position]);
}
@Override
public int getCount() {
return itemKeys.length;
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
Log.d(LOG_TAG, "setPrimaryItem " + position);
setCurrentItemIndex(position);
setCurrentContentFragment((ItemViewContentFragment) object);
}
}
}