Common Desktop Environment: Programmer's Guide
Contents of Chapter:
- Mechanisms for Invoking Actions from an Application
-
- Types of Actions
-
- Action Invocation API
-
- Related Information
-
- actions.c Example Program
-
- Loading the Database of Actions and Data Types
-
- To Initialize the Desktop Services Library
-
- To Load the Actions and Data-Typing Database
-
- To Request Notification of Reload Events
-
- Checking the Actions Database
-
- To Determine Whether a Specified Action Definition Exists
-
- To Obtain the Icon Image Information for a Specified Action
-
- To Get the Localized Label for an Action
-
- Invoking Actions
-
- To Invoke an Action
-
- Listing for actions.c
-
If your application manages an extensible collection of data types, there is a strong likelihood that it should be directly involved with action invocation. This chapter explains how you can invoke an action from an application. Included is an example program that shows you how to invoke an action.
For more information on actions and how you create them, see Chapter 9, "Accessing the Data_Typing Database," in this manual, and the following chapters in
the CDE Advanced User's and System Administrator's
Guide:
- "Introduction to Actions and Data Types"
- "Creating Actions and Data Types Using Create Action"
- "Creating Actions Manually"
- "Creating Data Types Manually"
The action invocation API exported by the Desktop Services library is one mechanism available to your application to cause another application to be invoked or to perform an operation. Other mechanisms include:
- The fork/exec system calls
- ToolTalk messages
Each of these mechanisms has benefits and limitations, so you must evaluate your specific situation to determine which is most appropriate.
The advantages of using the action invocation API include:
- Actions can encapsulate both traditional command-line applications (that is, COMMAND
actions) and ToolTalk applications (that is, TT_MSG
actions). The application that invokes the action does not need to know whether a command is forked or a message is sent.
- Actions are polymorphic and are integrated with the desktop's data-typing mechanisms. This means that an action, such as Open or Print, may have different behavior depending on the type of argument that is supplied, but the behavior differences are transparent to the application that invokes the action.
- Actions provide a great deal of configurability for the application developer, system integrator, system administrator, and end user. Any one of these people can edit the action database to modify the definition of how an action is to be performed.
- Actions work well in distributed environments. If an application uses fork/exec
to directly invoke another application, then both applications must be available and able to run on the same system. By contrast, the action invocation API uses information in the action database to determine on which system a COMMAND
action should be invoked.
- Actions enable your application to behave consistently with the behavior of the desktop. This is because the desktop's components interact by using actions when manipulating the user's data files.
The disadvantage of using the action invocation API is that it is only an invocation mechanism that has limited return value capabilities and has no capabilities for a dialog with the invoked action handler. If these features are required, fork/exec/pipes
can be used. However, within CDE, ToolTalk is the preferred cross process communications mechanism due to its generalized client/server paradigm.
Returning to invocation, suppose your application manages data files in several different formats (text and graphics) and needs to provide a way for the user to edit and display these files. To implement this feature without using actions, you would probably use one of the following mechanisms:
To implement this feature using actions, you only have to invoke the Open action on the buffer or on the data file. The action invocation API will use the action database to determine the appropriate message to send or command to invoke as well as handle all details, such as creating and cleaning up temporary files and catching necessary signals.
The action application program interface (API) works with any type of action. Types of actions in the desktop include:
- Command actions
- Specifies a command line to execute.
- ToolTalk actions
- Specifies a ToolTalk message to send, which is then received by the appropriate application.
- Map actions
- Refers to another action instead of defining any specific behavior.
See "Introduction to Actions and Data Types" in the CDE Advanced User's and System Administrator's Guide for more
information.
The action invocation API is exported from the Desktop Services library and provides functions to accomplish a number of tasks, such as:
- Initializing and loading the database of action and data-type definitions. The database must be loaded before an action can be run.
- Querying the database. There are functions to determine whether a specified action or its associated icon image, label, or description exists.
- Invoking an action. The application can pass file or buffer arguments to the action.
- Registering a callback to receive action status and return arguments.
For detailed information about action commands, functions, and data formats, see the following man pages:
- dtaction(1)
- dtactionfile(4)
- DtActionCallbackProc(3)
- DtActionDescription(3)
- DtActionExists(3)
- DtActionIcon(3)
- DtActionInvoke(3)
- DtActionLabel(3)
- DtActionQuit(3)
- DtActionQuitType(3)
- DtActionStUpCb(3)
- dtexec(1)
This section describes a simple example program, actions.c. A complete listing of actions.c is at the end of this chapter.
Loading the Database of Actions and Data Types
Before your application can invoke an action, it must
initialize the Desktop Services library (which contains the action invocation API) and load the database of action and data-type definitions.
To Initialize the Desktop Services Library
Use the DtInitialize() function to initialize the Desktop Services Library.
- DtInitialize(*display,widget,*name,*tool_class)
- DtInitialize()
uses the default Intrinsic XtAppContext
. The API provides an additional function, DtAppInitialize()
to use when your application must specify an app_context
:
- DtAppInitialize(app_context,*display,widget,*name, tool_class)
DtInitialize() Example
The following code segment shows how the example program actions.c uses DtInitialize().
if (DtInitialize(XtDisplay(shell), shell, argv[0],ApplicationClass)==False) {
/* DtInitialize() has already logged an appropriate error msg */
exit(-1);
}
To Load the Actions and Data-Typing Database
Use the DtDbLoad() function to load the actions and data-typing database.
- DtDbLoad
(void)
- DtDbLoad()
reads in the action and data-typing database. This function determines the set of directories that are to be searched for database files (the database search path) and loads the *.dt
files found into the database. The directory search path is based on the value of the DTDATABASESEARCHPATH
environment variable and internal defaults.
If you use DtDbLoad() in a long-lived application, it must dynamically reload the database whenever it is modified.
- Use the DtDbReloadNotify()function to request notification of reload events.
/* Notice changes to the database without needing to restart
application */
DtDbReloadNotify(DbReloadCallbackProc, callback_proc,
XTPointer, client_data);
- Supply a callback that:
- Destroys cached database information held by the application
- Calls the DtDbLoad() function again
C
allback_proc
cleans up any cached database information your application is holding and then invokes DtDbLoad()
. Client_data
may be used to pass additional client information to the callback routine.
Your application accesses the database if it needs to display the icon or label for an action. Also before invoking an action, your application can check that it exists. An action is identified in the database by the action name:
ACTION action_name
{
...
}
For example, the action definition for the Calculator looks like this:
ACTION Dtcalc
{
LABEL Calculator
ICON Dtcalc
ARG_COUNT 0
TYPE COMMAND
WINDOW_TYPE NO_STDIO
EXEC_STRING /usr/dt/bin/dtcalc
DESCRIPTION The Calculator (Dtcalc) action runs the \
desktop Calculator application.
}
The action name for the Calculator action is Dtcalc.
When an executable file has a file name that matches an action name in the existing database, that file is an action file--a representation for the underlying action. The information about the icon and label for that file are stored in the database.
To Determine Whether a Specified Action Definition Exists
Use the DtActionExists() function to determine whether a specified action definition exists.
- DtActionExists(*name)
- DtActionExists()
checks whether the specified name
corresponds to the name of an action in the database. The function returns True if name
corresponds to an action name, or False if no action with that name is found.
Use the DtActionIcon() function to obtain the icon image information.
- DtActionIcon(char *action_name)
An action definition specifies the icon image used to represent the action in the definition's ICON field:
ACTION action_name
{
ICON icon_image_base_name
...
}
DtActionIcon()
returns a character string containing the value of the icon image field. If the action definition does not contain an icon field, the function returns the value of the default action icon image, Dtactn
.
You then need to determine the location of the icon, and the size you want to use. Icons can exist in four sizes and are available in bitmap or pixmap form. For example, you can find the base name of the icon file from the action definition for the Calculator. You then use the base name coupled with the information given in Table 8-1
and knowledge of the location of all the icons to find the specific icon file you want.
The icon name for the calculator action is Dtcalc
, but that is not the entire file name. Icon file names are based on the size of the icon. Table 8-1
shows the sizes and file-naming conventions for the desktop icons.
Table 8-1 Icon Sizes and File Names
Note: See "Creating Icons for the Desktop" in the CDE Advanced User's and System Administrator's Guide for more information about the
desktop icon files.
For bitmaps, there is an additional file that is used as a mask, and its extension ends with _m.bm
. Thus, there can be a total of three files for each size icon. Here are the icon files for the calculator:
Dtcalc.t.bm
Dtcalc.t.pm
Dtcalc.t_m.bm
Dtcalc.m.bm
Dtcalc.m.pm
Dtcalc.m_m.bm
Dtcalc.l.bm
Dtcalc.l.pm
Dtcalc.l_m.bm
Note: There are no small icons (Dtcalc.s.bm, Dtcalc.s.pm, Dtcalc.s_m.bm) for the Calculator.
DtActionIcon()
returns only a base name; for the Calculator it is Dtcalc
. You must choose the type (pixmap or bitmap) and size (tiny, small, medium, or large) and append the applicable extension to the base name. In addition, you must know where the file resides.
To Get the Localized Label for an Action
Use the DtActionLabel() function to get the localized label for an action.
- char *DtActionLabel(char *actionName)
An action definition may include a label. The label is defined using the label_text field:
ACTION action_name
{
LABEL label_text
...
}
This label is used in graphical components (such as File Manager and the Application Manager) to label the action's icon. If an action definition does not include a label_text
field, the action_name
is used.
The value of label_text string should be used by all interface components to identify the action to the end user.
The DtActionLabel()
function returns the value of the label_text
field in the action definition of the action named actionName
. If the label_text
field does not exist, the function returns the actionName
.
After your application has initialized the Desktop Services Library it can then invoke an action.
To Invoke an Action
Use the DtActionInvoke function to invoke an action.
- DtActionInvokeID (widget, action, args, argCount, termOpts, execHost,
contexDir, useIndicator, statusUpdateCb, client_data)
DtActionInvoke()
searches the action database for an entry that matches the specified action name, and accepts arguments of the class, type, and count provided. Remember that your application must initialize and load the database before invoking an action.
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994 Novell, Inc.
*/
#include <Xm/XmAll.h>
#include <Dt/Dt.h>
#include <Dt/Action.h>
#define ApplicationClass "Dtaction"
static Widget shell;
static XtAppContext appContext;
static Widget actionText;
static Widget fileText;
static void CreateWidgets(Widget);
static void InvokeActionCb(Widget, XtPointer, XtPointer);
static void InvokeAction(char*, char*);
static void DbReloadProc(XtPointer);
void main(int argc, char **argv)
{
Arg args[20];
int n=0;
int numArgs = 0;
shell = XtAppInitialize(&appContext , ApplicationClass, NULL, 0,
&argc, argv, NULL, args, n);
CreateWidgets(shell);
if (DtInitialize(XtDisplay(shell), shell, argv[0],
ApplicationClass)==False) {
/* DtInitialize() has already logged an appropriate error msg */
exit(-1);
}
/* Load the filetype/action databases */
DtDbLoad();
/* Notice changes to the database without needing to restart application */
DtDbReloadNotify(DbReloadProc, NULL);
XtRealizeWidget(shell);
XmProcessTraversal(actionText, XmTRAVERSE_CURRENT);
XtAppMainLoop(appContext);
}
static void CreateWidgets(Widget shell)
{
Widget messageBox, workArea, w;
Arg args[20];
int n;
XmString labelString;
labelString = XmStringCreateLocalized("Invoke");
n = 0;
XtSetArg(args[n], XmNdialogType, XmDIALOG_TEMPLATE); n++;
XtSetArg(args[n], XmNokLabelString, labelString); n++;
messageBox = XmCreateMessageBox(shell, "messageBox", args, n);
XtManageChild(messageBox);
XmStringFree(labelString);
XtAddCallback(messageBox, XmNokCallback, InvokeActionCb, NULL);
n = 0;
XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
XtSetArg(args[n], XmNnumColumns, 2); n++;
XtSetArg(args[n], XmNentryAlignment, XmALIGNMENT_END); n++;
workArea = XmCreateWorkArea(messageBox, "workArea", args, n);
XtManageChild(workArea);
labelString = XmStringCreateLocalized("Invoke Action:");
n = 0;
XtSetArg(args[n], XmNlabelString, labelString); n++;
w = XmCreateLabel(workArea, "actionLabel", args, n);
XtManageChild(w);
XmStringFree(labelString);
labelString = XmStringCreateLocalized("On File:");
n = 0;
XtSetArg(args[n], XmNlabelString, labelString); n++;
w = XmCreateLabel(workArea, "fileLabel", args, n);
XtManageChild(w);
XmStringFree(labelString);
n = 0;
XtSetArg(args[n], XmNcolumns, 12); n++;
actionText = XmCreateTextField(workArea, "actionText", args, n);
XtManageChild(actionText);
n = 0;
XtSetArg(args[n], XmNcolumns, 12); n++;
fileText = XmCreateTextField(workArea, "fileText", args, n);
XtManageChild(fileText);
}
static void DbReloadProc(XtPointer cd)
{
/* Pick up any dynamic changes to the database files */
DtDbLoad();
}
static void InvokeActionCb(Widget w, XtPointer cd, XtPointer cb)
{
char *action;
char *file;
action = XmTextFieldGetString(actionText);
if (action == NULL) return;
if (strlen(action) == 0) {
XtFree(action);
return;
}
file = XmTextFieldGetString(fileText);
InvokeAction(action, file);
XtFree(action);
XtFree(file);
XmTextFieldSetString(actionText, "");
XmTextFieldSetString(fileText, "");
XmProcessTraversal(actionText, XmTRAVERSE_CURRENT);
}
static void InvokeAction(char *action, char *file)
{
DtActionArg *ap = NULL;
int nap = 0;
DtActionInvocationID actionId;
/* If a file was specified, build the file argument list */
printf("%s(%s)\n",action,file);
if (file != NULL && strlen(file) != 0) {
ap = (DtActionArg*) XtCalloc(1, sizeof(DtActionArg));
ap[0].argClass = DtACTION_FILE;
ap[0].u.file.name = file;
nap = 1;
}
/* Invoke the specified action */
actionId = DtActionInvoke(shell,action,ap,nap,NULL,NULL,NULL,True,NULL,NULL);
}
Generated with CERN WebMaker