mirror of
https://github.com/MinimalBible/MinimalBible
synced 2024-11-21 23:48:18 -05:00
Some migration refactoring
These classes were getting too big
This commit is contained in:
parent
2af409b3b0
commit
8533cf523c
@ -2,21 +2,15 @@ package org.bspeice.minimalbible.activity.viewer
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.support.annotation.LayoutRes
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.BaseExpandableListAdapter
|
|
||||||
import android.widget.ExpandableListView
|
import android.widget.ExpandableListView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import org.bspeice.minimalbible.R
|
import org.bspeice.minimalbible.R
|
||||||
import org.crosswire.jsword.book.Book
|
import org.crosswire.jsword.book.Book
|
||||||
import org.crosswire.jsword.book.bookName
|
|
||||||
import org.crosswire.jsword.book.getVersification
|
|
||||||
import org.crosswire.jsword.versification.BibleBook
|
import org.crosswire.jsword.versification.BibleBook
|
||||||
import org.crosswire.jsword.versification.getBooks
|
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
||||||
@ -25,7 +19,7 @@ class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, a
|
|||||||
val menuContent = contentView.findViewById(R.id._bible_menu) as ExpandableListView
|
val menuContent = contentView.findViewById(R.id._bible_menu) as ExpandableListView
|
||||||
|
|
||||||
fun doInitialize(b: Book, publisher: PublishSubject<BookScrollEvent>) {
|
fun doInitialize(b: Book, publisher: PublishSubject<BookScrollEvent>) {
|
||||||
val adapter = BibleAdapter(b, publisher)
|
val adapter = BibleMenuAdapter(b, publisher)
|
||||||
menuContent setAdapter adapter
|
menuContent setAdapter adapter
|
||||||
publisher subscribe {
|
publisher subscribe {
|
||||||
menuContent.collapseGroup(adapter.getGroupIdForBook(it.b))
|
menuContent.collapseGroup(adapter.getGroupIdForBook(it.b))
|
||||||
@ -33,108 +27,15 @@ class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
class BibleMenuGroup(val bindTo: View) {
|
||||||
* The actual adapter for displaying a book's menu navigation system.
|
|
||||||
* There are a couple of notes about this:
|
|
||||||
* Books are displayed with one row per BibleBook (Genesis, Exodus, etc.) as the group.
|
|
||||||
* Within each group, there are 3 chapters listed per row (to save space). In order to
|
|
||||||
* accommodate this, some slightly funky mathematics have to be used, and this is documented.
|
|
||||||
* Additionally, it doesn't make a whole lot of sense to genericize this using constants
|
|
||||||
* unless we go to programmatic layouts, since we still need to know the view ID's ahead of time.
|
|
||||||
*
|
|
||||||
* TODO: Refactor this so the math parts are separate from the actual override functions,
|
|
||||||
* so it's easier to test.
|
|
||||||
*/
|
|
||||||
class BibleAdapter(val b: Book, val scrollPublisher: PublishSubject<BookScrollEvent>)
|
|
||||||
: BaseExpandableListAdapter() {
|
|
||||||
|
|
||||||
// Map BibleBooks to the number of chapters they have
|
|
||||||
val menuMappings = b.getVersification().getBooks().map {
|
|
||||||
Pair(it, b.getVersification().getLastChapter(it))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getGroupIdForBook(b: BibleBook) = menuMappings.indexOf(
|
|
||||||
menuMappings.first { it.first == b }
|
|
||||||
)
|
|
||||||
|
|
||||||
var groupHighlighted: Int = 0
|
|
||||||
|
|
||||||
override fun getGroupCount(): Int = menuMappings.count()
|
|
||||||
|
|
||||||
fun getChaptersForGroup(group: Int) = menuMappings[group].second
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of child views for a given book.
|
|
||||||
* What makes this complicated is that we display 3 chapters per row.
|
|
||||||
* To make sure we include everything and account for integer division,
|
|
||||||
* we have to add a row if the chapter count modulo 3 is not even.
|
|
||||||
*/
|
|
||||||
override fun getChildrenCount(group: Int): Int {
|
|
||||||
val chapterCount = getChaptersForGroup(group)
|
|
||||||
return when (chapterCount % 3) {
|
|
||||||
0 -> chapterCount / 3
|
|
||||||
else -> (chapterCount / 3) + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getGroup(group: Int): String = b.bookName(menuMappings[group].first)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the starting chapter number for this child view
|
|
||||||
* In order to account for displaying 3 chapters per line,
|
|
||||||
* we need to multiply by three, and then add 1 for the index offset
|
|
||||||
*/
|
|
||||||
override fun getChild(group: Int, child: Int): Int = (child * 3) + 1
|
|
||||||
|
|
||||||
override fun getGroupId(group: Int): Long = group.toLong()
|
|
||||||
|
|
||||||
override fun getChildId(group: Int, child: Int): Long = child.toLong()
|
|
||||||
|
|
||||||
override fun hasStableIds(): Boolean = true
|
|
||||||
|
|
||||||
override fun isChildSelectable(group: Int, child: Int): Boolean = true
|
|
||||||
|
|
||||||
override fun getGroupView(position: Int, expanded: Boolean,
|
|
||||||
convertView: View?, parent: ViewGroup): View =
|
|
||||||
GroupItemHolder.init(
|
|
||||||
getOrInflate(convertView, parent, R.layout.list_bible_menu_group),
|
|
||||||
getGroup(position),
|
|
||||||
position == groupHighlighted)
|
|
||||||
|
|
||||||
override fun getChildView(group: Int, child: Int, isLast: Boolean,
|
|
||||||
convertView: View?, parent: ViewGroup): View {
|
|
||||||
val chapterStart = getChild(group, child)
|
|
||||||
val chapterCount = getChaptersForGroup(group)
|
|
||||||
val chapterEnd =
|
|
||||||
if (chapterCount < chapterStart + 2)
|
|
||||||
chapterCount
|
|
||||||
else
|
|
||||||
chapterStart + 2
|
|
||||||
val view = ChildItemHolder.init(
|
|
||||||
getOrInflate(convertView, parent, R.layout.list_bible_menu_child),
|
|
||||||
chapterStart..chapterEnd,
|
|
||||||
menuMappings[group].first,
|
|
||||||
scrollPublisher
|
|
||||||
)
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOrInflate(v: View?, p: ViewGroup, LayoutRes layout: Int) =
|
|
||||||
v ?: (p.getContext()
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
|
||||||
.inflate(layout, p, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
class GroupItemHolder(val bindTo: View) {
|
|
||||||
val content = bindTo.findViewById(R.id.content) as TextView
|
val content = bindTo.findViewById(R.id.content) as TextView
|
||||||
val resources = bindTo.getResources(): Resources
|
val resources = bindTo.getResources(): Resources
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun init(v: View, obj: Any, highlighted: Boolean): View {
|
fun init(v: View, obj: Any, highlighted: Boolean): View {
|
||||||
val holder =
|
val holder =
|
||||||
if (v.getTag() != null) v.getTag() as GroupItemHolder
|
if (v.getTag() != null) v.getTag() as BibleMenuGroup
|
||||||
else GroupItemHolder(v)
|
else BibleMenuGroup(v)
|
||||||
holder.bind(obj, highlighted)
|
holder.bind(obj, highlighted)
|
||||||
|
|
||||||
return v
|
return v
|
||||||
@ -155,7 +56,7 @@ class GroupItemHolder(val bindTo: View) {
|
|||||||
* Bind the child items. There are some funky math things going on since
|
* Bind the child items. There are some funky math things going on since
|
||||||
* we display three chapters per row, check the adapter for more documentation
|
* we display three chapters per row, check the adapter for more documentation
|
||||||
*/
|
*/
|
||||||
class ChildItemHolder(val bindTo: View, val book: BibleBook,
|
class BibleMenuChild(val bindTo: View, val book: BibleBook,
|
||||||
val scrollPublisher: PublishSubject<BookScrollEvent>) {
|
val scrollPublisher: PublishSubject<BookScrollEvent>) {
|
||||||
val content1 = bindTo.findViewById(R.id.content1) as TextView
|
val content1 = bindTo.findViewById(R.id.content1) as TextView
|
||||||
val content2 = bindTo.findViewById(R.id.content2) as TextView
|
val content2 = bindTo.findViewById(R.id.content2) as TextView
|
||||||
@ -165,8 +66,8 @@ class ChildItemHolder(val bindTo: View, val book: BibleBook,
|
|||||||
fun init(v: View, obj: IntRange, book: BibleBook,
|
fun init(v: View, obj: IntRange, book: BibleBook,
|
||||||
scrollPublisher: PublishSubject<BookScrollEvent>): View {
|
scrollPublisher: PublishSubject<BookScrollEvent>): View {
|
||||||
val holder =
|
val holder =
|
||||||
if (v.getTag() != null) v.getTag() as ChildItemHolder
|
if (v.getTag() != null) v.getTag() as BibleMenuChild
|
||||||
else ChildItemHolder(v, book, scrollPublisher)
|
else BibleMenuChild(v, book, scrollPublisher)
|
||||||
|
|
||||||
holder.clearViews()
|
holder.clearViews()
|
||||||
holder.bind(obj)
|
holder.bind(obj)
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
package org.bspeice.minimalbible.activity.viewer
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.support.annotation.LayoutRes
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.BaseExpandableListAdapter
|
||||||
|
import org.bspeice.minimalbible.R
|
||||||
|
import org.crosswire.jsword.book.Book
|
||||||
|
import org.crosswire.jsword.book.bookName
|
||||||
|
import org.crosswire.jsword.book.getVersification
|
||||||
|
import org.crosswire.jsword.versification.BibleBook
|
||||||
|
import org.crosswire.jsword.versification.getBooks
|
||||||
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual adapter for displaying a book's menu navigation system.
|
||||||
|
* There are a couple of notes about this:
|
||||||
|
* Books are displayed with one row per BibleBook (Genesis, Exodus, etc.) as the group.
|
||||||
|
* Within each group, there are 3 chapters listed per row (to save space). In order to
|
||||||
|
* accommodate this, some slightly funky mathematics have to be used, and this is documented.
|
||||||
|
* Additionally, it doesn't make a whole lot of sense to genericize this using constants
|
||||||
|
* unless we go to programmatic layouts, since we still need to know the view ID's ahead of time.
|
||||||
|
*
|
||||||
|
* TODO: Refactor this so the math parts are separate from the actual override functions,
|
||||||
|
* so it's easier to test.
|
||||||
|
*/
|
||||||
|
class BibleMenuAdapter(val b: Book, val scrollPublisher: PublishSubject<BookScrollEvent>)
|
||||||
|
: BaseExpandableListAdapter() {
|
||||||
|
|
||||||
|
// Map BibleBooks to the number of chapters they have
|
||||||
|
val menuMappings = b.getVersification().getBooks().map {
|
||||||
|
Pair(it, b.getVersification().getLastChapter(it))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGroupIdForBook(b: BibleBook) = menuMappings.indexOf(
|
||||||
|
menuMappings.first { it.first == b }
|
||||||
|
)
|
||||||
|
|
||||||
|
var groupHighlighted: Int = 0
|
||||||
|
|
||||||
|
override fun getGroupCount(): Int = menuMappings.count()
|
||||||
|
|
||||||
|
fun getChaptersForGroup(group: Int) = menuMappings[group].second
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of child views for a given book.
|
||||||
|
* What makes this complicated is that we display 3 chapters per row.
|
||||||
|
* To make sure we include everything and account for integer division,
|
||||||
|
* we have to add a row if the chapter count modulo 3 is not even.
|
||||||
|
*/
|
||||||
|
override fun getChildrenCount(group: Int): Int {
|
||||||
|
val chapterCount = getChaptersForGroup(group)
|
||||||
|
return when (chapterCount % 3) {
|
||||||
|
0 -> chapterCount / 3
|
||||||
|
else -> (chapterCount / 3) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGroup(group: Int): String = b.bookName(menuMappings[group].first)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the starting chapter number for this child view
|
||||||
|
* In order to account for displaying 3 chapters per line,
|
||||||
|
* we need to multiply by three, and then add 1 for the index offset
|
||||||
|
*/
|
||||||
|
override fun getChild(group: Int, child: Int): Int = (child * 3) + 1
|
||||||
|
|
||||||
|
override fun getGroupId(group: Int): Long = group.toLong()
|
||||||
|
|
||||||
|
override fun getChildId(group: Int, child: Int): Long = child.toLong()
|
||||||
|
|
||||||
|
override fun hasStableIds(): Boolean = true
|
||||||
|
|
||||||
|
override fun isChildSelectable(group: Int, child: Int): Boolean = true
|
||||||
|
|
||||||
|
override fun getGroupView(position: Int, expanded: Boolean,
|
||||||
|
convertView: View?, parent: ViewGroup): View =
|
||||||
|
BibleMenuGroup.init(
|
||||||
|
getOrInflate(convertView, parent, R.layout.list_bible_menu_group),
|
||||||
|
getGroup(position),
|
||||||
|
position == groupHighlighted)
|
||||||
|
|
||||||
|
override fun getChildView(group: Int, child: Int, isLast: Boolean,
|
||||||
|
convertView: View?, parent: ViewGroup): View {
|
||||||
|
val chapterStart = getChild(group, child)
|
||||||
|
val chapterCount = getChaptersForGroup(group)
|
||||||
|
val chapterEnd =
|
||||||
|
if (chapterCount < chapterStart + 2)
|
||||||
|
chapterCount
|
||||||
|
else
|
||||||
|
chapterStart + 2
|
||||||
|
val view = BibleMenuChild.init(
|
||||||
|
getOrInflate(convertView, parent, R.layout.list_bible_menu_child),
|
||||||
|
chapterStart..chapterEnd,
|
||||||
|
menuMappings[group].first,
|
||||||
|
scrollPublisher
|
||||||
|
)
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOrInflate(v: View?, p: ViewGroup, LayoutRes layout: Int) =
|
||||||
|
v ?: (p.getContext()
|
||||||
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
||||||
|
.inflate(layout, p, false)
|
||||||
|
}
|
@ -3,22 +3,12 @@ package org.bspeice.minimalbible.activity.viewer
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.text.SpannableStringBuilder
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
|
||||||
import org.bspeice.minimalbible.R
|
import org.bspeice.minimalbible.R
|
||||||
import org.bspeice.minimalbible.activity.viewer.BookAdapter.ChapterInfo
|
|
||||||
import org.bspeice.minimalbible.service.format.osisparser.OsisParser
|
|
||||||
import org.crosswire.jsword.book.Book
|
import org.crosswire.jsword.book.Book
|
||||||
import org.crosswire.jsword.book.getVersification
|
|
||||||
import org.crosswire.jsword.versification.BibleBook
|
|
||||||
import org.crosswire.jsword.versification.getBooks
|
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
class BibleView(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
class BibleView(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
||||||
@ -41,117 +31,3 @@ class BibleView(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 prefs: BibleViewerPreferences)
|
|
||||||
: RecyclerView.Adapter<PassageView>() {
|
|
||||||
|
|
||||||
val versification = b.getVersification()
|
|
||||||
val bookList = versification.getBooks()
|
|
||||||
// val chapterCount = bookList.map { versification.getLastChapter(it) - 1 }.sum()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store information needed to decode the text of a chapter
|
|
||||||
* Book, chapter, and bibleBook should be pretty self-explanatory
|
|
||||||
* The vStart, vEnd, and vOffset are needed to map between verses relative to their chapter,
|
|
||||||
* and the actual verse ordinal needed for parsing the text.
|
|
||||||
* So Genesis 1:1 would be chapter 1, bibleBook Genesis, vStart 1, vOffset 2
|
|
||||||
* since it actually starts at ordinal 3
|
|
||||||
*/
|
|
||||||
data class ChapterInfo(val book: Book, val chapter: Int, val bibleBook: BibleBook,
|
|
||||||
val vStart: Int, val vEnd: Int, val vOffset: Int)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of all ChapterInfo objects needed for displaying a book
|
|
||||||
* The for expression probably looks a bit nicer:
|
|
||||||
* for {
|
|
||||||
* book <- bookList
|
|
||||||
* chapter <- 1..versification.getLastChapter(currentBook)
|
|
||||||
* } yield ChapterInfo(...)
|
|
||||||
*
|
|
||||||
* Also note that getLastVerse() returns the number of verses in a chapter,
|
|
||||||
* not the actual last verse's ordinal
|
|
||||||
*/
|
|
||||||
// TODO: Lazy compute values needed for this list
|
|
||||||
val chapterList: List<ChapterInfo> = bookList.flatMap {
|
|
||||||
val currentBook = it
|
|
||||||
(1..versification.getLastChapter(currentBook)).map {
|
|
||||||
val firstVerseOrdinal = versification.getFirstVerse(currentBook, it)
|
|
||||||
val verseOrdinalOffset = firstVerseOrdinal - 1
|
|
||||||
val verseCount = versification.getLastVerse(currentBook, it)
|
|
||||||
val firstVerseRelative = 1
|
|
||||||
val lastVerseRelative = firstVerseRelative + verseCount
|
|
||||||
|
|
||||||
ChapterInfo(b, it, currentBook,
|
|
||||||
firstVerseRelative, lastVerseRelative, verseOrdinalOffset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* I'm not sure what the position argument actually represents,
|
|
||||||
* but on initial load it doesn't change
|
|
||||||
*/
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup?,
|
|
||||||
position: Int): PassageView {
|
|
||||||
val emptyView = LayoutInflater.from(parent!!.getContext())
|
|
||||||
.inflate(R.layout.viewer_passage_view, parent, false) as TextView
|
|
||||||
|
|
||||||
// TODO: Listen for changes to the text size?
|
|
||||||
emptyView.setTextSize(TypedValue.COMPLEX_UNIT_SP, prefs.baseTextSize().toFloat())
|
|
||||||
|
|
||||||
val passage = PassageView(emptyView, b)
|
|
||||||
return passage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind an existing view to its chapter content
|
|
||||||
*/
|
|
||||||
override fun onBindViewHolder(view: PassageView, position: Int) {
|
|
||||||
prefs.currentChapter(position)
|
|
||||||
return view bind chapterList[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of chapters in the book
|
|
||||||
*/
|
|
||||||
override fun getItemCount(): Int = chapterList.size()
|
|
||||||
|
|
||||||
public fun bindScrollHandler(provider: PublishSubject<BookScrollEvent>,
|
|
||||||
lM: RecyclerView.LayoutManager) {
|
|
||||||
provider subscribe {
|
|
||||||
val event = it
|
|
||||||
lM scrollToPosition
|
|
||||||
// Get all objects in the form (index, object)
|
|
||||||
chapterList.withIndex()
|
|
||||||
// get one that matches our book and chapter
|
|
||||||
.first {
|
|
||||||
event.b == it.value.bibleBook &&
|
|
||||||
event.chapter == it.value.chapter
|
|
||||||
}
|
|
||||||
// and get that index value to scroll to
|
|
||||||
.index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PassageView(val v: TextView, val b: Book)
|
|
||||||
: RecyclerView.ViewHolder(v) {
|
|
||||||
|
|
||||||
fun buildOrdinal(verse: Int, info: ChapterInfo) =
|
|
||||||
b.getVersification().decodeOrdinal(verse + info.vOffset)
|
|
||||||
|
|
||||||
fun getAllVerses(verses: Progression<Int>, info: ChapterInfo): SpannableStringBuilder {
|
|
||||||
val builder = SpannableStringBuilder()
|
|
||||||
val parser = OsisParser()
|
|
||||||
verses.forEach { parser.appendVerse(b, buildOrdinal(it, info), builder) }
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bind(info: ChapterInfo) {
|
|
||||||
Log.d("PassageView", "Binding chapter ${info.chapter}")
|
|
||||||
v setText getAllVerses(info.vStart..info.vEnd, info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,109 @@
|
|||||||
|
package org.bspeice.minimalbible.activity.viewer
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.bspeice.minimalbible.R
|
||||||
|
import org.crosswire.jsword.book.Book
|
||||||
|
import org.crosswire.jsword.book.getVersification
|
||||||
|
import org.crosswire.jsword.versification.BibleBook
|
||||||
|
import org.crosswire.jsword.versification.getBooks
|
||||||
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 prefs: BibleViewerPreferences)
|
||||||
|
: RecyclerView.Adapter<PassageView>() {
|
||||||
|
|
||||||
|
val versification = b.getVersification()
|
||||||
|
val bookList = versification.getBooks()
|
||||||
|
// val chapterCount = bookList.map { versification.getLastChapter(it) - 1 }.sum()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store information needed to decode the text of a chapter
|
||||||
|
* Book, chapter, and bibleBook should be pretty self-explanatory
|
||||||
|
* The vStart, vEnd, and vOffset are needed to map between verses relative to their chapter,
|
||||||
|
* and the actual verse ordinal needed for parsing the text.
|
||||||
|
* So Genesis 1:1 would be chapter 1, bibleBook Genesis, vStart 1, vOffset 2
|
||||||
|
* since it actually starts at ordinal 3
|
||||||
|
*/
|
||||||
|
data class ChapterInfo(val book: Book, val chapter: Int, val bibleBook: BibleBook,
|
||||||
|
val vStart: Int, val vEnd: Int, val vOffset: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all ChapterInfo objects needed for displaying a book
|
||||||
|
* The for expression probably looks a bit nicer:
|
||||||
|
* for {
|
||||||
|
* book <- bookList
|
||||||
|
* chapter <- 1..versification.getLastChapter(currentBook)
|
||||||
|
* } yield ChapterInfo(...)
|
||||||
|
*
|
||||||
|
* Also note that getLastVerse() returns the number of verses in a chapter,
|
||||||
|
* not the actual last verse's ordinal
|
||||||
|
*/
|
||||||
|
// TODO: Lazy compute values needed for this list
|
||||||
|
val chapterList: List<ChapterInfo> = bookList.flatMap {
|
||||||
|
val currentBook = it
|
||||||
|
(1..versification.getLastChapter(currentBook)).map {
|
||||||
|
val firstVerseOrdinal = versification.getFirstVerse(currentBook, it)
|
||||||
|
val verseOrdinalOffset = firstVerseOrdinal - 1
|
||||||
|
val verseCount = versification.getLastVerse(currentBook, it)
|
||||||
|
val firstVerseRelative = 1
|
||||||
|
val lastVerseRelative = firstVerseRelative + verseCount
|
||||||
|
|
||||||
|
ChapterInfo(b, it, currentBook,
|
||||||
|
firstVerseRelative, lastVerseRelative, verseOrdinalOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I'm not sure what the position argument actually represents,
|
||||||
|
* but on initial load it doesn't change
|
||||||
|
*/
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup?,
|
||||||
|
position: Int): PassageView {
|
||||||
|
val emptyView = LayoutInflater.from(parent!!.getContext())
|
||||||
|
.inflate(R.layout.viewer_passage_view, parent, false) as TextView
|
||||||
|
|
||||||
|
// TODO: Listen for changes to the text size?
|
||||||
|
emptyView.setTextSize(TypedValue.COMPLEX_UNIT_SP, prefs.baseTextSize().toFloat())
|
||||||
|
|
||||||
|
val passage = PassageView(emptyView, b)
|
||||||
|
return passage
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind an existing view to its chapter content
|
||||||
|
*/
|
||||||
|
override fun onBindViewHolder(view: PassageView, position: Int) {
|
||||||
|
prefs.currentChapter(position)
|
||||||
|
return view bind chapterList[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of chapters in the book
|
||||||
|
*/
|
||||||
|
override fun getItemCount(): Int = chapterList.size()
|
||||||
|
|
||||||
|
public fun bindScrollHandler(provider: PublishSubject<BookScrollEvent>,
|
||||||
|
lM: RecyclerView.LayoutManager) {
|
||||||
|
provider subscribe {
|
||||||
|
val event = it
|
||||||
|
lM scrollToPosition
|
||||||
|
// Get all objects in the form (index, object)
|
||||||
|
chapterList.withIndex()
|
||||||
|
// get one that matches our book and chapter
|
||||||
|
.first {
|
||||||
|
event.b == it.value.bibleBook &&
|
||||||
|
event.chapter == it.value.chapter
|
||||||
|
}
|
||||||
|
// and get that index value to scroll to
|
||||||
|
.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.bspeice.minimalbible.activity.viewer
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.bspeice.minimalbible.service.format.osisparser.OsisParser
|
||||||
|
import org.crosswire.jsword.book.Book
|
||||||
|
import org.crosswire.jsword.book.getVersification
|
||||||
|
|
||||||
|
class PassageView(val v: TextView, val b: Book)
|
||||||
|
: RecyclerView.ViewHolder(v) {
|
||||||
|
|
||||||
|
fun buildOrdinal(verse: Int, info: BookAdapter.ChapterInfo) =
|
||||||
|
b.getVersification().decodeOrdinal(verse + info.vOffset)
|
||||||
|
|
||||||
|
fun getAllVerses(verses: Progression<Int>, info: BookAdapter.ChapterInfo): SpannableStringBuilder {
|
||||||
|
val builder = SpannableStringBuilder()
|
||||||
|
val parser = OsisParser()
|
||||||
|
verses.forEach { parser.appendVerse(b, buildOrdinal(it, info), builder) }
|
||||||
|
return builder
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(info: BookAdapter.ChapterInfo) {
|
||||||
|
Log.d("PassageView", "Binding chapter ${info.chapter}")
|
||||||
|
v setText getAllVerses(info.vStart..info.vEnd, info)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user