The drop receiver's responsibilities for dropping are the same as any widget's responsibilities as the destination widget in a UTM transfer. See Chapter 16 for more details.
This chapter explains how a drop receiver can provide help to the user.
It might not always be obvious to the user what the result of dropping a particular source on a drop site might be. The user can request more information about the drop site by pressing osfHelp while the drag icon is over the drop site.
When the user presses osfHelp, UTM starts a drop by doing the following:
When the user presses osfHelp, your XmNdestinationCallback procedure must realize a DialogBox. This DialogBox must provide help about the drop site, and must give users the choice of either continuing or cancelling the drop. While the DialogBox is realized, your XmNdestinationCallback procedure must neither perform any transfers nor call XmTransferDone. Your XmNdestinationCallback procedure must save the transfer_id member for any later XmTransferValue calls to be made.
After the user accepts or rejects the transfer, the processing continues from the callbacks on the dialog buttons. In the case of accepting the transfer, the transfer may be continued by using the transfer_id in calls to all the normal transfer calls in UTM. In the case of rejecting the transfer, the programmer must call XmTransferDone with a status of XmTRANSFER_DONE_FAIL. This will clean up the internal state of UTM and provide drag and drop zap effects to indicate the failure to the user.
The following example taken from DNDDemo.c shows how the help dialog shown in the illustration was created.
Figure 26. Help Dialog.
View figure.
The handleDestination routine examines the operation member of the XmDestinationCallbackStruct. If operation holds XmOTHER, then the HandleHelp routine is called:
void handleDestination(Widget w, XtPointer client, XtPointer call) { XmDestinationCallbackStruct *cs = (XmDestinationCallbackStruct *) call; if (appInfo->highlightRect != NULL) RectUnhighlight(w); if (cs->operation != XmOTHER) HandleDrop(w, call, NULL); else HandleHelp(w, call, NULL); }
The HandleHelp routine displays the help dialog. The text presented in the dialog depends on the drop site and on the requested operation. Callback routines are registered to be performed when either of the dialog pushbuttons is pressed.
static void HandleHelp(Widget w, XtPointer call, XtPointer ignore) { XmDestinationCallbackStruct *cs = (XmDestinationCallbackStruct *) call; XmDropProcCallbackStruct *ds = (XmDropProcCallbackStruct *) cs -> destination_data; Boolean rectFound, bgFound, pixFound; XmString helpStr; RectPtr rect; Arg args[5]; XmString tempStr, buttonArray[2]; int n = 0; savedCB = cs; /* if we haven't created a help dialog, create one now */ if (helpDialog == NULL) { XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++; XtSetArg(args[n], XmNtitle, "Drop Help"); n++; helpDialog = XmCreateMessageDialog(topLevel, "Help", args, n); n = 0; buttonArray[0] = XmStringCreateSimple("Move"); buttonArray[1] = XmStringCreateSimple("Copy"); XtSetArg(args[n], XmNbuttons, buttonArray); n++; XtSetArg(args[n], XmNbuttonCount, 2); n++; XtSetArg(args[n], XmNbuttonSet, 0); n++; XtSetArg(args[n], XmNsimpleCallback, ChangeOperation); n++; tempStr = XmStringCreateSimple("Operations:"); XtSetArg(args[n], XmNoptionLabel, tempStr); n++; helpMenu = XmCreateSimpleOptionMenu(helpDialog, "helpMenu", args, n); XmStringFree(tempStr); XmStringFree(buttonArray[0]); XmStringFree(buttonArray[1]); XtAddCallback(helpDialog, XmNokCallback, (XtCallbackProc) HandleDrop, NULL); XtAddCallback(helpDialog, XmNcancelCallback, (XtCallbackProc) CancelDrop, NULL); XtUnmanageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_HELP_BUTTON)); XtRealizeWidget(helpDialog); } /* find the valid targets */ CheckTargets(ds->dragContext, XtDisplay(w), &rectFound, &bgFound, &pixFound); /* determine the appropriate help message */ if (rectFound) { if (ds->operations == XmDROP_MOVE | XmDROP_COPY) { XtManageChild(helpMenu); helpStr = XmStringCreateLtoR(HELP_MSG4, XmFONTLIST_DEFAULT_TAG); XtManageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } else if (ds->operation == XmDROP_MOVE) { XtUnmanageChild(helpMenu); helpStr = XmStringCreateLtoR(HELP_MSG2, XmFONTLIST_DEFAULT_TAG); XtManageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } else if (ds->operation == XmDROP_COPY) { XtUnmanageChild(helpMenu); helpStr = XmStringCreateLtoR(HELP_MSG3, XmFONTLIST_DEFAULT_TAG); XtManageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } } else if (bgFound || pixFound && ds->operation == XmDROP_COPY) { XtUnmanageChild(helpMenu); rect = RectFind(ds->x, ds->y); if (rect) { helpStr = XmStringCreateLtoR(HELP_MSG1, XmFONTLIST_DEFAULT_TAG); XtManageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } else { helpStr = XmStringCreateLtoR(HELP_MSG5, XmFONTLIST_DEFAULT_TAG); XtUnmanageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } } else { XtUnmanageChild(helpMenu); helpStr = XmStringCreateLtoR(HELP_MSG5, XmFONTLIST_DEFAULT_TAG); XtUnmanageChild(XmMessageBoxGetChild(helpDialog, XmDIALOG_OK_BUTTON)); } /* set the help message into the dialog */ XtSetArg(args[0], XmNmessageString, helpStr); XtSetValues(helpDialog, args, 1); /* Free the XmString */ XmStringFree(helpStr); /* map the help dialog */ XtManageChild(helpDialog); }
If the user selects the OK button to continue the drop, the program calls HandleDrop again. If the user selects the Cancel button, the program calls the CancelDrop routine. This routine calls XmTransferDone as follows to cancel the drop:
static void CancelDrop(Widget w, XtPointer call, XtPointer ignore) { XmDestinationCallbackStruct *cs; /* For drop help we save the XmDestinationCallbackStruct in a global variable named savedCB. */ cs = savedCB; XmTransferDone(cs -> transfer_id, XmTRANSFER_DONE_FAIL); }