mirror of
https://github.com/MinimalBible/MinimalBible
synced 2025-07-01 05:45:58 -04:00
Refactor the tag parsing system
Much cleaner, I like this a whole lot more.
This commit is contained in:
@ -11,21 +11,17 @@ import org.crosswire.jsword.versification.getBooks
|
||||
import org.crosswire.jsword.versification.BibleBook
|
||||
import org.bspeice.minimalbible.activity.viewer.BookAdapter.ChapterInfo
|
||||
import rx.subjects.PublishSubject
|
||||
import org.bspeice.minimalbible.service.lookup.VerseLookup
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.StyleSpan
|
||||
import android.graphics.Typeface
|
||||
import android.text.style.SuperscriptSpan
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.util.TypedValue
|
||||
import org.bspeice.minimalbible.service.format.osisparser.OsisParser
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Adapter used for displaying a book
|
||||
* Displays one chapter at a time,
|
||||
* as each TextView widget is it's own line break
|
||||
*/
|
||||
class BookAdapter(val b: Book, val lookup: VerseLookup,
|
||||
val prefs: BibleViewerPreferences)
|
||||
class BookAdapter(val b: Book, val prefs: BibleViewerPreferences)
|
||||
: RecyclerView.Adapter<PassageView>() {
|
||||
|
||||
val versification = b.getVersification()
|
||||
@ -81,7 +77,7 @@ class BookAdapter(val b: Book, val lookup: VerseLookup,
|
||||
// TODO: Prefs object for handling this?
|
||||
emptyView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
||||
|
||||
val passage = PassageView(emptyView, b, lookup)
|
||||
val passage = PassageView(emptyView, b)
|
||||
return passage
|
||||
}
|
||||
|
||||
@ -114,85 +110,20 @@ class BookAdapter(val b: Book, val lookup: VerseLookup,
|
||||
}
|
||||
}
|
||||
|
||||
class PassageView(val v: TextView, val b: Book, val lookup: VerseLookup)
|
||||
class PassageView(val v: TextView, val b: Book)
|
||||
: RecyclerView.ViewHolder(v) {
|
||||
|
||||
// Span to be applied to an individual verse - doesn't know about the sizes
|
||||
// of other verses so that's why start and end are relative
|
||||
/**
|
||||
* A holder object that knows how apply itself to a SpannableStringBuilder
|
||||
* Since we don't know ahead of time where this verse will end up relative to the
|
||||
* entire TextView (since there is one chapter per TextView) we use a start and end
|
||||
* relative to the verse text itself. That is, rStart of 0 indicates verse text start,
|
||||
* and rEnd of (text.length - 1) indicates the end of verse text
|
||||
* @param span The span object we should apply
|
||||
* @param rStart When the span should begin, relative to the verse
|
||||
* @param rEnd When the span should end, relative to the verse
|
||||
*/
|
||||
data class SpanHolder(val span: Any?, val rStart: Int, val rEnd: Int) {
|
||||
// TODO: Is there a more case-class like way of doing this?
|
||||
class object {
|
||||
val EMPTY = SpanHolder(null, 0, 0)
|
||||
}
|
||||
/**
|
||||
* Apply this span object to the specified builder
|
||||
* Tries to be as close to immutable as possible. The offset is used to calculate
|
||||
* the absolute position of when this span should start and end, since
|
||||
* rStart and rEnd are relative to the verse text, and know nothing about the
|
||||
* rest of the text in the TextView
|
||||
*/
|
||||
fun apply(builder: SpannableStringBuilder, offset: Int): SpannableStringBuilder {
|
||||
if (span != null)
|
||||
builder.setSpan(span, rStart + offset, rEnd + offset, 0)
|
||||
return builder
|
||||
}
|
||||
fun buildOrdinal(verse: Int, info: ChapterInfo) =
|
||||
b.getVersification().decodeOrdinal(verse + info.vOffset)
|
||||
|
||||
fun getAllVerses(verses: Progression<Int>, info: ChapterInfo): SpannableStringBuilder {
|
||||
val builder = SpannableStringBuilder()
|
||||
verses.forEach { OsisParser(builder).appendVerse(b, buildOrdinal(it, info)) }
|
||||
return builder
|
||||
}
|
||||
|
||||
// TODO: getRawVerse shouldn't know how to decode ints
|
||||
fun getRawVerse(verse: Int): String =
|
||||
lookup.getText(b.getVersification().decodeOrdinal(verse))
|
||||
|
||||
// TODO: This code is nasty, not sure how to refactor, but it needs doing
|
||||
fun getProcessedVerse(verseOrdinal: Int, info: ChapterInfo): Pair<String, List<SpanHolder>> {
|
||||
val rawText = getRawVerse(verseOrdinal)
|
||||
// To be honest, I have no idea why I need to subtract one. But I do.
|
||||
val relativeVerse = verseOrdinal - info.vOffset - 1
|
||||
val processedText = when (relativeVerse) {
|
||||
0 -> ""
|
||||
1 -> "${info.chapter} $rawText"
|
||||
else -> "$relativeVerse$rawText"
|
||||
}
|
||||
val spans: List<SpanHolder> = listOf(
|
||||
when (relativeVerse) {
|
||||
0 -> SpanHolder.EMPTY
|
||||
1 -> SpanHolder(StyleSpan(Typeface.BOLD), 0, info.chapter.toString().length)
|
||||
else -> SpanHolder(SuperscriptSpan(), 0, relativeVerse.toString().length)
|
||||
}
|
||||
)
|
||||
val secondSpan =
|
||||
if (relativeVerse > 1)
|
||||
// TODO: No magic numbers!
|
||||
spans plus SpanHolder(RelativeSizeSpan(0.6f), 0, relativeVerse.toString().length)
|
||||
else
|
||||
spans
|
||||
|
||||
return Pair(processedText, secondSpan)
|
||||
}
|
||||
|
||||
fun getAllVerses(verses: Progression<Int>, info: ChapterInfo) =
|
||||
verses.map { getProcessedVerse(it + info.vOffset, info) }
|
||||
// For each verse, get the text
|
||||
.fold(SpannableStringBuilder(), { initialBuilder, versePair ->
|
||||
val offset = initialBuilder.length()
|
||||
val builderWithText = initialBuilder append versePair.first
|
||||
|
||||
// And apply all spans
|
||||
versePair.second.fold(builderWithText, { postBuilder, span ->
|
||||
span.apply(postBuilder, offset)
|
||||
})
|
||||
})
|
||||
|
||||
fun bind(info: ChapterInfo) {
|
||||
Log.d("PassageView", "Binding chapter ${info.chapter}")
|
||||
v setText getAllVerses(info.vStart..info.vEnd, info)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user