Java tutorial
//--------------------------------------------------------------------------------------- // Copyright (c) 2001-2014 by PDFTron Systems Inc. All Rights Reserved. // Consult legal.txt regarding legal and license information. //--------------------------------------------------------------------------------------- package com.pdftron.pdf.controls; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ImageButton; import android.widget.PopupMenu; import android.widget.TextView; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.pdftron.common.PDFNetException; import com.pdftron.pdf.Action; import com.pdftron.pdf.Bookmark; import com.pdftron.pdf.Destination; import com.pdftron.pdf.PDFDoc; import com.pdftron.pdf.tools.R; import com.pdftron.pdf.utils.AnalyticsHandlerAdapter; import com.pdftron.pdf.utils.CustomEditText; import com.pdftron.pdf.utils.Utils; import com.pdftron.pdf.utils.recyclerview.ItemClickHelper; import com.pdftron.pdf.utils.recyclerview.SimpleRecyclerView; import com.pdftron.pdf.utils.recyclerview.SimpleRecyclerViewAdapter; import com.pdftron.pdf.utils.recyclerview.ViewHolderBindListener; import com.pdftron.pdf.utils.recyclerview.decoration.DividerItemDecoration; import com.pdftron.sdf.Obj; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import co.paulburke.android.itemtouchhelperdemo.helper.ItemTouchHelperAdapter; import co.paulburke.android.itemtouchhelperdemo.helper.SimpleItemTouchHelperCallback; public class UserBookmarkDialogFragment extends DialogFragment { public static final String PREFS_CONTROLS_FILE_NAME = "com_pdftron_pdfnet_pdfviewctrl_controls_prefs_file"; private static final String KEY_PREF_USER_BOOKMARK = "user_bookmarks_key"; private static final String KEY_PREF_USER_BOOKMARK_OBJ_TITLE = "pdftronUserBookmarks"; private static final String CURRENT_FILE_PATH = "current_file_path"; private static final String CURRENT_PAGE_NUMBER = "current_page_number"; private static final String CURRENT_PAGE_OBJNUM = "current_page_obj_num"; private static final String CURRENT_FILE_READONLY = "current_file_readonly"; private static final int CONTEXT_MENU_EDIT_ITEM = 0; private static final int CONTEXT_MENU_DELETE_ITEM = 1; private static final int CONTEXT_MENU_DELETE_ALL = 2; public interface UserBookmarkDialogFragmentListener { void onUserBookmarkClicked(int pageNum); } private UserBookmarkDialogFragmentListener mListener; private PopulateUserBookmarkListTask mTask; private ArrayList<UserBookmarkItem> mSource; private UserBookmarkViewAdapter mBookmarkViewAdapter; private SimpleRecyclerView mRecyclerViewBookmarks; private ImageButton mButtonAdd; private int mCurrentPage; private String mCurrentFilePath; private long mCurrentObjNum; private boolean mReadOnly; private PDFDoc mPDFDoc; private boolean mModified = false; private static boolean mRebuild = false; private ItemTouchHelper mItemTouchHelper; private ItemClickHelper mItemClickHelper; private boolean mIsDragging = false; public static UserBookmarkDialogFragment newInstance(String filePath, int currentPage, long currentObjNum) { UserBookmarkDialogFragment f = new UserBookmarkDialogFragment(); Bundle args = new Bundle(); args.putString(CURRENT_FILE_PATH, filePath); args.putInt(CURRENT_PAGE_NUMBER, currentPage); args.putLong(CURRENT_PAGE_OBJNUM, currentObjNum); args.putBoolean(CURRENT_FILE_READONLY, true); f.setArguments(args); return f; } public static UserBookmarkDialogFragment newInstance(String filePath, int currentPage, long currentObjNum, boolean readOnly) { UserBookmarkDialogFragment f = new UserBookmarkDialogFragment(); Bundle args = new Bundle(); args.putString(CURRENT_FILE_PATH, filePath); args.putInt(CURRENT_PAGE_NUMBER, currentPage); args.putLong(CURRENT_PAGE_OBJNUM, currentObjNum); args.putBoolean(CURRENT_FILE_READONLY, readOnly); f.setArguments(args); return f; } public UserBookmarkDialogFragment setPDFDoc(PDFDoc doc) { mPDFDoc = doc; return this; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (UserBookmarkDialogFragmentListener) activity; } catch (ClassCastException e) { throw new ClassCastException( activity.toString() + " must implement UserBookmarkDialogFragmentListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } @Override public void onResume() { super.onResume(); loadBookmarks(getActivity()); } @Override public void onPause() { super.onPause(); commitData(getActivity()); } public void onShowPopupMenu(final int position, View anchor) { PopupMenu popupMenu = new PopupMenu(getActivity(), anchor); Menu menu = popupMenu.getMenu(); final UserBookmarkItem bItem = mBookmarkViewAdapter.getItem(position); String[] menuItems = getResources().getStringArray(R.array.user_bookmark_dialog_context_menu); menu.add(Menu.NONE, CONTEXT_MENU_EDIT_ITEM, CONTEXT_MENU_EDIT_ITEM, menuItems[CONTEXT_MENU_EDIT_ITEM]); menu.add(Menu.NONE, CONTEXT_MENU_DELETE_ITEM, CONTEXT_MENU_DELETE_ITEM, menuItems[CONTEXT_MENU_DELETE_ITEM]); menu.add(Menu.NONE, CONTEXT_MENU_DELETE_ALL, CONTEXT_MENU_DELETE_ALL, menuItems[CONTEXT_MENU_DELETE_ALL]); MenuItem.OnMenuItemClickListener listener = new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { onPopupItemSelected(item, position); return true; } }; menu.getItem(CONTEXT_MENU_EDIT_ITEM).setOnMenuItemClickListener(listener); menu.getItem(CONTEXT_MENU_DELETE_ITEM).setOnMenuItemClickListener(listener); menu.getItem(CONTEXT_MENU_DELETE_ALL).setOnMenuItemClickListener(listener); popupMenu.show(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCurrentPage = getArguments().getInt(CURRENT_PAGE_NUMBER); mCurrentFilePath = getArguments().getString(CURRENT_FILE_PATH); mCurrentObjNum = getArguments().getLong(CURRENT_PAGE_OBJNUM); mReadOnly = getArguments().getBoolean(CURRENT_FILE_READONLY, false); if (mCurrentFilePath == null) { throw new NullPointerException("current file path can't be null"); } mSource = new ArrayList<UserBookmarkItem>(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.controls_fragment_bookmark_dialog, null); mBookmarkViewAdapter = new UserBookmarkViewAdapter(getActivity(), mSource, null); View recView = view.findViewById(R.id.controls_bookmark_recycler_view); mRecyclerViewBookmarks = (SimpleRecyclerView) recView; //mRecyclerViewBookmarks.setEmptyView(view.findViewById(R.id.control_bookmark_textview_empty)); mRecyclerViewBookmarks.setAdapter(mBookmarkViewAdapter); mButtonAdd = (ImageButton) view.findViewById(R.id.control_bookmark_add); mButtonAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mModified = true; UserBookmarkItem item = new UserBookmarkItem(); item.pageObjNum = mCurrentObjNum; item.pageNumber = mCurrentPage; item.title = getActivity().getString(R.string.controls_bookmark_dialog_default_title) + Integer.toString(mCurrentPage); mBookmarkViewAdapter.add(item); mBookmarkViewAdapter.notifyDataSetChanged(); com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance() .sendEvent(AnalyticsHandlerAdapter.CATEGORY_BOOKMARK, "User Bookmark Added"); } }); DividerItemDecoration mDivDecorator = new DividerItemDecoration(getContext()); mRecyclerViewBookmarks.addItemDecoration(mDivDecorator); mItemClickHelper = new ItemClickHelper(); mItemClickHelper.attachToRecyclerView(mRecyclerViewBookmarks); ItemTouchHelper.Callback touchCallback = new BookmarkItemTouchHelperCallback(mBookmarkViewAdapter, 1, true, false); mItemTouchHelper = new ItemTouchHelper(touchCallback); mItemTouchHelper.attachToRecyclerView(mRecyclerViewBookmarks); mItemClickHelper.setOnItemClickListener(new ItemClickHelper.OnItemClickListener() { @Override public void onItemClick(RecyclerView recyclerView, View view, int position, long id) { if (mListener != null) { mListener.onUserBookmarkClicked(mBookmarkViewAdapter.getItem(position).pageNumber); com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance().sendEvent( AnalyticsHandlerAdapter.CATEGORY_BOOKMARK, "Navigated by User Bookmark List"); } } }); mItemClickHelper.setOnItemLongClickListener(new ItemClickHelper.OnItemLongClickListener() { @Override public boolean onItemLongClick(RecyclerView recyclerView, View v, final int position, final long id) { mRecyclerViewBookmarks.post(new Runnable() { @Override public void run() { mIsDragging = true; RecyclerView.ViewHolder holder = mRecyclerViewBookmarks .findViewHolderForAdapterPosition(position); mItemTouchHelper.startDrag(holder); } }); return true; } }); return view; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { if (v.getId() == R.id.controls_bookmark_recycler_view) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; UserBookmarkItem item = mBookmarkViewAdapter.getItem(info.position); menu.setHeaderTitle(item.title); String[] menuItems = getResources().getStringArray(R.array.user_bookmark_dialog_context_menu); menu.add(Menu.NONE, CONTEXT_MENU_EDIT_ITEM, CONTEXT_MENU_EDIT_ITEM, menuItems[CONTEXT_MENU_EDIT_ITEM]); menu.add(Menu.NONE, CONTEXT_MENU_DELETE_ITEM, CONTEXT_MENU_DELETE_ITEM, menuItems[CONTEXT_MENU_DELETE_ITEM]); menu.add(Menu.NONE, CONTEXT_MENU_DELETE_ALL, CONTEXT_MENU_DELETE_ALL, menuItems[CONTEXT_MENU_DELETE_ALL]); MenuItem.OnMenuItemClickListener listener = new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { onContextItemSelected(item); return true; } }; menu.getItem(CONTEXT_MENU_EDIT_ITEM).setOnMenuItemClickListener(listener); menu.getItem(CONTEXT_MENU_DELETE_ITEM).setOnMenuItemClickListener(listener); menu.getItem(CONTEXT_MENU_DELETE_ALL).setOnMenuItemClickListener(listener); } } public boolean onPopupItemSelected(MenuItem item, int position) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); int menuItemIndex = item.getItemId(); switch (menuItemIndex) { case CONTEXT_MENU_EDIT_ITEM: mModified = true; mBookmarkViewAdapter.setEditMode(true); mBookmarkViewAdapter.setSelectedIndex(position); mBookmarkViewAdapter.notifyDataSetChanged(); com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance() .sendEvent(AnalyticsHandlerAdapter.CATEGORY_BOOKMARK, "User Bookmark Rename Clicked"); break; case CONTEXT_MENU_DELETE_ITEM: mModified = true; if (!mReadOnly) { boolean needUnlock = false; try { mPDFDoc.lock(); needUnlock = true; if (mBookmarkViewAdapter.getItem(position).pdfBookmark != null) { mBookmarkViewAdapter.getItem(position).pdfBookmark.delete(); } } catch (Exception e) { } finally { if (needUnlock) { try { mPDFDoc.unlock(); } catch (PDFNetException ex) { } } } } mBookmarkViewAdapter.remove(mBookmarkViewAdapter.getItem(position)); mBookmarkViewAdapter.notifyDataSetChanged(); com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance() .sendEvent(AnalyticsHandlerAdapter.CATEGORY_BOOKMARK, "User Bookmark Delete Clicked"); break; case CONTEXT_MENU_DELETE_ALL: mModified = true; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.controls_bookmark_dialog_delete_all_message) .setTitle(R.string.controls_misc_delete_all) .setPositiveButton(R.string.tools_misc_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (!mReadOnly) { removeRootPDFBookmark(mPDFDoc); } mBookmarkViewAdapter.clear(); mBookmarkViewAdapter.notifyDataSetChanged(); com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance().sendEvent( AnalyticsHandlerAdapter.CATEGORY_BOOKMARK, "User Bookmark Delete All Clicked"); } }).setNegativeButton(R.string.controls_misc_cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // do nothing } }).create().show(); break; } return true; } private void loadBookmarks(Context context) { if (mTask != null) { if (!(mTask.getStatus() == AsyncTask.Status.RUNNING)) { if (mReadOnly) { mTask = new PopulateUserBookmarkListTask(context, mCurrentFilePath); } else { Bookmark rootBookmark = getRootPDFBookmark(mPDFDoc, false); mTask = new PopulateUserBookmarkListTask(context, mCurrentFilePath, mPDFDoc, rootBookmark); } mTask.execute(); } } else { if (mReadOnly) { mTask = new PopulateUserBookmarkListTask(context, mCurrentFilePath); } else { Bookmark rootBookmark = getRootPDFBookmark(mPDFDoc, false); mTask = new PopulateUserBookmarkListTask(context, mCurrentFilePath, mPDFDoc, rootBookmark); } mTask.execute(); } } private void commitData(Context context) { if (!mModified) { return; } if (mReadOnly) { UserBookmarkDialogFragment.saveUserBookmarks(context, mCurrentFilePath, mSource); } else { UserBookmarkDialogFragment.savePDFBookmarks(mPDFDoc, mSource); } } // START Bookmark using Bookmark object public static Bookmark getRootPDFBookmark(PDFDoc pdfDoc, boolean createNew) { Bookmark bookmark = null; if (null != pdfDoc) { try { Obj catalog = pdfDoc.getRoot(); Obj bookmark_obj = catalog.findObj(KEY_PREF_USER_BOOKMARK_OBJ_TITLE); if (null != bookmark_obj) { // found existing bookmark obj bookmark = new Bookmark(bookmark_obj); } else { if (createNew) { // create new bookmark obj bookmark = Bookmark.create(pdfDoc, KEY_PREF_USER_BOOKMARK_OBJ_TITLE); pdfDoc.getRoot().put(KEY_PREF_USER_BOOKMARK_OBJ_TITLE, bookmark.getSDFObj()); } } } catch (PDFNetException e) { bookmark = null; } } return bookmark; } public static List<UserBookmarkItem> getPDFBookmarks(Bookmark rootBookmark) { ArrayList<UserBookmarkItem> data = new ArrayList<UserBookmarkItem>(); if (null != rootBookmark) { try { if (rootBookmark.hasChildren()) { Bookmark item = rootBookmark.getFirstChild(); for (; item.isValid(); item = item.getNext()) { UserBookmarkItem bookmarkItem = new UserBookmarkItem(); bookmarkItem.isBookmarkEdited = false; bookmarkItem.pdfBookmark = item; bookmarkItem.title = item.getTitle(); Action action = item.getAction(); if (null != action && action.isValid()) { if (action.getType() == Action.e_GoTo) { Destination dest = action.getDest(); if (null != dest && dest.isValid()) { bookmarkItem.pageNumber = dest.getPage().getIndex(); bookmarkItem.pageObjNum = dest.getPage().getSDFObj().getObjNum(); data.add(bookmarkItem); } } } } } } catch (PDFNetException ex) { AnalyticsHandlerAdapter.getInstance().sendException(ex); Log.e("PDFNet", ex.getMessage()); } } return data; } public static void savePDFBookmarks(PDFDoc pdfDoc, List<UserBookmarkItem> data) { if (data.size() > 0) { Bookmark rootBookmark = getRootPDFBookmark(pdfDoc, true); Bookmark firstBookmark = null; Bookmark currentBookmark = null; if (null != rootBookmark) { boolean needUnlock = false; try { if (rootBookmark.hasChildren()) { firstBookmark = rootBookmark.getFirstChild(); } pdfDoc.lock(); needUnlock = true; if (mRebuild) { Obj catalog = pdfDoc.getRoot(); if (catalog != null) { catalog.erase(KEY_PREF_USER_BOOKMARK_OBJ_TITLE); } rootBookmark = getRootPDFBookmark(pdfDoc, true); firstBookmark = null; mRebuild = false; } for (UserBookmarkItem item : data) { if (null == item.pdfBookmark) { if (null == currentBookmark) { // No items in the list above this on are currently in the document if (null == firstBookmark) { // this means there are no bookmarks at all, so create one. currentBookmark = rootBookmark.addChild(item.title); currentBookmark.setAction(Action .createGoto(Destination.createFit(pdfDoc.getPage(item.pageNumber)))); firstBookmark = currentBookmark; } else { // there already are bookmarks, so the new bookmark needs to be inserted in front of the first one currentBookmark = firstBookmark.addPrev(item.title); currentBookmark.setAction(Action .createGoto(Destination.createFit(pdfDoc.getPage(item.pageNumber)))); firstBookmark = currentBookmark; } } else { // at least one item in the list above the current item was in the list currentBookmark = currentBookmark.addNext(item.title); currentBookmark.setAction( Action.createGoto(Destination.createFit(pdfDoc.getPage(item.pageNumber)))); } item.pdfBookmark = currentBookmark; } else { currentBookmark = item.pdfBookmark; if (item.isBookmarkEdited) { Action action = item.pdfBookmark.getAction(); Destination dest = action.getDest(); dest.setPage(pdfDoc.getPage(item.pageNumber)); item.pdfBookmark.setTitle(item.title); } } } } catch (Exception ex) { AnalyticsHandlerAdapter.getInstance().sendException(ex); Log.e("PDFNet", ex.getMessage()); } finally { if (needUnlock) { try { pdfDoc.unlock(); } catch (PDFNetException e) { } } } } } else { removeRootPDFBookmark(pdfDoc); } } public static boolean removeRootPDFBookmark(PDFDoc pdfDoc) { boolean needUnlock = false; try { pdfDoc.lock(); needUnlock = true; Obj catalog = pdfDoc.getRoot(); if (catalog != null) { catalog.erase(KEY_PREF_USER_BOOKMARK_OBJ_TITLE); } } catch (PDFNetException e) { return false; } finally { if (needUnlock) { try { pdfDoc.unlock(); } catch (PDFNetException ex) { } } } return true; } private static List<UserBookmarkItem> getPDFData(Bookmark rootBookmark) { return UserBookmarkDialogFragment.getPDFBookmarks(rootBookmark); } public static void pageDeleted(PDFDoc pdfDoc, Long objNumber) { List<UserBookmarkItem> items = UserBookmarkDialogFragment .getPDFBookmarks(getRootPDFBookmark(pdfDoc, false)); boolean needUnlock = false; try { pdfDoc.lock(); needUnlock = true; for (UserBookmarkItem item : items) { if (item.pageObjNum == objNumber) { item.pdfBookmark.delete(); } } } catch (Exception e) { } finally { if (needUnlock) { try { pdfDoc.unlock(); } catch (PDFNetException ex) { } } } } public static void pageMoved(PDFDoc pdfDoc, long objNumber, long newObjNumber, int newPageNumber) { List<UserBookmarkItem> items = UserBookmarkDialogFragment .getPDFBookmarks(getRootPDFBookmark(pdfDoc, false)); boolean needUnlock = false; try { pdfDoc.lock(); needUnlock = true; for (UserBookmarkItem item : items) { if (item.pageObjNum == objNumber) { item.pageObjNum = newObjNumber; item.pageNumber = newPageNumber; item.pdfBookmark.delete(); item.pdfBookmark = null; break; } } savePDFBookmarks(pdfDoc, items); } catch (Exception e) { } finally { if (needUnlock) { try { pdfDoc.unlock(); } catch (PDFNetException ex) { } } } } // END Bookmark using Bookmark object // START Bookmark using SharedPreferences public static void saveUserBookmarks(Context context, String filePath, List<UserBookmarkItem> data) { SharedPreferences settings = context.getSharedPreferences(PREFS_CONTROLS_FILE_NAME, 0); SharedPreferences.Editor editor = settings.edit(); Gson gson = new Gson(); Type collectionType = new TypeToken<ArrayList<UserBookmarkItem>>() { }.getType(); String serializedDocs = gson.toJson(data, collectionType); editor.putString(KEY_PREF_USER_BOOKMARK + filePath, serializedDocs); editor.apply(); } public static void removeUserBookmarks(Context context, String filePath) { SharedPreferences settings = context.getSharedPreferences(PREFS_CONTROLS_FILE_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.remove(KEY_PREF_USER_BOOKMARK + filePath); editor.apply(); } public static List<UserBookmarkItem> getUserBookmarks(Context context, String filePath) { SharedPreferences settings = context.getSharedPreferences(PREFS_CONTROLS_FILE_NAME, 0); String serializedDocs = settings.getString(KEY_PREF_USER_BOOKMARK + filePath, ""); Gson gson = new Gson(); Type collectionType = new TypeToken<ArrayList<UserBookmarkItem>>() { }.getType(); ArrayList<UserBookmarkItem> data = null; try { data = gson.fromJson(serializedDocs, collectionType); } catch (Exception e) { AnalyticsHandlerAdapter.getInstance().sendException(e); } return data != null ? data : new ArrayList<UserBookmarkItem>(); } public static void updateUserBookmarkPageObj(Context context, String filePath, long pageObjNum, long newPageObjNum, int newPageNum) { List<UserBookmarkItem> items = UserBookmarkDialogFragment.getUserBookmarks(context, filePath); for (UserBookmarkItem item : items) { if (item.pageObjNum == pageObjNum) { item.pageObjNum = newPageObjNum; item.pageNumber = newPageNum; } } UserBookmarkDialogFragment.saveUserBookmarks(context, filePath, items); } public static void pageDeleted(Context context, String filePath, Long objNumber, int pageNumber, int pageCount) { List<UserBookmarkItem> items = UserBookmarkDialogFragment.getUserBookmarks(context, filePath); List<UserBookmarkItem> newItems = new ArrayList<>(); for (UserBookmarkItem item : items) { if (item.pageObjNum != objNumber) { newItems.add(item); } } UserBookmarkDialogFragment.saveUserBookmarks(context, filePath, newItems); updateBookmarksAfterRearranging(context, filePath, pageNumber, pageCount, false, -1); } public static void pageMoved(Context context, String filePath, long objNumber, long newObjNumber, int oldPageNumber, int newPageNumber) { updateUserBookmarkPageObj(context, filePath, objNumber, newObjNumber, newPageNumber); if (oldPageNumber < newPageNumber) { updateBookmarksAfterRearranging(context, filePath, oldPageNumber + 1, newPageNumber, false, newObjNumber); } else { updateBookmarksAfterRearranging(context, filePath, newPageNumber, oldPageNumber - 1, true, newObjNumber); } } public static void updateBookmarksAfterRearranging(Context context, String filePath, int fromPage, int toPage, boolean increment, long ignoreObjNumber) { if (fromPage > toPage) { int temp = fromPage; fromPage = toPage; toPage = temp; } int change = -1; if (increment) { change = 1; } List<UserBookmarkItem> items = UserBookmarkDialogFragment.getUserBookmarks(context, filePath); for (UserBookmarkItem item : items) { if (item.pageNumber >= fromPage && item.pageNumber <= toPage && item.pageObjNum != ignoreObjNumber) { item.pageNumber += change; } } UserBookmarkDialogFragment.saveUserBookmarks(context, filePath, items); } public static void updateUserBookmarksFilePath(Context context, String oldPath, String newPath) { List<UserBookmarkItem> items = UserBookmarkDialogFragment.getUserBookmarks(context, oldPath); if (items.size() > 0) { UserBookmarkDialogFragment.saveUserBookmarks(context, newPath, items); UserBookmarkDialogFragment.removeUserBookmarks(context, oldPath); } } private static List<UserBookmarkItem> getData(Context context, String filePath) { return UserBookmarkDialogFragment.getUserBookmarks(context, filePath); } // END Bookmark using SharedPreferences private class PopulateUserBookmarkListTask extends AsyncTask<Void, Void, Void> { private Context mContext; private String mFilePath; private List<UserBookmarkItem> mBookmarkList; private boolean mReadOnly; private Bookmark mBookmark; public PopulateUserBookmarkListTask(Context context, String filePath) { mContext = context; mBookmarkList = new ArrayList<UserBookmarkItem>(); mFilePath = filePath; mReadOnly = true; } public PopulateUserBookmarkListTask(Context context, String filePath, PDFDoc pdfDoc, Bookmark bookmark) { mContext = context; mBookmarkList = new ArrayList<UserBookmarkItem>(); mPDFDoc = pdfDoc; mBookmark = bookmark; mFilePath = filePath; mReadOnly = false; } @Override protected Void doInBackground(Void... params) { if (mReadOnly) { mBookmarkList.addAll(getData(mContext, mFilePath)); } else { mBookmarkList.addAll(getPDFData(mBookmark)); if (mBookmarkList.isEmpty()) { // Backwards compatibility // try to see if there were bookmarks from previous releases mBookmarkList.addAll(getData(mContext, mFilePath)); if (!mBookmarkList.isEmpty()) { mModified = true; // after porting, remove the old bookmarks removeUserBookmarks(mContext, mFilePath); } } } return null; } @Override protected void onPostExecute(Void aVoid) { if (Utils.isHoneycomb()) { mBookmarkViewAdapter.clear(); mBookmarkViewAdapter.addAll(mBookmarkList); } else { mSource.clear(); mSource.addAll(mBookmarkList); } mBookmarkViewAdapter.notifyDataSetChanged(); } } public class UserBookmarkViewAdapter extends SimpleRecyclerViewAdapter<UserBookmarkItem, UserBookmarkViewAdapter.PageViewHolder> implements ItemTouchHelperAdapter { private ArrayList<UserBookmarkItem> mBookmarks; private Context mContext; private boolean mEditMode; private int mSelectedIndex = -1; public UserBookmarkViewAdapter(Context context, ArrayList<UserBookmarkItem> objects, ViewHolderBindListener bindListener) { super(bindListener); mContext = context; mBookmarks = objects; mEditMode = false; } public void clear() { mBookmarks.clear(); } public void addAll(List<UserBookmarkItem> listBookmarks) { mBookmarks.addAll(listBookmarks); } public void setEditMode(boolean editMode) { mEditMode = editMode; if (editMode) { unregisterForContextMenu(mRecyclerViewBookmarks); mButtonAdd.setVisibility(View.GONE); } else { registerForContextMenu(mRecyclerViewBookmarks); mButtonAdd.setVisibility(View.VISIBLE); } } public void setSelectedIndex(int index) { mSelectedIndex = index; } @Override public boolean onItemMove(int fromPosition, int toPosition) { UserBookmarkItem oldItem = mBookmarks.get(fromPosition); UserBookmarkItem item = new UserBookmarkItem(); item.pageObjNum = oldItem.pageObjNum; item.pageNumber = oldItem.pageNumber; item.title = oldItem.title; for (UserBookmarkItem uitem : mBookmarks) { uitem.pdfBookmark = null; } mRebuild = true; mBookmarks.remove(fromPosition); mBookmarks.add(toPosition, item); notifyItemMoved(fromPosition, toPosition); mModified = true; return true; } @Override public void onItemDrop(int fromPosition, int toPosition) { } @Override public void onItemDismiss(int position) { } @Override public UserBookmarkItem getItem(int position) { return mBookmarks.get(position); } @Override public void add(UserBookmarkItem item) { mBookmarks.add(item); } @Override public boolean remove(UserBookmarkItem item) { if (mBookmarks.contains(item)) { mBookmarks.remove(item); return true; } return false; } @Override public UserBookmarkItem removeAt(int location) { if (location < mBookmarks.size()) { return mBookmarks.remove(location); } return null; } @Override public void insert(UserBookmarkItem item, int position) { mBookmarks.add(position, item); } @Override public void updateSpanCount(int count) { } @Override public UserBookmarkViewAdapter.PageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.controls_fragment_bookmark_listview_item, parent, false); return new PageViewHolder(view, UserBookmarkViewAdapter.this); } @Override public void onBindViewHolder(UserBookmarkViewAdapter.PageViewHolder holder, final int position) { super.onBindViewHolder(holder, position); UserBookmarkItem item = mBookmarks.get(position); holder.itemView.getBackground().setColorFilter(null); holder.itemView.getBackground().invalidateSelf(); holder.bookmarkTextView.setText(item.title); if (mEditMode) { if (position == mSelectedIndex) { holder.bookmarkTextView.setVisibility(View.GONE); holder.bookmarkEditText.setVisibility(View.VISIBLE); holder.bookmarkEditText.setText(item.title); holder.bookmarkEditText.requestFocus(); holder.bookmarkEditText.selectAll(); showSoftInput(); // commit changes holder.bookmarkEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { hideSoftInput(v); saveEditTextChanges(v, position); return true; } return false; } }); } } else { holder.bookmarkEditText.clearFocus(); holder.bookmarkTextView.setVisibility(View.VISIBLE); holder.bookmarkEditText.setVisibility(View.GONE); } } @Override public int getItemCount() { return mBookmarks.size(); } private void saveEditTextChanges(TextView v, int position) { v.clearFocus(); setEditMode(false); String title = v.getText().toString(); if (title.isEmpty()) { title = mContext.getString(R.string.controls_bookmark_dialog_default_empty_title); } mBookmarkViewAdapter.getItem(position).title = title; mBookmarkViewAdapter.getItem(position).isBookmarkEdited = true; notifyDataSetChanged(); } private void hideSoftInput(View view) { InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } private void showSoftInput() { InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); } public class PageViewHolder extends RecyclerView.ViewHolder { public TextView bookmarkTextView; public CustomEditText bookmarkEditText; public ImageButton contextButton; public PageViewHolder(View itemView, UserBookmarkViewAdapter adapter) { super(itemView); this.bookmarkTextView = (TextView) itemView .findViewById(R.id.control_bookmark_listview_item_textview); this.bookmarkEditText = (CustomEditText) itemView .findViewById(R.id.control_bookmark_listview_item_edittext); this.contextButton = (ImageButton) itemView .findViewById(R.id.control_bookmark_listview_item_context_button); this.contextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UserBookmarkDialogFragment.this.onShowPopupMenu(getPosition(), v); } }); } } } static class UserBookmarkItem { protected int pageNumber; protected long pageObjNum; protected String title; protected boolean isBookmarkEdited; protected Bookmark pdfBookmark; } private class BookmarkItemTouchHelperCallback extends SimpleItemTouchHelperCallback { public BookmarkItemTouchHelperCallback(ItemTouchHelperAdapter adapter, int span, boolean enableLongPress, boolean enableSwipe) { super(adapter, span, enableLongPress, enableSwipe); } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { // Set movement flags based on the layout manager if (viewHolder.getItemViewType() == VIEW_TYPE_HEADER) { return makeMovementFlags(0, 0); } final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; final int swipeFlags = 0; return makeMovementFlags(dragFlags, swipeFlags); } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); if (mIsDragging) { viewHolder.itemView.getBackground().setColorFilter(getResources().getColor(R.color.gray), PorterDuff.Mode.MULTIPLY); viewHolder.itemView.getBackground().invalidateSelf(); } } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); if (mIsDragging) { viewHolder.itemView.getBackground().setColorFilter(null); viewHolder.itemView.getBackground().invalidateSelf(); mIsDragging = false; } } } }