compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

Will support drag and drop file into widget?

Open gtf35 opened this issue 4 years ago • 22 comments

Will compose support drag and drop file into widget? Sometimes useful,for example, drag and drop an apk to the window to install it to phone.😉

gtf35 avatar Dec 27 '20 13:12 gtf35

https://github.com/JetBrains/compose-jb/issues/176

Dominaezzz avatar Dec 27 '20 13:12 Dominaezzz

Thanks,but it will open a dialog. I mean we can drag and drop files directly from the Explorer to the window。🤔

gtf35 avatar Dec 27 '20 13:12 gtf35

Oh sorry. Compose itself won't support that. You can register for drap and drop events with DropTargetListener on AppWindowAmbient.current.

Dominaezzz avatar Dec 27 '20 13:12 Dominaezzz

Here's a more concrete example https://twitter.com/tkuenneth/status/1331993022955917312?s=20 .

EDIT: https://dev.to/tkuenneth/from-swing-to-jetpack-compose-desktop-2-4a4h

Dominaezzz avatar Dec 27 '20 13:12 Dominaezzz

🤔 It is based on the window. If I want to trigger in a specific area, I guess, this way could not be possible

By the way, thanks again

gtf35 avatar Dec 27 '20 14:12 gtf35

This link looks like what I want, thank you so much

gtf35 avatar Dec 27 '20 14:12 gtf35

There isn't an immediately obvious way to limit it to a specific area. I think it's worth leaving this issue open.

Dominaezzz avatar Dec 27 '20 14:12 Dominaezzz

Maybe you can limit it with the new SwingPanel.

Dominaezzz avatar Dec 27 '20 14:12 Dominaezzz

Yeah, you are right. I only watch the video, he drop it in the widget, actually he doesnt limit it.

gtf35 avatar Dec 27 '20 14:12 gtf35

I thought about that idea, but in the latest「0.3.0-build136」 image

gtf35 avatar Dec 27 '20 14:12 gtf35

I think you need to use this version 0.0.0-unmerged-build21.

Dominaezzz avatar Dec 27 '20 14:12 Dominaezzz

Yeah, I see this version in issues, but I dont known how to find unmerged version.😉

by the way, this version ...
But this is another issues image

gtf35 avatar Dec 27 '20 14:12 gtf35

You have to update the version in build.gradle

Dominaezzz avatar Dec 27 '20 14:12 Dominaezzz

Yes, you are right🙌 Thanks a looooot

gtf35 avatar Dec 27 '20 15:12 gtf35

Guess we could close it, once SwingPanel support merged.

olonho avatar Jan 13 '21 10:01 olonho

But wouldn’t it be better to let compose-jb support it?

gtf35 avatar Jan 13 '21 10:01 gtf35

bump still no support for file drag and drop on a single element instead of the entire window?

illuminator3 avatar Apr 17 '21 20:04 illuminator3

You can also embed a androidx.compose.ui.awt.SwingPanel an have it accept drops, but that's also inconvenient to work with (and changes the style).

felixdivo avatar Aug 15 '21 11:08 felixdivo

@felixdivo Yeah, compatibility with Swing is not compose's own behavior

gtf35 avatar Aug 16 '21 05:08 gtf35

You can also embed a androidx.compose.ui.awt.SwingPanel an have it accept drops

That also does not work nicely due to #1062 and (very importantly!) #1202. I thought about putting a compose UI in the drop traget by nesting a ComposePanel in a SwingPanel, but that also does not work due to #1060 and #1061.

felixdivo avatar Oct 31 '21 00:10 felixdivo

You can do this with a custom modifier. Here's source for one here

Here's a desktop implementation.

And an Android implementation.

Here's a gif of both side by side

DnD

tunjid avatar Mar 18 '22 21:03 tunjid

I have a number of use cases for this:

  • Drag selected text from text views out into other apps
  • Drag text from other apps into text views
  • Drag images from other apps into text views
  • Drag images from other apps into specific drop areas (similar to what previous example showed)
  • Drag files from other apps (including file explorers) into specific drop areas
  • Drag things between two slots in the same app (probably possible without using real dnd)
  • Drag nodes from my app out into files

hakanai avatar Aug 27 '22 01:08 hakanai

Hello everyone, thank you for your request and use cases! Experimental drag and drop functionality for desktop has been merged and will be available in the next dev builds. It allows moving files/images/text inside your Compose desktop application out of the box!

Walingar avatar Mar 13 '23 16:03 Walingar

@Walingar this is great news! Is it available in 1.4.0?

mgroth0 avatar Apr 29 '23 22:04 mgroth0

Sample code for a text field receiving dropped text replacing the selection, working in desktop on v1.4.0.

Still missing the equivalent behaviour in the other direction.

var isDroppable by remember { mutableStateOf(false) }
val (textFieldValue, setTextFieldValue) = remember { mutableStateOf(TextFieldValue()) }

TextField(
    value = textFieldValue,
    onValueChange = setTextFieldValue,
    modifier = Modifier
        .border(4.dp, if (isDroppable) Color.Green else Color.Red)
        .onExternalDrag(
            onDragStart = { externalDragValue ->
                isDroppable = externalDragValue.dragData is androidx.compose.ui.DragData.Text
            },
        onDragExit = {
            isDroppable = false
        },
        onDrop = { externalDragValue ->
            isDroppable = false
            val dragData = externalDragValue.dragData
            if (dragData is androidx.compose.ui.DragData.Text) {
                setTextFieldValue(textFieldValue.copy(
                    text = textFieldValue.text.substring(0, textFieldValue.selection.start) +
                        dragData.readText() +
                        textFieldValue.text.substring(textFieldValue.selection.end),
                    selection = TextRange(textFieldValue.selection.end)
                ))
            }
        },
    )
)

hakanai avatar Apr 30 '23 11:04 hakanai

It works perfectly! Thanks @hakanai

mgroth0 avatar Apr 30 '23 16:04 mgroth0

@hakanai thank you for your example! Indeed, it is available in 1.4.0 as an experimental feature. So, please try it out and provide us feedback!

Also, @hakanai can you please describe your use case for DnD from Compose app. I will be glad if you can create a separate issue for that and describe it there!

Walingar avatar May 01 '23 13:05 Walingar

What if I want to drop an image and send it somewhere as a file? How can I transform a Painter object to a file object?

`.onExternalDrag( onDragStart = { isDroppable = true }, onDragExit = { isDroppable = false }, onDrop = { externalDragValue -> isDroppable = false val dragData = externalDragValue.dragData if (dragData is androidx.compose.ui.DragData.Image) { val img = dragData.readImage()

        }
    }
)`

June6-android avatar May 24 '23 06:05 June6-android

@June6-android You can try this code:

fun savePainterToFile(painter: Painter, file: File) {
    val image: Image = painter.toAwtImage(Density(1f), LayoutDirection.Ltr)
    val bufferedImage = BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB)
    bufferedImage.graphics.drawImage(image, 0, 0, null);
    ImageIO.write(bufferedImage, "png", file)
}

dima-avdeev-jb avatar May 25 '23 11:05 dima-avdeev-jb

Currently im trying to disable/enable drag and drop for a widget using this modifier, but on runtime the component never gets recomposed to check for the drag data type Is there any better way to do this? kotlin var isDroppable by remember { mutableStateOf(false) } val dragModifier: Modifier = Modifier.onExternalDrag ( enabled = isDroppable, onDragStart = { val data = it.dragData isDroppable = data is DragData.FilesList } )

SinaMegapolis avatar May 30 '23 07:05 SinaMegapolis