Browse Source

PDFView Flutter - 超链接注释交互完善,超链接注释内容修改交互

liuxiaolong 1 year ago
parent
commit
b9ba433d5a
22 changed files with 473 additions and 187 deletions
  1. 4 8
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/FlutterCPDFReaderView.kt
  2. 1 0
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotAttributeUtil.kt
  3. 4 1
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotType.kt
  4. 65 0
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/ContextMenuEventDispatcher.kt
  5. 14 4
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/PluginUtils.kt
  6. 78 76
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SampleContextMenuHelper.kt
  7. 66 7
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SamplePdfLinkAnnotAttachHelper.kt
  8. 2 8
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/view/PDFReaderView.kt
  9. 1 1
      lib/widgets/config.dart
  10. 9 1
      lib/widgets/constains.dart
  11. 8 1
      lib/widgets/events.dart
  12. 39 20
      lib/widgets/function/annot_attribute_options_widget.dart
  13. 1 1
      lib/widgets/function/attrwidget/attr_free_text_widget.dart
  14. 119 32
      lib/widgets/function/attrwidget/attr_link_widget.dart
  15. 1 1
      lib/widgets/function/attrwidget/attr_shape_type_widget.dart
  16. 1 1
      lib/widgets/function/attrwidget/stamp/attr_stamp_widget.dart
  17. 4 15
      lib/widgets/function/pdf_bottom_annot_fun_widget.dart
  18. 1 1
      lib/widgets/function/setting/setting_pdf_page_turning_widget.dart
  19. 52 6
      lib/widgets/models/annot_attribute_bean.dart
  20. 1 1
      lib/widgets/models/annot_bean.dart
  21. 1 1
      lib/widgets/models/annot_shape_bean.dart
  22. 1 1
      lib/widgets/models/standard_stamp_bean.dart

+ 4 - 8
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/FlutterCPDFReaderView.kt

@@ -3,6 +3,7 @@ package com.compdfkit.pdfviewer.flutter
 import android.content.Context
 import android.util.Log
 import android.view.View
+import com.compdfkit.pdfviewer.flutter.helpers.ContextMenuEventDispatcher
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_CHANNEL_READER_VIEW_CALL_BACK
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_CHANNEL_READER_VIEW_CONTEXT_MENU_HELPER
@@ -41,6 +42,7 @@ class FlutterCPDFReaderView(
     private var methodChannel: MethodChannel
 
     init {
+        Log.e("初始化", "FlutterCPDFReaderView")
         registerWith(messenger)
         readerView.openDocument(documentPath)
         PluginUtils.initPDFReaderViewConfig(readerView, configurationMap)
@@ -57,12 +59,7 @@ class FlutterCPDFReaderView(
                 readerView.setReaderViewCallbackEventEmitter(events)
             }
         }
-        val readerViewContextMenuHelperEventChannel = EventChannel(messenger, EVENT_CHANNEL_READER_VIEW_CONTEXT_MENU_HELPER)
-        readerViewContextMenuHelperEventChannel.setStreamHandler {
-            onListen { arguments, events ->
-                readerView.setContextMenuHelperEventEmitter(events)
-            }
-        }
+        ContextMenuEventDispatcher.register(messenger)
 
         val readerViewFocusedChangEventChannel = EventChannel(messenger, EVENT_CHANNEL_READER_VIEW_FOCUSED_CHANGE_CALL_BACK)
         readerViewFocusedChangEventChannel.setStreamHandler {
@@ -78,8 +75,7 @@ class FlutterCPDFReaderView(
     }
 
     override fun dispose() {
-        PDFReaderView.contextMenuHelperEventEmitter = null
-        Log.e("FlutterCPDFReaderView", "disponse: callbackEmitter:${PDFReaderView.contextMenuHelperEventEmitter}")
+        ContextMenuEventDispatcher.unRegister()
     }
 
     override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {

+ 1 - 0
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotAttributeUtil.kt

@@ -4,6 +4,7 @@ import android.graphics.Color
 import android.util.Log
 import com.compdfkit.core.annotation.CPDFAnnotation
 import com.compdfkit.core.annotation.CPDFLineAnnotation
+import com.compdfkit.core.annotation.CPDFLinkAnnotation
 import com.compdfkit.core.annotation.CPDFStampAnnotation
 import com.compdfkit.core.annotation.CPDFTextAttribute
 import com.compdfkit.core.annotation.CPDFTextAttribute.FontNameHelper.FontType

+ 4 - 1
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotType.kt

@@ -2,7 +2,7 @@ package com.compdfkit.pdfviewer.flutter.helpers
 
 
 /**
- *  AnnotType.kt
+ *  Contains.kt
  *  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
  *
  *  THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
@@ -38,3 +38,6 @@ enum class ShapeType {
 
 }
 
+
+
+

+ 65 - 0
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/ContextMenuEventDispatcher.kt

@@ -0,0 +1,65 @@
+package com.compdfkit.pdfviewer.flutter.helpers
+
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.EventChannel
+import io.flutter.plugin.common.EventChannel.EventSink
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+
+/**
+ *  ContextMenuEventDispatcher.kt
+ *  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ *  THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ *  AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ *  UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ *  This notice may not be removed from this file.
+ **/
+
+typealias OnMethodCall = (call: MethodCall, result: MethodChannel.Result) -> Unit
+
+object ContextMenuEventDispatcher {
+
+
+    private var modifyAnnotationAttrChannel: MethodChannel? = null
+    private var readerViewContextMenuHelperEventChannel: EventChannel? = null
+
+    private var readerViewContextMenuEventSink: EventSink? = null
+    private var handlerMap: HashMap<String, OnMethodCall> = hashMapOf()
+
+    fun register(messenger: BinaryMessenger) {
+
+        modifyAnnotationAttrChannel = MethodChannel(messenger, PluginUtils.METHOD_CHANNEL_MODIFY_ANNOTATION_ATTRIBUTE)
+        modifyAnnotationAttrChannel?.setMethodCallHandler { call, result ->
+            for (mutableEntry in handlerMap) {
+                mutableEntry.value.invoke(call, result)
+            }
+        }
+        readerViewContextMenuHelperEventChannel = EventChannel(messenger, PluginUtils.EVENT_CHANNEL_READER_VIEW_CONTEXT_MENU_HELPER)
+        readerViewContextMenuHelperEventChannel?.setStreamHandler {
+            onListen { arguments, events ->
+                readerViewContextMenuEventSink = events
+            }
+        }
+    }
+
+
+    fun sendEvent(map: Map<String, Any>) {
+        readerViewContextMenuEventSink?.success(map)
+    }
+
+
+    fun addModifyAnnotationCallBack(key: String, onMethodCall: OnMethodCall) {
+        handlerMap[key] = onMethodCall
+
+    }
+
+
+    fun unRegister() {
+        modifyAnnotationAttrChannel = null
+        readerViewContextMenuHelperEventChannel = null
+        handlerMap.clear()
+    }
+
+
+}

+ 14 - 4
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/PluginUtils.kt

@@ -55,8 +55,13 @@ object PluginUtils {
     const val EVENT_ANNOT_ATTR_TEXT_STAMP_DATE = "textStampDate"
     const val EVENT_ANNOT_ATTR_TEXT_STAMP_STYLE_SHAPE_TYPE = "textStampStyleShapeType"
     const val EVENT_ANNOT_ATTR_TEXT_STAMP_STYLE_COLOR_TYPE = "textStampStyleColorType"
-
-
+    const val EVENT_ANNOT_ATTR_LINK_TYPE = "linkType"
+    const val EVENT_ANNOT_ATTR_LINK_WEB = "linkWeb"
+    const val EVENT_ANNOT_ATTR_LINK_PAGE = "linkPage"
+    const val EVENT_ANNOT_ATTR_LINK_EMAIL = "linkEmail"
+    const val EVENT_ANNOT_ATTR_LINK_CANCEL_CREATE = "cancelCreateLink"
+    const val EVENT_DOCUMENT_CURRENT_PAGE_INDEX = "documentCurrentPageIndex"
+    const val EVENT_DOCUMENT_PAGE_COUNT = "documentPageCount"
 
     const val KEY_SCROLL_DIRECTION = "scrollDirection"
     const val KEY_IS_DOUBLE_PAGE = "isDoublePage"
@@ -89,7 +94,7 @@ object PluginUtils {
     const val FUNCTION_SET_CURRENT_FOCUSED_TYPE = "setCurrentFocusedType"
     const val FUNCTION_SET_READER_VIEW_BACKGROUND_COLOR = "setReaderViewBackgroundColor"
     const val FUNCTION_GET_READER_VIEW_BACKGROUND_COLOR = "getReaderViewBackgroundColor"
-
+    const val FUNCTION_GET_DOCUMENT_PAGE_INFO = "getDocumentPageInfo"
 
     fun initPDFReaderViewConfig(pdfReaderView: PDFReaderView, configurationMap: Map<String, Any>?) {
 
@@ -115,7 +120,6 @@ object PluginUtils {
             pdfReaderView.pdfReaderView.readBackgroundColor = it.fromHex()
         }
 
-
     }
 
 
@@ -194,6 +198,12 @@ object PluginUtils {
                     result.success(pdfReaderView.pdfReaderView.readBackgroundColor)
                 }
             }
+            FUNCTION_GET_DOCUMENT_PAGE_INFO ->{
+                result.success(mapOf(
+                    EVENT_DOCUMENT_CURRENT_PAGE_INDEX to pdfReaderView.currentPageIndex,
+                    EVENT_DOCUMENT_PAGE_COUNT to pdfReaderView.pdfReaderView.pdfDocument.pageCount
+                ))
+            }
             else -> {}
         }
     }

+ 78 - 76
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SampleContextMenuHelper.kt

@@ -15,14 +15,13 @@ import com.compdfkit.core.annotation.form.CPDFTextWidget
 import com.compdfkit.core.annotation.form.CPDFWidgetItem
 import com.compdfkit.core.annotation.form.CPDFWidgetItems
 import com.compdfkit.core.document.CPDFDestination
-import com.compdfkit.core.document.action.CPDFAction.ActionType
+import com.compdfkit.core.document.action.CPDFAction
 import com.compdfkit.core.document.action.CPDFGoToAction
 import com.compdfkit.core.document.action.CPDFUriAction
 import com.compdfkit.core.edit.CPDFEditTextArea
 import com.compdfkit.core.utils.TFileUtils
 import com.compdfkit.core.utils.TMathUtils
 import com.compdfkit.demo.activity.ReaderActivity
-import com.compdfkit.demo.component.annottool.listener.OnLinkInfoChangeListener
 import com.compdfkit.demo.component.annottool.popupwindow.*
 import com.compdfkit.demo.component.annottool.popupwindow.LinkAnnotationPopupWindow.LinkType
 import com.compdfkit.demo.component.toolbar.popupwindow.AddFormListContentPopupWindow
@@ -38,6 +37,10 @@ import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_ITALIC
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_SIZE
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_TYPE
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_LINK_EMAIL
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_LINK_PAGE
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_LINK_TYPE
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_LINK_WEB
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_SHAPE_TYPE
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA
@@ -57,9 +60,6 @@ import com.compdfkit.ui.reader.CPDFReaderView
 import com.compdfkit.ui.reader.IPDFErrorMessageCallback
 import com.compdfkit.ui.utils.CPDFTextUtils
 import io.flutter.plugin.common.BinaryMessenger
-import io.flutter.plugin.common.EventChannel
-import io.flutter.plugin.common.EventChannel.EventSink
-import io.flutter.plugin.common.MethodChannel
 import java.io.File
 import java.io.FileOutputStream
 import java.io.IOException
@@ -77,18 +77,14 @@ import kotlin.math.round
 class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, messenger: BinaryMessenger) : CPDFContextMenuShowHelper(readerView) {
     private val annotAttribute: CPDFAnnotAttribute
     private val mContext: Context
-    private var contextMenuHelperEventEmitter: EventSink? = null
     private var linkAnnotationPopupWindow: LinkAnnotationPopupWindow? = null
-    private var freeTextPopupWindow: FreeTextPopupWindow? = null
-    private var modifyAnnotationAttrChannel: MethodChannel
     private var selectMarkupAnnotImpl: CPDFBaseAnnotImpl<*>? = null
     private var selectPageView: CPDFPageView? = null
 
     init {
         annotAttribute = readerView.readerAttribute.annotAttribute
         this.mContext = mContext
-        modifyAnnotationAttrChannel = MethodChannel(messenger, PluginUtils.METHOD_CHANNEL_MODIFY_ANNOTATION_ATTRIBUTE)
-        modifyAnnotationAttrChannel.setMethodCallHandler { call, result ->
+        ContextMenuEventDispatcher.addModifyAnnotationCallBack("SampleContextMenuHelper") { call, result ->
             val configuration = call.arguments as? HashMap<String, Any>
             when (call.method) {
                 KEY_MODIFY_ANNOTATION_ATTRIBUTE -> {
@@ -106,6 +102,11 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                     val textColorAlpha = configuration.getInt(EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA)
                     val fontSize = configuration.getInt(EVENT_ANNOT_ATTR_FONT_SIZE) ?: 40
                     val fontTypeStr = configuration.getString(EVENT_ANNOT_ATTR_FONT_TYPE)
+                    val linkType = configuration.getString(EVENT_ANNOT_ATTR_LINK_TYPE)
+                    val linkWeb = configuration.getString(EVENT_ANNOT_ATTR_LINK_WEB)
+                    val linkPage = configuration.getInt(EVENT_ANNOT_ATTR_LINK_PAGE)
+                    val linkEmail = configuration.getString(EVENT_ANNOT_ATTR_LINK_EMAIL)
+
 
                     selectMarkupAnnotImpl?.let {
                         when (it) {
@@ -222,6 +223,38 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                                     selectPageView?.invalidate()
                                 }
                             }
+                            is CPDFLinkAnnotImpl -> {
+                                it.onGetAnnotation()?.let {
+                                    if (linkType.isNullOrEmpty()) {
+                                        return@addModifyAnnotationCallBack
+                                    }
+                                    when (LinkType.valueOf(linkType.uppercase())) {
+                                        LinkType.WEBSITE -> {
+                                            it.linkAction = CPDFUriAction().also {uriAction->
+                                                uriAction.uri = linkWeb
+                                            }
+                                        }
+                                        LinkType.PAGE -> {
+                                            if (linkPage != null) {
+                                                val gotoAction = CPDFGoToAction()
+                                                val size = readerView.getPageNoZoomSize(linkPage)
+                                                val destination = CPDFDestination(linkPage, 0F, size.height(), 1F)
+                                                if (readerView.pdfDocument == null) {
+                                                    return@addModifyAnnotationCallBack
+                                                }
+                                                gotoAction.setDestination(readerView.pdfDocument, destination)
+                                                it.linkAction = gotoAction
+                                            }
+                                        }
+                                        LinkType.EMAIL -> {
+                                            it.linkAction = CPDFUriAction().also {uriAction->
+                                                uriAction.uri = linkEmail
+                                            }
+                                        }
+                                    }
+
+                                }
+                            }
                             else -> {
 
                             }
@@ -233,6 +266,7 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                     selectPageView = null
                 }
             }
+
         }
     }
 
@@ -291,8 +325,7 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                         emptyMap<String, Any>()
                     }
                 }
-                contextMenuHelperEventEmitter?.success(attr)
-
+                ContextMenuEventDispatcher.sendEvent(attr)
             } else if (id == R.id.delete) {
                 pageView.deleteAnnotation(annotImpl)
             }
@@ -359,7 +392,7 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                     selectPageView = pageView
 
                     val fontName = freetextAnnotation.freetextDa.fontName
-                    contextMenuHelperEventEmitter?.success(
+                    ContextMenuEventDispatcher.sendEvent(
                         mapOf(
                             KEY_ANNOT_TYPE to AnnotType.FREETEXT.name.lowercase(),
                             EVENT_ANNOT_ATTR_FONT_BOLD to CPDFTextAttribute.FontNameHelper.isBold(fontName),
@@ -399,7 +432,7 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                 selectMarkupAnnotImpl = markupAnnotImpl
                 selectPageView = pageView
                 //Notify the flutter side to open the annotation attribute modification interface
-                contextMenuHelperEventEmitter?.success(
+                ContextMenuEventDispatcher.sendEvent(
                     mapOf(
                         KEY_ANNOT_TYPE to markupAnnotation.type.name.lowercase(),
                         EVENT_ANNOT_ATTR_COLOR to markupAnnotation.color.toHexColor(),
@@ -437,7 +470,7 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                 selectMarkupAnnotImpl = inkAnnotImpl
                 selectPageView = pageView
                 //Notify the flutter side to open the annotation attribute modification interface
-                contextMenuHelperEventEmitter?.success(
+                ContextMenuEventDispatcher.sendEvent(
                     mapOf(
                         KEY_ANNOT_TYPE to inkAnnotation.type.name.lowercase(),
                         EVENT_ANNOT_ATTR_COLOR to inkAnnotation.color.toHexColor(),
@@ -500,6 +533,8 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
         if (readerView == null || pageView == null) {
             return null
         }
+        selectMarkupAnnotImpl = linkAnnotImpl
+        selectPageView = pageView
         val document = readerView.pdfDocument ?: return null
         invokeOnClickListener(contentView, { v: View ->
             val id = v.id
@@ -509,70 +544,40 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                 if (action == null && destination == null) {
                     return@invokeOnClickListener
                 }
-                if (linkAnnotationPopupWindow == null) {
-                    linkAnnotationPopupWindow = LinkAnnotationPopupWindow(context, readerView)
-                }
-                linkAnnotationPopupWindow!!.setOnInfoChangeListener(object : OnLinkInfoChangeListener {
-                    override fun cancelCreateLink(): Boolean {
-                        return false
-                    }
-
-                    override fun createWebsiteLink(website: String): Boolean {
-                        val uriAction = CPDFUriAction()
-                        uriAction.uri = website
-                        linkAnnotation.linkAction = uriAction
-                        return true
-                    }
-
-                    override fun createEmailLink(email: String): Boolean {
-                        val uriAction = CPDFUriAction()
-                        uriAction.uri = email
-                        linkAnnotation.linkAction = uriAction
-                        return true
-                    }
-
-                    override fun createPageLink(pageNum: Int): Boolean {
-                        val goToAction = CPDFGoToAction()
-                        val size = readerView.getPageNoZoomSize(pageNum)
-                        val destination = CPDFDestination(pageNum, 0F, size.height(), 1F)
-                        val document = readerView.pdfDocument
-                        if (document == null) {
-                            return false
-                        }
-                        goToAction.setDestination(document, destination)
-                        linkAnnotation.linkAction = goToAction
-                        return true
+                val map = when {
+                    destination != null -> {
+                        mapOf(
+                            KEY_ANNOT_TYPE to linkAnnotation.type.name.lowercase(),
+                            EVENT_ANNOT_ATTR_LINK_TYPE to LinkType.PAGE.name.lowercase(),
+                            EVENT_ANNOT_ATTR_LINK_PAGE to destination.pageIndex + 1
+                        )
                     }
-                })
-                var linkType = LinkType.PAGE
-                var url = ""
-                if (destination != null) {
-                    linkType = LinkType.PAGE
-                    url = destination.pageIndex.toString()
-                } else {
-                    when (action!!.actionType) {
-                        ActionType.PDFActionType_GoTo -> {
-                            linkType = LinkType.PAGE
-                            val goToAction = action as CPDFGoToAction
-                            val destination1 = goToAction.getDestination(document)
-                            if (destination1 != null) {
-                                url = destination1.pageIndex.toString()
+                    else -> {
+                        when (action.actionType) {
+                            CPDFAction.ActionType.PDFActionType_GoTo -> {
+                                mapOf(
+                                    KEY_ANNOT_TYPE to linkAnnotation.type.name.lowercase(),
+                                    EVENT_ANNOT_ATTR_LINK_TYPE to LinkType.PAGE.name.lowercase(),
+                                    EVENT_ANNOT_ATTR_LINK_PAGE to (action as CPDFGoToAction).getDestination(readerView.pdfDocument).pageIndex + 1
+                                )
                             }
-                        }
-                        ActionType.PDFActionType_URI -> {
-                            val uriAction = action as CPDFUriAction
-                            url = uriAction.uri
-                            linkType = if (url.startsWith("mailto:")) {
-                                LinkType.EMAIL
-                            } else {
-                                LinkType.WEBSITE
+                            CPDFAction.ActionType.PDFActionType_URI -> {
+                                val uri = (action as CPDFUriAction).uri
+                                val linkType = if (uri.startsWith("mailto:")) LinkType.EMAIL else LinkType.WEBSITE
+                                mapOf(
+                                    KEY_ANNOT_TYPE to linkAnnotation.type.name.lowercase(),
+                                    EVENT_ANNOT_ATTR_LINK_TYPE to linkType.name.lowercase(),
+                                    EVENT_ANNOT_ATTR_LINK_WEB to uri,
+                                    EVENT_ANNOT_ATTR_LINK_EMAIL to uri.replace("mailto:", "")
+                                )
+                            }
+                            else -> {
+                                mapOf<String, Any>()
                             }
                         }
-                        else -> {}
                     }
                 }
-                linkAnnotationPopupWindow!!.setInitData(linkType, url)
-                linkAnnotationPopupWindow!!.show(linkType)
+                ContextMenuEventDispatcher.sendEvent(map)
             } else if (id == R.id.delete) {
                 pageView.deleteAnnotation(annotImpl)
             }
@@ -1258,8 +1263,5 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
         return contentView
     }
 
-    fun setContextMenuHelperEventEmitter(emitter: EventChannel.EventSink?) {
-        this.contextMenuHelperEventEmitter = emitter
-    }
 
 }

+ 66 - 7
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SamplePdfLinkAnnotAttachHelper.kt

@@ -1,15 +1,21 @@
 package com.compdfkit.pdfviewer.flutter.helpers
 
 import com.compdfkit.core.annotation.CPDFLinkAnnotation
-import com.compdfkit.pdfviewer.flutter.view.PDFReaderView
+import com.compdfkit.core.document.CPDFDestination
+import com.compdfkit.core.document.action.CPDFGoToAction
+import com.compdfkit.core.document.action.CPDFUriAction
+import com.compdfkit.demo.component.annottool.popupwindow.LinkAnnotationPopupWindow.LinkType
 import com.compdfkit.ui.proxy.attach.CPDFLinkAnnotAttachHelper
 
 /**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2023/3/28
- * description:
- */
+ *  SamplePdfLinkAnnotAttachHelper.kt
+ *  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ *  THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ *  AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ *  UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ *  This notice may not be removed from this file.
+ **/
 class SamplePdfLinkAnnotAttachHelper : CPDFLinkAnnotAttachHelper() {
 
 
@@ -18,8 +24,61 @@ class SamplePdfLinkAnnotAttachHelper : CPDFLinkAnnotAttachHelper() {
         if (linkAnnotation == null || !linkAnnotation.isValid) {
             return
         }
-        PDFReaderView.contextMenuHelperEventEmitter?.success(
+        ContextMenuEventDispatcher.sendEvent(
             mapOf(PluginUtils.KEY_ANNOT_TYPE to linkAnnotation.type.name.lowercase())
         )
+
+        ContextMenuEventDispatcher.addModifyAnnotationCallBack("SamplePDFLinkHelper") { call, result ->
+            val configuration = call.arguments as? HashMap<String, Any>
+            when (call.method) {
+                PluginUtils.KEY_MODIFY_ANNOTATION_ATTRIBUTE -> {
+                    val linkType = configuration.getString(PluginUtils.EVENT_ANNOT_ATTR_LINK_TYPE) ?: ""
+                    val linkPage = configuration.getInt(PluginUtils.EVENT_ANNOT_ATTR_LINK_PAGE) ?: 1
+                    val linkEmail = configuration.getString(PluginUtils.EVENT_ANNOT_ATTR_LINK_EMAIL) ?: ""
+                    val linkWebsite = configuration.getString(PluginUtils.EVENT_ANNOT_ATTR_LINK_WEB)
+                    val annotationType = configuration.getString(PluginUtils.KEY_ANNOT_TYPE)
+                    val cancelCreateLink = configuration.getBoolean(PluginUtils.EVENT_ANNOT_ATTR_LINK_CANCEL_CREATE) ?: false
+                    if (cancelCreateLink) {
+                        tpdfPage.deleteAnnotation(linkAnnotation)
+                        pageView.invalidate()
+                        return@addModifyAnnotationCallBack
+                    }
+                    if (AnnotType.LINK.name.equals(annotationType, true)) {
+                        when (LinkType.valueOf(linkType.uppercase())) {
+                            LinkType.WEBSITE -> {
+                                val uriAction = CPDFUriAction()
+                                uriAction.uri = linkWebsite
+                                linkAnnotation.linkAction = uriAction
+                                pageView?.addAnnotation(linkAnnotation, false)
+                            }
+                            LinkType.PAGE -> {
+                                runCatching {
+                                    readerView?.pdfDocument?.apply {
+                                        val goToAction = CPDFGoToAction()
+                                        val page = pageAtIndex(linkPage - 1)
+                                        val destination = CPDFDestination(linkPage - 1, 0f, page.size?.height() ?: 0f, 1f)
+                                        goToAction.setDestination(this, destination)
+                                        linkAnnotation.linkAction = goToAction
+                                        pageView.addAnnotation(linkAnnotation, false)
+                                    }
+                                    readerView.saveReaderAttribute()
+                                }
+                            }
+                            LinkType.EMAIL -> {
+                                linkAnnotation.linkAction = CPDFUriAction().apply {
+                                    uri = if (linkEmail.isEmpty() || !linkEmail.contains("mailto:")) {
+                                        "mailto:$linkEmail"
+                                    } else {
+                                        linkEmail
+                                    }
+                                }
+                                pageView?.addAnnotation(linkAnnotation, false)
+                                readerView.saveReaderAttribute()
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 }

+ 2 - 8
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/view/PDFReaderView.kt

@@ -31,15 +31,12 @@ import io.flutter.plugin.common.EventChannel
  **/
 class PDFReaderView(context: Context?, messenger: BinaryMessenger) : RelativeLayout(context), IReaderViewCallback {
 
-    companion object{
-        var contextMenuHelperEventEmitter: EventChannel.EventSink? = null
-
-    }
 
     private var callbackEventEmitter: EventChannel.EventSink? = null
     var pdfReaderView = CPDFReaderView(context)
     private var focusedChangeCallbackEventEmitter: EventChannel.EventSink? = null
     private var contextMenuHelper: SampleContextMenuHelper
+    var currentPageIndex = 0
     init {
         pdfReaderView.setReaderViewCallback(this)
         pdfReaderView.setOnFocusedTypeChangedListener {
@@ -72,6 +69,7 @@ class PDFReaderView(context: Context?, messenger: BinaryMessenger) : RelativeLay
     }
 
     override fun onMoveToChild(pageIndex: Int) {
+        currentPageIndex = pageIndex
         callbackEventEmitter?.success(mapOf("eventType" to EVENT_ON_MOVE_TO_CHILD, "pageIndex" to pageIndex))
 
     }
@@ -130,10 +128,6 @@ class PDFReaderView(context: Context?, messenger: BinaryMessenger) : RelativeLay
         callbackEventEmitter = emitter
     }
 
-    fun setContextMenuHelperEventEmitter(emitter: EventChannel.EventSink?) {
-        PDFReaderView.contextMenuHelperEventEmitter = emitter
-        contextMenuHelper.setContextMenuHelperEventEmitter(emitter)
-    }
 
     fun setFocusedChangeEventEmitter(emitter: EventChannel.EventSink?) {
         focusedChangeCallbackEventEmitter = emitter

+ 1 - 1
lib/widgets/config.dart

@@ -2,7 +2,7 @@
 
 
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/extension/color_extension.dart';
 
 

+ 9 - 1
lib/widgets/constains.dart

@@ -30,6 +30,8 @@ class Functions {
   static const setCurrentFocusedType = 'setCurrentFocusedType';
   static const modifyAnnotAttribute = 'modifyAnnotationAttribute';
   static const dismissModifyAnnotationAttr = "dismissModifyAnnotationAttr";
+
+  static const getDocumentPageInfo = 'getDocumentPageInfo';
 }
 
 /// Parameters of functions.
@@ -72,6 +74,12 @@ class EventParameters {
   static const annotTextStampDate = 'textStampDate';
   static const annotTextStampStyleShapeType  = 'textStampStyleShapeType';
   static const annotTextStampStyleColorType  = 'textStampStyleColorType';
+  static const annotLinkType = 'linkType';
+  static const annotLinkWeb = 'linkWeb';
+  static const annotLinkPage = 'linkPage';
+  static const annotLinkEmail = 'linkEmail';
+  static const annotLinkCancelCreate = 'cancelCreateLink';
+  static const documentPageCount = 'documentPageCount';
 
 }
 
@@ -146,7 +154,7 @@ enum StandardStamp {
 
 enum LinkType {
   page,
-  web,
+  website,
   email
 }
 

+ 8 - 1
lib/widgets/events.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/extension/color_extension.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_bean.dart';
 
@@ -357,3 +357,10 @@ void setCPDFReaderViewFocusType(AnnotationType annotationType) async {
     EventParameters.focusedType: annotationType.name
   });
 }
+
+
+/// get pdf document file page total count
+Future<int> getDocumentPageCount() async{
+  Map<dynamic, dynamic> map = await _methodChannel.invokeMethod(Functions.getDocumentPageInfo);
+  return map[EventParameters.documentPageCount];
+}

+ 39 - 20
lib/widgets/function/annot_attribute_options_widget.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_free_text_widget.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_link_widget.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/signature/attr_signature_list_widget.dart';
@@ -110,25 +110,44 @@ class _AnnotAttributeOptionsWidgetState
             },
           );
         }
-      case AnnotationType.stamp : {
-        return AttrStampWidget(callback: (String? standardStampName, TextStampBean? textStampBean){
-          if(standardStampName != null){
-            widget.annotBean.attributeBean
-              ..standardStampName = standardStampName
-            ..customStampBean = null;
-          }
-          if(textStampBean != null){
-            widget.annotBean.attributeBean
-              ..standardStampName = ''
-              ..customStampBean = textStampBean;
-          }
-          widget.attributeOptionsCallback(widget.annotBean.attributeBean);
-          Navigator.pop(context);
-        });
-      }
-      case AnnotationType.link : {
-        return const AttrLinkWidget();
-      }
+      case AnnotationType.stamp:
+        {
+          return AttrStampWidget(callback:
+              (String? standardStampName, TextStampBean? textStampBean) {
+            if (standardStampName != null) {
+              widget.annotBean.attributeBean
+                ..standardStampName = standardStampName
+                ..customStampBean = null;
+            }
+            if (textStampBean != null) {
+              widget.annotBean.attributeBean
+                ..standardStampName = ''
+                ..customStampBean = textStampBean;
+            }
+            widget.attributeOptionsCallback(widget.annotBean.attributeBean);
+            Navigator.pop(context);
+          });
+        }
+      case AnnotationType.link:
+        {
+          return AttrLinkWidget(
+            attributeBean: widget.annotBean.attributeBean,
+            callback: (LinkType linkType, String linkWeb, int linkPage,
+                String linkEmail) {
+              widget.annotBean.attributeBean
+                ..linkType = linkType
+                ..linkWeb = linkWeb
+                ..linkPage = linkPage
+                ..linkEmail = linkEmail;
+              widget.attributeOptionsCallback(widget.annotBean.attributeBean);
+            },
+            cancelCreateCallback: (cancelCreateLink) {
+              widget.annotBean.attributeBean.cancelCreateLink =
+                  cancelCreateLink;
+              widget.attributeOptionsCallback(widget.annotBean.attributeBean);
+            },
+          );
+        }
       default:
         return const Placeholder();
     }

+ 1 - 1
lib/widgets/function/attrwidget/attr_free_text_widget.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
 
 import 'attr_color_list_widget.dart';

+ 119 - 32
lib/widgets/function/attrwidget/attr_link_widget.dart

@@ -1,8 +1,29 @@
+
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
+import 'package:kmpdfkit_demo/widgets/events.dart';
+
+import '../../models/annot_attribute_bean.dart';
+
+
+///  attr_link_widget.dart
+///
+///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+///
+///  THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+///  AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+///  UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+///  This notice may not be removed from this file.
+
+
+typedef AttrLinkCallback = Function(LinkType linkType, String linkUrl, int linkPage, String linkEmail);
+typedef AttrLinkCancelCreateCallback = Function(bool cancelCreateLink);
 
 class AttrLinkWidget extends StatefulWidget {
-  const AttrLinkWidget({Key? key}) : super(key: key);
+  AttrLinkCallback callback;
+  AttrLinkCancelCreateCallback cancelCreateCallback;
+  AnnotAttributeBean attributeBean;
+  AttrLinkWidget({Key? key,required this.attributeBean, required this.callback, required this.cancelCreateCallback}) : super(key: key);
 
   @override
   State<AttrLinkWidget> createState() => _AttrLinkWidgetState();
@@ -15,47 +36,96 @@ class _AttrLinkWidgetState extends State<AttrLinkWidget> {
   final TextEditingController _emailTextController = TextEditingController();
   late LinkType selectType;
 
+  bool linkDataIsValid = true;
+  int pageCount = 1;
+
+
   @override
   void initState() {
     super.initState();
-    selectType = LinkType.web;
+    initLinkData();
+    getDocumentPageCount().then((value) {
+      setState(() {
+        pageCount = value;
+      });
+    });
   }
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      children: [
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-          children: [
-            _linkTypeWidget(LinkType.web, Icons.language, 'URL'),
-            _linkTypeWidget(LinkType.page, Icons.description_outlined, 'Page'),
-            _linkTypeWidget(LinkType.email, Icons.email_outlined, 'Email')
-          ],
-        ),
-        if (selectType == LinkType.web) ...{
-          TextField(
-            controller: _webTextController,
-            keyboardType: TextInputType.url,
-          )
-        } else if (selectType == LinkType.page) ...{
-          TextField(
-            controller: _pageTextController,
-            keyboardType: TextInputType.number,
-            decoration:const InputDecoration(hintText: '1-10',hintStyle: TextStyle(fontSize: 12)),
-          )
-        } else ...{
-          TextField(
-            controller: _emailTextController,
-            keyboardType: TextInputType.emailAddress,
-            decoration: const InputDecoration(hintText: 'support@17pdf.com',hintStyle: TextStyle(fontSize: 12)),
-          )
-        }
+    return  AlertDialog(
+      title: const Text('New Link'),
+      content: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+            children: [
+              _linkTypeWidget(LinkType.website, Icons.language, 'URL'),
+              _linkTypeWidget(LinkType.page, Icons.description_outlined, 'Page'),
+              _linkTypeWidget(LinkType.email, Icons.email_outlined, 'Email')
+            ],
+          ),
+          if (selectType == LinkType.website) ...{
+            TextField(
+              controller: _webTextController,
+              keyboardType: TextInputType.url,
+              onChanged: (value){
+                checkDataIsValid();
+              },
+            )
+          } else if (selectType == LinkType.page) ...{
+            TextField(
+              controller: _pageTextController,
+              keyboardType: TextInputType.number,
+              decoration: InputDecoration(hintText: '1-$pageCount',hintStyle: const TextStyle(fontSize: 12)),
+              onChanged: (value){
+                checkDataIsValid();
+              },
+            )
+          } else ...{
+            TextField(
+              controller: _emailTextController,
+              keyboardType: TextInputType.emailAddress,
+              decoration: const InputDecoration(hintText: 'support@17pdf.com',hintStyle: TextStyle(fontSize: 12)),
+              onChanged: (value){
+                checkDataIsValid();
+              },
+            )
+          }
+        ],
+      ),
+      actions: [
+        TextButton(
+            onPressed: () {
+              widget.cancelCreateCallback(true);
+              Navigator.pop(context);
+            },
+            child: const Text('Cancel', style: TextStyle(color: Colors.grey),)),
+        TextButton(onPressed: linkDataIsValid ? () {
+          widget.callback(selectType, _webTextController.text, _pageTextController.text.isNotEmpty ? int.parse(_pageTextController.text) : 0, _emailTextController.text);
+          Navigator.pop(context);
+        } : null, child: Text('Done',style: TextStyle(color: linkDataIsValid ? Colors.blue : Colors.grey),))
       ],
     );
   }
 
+  void checkDataIsValid() {
+    setState(() {
+      switch(selectType){
+        case LinkType.website:
+          linkDataIsValid =  _webTextController.text.isNotEmpty;
+          break;
+        case LinkType.page :
+          linkDataIsValid = _pageTextController.text.isNotEmpty;
+          break;
+        case LinkType.email:
+          linkDataIsValid = _emailTextController.text.isNotEmpty;
+          break;
+      }
+    });
+  }
+
   Widget _linkTypeWidget(LinkType linkType, IconData icon, String title) {
     return InkWell(
       child: Column(
@@ -72,7 +142,24 @@ class _AttrLinkWidgetState extends State<AttrLinkWidget> {
         setState(() {
           selectType = linkType;
         });
+        checkDataIsValid();
       },
     );
   }
+
+
+  void initLinkData(){
+    selectType = widget.attributeBean.linkType;
+    switch(selectType){
+      case LinkType.website:
+        _webTextController.text = widget.attributeBean.linkWeb.isEmpty ? "http://" : widget.attributeBean.linkWeb;
+        break;
+      case LinkType.email:
+        _emailTextController.text = widget.attributeBean.linkEmail;
+        break;
+      case LinkType.page:
+        _pageTextController.text = widget.attributeBean.linkPage.toString();
+        break;
+    }
+  }
 }

+ 1 - 1
lib/widgets/function/attrwidget/attr_shape_type_widget.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_color_list_widget.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_shape_bean.dart';

+ 1 - 1
lib/widgets/function/attrwidget/stamp/attr_stamp_widget.dart

@@ -1,7 +1,7 @@
 import 'dart:io';
 
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/stamp/attr_custom_stamp_edit_widget.dart';
 import 'package:kmpdfkit_demo/widgets/models/standard_stamp_bean.dart';
 import 'package:kmpdfkit_demo/widgets/models/text_stamp_bean.dart';

+ 4 - 15
lib/widgets/function/pdf_bottom_annot_fun_widget.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_svg/flutter_svg.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/events.dart';
 import 'package:kmpdfkit_demo/widgets/function/annot_attribute_options_widget.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/signature/attr_signature_list_widget.dart';
@@ -219,20 +219,9 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
       Future<void> close = showDialog(
           context: context,
           builder: (context) {
-            return AlertDialog(
-              title: const Text('New Link'),
-              content: AnnotAttributeOptionsWidget(
-                attributeOptionsCallback: callback,
-                annotBean: annotBean,
-              ),
-              actions: [
-                TextButton(
-                    onPressed: () {
-                      Navigator.pop(context);
-                    },
-                    child: const Text('Cancel', style: TextStyle(color: Colors.grey),)),
-                TextButton(onPressed: () {}, child: const Text('Done'))
-              ],
+            return AnnotAttributeOptionsWidget(
+              attributeOptionsCallback: callback,
+              annotBean: annotBean,
             );
           });
       close.then((value) {

+ 1 - 1
lib/widgets/function/setting/setting_pdf_page_turning_widget.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 import 'package:kmpdfkit_demo/widgets/events.dart';
 
 

+ 52 - 6
lib/widgets/models/annot_attribute_bean.dart

@@ -3,7 +3,7 @@ import 'dart:ui';
 import 'package:flutter/material.dart';
 import 'package:kmpdfkit_demo/widgets/models/text_stamp_bean.dart';
 
-import '../constains.dart';
+import '../contains.dart';
 import '../extension/color_extension.dart';
 
 ///  annot_attribute_bean.dart
@@ -45,6 +45,13 @@ class AnnotAttributeBean {
   String standardStampName;
   TextStampBean? customStampBean;
 
+  ///link
+  LinkType linkType;
+  String linkWeb;
+  int linkPage;
+  String linkEmail;
+  bool cancelCreateLink = false;
+
   AnnotAttributeBean(
       {this.color = Colors.red,
       this.alpha = 255,
@@ -64,7 +71,12 @@ class AnnotAttributeBean {
       this.imagePath = '',
       this.isSignature = false,
       this.standardStampName = '',
-      this.customStampBean});
+      this.customStampBean,
+      this.linkType = LinkType.website,
+      this.linkWeb = '',
+      this.linkPage = 1,
+      this.linkEmail = '',
+      this.cancelCreateLink = false});
 
   @override
   String toString() {
@@ -85,7 +97,11 @@ class AnnotAttributeBean {
         "imagePath:${imagePath},"
         "isSignature:${isSignature},"
         "standardStampName:${standardStampName},"
-        "customStampBean:${customStampBean?.toString()}";
+        "customStampBean:${customStampBean?.toString()},"
+        "linkType:${linkType.name},"
+        "linkWeb:${linkWeb},"
+        "linkPage:$linkPage,"
+        "linkEmail:$linkEmail}";
   }
 
   static AnnotAttributeBean parseMapValue(
@@ -102,7 +118,7 @@ class AnnotAttributeBean {
     String fillColor =
         result[EventParameters.annotAttrFillColor] ?? Colors.red.toHex();
     int fillColorAlpha = result[EventParameters.annotAttrFillColorAlpha] ?? 255;
-    String shapeTypeStr = result[EventParameters.annotAttrShapeType] ?? "";
+    String shapeTypeStr = result[EventParameters.annotAttrShapeType] ?? '';
     AnnotationType shapeType = shapeTypeStr.isEmpty
         ? annotationType
         : AnnotationType.values.byName(shapeTypeStr);
@@ -116,6 +132,10 @@ class AnnotAttributeBean {
     String fontType =
         result[EventParameters.annotAttrFontType] ?? FontType.helvetica.name;
 
+    String linkType = result[EventParameters.annotLinkType] ?? LinkType.website.name;
+    String linkWebSite = result[EventParameters.annotLinkWeb] ?? '';
+    int linkPage = result[EventParameters.annotLinkPage] ?? 1;
+    String linkEmail = result[EventParameters.annotLinkEmail] ?? '';
     return AnnotAttributeBean(
         color: HexColor.fromHex(annotAttrColor),
         alpha: annotAttrAlpha,
@@ -131,7 +151,11 @@ class AnnotAttributeBean {
         textColor: HexColor.fromHex(textColor),
         textColorAlpha: textColorAlpha,
         fontSize: fontSize.toInt(),
-        fontType: FontType.values.byName(fontType.toLowerCase()));
+        fontType: FontType.values.byName(fontType.toLowerCase()),
+        linkType: LinkType.values.byName(linkType.toLowerCase()),
+        linkWeb: linkWebSite,
+        linkPage: linkPage,
+        linkEmail: linkEmail);
   }
 
   Map<dynamic, dynamic> toMapValues(AnnotationType annotationType) {
@@ -198,7 +222,29 @@ class AnnotAttributeBean {
           };
         }
       case AnnotationType.link:
-        return {};
+        switch (linkType) {
+          case LinkType.website:
+            return {
+              EventParameters.annotType: annotationType.name,
+              EventParameters.annotLinkType: linkType.name,
+              EventParameters.annotLinkWeb: linkWeb,
+              EventParameters.annotLinkCancelCreate: cancelCreateLink
+            };
+          case LinkType.page:
+            return {
+              EventParameters.annotType: annotationType.name,
+              EventParameters.annotLinkType: linkType.name,
+              EventParameters.annotLinkPage: linkPage,
+              EventParameters.annotLinkCancelCreate: cancelCreateLink
+            };
+          case LinkType.email:
+            return {
+              EventParameters.annotType: annotationType.name,
+              EventParameters.annotLinkType: linkType.name,
+              EventParameters.annotLinkEmail: linkEmail,
+              EventParameters.annotLinkCancelCreate: cancelCreateLink
+            };
+        }
       case AnnotationType.unknown:
         return {};
     }

+ 1 - 1
lib/widgets/models/annot_bean.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 
 import 'annot_attribute_bean.dart';
 

+ 1 - 1
lib/widgets/models/annot_shape_bean.dart

@@ -1,5 +1,5 @@
 
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 
 ///  annot_shape_bean.dart
 ///

+ 1 - 1
lib/widgets/models/standard_stamp_bean.dart

@@ -1,5 +1,5 @@
 
-import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/contains.dart';
 
 
 ///  standard_stamp_bean.dart