Class

DragItem


Description

Used to transfer data being dragged by the user via drag and drop.

Methods

Name

Parameters

Returns

Shared

AddItem

Left As Integer, Top As Integer, Width As Integer, Height As Integer

Constructor

ctl As DesktopUIControl, x As Integer, y As Integer, width As Integer, height As Integer, [DragPicture As Picture]

Constructor

w As DesktopWindow, x As Integer, y As Integer, width As Integer, height As Integer, [DragPicture As Picture]

Drag

MoveFirst

NextItem

Boolean

Enumerations

DragItem.Types

Types

Specifies the type of drag the user is making.

Enumeration

Description

Default

Default action.

Copy

Copy the dragged item.

Move

Move the dragged item.

Link

Link the dragged item.

Property descriptions


DragItem.Destination

Destination As Object

The location of the dropped item when you drop it to the desktop or onto an application. The DragItem must contain some content that the Finder accepts.

This property is read-only.

Since Destination is of type Object, it potentially can return any type of Xojo object. Currently, Destination is set up to work only with the macOS Finder and will only return a FolderItem. To ensure that your application is compatible with future versions, check the type of object it returns with IsA before recasting it to a FolderItem.

On Windows and Linux, dragging items to the Desktop is not supported; therefore this property does not work on those platforms.

This code uses the Destination property to report the NativePath of a folder that is created by dragging a label from a window to the Finder:

Var di As DragItem
Var f As FolderItem
Var d As DateTime = DateTime.Now
Var tos As TextOutputStream

f = SpecialFolder.Temporary.Child("test" + Format(d.TotalSeconds, "#"))
If f <> Nil Then
  tos = TextOutputStream.Create(f)
  tos.Write("Howdy! Created by DragToFinder example.")
  tos.Close

  di = New DragItem(Self, 0, 0, 100, 100)
  di.FolderItem = f
  di.Drag
  If di.Destination <> Nil Then
    If di.Destination IsA FolderItem Then
      MessageBox(FolderItem(di.Destination).NativePath)
    End If
  End If
Else
  MessageBox("Unable to get FolderItem for temporary file.")
End If

DragItem.DragPicture

DragPicture As Picture

If you assign an image to this property, the picture will be used for the drag instead of the default rectangle. The image will be placed at the top left of the rectangle passed into the DragItem constructor.

It is only possible to change the DragPicture before calling Drag(), any attempt to do so after that point will fail.

This code sets the DragPicture property just after creating the new DragItem.

In an ImageViewer control, put this code in the MouseDown event:

Return True

You can then set up the drag in the MouseDrag event of the ImageViewer:

Var d As DragItem
d = New DragItem(Self, X, Y, Me.Width, Me.Height)
d.DragPicture = MyPicture ' a picture/image added to the project
d.Picture = Me.Image ' From the ImageViewer control
d.Drag ' Allow the drag

DragItem.DropHeight

DropHeight As Integer

Height of the object being dropped.

The following code displays the values of the DropWidth and DropHeight properties after the drag. The code is in the DropObject event.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable Then
  Me.Image = Picture.Open(obj.FolderItem)
End If
Label1.Text = obj.DropWidth.ToString
Label2.Text = obj.DropHeight.ToString

DragItem.DropLeft

DropLeft As Integer

Distance from the left side of the control where the object was dropped.

The following code displays the values of the DropLeft and DropTop properties after the drag. The code is in the DropObject event.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable Then
  Me.Image = Picture.Open(obj.FolderItem)
End If
Label1.Text = obj.DropLeft.ToString
Label2.Text = obj.DropTop.ToString

DragItem.DropTop

DropTop As Integer

Distance from the top of the control where the object was dropped.

The following code displays the values of the DropLeft and DropTop properties after the drag. The code is in the DropObject event.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable Then
  Me.Image = Picture.Open(obj.FolderItem)
End If
Label1.Text = obj.DropLeft.ToString
Label2.Text = obj.DropTop.ToString

DragItem.DropWidth

DropWidth As Integer

Width of the object being dropped.

The following code displays the values of the DropWidth and DropHeight properties after the drag. The code is in the DropObject event.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable Then
  Me.Image = Picture.Open(obj.FolderItem)
End If
Label1.Text = obj.DropWidth.ToString
Label2.Text = obj.DropHeight.ToString

DragItem.FolderItem

FolderItem As FolderItem

The FolderItem being dragged.

The following DropObject event specifies the passed FolderItem as the object to be dropped.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable Then
  Me.Image = Picture.Open(obj.FolderItem)
End If

DragItem.FolderItemAvailable

FolderItemAvailable As Boolean

If True, the FolderItem property contains a FolderItem.

This property is read-only.


DragItem.Handle

Handle As Integer

Returns the macOS handle to the DragItem. Handle returns 0 on Windows and Linux.

This property is read-only.

The following gets a handle to the DragItem.

d = New DragItem(Self, X, Y, Me.Width, Me.Height)
Var i As Integer = d.Handle

DragItem.MouseCursor

MouseCursor As MouseCursor

The cursor to be displayed during the drag.

The following code displays a custom cursor for the drag. It is in the MouseDown event of the DesktopImageViewer.

Var d As DragItem
d = New DragItem(Self, X, Y, Me.Width, Me.Height)

d.DragPicture = MyPicture
d.MouseCursor = System.Cursors.HandOpen
d.Picture = Me.Image
d.Drag ' Allow the drag

DragItem.Picture

Picture As Picture

The Picture being dragged.

The following code is in the DropObject event handler of an DesktopImageViewer. It assigns the dragged picture to the Image property of the DesktopImageViewer.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable then
  Me.Image = Picture.Open(obj.FolderItem)
End If

DragItem.PictureAvailable

PictureAvailable As Boolean

If True, the Picture property contains a picture.

This property is read-only.

The following code is in the DropObject event handler of an DesktopImageViewer. It tests whether a Picture has been dragged and, if so, assigns the dragged picture to the Image property of the DesktopImageViewer.

If obj.PictureAvailable Then
  Me.Image = obj.Picture
ElseIf obj.FolderItemAvailable then
  Me.Image = Picture.Open(obj.FolderItem)
End If

DragItem.PrivateRawData

PrivateRawData As String

Contains the raw data being dragged.

The parameter is the file type being dragged. MacType is a four-character resource type or programmer-defined four-character code. This data cannot be dragged to another application.

This code checks for raw data of any type and does the drop.

If obj.RawDataAvailable("????") Then
  Me.Text = obj.PrivateRawData("????")
End If

DragItem.RawData

RawData As String

Contains the raw data being dragged.

The DataType parameter supports both the older MacType and newer UTIs. If the DataType parameter is exactly 4 bytes then it is treated as a MacType for backwards compatibility. Otherwise it is treated as a UTI.

Checks if text data is in a a drag item:

If dragObject.RawDataAvailable("public.text") Then
  Me.Text = dragObject.RawData("public.text") ' UTI
End If

DragItem.RawDataAvailable

RawDataAvailable As Boolean

If True, the DragItem contains data of the type or UTI specified.

This property is read-only.

The DataType parameter supports both the older MacType and newer UTIs. If the DataType parameter is exactly 4 bytes then it is treated as a MacType for backwards compatibility. Otherwise it is treated as a UTI.

Checks if text data is in a a drag item:

If dragObject.RawDataAvailable("public.text") Then
  Me.Text = dragObject.RawData("public.text") ' UTI
End If

DragItem.Text

Text As String

The text being dragged.

The following DropObject event handler of a ListBox determines whether the dragged item has text; if it does, it creates a new row and assigns the dragged item's text property to the new row.

If obj.TextAvailable Then
  Me.AddRow(obj.Text)
End If

DragItem.TextAvailable

TextAvailable As Boolean

If True, the Text property contains text.

This property is read-only.

The object that is receiving dragged text needs to be capable of receiving the text. This is enabled by calling AcceptTextDrop in the Opening event. In the DropObject event, you can test the TextAvailable property prior to dropping the text. For example:

Do
  If obj.TextAvailable Then
    Me.AddRow(obj.Text)
  End If
Loop Until Not obj.NextItem

Method descriptions


DragItem.AddItem

AddItem(Left As Integer, Top As Integer, Width As Integer, Height As Integer)

Adds an item to the drag object. The parameters specify the drag rectangle to be displayed.

This allows you do add additional items to the drag. After calling AddItem, you assign new values to all the DragItem properties for the newly added item. When the item is dropped, the NextItem method can be called to iterate through all the items in the DragItem.

Add two pictures to a DragItem:

Var d As DragItem
d = New DragItem(Self, X, Y, Me.Width, Me.Height)

d.DragPicture = MyDragPic
d.MouseCursor = System.Cursors.HandOpen
d.Picture = MyFirstPic
d.AddItem(0, 0, Me.Width, Me.Height)
d.Picture = MySecondPic

d.Drag ' Allow the drag

DragItem.Constructor

Constructor(ctl As DesktopUIControl, x As Integer, y As Integer, width As Integer, height As Integer, [DragPicture As Picture])

Note

Constructors are special methods called when you create an object with the New keyword and pass in the parameters above.

Creates a new DragItem. The parameter ctl is the DesktopUIControl that the drag originates from. The parameters x and y are the coordinates relative to this control. The parameters width and height are the size/bounds of the drag rectangle. If the optional DragPicture parameter is passed, it will be used instead of the default rectangle to indicate the size and shape of the dragged item during the drag.


DragItem.Constructor

Constructor(w As DesktopWindow, x As Integer, y As Integer, width As Integer, height As Integer, [DragPicture As Picture])

Note

Constructors are special methods called when you create an object with the New keyword and pass in the parameters above.

Creates a new DragItem. The parameter w is the window that the drag originates from. The parameters x and y are the coordinates relative to this window. The parameters width and height are the size/bounds of the drag rectangle. If the optional DragPicture parameter is passed, it will be used instead of the default rectangle to indicate the size and shape of the dragged item during the drag.

The following code is from the example project "Custom Drag" in the Examples folder. The main window consists of a DesktopLabel control and a DesktopTextArea. The user can drag the text in the DesktopLabel into the DesktopTextArea. This is not possible by default but the ability to drag the text is enabled by the code in the MouseDown event of the DesktopLabel. It is:

Var d As DragItem
d = New DragItem(Self, Me.Left, Me.Top, Me.Width, Me.Height)
d.Text = Me.Text
d.Drag

This example drags a picture. It uses the optional DragPicture property in the constructor.

Var d As DragItem
d = New DragItem(Self, X, Y, Me.Width, Me.Height, MyPicture)

d.MouseCursor = System.Cursors.HandOpen
d.AddItem(0, 0, Me.Width, Me.Height)
d.Picture = Me.Image
d.Drag ' Allow the drag

DragItem.Drag

Drag

Allows the drag to take place. Note that it is only possible to change the image before calling Drag(), any attempt to do so after that point will fail.

This code drags the picture that is assigned to the Image property of an DesktopImageViewer to another DesktopImageViewer. In the MouseDown event of the first DesktopImageViewer, Drag is used to allow the drag.

Var d As DragItem
d = New DragItem(Self, X, Y, Me.Width, Me.Height)

d.DragPicture = Keaton534
d.MouseCursor = System.Cursors.HandOpen
d.Picture = Me.Image
d.Drag ' Allow the drag

In the second ImageViewer, put this code in its Opening event to allow the picture drop:

Me.AcceptPictureDrop

DragItem.MoveFirst

MoveFirst

If the DragItem contains multiple items, this method makes the first item the active item.

The active item is the item that can be access via the DragItem properties.


DragItem.NextItem

NextItem As Boolean

Returns True if there is another item that has been dragged and assigns the next item's values to the DragItem properties.

Call this method on the dropped item to check if there are additional items you need to process. When called it, assigns the next item's values to the DragItem properties.

Notes

When the user wishes to drag some data from a DesktopWindow or control, a new DragItem object must be created to hold that data in order to transfer it to the object the data will be dropped on. Xojo supports true drag and drop — which means that the recipient of the data can be anything that supports drag and drop and supports the kind of data being dragged. For example, text can be dragged to the desktop to create a text clipping file or any application that accepts dropped text (like SimpleText or the NotePad). Pictures can be dragged to the Desktop to create picture clipping files. Other types of data can be dragged using the RawData property.

The DragItem supports UTIs (Uniform Type Identifiers).

By default, a DragItem can contain only one row containing a single entry for each data type. Using the AddItem method, you can add more rows to the DragItem allowing multiple entries of the same data type. For example, if you wanted a drag item to contain two separate pictures, you would assign one picture to the Picture property then call the AddItem method to add a row and then assign the second picture to the Picture property.

The RawData and PrivateRawData properties allow you to support drag and drop for other data formats. You specify the data format using a four-character Type, corresponding to a Macintosh resource type. RawData and PrivateRawData return the dragged item as a string. It is up to the control or window that receives the DragItem to manage it. Typically, this will mean that you will have to make API calls or use a plug-in that is designed to handle the data format.

You can also use RawData or PrivateRawData to control internal drag and drop. If you make up a four-character Type (not an existing Macintosh resource type), you can prevent a control from receiving dragged text from other sources. See the example of dragging from one DesktopListBox to another.

There is no need to create a DragItem for TextAreas as this is handled automatically.

ListBoxes support the dragging of rows automatically if the EnableDrag property of the DesktopListBox is True (checked). Like TextAreas, the DragItem is created automatically for the ListBox but you must populate the DragItem in the DragRow event handler. See the notes for the DesktopListBox control for more information on dragging from ListBoxes.


Displaying drag pictures when there are multiple drag items

When there are multiple items in the DragItem, You can provide the drag picture in two ways: Using the constructor or by using the DragItem property.

If you use the constructor to provide a single picture, then on MacOS, this picture will be 3D stacked to indicate that there are multiple items. Since the same picture will be stacked in this manner it should be somewhat generic.

Alternatively you can not provide the picture in the constructor and then set the DragPicture property for each DragItem you add with AddItem. On MacOS this results in these separate images being vertically stacked to indicate each item being dragged. This can be more useful if your individual drag items are unique or distinct.


Dragging promised files

MacOS supports the concept of dragging a file before it actually exists in the file system. It could be a new document that hasn't been saved yet or a file that exists on a remote server or on the web.

In these cases, the drag and drop gesture serves the purpose of specifying the location at which to save the new file. When the drag and drop operation is complete, it tells the source where it wants the files saved and the dragging source creates the files. This special type of file drag is called a promise because the drag operation contains a promise from the source to the destination that the source will create the specified files if the drag and drop is accepted.

To drag and drop promised files, call the DesktopUIControl or DesktopWindow's AcceptRawDataDrop method with "phfs"; as the data type. When an application that sends file promises is dropped on your application, you will find a FolderItem in the dragged item. Usually this will point to a file in the TemporaryItems folder and you should ordinarily delete it when you are finished with it.

Sample code

This code shows how to implement dragging the picture in a DesktopCanvas control. This example uses the Me keyword to refer to the DesktopCanvas control.

Function MouseDown(X As Integer, Y As Integer) As Boolean
  Var d As DragItem
  d = New DragItem(Self, X, Y, Me.Width, Me.Height)
  d.Picture = Me.Backdrop
  d.Drag ' Allow the drag
End Function

See also the example for DesktopImageViewer, which illustrates drag and drop between two ImageViewers and jpeg files or clippings on the desktop and the DesktopListBox control, which has an example of drag and drop between two ListBoxes.

The following code implements a "mover" interface in which a user can drag rows from ListBox1 to ListBox2 (and in the reverse direction), but neither DesktopListBox accepts dragged text from other controls or from other apps. It uses PrivateRawData since it also prevents text from being dragged outside the application.

To permit drag and drop in both directions, the two ListBoxes are set up in an identical manner.

Each DesktopListBox has its EnableDrag property set to True. The DragRow event handler is:

Function DragRow(drag As DragItem, row As Integer) As Boolean
  drag.PrivateRawData("text") = Me.List(row) + EndOfLine ' get the text
  Me.RemoveRow(Row)
  Return True ' allow the drag
End Function

To enable each DesktopListBox to accept the dragged text, the following statement appears in its Opening event handler:

Me.AcceptRawDataDrop("text")

The DropObject event handler is as follows:

Sub DropObject (obj As DragItem)
  If obj.RawDataAvailable("text") Then
    Me.AddRow(obj.RawData("text"))
  End If
End Sub

The following code allows the user to drag several text files from the desktop to a DesktopTextArea. The example places the contents of all the text files in the DesktopTextArea, appending each file's contents to the Text property of the DesktopTextArea.

To support several files, the NextItem function is used to determine whether there are any more files remaining to be dropped.

Var textStream As TextInputStream
If obj.FolderItemAvailable Then
  Do
    textStream = TextInputStream.Open(obj.FolderItem)
    Me.TextArea1.AddText(textStream.ReadAll)
  Loop Until Not obj.NextItem
End If

The DesktopTextArea has the line:

Me.AcceptFileDrop(FileTypeGroup1.Text)

Compatibility

All project types on all supported operating systems.