A drag source widget has a dragDetectCallback hooked that sends the dragStart:argBlock: method of CwWidget. To start a drag from a drag source widget, the user holds down a mouse button while over the widget and moves the mouse to a different location.
Some platforms allow dragging with a button other than those listed above. To implement this behavior, applications call dragStart:argBlock: from a button event handler.
The following example hooks a dragDetectCallback to a specified widget:
hookDragDetect: aCwWidget "Hook a dragDetect callback to the specified widget." aCwWidget addCallback: XmNdragDetectCallback receiver:self selector: #dragDetect:clientData:callData: clientData: nil.
When a drag begins over the widget, dragDetect:clientData:callData: is sent to the receiver. The parameters to this callback are as follows:
The CwDragDetectCallbackData instance contains a ButtonPress event that can determine the mouse position and button when the button is pressed. The callData reason is either XmCRDRAG or XmCRDRAGSELECT.
On platforms that allow the left mouse button to initiate a drag, normal drag selection might cause the dragDetectCallback to be amibiguous in certain widgets, such as text and list widgets. In these cases, the callData reason will be XmCRDRAGSELECT and the application can decide whether to allow the drag selection to continue, or set the callData doit to false and start a drag.
OSF/Motif platforms provide default drag behavior in text, label, and button widgets. Common Widgets drag and drop turns off this behavior in a widget when a dragDetect callback is added.
An application starts a drag from a dragDetect callback handler by sending dragStart:argBlock: with a CwDragContext create argBlock to the widget that received the callback. Sending dragStart:argBlock: creates a CwDragContext which represents the drag source for the duration of the drag and drop operation. Only one instance of CwDragContext can exist at any time, and the instance ceases to exist when the drag and drop operation is complete.
The following drag context resources can be set in the create argBlock when the drag starts:
The following code shows a typical dragDetect callback handler. It starts a drag, specifying the operations and targets that the drag source supports and hooking a convertProc to handle the source side of the data transfer. Assume that self dragIcon answers a CgIcon.
dragDetectCallback: aCwWidget clientData: clientData callData: callData "Handle the dragDetect callback for the receiver." | startDrag | (startDrag := callData reason = XmCRDRAG) ifFalse: [ "The reason is XmCRDRAGSELECT. Decide if the user is doing a drag or a select." (self checkDragSourceCoordinates: callData event x @ callData event y)
ifTrue: [ "Interpret the mouse action as a drag operation rather than a selection operation. Set the doit flag to false to prevent the widget from doing normal selection processing." callData doit: false. startDrag := true]].
startDrag ifTrue: [ aCwWidget dragStart: callData event argBlock: [:dragContext | dragContext sourceCursorIcon: self dragIcon; dragOperations: XmDROPMOVE | XmDROPCOPY; exportTargets: #('STRING'); convertProc: (CwCallbackRec receiver: self selector: #convertProc:clientData:callData: clientData: aCwWidget)]].