@ -3,15 +3,14 @@ package io.legado.app.ui.book.read.page
import android.content.Context
import android.content.Context
import android.graphics.Canvas
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Paint
import android.text.Layout
import android.graphics.RectF
import android.text.StaticLayout
import android.util.AttributeSet
import android.util.AttributeSet
import android.view.View
import android.view.View
import io.legado.app.R
import io.legado.app.R
import io.legado.app.constant.PreferKey
import io.legado.app.constant.PreferKey
import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ReadBookConfig
import io.legado.app.lib.theme.accentColor
import io.legado.app.lib.theme.accentColor
import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.read.page.entities.TextChar
import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.utils.activity
import io.legado.app.utils.activity
import io.legado.app.utils.getCompatColor
import io.legado.app.utils.getCompatColor
@ -19,26 +18,26 @@ import io.legado.app.utils.getPrefBoolean
class ContentTextView ( context : Context , attrs : AttributeSet ? ) : View ( context , attrs ) {
class ContentTextView ( context : Context , attrs : AttributeSet ? ) : View ( context , attrs ) {
var selectAble = context . getPrefBoolean ( PreferKey . textSelectAble )
var upView : ( ( TextPage ) -> Unit ) ? = null
private val selectedPaint by lazy {
private val selectedPaint by lazy {
Paint ( ) . apply {
Paint ( ) . apply {
color = context . getCompatColor ( R . color . btn _bg _press _2 )
color = context . getCompatColor ( R . color . btn _bg _press _2 )
style = Paint . Style . FILL
style = Paint . Style . FILL
}
}
}
}
private var activityCallBack : CallBack
private var callBack : CallBack
var selectAble = context . getPrefBoolean ( PreferKey . textSelectAble )
private val visibleRect = RectF ( )
private var selectLineStart = 0
private val selectStart = arrayOf ( 0 , 0 , 0 )
private var selectCharStart = 0
private val selectEnd = arrayOf ( 0 , 0 , 0 )
private var selectLineEnd = 0
private var selectCharEnd = 0
private var textPage : TextPage = TextPage ( )
private var textPage : TextPage = TextPage ( )
//滚动参数
//滚动参数
private val pageFactory : TextPageFactory get ( ) = callBack . pageFactory
private val maxScrollOffset = 100f
private val maxScrollOffset = 100f
private var pageOffset = 0f
private var pageOffset = 0f
private var isLastPage = false
init {
init {
a ctivityC allBack = activity as CallBack
callBack = activity as CallBack
contentDescription = textPage . text
contentDescription = textPage . text
}
}
@ -48,72 +47,114 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
invalidate ( )
invalidate ( )
}
}
fun upVisibleRect ( ) {
visibleRect . set (
ChapterProvider . paddingLeft . toFloat ( ) ,
ChapterProvider . paddingTop . toFloat ( ) ,
ChapterProvider . visibleRight . toFloat ( ) ,
ChapterProvider . visibleBottom . toFloat ( )
)
}
override fun onSizeChanged ( w : Int , h : Int , oldw : Int , oldh : Int ) {
override fun onSizeChanged ( w : Int , h : Int , oldw : Int , oldh : Int ) {
super . onSizeChanged ( w , h , oldw , oldh )
super . onSizeChanged ( w , h , oldw , oldh )
ReadBookConfig . durConfig . let {
ChapterProvider . viewWidth = w
ChapterProvider . viewWidth = w
ChapterProvider . viewHeight = h
ChapterProvider . viewHeight = h
ChapterProvider . upSize ( )
ChapterProvider . upSize ( ReadBookConfig . durConfig )
upVisibleRect ( )
}
textPage . format ( )
}
}
override fun onDraw ( canvas : Canvas ) {
override fun onDraw ( canvas : Canvas ) {
super . onDraw ( canvas )
super . onDraw ( canvas )
if ( textPage . textLines . isEmpty ( ) ) {
canvas . clipRect ( visibleRect )
drawMsg ( canvas , textPage . text )
drawPage ( canvas )
} else {
drawHorizontalPage ( canvas )
}
}
}
@Suppress ( " DEPRECATION " )
/ * *
private fun drawMsg ( canvas : Canvas , msg : String ) {
* 绘制页面
val layout = StaticLayout (
* /
msg , ChapterProvider . contentPaint , width ,
private fun drawPage ( canvas : Canvas ) {
Layout . Alignment . ALIGN _NORMAL , 1f , 0f , false
var relativeOffset = relativeOffset ( 0 )
)
textPage . textLines . forEach { textLine ->
val y = ( height - layout . height ) / 2f
val lineTop = textLine . lineTop + relativeOffset
for ( lineIndex in 0 until layout . lineCount ) {
val lineBase = textLine . lineBase + relativeOffset
val x = ( width - layout . getLineMax ( lineIndex ) ) / 2
val lineBottom = textLine . lineBottom + relativeOffset
val words =
drawChars (
msg . substring ( layout . getLineStart ( lineIndex ) , layout . getLineEnd ( lineIndex ) )
canvas ,
canvas . drawText ( words , x , y , ChapterProvider . contentPaint )
textLine . textChars ,
lineTop ,
lineBase ,
lineBottom ,
textLine . isTitle ,
textLine . isReadAloud
)
}
if ( ! ReadBookConfig . isScroll ) return
//滚动翻页
val nextPage = relativePage ( 1 )
relativeOffset = relativeOffset ( 1 )
nextPage . textLines . forEach { textLine ->
val lineTop = textLine . lineTop + relativeOffset
val lineBase = textLine . lineBase + relativeOffset
val lineBottom = textLine . lineBottom + relativeOffset
drawChars (
canvas ,
textLine . textChars ,
lineTop ,
lineBase ,
lineBottom ,
textLine . isTitle ,
textLine . isReadAloud
)
}
relativeOffset = relativeOffset ( 2 )
if ( relativeOffset < ChapterProvider . visibleHeight ) {
relativePage ( 2 ) . textLines . forEach { textLine ->
val lineTop = textLine . lineTop + relativeOffset
val lineBase = textLine . lineBase + relativeOffset
val lineBottom = textLine . lineBottom + relativeOffset
drawChars (
canvas ,
textLine . textChars ,
lineTop ,
lineBase ,
lineBottom ,
textLine . isTitle ,
textLine . isReadAloud
)
}
}
}
}
}
private fun drawHorizontalPage ( canvas : Canvas ) {
/ * *
textPage . textLines . forEach { textLine ->
* 绘制文字
val textPaint = if ( textLine . isTitle ) {
* /
ChapterProvider . titlePaint
private fun drawChars (
} else {
canvas : Canvas ,
ChapterProvider . contentPaint
textChars : List < TextChar > ,
}
lineTop : Float ,
textPaint . color = if ( textLine . isReadAloud ) {
lineBase : Float ,
context . accentColor
lineBottom : Float ,
} else {
isTitle : Boolean ,
ReadBookConfig . durConfig . textColor ( )
isReadAloud : Boolean
}
) {
textLine . textChars . forEach {
val textPaint = if ( isTitle ) ChapterProvider . titlePaint else ChapterProvider . contentPaint
canvas . drawText (
textPaint . color =
it . charData ,
if ( isReadAloud ) context . accentColor else ReadBookConfig . durConfig . textColor ( )
it . leftBottomPosition . x ,
textChars . forEach {
it . leftBottomPosition . y ,
canvas . drawText ( it . charData , it . start , lineBase , textPaint )
textPaint
if ( it . selected ) {
)
canvas . drawRect ( it . start , lineTop , it . end , lineBottom , selectedPaint )
if ( it . selected ) {
canvas . drawRect (
it . leftBottomPosition . x ,
it . rightTopPosition . y ,
it . rightTopPosition . x ,
it . leftBottomPosition . y ,
selectedPaint
)
}
}
}
}
}
}
}
/ * *
* 滚动事件
* /
fun onScroll ( mOffset : Float ) {
fun onScroll ( mOffset : Float ) {
if ( mOffset == 0f ) return
var offset = mOffset
var offset = mOffset
if ( offset > maxScrollOffset ) {
if ( offset > maxScrollOffset ) {
offset = maxScrollOffset
offset = maxScrollOffset
@ -121,158 +162,430 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
offset = - maxScrollOffset
offset = - maxScrollOffset
}
}
if ( !is LastPage || offset < 0 ) {
pageOffset += offset
pageOffset += offset
if ( pageOffset > 0 ) {
isLastPage = false
if ( ! pageFactory . hasPrev ( ) ) {
}
pageOffset = 0f
// 首页
} else {
if ( pageOffset < 0 && ReadBook . durChapterIndex == 0 && ReadBook . durPageIndex == 0 ) {
pageFactory . moveToPrev ( )
pageOffset = 0f
textPage = pageFactory . currentPage
pageOffset -= textPage . height
upView ?. invoke ( textPage )
}
} else if ( pageOffset < - textPage . height ) {
if ( ! pageFactory . hasNext ( ) ) {
pageOffset = - textPage . height . toFloat ( )
} else {
pageOffset += textPage . height
pageFactory . moveToNext ( )
textPage = pageFactory . currentPage
upView ?. invoke ( textPage )
}
}
}
invalidate ( )
}
fun resetPageOffset ( ) {
pageOffset = 0f
}
}
fun selectText ( x : Float , y : Float ) : Boolean {
/ * *
* 选择初始文字
* /
fun selectText (
x : Float ,
y : Float ,
select : ( relativePage : Int , lineIndex : Int , charIndex : Int ) -> Unit
) {
if ( ! selectAble ) return
if ( ! visibleRect . contains ( x , y ) ) return
var relativeOffset = relativeOffset ( 0 )
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop && y < textLine . lineBottom ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . leftBottomPosition . x && x < textChar . rightTopPosition . x ) {
if ( x > textChar . start && x < textChar . end ) {
textChar . selected = true
textChar . selected = true
invalidate ( )
invalidate ( )
selectLineStart = lineIndex
selectStart [ 0 ] = 0
selectCharStart = charIndex
selectStart [ 1 ] = lineIndex
selectLineEnd = lineIndex
selectStart [ 2 ] = charIndex
selectCharEnd = charIndex
selectEnd [ 0 ] = 0
upSelectedStart (
selectEnd [ 1 ] = lineIndex
textChar . leftBottomPosition . x ,
selectEnd [ 2 ] = charIndex
textChar . leftBottomPosition . y
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
)
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
upSelectedEnd (
select ( 0 , lineIndex , charIndex )
textChar . rightTopPosition . x ,
return
textChar . leftBottomPosition . y
)
return true
}
}
}
}
break
return
}
}
if ( ! ReadBookConfig . isScroll ) return
//滚动翻页
relativeOffset = relativeOffset ( 1 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
val nextPage = relativePage ( 1 )
for ( ( lineIndex , textLine ) in nextPage . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
textChar . selected = true
invalidate ( )
selectStart [ 0 ] = 1
selectStart [ 1 ] = lineIndex
selectStart [ 2 ] = charIndex
selectEnd [ 0 ] = 1
selectEnd [ 1 ] = lineIndex
selectEnd [ 2 ] = charIndex
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
select ( 1 , lineIndex , charIndex )
return
}
}
return
}
}
relativeOffset = relativeOffset ( 2 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
for ( ( lineIndex , textLine ) in relativePage ( 2 ) . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
textChar . selected = true
invalidate ( )
selectStart [ 0 ] = 2
selectStart [ 1 ] = lineIndex
selectStart [ 2 ] = charIndex
selectEnd [ 0 ] = 2
selectEnd [ 1 ] = lineIndex
selectEnd [ 2 ] = charIndex
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
select ( 2 , lineIndex , charIndex )
return
}
}
return
}
}
}
}
return false
}
}
/ * *
* 开始选择符移动
* /
fun selectStartMove ( x : Float , y : Float ) {
fun selectStartMove ( x : Float , y : Float ) {
if ( ! visibleRect . contains ( x , y ) ) return
var relativeOffset = relativeOffset ( 0 )
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop && y < textLine . lineBottom ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . leftBottomPosition . x && x < textChar . rightTopPosition . x ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectLineStart != lineIndex || selectCharStart != charIndex ) {
if ( selectStart [ 0 ] != 0 || selectStart [ 1 ] != lineIndex || selectStart [ 2 ] != charIndex ) {
selectLineStart = lineIndex
if ( selectToInt ( 0 , lineIndex , charIndex ) > selectToInt ( selectEnd ) ) {
selectCharStart = charIndex
return
upSelectedStart (
}
textChar . leftBottomPosition . x ,
selectStart [ 0 ] = 0
textChar . leftBottomPosition . y
selectStart [ 1 ] = lineIndex
)
selectStart [ 2 ] = charIndex
upSelectChars ( textPage )
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
return
}
}
return
}
}
if ( ! ReadBookConfig . isScroll ) return
//滚动翻页
relativeOffset = relativeOffset ( 1 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
for ( ( lineIndex , textLine ) in relativePage ( 1 ) . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectStart [ 0 ] != 1 || selectStart [ 1 ] != lineIndex || selectStart [ 2 ] != charIndex ) {
if ( selectToInt ( 1 , lineIndex , charIndex ) > selectToInt ( selectEnd ) ) {
return
}
selectStart [ 0 ] = 1
selectStart [ 1 ] = lineIndex
selectStart [ 2 ] = charIndex
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
}
break
return
}
}
}
}
break
return
}
}
relativeOffset = relativeOffset ( 2 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
for ( ( lineIndex , textLine ) in relativePage ( 2 ) . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectStart [ 0 ] != 2 || selectStart [ 1 ] != lineIndex || selectStart [ 2 ] != charIndex ) {
if ( selectToInt ( 2 , lineIndex , charIndex ) > selectToInt ( selectEnd ) ) {
return
}
selectStart [ 0 ] = 2
selectStart [ 1 ] = lineIndex
selectStart [ 2 ] = charIndex
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
return
}
}
return
}
}
}
}
}
}
/ * *
* 结束选择符移动
* /
fun selectEndMove ( x : Float , y : Float ) {
fun selectEndMove ( x : Float , y : Float ) {
if ( ! visibleRect . contains ( x , y ) ) return
var relativeOffset = relativeOffset ( 0 )
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop && y < textLine . lineBottom ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . leftBottomPosition . x && x < textChar . rightTopPosition . x ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectLineEnd != lineIndex || selectCharEnd != charIndex ) {
if ( selectEnd [ 0 ] != 0 || selectEnd [ 1 ] != lineIndex || selectEnd [ 2 ] != charIndex ) {
selectLineEnd = lineIndex
if ( selectToInt ( 0 , lineIndex , charIndex ) < selectToInt ( selectStart ) ) {
selectCharEnd = charIndex
return
upSelectedEnd (
}
textChar . rightTopPosition . x ,
selectEnd [ 0 ] = 0
textChar . leftBottomPosition . y
selectEnd [ 1 ] = lineIndex
)
selectEnd [ 2 ] = charIndex
upSelectChars ( textPage )
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
}
break
return
}
}
}
}
break
return
}
}
if ( ! ReadBookConfig . isScroll ) return
//滚动翻页
relativeOffset = relativeOffset ( 1 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
for ( ( lineIndex , textLine ) in relativePage ( 1 ) . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectEnd [ 0 ] != 1 || selectEnd [ 1 ] != lineIndex || selectEnd [ 2 ] != charIndex ) {
if ( selectToInt ( 1 , lineIndex , charIndex ) < selectToInt ( selectStart ) ) {
return
}
selectEnd [ 0 ] = 1
selectEnd [ 1 ] = lineIndex
selectEnd [ 2 ] = charIndex
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
return
}
}
return
}
}
relativeOffset = relativeOffset ( 2 )
if ( relativeOffset >= ChapterProvider . visibleHeight ) return
for ( ( lineIndex , textLine ) in relativePage ( 2 ) . textLines . withIndex ( ) ) {
if ( y > textLine . lineTop + relativeOffset && y < textLine . lineBottom + relativeOffset ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
if ( x > textChar . start && x < textChar . end ) {
if ( selectEnd [ 0 ] != 2 || selectEnd [ 1 ] != lineIndex || selectEnd [ 2 ] != charIndex ) {
if ( selectToInt ( 2 , lineIndex , charIndex ) < selectToInt ( selectStart ) ) {
return
}
selectEnd [ 0 ] = 2
selectEnd [ 1 ] = lineIndex
selectEnd [ 2 ] = charIndex
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset )
upSelectChars ( )
}
return
}
}
return
}
}
}
}
}
}
private fun upSelectChars ( textPage : TextPage ) {
/ * *
for ( ( lineIndex , textLine ) in textPage . textLines . withIndex ( ) ) {
* 选择开始文字
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
* /
textChar . selected =
fun selectStartMoveIndex ( relativePage : Int , lineIndex : Int , charIndex : Int ) {
if ( lineIndex == selectLineStart && lineIndex == selectLineEnd ) {
selectStart [ 0 ] = relativePage
charIndex in selectCharStart .. selectCharEnd
selectStart [ 1 ] = lineIndex
} else if ( lineIndex == selectLineStart ) {
selectStart [ 2 ] = charIndex
charIndex >= selectCharStart
val textLine = relativePage ( relativePage ) . textLines [ lineIndex ]
} else if ( lineIndex == selectLineEnd ) {
val textChar = textLine . textChars [ charIndex ]
charIndex <= selectCharEnd
upSelectedStart ( textChar . start , textLine . lineBottom + relativeOffset ( relativePage ) )
} else {
upSelectChars ( )
lineIndex in ( selectLineStart + 1 ) until selectLineEnd
}
}
/ * *
* 选择结束文字
* /
fun selectEndMoveIndex ( relativePage : Int , lineIndex : Int , charIndex : Int ) {
selectEnd [ 0 ] = relativePage
selectEnd [ 1 ] = lineIndex
selectEnd [ 2 ] = charIndex
val textLine = relativePage ( relativePage ) . textLines [ lineIndex ]
val textChar = textLine . textChars [ charIndex ]
upSelectedEnd ( textChar . end , textLine . lineBottom + relativeOffset ( relativePage ) )
upSelectChars ( )
}
private fun upSelectChars ( ) {
val last = if ( ReadBookConfig . isScroll ) 2 else 0
for ( relativePos in 0. . last ) {
for ( ( lineIndex , textLine ) in relativePage ( relativePos ) . textLines . withIndex ( ) ) {
for ( ( charIndex , textChar ) in textLine . textChars . withIndex ( ) ) {
textChar . selected =
if ( relativePos == selectStart [ 0 ]
&& relativePos == selectEnd [ 0 ]
&& lineIndex == selectStart [ 1 ]
&& lineIndex == selectEnd [ 1 ]
) {
charIndex in selectStart [ 2 ] .. selectEnd [ 2 ]
} else if ( relativePos == selectStart [ 0 ] && lineIndex == selectStart [ 1 ] ) {
charIndex >= selectStart [ 2 ]
} else if ( relativePos == selectEnd [ 0 ] && lineIndex == selectEnd [ 1 ] ) {
charIndex <= selectEnd [ 2 ]
} else if ( relativePos == selectStart [ 0 ] && relativePos == selectEnd [ 0 ] ) {
lineIndex in ( selectStart [ 1 ] + 1 ) until selectEnd [ 1 ]
} else if ( relativePos == selectStart [ 0 ] ) {
lineIndex > selectStart [ 1 ]
} else if ( relativePos == selectEnd [ 0 ] ) {
lineIndex < selectEnd [ 1 ]
} else {
relativePos in selectStart [ 0 ] + 1 until selectEnd [ 0 ]
}
}
}
}
}
}
invalidate ( )
invalidate ( )
}
}
private fun upSelectedStart ( x : Float , y : Float ) {
private fun upSelectedStart ( x : Float , y : Float ) {
activityCallBack . upSelectedStart ( x , y + activityCallBack . headerHeight )
callBack . upSelectedStart ( x , y + callBack . headerHeight )
}
}
private fun upSelectedEnd ( x : Float , y : Float ) {
private fun upSelectedEnd ( x : Float , y : Float ) {
activityCallBack . upSelectedEnd ( x , y + activityCallBack . headerHeight )
callBack . upSelectedEnd ( x , y + callBack . headerHeight )
}
}
fun cancelSelect ( ) {
fun cancelSelect ( ) {
textPage . textLines . forEach { textLine ->
val last = if ( ReadBookConfig . isScroll ) 2 else 0
textLine . textChars . forEach {
for ( relativePos in 0. . last ) {
it . selected = false
relativePage ( relativePos ) . textLines . forEach { textLine ->
textLine . textChars . forEach {
it . selected = false
}
}
}
}
}
invalidate ( )
invalidate ( )
activityCallBack . onCancelSelect ( )
callBack . onCancelSelect ( )
}
}
val selectedText : String
val selectedText : String
get ( ) {
get ( ) {
val stringBuilder = StringBuilder ( )
val stringBuilder = StringBuilder ( )
for ( lineIndex in selectLineStart .. selectLineEnd ) {
for ( relativePos in selectStart [ 0 ] .. selectEnd [ 0 ] ) {
if ( lineIndex == selectLineStart && lineIndex == selectLineEnd ) {
val textPage = relativePage ( relativePos )
stringBuilder . append (
if ( relativePos == selectStart [ 0 ] && relativePos == selectEnd [ 0 ] ) {
textPage . textLines [ lineIndex ] . text . substring (
for ( lineIndex in selectStart [ 1 ] .. selectEnd [ 1 ] ) {
selectCharStart ,
if ( lineIndex == selectStart [ 1 ] && lineIndex == selectEnd [ 1 ] ) {
selectCharEnd + 1
stringBuilder . append (
)
textPage . textLines [ lineIndex ] . text . substring (
)
selectStart [ 2 ] ,
} else if ( lineIndex == selectLineStart ) {
selectEnd [ 2 ] + 1
stringBuilder . append (
)
textPage . textLines [ lineIndex ] . text . substring (
)
selectCharStart
} else if ( lineIndex == selectStart [ 1 ] ) {
)
stringBuilder . append (
)
textPage . textLines [ lineIndex ] . text . substring (
} else if ( lineIndex == selectLineEnd ) {
selectStart [ 2 ]
stringBuilder . append (
)
textPage . textLines [ lineIndex ] . text . substring ( 0 , selectCharEnd + 1 )
)
)
} else if ( lineIndex == selectEnd [ 1 ] ) {
} else {
stringBuilder . append (
stringBuilder . append ( textPage . textLines [ lineIndex ] . text )
textPage . textLines [ lineIndex ] . text . substring ( 0 , selectEnd [ 2 ] + 1 )
)
} else {
stringBuilder . append ( textPage . textLines [ lineIndex ] . text )
}
}
} else if ( relativePos == selectStart [ 0 ] ) {
for ( lineIndex in selectStart [ 1 ] until relativePage ( relativePos ) . textLines . size ) {
if ( lineIndex == selectStart [ 1 ] ) {
stringBuilder . append (
textPage . textLines [ lineIndex ] . text . substring (
selectStart [ 2 ]
)
)
} else {
stringBuilder . append ( textPage . textLines [ lineIndex ] . text )
}
}
} else if ( relativePos == selectEnd [ 0 ] ) {
for ( lineIndex in 0. . selectEnd [ 1 ] ) {
if ( lineIndex == selectEnd [ 1 ] ) {
stringBuilder . append (
textPage . textLines [ lineIndex ] . text . substring ( 0 , selectEnd [ 2 ] + 1 )
)
} else {
stringBuilder . append ( textPage . textLines [ lineIndex ] . text )
}
}
} else if ( relativePos in selectStart [ 0 ] + 1 until selectEnd [ 0 ] ) {
for ( lineIndex in selectStart [ 1 ] .. selectEnd [ 1 ] ) {
stringBuilder . append ( textPage . textLines [ lineIndex ] . text )
}
}
}
}
}
return stringBuilder . toString ( )
return stringBuilder . toString ( )
}
}
private fun selectToInt ( page : Int , line : Int , char : Int ) : Int {
return page * 1000000 + line * 100000 + char
}
private fun selectToInt ( select : Array < Int > ) : Int {
return select [ 0 ] * 1000000 + select [ 1 ] * 100000 + select [ 2 ]
}
private fun relativeOffset ( relativePos : Int ) : Float {
return when ( relativePos ) {
0 -> pageOffset
1 -> pageOffset + textPage . height
else -> pageOffset + textPage . height + pageFactory . nextPage . height
}
}
private fun relativePage ( relativePos : Int ) : TextPage {
return when ( relativePos ) {
0 -> textPage
1 -> pageFactory . nextPage
else -> pageFactory . nextPagePlus
}
}
interface CallBack {
interface CallBack {
fun upSelectedStart ( x : Float , y : Float )
fun upSelectedStart ( x : Float , y : Float )
fun upSelectedEnd ( x : Float , y : Float )
fun upSelectedEnd ( x : Float , y : Float )
fun onCancelSelect ( )
fun onCancelSelect ( )
val headerHeight : Int
val headerHeight : Int
val pageFactory : TextPageFactory
}
}
}
}