|
@@ -9,27 +9,53 @@
|
|
|
|
|
|
package com.compdfkit.tools.annotation.pdfannotationlist;
|
|
|
|
|
|
+import android.app.Activity;
|
|
|
+import android.content.Intent;
|
|
|
+import android.net.Uri;
|
|
|
import android.os.Bundle;
|
|
|
+import android.os.Environment;
|
|
|
+import android.text.TextUtils;
|
|
|
+import android.view.Gravity;
|
|
|
import android.view.LayoutInflater;
|
|
|
import android.view.View;
|
|
|
import android.view.ViewGroup;
|
|
|
+import android.widget.PopupWindow;
|
|
|
import android.widget.ProgressBar;
|
|
|
|
|
|
+import androidx.activity.result.ActivityResultLauncher;
|
|
|
+import androidx.activity.result.contract.ActivityResultContracts;
|
|
|
import androidx.annotation.NonNull;
|
|
|
import androidx.annotation.Nullable;
|
|
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
|
+import androidx.core.view.GravityCompat;
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
|
|
+import com.compdfkit.core.annotation.CPDFAnnotation;
|
|
|
+import com.compdfkit.core.document.CPDFDocument;
|
|
|
+import com.compdfkit.core.page.CPDFPage;
|
|
|
import com.compdfkit.tools.R;
|
|
|
+import com.compdfkit.tools.annotation.pdfannotationbar.data.CAnnotationToolDatas;
|
|
|
import com.compdfkit.tools.annotation.pdfannotationlist.adapter.CPDFAnnotListAdapter;
|
|
|
import com.compdfkit.tools.annotation.pdfannotationlist.bean.CPDFAnnotListItem;
|
|
|
import com.compdfkit.tools.annotation.pdfannotationlist.data.CPDFAnnotDatas;
|
|
|
+import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CMarkedTipsWindow;
|
|
|
import com.compdfkit.tools.common.interfaces.COnSetPDFDisplayPageIndexListener;
|
|
|
+import com.compdfkit.tools.common.utils.CFileUtils;
|
|
|
+import com.compdfkit.tools.common.utils.CLog;
|
|
|
+import com.compdfkit.tools.common.utils.CToastUtil;
|
|
|
+import com.compdfkit.tools.common.utils.CUriUtil;
|
|
|
import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
|
|
|
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
|
|
|
+import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
|
|
|
+import com.compdfkit.tools.common.views.directory.CFileDirectoryDialog;
|
|
|
import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
|
|
|
+import com.compdfkit.ui.reader.CPDFPageView;
|
|
|
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
@@ -45,11 +71,42 @@ public class CPDFAnnotationListFragment extends Fragment {
|
|
|
private CPDFAnnotListAdapter listAdapter;
|
|
|
|
|
|
private ProgressBar progressBar;
|
|
|
+ private CPopupMenuWindow reviewStatusMenuWindow;
|
|
|
|
|
|
public static CPDFAnnotationListFragment newInstance() {
|
|
|
return new CPDFAnnotationListFragment();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private ActivityResultLauncher<Intent> importAnnotFileLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
|
|
+ if (result.getResultCode() == Activity.RESULT_OK) {
|
|
|
+ Uri uri = result.getData().getData();
|
|
|
+ // get xfdf format file name
|
|
|
+ String fileName = CUriUtil.getUriFileName(getContext(), uri);
|
|
|
+ //Determine whether the file is in xfdf format
|
|
|
+ if (fileName.toLowerCase().endsWith(".xfdf")){
|
|
|
+ // Save the file to the app's internal storage cache directory
|
|
|
+ String dir = new File(getContext().getCacheDir(), CFileUtils.CACHE_FOLDER + File.separator + "xfdfFile").getAbsolutePath();
|
|
|
+ // Get the saved file path
|
|
|
+ String importFilePath = CFileUtils.copyFileToInternalDirectory(getContext(), uri, dir, fileName);
|
|
|
+ CLog.e("ComPDFKit-Tools", "importFilePath:" + importFilePath);
|
|
|
+
|
|
|
+ if (!TextUtils.isEmpty(importFilePath)){
|
|
|
+ boolean importResult = CPDFAnnotDatas.importAnnotations(pdfView.getCPdfReaderView().getPDFDocument(), importFilePath);
|
|
|
+ if (importResult){
|
|
|
+ CToastUtil.showLongToast(getContext(), R.string.tools_import_success);
|
|
|
+ updateAnnotationList();
|
|
|
+ pdfView.getCPdfReaderView().reloadPages();
|
|
|
+ }
|
|
|
+ CLog.e("ComPDFKit-Tools", "import Annotation xfdf format file " + (importResult ? "success" : "fail"));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ CLog.e("ComPDFKit-Tools", "Please select xfdf format file");
|
|
|
+ CToastUtil.showLongToast(getContext(), R.string.tools_please_select_xfdf_format_file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
public void initWithPDFView(CPDFViewCtrl pdfView) {
|
|
|
this.pdfView = pdfView;
|
|
|
}
|
|
@@ -69,27 +126,44 @@ public class CPDFAnnotationListFragment extends Fragment {
|
|
|
super.onViewCreated(view, savedInstanceState);
|
|
|
listAdapter = new CPDFAnnotListAdapter();
|
|
|
updateAnnotationList();
|
|
|
- listAdapter.addOnItemChildClickListener(R.id.cl_root, (adapter, view1, position) -> {
|
|
|
+ listAdapter.addOnItemChildClickListener((adapter,view1,position) -> {
|
|
|
CPDFAnnotListItem item = adapter.list.get(position);
|
|
|
- if (!item.isHeader()) {
|
|
|
- if (displayPageIndexListener != null) {
|
|
|
- displayPageIndexListener.displayPage(item.getPage());
|
|
|
+ if (view1.getId() == R.id.cl_root) {
|
|
|
+ if (!item.isHeader()) {
|
|
|
+ if (displayPageIndexListener != null) {
|
|
|
+ displayPageIndexListener.displayPage(item.getPage());
|
|
|
+ }
|
|
|
}
|
|
|
+ } else if(view1.getId() == R.id.iv_review_status){
|
|
|
+ showReviewStatusMenu(item,position, view1);
|
|
|
+ } else if(view1.getId() == R.id.cb_marked_status){
|
|
|
+ showMarkedStatusMenu(position, view1);
|
|
|
+ } else if(view1.getId() == R.id.iv_more){
|
|
|
+ showAnnotationMoreMenu(item, position, view1);
|
|
|
}
|
|
|
- });
|
|
|
+ },R.id.iv_review_status, R.id.cb_marked_status, R.id.iv_more, R.id.cl_root);
|
|
|
+
|
|
|
rvAnnotation.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
|
rvAnnotation.setAdapter(listAdapter);
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void updateAnnotationList() {
|
|
|
- progressBar.setVisibility(View.VISIBLE);
|
|
|
+ public void updateAnnotationList() {
|
|
|
+ updateAnnotationList(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateAnnotationList(boolean showProgressBar) {
|
|
|
+ if (showProgressBar){
|
|
|
+ progressBar.setVisibility(View.VISIBLE);
|
|
|
+ }
|
|
|
CThreadPoolUtils.getInstance().executeIO(() -> {
|
|
|
List<CPDFAnnotListItem> list = CPDFAnnotDatas.getAnnotationList(pdfView);
|
|
|
if (getActivity() != null) {
|
|
|
getActivity().runOnUiThread(()->{
|
|
|
if (list == null || list.size() <= 0) {
|
|
|
clEmptyView.setVisibility(View.VISIBLE);
|
|
|
+ }else {
|
|
|
+ clEmptyView.setVisibility(View.GONE);
|
|
|
}
|
|
|
listAdapter.setList(list);
|
|
|
progressBar.setVisibility(View.GONE);
|
|
@@ -98,6 +172,121 @@ public class CPDFAnnotationListFragment extends Fragment {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * show toolbar annotation menu, in CPDFBOTAFragment
|
|
|
+ * @param anchorView
|
|
|
+ */
|
|
|
+ public void showAnnotationMenu(View anchorView){
|
|
|
+ CPopupMenuWindow menuWindow = new CPopupMenuWindow(getContext());
|
|
|
+ menuWindow.addItem(R.string.tools_import_annotations, v -> {
|
|
|
+ importAnnotFileLauncher.launch(CFileUtils.getIntent("application/octet-stream"));
|
|
|
+ });
|
|
|
+ menuWindow.addItem(R.string.tools_export_annotations, v -> {
|
|
|
+ String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
|
|
+ CFileDirectoryDialog directoryDialog = CFileDirectoryDialog.newInstance(dirPath, getString(R.string.tools_saving_path), getString(R.string.tools_okay));
|
|
|
+ directoryDialog.setSelectFolderListener(dir -> {
|
|
|
+ CPDFDocument document = pdfView.getCPdfReaderView().getPDFDocument();
|
|
|
+ boolean result = CPDFAnnotDatas.exportAnnotations(document, dir, CFileUtils.getFileNameNoExtension(document.getFileName()));
|
|
|
+ if (result){
|
|
|
+ CToastUtil.showLongToast(getContext(), R.string.tools_export_success);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ directoryDialog.show(getChildFragmentManager(), "dirDialog");
|
|
|
+ });
|
|
|
+ menuWindow.addItem(R.string.tools_delete_all_annotations, v -> {
|
|
|
+ deleteAllAnnotations();
|
|
|
+ });
|
|
|
+ menuWindow.addItem(R.string.tools_delete_all_replies, v -> {
|
|
|
+ CPDFDocument document = pdfView.getCPdfReaderView().getPDFDocument();
|
|
|
+ CPDFAnnotDatas.removeAllAnnotationReply(document);
|
|
|
+ updateAnnotationList();
|
|
|
+ });
|
|
|
+ menuWindow.showAsDropDown(anchorView);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * delete pdf document all annotations
|
|
|
+ */
|
|
|
+ public void deleteAllAnnotations(){
|
|
|
+ CPDFDocument document = pdfView.getCPdfReaderView().getPDFDocument();
|
|
|
+ boolean result = document.removeAllAnnotations();
|
|
|
+ if (result){
|
|
|
+ pdfView.getCPdfReaderView().reloadPages();
|
|
|
+ updateAnnotationList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showReviewStatusMenu(CPDFAnnotListItem item,int position, View anchorView){
|
|
|
+ anchorView.setSelected(true);
|
|
|
+ reviewStatusMenuWindow = new CPopupMenuWindow(getContext());
|
|
|
+ reviewStatusMenuWindow.setOutsideTouchable(false);
|
|
|
+ reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_accepted, R.string.tools_accepted, v -> {
|
|
|
+ listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_ACCEPTED);
|
|
|
+ });
|
|
|
+ reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_rejected, R.string.tools_rejected, v -> {
|
|
|
+ listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_REJECTED);
|
|
|
+ });
|
|
|
+ reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_cancelled, R.string.tools_cancelled, v -> {
|
|
|
+ listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_CANCELLED);
|
|
|
+
|
|
|
+ });
|
|
|
+ reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_completed, R.string.tools_completed, v -> {
|
|
|
+ listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_COMPLETED);
|
|
|
+ });
|
|
|
+ reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_none, R.string.tools_none, v -> {
|
|
|
+ listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_NONE);
|
|
|
+ });
|
|
|
+ reviewStatusMenuWindow.setOnDismissListener(() -> anchorView.setSelected(false));
|
|
|
+ int[] windowPos = CDimensUtils.calculatePopWindowPos(anchorView, reviewStatusMenuWindow.getContentView());
|
|
|
+ windowPos[0] -= reviewStatusMenuWindow.getContentView().getMeasuredWidth() /2;
|
|
|
+
|
|
|
+ windowPos[1] -= anchorView.getMeasuredHeight() / 2;
|
|
|
+ windowPos[1] -= anchorView.getMeasuredHeight();
|
|
|
+ reviewStatusMenuWindow.setAnimationStyle(R.style.PopupAnimation);
|
|
|
+ reviewStatusMenuWindow.showAtLocation(anchorView, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showMarkedStatusMenu( int position,View anchorView){
|
|
|
+ listAdapter.checkedMarkedStatus(position);
|
|
|
+ CMarkedTipsWindow tipsWindow = new CMarkedTipsWindow(getContext());
|
|
|
+ tipsWindow.setMarkState(listAdapter.list.get(position).getMarkState());
|
|
|
+
|
|
|
+ tipsWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
|
|
+ int winWidth = tipsWindow.getContentView().getMeasuredWidth();
|
|
|
+ int winHeight = tipsWindow.getContentView().getMeasuredHeight();
|
|
|
+ int anchorViewWidth = anchorView.getWidth();
|
|
|
+ int anchorViewHeight = anchorView.getHeight();
|
|
|
+ int offsetX = (anchorViewWidth - winWidth) / 2;
|
|
|
+ int offsetY = anchorViewHeight + winHeight;
|
|
|
+ tipsWindow.showAsDropDown(anchorView, offsetX, -offsetY);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showAnnotationMoreMenu(CPDFAnnotListItem item, int position, View anchorView){
|
|
|
+ CPopupMenuWindow moreMenu = new CPopupMenuWindow(getContext());
|
|
|
+ moreMenu.addItem(R.string.tools_add_a_new_reply,v -> {
|
|
|
+
|
|
|
+ });
|
|
|
+ moreMenu.addItem(R.string.tools_view_replies, v -> {
|
|
|
+
|
|
|
+ });
|
|
|
+ moreMenu.addItem(R.string.tools_delete_annotation, v -> {
|
|
|
+ boolean result = item.getAttr().removeFromPage();
|
|
|
+ if (result){
|
|
|
+ listAdapter.remove(position);
|
|
|
+ ArrayList<Integer> pages = new ArrayList<>();
|
|
|
+ pages.add(item.getPage());
|
|
|
+ pdfView.getCPdfReaderView().reloadPages(pages);
|
|
|
+ pdfView.getCPdfReaderView().postDelayed(()-> updateAnnotationList(false), 450);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ int[] windowPos = CDimensUtils.calculatePopWindowPos(anchorView, moreMenu.getContentView());
|
|
|
+ windowPos[0] -= anchorView.getMeasuredWidth() /2 ;
|
|
|
+ windowPos[1] -= anchorView.getMeasuredHeight();
|
|
|
+ moreMenu.setAnimationStyle(R.style.PopupAnimation);
|
|
|
+ moreMenu.showAtLocation(anchorView, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
|
|
|
+ }
|
|
|
+
|
|
|
public void setPDFDisplayPageIndexListener(COnSetPDFDisplayPageIndexListener displayPageIndexListener) {
|
|
|
this.displayPageIndexListener = displayPageIndexListener;
|
|
|
}
|