Skip to content

Commit

Permalink
feat: improve theming and text rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
SuhasDissa committed May 6, 2024
1 parent 461508e commit e3abf0a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
Expand All @@ -23,11 +22,10 @@ import net.youapps.calcyou.viewmodels.GraphViewModel

@Composable
fun CanvasView(vm: GraphViewModel) {
Box(Modifier.background(Color.White)) {
Box(Modifier.background(MaterialTheme.colorScheme.background)) {
val textMeasurer = rememberTextMeasurer()
val drawModifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.pointerInput(Unit) {
awaitEachGesture {
val downEvent = awaitFirstDown()
Expand Down Expand Up @@ -86,10 +84,12 @@ fun CanvasView(vm: GraphViewModel) {
} while (event.changes.any { it.pressed })
}
}
val gridLinesColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.2f)
val gridAxesColor = MaterialTheme.colorScheme.onBackground
Canvas(modifier = drawModifier) {
val scale = 1f
scale(scale) {
renderCanvas(vm.window, vm, scale, textMeasurer)
renderCanvas(vm.window, vm, scale, textMeasurer, gridLinesColor, gridAxesColor)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import net.youapps.calcyou.data.graphing.Function
import net.youapps.calcyou.data.graphing.Window
import net.youapps.calcyou.data.graphing.unitToPxCoordinates
import net.youapps.calcyou.viewmodels.GraphViewModel
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.floor

fun DrawScope.drawGridLines(window: Window, lineWidth: Float) {
fun DrawScope.drawGridLines(window: Window, lineWidth: Float, gridLinesColor: Color) {
val xRange = IntRange(
ceil(window.xMin / window.xScale).toInt(),
floor(window.xMax / window.xScale).toInt()
Expand All @@ -23,7 +27,7 @@ fun DrawScope.drawGridLines(window: Window, lineWidth: Float) {
if (i == 0) continue
val xDraw =
Offset(i * window.xScale, 0f).unitToPxCoordinates(window, size.width, size.height).x
drawLine(Color.LightGray, Offset(xDraw, 0f), Offset(xDraw, size.height), lineWidth)
drawLine(gridLinesColor, Offset(xDraw, 0f), Offset(xDraw, size.height), lineWidth)
}
val yRange = IntRange(
ceil(window.yMin / window.yScale).toInt(),
Expand All @@ -34,25 +38,49 @@ fun DrawScope.drawGridLines(window: Window, lineWidth: Float) {
if (i == 0) continue
val yDraw =
Offset(0f, i * window.yScale).unitToPxCoordinates(window, size.width, size.height).y
drawLine(Color.LightGray, Offset(0f, yDraw), Offset(size.width, yDraw), lineWidth)
drawLine(gridLinesColor, Offset(0f, yDraw), Offset(size.width, yDraw), lineWidth)
}
}

internal fun Float.toDisplayString(): String {
return when {
(this % 1f == 0f) && (this in 0.0001f..10000f) -> {
this.toInt().toString()
}

abs(this) <= 0.0001 -> {
"%.3e".format(this)
}

abs(this) < 10000 -> {
this.toString()
}

else -> {
"%.2e".format(this)
}
}
}

fun DrawScope.drawAxes(
window: Window, lineWidth: Float, canvasScale: Float, textMeasurer: TextMeasurer
window: Window,
lineWidth: Float,
canvasScale: Float,
textMeasurer: TextMeasurer,
axesColor: Color
) {

// y-axis
val windowCenterInCanvas = Offset(0f, 0f).unitToPxCoordinates(window, size.width, size.height)
drawLine(
Color.Black,
axesColor,
Offset(windowCenterInCanvas.x, 0f),
Offset(windowCenterInCanvas.x, size.height),
lineWidth
)
// x-axis
drawLine(
Color.Black,
axesColor,
Offset(0f, windowCenterInCanvas.y),
Offset(size.width, windowCenterInCanvas.y),
lineWidth
Expand All @@ -66,25 +94,32 @@ fun DrawScope.drawAxes(
for (i in xTickRange) {
if (i == 0) continue

val xDisplayValue = (i * window.xScale).toString()
val xDisplayValue = (i * window.xScale).toDisplayString()
val xDraw =
Offset(i * window.xScale, 0f).unitToPxCoordinates(window, size.width, size.height).x
val yDraw = Offset(0f, 0f).unitToPxCoordinates(window, size.width, size.height).y

// Ticks and labels
val halfTickLength = 10f / canvasScale
val textOffset = 15f / canvasScale
drawLine(
Color.Black,
axesColor,
Offset(xDraw, yDraw + halfTickLength),
Offset(xDraw, yDraw - halfTickLength),
lineWidth
)
val textWidth = 200 / canvasScale
val textHeight = 40 / canvasScale
val textPadding = 20 / canvasScale
drawText(
textMeasurer,
xDisplayValue,
topLeft = Offset(xDraw, yDraw + textOffset),
size = Size(50 / canvasScale, 40 / canvasScale)
topLeft = Offset(xDraw - textWidth / 2, yDraw + textPadding),
size = Size(textWidth, textHeight),
style = TextStyle(
color = axesColor,
textAlign = TextAlign.Center,
fontWeight = FontWeight.Medium
)
)
}

Expand All @@ -95,24 +130,27 @@ fun DrawScope.drawAxes(
for (i in yTickRange) {
if (i == 0) continue

val yDisplayValue = (i * window.yScale).toString()
val yDisplayValue = (i * window.yScale).toDisplayString()
val xDraw = Offset(0f, 0f).unitToPxCoordinates(window, size.width, size.height).x
val yDraw =
Offset(0f, i * window.yScale).unitToPxCoordinates(window, size.width, size.height).y

val halfTickLength = 10f / canvasScale
val textOffset = 15f / canvasScale
drawLine(
Color.Black,
axesColor,
Offset(xDraw - halfTickLength, yDraw),
Offset(xDraw + halfTickLength, yDraw),
lineWidth
)
val textWidth = 200 / canvasScale
val textHeight = 40 / canvasScale
val textPadding = 20 / canvasScale
drawText(
textMeasurer,
yDisplayValue,
topLeft = Offset(xDraw - textOffset, yDraw),
size = Size(50 / canvasScale, 40 / canvasScale)
topLeft = Offset(xDraw + textPadding, yDraw - textHeight / 2),
size = Size(textWidth, textHeight),
style = TextStyle(color = axesColor, fontWeight = FontWeight.Medium)
)
}
}
Expand Down Expand Up @@ -141,12 +179,14 @@ fun DrawScope.renderCanvas(
window: Window,
vm: GraphViewModel,
canvasScale: Float,
textMeasurer: TextMeasurer
textMeasurer: TextMeasurer,
gridLinesColor: Color,
axesColor: Color
) {
val lineWidth = 5f / canvasScale
window.findAutoScale()
drawGridLines(window, lineWidth)
drawAxes(window, lineWidth, canvasScale, textMeasurer)
drawGridLines(window, lineWidth, gridLinesColor)
drawAxes(window, lineWidth, canvasScale, textMeasurer, axesColor)

vm.functions.forEach { drawGraph(window, it, lineWidth) }
}

0 comments on commit e3abf0a

Please sign in to comment.