/* Written by Dan Heller and Paula Ferguson.
* Copyright 1994, O'Reilly & Associates, Inc.
* Permission to use, copy, and modify this program without
* restriction is hereby granted, as long as this copyright
* notice appears in each copy of the program source code.
* This program is freely distributable without licensing fees and
* is provided without guarantee or warrantee expressed or implied.
* This program is -not- in the public domain.
*/
/* action_area.c -- demonstrate how CreateActionArea() can be used
* in a real application. Create what would otherwise be identified
* as a PromptDialog, only this is of our own creation. As such,
* we provide a TextField widget for input. When the user presses
* Return, the OK button is activated.
*/
#include <Xm/DialogS.h>
#include <Xm/PushBG.h>
#include <Xm/PushB.h>
#include <Xm/LabelG.h>
#include <Xm/PanedW.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>
typedef struct {
char *label;
void (*callback)();
XtPointer data;
} ActionAreaItem;
static void
do_dialog(), close_dialog(), activate_cb(),
ok_pushed(), clear_pushed(), help();
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, button;
XtAppContext app;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
button = XtVaCreateManagedWidget ("Push Me",
xmPushButtonWidgetClass, toplevel, NULL);
XtAddCallback (button, XmNactivateCallback, do_dialog, NULL);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* callback routine for "Push Me" button. Actually, this represents
* a function that could be invoked by any arbitrary callback. Here,
* we demonstrate how one can build a standard customized dialog box.
* The control area is created here and the action area is created in
* a separate, generic routine: CreateActionArea().
*/
static void
do_dialog(w, client_data, call_data)
Widget w; /* will act as dialog's parent */
XtPointer client_data;
XtPointer call_data;
{
Widget dialog, pane, rc, text_w, action_a;
XmString string;
extern Widget CreateActionArea();
static ActionAreaItem action_items[] = {
{ "OK", ok_pushed, NULL },
{ "Clear", clear_pushed, NULL },
{ "Cancel", close_dialog, NULL },
{ "Help", help, "Help Button" },
};
/* The DialogShell is the Shell for this dialog. Set it up so
* that the "Close" button in the window manager's system menu
* destroys the shell (it only unmaps it by default).
*/
dialog = XtVaCreatePopupShell ("dialog",
xmDialogShellWidgetClass, XtParent (w),
XmNtitle, "Dialog Shell", /* give arbitrary title in wm */
XmNdeleteResponse, XmDESTROY, /* system menu "Close" action */
NULL);
/* now that the dialog is created, set the Cancel button's
* client data, so close_dialog() will know what to destroy.
*/
action_items[2].data = (XtPointer) dialog;
/* Create the paned window as a child of the dialog. This will
* contain the control area and the action area
* (created by CreateActionArea() using the action_items above).
*/
pane = XtVaCreateWidget ("pane", xmPanedWindowWidgetClass, dialog,
XmNsashWidth, 1,
XmNsashHeight, 1,
NULL);
/* create the control area which contains a
* Label gadget and a TextField widget.
*/
rc = XtVaCreateWidget ("control_area", xmRowColumnWidgetClass, pane, NULL);
string = XmStringCreateLocalized ("Type Something:");
XtVaCreateManagedWidget ("label", xmLabelGadgetClass, rc,
XmNlabelString, string,
NULL);
XmStringFree (string);
text_w = XtVaCreateManagedWidget ("text-field",
xmTextFieldWidgetClass, rc, NULL);
/* RowColumn is full -- now manage */
XtManageChild (rc);
/* Set the client data for the "OK" and "Cancel" buttons */
action_items[0].data = (XtPointer) text_w;
action_items[1].data = (XtPointer) text_w;
/* Create the action area. */
action_a = CreateActionArea (pane, action_items, XtNumber (action_items));
/* callback for Return in TextField. Use action_a as client data */
XtAddCallback (text_w, XmNactivateCallback, activate_cb, action_a);
XtManageChild (pane);
XtPopup (dialog, XtGrabNone);
}
/* The next four functions are the callback routines for the buttons
* in the action area for the dialog created above. Again, they are
* simple examples, yet they demonstrate the fundamental design approach.
*/
static void
close_dialog(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
Widget shell = (Widget) client_data;
XtDestroyWidget (shell);
}
/* The "ok" button was pushed or the user pressed Return */
static void
ok_pushed(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
Widget text_w = (Widget) client_data;
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
char *text = XmTextFieldGetString (text_w);
printf ("String = %s\n", text);
XtFree (text);
}
static void
clear_pushed(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
Widget text_w = (Widget) client_data;
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
/* cancel the whole operation; reset to NULL. */
XmTextFieldSetString (text_w, "");
}
static void
help(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
String string = (String) client_data;
puts(string);
}
/* When Return is pressed in TextField widget, respond by getting
* the designated "default button" in the action area and activate
* it as if the user had selected it.
*/
static void
activate_cb(text_w, client_data, call_data)
Widget text_w; /* user pressed Return in this widget */
XtPointer client_data; /* action_area passed as client data */
XtPointer call_data;
{
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
Widget dflt, action_area = (Widget) client_data;
/* get the "default button" from the action area... */
XtVaGetValues (action_area, XmNdefaultButton, &dflt, NULL);
if (dflt) /* sanity check -- this better work */
/* make the default button think it got pushed using
* XtCallActionProc(). This function causes the button
* to appear to be activated as if the user pressed it.
*/
XtCallActionProc (dflt, "ArmAndActivate", cbs->event, NULL, 0);
}
#define TIGHTNESS 20
Widget
CreateActionArea(parent, actions, num_actions)
Widget parent;
ActionAreaItem *actions;
int num_actions;
{
Widget action_area, widget;
int i;
action_area = XtVaCreateWidget ("action_area", xmFormWidgetClass, parent,
XmNfractionBase, TIGHTNESS*num_actions - 1,
XmNleftOffset, 10,
XmNrightOffset, 10,
NULL);
for (i = 0; i < num_actions; i++) {
widget = XtVaCreateManagedWidget (actions[i].label,
xmPushButtonWidgetClass, action_area,
XmNleftAttachment, i? XmATTACH_POSITION : XmATTACH_FORM,
XmNleftPosition, TIGHTNESS*i,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment,
i != num_actions - 1 ? XmATTACH_POSITION : XmATTACH_FORM,
XmNrightPosition, TIGHTNESS * i + (TIGHTNESS - 1),
XmNshowAsDefault, i == 0,
XmNdefaultButtonShadowThickness, 1,
NULL);
if (actions[i].callback)
XtAddCallback (widget, XmNactivateCallback,
actions[i].callback, actions[i].data);
if (i == 0) {
/* Set the action_area's default button to the first widget
* created (or, make the index a parameter to the function
* or have it be part of the data structure). Also, set the
* pane window constraint for max and min heights so this
* particular pane in the PanedWindow is not resizable.
*/
Dimension height, h;
XtVaGetValues (action_area, XmNmarginHeight, &h, NULL);
XtVaGetValues (widget, XmNheight, &height, NULL);
height += 2 * h;
XtVaSetValues (action_area,
XmNdefaultButton, widget,
XmNpaneMaximum, height,
XmNpaneMinimum, height,
NULL);
}
}
XtManageChild (action_area);
return action_area;
}