466 lines
17 KiB
Plaintext
466 lines
17 KiB
Plaintext
<!-- $XConsortium: Concepts.sgm /main/7 1996/09/08 22:00:17 rws $ -->
|
|
<!-- (c) Copyright 1995 Digital Equipment Corporation. -->
|
|
<!-- (c) Copyright 1995 Hewlett-Packard Company. -->
|
|
<!-- (c) Copyright 1995 International Business Machines Corp. -->
|
|
<!-- (c) Copyright 1995 Sun Microsystems, Inc. -->
|
|
<!-- (c) Copyright 1995 Novell, Inc. -->
|
|
<!-- (c) Copyright 1995 FUJITSU LIMITED. -->
|
|
<!-- (c) Copyright 1995 Hitachi. -->
|
|
<!-- Help volume: App Builder
|
|
File name: concepts -->
|
|
<Chapter Id="ABConcepts">
|
|
<Title>App Builder Concepts</Title>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.1">
|
|
<Para><XRef Linkend="ABProcess">
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.2">
|
|
<Para><XRef Linkend="ABProjectsModules">
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.3">
|
|
<Para><XRef Linkend="ABMessageExample">
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.4">
|
|
<Para><XRef Linkend="ABAboutAttachments">
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
<Sect1 Id="ABProcess">
|
|
<Title>Summary of the App Builder Process</Title>
|
|
<IndexTerm>
|
|
<Primary>app builder process</Primary>
|
|
</IndexTerm>
|
|
<IndexTerm>
|
|
<Primary>process, creating an interface</Primary>
|
|
</IndexTerm>
|
|
<Para>The process of creating an App Builder user interface can be summarized as follows.
|
|
</Para>
|
|
<OrderedList>
|
|
<ListItem Id="H.CNCP.item.5">
|
|
<Para>Design the interface; draw a picture of it.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.6">
|
|
<Para>Perform an App Builder "spec" of the interface (determine what
|
|
App Builder objects will be used for each of the parts of the
|
|
interface design).
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.7">
|
|
<Para>Start App Builder.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.8">
|
|
<Para>Drag and drop a main window onto the desktop; this will be the
|
|
starting point for all functions in the finished application.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.9">
|
|
<Para>Drag and drop a control pane onto the main window; controls
|
|
will be dropped onto the control pane.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.10">
|
|
<Para>Drag and drop the appropriate controls onto the control pane;
|
|
use the group, alignment, and attachment tools of App Builder to
|
|
position the controls properly.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.11">
|
|
<Para>Drag and drop other main windows and custom dialogs
|
|
onto the desktop to create the other parts of the interface.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.12">
|
|
<Para>Make programmatic connections between objects in the
|
|
interface; test the connections in test mode.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.13">
|
|
<Para>Refine the interface and continue testing until it is right.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.14">
|
|
<Para>Generate code by running the App Builder code generator; add
|
|
user code to complete the functionality of the application.
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.15">
|
|
<Para>Compile, run, test, iteratively until the application is
|
|
complete.
|
|
</Para>
|
|
</ListItem>
|
|
</OrderedList>
|
|
</Sect1>
|
|
<Sect1 Id="ABProjectsModules">
|
|
<Title>App Builder Projects and Modules</Title>
|
|
<IndexTerm>
|
|
<Primary>projects</Primary>
|
|
</IndexTerm>
|
|
<IndexTerm>
|
|
<Primary>modules</Primary>
|
|
</IndexTerm>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.16">
|
|
<Para><XRef Linkend="ABProjectDef">
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.17">
|
|
<Para><XRef Linkend="ABModuleDef">
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
<Sect2 Id="ABProjectDef">
|
|
<Title>What Is a Project?</Title>
|
|
<Para>When you use App Builder to create a graphical user interface, you are
|
|
working on a <Emphasis>project,</Emphasis> which is comprised of one or more
|
|
modules. App Builder, which was built with itself, was a single project,
|
|
comprised of over 30 modules.</Para>
|
|
<Para>A project file is started when you select New Project in the File menu
|
|
or when you drag and drop a window onto the desktop in a new session
|
|
of App Builder.</Para>
|
|
<Para>A project file is saved when you select Save Project in the File menu
|
|
or when you select Save in the Project menu in the Project Organizer.
|
|
A project file has a <ComputerOutput>.bip</ComputerOutput> (builder interface
|
|
project) suffix.</Para>
|
|
<Procedure>
|
|
<Title>See Also</Title>
|
|
<Step>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.18">
|
|
<Para><XRef Linkend="ABModuleDef"></Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
</Step>
|
|
</Procedure>
|
|
</Sect2>
|
|
<Sect2 Id="ABModuleDef">
|
|
<Title>What Is a Module?</Title>
|
|
<Para>A module is a logical unit of a project. Each window and dialog in
|
|
App Builder is a module of the App Builder project, for instance.</Para>
|
|
<Para>All module files in a project are saved when the project is saved. You
|
|
can explicitly save a particular module by selecting Save in the
|
|
Module menu in the Project Organizer.</Para>
|
|
<Para>A saved module file has a <ComputerOutput>.bil</ComputerOutput> (builder interface
|
|
language) suffix.</Para>
|
|
<Procedure>
|
|
<Title>See Also</Title>
|
|
<Step>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.19">
|
|
<Para><XRef Linkend="ABProjectDef"></Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
</Step>
|
|
</Procedure>
|
|
</Sect2>
|
|
</Sect1>
|
|
<Sect1 Id="ABMessageExample">
|
|
<Title>Example: Writing Code for Messages</Title>
|
|
<Para>Once you have created a message as described in <XRef Linkend="ABCreateMessage">, you must determine when and how it should be
|
|
displayed. Usually messages are displayed after a certain piece of
|
|
logic has been executed. For example, if a user types digits in a
|
|
text field that is designed to accept a name, you will want to post an
|
|
error message informing the user that digits are not valid.</Para>
|
|
<Para>Message boxes in Motif can be displayed in one of two ways: modally or
|
|
non-modally (equivalently, blocking or non-blocking). The App Builder
|
|
code generator (<ComputerOutput>dtcodegen</ComputerOutput>) supplies two routines,
|
|
corresponding to the two modes of display. They are found in
|
|
<ComputerOutput>dtb_utils.c</ComputerOutput> and are named:</Para>
|
|
<ItemizedList Mark="•">
|
|
<ListItem Id="H.CNCP.item.20">
|
|
<Para><ComputerOutput>dtb_show_modal_message()</ComputerOutput>
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.21">
|
|
<Para><ComputerOutput>dtb_show_message()</ComputerOutput>
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
<Para>If you want to display a particular message modally, use
|
|
<ComputerOutput>dtb_show_ modal_message()</ComputerOutput>.
|
|
If you want to display a particular message non-modally,
|
|
use <ComputerOutput>dtb_show_message()</ComputerOutput>.
|
|
</Para>
|
|
<Procedure>
|
|
<Title>See Also</Title>
|
|
<Step>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.22">
|
|
<Para><XRef Linkend="ABCodingModal">
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem Id="H.CNCP.item.23">
|
|
<Para><XRef Linkend="ABCodingNonModal">
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
</Step>
|
|
</Procedure>
|
|
<Sect2 Id="ABCodingModal">
|
|
<Title>Coding for Modal Messages</Title>
|
|
<Para>As explained above, if a message is to be displayed modally, use
|
|
<ComputerOutput>dtb_show_modal_message()</ComputerOutput>. This routine returns
|
|
a value which indicates which message box button the user has pressed.
|
|
The value is an <ComputerOutput>enum</ComputerOutput> that is defined in
|
|
<ComputerOutput>dtb_utils.h</ComputerOutput>:</Para>
|
|
<LiteralLayout>/*
|
|
* Returns answer value for modal MessageBox
|
|
*/
|
|
typedef enum {
|
|
DTB_ANSWER_NONE,
|
|
DTB_ANSWER_ACTION1,
|
|
DTB_ANSWER_ACTION2,
|
|
DTB_ANSWER_ACTION3,
|
|
DTB_ANSWER_CANCEL,
|
|
DTB_ANSWER_HELP
|
|
} DTB_MODAL_ANSWER;
|
|
</LiteralLayout>
|
|
<Para>You can then examine the return value (for example via a switch
|
|
statement) and execute the appropriate piece of code.</Para>
|
|
<Para>Here's an example of displaying a message modally. Say that you have
|
|
created a simple application, named <ComputerOutput>foo</ComputerOutput>. The
|
|
project is named <ComputerOutput>foo.bip</ComputerOutput> and consists of one
|
|
module, <ComputerOutput>foo.bil</ComputerOutput>. The module
|
|
<ComputerOutput>foo.bil</ComputerOutput> consists of a main window, control pane,
|
|
and two text fields, one for the user to enter a person's first name
|
|
and the other to enter the last name. If the user types digits, an
|
|
error message should be posted, informing the user that digits are not
|
|
allowed, and giving the user a couple of options. The user can start
|
|
over, which means the text entered will be erased, or the user can
|
|
continue, which means that the text entered will be left intact,
|
|
giving the user discretion as to how to modify the text.</Para>
|
|
<Para>A call-function connection is made for both text fields, which will
|
|
be called each time the user types something. The function for the
|
|
first text field will check if the character typed is a digit. If so,
|
|
it will post the error message modally:</Para>
|
|
<LiteralLayout>void
|
|
verify_first_nameCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData
|
|
)
|
|
{
|
|
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
|
|
char *text = (char *)NULL;
|
|
int textlen = 0;
|
|
DTB_MODAL_ANSWER answer = DTB_ANSWER_NONE;
|
|
DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
|
|
|
|
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
|
|
|
|
text = XmTextFieldGetString(widget);
|
|
if ((text != NULL) && (*text != NULL))
|
|
{
|
|
textlen = strlen(text);
|
|
if (isdigit(text[textlen-1]))
|
|
{
|
|
dtb_foo_message_initialize(&dtb_foo_message);
|
|
answer = dtb_show_modal_message(instance->textfield,
|
|
&dtb_foo_message, NULL, NULL, NULL);
|
|
switch (answer)
|
|
{
|
|
case DTB_ANSWER_ACTION1: /* Start Over */
|
|
XmTextFieldSetString(widget, "");
|
|
break;
|
|
|
|
case DTB_ANSWER_ACTION2: /* Continue */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
|
|
}
|
|
</LiteralLayout>
|
|
<Procedure>
|
|
<Title>See Also</Title>
|
|
<Step>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.24">
|
|
<Para><XRef Linkend="ABCodingNonModal">
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
</Step>
|
|
</Procedure>
|
|
</Sect2>
|
|
<Sect2 Id="ABCodingNonModal">
|
|
<Title>Coding for Non-Modal Messages</Title>
|
|
<Para>If you want to post a non-modal message, you should use
|
|
<ComputerOutput>dtb_show_message()</ComputerOutput>. The callbacks for the
|
|
message box buttons should be specified via the Connections Editor, as
|
|
described in <XRef Linkend="ABConnectMessage">. The buttons that are specified
|
|
for the message box are displayed as When items for the message
|
|
object in the Connections Editor.</Para>
|
|
<Para>Using the same example as above, make the last name text field display
|
|
the error message non-modally if the user types a digit. As
|
|
previously mentioned, first you'll need to make a couple of
|
|
call-function connections for the two buttons in the message box,
|
|
labelled "Start Over" and "Continue." When code is generated,
|
|
add code to those routines to do the right thing. The start
|
|
over routine will clear out the text field and the continue routine
|
|
will do nothing, in this case.</Para>
|
|
<LiteralLayout>void
|
|
verify_last_nameCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData
|
|
)
|
|
{
|
|
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
|
|
char *text = (char *)NULL;
|
|
int textlen = 0;
|
|
DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
|
|
|
|
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
|
|
|
|
text = XmTextFieldGetString(widget);
|
|
if ((text != NULL) && (*text != NULL))
|
|
{
|
|
textlen = strlen(text);
|
|
if (isdigit(text[textlen-1]))
|
|
{
|
|
dtb_foo_message_initialize(&dtb_foo_message);
|
|
dtb_show_message(instance->textfield,
|
|
&dtb_foo_message, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
|
|
}
|
|
|
|
|
|
void
|
|
start_overCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData
|
|
)
|
|
{
|
|
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
|
|
|
|
DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
|
|
|
|
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
|
|
|
|
XmTextFieldSetString(dtb_foo_mainwindow.textfield2, "");
|
|
|
|
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
|
|
}
|
|
|
|
|
|
void
|
|
continueCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData
|
|
)
|
|
{
|
|
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
|
|
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
|
|
|
|
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
|
|
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
|
|
}
|
|
</LiteralLayout>
|
|
<Para>The two routines above, <ComputerOutput>start_overCB()</ComputerOutput> and
|
|
<ComputerOutput>continueCB()</ComputerOutput>, are added as callbacks for the two
|
|
buttons via the call to <ComputerOutput>dtb_show_message()</ComputerOutput>. Here
|
|
is the code fragment that adds the callback (from
|
|
<ComputerOutput>dtb_utils.c</ComputerOutput>):</Para>
|
|
<LiteralLayout>/* Add Callbacks if necessary */
|
|
if (mbr->action1_callback != (XtCallbackProc) NULL)
|
|
XtAddCallback(msg_dlg, XmNokCallback, mbr->action1_callback, NULL);
|
|
if (mbr->cancel_callback != (XtCallbackProc) NULL)
|
|
XtAddCallback(msg_dlg, XmNcancelCallback, mbr->cancel_callback,
|
|
NULL);
|
|
if (mbr->action2_callback != (XtCallbackProc) NULL)
|
|
{
|
|
action_btn = dtb_MessageBoxGetActionButton(msg_dlg, DTB_ACTION2_BUTTON);
|
|
if (action_btn != NULL)
|
|
XtAddCallback(action_btn, XmNactivateCallback,
|
|
mbr->action2_callback, NULL);
|
|
}
|
|
if (mbr->action3_callback != (XtCallbackProc) NULL)
|
|
{
|
|
action_btn = dtb_MessageBoxGetActionButton(msg_dlg, DTB_ACTION3_BUTTON); if (action_btn != NULL)
|
|
XtAddCallback(action_btn, XmNactivateCallback,
|
|
mbr->action3_callback, NULL);
|
|
}
|
|
</LiteralLayout>
|
|
<Para>The structure <ComputerOutput>mbr</ComputerOutput> contains all the necessary
|
|
information for the message. The structure is filled in with the
|
|
values specified in the Message Editor when the message object was
|
|
created via the
|
|
<ComputerOutput>dtb_<modulename>_<messagename>_initialize()</ComputerOutput>
|
|
routine -- in this example,
|
|
<ComputerOutput>dtb_foo_message_initialize()</ComputerOutput>.</Para>
|
|
<Procedure>
|
|
<Title>See Also</Title>
|
|
<Step>
|
|
<ItemizedList Mark="•" Role="tight">
|
|
<ListItem Id="H.CNCP.item.25">
|
|
<Para><XRef Linkend="ABCodingModal">
|
|
</Para>
|
|
</ListItem>
|
|
</ItemizedList>
|
|
</Step>
|
|
</Procedure>
|
|
</Sect2>
|
|
</Sect1>
|
|
<Sect1 Id="ABAboutAttachments">
|
|
<Title>About Attachments</Title>
|
|
<Para>Attachments (and groups, which are based on attachments) establish
|
|
dynamic layout behavior for objects in the interface. Dynamic layout
|
|
behavior ensures that objects will maintain consistent relationships
|
|
during resize activities. Attachments enable an internationalized
|
|
application to work well in a number of locales.
|
|
All child objects are attached by their top and left edges to the top
|
|
and left edge of their parent object, by default. Thus a control pane
|
|
dropped on a main window is attached by its left and top edges to the
|
|
left and top edges of the main window. Similarly, a button dropped on
|
|
the control pane is attached to the control pane.</Para>
|
|
<Para>If the parent object is resized in an upward or leftward direction,
|
|
the child object moves with the parent, maintaining the distance from
|
|
the top and left edge of the parent.</Para>
|
|
<Para>If a pane object is dropped on the top or left edge of its parent it
|
|
will be attached to that edge with an offset of 0. If it is dropped
|
|
some distance to the right and below the left and top edges of its
|
|
parent, it will have positive offsets.</Para>
|
|
<Para>If a pane object is resized from its right and bottom edges so that it
|
|
spans its parent object, it will be attached to the right and bottom
|
|
edges of its parent.</Para>
|
|
<Procedure>
|
|
<Title>Attachment Example: Custom Dialog</Title>
|
|
<Step>
|
|
<Para>See an App Builder custom dialog object for an example of attachments.
|
|
Each of the buttons at the bottom of the custom dialog are attached to
|
|
the top and sides of their enclosing dialog panel. They are attached
|
|
five pixels from the top of the panel and varying percentages from the
|
|
left edge of the panel (Button1 left edge 10%, right edge 30%; Button2
|
|
40% and 60%; Button3 70% and 90%).</Para>
|
|
<Para>The left edge of Button1 will always be 10% from the edge of the panel
|
|
and the right edge of Button1 will always be 30% from the edge of the
|
|
panel. Button1 will, therefore, always be as wide as 20% of the total
|
|
width of the panel. Button2's edges are 40% and 60% from the left edge
|
|
of the panel; Button3's edges are 70% and 90% from the left edge of
|
|
the panel. The three buttons will grow and shrink as the panel grows
|
|
and shrinks, and the distance between them will always be 10% of the
|
|
total width of the panel.</Para>
|
|
<!-- EOF: Concepts -->
|
|
</Step>
|
|
</Procedure>
|
|
</Sect1>
|
|
</Chapter>
|
|
<!--fickle 1.15 help-to-docbook 1.4 01/17/96 17:37:35-->
|