monakhv.android.samlib.BookListFragment.java Source code

Java tutorial

Introduction

Here is the source code for monakhv.android.samlib.BookListFragment.java

Source

/*
 * Copyright 2013 Dmitry Monakhov.
 *
 * 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 monakhv.android.samlib;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.text.Html;
import android.util.Log;
import android.view.ContextMenu;

import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;

import java.text.SimpleDateFormat;
import java.util.Date;
import static monakhv.android.samlib.ActivityUtils.setDivider;
import monakhv.android.samlib.data.SettingsHelper;
import monakhv.android.samlib.dialogs.SingleChoiceSelectDialog;
import monakhv.android.samlib.service.DownloadBookServiceIntent;
import monakhv.android.samlib.sql.AuthorController;
import monakhv.android.samlib.sql.AuthorProvider;
import monakhv.android.samlib.sql.BookController;
import monakhv.android.samlib.sql.SQLController;
import monakhv.android.samlib.sql.entity.Author;
import monakhv.android.samlib.sql.entity.Book;
import monakhv.android.samlib.sql.entity.SamLibConfig;

/**
 *
 * @author monakhv
 */
public class BookListFragment extends SherlockListFragment
        implements LoaderManager.LoaderCallbacks<Cursor>, ListSwipeListener.SwipeCallBack {
    private Callbacks mCallbacks;

    public interface Callbacks {
        public void cleanAuthorSelection();

        public void onOpenPanel();

    }

    private static final String DATE_FORMAT = "dd.MM.yyyy";
    private static final String DEBUG_TAG = "BookListFragment";
    public static final String AUTHOR_ID = "AUTHOR_ID";
    public static final int BOOK_LIST_LOADER = 0x12;
    private SimpleCursorAdapter adapter;
    //private GestureDetector detector;
    private int author_id;
    private AuthorController sql;
    private SettingsHelper settings;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getActivity().getIntent().getExtras() == null) {
            author_id = 0;
        } else {
            author_id = getActivity().getIntent().getExtras().getInt(AUTHOR_ID);
        }
        order = SortOrder.DateUpdate;

        getLoaderManager().initLoader(BOOK_LIST_LOADER, null, this);
        sql = new AuthorController(getActivity());

        String[] from = { SQLController.COL_BOOK_TITLE, SQLController.COL_BOOK_SIZE,
                SQLController.COL_BOOK_DESCRIPTION, SQLController.COL_BOOK_ISNEW, SQLController.COL_BOOK_GROUP_ID,
                SQLController.COL_BOOK_AUTHOR, SQLController.COL_BOOK_FORM };
        int[] to = { R.id.bookTitle, R.id.bookUpdate, R.id.bookDesc, R.id.Bookicon, R.id.Staricon,
                R.id.bookAuthorName, R.id.bookForm };

        adapter = new SimpleCursorAdapter(getActivity(), R.layout.book_row, null, from, to,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

        settings = new SettingsHelper(getActivity());
        order = settings.getBookSortOrder();
        adapter.setViewBinder(new BookViewBinder());
        setListAdapter(adapter);
        //detector = new GestureDetector(getActivity(), new ListSwipeListener(this));

    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }
        mCallbacks = (Callbacks) activity;
    }

    public void setAuthorId(int id) {
        if (id == author_id) {
            return;
        }
        author_id = id;
        if (isAdded()) {
            getLoaderManager().restartLoader(BOOK_LIST_LOADER, null, this);
            getListView().setSelectionAfterHeaderView();
        }
    }

    public int getAuthorId() {
        return author_id;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView emptyText = (TextView) getActivity().findViewById(R.id.id_empty_book_text);
        getListView().setEmptyView(emptyText);
        if (author_id == SamLibConfig.SELECTED_BOOK_ID) {
            emptyText.setText(R.string.no_selected_books);
        } else {
            emptyText.setText(R.string.no_new_books);
        }

        registerForContextMenu(getListView());

        getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {

            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Cursor c = (Cursor) adapter.getItem(position);
                long book_id = c.getLong(c.getColumnIndex(SQLController.COL_ID));
                Book book = sql.getBookController().getById(book_id);
                loadBook(book);
            }
        });

        setDivider(getListView());

    }

    private Book selected = null;
    private final int menu_mark_read = 1;
    private final int menu_browser = 2;
    private final int menu_selected = 3;
    private final int menu_deselected = 4;
    private final int menu_reload = 5;

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

        if (v.getId() == getListView().getId()) {
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;

            Cursor cursor = (Cursor) adapter.getItem(info.position);
            long book_id = cursor.getLong(cursor.getColumnIndex(SQLController.COL_ID));

            selected = sql.getBookController().getById(book_id);
            if (selected.isIsNew()) {
                menu.add(1, menu_mark_read, 1, getText(R.string.menu_read));
            }
            menu.add(1, menu_browser, 20, getText(R.string.menu_open_web));
            if (selected.getGroup_id() == Book.SELECTED_GROUP_ID) {
                menu.add(1, menu_deselected, 40, getText(R.string.menu_deselected));
            } else {
                menu.add(1, menu_selected, 30, getText(R.string.menu_selected));
            }
            menu.add(1, menu_reload, 50, getText(R.string.menu_reload));

        }
    }

    @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        settings.log("MARK_READ", "BookListFragment:   onContextItemSelected  item id: " + item.getItemId());
        BookController bookSQL = sql.getBookController();

        if (item.getItemId() == menu_browser) {
            launchBrowser(selected);
        }
        if (item.getItemId() == menu_mark_read) {
            settings.log("MARK_READ", "BookListFragment:  onContextItemSelected call markRead for book: "
                    + selected.getId() + "  -  " + selected.getUri());
            bookSQL.markRead(selected);
            sql.testMarkRead(sql.getByBook(selected));
        }
        if (item.getItemId() == menu_selected) {
            selected.setGroup_id(Book.SELECTED_GROUP_ID);
            bookSQL.update(selected);
        }
        if (item.getItemId() == menu_deselected) {
            selected.setGroup_id(0);
            bookSQL.update(selected);
        }
        if (item.getItemId() == menu_reload) {

            selected.cleanFile();
            loadBook(selected);
        }
        return super.onContextItemSelected(item);
    }

    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {

        String selection;
        if (author_id == SamLibConfig.SELECTED_BOOK_ID) {
            selection = SQLController.COL_BOOK_GROUP_ID + "=" + Book.SELECTED_GROUP_ID;
        } else {
            selection = SQLController.COL_BOOK_AUTHOR_ID + "=" + author_id;
        }

        // SQLController.COL_BOOK_MTIME + " DESC")
        return new CursorLoader(getActivity(), AuthorProvider.BOOKS_URI, null, selection, null, order.getOrder());

    }

    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        adapter.swapCursor(cursor);

    }

    public void onLoaderReset(Loader<Cursor> loader) {
        adapter.swapCursor(null);

    }

    private int id_menu_sort = 31;
    private SingleChoiceSelectDialog sortDialog;
    private SortOrder order;

    public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {

        menu.add(100, id_menu_sort, 100, getString(R.string.menu_sort));
        menu.findItem(id_menu_sort).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        menu.findItem(id_menu_sort).setIcon(settings.getSortIcon());
        super.onCreateOptionsMenu(menu, menuInflater);

    }

    @Override
    public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
        int sel = item.getItemId();
        if (sel == android.R.id.home) {
            mCallbacks.onOpenPanel();
        }
        if (sel == id_menu_sort) {
            selectSortOrder();

        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Show Dialog to select sort order for Book list
     *
     */
    public void selectSortOrder() {
        AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SortOrder so = SortOrder.values()[position];
                setSortOrder(so);
                sortDialog.dismiss();

            }
        };
        sortDialog = SingleChoiceSelectDialog.getInstance(SortOrder.getTitles(getActivity()), listener,
                this.getString(R.string.dialog_title_sort_book), getSortOrder().ordinal());
        sortDialog.show(getActivity().getSupportFragmentManager(), "DoBookSortDialog");
    }

    private void setSortOrder(SortOrder so) {
        order = so;
        getLoaderManager().restartLoader(BOOK_LIST_LOADER, null, this);
        getListView().setSelectionAfterHeaderView();
    }

    public SortOrder getSortOrder() {
        return order;
    }

    /**
     * Launch Browser to load book from web server
     *
     * @param book book to read
     */
    private void launchBrowser(Book book) {

        String surl = book.getUrlForBrowser(getActivity());

        Log.d(DEBUG_TAG, "book url: " + surl);

        Uri uri = Uri.parse(surl);
        Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uri);
        SettingsHelper setting = new SettingsHelper(getActivity());
        if (setting.getAutoMarkFlag()) {
            sql.getBookController().markRead(book);
            sql.testMarkRead(sql.getByBook(book));
        }

        startActivity(launchBrowser);
    }

    /**
     * Launch Reader to read the book considering book is downloaded
     *
     * @param book the book to read
     */
    void launchReader(Book book) {

        Intent launchBrowser = new Intent();
        launchBrowser.setAction(android.content.Intent.ACTION_VIEW);
        launchBrowser.setDataAndType(Uri.parse(book.getFileURL()), book.getFileMime());

        SettingsHelper setting = new SettingsHelper(getActivity());
        if (setting.getAutoMarkFlag()) {
            sql.getBookController().markRead(book);
            sql.testMarkRead(sql.getByBook(book));
        }
        startActivity(launchBrowser);
    }

    /**
     * Open book or start Download process if need
     * 
     * @param book  the book to open
     */

    private void loadBook(Book book) {
        book.setFileType(settings.getFileType());
        if (book.needUpdateFile()) {
            progress = new ProgressDialog(getActivity());
            progress.setMessage(getActivity().getText(R.string.download_Loading));
            progress.setCancelable(true);
            progress.setIndeterminate(true);
            progress.show();
            DownloadBookServiceIntent.start(getActivity(), book.getId(), true);

        } else {

            launchReader(book);
        }

    }

    public boolean singleClick(MotionEvent e) {
        int position = getListView().pointToPosition((int) e.getX(), (int) e.getY());
        Cursor c = (Cursor) adapter.getItem(position);
        if (c.getPosition() < 0) {
            //Log.d(DEBUG_TAG, "get cursor at position: "+c.getPosition()+ " Exiting.");
            return false;
        }
        long book_id = c.getLong(c.getColumnIndex(SQLController.COL_ID));

        Book book = sql.getBookController().getById(book_id);

        loadBook(book);
        return true;
    }

    public boolean swipeRight(MotionEvent e) {
        int position = getListView().pointToPosition((int) e.getX(), (int) e.getY());
        Cursor c = (Cursor) adapter.getItem(position);

        if (c.getPosition() < 0) {
            //Log.d(DEBUG_TAG, "get cursor at position: "+c.getPosition()+ " Exiting.");
            return false;
        }
        long book_id = c.getLong(c.getColumnIndex(SQLController.COL_ID));

        Book book = sql.getBookController().getById(book_id);
        settings.log("MARK_READ", "BookListFragment: call markRead for book: " + book_id + "  -  " + book.getUri());
        sql.getBookController().markRead(book);
        Author a = sql.getByBook(book);
        sql.testMarkRead(a);

        return true;

    }

    ProgressDialog progress;

    public boolean swipeLeft(MotionEvent e) {

        int position = getListView().pointToPosition((int) e.getX(), (int) e.getY());
        Cursor c = (Cursor) adapter.getItem(position);

        if (c.getPosition() < 0) {
            Log.d(DEBUG_TAG, "get cursor at position: " + c.getPosition() + " Exiting.");
            return false;
        }
        long book_id = c.getLong(c.getColumnIndex(SQLController.COL_ID));
        Book book = sql.getBookController().getById(book_id);
        launchBrowser(book);
        return true;
    }

    private class BookViewBinder implements SimpleCursorAdapter.ViewBinder {

        public boolean setViewValue(View view, Cursor cursor, int i) {
            int idx_form = cursor.getColumnIndex(SQLController.COL_BOOK_FORM);
            int idx_mtime = cursor.getColumnIndex(SQLController.COL_BOOK_MTIME);
            int idx_date = cursor.getColumnIndex(SQLController.COL_BOOK_DATE);
            int idx_desc = cursor.getColumnIndex(SQLController.COL_BOOK_DESCRIPTION);
            int idx_size = cursor.getColumnIndex(SQLController.COL_BOOK_SIZE);
            int idx_title = cursor.getColumnIndex(SQLController.COL_BOOK_TITLE);
            int idx_isNew = cursor.getColumnIndex(SQLController.COL_BOOK_ISNEW);
            int idx_group_id = cursor.getColumnIndex(SQLController.COL_BOOK_GROUP_ID);
            int idx_author = cursor.getColumnIndex(SQLController.COL_BOOK_AUTHOR);
            long book_id = cursor.getLong(cursor.getColumnIndex(SQLController.COL_ID));
            final Book book = sql.getBookController().getById(book_id);

            if (i == idx_title || i == idx_desc) {
                TextView tv = ((TextView) view);

                //tv.setText(cursor.getString(i).replaceAll("&quot;", "\""));
                try {
                    tv.setText(Html.fromHtml(cursor.getString(i)));
                } catch (Exception ex) {//This is because of old book scheme where Description could be null
                    tv.setText("");
                }
                return true;
            }

            if (i == idx_author) {
                TextView tv = ((TextView) view);
                if (author_id != SamLibConfig.SELECTED_BOOK_ID) {
                    tv.setVisibility(View.GONE);
                    return true;
                } else {
                    tv.setVisibility(View.VISIBLE);
                }

                tv.setText(cursor.getString(idx_author));
                return true;
            }

            if (i == idx_size) {
                TextView tv = ((TextView) view);
                tv.setText(cursor.getString(i) + "K");
                return true;
            }

            if (i == idx_form) {
                TextView tv = ((TextView) view);
                tv.setText(cursor.getString(i));
            }

            if (i == idx_mtime || i == idx_date) {
                SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);

                long dd = cursor.getLong(i);
                Date date = new Date(dd);
                ((TextView) view).setText(df.format(date));
                return true;
            }

            if (i == idx_isNew) {
                final ImageView iv = (ImageView) view;

                if (cursor.getInt(i) == 1) {
                    iv.setImageResource(R.drawable.open);

                } else {
                    iv.setImageResource(R.drawable.closed);

                }
                view.setOnClickListener(new View.OnClickListener() {

                    public void onClick(View v) {
                        if (book.isIsNew()) {
                            sql.getBookController().markRead(book);

                        } else {
                            sql.getBookController().markUnRead(book);

                        }
                        mCallbacks.cleanAuthorSelection();
                        Author a = sql.getByBook(book);
                        sql.testMarkRead(a);
                    }
                });
                return true;
            }
            if (i == idx_group_id) {
                if (cursor.getInt(i) == 1) {
                    ((ImageView) view).setImageResource(settings.getSelectedIcon());
                    return true;
                } else {
                    ((ImageView) view).setImageResource(R.drawable.rating_not_important);
                    return false;
                }

            }
            return false;
        }
    }

    public enum SortOrder {

        DateUpdate(R.string.sort_book_mtime, SQLController.COL_BOOK_MTIME + " DESC"), BookName(
                R.string.sort_book_title,
                SQLController.COL_BOOK_ISNEW + " DESC, " + SQLController.COL_BOOK_TITLE), BookDate(
                        R.string.sort_book_date,
                        SQLController.COL_BOOK_ISNEW + " DESC, " + SQLController.COL_BOOK_DATE + " DESC"), BookSize(
                                R.string.sort_book_size,
                                SQLController.COL_BOOK_ISNEW + " DESC, " + SQLController.COL_BOOK_SIZE + " DESC");

        private final int name;
        private final String order;

        private SortOrder(int name, String order) {
            this.name = name;
            this.order = order;
        }

        public String getOrder() {
            return order;
        }

        public static String[] getTitles(Context ctx) {
            String[] res = new String[values().length];
            int i = 0;
            for (SortOrder so : values()) {
                res[i] = ctx.getString(so.name);
                ++i;
            }
            return res;
        }
    }
}