@@ -4,7 +4,6 @@ import androidx.compose.ui.geometry.Offset
44import androidx.compose.ui.geometry.Size
55import androidx.lifecycle.ViewModel
66import androidx.lifecycle.viewModelScope
7- import kotlinx.coroutines.CancellationException
87import kotlinx.coroutines.Dispatchers
98import kotlinx.coroutines.Job
109import kotlinx.coroutines.delay
@@ -23,8 +22,7 @@ class UiViewModel : ViewModel() {
2322 val functionsState: StateFlow <FunctionsState > = _functionsState .asStateFlow()
2423
2524 private var nativeBridge = NativeBridge ()
26- private var calculationJob: Job ? = null
27- private var updateJob: Job ? = null
25+ private var reloadJob: Job ? = null
2826
2927 fun updateFunction (function : String ) {
3028 _functionsState .update { currentState ->
@@ -41,32 +39,31 @@ class UiViewModel : ViewModel() {
4139 canvasSize = size
4240 )
4341 }
44- updateJob?.cancel()
45- updateJob = viewModelScope.launch {
46- delay(50 )
47- updateGraph()
48- }
42+ updateGraph()
4943 }
5044
51- fun updateOffset ( offsetChange : Offset ) {
45+ fun updateScaleOffset ( scaleChange : Float , offsetChange : Offset ) {
5246 _graphState .update { currentState ->
5347 currentState.copy(
5448 xOffset = currentState.xOffset + offsetChange.x,
55- yOffset = currentState.yOffset + offsetChange.y
49+ yOffset = currentState.yOffset + offsetChange.y,
50+ xWidth = currentState.xWidth / scaleChange
5651 )
5752 }
58- updateJob?.cancel()
59- updateJob = viewModelScope.launch {
60- delay(50 )
61- updateGraph()
53+ if (reloadJob?.isActive != true ) {
54+ reloadJob = viewModelScope.launch {
55+ updateGraph()
56+ delay(16 ) // Limit to roughly 60fps max
57+ }
6258 }
6359 }
6460
65- fun resetOffset () {
61+ fun resetOrigin () {
6662 _graphState .update { currentState ->
6763 currentState.copy(
6864 xOffset = 0f ,
69- yOffset = 0f
65+ yOffset = 0f ,
66+ xWidth = 10f
7067 )
7168 }
7269 updateGraph()
@@ -106,48 +103,36 @@ class UiViewModel : ViewModel() {
106103
107104 fun updateGraph () {
108105 if (functionsState.value.function.isNotEmpty()) {
109- calculationJob?.cancel()
110- calculationJob = viewModelScope.launch(Dispatchers .IO ) {
111- try {
112- val xWidth =
113- graphState.value.xWidth // Number of integral x-coordinates visible on screen
114- val yWidth =
115- xWidth * (graphState.value.canvasSize.height / graphState.value.canvasSize.width)
116- val function = functionsState.value.function
117- val canvasSize = graphState.value.canvasSize
118-
119- // We use the native C++ function for calculating graph points to plot faster
120-
121- val newPoints = nativeBridge
122- .calculateGraphPoints(
123- xWidth = xWidth,
124- yWidth = yWidth.toDouble(),
125- xOffset = graphState.value.xOffset.toDouble(),
126- yOffset = graphState.value.yOffset.toDouble(),
127- canvasWidth = canvasSize.width.toDouble(),
128- canvasHeight = canvasSize.height.toDouble(),
129- tStart = functionsState.value.tStart,
130- tEnd = functionsState.value.tEnd,
131- thetaStart = functionsState.value.thetaStart,
132- thetaEnd = functionsState.value.thetaEnd,
133- function = function
134- )
135- .toOffsetList()
136-
137- _graphState .update { currentState ->
138- currentState.copy(
139- invalidations = currentState.invalidations + 1 ,
140- points = newPoints
141- )
142- }
143- } catch (e: Exception ) {
144- if (e !is CancellationException )
145- _graphState .update { currentState ->
146- currentState.copy(
147- invalidations = currentState.invalidations + 1 ,
148- points = emptyList()
149- )
150- }
106+ viewModelScope.launch(Dispatchers .IO ) {
107+ val xWidth =
108+ graphState.value.xWidth // Number of integral x-coordinates visible on screen
109+ val yWidth =
110+ xWidth * (graphState.value.canvasSize.height / graphState.value.canvasSize.width)
111+ val function = functionsState.value.function
112+ val canvasSize = graphState.value.canvasSize
113+
114+ // We use the native C++ function for calculating graph points to plot faster
115+ val newPoints = nativeBridge
116+ .calculateGraphPoints(
117+ xWidth = xWidth.toDouble(),
118+ yWidth = yWidth.toDouble(),
119+ xOffset = graphState.value.xOffset.toDouble(),
120+ yOffset = graphState.value.yOffset.toDouble(),
121+ canvasWidth = canvasSize.width.toDouble(),
122+ canvasHeight = canvasSize.height.toDouble(),
123+ tStart = functionsState.value.tStart,
124+ tEnd = functionsState.value.tEnd,
125+ thetaStart = functionsState.value.thetaStart,
126+ thetaEnd = functionsState.value.thetaEnd,
127+ function = function
128+ )
129+ .toOffsetList()
130+
131+ _graphState .update { currentState ->
132+ currentState.copy(
133+ invalidations = currentState.invalidations + 1 ,
134+ points = newPoints
135+ )
151136 }
152137 }
153138 }
0 commit comments