mobile/android/base/home/ReadingListPanel.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko.home;
     8 import java.util.EnumSet;
    10 import org.mozilla.gecko.R;
    11 import org.mozilla.gecko.ReaderModeUtils;
    12 import org.mozilla.gecko.Telemetry;
    13 import org.mozilla.gecko.TelemetryContract;
    14 import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
    15 import org.mozilla.gecko.db.BrowserDB;
    16 import org.mozilla.gecko.db.BrowserDB.URLColumns;
    17 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
    19 import android.app.Activity;
    20 import android.content.Context;
    21 import android.content.res.Configuration;
    22 import android.database.Cursor;
    23 import android.os.Bundle;
    24 import android.support.v4.app.LoaderManager.LoaderCallbacks;
    25 import android.support.v4.content.Loader;
    26 import android.support.v4.widget.CursorAdapter;
    27 import android.text.SpannableStringBuilder;
    28 import android.text.Spanned;
    29 import android.text.style.ImageSpan;
    30 import android.view.LayoutInflater;
    31 import android.view.View;
    32 import android.view.ViewGroup;
    33 import android.view.ViewStub;
    34 import android.widget.AdapterView;
    35 import android.widget.TextView;
    37 /**
    38  * Fragment that displays reading list contents in a ListView.
    39  */
    40 public class ReadingListPanel extends HomeFragment {
    42     // Cursor loader ID for reading list
    43     private static final int LOADER_ID_READING_LIST = 0;
    45     // Formatted string in hint text to be replaced with an icon.
    46     private final String MATCH_STRING = "%I";
    48     // Adapter for the list of reading list items
    49     private ReadingListAdapter mAdapter;
    51     // The view shown by the fragment
    52     private HomeListView mList;
    54     // Reference to the View to display when there are no results.
    55     private View mEmptyView;
    57     // Reference to top view.
    58     private View mTopView;
    60     // Callbacks used for the reading list and favicon cursor loaders
    61     private CursorLoaderCallbacks mCursorLoaderCallbacks;
    63     // On URL open listener
    64     private OnUrlOpenListener mUrlOpenListener;
    66     @Override
    67     public void onAttach(Activity activity) {
    68         super.onAttach(activity);
    70         try {
    71             mUrlOpenListener = (OnUrlOpenListener) activity;
    72         } catch (ClassCastException e) {
    73             throw new ClassCastException(activity.toString()
    74                     + " must implement HomePager.OnUrlOpenListener");
    75         }
    76     }
    78     @Override
    79     public void onDetach() {
    80         super.onDetach();
    82         mUrlOpenListener = null;
    83     }
    85     @Override
    86     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    87         return inflater.inflate(R.layout.home_reading_list_panel, container, false);
    88     }
    90     @Override
    91     public void onViewCreated(View view, Bundle savedInstanceState) {
    92         super.onViewCreated(view, savedInstanceState);
    94         mTopView = view;
    96         mList = (HomeListView) view.findViewById(R.id.list);
    97         mList.setTag(HomePager.LIST_TAG_READING_LIST);
    99         mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   100             @Override
   101             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
   102                 final Cursor c = mAdapter.getCursor();
   103                 if (c == null || !c.moveToPosition(position)) {
   104                     return;
   105                 }
   107                 String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
   108                 url = ReaderModeUtils.getAboutReaderForUrl(url);
   110                 Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL);
   112                 // This item is a TwoLinePageRow, so we allow switch-to-tab.
   113                 mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
   114             }
   115         });
   117         mList.setContextMenuInfoFactory(new HomeContextMenuInfo.Factory() {
   118             @Override
   119             public HomeContextMenuInfo makeInfoForCursor(View view, int position, long id, Cursor cursor) {
   120                 final HomeContextMenuInfo info = new HomeContextMenuInfo(view, position, id);
   121                 info.url = cursor.getString(cursor.getColumnIndexOrThrow(ReadingListItems.URL));
   122                 info.title = cursor.getString(cursor.getColumnIndexOrThrow(ReadingListItems.TITLE));
   123                 info.readingListItemId = cursor.getInt(cursor.getColumnIndexOrThrow(ReadingListItems._ID));
   124                 return info;
   125             }
   126         });
   127         registerForContextMenu(mList);
   128     }
   130     @Override
   131     public void onDestroyView() {
   132         super.onDestroyView();
   133         mList = null;
   134         mTopView = null;
   135         mEmptyView = null;
   136     }
   138     @Override
   139     public void onConfigurationChanged(Configuration newConfig) {
   140         super.onConfigurationChanged(newConfig);
   142         // Detach and reattach the fragment as the layout changes.
   143         if (isVisible()) {
   144             getFragmentManager().beginTransaction()
   145                                 .detach(this)
   146                                 .attach(this)
   147                                 .commitAllowingStateLoss();
   148         }
   149     }
   151     @Override
   152     public void onActivityCreated(Bundle savedInstanceState) {
   153         super.onActivityCreated(savedInstanceState);
   155         mAdapter = new ReadingListAdapter(getActivity(), null);
   156         mList.setAdapter(mAdapter);
   158         // Create callbacks before the initial loader is started.
   159         mCursorLoaderCallbacks = new CursorLoaderCallbacks();
   160         loadIfVisible();
   161     }
   163     @Override
   164     protected void load() {
   165         getLoaderManager().initLoader(LOADER_ID_READING_LIST, null, mCursorLoaderCallbacks);
   166     }
   168     private void updateUiFromCursor(Cursor c) {
   169         // We delay setting the empty view until the cursor is actually empty.
   170         // This avoids image flashing.
   171         if ((c == null || c.getCount() == 0) && mEmptyView == null) {
   172             final ViewStub emptyViewStub = (ViewStub) mTopView.findViewById(R.id.home_empty_view_stub);
   173             mEmptyView = emptyViewStub.inflate();
   175             final TextView emptyHint = (TextView) mEmptyView.findViewById(R.id.home_empty_hint);
   176             String readingListHint = emptyHint.getText().toString();
   178             // Use an ImageSpan to include the reader icon in the "Tip".
   179             int imageSpanIndex = readingListHint.indexOf(MATCH_STRING);
   180             if (imageSpanIndex != -1) {
   181                 final ImageSpan readingListIcon = new ImageSpan(getActivity(), R.drawable.reader_cropped, ImageSpan.ALIGN_BOTTOM);
   182                 final SpannableStringBuilder hintBuilder = new SpannableStringBuilder(readingListHint);
   184                 // Add additional spacing.
   185                 hintBuilder.insert(imageSpanIndex + MATCH_STRING.length(), " ");
   186                 hintBuilder.insert(imageSpanIndex, " ");
   188                 // Add icon.
   189                 hintBuilder.setSpan(readingListIcon, imageSpanIndex + 1, imageSpanIndex + MATCH_STRING.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
   191                 emptyHint.setText(hintBuilder, TextView.BufferType.SPANNABLE);
   192             }
   194             mList.setEmptyView(mEmptyView);
   195         }
   196     }
   198     /**
   199      * Cursor loader for the list of reading list items.
   200      */
   201     private static class ReadingListLoader extends SimpleCursorLoader {
   202         public ReadingListLoader(Context context) {
   203             super(context);
   204         }
   206         @Override
   207         public Cursor loadCursor() {
   208             return BrowserDB.getReadingList(getContext().getContentResolver());
   209         }
   210     }
   212     /**
   213      * Cursor adapter for the list of reading list items.
   214      */
   215     private class ReadingListAdapter extends CursorAdapter {
   216         public ReadingListAdapter(Context context, Cursor cursor) {
   217             super(context, cursor, 0);
   218         }
   220         @Override
   221         public void bindView(View view, Context context, Cursor cursor) {
   222             final ReadingListRow row = (ReadingListRow) view;
   223             row.updateFromCursor(cursor);
   224         }
   226         @Override
   227         public View newView(Context context, Cursor cursor, ViewGroup parent) {
   228             return LayoutInflater.from(parent.getContext()).inflate(R.layout.reading_list_item_row, parent, false);
   229         }
   230     }
   232     /**
   233      * LoaderCallbacks implementation that interacts with the LoaderManager.
   234      */
   235     private class CursorLoaderCallbacks implements LoaderCallbacks<Cursor> {
   236         @Override
   237         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
   238             return new ReadingListLoader(getActivity());
   239         }
   241         @Override
   242         public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
   243             mAdapter.swapCursor(c);
   244             updateUiFromCursor(c);
   245         }
   247         @Override
   248         public void onLoaderReset(Loader<Cursor> loader) {
   249             mAdapter.swapCursor(null);
   250         }
   251     }
   252 }

mercurial