mobile/android/base/home/ReadingListPanel.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial