/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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.rubika.aotalk.aou;
import java.text.Collator;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.mcsoxford.rss.RSSFault;
import org.mcsoxford.rss.RSSFeed;
import org.mcsoxford.rss.RSSItem;
import org.mcsoxford.rss.RSSReader;
import org.mcsoxford.rss.RSSReaderException;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.google.analytics.tracking.android.EasyTracker;
import com.google.analytics.tracking.android.Tracker;
import com.rubika.aotalk.AOTalk;
import com.rubika.aotalk.R;
import com.rubika.aotalk.item.AouNews;
import com.rubika.aotalk.util.Logging;
import com.rubika.aotalk.util.Statics;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class FragmentNews extends SherlockListFragment implements LoaderManager.LoaderCallbacks<List<AouNews>> {
private static final String APP_TAG = "--> The Leet :: FragmentNews";
private ListAdapter mAdapter;
private static Tracker tracker;
private static AOU aou;
public static FragmentNews newInstance(AOU a) {
FragmentNews f = new FragmentNews();
aou = a;
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EasyTracker.getInstance().setContext(AOTalk.getContext());
tracker = EasyTracker.getTracker();
}
/**
* Perform alphabetical comparison of application entry objects.
*/
public static final Comparator<AouNews> ALPHA_COMPARATOR = new Comparator<AouNews>() {
private final Collator sCollator = Collator.getInstance();
@Override
public int compare(AouNews object1, AouNews object2) {
return sCollator.compare(object1.getLabel(), object2.getLabel());
}
};
/**
* Helper for determining if the configuration has changed in an interesting
* way so we need to rebuild the app list.
*/
public static class InterestingConfigChanges {
final Configuration mLastConfiguration = new Configuration();
int mLastDensity;
boolean applyNewConfig(Resources res) {
int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE
|ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
mLastDensity = res.getDisplayMetrics().densityDpi;
return true;
}
return false;
}
}
public static class ListLoader extends AsyncTaskLoader<List<AouNews>> {
List<AouNews> dataList;
//PackageIntentReceiver mPackageObserver;
final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
public ListLoader(Context context) {
super(context);
// Retrieve the package manager for later use; note we don't
// use 'context' directly but instead the save global application
// context returned by getContext().
}
@Override public List<AouNews> loadInBackground() {
long loadTime = System.currentTimeMillis();
RSSReader reader = new RSSReader();
List<AouNews> items = new ArrayList<AouNews>();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
try {
RSSFeed feed = reader.load(Statics.NEWS_URL);
List<RSSItem> feedItems = feed.getItems();
for(RSSItem i : feedItems) {
String title = "";
String target = "";
title = i.getTitle();
if (title.length() > 0) {
if (title.contains(" - ")) {
target = title.substring(0, title.indexOf(" - ")).trim();
title = title.substring(title.indexOf(" - ") + 2, title.length()).trim();
}
} else {
target = "";
title = "";
}
items.add(new AouNews(
title,
i.getDescription(),
df.format(i.getPubDate()),
i.getLink().toString(),
target
));
}
} catch (RSSReaderException e) {
Logging.log(APP_TAG, e.getMessage());
} catch (RSSFault e) {
Logging.log(APP_TAG, e.getMessage());
}
reader.close();
reader = null;
if (items.size() > 0) {
tracker.sendTiming("Loading", System.currentTimeMillis() - loadTime, "AOU News", null);
}
return items;
}
@Override public void deliverResult(List<AouNews> news) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (news != null) {
onReleaseResources(news);
}
}
List<AouNews> oldNews = news;
dataList = news;
if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(news);
}
// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if (oldNews != null) {
onReleaseResources(oldNews);
}
}
@Override protected void onStartLoading() {
if (dataList != null) {
// If we currently have a result available, deliver it
// immediately.
deliverResult(dataList);
}
// Has something interesting in the configuration changed since we
// last built the app list?
boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());
if (takeContentChanged() || dataList == null || configChange) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Handles a request to cancel a load.
*/
@Override public void onCanceled(List<AouNews> news) {
super.onCanceled(news);
// At this point we can release the resources associated with 'apps'
// if needed.
onReleaseResources(news);
}
/**
* Handles a request to completely reset the Loader.
*/
@Override protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'news'
// if needed.
if (dataList != null) {
onReleaseResources(dataList);
dataList = null;
}
}
/**
* Helper function to take care of releasing resources associated
* with an actively loaded data set.
*/
protected void onReleaseResources(List<AouNews> news) {
// For a simple List<> there is nothing to do. For something
// like a Cursor, we would close it here.
}
}
public static class ListAdapter extends ArrayAdapter<AouNews> {
private final LayoutInflater mInflater;
private boolean animationEnabled;
public ListAdapter(Context context, boolean enableAnimation) {
super(context, android.R.layout.simple_list_item_2);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
animationEnabled = enableAnimation;
}
public void setData(List<AouNews> data) {
clear();
if (data != null) {
for (AouNews entry : data) {
add(entry);
}
}
}
/**
* Populate new items in the list.
*/
@Override public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_news, parent, false);
}
AouNews item = getItem(position);
((TextView)convertView.findViewById(R.id.text)).setText(item.getLabel());
((TextView)convertView.findViewById(R.id.date)).setText(item.getDate());
((TextView)convertView.findViewById(R.id.target)).setText(item.getTarget());
if (animationEnabled) {
Animation animation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, (float)0, Animation.RELATIVE_TO_SELF, (float)0.5);
animation.setDuration(200);
animation.setFillAfter(true);
convertView.setAnimation(animation);
convertView.startAnimation(animation);
}
return convertView;
}
}
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText(getString(R.string.no_news));
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new ListAdapter(getActivity(), PreferenceManager.getDefaultSharedPreferences(this.getActivity().getBaseContext()).getBoolean("enableAnimations", true));
setListAdapter(mAdapter);
getListView().setScrollingCacheEnabled(false);
getListView().setDividerHeight(0);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
container.setBackgroundResource(0);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent();
intent.setClass(mAdapter.getContext(), ActivityNews.class);
intent.putExtra("title", mAdapter.getItem(position).getLabel());
intent.putExtra("date", mAdapter.getItem(position).getDate());
intent.putExtra("text", mAdapter.getItem(position).getDesc());
intent.putExtra("link", mAdapter.getItem(position).getLink());
if (AOU.isTablet) {
aou.loadFragment(intent, 1);
} else {
mAdapter.getContext().startActivity(intent);
}
}
@Override public Loader<List<AouNews>> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader with no arguments, so it is simple.
return new ListLoader(getActivity());
}
@Override public void onLoaderReset(Loader<List<AouNews>> loader) {
// Clear the data in the adapter.
mAdapter.setData(null);
}
@Override
public void onLoadFinished(Loader<List<AouNews>> arg0, List<AouNews> arg1) {
// Set the new data in the adapter.
mAdapter.setData(arg1);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
}