Skip to content

Commit

Permalink
refactor: automatically switch bar view when board window attach or d…
Browse files Browse the repository at this point in the history
…etach

Broadcast the window attach / detach event via InputBroadcaster.
  • Loading branch information
WhiredPlanck committed Mar 31, 2024
1 parent 281d31a commit 8fe83c8
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 77 deletions.
36 changes: 24 additions & 12 deletions app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@ import android.widget.ViewAnimator
import com.osfans.trime.core.Rime
import com.osfans.trime.core.RimeNotification.OptionNotification
import com.osfans.trime.data.theme.ColorManager
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.databinding.CandidateBarBinding
import com.osfans.trime.ime.broadcast.InputBroadcastReceiver
import com.osfans.trime.ime.core.TrimeInputMethodService
import com.osfans.trime.ime.dependency.InputScope
import com.osfans.trime.ime.enums.SymbolKeyboardType
import com.osfans.trime.ime.symbol.LiquidTabsUi
import com.osfans.trime.ime.symbol.TabManager
import com.osfans.trime.ime.window.BoardWindow
import me.tatarka.inject.annotations.Inject
import splitties.views.dsl.core.add
import splitties.views.dsl.core.lParams
import splitties.views.dsl.core.matchParent

@InputScope
@Inject
class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme) : InputBroadcastReceiver {
class QuickBar(context: Context, service: TrimeInputMethodService) : InputBroadcastReceiver {
val oldCandidateBar by lazy {
CandidateBarBinding.inflate(LayoutInflater.from(context)).apply {
with(root) {
Expand All @@ -40,20 +38,23 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
}
}

val tabsUi by lazy {
LiquidTabsUi(context, theme).apply {
setTabs(TabManager.tabCandidates)
}
private val tabUi by lazy {
TabUi(context)
}

enum class State {
Candidate,
Tab,
}

fun switchUiByState(state: State) {
if (view.displayedChild == state.ordinal) return
view.displayedChild = state.ordinal
private fun switchUiByState(state: State) {
val index = state.ordinal
if (view.displayedChild == index) return
val new = view.getChildAt(index)
if (new != tabUi.root) {
tabUi.removeExternal()
}
view.displayedChild = index
}

val view by lazy {
Expand All @@ -75,7 +76,7 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
"candidate_border_round",
)
add(oldCandidateBar.root, lParams(matchParent, matchParent))
add(tabsUi.root, lParams(matchParent, matchParent))
add(tabUi.root, lParams(matchParent, matchParent))
}
}

Expand All @@ -89,4 +90,15 @@ class QuickBar(context: Context, service: TrimeInputMethodService, theme: Theme)
}
}
}

override fun onWindowAttached(window: BoardWindow) {
if (window is BoardWindow.BarBoardWindow) {
window.onCreateBarView()?.let { tabUi.addExternal(it) }
switchUiByState(State.Tab)
}
}

override fun onWindowDetached(window: BoardWindow) {
switchUiByState(State.Candidate)
}
}
38 changes: 38 additions & 0 deletions app/src/main/java/com/osfans/trime/ime/bar/TabUi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.osfans.trime.ime.bar

import android.content.Context
import android.view.View
import splitties.views.dsl.constraintlayout.centerInParent
import splitties.views.dsl.constraintlayout.constraintLayout
import splitties.views.dsl.constraintlayout.lParams
import splitties.views.dsl.core.Ui
import splitties.views.dsl.core.add
import splitties.views.dsl.core.matchParent

class TabUi(override val ctx: Context) : Ui {
private var external: View? = null

override val root = constraintLayout { }

fun addExternal(view: View) {
if (external != null) {
throw IllegalStateException("TabBar external view is already present")
}
external = view
root.run {
add(
view,
lParams(matchParent, matchParent) {
centerInParent()
},
)
}
}

fun removeExternal() {
external?.let {
root.removeView(it)
external = null
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.osfans.trime.ime.broadcast

import com.osfans.trime.core.RimeNotification.OptionNotification
import com.osfans.trime.ime.window.BoardWindow

interface InputBroadcastReceiver {
fun onRimeOptionUpdated(value: OptionNotification.Value) {}

fun onWindowAttached(window: BoardWindow) {}

fun onWindowDetached(window: BoardWindow) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.osfans.trime.ime.broadcast

import com.osfans.trime.core.RimeNotification.OptionNotification
import com.osfans.trime.ime.dependency.InputScope
import com.osfans.trime.ime.window.BoardWindow
import me.tatarka.inject.annotations.Inject
import java.util.concurrent.ConcurrentLinkedQueue

Expand Down Expand Up @@ -29,4 +30,12 @@ class InputBroadcaster : InputBroadcastReceiver {
override fun onRimeOptionUpdated(value: OptionNotification.Value) {
receivers.forEach { it.onRimeOptionUpdated(value) }
}

override fun onWindowAttached(window: BoardWindow) {
receivers.forEach { it.onWindowAttached(window) }
}

override fun onWindowDetached(window: BoardWindow) {
receivers.forEach { it.onWindowDetached(window) }
}
}
5 changes: 2 additions & 3 deletions app/src/main/java/com/osfans/trime/ime/core/InputView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,9 @@ class InputView(

fun switchBoard(board: Board) {
when (board) {
Board.Main -> windowManager.attachWindow(keyboardWindow)
Board.Symbol -> windowManager.attachWindow(liquidKeyboard)
Board.Main -> windowManager.attachWindow(KeyboardWindow)
Board.Symbol -> windowManager.attachWindow(LiquidKeyboard)
}
quickBar.switchUiByState(QuickBar.State.entries[board.ordinal])
}

private var showingDialog: Dialog? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import com.osfans.trime.data.theme.ThemeManager
import com.osfans.trime.ime.broadcast.IntentReceiver
import com.osfans.trime.ime.enums.FullscreenMode
import com.osfans.trime.ime.enums.InlinePreeditMode
import com.osfans.trime.ime.enums.KeyCommandType
import com.osfans.trime.ime.enums.Keycode
import com.osfans.trime.ime.enums.SymbolKeyboardType
import com.osfans.trime.ime.keyboard.Event
Expand All @@ -64,7 +63,6 @@ import com.osfans.trime.ime.keyboard.InputFeedbackManager
import com.osfans.trime.ime.keyboard.Key
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
import com.osfans.trime.ime.keyboard.KeyboardView
import com.osfans.trime.ime.symbol.LiquidTabsUi
import com.osfans.trime.ime.symbol.TabManager
import com.osfans.trime.ime.text.Candidate
import com.osfans.trime.ime.text.CompositionPopupWindow
Expand All @@ -89,7 +87,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
get() = AppPrefs.defaultInstance()
private var mainKeyboardView: KeyboardView? = null // 主軟鍵盤
private var mCandidate: Candidate? = null // 候選
private var liquidTabsUi: LiquidTabsUi? = null
var inputView: InputView? = null
private var initializationUi: InitializationUi? = null
private var eventListeners = WeakHashSet<EventListener>()
Expand Down Expand Up @@ -271,7 +268,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
if (tabIndex >= 0) {
inputView!!.switchBoard(InputView.Board.Symbol)
symbolKeyboardType = inputView!!.liquidKeyboard.select(tabIndex)
liquidTabsUi?.activateTab(TabManager.selectedOrZero)
mCompositionPopupWindow?.composition?.compositionView?.changeToLiquidKeyboardToolbar()
showCompositionView(false)
} else {
Expand Down Expand Up @@ -319,17 +315,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
mainKeyboardView = inputView!!.keyboardWindow.oldMainInputView.mainKeyboardView
// 初始化候选栏
mCandidate = inputView!!.quickBar.oldCandidateBar.candidates
liquidTabsUi =
inputView!!.quickBar.tabsUi.apply {
setOnTabClickListener {
val tag = TabManager.tabTags[it]
if (tag.type == SymbolKeyboardType.NO_KEY && tag.command == KeyCommandType.EXIT) {
selectLiquidKeyboard(-1)
} else {
selectLiquidKeyboard(it)
}
}
}

mCompositionPopupWindow =
CompositionPopupWindow(this, ThemeManager.activeTheme).apply {
Expand Down Expand Up @@ -1134,8 +1119,6 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
} else {
mCandidate!!.setText(0)
}
// 刷新候选词后,如果候选词超出屏幕宽度,滚动候选栏
// mTabRoot?.move(mCandidate!!.highlightLeft, mCandidate!!.highlightRight)
}
mainKeyboardView?.invalidateComposingKeys()
if (!onEvaluateInputViewShown()) setCandidatesViewShown(textInputManager!!.isComposable) // 實體鍵盤打字時顯示候選欄
Expand Down
41 changes: 17 additions & 24 deletions app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.osfans.trime.ime.symbol

import android.content.Context
import android.view.View
import androidx.core.view.setPadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.StaggeredGridLayoutManager
Expand All @@ -21,19 +20,12 @@ import com.osfans.trime.ime.core.TrimeInputMethodService
import com.osfans.trime.ime.dependency.InputScope
import com.osfans.trime.ime.enums.KeyCommandType
import com.osfans.trime.ime.enums.SymbolKeyboardType
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
import com.osfans.trime.ime.text.TextInputManager
import com.osfans.trime.ime.window.BoardWindow
import com.osfans.trime.ime.window.ResidentWindow
import kotlinx.coroutines.launch
import me.tatarka.inject.annotations.Inject
import splitties.dimensions.dp
import splitties.views.dsl.constraintlayout.centerInParent
import splitties.views.dsl.constraintlayout.constraintLayout
import splitties.views.dsl.constraintlayout.lParams
import splitties.views.dsl.core.add
import splitties.views.dsl.core.matchParent
import splitties.views.dsl.recyclerview.recyclerView
import timber.log.Timber

@InputScope
Expand All @@ -42,7 +34,8 @@ class LiquidKeyboard(
private val context: Context,
private val service: TrimeInputMethodService,
private val theme: Theme,
) : BoardWindow.NoBarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener {
) : BoardWindow.BarBoardWindow(), ResidentWindow, ClipboardHelper.OnClipboardUpdateListener {
private lateinit var liquidLayout: LiquidLayout
private val symbolHistory = SymbolHistory(180)
private var adapterType: AdapterType = AdapterType.INIT
private val simpleAdapter by lazy {
Expand Down Expand Up @@ -81,23 +74,22 @@ class LiquidKeyboard(
override val key: ResidentWindow.Key
get() = LiquidKeyboard

private val keyboardView =
context.recyclerView {
val space = dp(3)
addItemDecoration(SpacesItemDecoration(space))
setPadding(space)
}
private val keyboardView by lazy {
liquidLayout.boardView
}

override fun onCreateView(): View {
return context.constraintLayout {
add(
keyboardView,
lParams(matchParent, KeyboardSwitcher.currentKeyboard.keyboardHeight) {
centerInParent()
},
)
override fun onCreateView(): View =
LiquidLayout(context, theme).apply {
liquidLayout = this
tabsUi.apply {
setTabs(TabManager.tabTags)
setOnTabClickListener { i ->
select(i)
}
}
}
}

override fun onCreateBarView() = liquidLayout.tabsUi.root

override fun onAttached() {}

Expand Down Expand Up @@ -128,6 +120,7 @@ class LiquidKeyboard(

fun select(i: Int): SymbolKeyboardType {
val tag = TabManager.tabTags[i]
liquidLayout.tabsUi.activateTab(i)
symbolHistory.load()
when (tag.type) {
SymbolKeyboardType.CLIPBOARD,
Expand Down
39 changes: 39 additions & 0 deletions app/src/main/java/com/osfans/trime/ime/symbol/LiquidLayout.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.osfans.trime.ime.symbol

import android.annotation.SuppressLint
import android.content.Context
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.setPadding
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.ime.keyboard.KeyboardSwitcher
import splitties.dimensions.dp
import splitties.views.dsl.constraintlayout.bottomOfParent
import splitties.views.dsl.constraintlayout.centerHorizontally
import splitties.views.dsl.constraintlayout.lParams
import splitties.views.dsl.constraintlayout.matchConstraints
import splitties.views.dsl.constraintlayout.topOfParent
import splitties.views.dsl.core.add
import splitties.views.dsl.recyclerview.recyclerView

@SuppressLint("ViewConstructor")
class LiquidLayout(context: Context, theme: Theme) : ConstraintLayout(context) {
val boardView =
recyclerView {
val space = dp(3)
addItemDecoration(SpacesItemDecoration(space))
setPadding(space)
}

val tabsUi = LiquidTabsUi(context, theme)

init {
add(
boardView,
lParams(matchConstraints, KeyboardSwitcher.currentKeyboard.keyboardHeight) {
topOfParent()
centerHorizontally()
bottomOfParent()
},
)
}
}
1 change: 0 additions & 1 deletion app/src/main/java/com/osfans/trime/ime/symbol/TabTag.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.osfans.trime.ime.symbol

import android.graphics.Rect
import com.osfans.trime.ime.enums.KeyCommandType
import com.osfans.trime.ime.enums.SymbolKeyboardType

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class BoardWindowManager(
val oldView = currentView!!
oldWindow.onDetached()
view.removeView(oldView)
broadcaster.onWindowDetached(oldWindow)
Timber.d("Detach $oldWindow")
if (oldWindow !is ResidentWindow) {
broadcaster.removeReceiver(oldWindow)
Expand All @@ -75,6 +76,7 @@ class BoardWindowManager(
Timber.d("Attach $window")
window.onAttached()
currentWindow = window
broadcaster.onWindowAttached(window)
}

val view: FrameLayout by lazy { context.frameLayout() }
Expand Down
20 changes: 0 additions & 20 deletions app/src/main/res/layout/symbol_input_layout.xml

This file was deleted.

0 comments on commit 8fe83c8

Please sign in to comment.