Skip to content

Commit

Permalink
Fancy drag and drop WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
alexvanyo committed Dec 26, 2024
1 parent 2c30606 commit 3bb26e5
Show file tree
Hide file tree
Showing 18 changed files with 916 additions and 697 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import com.alexvanyo.composelife.logging.e

fun Application.initStrictModeIfNeeded() {
if (isDebuggable) {
//initStrictMode()
initStrictMode()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class LoadedCellStatePreviewTests : BaseUiInjectTest<TestComposeLifeApplicationC
Spacer(
modifier = Modifier
.testTag("TestDropTarget")
.cellStateDragAndDropTarget {
droppedCellState = it
.cellStateDragAndDropTarget { _, cellState ->
droppedCellState = cellState
}
.size(100.dp)
.background(Color.Blue),
Expand Down Expand Up @@ -141,8 +141,8 @@ class LoadedCellStatePreviewTests : BaseUiInjectTest<TestComposeLifeApplicationC
downTime,
SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE,
testDropTargetCenter.x.toFloat(),
testDropTargetCenter.y.toFloat(),
testDropTargetCenter.x,
testDropTargetCenter.y,
0,
).apply {
source = InputDevice.SOURCE_TOUCHSCREEN
Expand All @@ -154,8 +154,8 @@ class LoadedCellStatePreviewTests : BaseUiInjectTest<TestComposeLifeApplicationC
downTime,
SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP,
testDropTargetCenter.x.toFloat(),
testDropTargetCenter.y.toFloat(),
testDropTargetCenter.x,
testDropTargetCenter.y,
0,
).apply {
source = InputDevice.SOURCE_TOUCHSCREEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import androidx.compose.ui.draganddrop.mimeTypes
import androidx.compose.ui.draganddrop.toAndroidDragEvent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionOnScreen
import androidx.compose.ui.layout.positionInWindow
import com.alexvanyo.composelife.logging.Logger
import com.alexvanyo.composelife.logging.d
import com.alexvanyo.composelife.model.CellState
Expand Down Expand Up @@ -75,17 +75,17 @@ actual fun Modifier.cellStateDragAndDropSource(

context(CellStateParserProvider)
@Composable
@Suppress("ComposeComposableModifier")
@Suppress("ComposeComposableModifier", "LongMethod", "CyclomaticComplexMethod")
actual fun Modifier.cellStateDragAndDropTarget(
mutableCellStateDropStateHolder: MutableCellStateDropStateHolder,
setSelectionToCellState: (Offset, CellState) -> Unit,
setSelectionToCellState: (dropOffset: Offset, cellState: CellState) -> Unit,
): Modifier {
val coroutineScope = rememberCoroutineScope()
val dragAndDropEvents = remember { Channel<CellStateDragAndDropEvent>(Channel.UNLIMITED) }

val currentSetSelectionToCellState by rememberUpdatedState(setSelectionToCellState)

var positionOnScreen by remember {
var positionInWindow by remember {
mutableStateOf(Offset.Zero)
}

Expand Down Expand Up @@ -128,7 +128,7 @@ actual fun Modifier.cellStateDragAndDropTarget(
is DeserializationResult.Successful -> {
currentSetSelectionToCellState(
offset,
deserializationResult.cellState
deserializationResult.cellState,

Check warning on line 131 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L129-L131

Added lines #L129 - L131 were not covered by tests
)
}
is DeserializationResult.Unsuccessful -> {
Expand Down Expand Up @@ -184,8 +184,8 @@ actual fun Modifier.cellStateDragAndDropTarget(
override fun onStarted(event: DragAndDropEvent) {
dragAndDropEvents.trySend(
CellStateDragAndDropEvent.Started(

Check warning on line 186 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L185-L186

Added lines #L185 - L186 were not covered by tests
clipData = event.toAndroidDragEvent().clipData ?:
event.toAndroidDragEvent().localState as? ClipData,
clipData = event.toAndroidDragEvent().clipData
?: event.toAndroidDragEvent().localState as? ClipData,
),
)
}

Check warning on line 191 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L191

Added line #L191 was not covered by tests
Expand All @@ -194,12 +194,12 @@ actual fun Modifier.cellStateDragAndDropTarget(
val androidDragEvent = event.toAndroidDragEvent()
dragAndDropEvents.trySend(
CellStateDragAndDropEvent.Entered(

Check warning on line 196 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L194-L196

Added lines #L194 - L196 were not covered by tests
clipData = event.toAndroidDragEvent().clipData ?:
event.toAndroidDragEvent().localState as? ClipData,
clipData = event.toAndroidDragEvent().clipData
?: event.toAndroidDragEvent().localState as? ClipData,
offset = Offset(
androidDragEvent.x,
androidDragEvent.y,
) - positionOnScreen,
) - positionInWindow,

Check warning on line 202 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L199-L202

Added lines #L199 - L202 were not covered by tests
),
)
}

Check warning on line 205 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L205

Added line #L205 was not covered by tests
Expand All @@ -208,30 +208,30 @@ actual fun Modifier.cellStateDragAndDropTarget(
val androidDragEvent = event.toAndroidDragEvent()
dragAndDropEvents.trySend(
CellStateDragAndDropEvent.Moved(

Check warning on line 210 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L208-L210

Added lines #L208 - L210 were not covered by tests
clipData = event.toAndroidDragEvent().clipData ?:
event.toAndroidDragEvent().localState as? ClipData,
clipData = event.toAndroidDragEvent().clipData
?: event.toAndroidDragEvent().localState as? ClipData,
offset = Offset(
androidDragEvent.x,
androidDragEvent.y,
) - positionOnScreen,
) - positionInWindow,

Check warning on line 216 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L213-L216

Added lines #L213 - L216 were not covered by tests
),
)
}

Check warning on line 219 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L219

Added line #L219 was not covered by tests

override fun onExited(event: DragAndDropEvent) {
dragAndDropEvents.trySend(
CellStateDragAndDropEvent.Exited(

Check warning on line 223 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L222-L223

Added lines #L222 - L223 were not covered by tests
clipData = event.toAndroidDragEvent().clipData ?:
event.toAndroidDragEvent().localState as? ClipData,
clipData = event.toAndroidDragEvent().clipData
?: event.toAndroidDragEvent().localState as? ClipData,
),
)
}

Check warning on line 228 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L228

Added line #L228 was not covered by tests

override fun onEnded(event: DragAndDropEvent) {
dragAndDropEvents.trySend(
CellStateDragAndDropEvent.Ended(

Check warning on line 232 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L231-L232

Added lines #L231 - L232 were not covered by tests
clipData = event.toAndroidDragEvent().clipData ?:
event.toAndroidDragEvent().localState as? ClipData,
clipData = event.toAndroidDragEvent().clipData
?: event.toAndroidDragEvent().localState as? ClipData,
),
)
}

Check warning on line 237 in ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/androidMain/kotlin/com/alexvanyo/composelife/ui/cells/CellStateDragAndDrop.android.kt#L237

Added line #L237 was not covered by tests
Expand All @@ -248,7 +248,7 @@ actual fun Modifier.cellStateDragAndDropTarget(
}

return onGloballyPositioned { coordinates ->
positionOnScreen = coordinates.positionOnScreen()
positionInWindow = coordinates.positionInWindow()
}
.dragAndDropTarget(
shouldStartDragAndDrop = { event ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ expect fun Modifier.cellStateDragAndDropSource(getCellState: () -> CellState): M
*/
context(CellStateParserProvider)
@Composable
@Suppress("ComposeComposableModifier")
expect fun Modifier.cellStateDragAndDropTarget(
mutableCellStateDropStateHolder: MutableCellStateDropStateHolder = rememberMutableCellStateDropStateHolder(),
setSelectionToCellState: (dropOffset: Offset, cellState: CellState) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ fun rememberMutableCellStateDropStateHolder(): MutableCellStateDropStateHolder {
set(value) {
cellStateDropState = value
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ private fun CellWindowImpl(
scaledCellDpSize = scaledCellDpSize,
cellWindow = cellWindow,
pixelOffsetFromCenter = fracPixelOffsetFromCenter,
modifier = Modifier
modifier = Modifier,

)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alexvanyo.composelife.ui.cells

import androidx.annotation.FloatRange
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.toRect
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke

/**
* Draws a dashed line rectangle, with intervals and phase applied symmetrically.
*
* The dashed line effect is drawn in 8 line segments: from the middle of each side,
* to each corner.
*/
internal fun DrawScope.drawDashedRect(

Check warning on line 36 in ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt#L36

Added line #L36 was not covered by tests
selectionColor: Color,
strokeWidth: Float,
intervals: FloatArray,
phase: Float = 0f,
rect: Rect = size.toRect(),

Check warning on line 41 in ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt#L40-L41

Added lines #L40 - L41 were not covered by tests
) {
// Draw the selection outlines in a way that is symmetric, and hides the extra of the lines near the
// corners with the selection handles
listOf(
rect.topCenter to rect.topLeft,
rect.topCenter to rect.topRight,
rect.centerLeft to rect.topLeft,
rect.centerLeft to rect.bottomLeft,
rect.bottomCenter to rect.bottomLeft,
rect.bottomCenter to rect.bottomRight,
rect.centerRight to rect.topRight,
rect.centerRight to rect.bottomRight,
).forEach { (start, end) ->
drawDashedLine(
color = selectionColor,
start = start,
end = end,
strokeWidth = strokeWidth,
intervals = intervals,
phase = phase,

Check warning on line 61 in ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt#L45-L61

Added lines #L45 - L61 were not covered by tests
)
}
}

Check warning on line 64 in ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt

View check run for this annotation

Codecov / codecov/patch

ui-cells/src/jbMain/kotlin/com/alexvanyo/composelife/ui/cells/DashedDrawing.kt#L63-L64

Added lines #L63 - L64 were not covered by tests

@Suppress("LongParameterList")
internal expect fun DrawScope.drawDashedLine(
color: Color,
start: Offset,
end: Offset,
intervals: FloatArray,
phase: Float = 0f,
strokeWidth: Float = Stroke.HairlineWidth,
cap: StrokeCap = Stroke.DefaultCap,
@FloatRange(from = 0.0, to = 1.0) alpha: Float = 1.0f,
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DrawScope.DefaultBlendMode,
)
Loading

0 comments on commit 3bb26e5

Please sign in to comment.