diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/DrawScreen.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/DrawScreen.kt index 9d1257a643..bb569872e2 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/DrawScreen.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/DrawScreen.kt @@ -82,6 +82,7 @@ import dev.olshevski.navigation.reimagined.hilt.hiltViewModel import kotlinx.coroutines.launch import ru.tech.imageresizershrinker.presentation.draw_screen.components.BlurRadiusSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawAlphaSelector +import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawArrowsSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawBackgroundSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawBehavior import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawColorSelector @@ -295,6 +296,9 @@ fun DrawScreen( var blurRadius by rememberSaveable(viewModel.drawBehavior, drawMode) { mutableFloatStateOf(if (drawMode is DrawMode.Neon) 35f else 0f) } + var drawArrowsEnabled by remember(viewModel.drawBehavior) { + mutableStateOf(false) + } val controls = @Composable { OpenColorPickerCard( @@ -349,6 +353,17 @@ fun DrawScreen( drawMode = drawMode, onDrawModeChange = { drawMode = it } ) + AnimatedVisibility(!isEraserOn) { + DrawArrowsSelector( + modifier = Modifier.padding( + start = 16.dp, + end = 16.dp, + bottom = 16.dp + ), + checked = drawArrowsEnabled, + onCheckedChange = { drawArrowsEnabled = it } + ) + } SaveExifWidget( modifier = Modifier.padding(horizontal = 16.dp), selected = viewModel.saveExif, @@ -434,6 +449,7 @@ fun DrawScreen( onShare = { viewModel.shareBitmap { showConfetti() } }, paths = viewModel.paths, isEraserOn = isEraserOn, + drawArrowsEnabled = drawArrowsEnabled, drawMode = drawMode, backgroundColor = backgroundColor, drawColor = drawColor.copy(alpha), diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/BitmapDrawer.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/BitmapDrawer.kt index 8beb78894b..dc0e755944 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/BitmapDrawer.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/BitmapDrawer.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.ImageShader import androidx.compose.ui.graphics.Paint import androidx.compose.ui.graphics.PaintingStyle import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.PathMeasure import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.StrokeJoin import androidx.compose.ui.graphics.asAndroidBitmap @@ -53,6 +54,8 @@ import ru.tech.imageresizershrinker.presentation.erase_background_screen.compone import ru.tech.imageresizershrinker.presentation.erase_background_screen.components.transparencyChecker import ru.tech.imageresizershrinker.presentation.root.theme.outlineVariant import ru.tech.imageresizershrinker.presentation.root.transformation.filter.StackBlurFilter +import kotlin.math.cos +import kotlin.math.sin @Composable @@ -66,6 +69,7 @@ fun BitmapDrawer( isEraserOn: Boolean, drawMode: DrawMode, modifier: Modifier, + drawArrowsEnabled: Boolean, onDraw: (Bitmap) -> Unit, backgroundColor: Color, zoomEnabled: Boolean, @@ -128,7 +132,7 @@ fun BitmapDrawer( LaunchedEffect(imageBitmap, drawBitmap) { blurredBitmap = imageManager.transform( image = drawImageBitmap.overlay(drawBitmap).asAndroidBitmap(), - transformations = listOf(StackBlurFilter(context, 0.3f to 50)) + transformations = listOf(StackBlurFilter(context, 0.3f to 20)) )?.asImageBitmap() } @@ -204,6 +208,35 @@ fun BitmapDrawer( MotionEvent.Up -> { drawPath.lineTo(currentPosition.x, currentPosition.y) + + if (drawArrowsEnabled && !isEraserOn) { + val preLastPoint = PathMeasure().apply { + setPath(drawPath, false) + }.let { + it.getPosition(it.length - strokeWidth * 3f) + } + val lastPoint = currentPosition + + val (x, y) = lastPoint - preLastPoint + + + val angle1 = 150.0 + val rotatedX1 = + x * cos(Math.toRadians(angle1)) - y * sin(Math.toRadians(angle1)) + val rotatedY1 = + x * sin(Math.toRadians(angle1)) + y * cos(Math.toRadians(angle1)) + + val angle2 = 210.0 + val rotatedX2 = + x * cos(Math.toRadians(angle2)) - y * sin(Math.toRadians(angle2)) + val rotatedY2 = + x * sin(Math.toRadians(angle2)) + y * cos(Math.toRadians(angle2)) + + drawPath.relativeLineTo(rotatedX1.toFloat(), rotatedY1.toFloat()) + drawPath.moveTo(lastPoint.x, lastPoint.y) + drawPath.relativeLineTo(rotatedX2.toFloat(), rotatedY2.toFloat()) + } + currentPosition = Offset.Unspecified previousPosition = currentPosition motionEvent = MotionEvent.Idle diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawArrowsSelector.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawArrowsSelector.kt new file mode 100644 index 0000000000..796ae41376 --- /dev/null +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawArrowsSelector.kt @@ -0,0 +1,61 @@ +package ru.tech.imageresizershrinker.presentation.draw_screen.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowCircleUp +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import ru.tech.imageresizershrinker.R +import ru.tech.imageresizershrinker.presentation.root.utils.modifier.container + +@Composable +fun DrawArrowsSelector( + modifier: Modifier, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit +) { + Row( + modifier = modifier + .container(shape = RoundedCornerShape(24.dp), resultPadding = 0.dp) + .clickable { onCheckedChange(!checked) } + .padding(horizontal = 16.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(Icons.Rounded.ArrowCircleUp, null, modifier = Modifier.defaultMinSize(24.dp, 24.dp)) + Column( + modifier = Modifier + .weight(1f) + .padding(start = 16.dp, end = 16.dp, top = 6.dp, bottom = 8.dp) + ) { + Text( + text = stringResource(R.string.draw_arrows), + fontWeight = FontWeight.Medium + ) + Text( + text = stringResource(R.string.draw_arrows_sub), + fontWeight = FontWeight.Normal, + color = LocalContentColor.current.copy(0.5f), + lineHeight = 12.sp, + fontSize = 12.sp + ) + } + Switch( + checked = checked, + onCheckedChange = onCheckedChange + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawHost.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawHost.kt index f2136a5f87..161120398f 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawHost.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/draw_screen/components/DrawHost.kt @@ -124,6 +124,7 @@ fun DrawHost( drawColor: Color, drawAlpha: Float, strokeWidth: Float, + drawArrowsEnabled: Boolean, bitmap: Bitmap, blurRadius: Float, addPath: (PathPaint) -> Unit, @@ -160,6 +161,7 @@ fun DrawHost( zoomEnabled = zoomEnabled, onDraw = onDraw, imageManager = imageManager, + drawArrowsEnabled = drawArrowsEnabled, backgroundColor = backgroundColor ) } diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/single_edit_screen/components/DrawEditOption.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/single_edit_screen/components/DrawEditOption.kt index 327a245b29..dd95a47b64 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/single_edit_screen/components/DrawEditOption.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/single_edit_screen/components/DrawEditOption.kt @@ -50,6 +50,7 @@ import ru.tech.imageresizershrinker.domain.image.ImageManager import ru.tech.imageresizershrinker.presentation.draw_screen.components.BitmapDrawer import ru.tech.imageresizershrinker.presentation.draw_screen.components.BlurRadiusSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawAlphaSelector +import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawArrowsSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawColorSelector import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawMode import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawModeSelector @@ -132,6 +133,9 @@ fun DrawEditOption( var blurRadius by rememberSaveable(drawMode) { mutableFloatStateOf(if (drawMode is DrawMode.Neon) 35f else 0f) } + var drawArrowsEnabled by remember { + mutableStateOf(false) + } val secondaryControls = @Composable { val border = BorderStroke( @@ -234,6 +238,17 @@ fun DrawEditOption( drawMode = drawMode, onDrawModeChange = { drawMode = it } ) + AnimatedVisibility(!isEraserOn) { + DrawArrowsSelector( + modifier = Modifier.padding( + start = 16.dp, + end = 16.dp, + bottom = 16.dp + ), + checked = drawArrowsEnabled, + onCheckedChange = { drawArrowsEnabled = it } + ) + } }, fabButtons = null, actions = { @@ -299,6 +314,7 @@ fun DrawEditOption( onDraw = { stateBitmap = it }, + drawArrowsEnabled = drawArrowsEnabled, backgroundColor = Color.Transparent ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9edb8c51b6..80cd255e6c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -378,6 +378,8 @@ Allow betas Update checking will include beta app versions if enabled Enables drawing shadows behind containers and buttons if borders are disabled + Draw Arrows + If enabled drawing path will be represented as pointing arrow Start Center