Skip to content

Commit a15080b

Browse files
add confirm and cancel options to frame selection
1 parent f57e842 commit a15080b

File tree

4 files changed

+119
-62
lines changed

4 files changed

+119
-62
lines changed

app/src/main/java/com/smarttoolfactory/composecropper/demo/ImageCropDemo.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,19 @@ fun ImageCropDemo() {
5151
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
5252
)
5353

54-
val defaultImage = ImageBitmap.imageResource(id = R.drawable.squircle)
54+
val defaultImage1 = ImageBitmap.imageResource(id = R.drawable.squircle)
55+
val defaultImage2 = ImageBitmap.imageResource(id = R.drawable.cloud)
56+
val defaultImage3 = ImageBitmap.imageResource(id = R.drawable.sun)
5557

56-
val cropFrameFactory = remember { CropFrameFactory(defaultImage) }
58+
val cropFrameFactory = remember {
59+
CropFrameFactory(
60+
listOf(
61+
defaultImage1,
62+
defaultImage2,
63+
defaultImage3
64+
)
65+
)
66+
}
5767

5868
var cropProperties by remember {
5969
mutableStateOf(

app/src/main/java/com/smarttoolfactory/composecropper/preferences/CropFrameSelection.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fun CropFrameSelection(
4040
CropFrameListDialog(
4141
aspectRatio = aspectRatio,
4242
cropFrame = cropFrame,
43-
onDismiss = {
43+
onConfirm = {
4444
cropFrame = it
4545
cropFrameFactory.editCropFrame(cropFrame)
4646

@@ -51,6 +51,9 @@ fun CropFrameSelection(
5151
)
5252
)
5353
showEditDialog = false
54+
},
55+
onDismiss = {
56+
showEditDialog = false
5457
}
5558
)
5659
}

app/src/main/java/com/smarttoolfactory/composecropper/preferences/frames/edit/CropFrameEditDialog.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.material3.AlertDialog
4-
import androidx.compose.material3.Button
54
import androidx.compose.material3.Text
5+
import androidx.compose.material3.TextButton
66
import androidx.compose.runtime.*
77
import androidx.compose.ui.graphics.ImageBitmap
88
import androidx.compose.ui.res.imageResource
@@ -101,8 +101,8 @@ fun CropFrameEditDialog(
101101
}
102102
},
103103
confirmButton = {
104-
Button(onClick = {
105-
104+
TextButton(
105+
onClick = {
106106
val newOutlines: List<CropOutline> = cropFrame.outlines
107107
.toMutableList()
108108
.apply {
@@ -116,11 +116,13 @@ fun CropFrameEditDialog(
116116

117117
onConfirm(newCropFrame)
118118
}) {
119-
Text("OK")
119+
Text("Accept")
120120
}
121121
},
122122
dismissButton = {
123-
Button(onClick = { onDismiss() }) {
123+
TextButton(
124+
onClick = { onDismiss() }
125+
) {
124126
Text(text = "Cancel")
125127
}
126128
}

app/src/main/java/com/smarttoolfactory/composecropper/preferences/frames/list/CropFrameListDialog.kt

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.*
1212
import androidx.compose.foundation.lazy.grid.GridCells
1313
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
1414
import androidx.compose.foundation.lazy.grid.itemsIndexed
15+
import androidx.compose.foundation.shape.CircleShape
1516
import androidx.compose.foundation.shape.RoundedCornerShape
1617
import androidx.compose.material.icons.Icons
1718
import androidx.compose.material.icons.filled.Add
@@ -21,6 +22,7 @@ import androidx.compose.material3.*
2122
import androidx.compose.runtime.*
2223
import androidx.compose.ui.Alignment
2324
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.draw.clip
2426
import androidx.compose.ui.draw.drawWithCache
2527
import androidx.compose.ui.draw.shadow
2628
import androidx.compose.ui.graphics.*
@@ -33,8 +35,8 @@ import androidx.compose.ui.unit.dp
3335
import androidx.compose.ui.unit.sp
3436
import com.google.modernstorage.photopicker.PhotoPicker
3537
import com.smarttoolfactory.composecropper.preferences.frames.edit.CropFrameEditDialog
36-
import com.smarttoolfactory.cropper.model.*
3738
import com.smarttoolfactory.composecropper.preferences.frames.edit.CropShapeAddDialog
39+
import com.smarttoolfactory.cropper.model.*
3840
import com.smarttoolfactory.cropper.util.buildOutline
3941
import com.smarttoolfactory.cropper.util.scaleAndTranslatePath
4042

@@ -45,7 +47,8 @@ import com.smarttoolfactory.cropper.util.scaleAndTranslatePath
4547
fun CropFrameListDialog(
4648
aspectRatio: AspectRatio,
4749
cropFrame: CropFrame,
48-
onDismiss: (CropFrame) -> Unit
50+
onDismiss: () -> Unit,
51+
onConfirm: (CropFrame) -> Unit
4952
) {
5053
var updatedCropFrame by remember {
5154
mutableStateOf(cropFrame)
@@ -115,79 +118,117 @@ fun CropFrameListDialog(
115118
outlines = newOutlines
116119
)
117120
)
121+
122+
selectedIndex = updatedCropFrame.selectedIndex
118123
}
119124
}
120125
}
121126

122127
AlertDialog(
123-
onDismissRequest = { onDismiss(updatedCropFrame) },
128+
onDismissRequest = {
129+
onDismiss()
130+
},
131+
title = {
132+
Row(
133+
modifier = Modifier.fillMaxWidth(),
134+
verticalAlignment = Alignment.CenterVertically
135+
) {
136+
Text(
137+
text = "Frames",
138+
fontSize = 24.sp,
139+
fontWeight = FontWeight.Bold,
140+
color = MaterialTheme.colorScheme.primary
141+
)
142+
Spacer(modifier = Modifier.weight(1f))
143+
144+
val enabled = selectedIndex != 0
145+
146+
Icon(
147+
modifier = Modifier
148+
.clip(CircleShape)
149+
.background(
150+
if (enabled) MaterialTheme.colorScheme.error
151+
else Color.LightGray
152+
)
153+
.size(28.dp)
154+
.clickable(
155+
enabled = enabled,
156+
onClick = {
157+
val outlines = updatedCropFrame.outlines
158+
.toMutableList()
159+
.apply {
160+
removeAt(selectedIndex)
161+
}
162+
updatedCropFrame = updatedCropFrame.copy(
163+
cropOutlineContainer = getOutlineContainer(
164+
updatedCropFrame.outlineType,
165+
outlines.size - 1,
166+
outlines
167+
)
168+
)
169+
170+
selectedIndex = outlines.size - 1
171+
}
172+
)
173+
.padding(6.dp),
174+
175+
imageVector = Icons.Default.Delete,
176+
tint = if (enabled) Color.White else Color.Gray,
177+
contentDescription = "Delete"
178+
)
179+
180+
Spacer(modifier = Modifier.width(12.dp))
181+
Icon(
182+
modifier = Modifier
183+
.clip(CircleShape)
184+
.background(MaterialTheme.colorScheme.primary)
185+
.size(28.dp)
186+
.clickable {
187+
showEditDialog = true
188+
}
189+
.padding(6.dp),
190+
imageVector = Icons.Default.Edit,
191+
tint = Color.White,
192+
contentDescription = "Edit"
193+
)
194+
}
195+
},
124196
text = {
125197
CropOutlineGridList(
126198
modifier = Modifier
127199
.fillMaxWidth()
128-
.heightIn(min = 280.dp),
200+
.heightIn(min = 240.dp),
129201
selectedIndex = selectedIndex,
130202
outlineType = updatedCropFrame.outlineType,
131203
outlines = updatedCropFrame.outlines,
132204
aspectRatio = aspectRatio,
133205
onItemClick = {
134-
135206
selectedIndex = it
136207
updatedCropFrame.selectedIndex = selectedIndex
137-
138-
println("Update cropFrame with index: $it, crop index: ${updatedCropFrame.selectedIndex}")
139208
},
140209
onAddItemClick = {
141210
showAddDialog = true
142211
}
143212
)
144213
},
145214
dismissButton = {
146-
FilledTonalButton(
147-
enabled = selectedIndex != 0,
215+
TextButton(
148216
onClick = {
149-
val outlines = updatedCropFrame.outlines
150-
.toMutableList()
151-
.apply {
152-
removeAt(selectedIndex)
153-
}
154-
updatedCropFrame = updatedCropFrame.copy(
155-
cropOutlineContainer = getOutlineContainer(
156-
updatedCropFrame.outlineType,
157-
outlines.size - 1,
158-
outlines
159-
)
160-
)
161-
162-
selectedIndex = outlines.size - 1
163-
},
164-
colors = ButtonDefaults.filledTonalButtonColors(
165-
containerColor = MaterialTheme.colorScheme.error,
166-
contentColor = MaterialTheme.colorScheme.onError
167-
)
168-
217+
onDismiss()
218+
}
169219
) {
170-
Icon(
171-
imageVector = Icons.Default.Delete,
172-
contentDescription = "Delete"
173-
)
174-
Text("Delete")
220+
221+
Text("Cancel")
175222
}
176223
},
177224
confirmButton = {
178-
if (outlineType != OutlineType.ImageMask) {
179-
Button(
225+
TextButton(
180226
onClick = {
181-
showEditDialog = true
227+
onConfirm(updatedCropFrame)
182228
}
183229
) {
184-
Icon(
185-
imageVector = Icons.Default.Edit,
186-
contentDescription = "Edit"
187-
)
188-
Text("Edit")
230+
Text("Accept")
189231
}
190-
}
191232
}
192233
)
193234
}
@@ -296,7 +337,6 @@ private fun CropOutlineGridItem(
296337
.aspectRatio(1f),
297338
cropOutline = cropOutline,
298339
aspectRatio,
299-
selected,
300340
color
301341
)
302342

@@ -305,13 +345,13 @@ private fun CropOutlineGridItem(
305345
modifier = Modifier
306346
.align(Alignment.BottomStart)
307347
.fillMaxWidth()
308-
.background(Color.White.copy(.2f))
309-
.padding(horizontal = 5.dp, vertical = 4.dp),
348+
.background(MaterialTheme.colorScheme.primaryContainer.copy(alpha = .7f))
349+
.padding(horizontal = 8.dp, vertical = 6.dp),
310350
contentAlignment = Alignment.Center
311351
) {
312352
Text(
313353
text = cropOutline.title,
314-
color = color,
354+
color = MaterialTheme.colorScheme.onPrimaryContainer,
315355
fontSize = 12.sp,
316356
maxLines = 1,
317357
fontWeight = FontWeight.Bold,
@@ -326,7 +366,6 @@ private fun CropOutlineDisplay(
326366
modifier: Modifier,
327367
cropOutline: CropOutline,
328368
aspectRatio: AspectRatio,
329-
selected: Boolean,
330369
color: Color
331370
) {
332371

@@ -348,8 +387,8 @@ private fun CropOutlineDisplay(
348387
.drawWithCache {
349388
val coefficient = .8f
350389

351-
val (left, top, outline) = buildOutline(
352-
AspectRatio(1f),
390+
val (offset, outline) = buildOutline(
391+
aspectRatio,
353392
coefficient,
354393
cropOutline.shape,
355394
size,
@@ -359,8 +398,8 @@ private fun CropOutlineDisplay(
359398

360399
onDrawWithContent {
361400
translate(
362-
left = left,
363-
top = top
401+
left = offset.x,
402+
top = offset.y
364403
) {
365404
drawOutline(
366405
outline = outline,
@@ -387,11 +426,14 @@ private fun CropOutlineDisplay(
387426
onDrawWithContent {
388427
drawPath(path, color)
389428
}
390-
})
429+
}
430+
)
391431
}
392432
is CropImageMask -> {
393433
Box(
394-
modifier = Modifier.matchParentSize(),
434+
modifier = Modifier
435+
.matchParentSize()
436+
.padding(4.dp),
395437
contentAlignment = Alignment.Center
396438
) {
397439
Image(bitmap = cropOutline.image, contentDescription = "ImageMask")

0 commit comments

Comments
 (0)