\begindata{text,538373940} \textdsversion{12} \template{default} \define{global

\begindata{text,538373940}
\textdsversion{12}
\template{default}
\define{global
}
\define{itemize
}
\define{programexample
}
\formatnote{\chapter{Example 5:
Menus}} \indexi{Menus}
Example 5 illustrates how to create an object that has menus.
Toolkit provides two classes--\italic{Menulist}
The Andrew
\indexi{Menulist} \indexi{Class++Menulist}
and \italic{Bind} \indexi{Bind} \indexi{Class++Bind} --that together
allow
objects to bind lists of menus to command procedures.
The example program in this section will build upon the program in
Example 4.
Like Example 4, this program draws \italic{hello world} initially at the
center of the window; if the user clicks on the left mouse button, the
program
draws \italic{hello world} centered at the location of the mouse cursor
when
the user lets up on the button, if the user clicks on the right mouse
button,
the string may be dragged around the screen. Like Example 4, the program
also
responds to two keys: Ctrl-c to center \italic{hello world}, and Ctrl-i
to
invert the screen. In addition, the program posts a new menu card
entitled
\bold{Hello World} with two menu items, \bold{Center} and \bold{Invert}.
If
the user pops-up the \bold{Hello World} menu card and chooses
\bold{Center},
the program centers \italic{hello world} in the window; if the user
chooses
the menu item \bold{Invert}, the program inverts the screen, from white
to
black and black to white.
The discussion that follows presents a step-by-step description of how to
modify the \italic{helloworldview} class in Example 4 to produce Example
5.
If you were to follow the steps, you would produce a program, called
\italic{helloworldapp}, in five files:
\itemize{
a hellov.ch file -- will contain the class definition for
\italic{helloworldview}. It will be exactly the same as Example 4 with
the
addition of an extra data declaration for a menu list.
a hellov.c file -- will contain statements that import Andrew Toolkit
classes
and define the object's methods and class procedures. We will add to
Example
4's class procedure for initializing a menulist and for binding menu
items to
command procedures.
a helloa.ch file -- will contain the class definition for the application
program that will display an instance of the class in a window. This
will be
exactly the same as in Example 4.
a helloa.c -- will contain declarations needed by the Andrew Toolkit
linking
and loading facilities as well the definition of the
\italic{helloworldview}
application method. This will be exactly the same as in Example 4.
Makefile -- will contain the directions for compiling, linking and
loading.
This will be exactly the same as Example 4.
}
For a complete listing of these files, see \italic{Program listing for
Example
5} at the end of this section on p.
\begindata{textref,539236104}
\textdsversion{12}
# ExFiveListing\
\enddata{textref,539236104}
\view{textrefv,539236104,910,0,0}. The source code is available in the
directory /usr/andrew/examples/ex5.
Although the discussion of the steps refers directly to this example, the
information generally applies to the creation of any class that will
create
menus.
\begindata{bp,538929032}
\enddata{bp,538929032}
\view{bpv,538929032,911,0,0}
\section{Running the example program}
\formatnote{\bold{Action 1.}\formatnote{
program, at
the \bold{command }prompt type
} \formatnote{To run the
runapp /usr/andrew/examples/ex5/helloa
and press the Enter key.
}
\bold{Response.}\formatnote{
\italic{hello world}
}The program will produce a window with
centered in the body of the window.
\bold{Action 2.} \formatnote{
window,
position the
}To move \italic{hello world} in the
mouse cursor within the program's window, click with the left mouse
button, or
click on the right mouse button, and drag the mouse.
\bold{Response. }\formatnote{
wherever
you release the mouse button.
} \italic{hello world} will be drawn
\bold{Action 3.}\formatnote{
}To use the menus to center \italic{hello
world}, position the mouse cursor within the program's window, pop up the
menus, and choose \bold{Center}
from the \bold{Hello World} menu card.
\bold{Response. }\formatnote{
the
center of the window.
} \italic{hello world} will be drawn in
\bold{Action 4.}\formatnote{
up the
menus and
}To invert the drawing, using menus, pop
choose \bold{Invert} from the \bold{Hello World} card.
\bold{Response.}\formatnote{
case, it
will change
}The background will invert.
In this
from white to black.
\bold{Action 5.}\formatnote{
choose \bold{Quit}
}To quit the program, pop-up the menus and
from the top card.
\bold{Response.} \formatnote{
screen.
}The program will disappear from the
}
\begindata{bp,538929288}
\enddata{bp,538929288}
\view{bpv,538929288,912,0,0}
\section{Overview of menu lists} \indexi{Menus++Menu lists}
Menu lists provide stacks of menu cards that a user can pop-up within the
body
of your program's windows. Each menu list corresponds to one stack of
menu
cards. Your program can have only one stack of menu cards per window,
but can
have any number of stacks that it posts at different times. There can be
any
number of cards in a stack.
Each card in the stack can have a title and any number of menu items. If
you
use the methods that \italic{menulist} and \italic{bind} provide to bind
a
menu item to a command procedure, then when the user chooses that menu
item,
the \italic{Interaction Manager} will invoke the procedure. For example,
if
you bind the menu item \bold{Save} to the procedure
\italic{Write_Buffer_to_File}, then when the user chooses the menu item
\bold{Save}, the \italic{Interaction Manager} will invoke
\italic{Write_Buffer_to_File}.
The Andrew Toolkit class \italic{Menulist} provides methods for adding
menu
items to a card or deleting them, and for deleting all the cards from the
stack of menu cards.
\subsection{Menu chains} \indexi{Menus++Chains}
\indexi{Menus++Priority}
In the Andrew Toolkit, an object can contain other objects. Since an
object
may not know what other objects it will contain in advance, there must be
a
protocol that allows objects to coordinate the menu items that each
object may
add or delete from the stack of menus. For example, if a multi-media
editor
containing a drawing editor both add the menu item \bold{Quit}, there
must be
a way to decide which menu item takes priority. \italic{Menu chains}
establish the priority of menu items.
Menu chains work according to the following protocol: Each object posts
the
menus that it wants. If the object is contained in another object, the
parent
object determines the placement of the child's menu list in a menu chain.
If a menu list \italic{ml}\italic{\subscript{j }}occurs after the menu
list
\italic{ml}\italic{\subscript{i}} in the menu chain, then
\italic{ml}\italic{\subscript{j}}'s menus take precedence over
\italic{ml}\subscript{\italic{j}}'s. Thus, a parent object can decide
that
its menus should have precedence over its child's menus, or that its
child's
menus should have precedence. The usual way to decide precedence is
based on
input focus: the menus of the object with the input focus should have
precedence.
\subsection{Flow of control for menus} \indexi{Menus++Flow of control}
An object will normally define its menus when it is first loaded.
this
In
case, the object's class procedure, \italic{InitializeClass}, will create
a
menu list and add its menu items to the menus. Normally, the object will
create all the menu lists it will ever use. At this point, the menu
items are
defined, but they are not yet visible to the user.
Whenever an instance of the class is created, its
\italic{InitializeObject}
method should normally not define the menus, but should
\italic{duplicate} the
menus of its class in order to save space. \indexi{Menus++Duplication}
Most application programs start up by creating a set of views and asking
the
\italic{Interaction Manager} to make one of the views the input focus. A
user
can request a view to make itself the input focus by clicking in its
visual
rectangle. If a view wishes to respond to such user requests, it should
request the \italic{Interaction Manager} to give it the input focus upon
receiving the \italic{DownTransition} in its \italic{Hit} method.
When an object receives the input focus, it should post the
\italic{menulist}
that it wants to have displayed to the user. If the object does not want
menus, it should post a \smaller{NULL} menulist so that its parent menus
are
posted.
When a child posts menus, its parent's \italic{post menu} method is
called.
If a parent object wants to control which menus appear, it should save
all
its children's menu lists when it creates the children. After the parent
has
created all its children, it should create its own menu list, and chain
its
children's menu lists into the menu chain according to the priority it
desires. Then, in its own \italic{post menu} method, it should post the
chained list. The menu list that the top-most object posts defines the
complete set of menu items that can be displayed to the user.
\section{Modifying the class definition}
\subsection{Declaring the class}
If you are creating a subclass of view that will have menus, you must add
a
pointer to a menulist structure to the class's data definition.
For example, the following is the new class declaration for the example
class
\italic{helloworldview}:
\programexample{
class helloworldview[hellov] : view \{ overrides:
FullUpdate(enum view_UpdateType type, long left, long top, long
width,
long height);
Update();
Hit (enum view_MouseAction action, long x, long y, long
numberOfClicks)
returns struct helloworldview *;
ReceiveInputFocus();
LoseInputFocus();
classprocedures:
InitializeClass() returns boolean;
data:
\bold{struct menulist *menulist;}
struct keystate *keystate;
long x,y;
boolean blackOnWhite;
boolean newBlackOnWhite;
long distX,distY;
long newX, newY;
boolean HaveDownTransition;
boolean haveInputFocus;
\};
}
Everything is the same as Example 4, except for the data declaration
\italic{struct menulist *menulist}. \italic{helloworldview} will store
its
menu list in \italic{menulist}.
Note that any class that uses menus must also override
\italic{ReceiveInputFocus} and \italic{LoseInputFocus}.
\subsection{Describing the menus}
\indexi{Menus++Description}
\indexi{Bind description}
The description of the menus should be stored in a \smaller{NULL}
terminated
array of \italic{struct bind_Description}. The structure of a bind
description array is described in detail in Example 4. Each entry in the
array should be a description of a single menu item binding.
For example, the two menu items for helloworldview are described by the
following array, \italic{helloworldviewBindings}, in \italic{hellov.c}:
\programexample{
static struct bind_Description helloworldviewBindings[]=\{
\{"helloworld-center", "\\003",0,\bold{ "Hello World,Center",}0,0,
Center,
"Center the helloworld string."\\\},
\{"helloworld-invert", "\\011",0, \bold{"Hello World,Invert",}0,0,
Invert,
"Invert the helloworld string."\},
NULL \};
}
The first entry in the array describes the binding of the menu item
\indexi{Menus++Cards}
\bold{Center} on the menu card \bold{Hello World} to the procedure
\italic{Center}. The item in the first entry, \italic{"helloworldcenter,"} is
the user invocation name, discussed in Example 4. The next two items,
"\\003",0, are the keyboard descriptions (again, see Example 4). These
could
be \smaller{NULL},0 if you did not want key bindings at all.
The next item, \italic{"Hello World, Center"},
part
is the menu string.
The
before the comma, \italic{Hello World,} specifies the menu card and the
part
after the comma, \italic{Center,} specifies the menu item. If no card
name
appears, menu items will appear on the front menu card. The menu items
are
listed on a card in the order they are added to the menu list and without
blank lines between the menu items. Cards are stacked in the order in
which
they are posted. More complicated menu string formats allow you to
control
the order and spacing of menu items on the cards) and the stacking of
cards.
The next item, 0, represents the data to be passed to the procedure upon
the
user selecting the menu item \bold{Center}; in this example, none. The
next
item, 0, is the menu mask; again, in this example, none.
The remaining items are the same as Example 4. Likewise, the second
entry in
the array binds the menu item \bold{Invert} on the card \bold{Hello
World} to
the procedure \italic{Invert}. The third entry in the array is
\smaller{NULL}
and indicates the end of the description of the bindings.
When you run the program and pop-up the menus, you will find that the
menu
card "Hello World" is the second card in the stack of menus. The first
card
will be unnamed, and will have the menu item \bold{Quit} on it. The
first
card is posted by the \italic{Interaction Manger}, \italic{im},
\italic{helloworldview's} parent in the view tree.
\indexi{Interaction manager++Menus}
\indexi{Menus++Quit option}
Parents in the view tree can choose to override menus that a child posts
or
add to those menus. Normally, parents give precedence to the menus of
the
view with the input focus.
The actual command functions, \italic{Center} and \italic{Invert} were
discussed previously in Example 4. They remain exactly the same.
\subsection{Creating the menu list for the class} \indexi{Menu
list++Creating}
\indexi{ \italic{InitializeClass}}
\indexi{Class++Initializing}
A \italic{menulist} for the class represents the set of bindings from the
menu
items to the functions to be performed. The same \italic{menulist} can
normally be shared among all instances of a view. Thus, like
\italic{keymap},
a \italic{menulist} should be created in \italic{InitializeClass}, a
class
procedure that is called only once--the first time the class is loaded.
Likewise, the structure declaration for the \italic{menulist} can be
done in
the module rather than in the class data.
In general, to create menus, you should declare an
\italic{InitializeClass}
procedure that creates a new \italic{menulist} and associates the menu
bindings for the class with the newly created \italic{menulist}.
For example, the following creates a \italic{menulist} and associates the
\italic{menulist} with the menu descriptions for the view
\italic{helloworldview} in the file \italic{hellov.c}:
\programexample{
\bold{static struct menulist *helloworldviewMenulist;}
boolean helloworldview__InitializeClass(classID)
struct classheader *classID;
\{
\bold{helloworldviewMenulist=menulist_New();}
helloworldviewKeymap=keymap_New();
bind_BindList(helloworldviewBindings,
helloworldviewKeymap,\bold{helloworldviewMenulist,}&helloworldview_classi
nfo);
return TRUE;
}
\}
The statement \italic{static struct menulist *helloworldviewMenulist}
declares
the menulist structure for this class. The statement
\italic{helloworldviewMenulist=menulist_New()} creates a new menulist and
stores it in \italic{helloworldviewMenulist}. The statement
\italic{bind_BindList (helloworldviewBindings, helloworldviewKeymap,
helloworldviewMenulist, &helloworldview_classinfo)} associates the menu
descriptions in \italic{helloworldviewBindings} with the newly create
menulist, \italic{helloworldviewMenulist}. The method
\italic{bind_BindList}
is described in Example 4. The second parameter,
\italic{helloworldviewKeymap}
could be \smaller{NULL} for a class with no key bindings.
If you are creating a subclass of view and your application requires
dynamic
menu items, then you can create multiple menu lists for the class;
alternatively, you can use menu masks.
\subsection{Duplicating the menu list for the object}
\indexi{Menus++Duplicating}
Most objects in the same class can share menus. To share menus, when an
instance of an object is created, its \italic{InitializeObject}
\indexi{Objects++Initializing}
\indexi{ \italic{InitializeObject}} method should not create the menus,
but
should duplicate the menus of its class. The duplicated menus should be
stored as part of the view's data for later use in
\italic{ReceiveInputFocus}.
In addition, a view with menus should set a flag in its
\italic{InitializeObject} method to indicate that it does not have the
input
focus.
The following \italic{InitializeObject} method, in \italic{hellov.c},
creates
a \italic{menulist} for the object by duplicating the one for the class
and
associates the \italic{menulist} for the class,
\italic{helloworldviewMenulist}, with \italic{hwv}, an instance of the
view
\italic{helloworldview}:
\programexample{
boolean helloworldview__InitializeObject(hwv)
struct helloworldview *hwv;
\{
hwv->x = POSUNDEF;
hwv->y = POSUNDEF;
hwv->blackOnWhite = TRUE;
hwv->newBlackOnWhite = TRUE;
hwv->HaveDownTransition = FALSE;
hwv->keystate = keystate_Create(hwv, helloworldviewKeymap);
\bold{hwv->menulist = menulist_DuplicateML(helloworldviewMenulist,
hwv);}
hwv->haveInputFocus = FALSE;
return TRUE;
\}
}
The statement \italic{hwv->menulist =
menulist_DuplicateML(helloworldviewMenulist, hwv)} creates a duplicate of
the
class helloworldview's \italic{menulist},
\italic{helloworldviewMenulist},
associates the \italic{menulist} with the view, \italic{hwv}, and stores
a
pointer to the newly duplicated \italic{menulist} in \italic{hwv>menulist}.
The remaining statements are as in Example 4.
\subsection{User requests for the input focus}
\indexi{Input focus++Requesting}
\indexi{Menus++Input focus}
By convention, a user can request a \italic{view} to make itself the
input
focus by clicking within its space on the screen. If a \italic{view}
wishes
to respond to such user requests, it should request the
\italic{Interaction
Manager} to give it the input focus upon receiving the
\italic{DownTransition}
in its \italic{Hit} method. Normally, if you are building a
\italic{view}
that will have menus, then in the \italic{view}'s \italic{Hit} method,
you
should request the input focus by calling \italic{WantInputFocus}. In
Example
5, the \italic{helloworldview_Hit} method does not need to be modified
from
Example 4, since it requests the input focus in order to do keyboard
input.
\paragraph{Receiving the input focus}
\indexi{Input focus++Receiving}
When the \italic{Interaction Manager} gives a view the input focus, it
notifies the view by calling a method, \italic{ReceiveInputFocus}. If
you are
writing a view that has menus, its \italic{ReceiveInputFocus} method must
first set a flag that indicates it has the input focus. In general, you
will
need to write other methods (\italic{e.g.}, Hit, Update, etc.) so that
they
test this flag and act accordingly (see Example 4).
Second, the view should post its \italic{menulist} to its parent. The
\italic{menulist} provides the \italic{Interaction Manager} with the
information it needs to post menus appropriately for the view.
The following, in \italic{hellov.c}, is the \italic{ReceiveInputFocus}
method
for this example:
\programexample{
void helloworldview__ReceiveInputFocus(hwv)
struct helloworldview *hwv;
\{
hwv->haveInputFocus = TRUE;
hwv->keystate->next = NULL;
helloworldview_PostKeyState(hwv, hwv->keystate);
\bold{helloworldview_PostMenus(hwv, hwv->menulist);}
\}
}
The statement \italic{hwv->haveInputFocus = \smaller{TRUE}} sets a flag
to
indicate that \italic{hwv} has the input focus. The statement
\italic{helloworldview_PostMenus (hwv, hwv->menulist)} posts the
\italic{menulist} \italic{hwv->menulist} for \italic{hwv} to the
\italic{Interaction Manager}.
If you are creating a view that is overriding view's
\italic{ReceiveInputFocus}
method, even if your view does not have a \italic{menulist }it should
post a
\italic{menulist} of \smaller{NULL.}
\paragraph{Losing the input focus} \indexi{Input focus++Losing}
When the \italic{Interaction Manager} takes the input focus
view,
it notifies the view by calling \italic{LoseInputFocus}. A
\italic{LoseInputFocus} method should set a flag indicating
longer
has the input focus, then do whatever it needs to do before
input
focus.
away from a
view's
that it no
losing the
The following \italic{LoseInputFocus} method for Example 5 is exactly the
same
as Example 4:
\programexample{
void helloworldview__LoseInputFocus(hwv)
struct helloworldview *hwv;
hwv->haveInputFocus = FALSE;
\{
\}
}
\subsection{Requesting the input focus upon start-up}
If you are creating an application that has menus and you want the menus
to
appear immediately, then it should request the input focus after putting
the
object in the view tree and before entering the keyboard processor
interaction
loop. If the input focus is not requested, the menus will not appear
until
the first call to \italic{FullUpdate}, which occurs after a mouse action.
To request the input focus immediately upon start-up, you must include
the
WantInputFocus statement as you did in the previous example in helloa.c,
right
after the im_SetView statement.
\subsection{Importing Andrew Toolkit procedures}
\indexi{Importing}
\programexample{
#include <class.h> #include "hellov.eh"
#include "graphic.ih" #include "rect.ih" #include "keymap.ih" #include
"keystate.ih" #include "bind.ih" \bold{#include "menulist.ih"}
}
The import/export declarations are exactly the same as in the previous
example, with the addition of \italic{menulist.ih} to import the menu
list
methods.
\begindata{bp,538929224}
\enddata{bp,538929224}
\view{bpv,538929224,913,0,0}
\begindata{texttag,539315976}
\textdsversion{12}
ExFiveListing\
\enddata{texttag,539315976}
\view{texttagv,539315976,914,0,0}
\section{Program listing for Example 5}
\formatnote{
\bold{hellov.ch}
class helloworldview[hellov]: view \{
overrides:
FullUpdate(enum view_UpdateType type, long left, long top, long
width,
long height);
Update();
Hit (enum view_MouseAction action, long x, long y, long
numberOfClicks)
returns struct view *;
ReceiveInputFocus();
LoseInputFocus();
classprocedures:
InitializeClass() returns boolean;
data:
struct menulist *menulist;
struct keystate *keystate;
boolean HaveDownTransition;
boolean haveInputFocus;
long x,y;
long distX,distY;
boolean blackOnWhite;
long newX,newY;
boolean newBlackOnWhite;
\};
\bold{hellov.c}
#include <class.h>
#include "hellov.eh"
#include "graphic.ih"
#include "rect.h"
#include "keymap.ih"
#include "keystate.ih"
#include "menulist.ih"
#include "bind.ih"
#define POSUNDEF -1
static struct keymap *helloworldviewKeymap;
static struct menulist *helloworldviewMenulist;
boolean helloworldview__InitializeObject(classID, hwv)
struct classheader *classID;
struct helloworldview *hwv;
\{
hwv->x = POSUNDEF;
hwv->y = POSUNDEF;
hwv->HaveDownTransition = FALSE;
hwv->haveInputFocus = FALSE;
hwv->keystate = keystate_Create(hwv, helloworldviewKeymap);
hwv->blackOnWhite = TRUE;
hwv->newBlackOnWhite = TRUE;
hwv->menulist = menulist_DuplicateML(helloworldviewMenulist, hwv);
return TRUE;
\}
void helloworldview__FullUpdate(hwv, type, left, top, width, height)
struct helloworldview *hwv;
enum view_UpdateType type;
long left;
long top;
long width;
long height;
\{
struct rectangle myVisualRect;
helloworldview_GetVisualBounds(hwv,&myVisualRect);
if (hwv->x == POSUNDEF) \{
hwv->x = rectangle_Left(&myVisualRect) +
rectangle_Width(&myVisualRect) / 2;
hwv->y = rectangle_Top(&myVisualRect) +
rectangle_Height(&myVisualRect) / 2;
hwv->newX = hwv->x;
hwv->newY = hwv->y;
\}
else \{
hwv->x = hwv->newX;
hwv->y = hwv->newY;
\}
helloworldview_SetTransferMode(hwv, graphic_COPY);
if (hwv->blackOnWhite)
helloworldview_FillRect(hwv, &myVisualRect,
helloworldview_WhitePattern(hwv));
else
helloworldview_FillRect(hwv, &myVisualRect,
helloworldview_BlackPattern(hwv));
helloworldview_SetTransferMode(hwv, graphic_INVERT);
helloworldview_MoveTo(hwv, hwv->x, hwv->y);
helloworldview_DrawString(hwv,"hello world",
graphic_BETWEENTOPANDBASELINE |
graphic_BETWEENLEFTANDRIGHT);
\}
void helloworldview__Update(hwv)
struct helloworldview *hwv;
\{
/* TransferMode is graphic_INVERT from the last FullUpdate */
if (hwv->newBlackOnWhite != hwv->blackOnWhite)
\{
struct rectangle vr;
helloworldview_GetVisualBounds(hwv,&vr);
helloworldview_FillRect(hwv, &vr,
helloworldview_BlackPattern(hwv));
hwv->blackOnWhite = hwv->newBlackOnWhite;
\}
if (hwv->newX != hwv->x || hwv->newY != hwv->y) \{
helloworldview_MoveTo(hwv, hwv->x, hwv->y);
helloworldview_DrawString(hwv, "hello world",
graphic_BETWEENTOPANDBASELINE |
graphic_BETWEENLEFTANDRIGHT);
hwv->x = hwv->newX;
hwv->y = hwv->newY;
helloworldview_MoveTo(hwv, hwv->x, hwv->y);
helloworldview_DrawString(hwv, "hello world",
graphic_BETWEENTOPANDBASELINE |
graphic_BETWEENLEFTANDRIGHT);
\}
\}
struct view *helloworldview__Hit(hwv, action, x, y, numberOfClicks)
struct helloworldview *hwv;
enum view_MouseAction action;
long x;
long y;
long numberOfClicks;
\{
if(hwv->HaveDownTransition)
switch(action)\{
case view_RightUp:
hwv->HaveDownTransition=FALSE;
/* fall through */
case view_RightMovement:
hwv->newX=x-hwv->distX;
hwv->newY=y-hwv->distY;
break;
case view_LeftUp:
hwv->HaveDownTransition=FALSE;
hwv->newX=x;
hwv->newY=y;
break;
case view_LeftMovement:
/* do nothing */
break;
default:
/* re-synchronize mouse */
hwv->HaveDownTransition=FALSE;
\}
if(!hwv->HaveDownTransition)
switch(action)\{
case view_RightDown:
hwv->distX=x-hwv->x;
hwv->distY=y-hwv->y;
/* fall through */
case view_LeftDown:
hwv->HaveDownTransition=TRUE;
helloworldview_WantInputFocus(hwv,hwv);
break;
\}
helloworldview_WantUpdate(hwv,hwv);
return (struct view *)hwv;
\}
void helloworldview__ReceiveInputFocus(hwv)
struct helloworldview *hwv;
\{
hwv->haveInputFocus = TRUE;
hwv->keystate->next = NULL;
helloworldview_PostKeyState(hwv, hwv->keystate);
helloworldview_PostMenus(hwv, hwv->menulist);
\}
void helloworldview__LoseInputFocus(hwv)
struct helloworldview *hwv;
\{
hwv->haveInputFocus = FALSE;
\}
static void Center(hwv, rock)
struct helloworldview *hwv;
long rock;
\{
struct rectangle myVisualRect;
helloworldview_GetVisualBounds(hwv,&myVisualRect);
hwv->newX = rectangle_Left(&myVisualRect) +
rectangle_Width(&myVisualRect)
/ 2;
hwv->newY = rectangle_Top(&myVisualRect) +
rectangle_Height(&myVisualRect)
/ 2;
helloworldview_WantUpdate(hwv, hwv);
\}
static void Invert(hwv, rock)
struct helloworldview *hwv;
long rock;
\{
hwv->newBlackOnWhite = ! hwv->newBlackOnWhite;
helloworldview_WantUpdate(hwv, hwv);
\}
static struct bind_Description helloworldviewBindings[]=\{
\{"helloworld-center", "\\003",0, "Hello World,Center",0,0, Center,
"Center the helloworld string."\},
\{"helloworld-invert", "\\011",0, "Hello World,Invert",0,0, Invert,
"Invert the helloworld string."\},
NULL
\};
boolean helloworldview__InitializeClass(classID)
struct classheader *classID;
\{
helloworldviewMenulist=menulist_New();
helloworldviewKeymap=keymap_New();
bind_BindList(helloworldviewBindings,
helloworldviewKeymap,helloworldviewMenulist,
&helloworldview_classinfo);
return TRUE;
\}
\bold{helloa.ch}
class helloworldapp[helloa] : application[app]\{
overrides:
Start() returns boolean;
\};
\bold{helloa.c}
#include <class.h>
#include "helloa.eh"
#include "im.ih"
#include "hellov.ih"
boolean helloworldapp__Start(hwapp)
struct helloworldapp *hwapp;
\{
struct helloworldview *hwv;
struct im *im;
if(!super_Start(hwapp))
return FALSE;
hwv=helloworldview_New();
if(hwv==NULL)
return FALSE;
im=im_Create(NULL);
if(im==NULL)\{
helloworldview_Destroy(hwv);
return FALSE;
\}
im_SetView(im,hwv);
helloworldview_WantInputFocus(hwv,hwv);
return TRUE;
\}
\bold{Makefile}
SRCDIR=/usr/andrew/
INCLUDES= -I. -I$\{SRCDIR\}include/atk -I$\{SRCDIR\}include
INCLUDESRC = $\{SRCDIR\}include/atk
CC=cc
DEBUG = -g
TOOLS = $\{SRCDIR\}bin/
CFLAGS= $\{DEBUG\} $\{INCLUDES\}
CLASSFLAGS=$\{INCLUDES\}
MAKEDO = $\{TOOLS\}makedo $\{DEBUG\} -b $\{TOOLS\} -d $\{SRCDIR\}lib
CLASS = $\{TOOLS\}class
.SUFFIXES: .ih .eh .ch .do
.ch.ih:
$\{CLASS\} $\{CLASSFLAGS\} $*.ch
.ch.eh:
$\{CLASS\} $\{CLASSFLAGS\} $*.ch
.o.do:
$\{MAKEDO\} $<
all:
helloa.do hellov.do
helloa.do: helloa.o helloa.eh
hellov.do: hellov.o hellov.eh
helloa.o: helloa.c
helloa.o: $\{INCLUDESRC\}/app.ih
helloa.o: $\{INCLUDESRC\}/graphic.ih
helloa.o: $\{INCLUDESRC\}/im.ih
helloa.o: $\{INCLUDESRC\}/observe.ih
helloa.o: $\{INCLUDESRC\}/point.h
helloa.o: $\{INCLUDESRC\}/rect.h
helloa.o: $\{INCLUDESRC\}/view.ih
helloa.o: $\{SRCDIR\}include/class.h
helloa.o: hellov.ih
helloa.o: helloa.eh
helloa.eh helloa.ih: helloa.ch
helloa.eh helloa.ih: $\{INCLUDESRC\}/app.ih
hellov.o: hellov.c
hellov.o: $\{INCLUDESRC\}/graphic.ih
hellov.o: $\{INCLUDESRC\}/observe.ih
hellov.o: $\{INCLUDESRC\}/point.h
hellov.o: $\{INCLUDESRC\}/rect.h
hellov.o: $\{INCLUDESRC\}/view.ih
hellov.o: $\{SRCDIR\}include/class.h
hellov.o: hellov.eh
hellov.eh hellov.ih: hellov.ch
hellov.eh hellov.ih: $\{INCLUDESRC\}/graphic.ih
hellov.eh hellov.ih: $\{INCLUDESRC\}/observe.ih
hellov.eh hellov.ih: $\{INCLUDESRC\}/point.h
hellov.eh hellov.ih: $\{INCLUDESRC\}/rect.h
hellov.eh hellov.ih: $\{INCLUDESRC\}/view.ih
hellov.eh hellov.ih: $\{SRCDIR\}include/class.h
}
\begindata{bp,537558784}
\enddata{bp,537558784}
\view{bpv,537558784,916,0,0}
Copyright 1992 Carnegie Mellon University and IBM.
All rights reserved.
\smaller{\smaller{$Disclaimer:
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of IBM not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission.
#
# THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ANY COPYRIGHT
# HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# $
}}\enddata{text,538373940}