Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions app/src/main/java/net/youapps/calcyou/NavHost.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
package net.youapps.calcyou

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.input.KeyboardType
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import net.youapps.calcyou.data.evaluator.MathUtil
import net.youapps.calcyou.ui.CalculatorScreen
import net.youapps.calcyou.ui.components.NumberFormatter
import net.youapps.calcyou.ui.screens.CharacterInputScreen
import net.youapps.calcyou.ui.screens.ConverterGridScreen
import net.youapps.calcyou.ui.screens.ConverterScreen
import net.youapps.calcyou.ui.screens.graphing.GraphingScreen

@Composable
fun AppNavHost(modifier: Modifier = Modifier, navHostController: NavHostController) {
val currentConfiguration = LocalConfiguration.current
val numberFormatter = remember{ NumberFormatter(currentConfiguration) }
NavHost(
modifier = modifier,
navController = navHostController,
startDestination = Destination.Calculator.route
) {
composable(route = Destination.Calculator.route) {
CalculatorScreen()
CalculatorScreen(
formatNumberFromString = numberFormatter::formatNumberFromString,
userLocale = numberFormatter.locale
)
}

composable(route = Destination.Converters.route) {
Expand All @@ -45,7 +53,12 @@ fun AppNavHost(modifier: Modifier = Modifier, navHostController: NavHostControll
converterName = converter.resId,
keyboardType = KeyboardType.Number,
stringToConverterArg = { it.toDoubleOrNull() },
converterArgToString = { MathUtil.doubleToString(it) }
converterArgToString = { MathUtil.doubleToString(it) },
formatNumberFromString = numberFormatter::formatNumberFromString,
formatOctNumberFromString = numberFormatter::formatOctNumberFromString,
formatHexNumberFromString = numberFormatter::formatHexNumberFromString,
formatBinNumberFromString = numberFormatter::formatBinNumberFromString,
decimalSep = numberFormatter.decimalSep
)
}
}
Expand All @@ -57,7 +70,12 @@ fun AppNavHost(modifier: Modifier = Modifier, navHostController: NavHostControll
converterName = converter.resId,
keyboardType = KeyboardType.Text,
stringToConverterArg = { it.ifEmpty { null } },
converterArgToString = { it.orEmpty() }
converterArgToString = { it.orEmpty() },
formatNumberFromString = numberFormatter::formatNumberFromString,
formatOctNumberFromString = numberFormatter::formatOctNumberFromString,
formatHexNumberFromString = numberFormatter::formatHexNumberFromString,
formatBinNumberFromString = numberFormatter::formatBinNumberFromString,
decimalSep = numberFormatter.decimalSep
)
}
}
Expand Down
6 changes: 1 addition & 5 deletions app/src/main/java/net/youapps/calcyou/data/EventHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@ import androidx.compose.runtime.MutableState
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import net.youapps.calcyou.data.evaluator.TrigonometricMode
import java.lang.Exception
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols

class EventHandler(
private val context: Context,
private val onUpdateHistory: (String) -> Unit
) {
private val tokenizer = Tokenizer(context)
private val evaluator = FormattingEvaluator(tokenizer)
private val numberFormat = DecimalFormatSymbols.getInstance()

fun processEvent(
event: CalculatorEvent,
Expand All @@ -41,7 +37,7 @@ class EventHandler(
}

CalculatorEvent.Decimal -> {
currentText.insertText(numberFormat.decimalSeparator.toString())
currentText.insertText(".")
}

CalculatorEvent.Evaluate -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class FormattingEvaluator(private val tokenizer: Tokenizer) {
return if (result.isNaN()) {
null
} else {
val shortened = MathUtil.doubleToString(result)
tokenizer.getLocalizedExpression(shortened)
MathUtil.doubleToString(result)
}
}
}
14 changes: 10 additions & 4 deletions app/src/main/java/net/youapps/calcyou/ui/CalculatorScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ import net.youapps.calcyou.ui.components.CenterKeypadHorizontal
import net.youapps.calcyou.ui.components.Keypad
import net.youapps.calcyou.ui.components.SideKeypadHorizontal
import net.youapps.calcyou.viewmodels.CalculatorViewModel
import java.util.Locale

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CalculatorScreen(
modifier: Modifier = Modifier,
calculatorViewModel: CalculatorViewModel = viewModel(factory = CalculatorViewModel.Factory)
calculatorViewModel: CalculatorViewModel = viewModel(factory = CalculatorViewModel.Factory),
formatNumberFromString: (String)->String,
userLocale: Locale
) {
val orientation = LocalConfiguration.current.orientation
if (orientation == ORIENTATION_LANDSCAPE) {
Expand All @@ -50,10 +53,12 @@ fun CalculatorScreen(
CalculatorDisplay(
calculatorViewModel,
primaryTextStyle = MaterialTheme.typography.headlineMedium,
secondaryTextStyle = MaterialTheme.typography.headlineSmall
secondaryTextStyle = MaterialTheme.typography.headlineSmall,
formatNumberFromString = formatNumberFromString
)
CenterKeypadHorizontal(
calculatorViewModel::onEvent,
userLocale = userLocale,
textStyle = MaterialTheme.typography.headlineSmall,
iconSize = 32.dp
)
Expand All @@ -69,9 +74,10 @@ fun CalculatorScreen(
.then(modifier),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
CalculatorDisplay(calculatorViewModel)
CalculatorDisplay(calculatorViewModel, formatNumberFromString = formatNumberFromString)
Keypad(
onEvent = calculatorViewModel::onEvent,
userLocale = userLocale,
trigonometricMode = calculatorViewModel.trigonometricMode.value
)
}
Expand All @@ -82,5 +88,5 @@ fun CalculatorScreen(
@Preview(showBackground = true)
@Composable
private fun DefaultPreview() {
CalculatorScreen()
CalculatorScreen(formatNumberFromString = {""}, userLocale = Locale.getDefault())
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
Expand All @@ -25,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import net.youapps.calcyou.viewmodels.CalculatorViewModel
Expand All @@ -35,7 +35,8 @@ fun ColumnScope.CalculatorDisplay(
calculatorViewModel: CalculatorViewModel,
primaryTextStyle: TextStyle = MaterialTheme.typography.displayMedium,
secondaryTextStyle: TextStyle = MaterialTheme.typography.displaySmall,
tertiaryTextStyle: TextStyle = MaterialTheme.typography.titleLarge
tertiaryTextStyle: TextStyle = MaterialTheme.typography.titleLarge,
formatNumberFromString: (String)->String
) {
Column(
modifier = Modifier
Expand All @@ -61,7 +62,7 @@ fun ColumnScope.CalculatorDisplay(
) {
items(items = calculatorViewModel.history) { item ->
Text(
text = item,
text = formatNumberFromString(item),
modifier = Modifier
.animateItemPlacement()
.clickable {
Expand All @@ -75,7 +76,7 @@ fun ColumnScope.CalculatorDisplay(
}
CompositionLocalProvider(LocalTextInputService provides null) {
BasicTextField(
value = calculatorViewModel.displayText,
value = TextFieldValue(formatNumberFromString(calculatorViewModel.displayText.text)),
onValueChange = {
calculatorViewModel.displayText = it
},
Expand All @@ -101,7 +102,7 @@ fun ColumnScope.CalculatorDisplay(
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(20.dp))
.padding(vertical = 4.dp, horizontal = 16.dp),
text = previewText,
text = formatNumberFromString(previewText),
textAlign = TextAlign.End,
style = tertiaryTextStyle,
)
Expand Down
16 changes: 10 additions & 6 deletions app/src/main/java/net/youapps/calcyou/ui/components/Keypad.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import net.youapps.calcyou.data.evaluator.TrigonometricMode
import net.youapps.calcyou.ui.components.buttons.CalculatorButton
import net.youapps.calcyou.ui.components.buttons.CalculatorTextButton
import java.text.DecimalFormatSymbols
import java.util.Locale


val leftKeypad = arrayOf(
Expand Down Expand Up @@ -73,22 +74,24 @@ val combinedKeypad = arrayOf(
@Composable
fun Keypad(
trigonometricMode: TrigonometricMode,
onEvent: (CalculatorEvent) -> Unit
onEvent: (CalculatorEvent) -> Unit,
userLocale: Locale
) {
Column(
modifier = Modifier
.fillMaxWidth()
) {
SwipePanels(
start = { SideKeypad(onEvent = onEvent, keys = leftKeypad, trigonometricMode = trigonometricMode) },
center = { CenterKeypad(onEvent) },
center = { CenterKeypad(onEvent, userLocale = userLocale) },
end = { SideKeypad(onEvent = onEvent, keys = rightKeypad, trigonometricMode = trigonometricMode) })
}
}

@Composable
fun CenterKeypad(
onEvent: (CalculatorEvent) -> Unit
onEvent: (CalculatorEvent) -> Unit,
userLocale: Locale
) {
val buttonSpacing = 8.dp
Column(
Expand Down Expand Up @@ -247,7 +250,7 @@ fun CenterKeypad(
}
)
CalculatorButton(
text = remember { DecimalFormatSymbols.getInstance().decimalSeparator.toString() },
text = remember { DecimalFormatSymbols.getInstance(userLocale).decimalSeparator.toString() },
onClick = {
onEvent(CalculatorEvent.Decimal)
}
Expand Down Expand Up @@ -278,6 +281,7 @@ fun CenterKeypad(
@Composable
fun CenterKeypadHorizontal(
onEvent: (CalculatorEvent) -> Unit,
userLocale: Locale,
textStyle: TextStyle = MaterialTheme.typography.displaySmall,
iconSize: Dp = 48.dp
) {
Expand Down Expand Up @@ -456,7 +460,7 @@ fun CenterKeypadHorizontal(
textStyle = textStyle
)
CalculatorButton(
text = remember { DecimalFormatSymbols.getInstance().decimalSeparator.toString() },
text = remember { DecimalFormatSymbols.getInstance(userLocale).decimalSeparator.toString() },
square = false,
onClick = {
onEvent(CalculatorEvent.Decimal)
Expand Down Expand Up @@ -608,5 +612,5 @@ fun SideKeypadHorizontal(
@Preview(showBackground = true)
@Composable
private fun DefaultPreview() {
Keypad(onEvent = {}, trigonometricMode = TrigonometricMode.DEGREE)
Keypad(onEvent = {}, userLocale = Locale.getDefault(), trigonometricMode = TrigonometricMode.DEGREE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package net.youapps.calcyou.ui.components

import android.content.res.Configuration
import androidx.core.os.ConfigurationCompat
import java.text.DecimalFormatSymbols
import java.util.Locale

class NumberFormatter(configuration: Configuration) {
val locale: Locale = ConfigurationCompat.getLocales(configuration).get(0)?: Locale.getDefault()
private val symbols = DecimalFormatSymbols.getInstance(locale)
private val thousandsSep = symbols.groupingSeparator.toString()
private val bitGroupingSymb = " "
val decimalSep = symbols.decimalSeparator.toString()

// Escape special regex characters if needed
private val escapedDecimalSep = Regex.escape(decimalSep)
//The regex assumes that the decimal part of numbers won't have more than 99 digits
private val regex = """(?<!$escapedDecimalSep\d{0,99})\d(?=(\d{3})+(?!\d))""".toRegex()
private val hexRegex = """(?<!$escapedDecimalSep[0-9A-Fa-f]{0,99})[0-9A-Fa-f](?=([0-9A-Fa-f]{2})+(?![0-9A-Fa-f]))""".toRegex()
private val binRegex = """(?<!$escapedDecimalSep[0-1]{0,99})[0-1](?=([0-1]{4})+(?![0-1]))""".toRegex()

fun formatNumberFromString(input: String): String{
return input.replace(".", decimalSep)
.replace(regex, "$0$thousandsSep")
}
fun formatOctNumberFromString(input: String): String{
return input.replace(".", decimalSep)
.replace(regex, "$0$bitGroupingSymb")
}
fun formatHexNumberFromString(input: String): String{
return input.replace(".", decimalSep)
.replace(hexRegex, "$0$bitGroupingSymb")
}
fun formatBinNumberFromString(input: String): String{
return input.replace(".", decimalSep)
.replace(binRegex, "$0$bitGroupingSymb")
}
}

Loading