Skip to content

Commit c4ef5c6

Browse files
move crop edits to app module
1 parent 30b3da1 commit c4ef5c6

File tree

10 files changed

+123
-42
lines changed

10 files changed

+123
-42
lines changed

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

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

54-
val cropFrameFactory = remember { CropFrameFactory() }
54+
val defaultImage = ImageBitmap.imageResource(id = R.drawable.squircle)
55+
56+
val cropFrameFactory = remember { CropFrameFactory(defaultImage) }
5557

5658
var cropProperties by remember {
5759
mutableStateOf(
@@ -148,7 +150,9 @@ private fun MainContent(
148150
Column(modifier = Modifier.fillMaxSize()) {
149151

150152
ImageCropper(
151-
modifier = Modifier.fillMaxWidth().weight(1f),
153+
modifier = Modifier
154+
.fillMaxWidth()
155+
.weight(1f),
152156
imageBitmap = imageBitmap,
153157
contentDescription = "Image Cropper",
154158
cropStyle = cropStyle,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.smarttoolfactory.composecropper.preferences
22

3+
import CropFrameListDialog
34
import androidx.compose.foundation.layout.fillMaxWidth
45
import androidx.compose.foundation.layout.padding
56
import androidx.compose.foundation.layout.width
@@ -14,7 +15,6 @@ import com.smarttoolfactory.cropper.model.CropFrame
1415
import com.smarttoolfactory.cropper.model.OutlineType
1516
import com.smarttoolfactory.cropper.settings.CropFrameFactory
1617
import com.smarttoolfactory.cropper.settings.CropOutlineProperty
17-
import com.smarttoolfactory.cropper.settings.frames.edit.CropFrameListDialog
1818
import com.smarttoolfactory.cropper.widget.CropFrameDisplayCard
1919

2020
/**
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.material3.AlertDialog
44
import androidx.compose.material3.Button

cropper/src/main/java/com/smarttoolfactory/cropper/settings/frames/edit/CropFrameAddDialog.kt renamed to app/src/main/java/com/smarttoolfactory/composecropper/preferences/frames/edit/CropShapeAddDialog.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.material3.AlertDialog
44
import androidx.compose.material3.Button
@@ -10,7 +10,7 @@ import com.smarttoolfactory.cropper.R
1010
import com.smarttoolfactory.cropper.model.*
1111

1212
@Composable
13-
fun CropFrameAddDialog(
13+
fun CropShapeAddDialog(
1414
aspectRatio: AspectRatio,
1515
cropFrame: CropFrame,
1616
onConfirm: (CropFrame) -> Unit,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.foundation.layout.*
44
import androidx.compose.foundation.shape.CutCornerShape

cropper/src/main/java/com/smarttoolfactory/cropper/settings/frames/edit/OvalCropShapeEdit.kt renamed to app/src/main/java/com/smarttoolfactory/composecropper/preferences/frames/edit/OvalCropShapeEdit.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.foundation.layout.*
44
import androidx.compose.foundation.shape.GenericShape
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.foundation.layout.*
44
import androidx.compose.material3.ExperimentalMaterial3Api
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
1+
package com.smarttoolfactory.composecropper.preferences.frames.edit
22

33
import androidx.compose.foundation.layout.*
44
import androidx.compose.foundation.shape.RoundedCornerShape
Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
package com.smarttoolfactory.cropper.settings.frames.edit
2-
1+
import android.annotation.SuppressLint
2+
import android.graphics.Bitmap
3+
import android.graphics.ImageDecoder
4+
import android.os.Build
5+
import android.provider.MediaStore
6+
import androidx.activity.compose.rememberLauncherForActivityResult
37
import androidx.compose.foundation.Image
48
import androidx.compose.foundation.background
59
import androidx.compose.foundation.border
@@ -19,16 +23,18 @@ import androidx.compose.ui.Alignment
1923
import androidx.compose.ui.Modifier
2024
import androidx.compose.ui.draw.drawWithCache
2125
import androidx.compose.ui.draw.shadow
22-
import androidx.compose.ui.graphics.Color
23-
import androidx.compose.ui.graphics.Path
24-
import androidx.compose.ui.graphics.drawOutline
26+
import androidx.compose.ui.graphics.*
2527
import androidx.compose.ui.graphics.drawscope.translate
28+
import androidx.compose.ui.platform.LocalContext
2629
import androidx.compose.ui.platform.LocalDensity
2730
import androidx.compose.ui.text.font.FontWeight
2831
import androidx.compose.ui.text.style.TextOverflow
2932
import androidx.compose.ui.unit.dp
3033
import androidx.compose.ui.unit.sp
34+
import com.google.modernstorage.photopicker.PhotoPicker
35+
import com.smarttoolfactory.composecropper.preferences.frames.edit.CropFrameEditDialog
3136
import com.smarttoolfactory.cropper.model.*
37+
import com.smarttoolfactory.composecropper.preferences.frames.edit.CropShapeAddDialog
3238
import com.smarttoolfactory.cropper.util.buildOutline
3339
import com.smarttoolfactory.cropper.util.scaleAndTranslatePath
3440

@@ -49,9 +55,12 @@ fun CropFrameListDialog(
4955
mutableStateOf(updatedCropFrame.selectedIndex)
5056
}
5157

58+
val outlineType = cropFrame.outlineType
59+
5260
var showEditDialog by remember { mutableStateOf(false) }
5361
var showAddDialog by remember { mutableStateOf(false) }
5462

63+
5564
if (showEditDialog) {
5665
CropFrameEditDialog(
5766
aspectRatio = aspectRatio,
@@ -69,18 +78,45 @@ fun CropFrameListDialog(
6978
}
7079

7180
if (showAddDialog) {
72-
CropFrameAddDialog(
73-
aspectRatio = aspectRatio,
74-
cropFrame = updatedCropFrame.copy(),
75-
onConfirm = {
76-
updatedCropFrame = it
77-
selectedIndex = updatedCropFrame.selectedIndex
78-
showAddDialog = false
79-
},
80-
onDismiss = {
81-
showAddDialog = false
81+
82+
val outline = updatedCropFrame.cropOutlineContainer.selectedItem
83+
if (outline is CropShape) {
84+
CropShapeAddDialog(
85+
aspectRatio = aspectRatio,
86+
cropFrame = updatedCropFrame.copy(),
87+
onConfirm = {
88+
updatedCropFrame = it
89+
selectedIndex = updatedCropFrame.selectedIndex
90+
showAddDialog = false
91+
},
92+
onDismiss = {
93+
showAddDialog = false
94+
}
95+
)
96+
} else if (outline is CropImageMask) {
97+
98+
PickImageMask {
99+
100+
val id = updatedCropFrame.outlineCount
101+
val newOutline =
102+
ImageMaskOutline(id = updatedCropFrame.outlineCount, "ImageMask $id", it)
103+
104+
val newOutlines: List<CropOutline> = cropFrame.outlines
105+
.toMutableList()
106+
.apply {
107+
add(newOutline)
108+
}
109+
.toList()
110+
111+
updatedCropFrame = cropFrame.copy(
112+
cropOutlineContainer = getOutlineContainer(
113+
outlineType = outlineType,
114+
index = newOutlines.size - 1,
115+
outlines = newOutlines
116+
)
117+
)
82118
}
83-
)
119+
}
84120
}
85121

86122
AlertDialog(
@@ -91,6 +127,7 @@ fun CropFrameListDialog(
91127
.fillMaxWidth()
92128
.heightIn(min = 280.dp),
93129
selectedIndex = selectedIndex,
130+
outlineType = updatedCropFrame.outlineType,
94131
outlines = updatedCropFrame.outlines,
95132
aspectRatio = aspectRatio,
96133
onItemClick = {
@@ -138,16 +175,18 @@ fun CropFrameListDialog(
138175
}
139176
},
140177
confirmButton = {
141-
Button(
142-
onClick = {
143-
showEditDialog = true
178+
if (outlineType != OutlineType.ImageMask) {
179+
Button(
180+
onClick = {
181+
showEditDialog = true
182+
}
183+
) {
184+
Icon(
185+
imageVector = Icons.Default.Edit,
186+
contentDescription = "Edit"
187+
)
188+
Text("Edit")
144189
}
145-
) {
146-
Icon(
147-
imageVector = Icons.Default.Edit,
148-
contentDescription = "Edit"
149-
)
150-
Text("Edit")
151190
}
152191
}
153192
)
@@ -157,6 +196,7 @@ fun CropFrameListDialog(
157196
private fun CropOutlineGridList(
158197
modifier: Modifier = Modifier,
159198
selectedIndex: Int,
199+
outlineType: OutlineType,
160200
outlines: List<CropOutline>,
161201
aspectRatio: AspectRatio,
162202
onItemClick: (Int) -> Unit,
@@ -189,13 +229,15 @@ private fun CropOutlineGridList(
189229
}
190230
}
191231

192-
item {
193-
AddItemButton(
194-
Modifier
195-
.fillMaxWidth()
196-
.aspectRatio(3 / 4f)
197-
) {
198-
onAddItemClick()
232+
if (outlineType != OutlineType.Custom) {
233+
item {
234+
AddItemButton(
235+
Modifier
236+
.fillMaxWidth()
237+
.aspectRatio(1f)
238+
) {
239+
onAddItemClick()
240+
}
199241
}
200242
}
201243
}
@@ -358,3 +400,33 @@ private fun CropOutlineDisplay(
358400
}
359401
}
360402
}
403+
404+
@SuppressLint("UnsafeOptInUsageError")
405+
@Composable
406+
private fun PickImageMask(
407+
onImageSelected: (ImageBitmap) -> Unit
408+
409+
) {
410+
val context = LocalContext.current
411+
412+
val photoPicker = rememberLauncherForActivityResult(PhotoPicker()) { uris ->
413+
val uri = uris.firstOrNull() ?: return@rememberLauncherForActivityResult
414+
415+
val bitmap: Bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
416+
ImageDecoder.decodeBitmap(
417+
ImageDecoder.createSource(context.contentResolver, uri)
418+
) { decoder, info, source ->
419+
decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
420+
decoder.isMutableRequired = true
421+
}
422+
} else {
423+
MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
424+
}
425+
426+
onImageSelected(bitmap.asImageBitmap())
427+
}
428+
429+
LaunchedEffect(key1 = Unit) {
430+
photoPicker.launch(PhotoPicker.Args(PhotoPicker.Type.IMAGES_ONLY, 1))
431+
}
432+
}

cropper/src/main/java/com/smarttoolfactory/cropper/model/CropFrame.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ data class CropFrame(
2222

2323
val outlineCount: Int
2424
get() = cropOutlineContainer.size
25+
26+
fun addOutline(outline: CropOutline): CropFrame {
27+
28+
return this
29+
}
2530
}
2631

2732
@Suppress("UNCHECKED_CAST")

0 commit comments

Comments
 (0)