-
-
Notifications
You must be signed in to change notification settings - Fork 385
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: replace Composition (view) with CandidatesView
feat: implement CandidatesView, PreeditUi, PagedCandidatesUi and LabeledCanidateItemUi refactor: remove Composition (view) refactor: change candidate's label, text and comment size to float type
- Loading branch information
1 parent
2e1328c
commit 9abbf9a
Showing
9 changed files
with
357 additions
and
465 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
app/src/main/java/com/osfans/trime/ime/candidates/popup/LabeledCandidateItemUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2015 - 2024 Rime community | ||
* SPDX-License-Identifier: GPL-3.0-or-later | ||
*/ | ||
|
||
package com.osfans.trime.ime.candidates.popup | ||
|
||
import android.content.Context | ||
import android.graphics.Color | ||
import android.graphics.Typeface | ||
import android.text.TextPaint | ||
import android.text.style.UnderlineSpan | ||
import androidx.annotation.ColorInt | ||
import androidx.core.text.buildSpannedString | ||
import androidx.core.text.inSpans | ||
import com.osfans.trime.core.RimeProto | ||
import com.osfans.trime.data.theme.ColorManager | ||
import com.osfans.trime.data.theme.FontManager | ||
import com.osfans.trime.data.theme.Theme | ||
import com.osfans.trime.util.sp | ||
import splitties.views.backgroundColor | ||
import splitties.views.dsl.core.Ui | ||
import splitties.views.dsl.core.textView | ||
|
||
class LabeledCandidateItemUi( | ||
override val ctx: Context, | ||
val theme: Theme, | ||
) : Ui { | ||
class CandidateSpan( | ||
@ColorInt private val color: Int, | ||
private val textSize: Float, | ||
private val typeface: Typeface, | ||
) : UnderlineSpan() { | ||
override fun updateDrawState(ds: TextPaint) { | ||
ds.isUnderlineText = false | ||
ds.color = color | ||
ds.textSize = textSize | ||
ds.typeface = typeface | ||
} | ||
} | ||
|
||
private val labelSize = theme.generalStyle.labelTextSize | ||
private val textSize = theme.generalStyle.candidateTextSize | ||
private val commentSize = theme.generalStyle.commentTextSize | ||
private val labelFont = FontManager.getTypeface("label_font") | ||
private val textFont = FontManager.getTypeface("candidate_font") | ||
private val commentFont = FontManager.getTypeface("comment_font") | ||
private val labelColor = ColorManager.getColor("label_color")!! | ||
private val textColor = ColorManager.getColor("candidate_text_color")!! | ||
private val commentColor = ColorManager.getColor("comment_text_color")!! | ||
private val highlightLabelColor = ColorManager.getColor("hilited_label_color")!! | ||
private val highlightCommentTextColor = ColorManager.getColor("hilited_comment_text_color")!! | ||
private val highlightCandidateTextColor = ColorManager.getColor("hilited_candidate_text_color")!! | ||
private val highlightBackColor = ColorManager.getColor("hilited_back_color")!! | ||
|
||
override val root = textView() | ||
|
||
fun update( | ||
candidate: RimeProto.Candidate, | ||
highlighted: Boolean, | ||
) { | ||
val labelFg = if (highlighted) highlightLabelColor else labelColor | ||
val textFg = if (highlighted) highlightCandidateTextColor else textColor | ||
val commentFg = if (highlighted) highlightCommentTextColor else commentColor | ||
root.text = | ||
buildSpannedString { | ||
inSpans(CandidateSpan(labelFg, ctx.sp(labelSize), labelFont)) { append(candidate.label) } | ||
inSpans(CandidateSpan(textFg, ctx.sp(textSize), textFont)) { append(candidate.text) } | ||
if (!candidate.comment.isNullOrEmpty()) { | ||
append(" ") | ||
inSpans(CandidateSpan(commentFg, ctx.sp(commentSize), commentFont)) { append(candidate.comment) } | ||
} | ||
} | ||
val bg = if (highlighted) highlightBackColor else Color.TRANSPARENT | ||
root.backgroundColor = bg | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
app/src/main/java/com/osfans/trime/ime/candidates/popup/PagedCandidatesUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2015 - 2024 Rime community | ||
* SPDX-License-Identifier: GPL-3.0-or-later | ||
*/ | ||
|
||
package com.osfans.trime.ime.candidates.popup | ||
|
||
import android.content.Context | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.chad.library.adapter4.BaseQuickAdapter | ||
import com.google.android.flexbox.AlignItems | ||
import com.google.android.flexbox.FlexDirection | ||
import com.google.android.flexbox.FlexWrap | ||
import com.google.android.flexbox.FlexboxLayoutManager | ||
import com.osfans.trime.core.RimeProto | ||
import com.osfans.trime.data.theme.Theme | ||
import splitties.views.dsl.core.Ui | ||
import splitties.views.dsl.recyclerview.recyclerView | ||
|
||
class PagedCandidatesUi( | ||
override val ctx: Context, | ||
val theme: Theme, | ||
) : Ui { | ||
private var menu = RimeProto.Context.Menu() | ||
|
||
class UiViewHolder( | ||
val ui: Ui, | ||
) : RecyclerView.ViewHolder(ui.root) | ||
|
||
val candidatesAdapter = | ||
object : BaseQuickAdapter<RimeProto.Candidate, UiViewHolder>() { | ||
override fun getItemCount(items: List<RimeProto.Candidate>) = | ||
items.size + (if (menu.pageNumber != 0 || !menu.isLastPage) 1 else 0) | ||
|
||
override fun getItemViewType( | ||
position: Int, | ||
list: List<RimeProto.Candidate>, | ||
) = if (position < list.size) 0 else 1 | ||
|
||
override fun onCreateViewHolder( | ||
context: Context, | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): UiViewHolder = | ||
when (viewType) { | ||
0 -> UiViewHolder(LabeledCandidateItemUi(ctx, theme)) | ||
else -> UiViewHolder(LabeledCandidateItemUi(ctx, theme)) | ||
} | ||
|
||
override fun onBindViewHolder( | ||
holder: UiViewHolder, | ||
position: Int, | ||
item: RimeProto.Candidate?, | ||
) { | ||
when (getItemViewType(position)) { | ||
0 -> { | ||
holder.ui as LabeledCandidateItemUi | ||
val candidate = item ?: return | ||
holder.ui.update(candidate, position == menu.highlightedCandidateIndex) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private val candidatesLayoutManager = | ||
FlexboxLayoutManager(ctx).apply { | ||
flexWrap = FlexWrap.WRAP | ||
flexDirection = FlexDirection.ROW | ||
alignItems = AlignItems.BASELINE | ||
} | ||
|
||
override val root = | ||
recyclerView { | ||
isFocusable = false | ||
adapter = candidatesAdapter | ||
layoutManager = candidatesLayoutManager | ||
} | ||
|
||
fun update(menu: RimeProto.Context.Menu) { | ||
this.menu = menu | ||
candidatesAdapter.submitList(menu.candidates.toList()) | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
app/src/main/java/com/osfans/trime/ime/composition/CandidatesView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2015 - 2024 Rime community | ||
* SPDX-License-Identifier: GPL-3.0-or-later | ||
*/ | ||
|
||
package com.osfans.trime.ime.composition | ||
|
||
import android.annotation.SuppressLint | ||
import android.content.Context | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import com.osfans.trime.core.RimeProto | ||
import com.osfans.trime.daemon.RimeSession | ||
import com.osfans.trime.daemon.launchOnReady | ||
import com.osfans.trime.data.theme.Theme | ||
import com.osfans.trime.ime.candidates.popup.PagedCandidatesUi | ||
import splitties.dimensions.dp | ||
import splitties.views.dsl.constraintlayout.below | ||
import splitties.views.dsl.constraintlayout.bottomOfParent | ||
import splitties.views.dsl.constraintlayout.lParams | ||
import splitties.views.dsl.constraintlayout.startOfParent | ||
import splitties.views.dsl.constraintlayout.topOfParent | ||
import splitties.views.dsl.core.add | ||
import splitties.views.dsl.core.wrapContent | ||
import splitties.views.horizontalPadding | ||
import splitties.views.verticalPadding | ||
|
||
@SuppressLint("ViewConstructor") | ||
class CandidatesView( | ||
val ctx: Context, | ||
val rime: RimeSession, | ||
val theme: Theme, | ||
) : ConstraintLayout(ctx) { | ||
private var menu = RimeProto.Context.Menu() | ||
private var inputComposition = RimeProto.Context.Composition() | ||
|
||
private val preeditUi = PreeditUi(ctx, theme) | ||
|
||
private val candidatesUi = | ||
PagedCandidatesUi(ctx, theme).apply { | ||
candidatesAdapter.setOnItemClickListener { _, _, position -> | ||
rime.launchOnReady { it.selectPagedCandidate(position) } | ||
} | ||
} | ||
|
||
fun update(ctx: RimeProto.Context) { | ||
inputComposition = ctx.composition | ||
menu = ctx.menu | ||
updateUi() | ||
} | ||
|
||
private fun evaluateVisibility(): Boolean = | ||
!inputComposition.preedit.isNullOrEmpty() || | ||
menu.candidates.isNotEmpty() | ||
|
||
private fun updateUi() { | ||
if (evaluateVisibility()) { | ||
preeditUi.update(inputComposition) | ||
preeditUi.root.visibility = if (preeditUi.visible) View.VISIBLE else View.GONE | ||
candidatesUi.update(menu) | ||
// visibility = View.VISIBLE | ||
} else { | ||
// visibility = View.GONE | ||
} | ||
} | ||
|
||
init { | ||
// invisible by default | ||
// visibility = GONE | ||
|
||
verticalPadding = dp(theme.generalStyle.layout.marginX) | ||
horizontalPadding = dp(theme.generalStyle.layout.marginY) | ||
add( | ||
preeditUi.root, | ||
lParams(wrapContent, wrapContent) { | ||
topOfParent() | ||
startOfParent() | ||
}, | ||
) | ||
add( | ||
candidatesUi.root, | ||
lParams(wrapContent, wrapContent) { | ||
below(preeditUi.root) | ||
startOfParent() | ||
bottomOfParent() | ||
}, | ||
) | ||
|
||
isFocusable = false | ||
layoutParams = ViewGroup.LayoutParams(wrapContent, wrapContent) | ||
} | ||
} |
Oops, something went wrong.