Skip to content

Commit

Permalink
Use 'AppStateFlow' to derive input position
Browse files Browse the repository at this point in the history
  • Loading branch information
NorseDreki committed Feb 23, 2024
1 parent c9c62c1 commit 9c01570
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 60 deletions.
2 changes: 1 addition & 1 deletion src/nativeMain/kotlin/AppConfig.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object AppConfig {

const val INPUT_KEY_DELAY_MILLIS = 30L
const val INPUT_KEY_DELAY_MILLIS = 10L

const val DEFAULT_TAG_WIDTH = 23

Expand Down
12 changes: 10 additions & 2 deletions src/nativeMain/kotlin/AppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ data class AppState(

val autoscroll: Boolean,

val packageFilter: Pair<ByPackage?, Boolean>
val packageFilter: Pair<ByPackage?, Boolean>,

val inputFilterLocation: Pair<Int, Int>

//val linesCount: Int,
)
Expand All @@ -18,11 +20,13 @@ interface AppStateFlow {
fun autoscroll(on: Boolean)

fun filterByPackage(f: ByPackage?, enable: Boolean)

fun setInputFilterLocation(x: Int, y: Int)
}

class InternalAppStateFlow : AppStateFlow {

override val state = MutableStateFlow(AppState(false, null to false))
override val state = MutableStateFlow(AppState(false, null to false, 0 to 0))

override fun autoscroll(on: Boolean) {
state.value = state.value.copy(autoscroll = on)
Expand All @@ -36,4 +40,8 @@ class InternalAppStateFlow : AppStateFlow {
state.value = state.value.copy(packageFilter = f to enable)
//}
}

override fun setInputFilterLocation(x: Int, y: Int) {
state.value = state.value.copy(inputFilterLocation = x to y)
}
}
2 changes: 1 addition & 1 deletion src/nativeMain/kotlin/FileLogger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class FileLogger : CanLog {
?: throw RuntimeException("Was not able to open log file for writing.")

override fun d(line: String) {
fprintf(file, "$line$\n")
fprintf(file, "$line\n")
fflush(file)
}

Expand Down
2 changes: 1 addition & 1 deletion src/nativeMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ fun main(args: Array<String>) {
with(appModule) {
Logger.set(fileLogger)

input.start()
appPresenter.start()
input.start()

input
.keypresses
Expand Down
10 changes: 7 additions & 3 deletions src/nativeMain/kotlin/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import BuildConfig
import FileLogger
import InternalAppStateFlow
import di.DogcatModule.dogcatModule
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CloseableCoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import logger.CanLog
Expand All @@ -19,7 +19,7 @@ import ui.status.StatusPresenter
import userInput.DefaultInput
import userInput.Input

class AppModule {
class AppModule(ui: CloseableCoroutineDispatcher) {

private val appModule = DI.Module("app") {
bindSingleton<CanLog> {
Expand All @@ -29,8 +29,10 @@ class AppModule {
NoOpLogger()
}
}
bindSingleton<Input> { DefaultInput(Dispatchers.IO) }

//bindSingleton<Input> { DefaultInput(Dispatchers.IO) }
bindSingleton<AppStateFlow> { InternalAppStateFlow() }
bindSingleton<Input> { DefaultInput(instance()) }
bindSingleton<AppPresenter> {
AppPresenter(
instance(),
Expand Down Expand Up @@ -60,4 +62,6 @@ class AppModule {
val input: Input by serviceLocator.instance()

val appPresenter: AppPresenter by serviceLocator.instance()


}
2 changes: 2 additions & 0 deletions src/nativeMain/kotlin/ui/AppPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class AppPresenter(
else -> dogcat(Start.PickAllApps)
}

appStateFlow.setInputFilterLocation("Filter: ".length, 49)

view.start()

val scope = CoroutineScope(coroutineContext)
Expand Down
2 changes: 2 additions & 0 deletions src/nativeMain/kotlin/ui/AppView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class AppView {

//intrflush(stdscr, false)

//nonl()

//nl()
//Use the ncurses functions for output. My guess is that initscr changes terminal settings such that \n only performs a line feed, not a carriage return. –
//melpomene
Expand Down
5 changes: 3 additions & 2 deletions src/nativeMain/kotlin/ui/logLines/LogLinesView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,16 @@ class LogLinesView {

fun refresh() {
//logger.Logger.d("FVL $firstVisibleLine")
curs_set(0)
prefresh(pad, firstVisibleLine, 0, position.startY, position.startX, position.endY, position.endX)

val notSeeingLastLine = firstVisibleLine <= linesCount - pageSize
if (notSeeingLastLine) {
curs_set(0)
//curs_set(0)
//Logger.d("Cursor is hidden")
} else {
//wmove(pad, firstVisibleLine, 0)
curs_set(1)
//curs_set(1)
//Logger.d("Cursor is visible")
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/nativeMain/kotlin/ui/status/StatusPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,15 @@ class StatusPresenter(
}
.launchIn(scope)

/*dogcat

dogcat
.state
.filterIsInstance<CapturingInput>()
.filterIsInstance<Active>()
.flatMapLatest { it.heartbeat }
.onEach {
view.updateDevice("Device", it)
//view.updateDevice("Device", it)
}
.launchIn(scope)*/
.launchIn(scope)
}

suspend fun stop() {
Expand Down
79 changes: 33 additions & 46 deletions src/nativeMain/kotlin/userInput/Input.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package userInput

import AppConfig.INPUT_KEY_DELAY_MILLIS
import AppStateFlow
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
Expand All @@ -18,35 +19,34 @@ interface Input : HasLifecycle {
}

class DefaultInput(
private val ioDispatcher: CoroutineDispatcher
private val appStateFlow: AppStateFlow
) : Input {

private val keypressesSubject = MutableSharedFlow<Int>()
override val keypresses = keypressesSubject //.debounceRepetitiveKeys(150.milliseconds)
override val keypresses = keypressesSubject

private val stringsSubject = MutableSharedFlow<String>()
override val strings = stringsSubject

private var inputMode = false
//private val inputModeMutex = Mutex()

private val fl = 0//"Filter: ".length

private var inputBuffer = StringBuilder()
private var cursorPosition = fl

@OptIn(ExperimentalForeignApi::class)
override suspend fun start() {
val x = appStateFlow.state.value.inputFilterLocation.first
val y = appStateFlow.state.value.inputFilterLocation.second

CoroutineScope(coroutineContext)
.launch {//(ioDispatcher) {
.launch {
var cursorPosition = x

while (isActive) {
val key = wgetch(stdscr)

if (key == ERR) {

if (inputMode) {
curs_set(1)
wmove(stdscr, 49 , cursorPosition)
wmove(stdscr, y , cursorPosition)
wrefresh(stdscr)
}

Expand All @@ -55,75 +55,62 @@ class DefaultInput(
continue
}

if (Keymap.bindings[key] == Keymap.Actions.InputFilterBySubstring) {
if (Keymap.bindings[key] == Keymap.Actions.InputFilterBySubstring && !inputMode) {
inputMode = true
//echo()

mvwaddstr(stdscr, y, 0, "Filter: ")

continue
}


// limit max input
if (inputMode) {
when (key) {
KEY_LEFT -> if (cursorPosition > 0) cursorPosition--
KEY_RIGHT -> if (cursorPosition < inputBuffer.length) cursorPosition++
KEY_BACKSPACE, 127/*, KEY_DELETE*/ -> {
Logger.d("${context()} Delete char")
KEY_LEFT -> if (cursorPosition - x > 0) cursorPosition--

KEY_RIGHT -> if (cursorPosition - x < inputBuffer.length) cursorPosition++

if (cursorPosition > 0) {
inputBuffer.deleteAt(cursorPosition - fl - 1)
KEY_BACKSPACE, 127/*, KEY_DELETE*/ -> {
if (cursorPosition - x > 0) {
inputBuffer.deleteAt(cursorPosition - x - 1)
cursorPosition--
// Delete the character on the screen
mvdelch(49, cursorPosition)

mvdelch(y, cursorPosition)
}
}

'\n'.code -> {
// Handle the completed input
val input = inputBuffer.toString()
inputBuffer.clear()
cursorPosition = fl
//noecho()
cursorPosition = x
curs_set(0)
inputMode = false
// Emit the input string

stringsSubject.emit(input)
}

//add ESC support

else -> {
val char = key.toChar()

if (char in ' '..'~') {
inputBuffer.insert(cursorPosition, char)
mvaddch(49, cursorPosition, key.toUInt())
inputBuffer.insert(cursorPosition - x, char)
mvaddch(y, cursorPosition, key.toUInt())

cursorPosition++
// Add the character to the screen
}
}
}
// Move the cursor to the correct position
wmove(stdscr, 49, cursorPosition)
wmove(stdscr, y, cursorPosition)

} else {
Logger.d("${context()} Process key $key")
keypressesSubject.emit(key)
}
}
}


/*CoroutineScope(coroutineContext)
.launch(ioDispatcher) {
while (isActive) {
val key = wgetch(stdscr)
if (key == ERR) {
delay(INPUT_KEY_DELAY_MILLIS)
continue
}
Logger.d("${context()} Process key $key")
keypressesSubject.emit(key)
}
}*/
}

override suspend fun stop() {
Expand Down

0 comments on commit 9c01570

Please sign in to comment.