ReaderActivity.kt 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. package com.kdanmobile.reader
  2. import android.annotation.SuppressLint
  3. import android.app.Activity
  4. import android.app.Dialog
  5. import android.arch.lifecycle.Observer
  6. import android.arch.lifecycle.ViewModelProviders
  7. import android.content.Intent
  8. import android.net.Uri
  9. import android.os.Build
  10. import android.os.Bundle
  11. import android.support.constraint.ConstraintLayout
  12. import android.support.constraint.ConstraintSet
  13. import android.support.design.widget.Snackbar
  14. import android.support.v4.content.ContextCompat
  15. import android.support.v7.app.AlertDialog
  16. import android.support.v7.app.AppCompatActivity
  17. import android.util.DisplayMetrics
  18. import android.view.*
  19. import android.view.animation.AnimationUtils
  20. import android.widget.EditText
  21. import android.widget.LinearLayout
  22. import android.widget.TextView
  23. import android.widget.Toast
  24. import com.kdanmobile.kmpdfkit.globaldata.KMPDFAnnotEditMode
  25. import com.kdanmobile.kmpdfkit.pdfcommon.KMPDFReaderView
  26. import com.kdanmobile.kmpdfkit.pdfcommon.PDFInfo
  27. import com.kdanmobile.reader.Utils.applyConstraintSet
  28. import com.kdanmobile.reader.annotationattribute.AnnotationAttribute
  29. import com.kdanmobile.reader.annotationattribute.AnnotationColor
  30. import com.kdanmobile.reader.annotationattribute.InkAttribute
  31. import com.kdanmobile.reader.password.DialogPasswordActivity
  32. import com.kdanmobile.reader.screen.contextmenu.TextBoxContextMenuActionListener
  33. import com.kdanmobile.reader.screen.model.SharePrefsModel
  34. import com.kdanmobile.reader.screen.reader.mediabox.MediaBoxView
  35. import com.kdanmobile.reader.screen.reader.mediabox.shape.ShapeTabView
  36. import com.kdanmobile.reader.screen.reader.mediabox.signature.SignatureTabView
  37. import com.kdanmobile.reader.screen.reader.mediabox.stamp.StampTabView
  38. import com.kdanmobile.reader.screen.reader.mediabox.textbox.TextBoxTabView
  39. import com.kdanmobile.reader.screen.view.*
  40. import com.kdanmobile.reader.setting.ReaderSettingDialogFragment
  41. import com.kdanmobile.reader.setting.ReaderSettingListener
  42. import com.kdanmobile.reader.thumb.FileUtil
  43. import com.kdanmobile.reader.thumb.PdfThumbActivity
  44. import com.kdanmobile.reader.utils.AnimationUtil
  45. import com.kdanmobile.reader.utils.DensityUtil
  46. import com.kdanmobile.reader.utils.UriToPathUtil
  47. import com.kdanmobile.reader.view.AnnotationAttributeView
  48. import com.kdanmobile.reader.view.AnnotationAttributeWindow
  49. import kotlinx.android.synthetic.main.activity_reader.*
  50. import java.io.File
  51. import java.util.*
  52. import kotlin.properties.Delegates
  53. abstract class ReaderActivity : AppCompatActivity(), ReaderSettingListener {
  54. /**
  55. * If return true, ReaderActivity.onBackPressed will not run
  56. */
  57. abstract fun onBackPressedWhenNothingCanClose(): Boolean
  58. abstract fun onClickShare()
  59. abstract fun onClickKdanCloud()
  60. abstract fun onClickTextReflow()
  61. abstract fun onClickFileInfo()
  62. abstract fun onClickIBonPrint()
  63. abstract fun onClickPrint()
  64. abstract fun onClickUserGuide()
  65. abstract fun transferThumbIntent(): Intent
  66. abstract fun provideReaderSettingDialogFragment(): ReaderSettingDialogFragment
  67. abstract fun getKdanPdfReaderFolder(): File
  68. abstract fun isIBonPrintEnabled(): Boolean
  69. open fun isBottomBarKdanCloudBtnVisible(): Boolean { return true }
  70. open fun insertToRecentDocumentList(filename: String) {}
  71. open fun saveCurrentPageIndex(filename: String, currentPage: Int) {}
  72. open fun loadCurrentPageIndex(filename: String, defaultValue: Int): Int = 0
  73. companion object {
  74. const val KEY_FILE_ABSOLUTE = "file_absolutepath"
  75. const val THUMB = 221
  76. const val REQUEST_PASSWORD = 222
  77. }
  78. protected val file: File?
  79. get() {
  80. return viewModel.file
  81. }
  82. protected var filePath: String? = null
  83. private set
  84. protected val pdfInfo: PDFInfo?
  85. get() {
  86. return viewModel.pdfInfo
  87. }
  88. protected val isPasswordProtected: Boolean
  89. get() {
  90. return viewModel.isPasswordProtected
  91. }
  92. protected val currentPageIndex: Int
  93. get() {
  94. return viewModel.pdfInfoHandler.getCurrentPage()
  95. }
  96. protected val pageCount: Int
  97. get() {
  98. return viewModel.pdfInfoHandler.getPdfPageCount()
  99. }
  100. protected val password: String
  101. get() {
  102. return viewModel.password
  103. }
  104. protected val readerModel: ReaderModel
  105. get() {
  106. return viewModel.readerModel
  107. }
  108. private lateinit var viewModel: ReaderViewModel
  109. private var isShowPasswordActivity = false
  110. // For hide/show toolbars
  111. private var isHideToolbar = false
  112. private lateinit var originConstraintSet: ConstraintSet
  113. private var menuItemBookmark: MenuItem? = null
  114. private val UI_ANIMATION_DURATION = 300L
  115. private val FRAGMENT_READER_SETTING_TAG = "ReaderSetting"
  116. private var w_318: Int = 0
  117. private var w_240: Int = 0
  118. private var w_left: Int = 0
  119. private var oldLeftToolbarType = ReaderViewModel.LeftToolbarType.NONE
  120. private var snackbarMediaBox: Snackbar? = null
  121. private var fileCannotOpenDialog: AlertDialog? = null
  122. private var isHidePdfPage: Boolean by Delegates.observable(false) { property, oldValue, newValue ->
  123. if (newValue == oldValue) return@observable
  124. // println("${property.name} changed from $oldValue to $newValue")
  125. tv_readerActivity_pdfPage.clearAnimation()
  126. when (newValue) {
  127. true -> tv_readerActivity_pdfPage.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out))
  128. false -> tv_readerActivity_pdfPage.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in))
  129. }
  130. }
  131. override fun onCreate(savedInstanceState: Bundle?) {
  132. super.onCreate(savedInstanceState)
  133. window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  134. setContentView(R.layout.activity_reader)
  135. setSupportActionBar(toolbar_readerActivity)
  136. isShowPasswordActivity = savedInstanceState?.getBoolean("isShowPasswordActivity") ?: false
  137. filePath = savedInstanceState?.getString("filePath")
  138. val copyFile = intent.getBooleanExtra("copyFile", true)
  139. val displayMetrics = DisplayMetrics()
  140. windowManager.defaultDisplay.getMetrics(displayMetrics)
  141. val width = Math.min(DensityUtil.getScreenWidthPx(baseContext), DensityUtil.getScreenHeightPx(baseContext))
  142. w_318 = 318 * width / 800
  143. w_240 = 240 * width / 800
  144. w_left = resources.getDimension(R.dimen.reader_left_right_toolbar_icon_width).toInt()
  145. cloneOriginConstraintSet()
  146. setupToolbar()
  147. setupRightSideToolbar()
  148. setupMediaBoxView()
  149. FileUtil.init(getKdanPdfReaderFolder())
  150. val factory = ReaderViewModelFactory()
  151. viewModel = ViewModelProviders.of(this, factory).get(ReaderViewModel::class.java)
  152. viewModel.isOpenedFileLiveData.observe(this, Observer(this::onIsOpenedFileUpdate))
  153. viewModel.fileNameLiveData.observe(this, Observer { supportActionBar?.title = it })
  154. viewModel.annotationModeLiveData.observe(this, Observer(this::onAnnotationModeUpdate))
  155. viewModel.annotationEitModeLiveData.observe(this, Observer(this::onAnnotationEditModeUpdate))
  156. viewModel.isCopyModeLiveData.observe(this, Observer (this::onIsCopyModeUpdate))
  157. viewModel.highLightAttributeLiveData.observe(this, Observer(this::onHighlightAttributeUpdate))
  158. viewModel.strikeAttributeLiveData.observe(this, Observer(this::onStrikeAttributeUpdate))
  159. viewModel.underLineAttributeLiveData.observe(this, Observer(this::onUnderlineAttributeUpdate))
  160. viewModel.inkAttributeLiveData.observe(this, Observer(this::onInkAttributeUpdate))
  161. viewModel.isOpenedFileLiveData.value?.also { isOpened ->
  162. val hasOpened = null != filePath
  163. if (isShowPasswordActivity) return@also
  164. if (isOpened) return@also
  165. filePath = if (intent.action == Intent.ACTION_VIEW) {
  166. UriToPathUtil.getInstance().getPath(applicationContext, intent.data)
  167. } else {
  168. intent.getStringExtra(KEY_FILE_ABSOLUTE)
  169. }
  170. if (!hasOpened) {
  171. val copyMode = if (copyFile) FileUtil.CopyMode.CREATE_NEW_FILE else FileUtil.CopyMode.DO_NOTHING
  172. if (!filePath.isNullOrEmpty()) {
  173. filePath = FileUtil.copyFileToKdanPdfReaderFolder(filePath as String, copyMode)
  174. } else if (intent.action == Intent.ACTION_VIEW && null != intent.data) {
  175. filePath = FileUtil.saveFileToKdanPdfReaderFolder(this, intent.data!!, copyMode)
  176. }
  177. if (!filePath.isNullOrEmpty()) {
  178. insertToRecentDocumentList(filePath as String)
  179. }
  180. }
  181. if (filePath.isNullOrEmpty()) {
  182. showFileCannotOpenDialog(getString(R.string.cannot_open_buffer))
  183. } else {
  184. val result = viewModel.openPdfFile(applicationContext, Uri.parse(filePath), password, Runnable { requestPassword() }, intent.type)
  185. if (result == ReaderViewModel.OpenFileResult.FAILED) {
  186. showFileCannotOpenDialog(getString(R.string.cannot_open_file_Path, filePath))
  187. }
  188. }
  189. }
  190. setupLeftToolbar()
  191. setupRightToolbar()
  192. setupBottomToolbar()
  193. viewModel.pageIndexLiveData.observe(this, Observer(this::onPageIndexChanged))
  194. viewModel.isPageInBookmarksLiveData.observe(this, Observer(this::onIsPageInBookmarksChanged))
  195. viewModel.isLeftToolbarOpenLiveData.observe(this, Observer(this::onLeftToolbarOpenStateChanged))
  196. viewModel.leftToolbarTypeLiveData.observe(this, Observer(this::onLeftToolbarTypeChanged))
  197. isHidePdfPage = true
  198. applySetting()
  199. setupPdfChangedListener()
  200. }
  201. private fun showFileCannotOpenDialog(title: String) {
  202. fileCannotOpenDialog = AlertDialog.Builder(this)
  203. .setTitle(title)
  204. .setCancelable(false)
  205. .setPositiveButton(getString(android.R.string.ok)) { dialog, which ->
  206. finish()
  207. }
  208. .create()
  209. fileCannotOpenDialog?.show()
  210. }
  211. override fun onDestroy() {
  212. fileCannotOpenDialog?.dismiss()
  213. super.onDestroy()
  214. }
  215. override fun onSaveInstanceState(outState: Bundle?) {
  216. super.onSaveInstanceState(outState)
  217. outState?.putBoolean("isShowPasswordActivity", isShowPasswordActivity)
  218. outState?.putString("filePath", filePath)
  219. }
  220. private fun requestPassword(isIncorrectPassword: Boolean = false) {
  221. isShowPasswordActivity = true
  222. val intent = Intent(baseContext, DialogPasswordActivity::class.java)
  223. val bundle = Bundle()
  224. bundle.putBoolean("isIncorrectPassword", isIncorrectPassword)
  225. intent.putExtras(bundle)
  226. startActivityForResult(intent, REQUEST_PASSWORD)
  227. }
  228. fun isPdf(): Boolean {
  229. var isPdf = filePath?.toLowerCase(Locale.US)?.endsWith(".pdf") ?: false
  230. // TODO this workaround should be removed in the future
  231. // workaround: password-protected pdf is not editable
  232. isPdf = isPdf && !isPasswordProtected
  233. return isPdf
  234. }
  235. final override fun onBackPressed() {
  236. when {
  237. mediaBoxView.isShown -> mediaBoxView.dismiss()
  238. onBackPressedWhenNothingCanClose() -> { /** do nothing **/ }
  239. else -> super.onBackPressed()
  240. }
  241. }
  242. override fun onCreateOptionsMenu(menu: Menu?): Boolean {
  243. menuInflater.inflate(R.menu.reader_more, menu)
  244. menuItemBookmark = menu?.findItem(R.id.item_reader_bookmark)
  245. onIsPageInBookmarksChanged(viewModel.isPageInBookmarksLiveData.value)
  246. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  247. menu?.findItem(R.id.item_reader_more_print)?.isVisible = false
  248. }
  249. if (!isPdf()) {
  250. menu?.apply {
  251. findItem(R.id.item_reader_more_text_reflow)?.isVisible = false
  252. findItem(R.id.item_reader_more_clear_signature)?.isVisible = false
  253. findItem(R.id.item_reader_more_file_info)?.isVisible = false
  254. findItem(R.id.item_reader_more_print)?.isVisible = false
  255. findItem(R.id.item_ibon_print)?.isVisible = false
  256. }
  257. menuItemBookmark?.isVisible = false
  258. }
  259. if (!isIBonPrintEnabled()) {
  260. menu?.findItem(R.id.item_ibon_print)?.isVisible = false
  261. }
  262. return true
  263. }
  264. @SuppressLint("RestrictedApi")
  265. override fun onPrepareOptionsPanel(view: View?, menu: Menu?): Boolean {
  266. /** Force show action menu item icon **/
  267. menu?.also {
  268. if ("MenuBuilder" != it::javaClass.get().simpleName) return@also
  269. try {
  270. val method = it.javaClass.getDeclaredMethod("setOptionalIconsVisible", java.lang.Boolean.TYPE)
  271. method.isAccessible = true
  272. method.invoke(it, true)
  273. } catch (e: Exception) {
  274. // Do nothing
  275. }
  276. }
  277. return super.onPrepareOptionsPanel(view, menu)
  278. }
  279. protected fun getPageText(pageIndex: Int) = viewModel.getPageText(pageIndex)
  280. private fun cloneOriginConstraintSet() {
  281. if (!isBelowKitkat()) {
  282. originConstraintSet = ConstraintSet().apply {
  283. clone(constrainLayout_readerActivity_root)
  284. }
  285. }
  286. }
  287. private fun onIsCopyModeUpdate(isCopyMode: Boolean?) {
  288. if (isCopyMode == null) return
  289. when (isCopyMode) {
  290. true -> hideTopLeftBottomToolbars()
  291. false -> showAllToolbars()
  292. }
  293. }
  294. private fun onHighlightAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  295. if (annotationAttribute == null) return
  296. view_readerActivity_highLightStroke.setBackgroundColor(annotationAttribute.color)
  297. }
  298. private fun onStrikeAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  299. if (annotationAttribute == null) return
  300. view_readerActivity_strikeStroke.setBackgroundColor(annotationAttribute.color)
  301. }
  302. private fun onUnderlineAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  303. if (annotationAttribute == null) return
  304. view_readerActivity_underlineStroke.setBackgroundColor(annotationAttribute.color)
  305. }
  306. private fun onInkAttributeUpdate(inkAttribute: InkAttribute?) {
  307. if (inkAttribute == null) return
  308. val color = inkAttribute.color
  309. AnnotationColor.values().forEach {
  310. if (ContextCompat.getColor(this, it.colorResId) == color) {
  311. val drawableResId = when (it) {
  312. AnnotationColor.Color1 -> R.drawable.ic_reader_right_toolbar_ink_color1
  313. AnnotationColor.Color2 -> R.drawable.ic_reader_right_toolbar_ink_color2
  314. AnnotationColor.Color3 -> R.drawable.ic_reader_right_toolbar_ink_color3
  315. AnnotationColor.Color4 -> R.drawable.ic_reader_right_toolbar_ink_color4
  316. AnnotationColor.Color5 -> R.drawable.ic_reader_right_toolbar_ink_color5
  317. AnnotationColor.Color6 -> R.drawable.ic_reader_right_toolbar_ink_color6
  318. AnnotationColor.Color7 -> R.drawable.ic_reader_right_toolbar_ink_color7
  319. AnnotationColor.Color8 -> R.drawable.ic_reader_right_toolbar_ink_color8
  320. AnnotationColor.Color9 -> R.drawable.ic_reader_right_toolbar_ink_color9
  321. AnnotationColor.Color10 -> R.drawable.ic_reader_right_toolbar_ink_color10
  322. }
  323. iv_readerActivity_ink.setImageResource(drawableResId)
  324. return
  325. }
  326. }
  327. }
  328. private fun onAnnotationModeUpdate(annotationMode: ReaderViewModel.AnnotationMode?) {
  329. if (annotationMode == null) return
  330. if (viewModel.isCrop) return
  331. val map = HashMap<ReaderViewModel.AnnotationMode, View>().apply {
  332. put(ReaderViewModel.AnnotationMode.Highlight, iv_readerActivity_highLight)
  333. put(ReaderViewModel.AnnotationMode.Strike, iv_readerActivity_strike)
  334. put(ReaderViewModel.AnnotationMode.Underline, iv_readerActivity_underline)
  335. put(ReaderViewModel.AnnotationMode.Ink, iv_readerActivity_ink)
  336. }
  337. map.forEach {
  338. if (it.key == annotationMode) {
  339. val color = ContextCompat.getColor(this, R.color.reader_right_toolbar_selected_bg)
  340. it.value.setBackgroundColor(color)
  341. } else {
  342. it.value.setBackgroundDrawable(null)
  343. }
  344. }
  345. when (annotationMode == ReaderViewModel.AnnotationMode.None) {
  346. true -> showAllToolbars()
  347. false -> hideTopLeftBottomToolbars()
  348. }
  349. readerModel.onPdfChangedListener?.onPageUpdated(arrayListOf(currentPageIndex))
  350. }
  351. private fun onAnnotationEditModeUpdate(mode: KMPDFAnnotEditMode.Mode?) {
  352. when (mode) {
  353. KMPDFAnnotEditMode.Mode.NULL -> {
  354. showAllToolbars()
  355. isHideToolbar = false
  356. snackbarMediaBox?.dismiss()
  357. snackbarMediaBox = null
  358. }
  359. KMPDFAnnotEditMode.Mode.SIGN_MODIFY -> {
  360. hideAllToolbars()
  361. isHideToolbar = true
  362. }
  363. KMPDFAnnotEditMode.Mode.FREETEXT_MODIFY, KMPDFAnnotEditMode.Mode.STAMP_MODIFY, KMPDFAnnotEditMode.Mode.SHAPE_MODIFY -> {
  364. hideAllToolbars()
  365. isHideToolbar = true
  366. snackbarMediaBox?.dismiss()
  367. snackbarMediaBox = null
  368. }
  369. else -> {}
  370. }
  371. isHidePdfPage = true
  372. readerModel.onPdfChangedListener?.onPageUpdated(arrayListOf(currentPageIndex))
  373. }
  374. private fun onIsOpenedFileUpdate(isOpened: Boolean?) {
  375. if (isOpened == null) return
  376. val container = viewGroup_readerActivity_container
  377. container.removeAllViews()
  378. if (!isOpened) return
  379. val context = this
  380. val readerView = object : KMPDFReaderView(context) {
  381. @SuppressLint("ClickableViewAccessibility")
  382. override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
  383. if (motionEvent.action == MotionEvent.ACTION_UP) {
  384. if (viewModel.isCopyModeLiveData.value == true) {
  385. if (viewModel.copySelection()) {
  386. val context = this@ReaderActivity
  387. Toast.makeText(context, R.string.reader_copy_text_success, Toast.LENGTH_SHORT).show()
  388. }
  389. }
  390. }
  391. return super.onTouchEvent(motionEvent)
  392. }
  393. override fun onTapMainDocArea() {
  394. super.onTapMainDocArea()
  395. when (isHideToolbar) {
  396. true -> {
  397. showAllToolbars()
  398. viewModel.clearSelection()
  399. }
  400. false -> hideAllToolbars()
  401. }
  402. isHideToolbar = !isHideToolbar
  403. }
  404. override fun onMoveToChild(pageIndex: Int) {
  405. super.onMoveToChild(pageIndex)
  406. viewModel.setPageIndex(pageIndex)
  407. }
  408. override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
  409. val isEditMode = viewModel.annotationModeLiveData.value != ReaderViewModel.AnnotationMode.None
  410. val isCopyMode = viewModel.isCopyModeLiveData.value != false
  411. if (!isEditMode && !isCopyMode && !isHideToolbar) {
  412. hideAllToolbars()
  413. isHideToolbar = true
  414. }
  415. isHidePdfPage = isEditMode || isCopyMode
  416. return super.onScroll(e1, e2, distanceX, distanceY)
  417. }
  418. }
  419. viewModel.setReaderView(readerView)
  420. if (!filePath.isNullOrEmpty()) {
  421. val defaultValue = viewModel.pageIndexLiveData.value ?: 0
  422. val pageIndex = loadCurrentPageIndex(filePath as String, defaultValue)
  423. viewModel.pdfInfoHandler.setCurrentPage(pageIndex)
  424. viewModel.fileNameLiveData.postValue(File(filePath as String).name)
  425. }
  426. initTextBoxContextMenuActions()
  427. container.addView(readerView)
  428. val model = SharePrefsModel(this)
  429. onReadModeChanged(model.readMode.value ?: 0)
  430. if (model.isCropModeEnable.value == true) {
  431. readerView.post {
  432. onCropModeEnableChanged(true)
  433. }
  434. }
  435. }
  436. private fun initTextBoxContextMenuActions() {
  437. viewModel.setTextBoxContextMenuActions(object : TextBoxContextMenuActionListener {
  438. override fun onDelete(): Boolean {
  439. viewModel.deleteSelectedTextBox()
  440. return true
  441. }
  442. override fun onEditStyle(): Boolean {
  443. mediaBoxView.showTextBoxStyleView()
  444. viewModel.editSelectedTextBoxStyle()
  445. return true
  446. }
  447. override fun onEditText(): Boolean {
  448. hideAllToolbars()
  449. isHideToolbar = true
  450. viewModel.editSelectedTextBoxText()
  451. return true
  452. }
  453. override fun onCopy(): Boolean {
  454. viewModel.copySelectedTextBox()
  455. return true
  456. }
  457. })
  458. }
  459. override fun onStop() {
  460. viewModel.saveModifyingAnnotation()
  461. viewModel.temporarySave()
  462. if (!filePath.isNullOrEmpty()) {
  463. saveCurrentPageIndex(filePath as String, currentPageIndex)
  464. }
  465. super.onStop()
  466. }
  467. private fun onPageIndexChanged(pageIndex: Int?) {
  468. pageIndex?.also {
  469. viewModel.setBookmarkDisplay(pageIndex)
  470. readerModel.onPdfChangedListener?.onPageSelected(pageIndex)
  471. tv_readerActivity_pdfPage.post {
  472. tv_readerActivity_pdfPage.text="${(pageIndex) + 1}/${viewModel.pdfInfoHandler.getPdfPageCount()}"
  473. }
  474. }
  475. }
  476. private fun onIsPageInBookmarksChanged(isPageInBookmarks: Boolean?) {
  477. isPageInBookmarks?.let {
  478. if (it) {
  479. menuItemBookmark?.icon = ContextCompat.getDrawable(this, R.drawable.ic_bookmark_fill)
  480. } else {
  481. menuItemBookmark?.icon = ContextCompat.getDrawable(this, R.drawable.ic_bookmark_border)
  482. }
  483. }
  484. }
  485. private fun isBelowKitkat(): Boolean {
  486. return true
  487. // return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT
  488. }
  489. private fun showAllToolbars() {
  490. if (isBelowKitkat()) {
  491. val duration = ((1 - toolbar_readerActivity.alpha) * UI_ANIMATION_DURATION).toLong()
  492. AnimationUtil.showViewFromTopToBottom(toolbar_readerActivity, duration)
  493. AnimationUtil.showViewFromBottomToTop(viewGroup_readerActivity_bottomToolbar, duration)
  494. AnimationUtil.showViewFromLeftToRight(viewGroup_readerActivity_leftToolbar, duration)
  495. AnimationUtil.showViewFromRightToLeft(viewGroup_readerActivity_rightToolbar, duration)
  496. } else {
  497. constrainLayout_readerActivity_root.applyConstraintSet(originConstraintSet, UI_ANIMATION_DURATION)
  498. }
  499. isHidePdfPage = true
  500. }
  501. private fun hideAllToolbars() {
  502. if (isBelowKitkat()) {
  503. val duration = (toolbar_readerActivity.alpha * UI_ANIMATION_DURATION).toLong()
  504. AnimationUtil.hideViewFromBottomToTop(toolbar_readerActivity, duration)
  505. AnimationUtil.hideViewFromTopToBottom(viewGroup_readerActivity_bottomToolbar, duration)
  506. AnimationUtil.hideViewFromRightToLeft(viewGroup_readerActivity_leftToolbar, duration)
  507. AnimationUtil.hideViewFromLeftToRight(viewGroup_readerActivity_rightToolbar, duration)
  508. hideSearchViewSoftKeyboard()
  509. } else {
  510. constrainLayout_readerActivity_root.applyConstraintSet(this, R.layout.activity_reader_hide_all, UI_ANIMATION_DURATION)
  511. }
  512. }
  513. private fun hideTopLeftBottomToolbars() {
  514. if (isBelowKitkat()) {
  515. val duration = (toolbar_readerActivity.alpha * UI_ANIMATION_DURATION).toLong()
  516. AnimationUtil.hideViewFromBottomToTop(toolbar_readerActivity, duration)
  517. AnimationUtil.hideViewFromTopToBottom(viewGroup_readerActivity_bottomToolbar, duration)
  518. AnimationUtil.hideViewFromRightToLeft(viewGroup_readerActivity_leftToolbar, duration)
  519. hideSearchViewSoftKeyboard()
  520. } else {
  521. constrainLayout_readerActivity_root.applyConstraintSet(this, R.layout.activity_reader_hide_top_left_bottom, UI_ANIMATION_DURATION)
  522. }
  523. }
  524. private fun setupPdfChangedListener() {
  525. readerModel.onPdfChangedListener = object : OnPdfChangedListener {
  526. override fun onPageCreated(pages: List<Int>) {
  527. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
  528. }
  529. override fun onPageDeleted(pages: List<Int>) {
  530. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  531. if (view is LeftToolbarView) {
  532. view.updateContent()
  533. view.onScrollToContent(currentPageIndex, true)
  534. }
  535. }
  536. override fun onPageSelected(pageIndex: Int) {
  537. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  538. if (view is LeftToolbarView) {
  539. view.onScrollToContent(currentPageIndex, true)
  540. }
  541. }
  542. override fun onPageUpdated(pages: List<Int>) {
  543. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  544. if (view is LeftToolbarView) {
  545. view.updateContent()
  546. view.onScrollToContent(currentPageIndex, true)
  547. }
  548. }
  549. }
  550. }
  551. private fun updateBookmarkView() {
  552. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  553. if (view is BookmarkView) {
  554. view.updateContent()
  555. view.onScrollToContent(currentPageIndex, true)
  556. }
  557. }
  558. private fun setupToolbar() {
  559. toolbar_readerActivity.setNavigationOnClickListener { finish() }
  560. toolbar_readerActivity.setOnMenuItemClickListener {
  561. when (it.itemId) {
  562. R.id.item_reader_bookmark -> onClickBookmark()
  563. R.id.item_reader_more_text_reflow -> onClickTextReflow()
  564. R.id.item_reader_more_file_info -> onClickFileInfo()
  565. R.id.item_ibon_print -> onClickIBonPrint()
  566. R.id.item_reader_more_print -> onClickPrint()
  567. R.id.item_reader_more_user_guide -> onClickUserGuide()
  568. R.id.item_reader_more_clear_signature -> onClickClearSignature()
  569. }
  570. return@setOnMenuItemClickListener true
  571. }
  572. }
  573. private fun onClickBookmark() {
  574. viewModel.isPageInBookmarksLiveData.value?.let {
  575. if (!it) {
  576. showAddBookmarkDialog()
  577. } else {
  578. showDeleteBookmarkDialog()
  579. }
  580. }
  581. }
  582. private fun onClickClearSignature() {
  583. AlertDialog.Builder(this)
  584. .setMessage(R.string.reader_clear_signature_dialog_msg)
  585. .setPositiveButton(android.R.string.yes) { _, _ -> viewModel.clearSignature() }
  586. .setNegativeButton(android.R.string.no) { _, _ -> /* do nothing */ }
  587. .show()
  588. }
  589. private fun showAddBookmarkDialog() {
  590. val alertDialogBuilder = AlertDialog.Builder(this)
  591. val editText = EditText(this)
  592. val layoutParams =
  593. LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
  594. editText.layoutParams = layoutParams
  595. val defaultTitle = getString(R.string.dialogAddBookmark_page) + " " + (viewModel.pdfInfoHandler.getCurrentPage() + 1)
  596. editText.setText(defaultTitle, TextView.BufferType.EDITABLE)
  597. editText.setSelection(0, defaultTitle.length)
  598. alertDialogBuilder.setTitle(getString(R.string.reader_alert_dialog_title_add_bookmark))
  599. alertDialogBuilder.setView(editText)
  600. alertDialogBuilder.setPositiveButton(getString(R.string.reader_alert_dialog_button_confirm)) { dialog, which ->
  601. viewModel.addBookmark(editText.text.toString())
  602. updateBookmarkView()
  603. }
  604. alertDialogBuilder.setNegativeButton(getString(R.string.reader_alert_dialog_button_cancel)) { dialog, which ->
  605. }
  606. alertDialogBuilder.create().show()
  607. editText.requestFocus()
  608. }
  609. private fun getBookmarkTitle(page: Int): String {
  610. val bookmarks = viewModel.bookmarkHandler.getBookmarks()
  611. for (bookmark in bookmarks) {
  612. if (bookmark.pageNum == page) {
  613. return bookmark.title
  614. }
  615. }
  616. return ""
  617. }
  618. private fun showDeleteBookmarkDialog() {
  619. val alertDialogBuilder = AlertDialog.Builder(this)
  620. alertDialogBuilder.setTitle(getString(R.string.reader_alert_dialog_title_delete_bookmark))
  621. val bookmarkTitle = getBookmarkTitle(viewModel.pdfInfoHandler.getCurrentPage())
  622. val message = String.format(getString(R.string.reader_alert_dialog_message_delete_bookmark), bookmarkTitle)
  623. alertDialogBuilder.setMessage(message)
  624. alertDialogBuilder.setPositiveButton(getString(R.string.reader_alert_dialog_button_confirm)) { dialog, which ->
  625. viewModel.deleteBookmark()
  626. updateBookmarkView()
  627. }
  628. alertDialogBuilder.setNegativeButton(getString(R.string.reader_alert_dialog_button_cancel)) { dialog, which ->
  629. }
  630. alertDialogBuilder.create().show()
  631. }
  632. private fun hideSearchViewSoftKeyboard() {
  633. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  634. if (view is SearchView) {
  635. view.hideSoftKeyboard()
  636. }
  637. }
  638. private fun setupLeftToolbar() {
  639. viewGroup_readerActivity_leftToolbar.setScroll(false)
  640. setLeftToolbarWidth(w_240)
  641. viewGroup_readerActivity_leftToolbar.smoothScrollTo(w_240, 0, 0)
  642. val child = layoutInflater.inflate(R.layout.view_thumbnail, null)
  643. linearLayout_readerActivity_leftToolbarContainer.addView(child)
  644. fun onClickLeftToolbarItem(leftToolbarType: ReaderViewModel.LeftToolbarType) {
  645. viewModel.setLeftToolbarType(leftToolbarType)
  646. updateLeftToolbarOpenState(leftToolbarType)
  647. }
  648. iv_readerActivity_thumbnail.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.THUMBNAIL) }
  649. iv_readerActivity_bookmark.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.BOOKMARK) }
  650. iv_readerActivity_outline.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.OUTLINE) }
  651. iv_readerActivity_search.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.SEARCH) }
  652. if (!isPdf()) {
  653. iv_readerActivity_bookmark.visibility = View.GONE
  654. if (!isPasswordProtected) iv_readerActivity_outline.visibility = View.GONE
  655. }
  656. }
  657. override fun onReadModeChanged(readMode: Int) {
  658. viewModel.readMode = when (readMode) {
  659. ReadingModeSelectView.modeDay -> ReaderViewModel.ReadMode.READ_MODE_DAY
  660. ReadingModeSelectView.modeNight -> ReaderViewModel.ReadMode.READ_MODE_NIGHT
  661. ReadingModeSelectView.modeSoft -> ReaderViewModel.ReadMode.READ_MODE_SOFT
  662. ReadingModeSelectView.modeChromeWhite -> ReaderViewModel.ReadMode.MODE_CHROME_WHITE
  663. ReadingModeSelectView.modeEtonBlue -> ReaderViewModel.ReadMode.MODE_ETON_BLUE
  664. ReadingModeSelectView.modeWhiteLilac -> ReaderViewModel.ReadMode.MODE_WHITE_LILAC
  665. else -> ReaderViewModel.ReadMode.READ_MODE_DAY
  666. }
  667. }
  668. override fun onCropModeEnableChanged(enable: Boolean) {
  669. viewModel.isCrop = enable
  670. val buttons = arrayOf(iv_readerActivity_highLight, iv_readerActivity_strike, iv_readerActivity_underline, iv_readerActivity_ink, ib_readerActivity_bottomToolbarMediaBox)
  671. if (enable) {
  672. viewModel.stopAnnotationMode()
  673. val color = ContextCompat.getColor(baseContext, R.color.reader_right_toolbar_disabled_bg)
  674. for (button in buttons) {
  675. button.isEnabled = false
  676. button.setBackgroundColor(color)
  677. }
  678. } else {
  679. for (button in buttons) {
  680. button.isEnabled = true
  681. button.setBackgroundDrawable(null)
  682. }
  683. }
  684. }
  685. override fun onShowStateBarEnableChanged(enable: Boolean, dialog: Dialog?) {
  686. when (enable) {
  687. true -> {
  688. dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
  689. window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
  690. }
  691. false -> {
  692. dialog?.window?.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  693. window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  694. }
  695. }
  696. }
  697. override fun onTurnPageDirectionChanged(direction: Int) {
  698. viewModel.viewDirection = when (direction == 0) {
  699. true -> ReaderViewModel.ViewDirection.VerticalSinglePageContinues
  700. false -> ReaderViewModel.ViewDirection.HorizontalSinglePage
  701. }
  702. }
  703. override fun onShowTurnPageBtnEnableChanged(enable: Boolean) {
  704. when (enable) {
  705. true -> {
  706. ib_readerActivity_bottomToolbarPrevious.visibility = View.VISIBLE
  707. ib_readerActivity_bottomToolbarNext.visibility = View.VISIBLE
  708. }
  709. false -> {
  710. ib_readerActivity_bottomToolbarPrevious.visibility = View.GONE
  711. ib_readerActivity_bottomToolbarNext.visibility = View.GONE
  712. }
  713. }
  714. }
  715. override fun onLockScreenSleepEnableChanged(enable: Boolean) {
  716. when (enable) {
  717. true -> window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  718. false -> window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  719. }
  720. }
  721. override fun onShowCommentToolEnableChanged(enable: Boolean) {
  722. }
  723. override fun onShowBOTAToolEnableChanged(enable: Boolean) {
  724. }
  725. private fun setupRightSideToolbar() {
  726. iv_readerActivity_setting.setOnClickListener {
  727. val settingDialog = provideReaderSettingDialogFragment()
  728. settingDialog.show(supportFragmentManager, FRAGMENT_READER_SETTING_TAG)
  729. }
  730. }
  731. private fun applySetting() {
  732. val model = SharePrefsModel(this)
  733. onShowStateBarEnableChanged(model.isShowStateBarEnable.value ?: false, null)
  734. onTurnPageDirectionChanged(model.turnPageDirection.value ?: 0)
  735. onShowTurnPageBtnEnableChanged(model.isShowTurnPageBtnEnable.value ?: false)
  736. onLockScreenSleepEnableChanged(model.isLockScreenSleepEnable.value ?: false)
  737. onShowCommentToolEnableChanged(model.isShowCommentToolEnable.value ?: false)
  738. onShowBOTAToolEnableChanged(model.isShowBOTAToolEnable.value ?: false)
  739. }
  740. private fun setupBottomToolbar() {
  741. ib_readerActivity_bottomToolbarMediaBox.setOnClickListener { mediaBoxView.show() }
  742. ib_readerActivity_bottomToolbarViewAll.setOnClickListener {
  743. onClickBottomThumb1()
  744. }
  745. ib_readerActivity_bottomToolbarPrevious.setOnClickListener {
  746. val handler = viewModel.pdfInfoHandler
  747. val pageIndex = handler.getCurrentPage()
  748. val previousPageIndex = Math.max(pageIndex - 1, 0)
  749. handler.setCurrentPage(previousPageIndex)
  750. }
  751. ib_readerActivity_bottomToolbarNext.setOnClickListener {
  752. val handler = viewModel.pdfInfoHandler
  753. val pageIndex = handler.getCurrentPage()
  754. val nextPageIndex = Math.min(pageIndex + 1, handler.getPdfPageCount() - 1)
  755. handler.setCurrentPage(nextPageIndex)
  756. }
  757. ib_readerActivity_bottomToolbarKdanCloud.visibility = if (isBottomBarKdanCloudBtnVisible()) {
  758. View.VISIBLE
  759. } else {
  760. View.GONE
  761. }
  762. ib_readerActivity_bottomToolbarKdanCloud.setOnClickListener {
  763. onClickKdanCloud()
  764. }
  765. ib_readerActivity_bottomToolbarShare.setOnClickListener {
  766. onClickShare()
  767. }
  768. if (!isPdf()) {
  769. ib_readerActivity_bottomToolbarMediaBox.visibility = View.GONE
  770. }
  771. }
  772. private fun setupMediaBoxView() {
  773. fun showSnackbar(title: String, btnText: String) {
  774. snackbarMediaBox = Snackbar.make(mediaBoxView, title, Snackbar.LENGTH_INDEFINITE)
  775. .setAction(btnText) {
  776. viewModel.clearSelection()
  777. mediaBoxView.post {
  778. mediaBoxView.show()
  779. snackbarMediaBox?.dismiss()
  780. snackbarMediaBox = null
  781. }
  782. }
  783. snackbarMediaBox?.setActionTextColor(ContextCompat.getColor(this, R.color.bright_blue))
  784. snackbarMediaBox?.show()
  785. }
  786. mediaBoxView.apply {
  787. onShowListener = Runnable {
  788. onMediaBoxShown()
  789. snackbarMediaBox?.dismiss()
  790. snackbarMediaBox = null
  791. }
  792. onDismissListener = Runnable {
  793. onMediaBoxDismissed()
  794. snackbarMediaBox?.dismiss()
  795. snackbarMediaBox = null
  796. }
  797. onClickAddButtonListener = object : MediaBoxView.OnClickHeaderButtonListener {
  798. override fun onClickTextBoxAddButton(textBoxTabView: TextBoxTabView) {
  799. dismiss(false)
  800. viewModel.setTextBoxAttribute(textBoxTabView.getTextBoxAttribute())
  801. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_textBox), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  802. }
  803. override fun onClickTextBoxStyleApplyButton(textBoxTabView: TextBoxTabView) {
  804. dismiss(false)
  805. viewModel.setTextBoxAttribute(textBoxTabView.getTextBoxAttribute(), true)
  806. }
  807. override fun onClickSignatureAddButton(signatureTabView: SignatureTabView) {
  808. dismiss(false)
  809. viewModel.setSignatureAttribute(signatureTabView.getSignatureAttribute())
  810. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_signature), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  811. }
  812. override fun onClickStampAddButton(stampTabView: StampTabView) {
  813. dismiss(false)
  814. viewModel.setStampAttribute(stampTabView.getStampAttribute())
  815. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_stamp), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  816. }
  817. override fun onClickShapeAddButton(shapeTabView: ShapeTabView) {
  818. dismiss(false)
  819. viewModel.setShapeAttribute(shapeTabView.getShapeAttribute())
  820. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_shape), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  821. }
  822. }
  823. }
  824. }
  825. private fun setupRightToolbar() {
  826. viewGroup_readerActivity_rightToolbar.setScroll(false)
  827. iv_readerActivity_highLight.apply {
  828. setOnClickListener { viewModel.onClickHighlightBtn() }
  829. setOnLongClickListener { btn ->
  830. viewModel.onLongClickHighlightBtn()
  831. val context = this@ReaderActivity
  832. AnnotationAttributeWindow(context, true).also { window ->
  833. viewModel.highLightAttributeLiveData.value?.let { attr ->
  834. window.annotationAttributeView.annotationAttribute = attr
  835. }
  836. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  837. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  838. viewModel.setHighLightAttributes(annotationAttributeView.annotationAttribute)
  839. }
  840. }
  841. val contentView = window.contentView.apply {
  842. val w = Utils.makeDropDownMeasureSpec(window.width)
  843. val y = Utils.makeDropDownMeasureSpec(window.height)
  844. measure(w, y)
  845. }
  846. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  847. val xOff = (-contentView.measuredWidth - space).toInt()
  848. val yOff = -btn.height
  849. window.showAsDropDown(btn, xOff, yOff)
  850. }
  851. return@setOnLongClickListener true
  852. }
  853. }
  854. iv_readerActivity_strike.apply {
  855. setOnClickListener { viewModel.onClickStrikeBtn() }
  856. setOnLongClickListener { btn ->
  857. viewModel.onLongClickStrikeBtn()
  858. val context = this@ReaderActivity
  859. AnnotationAttributeWindow(context, true).also { window ->
  860. viewModel.strikeAttributeLiveData.value?.let { attr ->
  861. window.annotationAttributeView.annotationAttribute = attr
  862. }
  863. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  864. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  865. viewModel.setStrikeOutAttributes(annotationAttributeView.annotationAttribute)
  866. }
  867. }
  868. val contentView = window.contentView.apply {
  869. val w = Utils.makeDropDownMeasureSpec(window.width)
  870. val y = Utils.makeDropDownMeasureSpec(window.height)
  871. measure(w, y)
  872. }
  873. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  874. val xOff = (-contentView.measuredWidth - space).toInt()
  875. val yOff = -btn.height
  876. window.showAsDropDown(btn, xOff, yOff)
  877. }
  878. return@setOnLongClickListener true
  879. }
  880. }
  881. iv_readerActivity_underline.apply {
  882. setOnClickListener { viewModel.onClickUnderlineBtn() }
  883. setOnLongClickListener { btn ->
  884. viewModel.onLongClickUnderlineBtn()
  885. val context = this@ReaderActivity
  886. AnnotationAttributeWindow(context, true).also { window ->
  887. viewModel.underLineAttributeLiveData.value?.let { attr ->
  888. window.annotationAttributeView.annotationAttribute = attr
  889. }
  890. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  891. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  892. viewModel.setUnderLineAttributes(annotationAttributeView.annotationAttribute)
  893. }
  894. }
  895. val contentView = window.contentView.apply {
  896. val w = Utils.makeDropDownMeasureSpec(window.width)
  897. val y = Utils.makeDropDownMeasureSpec(window.height)
  898. measure(w, y)
  899. }
  900. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  901. val xOff = (-contentView.measuredWidth - space).toInt()
  902. val yOff = -btn.height
  903. window.showAsDropDown(btn, xOff, yOff)
  904. }
  905. return@setOnLongClickListener true
  906. }
  907. }
  908. iv_readerActivity_ink.apply {
  909. setOnClickListener { viewModel.onClickInkBtn() }
  910. setOnLongClickListener { btn ->
  911. viewModel.onLongClickInkBtn()
  912. val context = this@ReaderActivity
  913. AnnotationAttributeWindow(context, false).also { window ->
  914. viewModel.inkAttributeLiveData.value?.let { attr ->
  915. window.annotationAttributeView.inkAttribute = attr
  916. }
  917. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  918. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  919. viewModel.setInkAttributes(annotationAttributeView.inkAttribute)
  920. }
  921. }
  922. val contentView = window.contentView.apply {
  923. val w = Utils.makeDropDownMeasureSpec(window.width)
  924. val y = Utils.makeDropDownMeasureSpec(window.height)
  925. measure(w, y)
  926. }
  927. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  928. val xOff = (-contentView.measuredWidth - space).toInt()
  929. val yOff = -contentView.measuredHeight
  930. window.showAsDropDown(btn, xOff, yOff)
  931. }
  932. return@setOnLongClickListener true
  933. }
  934. }
  935. if (!isPdf()) {
  936. iv_readerActivity_highLight.visibility = View.GONE
  937. iv_readerActivity_strike.visibility = View.GONE
  938. iv_readerActivity_underline.visibility = View.GONE
  939. iv_readerActivity_ink.visibility = View.GONE
  940. view_readerActivity_highLightStroke.visibility = View.GONE
  941. view_readerActivity_strikeStroke.visibility = View.GONE
  942. view_readerActivity_underlineStroke.visibility = View.GONE
  943. }
  944. }
  945. private fun setLeftToolbarWidth(width: Int) {
  946. var params = viewGroup_readerActivity_leftToolbar.layoutParams as ConstraintLayout.LayoutParams
  947. params.width = width + w_left
  948. params.height = 0
  949. viewGroup_readerActivity_leftToolbar.layoutParams = params
  950. params = linearLayout_readerActivity_leftToolbarContainer.layoutParams as ConstraintLayout.LayoutParams
  951. params.width = width
  952. linearLayout_readerActivity_leftToolbarContainer.layoutParams = params
  953. }
  954. private fun updateLeftToolbarOpenState(type: ReaderViewModel.LeftToolbarType) {
  955. val isLeftToolbarOpen = viewModel.isLeftToolbarOpenLiveData.value ?: false
  956. viewModel.setIsLeftToolbarOpen(!isLeftToolbarOpen || oldLeftToolbarType != type)
  957. cloneOriginConstraintSet()
  958. }
  959. private fun onMediaBoxShown() {
  960. hideAllToolbars()
  961. isHideToolbar = true
  962. }
  963. private fun onMediaBoxDismissed() {
  964. showAllToolbars()
  965. isHideToolbar = false
  966. viewModel.clearSelection()
  967. }
  968. private fun setLeftToolbarContentView(leftToolbarType: ReaderViewModel.LeftToolbarType) {
  969. if (oldLeftToolbarType != leftToolbarType) {
  970. linearLayout_readerActivity_leftToolbarContainer.removeAllViews()
  971. val view = when (leftToolbarType) {
  972. ReaderViewModel.LeftToolbarType.NONE,
  973. ReaderViewModel.LeftToolbarType.THUMBNAIL -> {
  974. val thumbnailView = ThumbnailView(this)
  975. thumbnailView.setHandlers(viewModel.pdfInfoHandler, viewModel.thumbnailHandler)
  976. thumbnailView
  977. }
  978. ReaderViewModel.LeftToolbarType.BOOKMARK -> {
  979. val bookmarkView = BookmarkView(this)
  980. bookmarkView.setHandlers(viewModel.pdfInfoHandler, viewModel.thumbnailHandler, viewModel.bookmarkHandler)
  981. bookmarkView
  982. }
  983. ReaderViewModel.LeftToolbarType.OUTLINE -> {
  984. val outlineView = OutlineView(this)
  985. outlineView.setHandlers(viewModel.pdfInfoHandler, viewModel.outlineHandler)
  986. outlineView
  987. }
  988. ReaderViewModel.LeftToolbarType.SEARCH -> {
  989. val searchView = SearchView(this)
  990. searchView.setHandlers(viewModel.pdfInfoHandler, viewModel.searchHandler)
  991. searchView
  992. }
  993. }
  994. linearLayout_readerActivity_leftToolbarContainer.addView(view as View)
  995. oldLeftToolbarType = leftToolbarType
  996. }
  997. }
  998. private fun getLeftToolbarContentWidth(): Int {
  999. return when (viewModel.leftToolbarTypeLiveData.value == ReaderViewModel.LeftToolbarType.THUMBNAIL) {
  1000. true -> w_240
  1001. false -> w_318
  1002. }
  1003. }
  1004. private fun onLeftToolbarTypeChanged(leftToolbarType: ReaderViewModel.LeftToolbarType?) {
  1005. updateLeftToolbarIcons()
  1006. setLeftToolbarWidth(getLeftToolbarContentWidth())
  1007. cloneOriginConstraintSet()
  1008. if (leftToolbarType != null) {
  1009. setLeftToolbarContentView(leftToolbarType)
  1010. }
  1011. }
  1012. private fun onLeftToolbarOpenStateChanged(open: Boolean?) {
  1013. updateLeftToolbarIcons()
  1014. when (open == true) {
  1015. true -> viewGroup_readerActivity_leftToolbar.smoothScrollTo(0, 0, UI_ANIMATION_DURATION.toInt())
  1016. false -> {
  1017. viewGroup_readerActivity_leftToolbar.smoothScrollTo(getLeftToolbarContentWidth(), 0, UI_ANIMATION_DURATION.toInt())
  1018. hideSearchViewSoftKeyboard()
  1019. }
  1020. }
  1021. }
  1022. private fun updateLeftToolbarIcons() {
  1023. iv_readerActivity_thumbnail.setImageResource(R.drawable.ic_left_toolbar_thumbnails)
  1024. iv_readerActivity_bookmark.setImageResource(R.drawable.ic_left_toolbar_bookmarks)
  1025. iv_readerActivity_outline.setImageResource(R.drawable.ic_left_toolbar_outline)
  1026. iv_readerActivity_search.setImageResource(R.drawable.ic_left_toolbar_search)
  1027. if (viewModel.isLeftToolbarOpenLiveData.value == true) {
  1028. when (viewModel.leftToolbarTypeLiveData.value) {
  1029. ReaderViewModel.LeftToolbarType.NONE -> {}
  1030. ReaderViewModel.LeftToolbarType.THUMBNAIL -> iv_readerActivity_thumbnail.setImageResource(R.drawable.ic_left_toolbar_thumbnails_selected)
  1031. ReaderViewModel.LeftToolbarType.BOOKMARK -> iv_readerActivity_bookmark.setImageResource(R.drawable.ic_left_toolbar_bookmarks_selected)
  1032. ReaderViewModel.LeftToolbarType.OUTLINE -> iv_readerActivity_outline.setImageResource(R.drawable.ic_left_toolbar_outline_selected)
  1033. ReaderViewModel.LeftToolbarType.SEARCH -> iv_readerActivity_search.setImageResource(R.drawable.ic_left_toolbar_search_selected)
  1034. }
  1035. }
  1036. }
  1037. private fun onClickBottomThumb1() {
  1038. val intent = transferThumbIntent()
  1039. startActivityForResult(intent, THUMB)
  1040. viewModel.transferReaderModel()
  1041. }
  1042. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  1043. super.onActivityResult(requestCode, resultCode, data)
  1044. if (resultCode == Activity.RESULT_OK){
  1045. when (requestCode) {
  1046. THUMB -> {
  1047. val mode = data?.getIntExtra("operate", -1)
  1048. when (mode) {
  1049. PdfThumbActivity.THUMB_NORMAL -> {
  1050. val pageIndex = data.getIntExtra("result", 0)
  1051. viewModel.pdfInfoHandler.setCurrentPage(pageIndex)
  1052. viewModel.setPageIndex(pageIndex)
  1053. }
  1054. }
  1055. }
  1056. REQUEST_PASSWORD -> {
  1057. val password = data?.getStringExtra("password") ?: ""
  1058. if (password.isEmpty()) {
  1059. finish()
  1060. } else {
  1061. viewModel.isOpenedFileLiveData.value?.also { isOpened ->
  1062. if (isOpened) return@also
  1063. val result = viewModel.openPdfFile(applicationContext, Uri.parse(filePath), password, Runnable { requestPassword(true) }, intent.type)
  1064. if (result == ReaderViewModel.OpenFileResult.FAILED) {
  1065. showFileCannotOpenDialog(getString(R.string.cannot_open_file_Path, filePath))
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }
  1071. }
  1072. }
  1073. }