/* $XConsortium: simpledrop.c /main/6 1996/04/21 18:50:33 drk $ */
/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*
*/
/*
* HISTORY
*/
/*
* A Simple Drag And Drop Demo
*
* Created: Vania JOLOBOFF / January 1994
* ======================================================================
*
*/
/*
* ===================== include ========================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <Xm/XmAll.h>
/* ======================================================================
* General Types
*/
typedef enum {closed, open} State ;
/*
* The demo basic data structure
*/
typedef struct _Airport {
XtAppContext context;
Display * display;
int screen_width;
int screen_height;
State state;
Widget main; /* the main window */
Widget drop_area; /* the drop_area drawing area */
Widget help_dialog;
Widget error_dialog;
Widget warning_dialog;
Widget msg_area;
Position drop_x;
Position drop_y;
} DropDemoRec, *DropDemo;
/* ======================================================================
* Global constants and variables
*/
Atom StringAtom;
Atom PixmapAtom;
Atom CTAtom;
/* ============================ prototypes ======================= */
static void Warning(DropDemo this, String s1, String s2);
/* issue a warning to user */
static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
XtCallbackProc procs[], XtPointer private[], int count);
static void HelpCallback(Widget button, XtPointer client_data, XtPointer cbs);
static void ExitCallback(Widget button, XtPointer client_data, XtPointer cbs);
static void SomethingDropped(Widget dc, XtPointer client_data,
XmDropProcCallbackStruct *call_data);
/* drop proc callback on airport. Something is landing */
static void TransferDone(Widget transfer, XtPointer client_data,
Atom * selection, Atom * type, XtPointer value,
unsigned long *length, int *format);
/* Xt Selection Callback. Transfer flight number from source */
/* =====================================================================
* Show application modal warning dialogue box with specified messages
*/
static void Warning(DropDemo this, String s1, String s2)
{
XmString msg;
char tmp[256];
if (s1 == NULL)
msg = XmStringCreateLocalized(s2);
else if (s2 == NULL)
msg = XmStringCreateLocalized(s1);
else {
strncat(strcpy(tmp, s1), s2, 256);
msg = XmStringCreateLocalized(tmp);
}
if (this->warning_dialog == NULL) {
Arg args[8];
int n = 0;
XtSetArg(args[n], XmNdialogStyle,
XmDIALOG_FULL_APPLICATION_MODAL);
n++;
this->warning_dialog = XmCreateWarningDialog(this->main,
"warning", args, n);
}
printf("warning %s\n", tmp);
XtVaSetValues(this->warning_dialog, XmNmessageString, msg, NULL);
/* XmStringFree(msg); */
printf("managing dialog\n");
XtManageChild(this->warning_dialog);
}
/* ===============================================================
* Create a cascade and a pulldown entry into a menubar,
* from a list of push button specs.
* If the label is NULL, create a separator instead of a push button.
*/
static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
XtCallbackProc procs[], XtPointer private[],
int count)
{
Widget menu;
Widget kid;
Arg args[8];
int n;
int i;
char name[128];
n = 0;
menu = XmCreatePulldownMenu(menubar,
strcat(strcpy(name, entry), "Menu"),
args, n);
for( i = 0; i < count; i++) {
n = 0;
if (labels[i] == NULL) {
kid = XmCreateSeparator(menu, "sep", args, n);
}
else {
kid = XmCreatePushButton(menu, labels[i], args, n);
if (procs[i] != NULL)
XtAddCallback(kid, XmNactivateCallback, procs[i], private[i]);
}
XtManageChild(kid);
}
n = 0;
XtSetArg(args[n], XmNlabelString, XmStringCreateSimple(entry)); n++;
XtSetArg(args[n], XmNsubMenuId, menu); n++;
kid = XmCreateCascadeButton(menubar, entry, args, n);
XtManageChild(kid);
return kid;
}
/* ==============================================================
* Main loop
*/
int main(int argc, char *argv[])
{
#define MAIN_CHILDREN 3
#define FORM_CHILDREN 2
#define SetMenuEntry(k,l,p,d) labels[k]=l;procs[k]=p;private[k]=d;
#define NUM_TARGETS 3
Atom targets[NUM_TARGETS];
Widget theWidgetRoot;
Widget main_kid[MAIN_CHILDREN];
Widget form_kid[FORM_CHILDREN];
Widget framed[2];
Widget entry;
static char myClass[] = "DropDemo";
Arg args[10];
int n ;
String labels[4];
XtCallbackProc procs[4];
XtPointer private[4];
DropDemo this;
/*
* Initialize
*/
this = (DropDemo) XtCalloc(sizeof(DropDemoRec), 1);
this->state = closed;
theWidgetRoot = XtVaAppInitialize(&this->context, myClass,
NULL, 0, &argc, argv, NULL, NULL,
XmNallowShellResize, True,
NULL);
this->display = XtDisplay(theWidgetRoot);
StringAtom = XmInternAtom(this->display, "STRING", False);
PixmapAtom = XmInternAtom(this->display, "PIXMAP", False);
CTAtom = XmInternAtom(this->display, "COMPOUND_TEXT", False);
/*
* Create the widget structure.
* Create the Main Window, the menubar and the pulldown menus
* Then a scale and a drawing area inside a frame inside a form
*/
n = 0;
this->main = XmCreateMainWindow(theWidgetRoot, "main", args, n);
/*
* Create the menu bar with a File and Help entries
*/
n = 0;
XtSetArg (args[n], XmNscrolledWindowChildType, XmMENU_BAR); n++ ;
main_kid[0] = XmCreateMenuBar(this->main, "menubar", args, n);
n = 0;
SetMenuEntry(n, "Exit", (XtCallbackProc)ExitCallback, (XtPointer)this );
n++;
entry = MenuBarEntry(main_kid[0], "File", labels, procs, private, n);
n = 0;
SetMenuEntry(0, "Tutorial", (XtCallbackProc)HelpCallback, (XtPointer)this);
n++;
entry = MenuBarEntry(main_kid[0], "Help", labels, procs, private, n);
n = 0;
XtSetArg(args[n], XmNmenuHelpWidget, entry); n++;
XtSetValues(main_kid[0], args, n);
/*
* Create the work area as a Form containing a Scale and a Frame
*/
n = 0;
this->screen_width = WidthOfScreen(XtScreenOfObject(this->main));
this->screen_height = HeightOfScreen(XtScreenOfObject(this->main));
XtSetArg(args[n], XmNwidth, this->screen_width*3/7); n++;
XtSetArg(args[n], XmNheight, this->screen_height*3/7); n++;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); n++;
XtSetArg (args[n], XmNscrolledWindowChildType, XmWORK_AREA); n++ ;
main_kid[1] = XmCreateForm(this->main, "work_area", args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNvalue, 0); n++;
XtSetArg(args[n], XmNmaximum, this->screen_width*3/7); n++;
XtSetArg(args[n], XmNminimum, 0); n++;
XtSetArg(args[n], XmNshowValue, True); n++;
XtSetArg(args[n], XmNtitleString,
XmStringCreateLocalized("Number To Drag")); n++;
form_kid[0] = XmCreateScale(main_kid[1], "scale", args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET) ; n++;
XtSetArg(args[n], XmNtopWidget, form_kid[0]) ; n++;
XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++;
form_kid[1] = XmCreateFrame(main_kid[1], "frame", args, n);
n = 0;
XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
framed[0] = XmCreateLabel(form_kid[1], "drop_here", args, n);
/*
* Create the dropping area
*/
n = 0;
this->drop_area =
framed[1] = XmCreateBulletinBoard(form_kid[1], "da", args, n);
XtVaSetValues(this->drop_area, XmNuserData, this, NULL);
n = 0;
targets[0] = StringAtom;
targets[1] = PixmapAtom;
targets[2] = CTAtom;
XtSetArg(args[n], XmNimportTargets, targets); n++;
XtSetArg(args[n], XmNnumImportTargets, NUM_TARGETS); n++;
XtSetArg(args[n], XmNdragProc, NULL); n++;
XtSetArg(args[n], XmNdropProc, SomethingDropped); n++;
XmDropSiteRegister(this->drop_area, args, n);
XtManageChildren(framed, 2);
XtManageChildren(form_kid, FORM_CHILDREN);
XtManageChildren(main_kid, 2);
XtManageChild(this->main);
XtRealizeWidget(theWidgetRoot);
XtAppMainLoop(this->context);
return 0; /* make compiler happy */
}
/* ===============================================================
* The Exit Callback. Exit properly.
*/
static void ExitCallback(Widget button, XtPointer client_data, XtPointer cbs)
{
DropDemo this = (DropDemo) client_data;
XtCloseDisplay(this->display);
exit(0);
}
/* ======================================================================
* Help Callback. Display help message.
*/
static void HelpCallback(Widget button, XtPointer client_data, XtPointer cbs)
{
DropDemo this = (DropDemo) client_data;
static char helpmsg[] =
"Please drag the value of the scale into the drop area";
if ( this->help_dialog == NULL ) {
Arg args[8];
int n = 0;
XtSetArg(args[n], XmNmessageString,
XmStringCreateLocalized(helpmsg)); n++;
this->help_dialog = XmCreateInformationDialog(button,
"helpdialog", args, n);
}
XtManageChild(this->help_dialog);
}
/* ===============================================================
* Drop proc callback of the drop site.
* If the drop site is invalid, issue a warning
* If the drop site is valid, we know the target is at least one of
* String, CT or Pixmap.
* Pick one of them only in this order of preference.
*/
static void SomethingDropped(Widget dropSite, XtPointer client_data,
XmDropProcCallbackStruct *call_data)
{
#define NUMREC 2
DropDemo this;
Arg args[8];
Arg get_args[4];
Atom * exports;
XmDropTransferEntryRec target_data[NUMREC];
unsigned char status;
Widget dc = call_data->dragContext;
int n = 0;
int i = 0;
Cardinal num_targets = 0;
Cardinal num_transfer = 0;
XtVaGetValues(dropSite, XmNuserData, &this, NULL);
XtSetArg(get_args[i], XmNexportTargets, &exports); i++;
XtSetArg(get_args[i], XmNnumExportTargets, &num_targets); i++;
XtGetValues(dc, get_args, i);
if (call_data->dropSiteStatus == XmVALID_DROP_SITE) {
call_data->operation = XmDROP_COPY;
this->drop_x = call_data->x;
this->drop_y = call_data->y;
for (i = 0; i < num_targets; i++ )
if (exports[i] == StringAtom
|| exports[i] == CTAtom
|| exports[i] == PixmapAtom) {
status = XmTRANSFER_SUCCESS;
num_transfer = 1;
target_data[0].client_data = (XtPointer) this;
target_data[0].target = exports[i];
XtSetArg(args[n], XmNtransferProc, TransferDone); n++;
XtSetArg(args[n], XmNdropTransfers, target_data); n++;
break;
}
}
else {
Warning(this, "Non Identified Object is Dropped. ",
num_targets > 0 ? XmGetAtomName(this->display,exports[0]) : "");
status = XmTRANSFER_FAILURE;
}
XtSetArg(args[n], XmNnumDropTransfers, num_transfer); n++;
XtSetArg(args[n], XmNtransferStatus, status); n++;
XmDropTransferStart(call_data->dragContext, args, n);
#undef NUMREC
}
/* ===============================================================
* The selection callback proc after drop transfer.
* Bytes have been received. Check they are OK
* If data received is corrupted, issue a warning.
*/
static void TransferDone(Widget transfer, XtPointer client_data,
Atom * selection, Atom * type, XtPointer value,
unsigned long *length, int *format)
{
Arg args[16];
int n = 0;
Widget label;
DropDemo this = (DropDemo) client_data;
XmString string = NULL;
char msg[256];
if (*format == 8)
{
if (*type == StringAtom)
string = XmStringCreateSimple( (char *) value );
else if (*type == CTAtom)
string = XmCvtCTToXmString( (char *) value );
XtSetArg(args[n], XmNlabelString, string); n++;
}
else if (*type == PixmapAtom && *format == 32) {
Pixmap pixmap = (Pixmap) value;
XtSetArg(args[n], XmNbackgroundPixmap, pixmap); n++;
}
else {
XtVaSetValues(transfer,
XmNtransferStatus, XmTRANSFER_FAILURE,
XmNnumDropTransfers, 0,
NULL);
sprintf(msg, "Type %s format %d",
XmGetAtomName(this->display, *type), *format);
Warning(this, "Dropped data is corrupted. ", msg);
return;
}
XtSetArg(args[n], XmNx, this->drop_x); n++;
XtSetArg(args[n], XmNy, this->drop_y); n++;
label = XmCreateLabel(this->drop_area, "label", args, n);
XtManageChild(label);
if (string != NULL)
XmStringFree(string);
}