Chapter 2 Hello, World

2.2 Explanation

Line 1: The building blocks of AM2 applications are classes and objects. A class defines a set of structured data and a set of methods that operate on that data. An object is an instance of a particular class.

Our application starts off with the definition of a class that will describe the frame holding the single button of the application. We are only going to need one instance of this class so we don't need to name it. We declare the class with the keyword anonymous. If we were going to create another instance of this class later, we would need to name the class so we could refer to it again. In this case, we would declare it with the keyword class and supply a name for the class.

XFtop is the name of a system supplied wrapped class. XFtop provides a top-level shell or frame that can contain other components and that will interact with your system's window manager. By itself, instances of XFtop are fairly boring, but they perform a very real function. By dealing with the window manager and the other top level windows on your display, instances of XFtop handle requests to minimize the application and manage stacking order.

The colon between the keyword anonymous and the class name XFtop means that the nameless class we are describing inherits from XFtop. That is, it has all the characteristics of the system-supplied XFtop, plus a few extras that we will define in the following lines.

Line 2: The curly brace ( { ) marks the start of our special additions, which will distinguish our anonymous class from its XFtop base. It is matched by the closed curly brace ( } ) on line 7 that marks the end of our special additions.

Line 3: As we said, an XFtop that doesn't contain anything is boring. Our frame does contain something, a single button. And this is the line that inserts the button in the frame.

In AM2, the standard way to make one window system component (we call them widgets) contain another is to make the contained widget a member of the container parent class. Well, almost. Since XFtop is a built-in wrapped class, we can't alter it, say by adding a new member. But we can create a new class that inherits from the wrapped class. And that derived class can contain additional members. So wrapped classes implementing container widgets are used as bases for user defined classes that contain other widgets as members.

And we are defining just such a member here. The member is an instance of the wrapped class XFbutton, and we refer to it within this anonymous class by the name we assign it here, button. This is a little subtle. The class we are defining here has no name, but it has named members. All members must have names, but classes do not need to be named unless we are going to refer to them later.

The open curly bracket that follows the button declaration marks the beginning of a block of code that allows us to particularize this instance of the XFbutton class.

Line 4: The XFbutton wrapped class contains a member called label. You don't have to declare this member. It's built in. You don't even have to initialize it, although you almost certainly want to. If you don't, your button won't have a text label. In this line, we set button's label to be the string "Hello, World". Notice that this initialization is actually an executable statement, and so must be followed by a semicolon.

Line 5: This line describes what we want to happen when the button is clicked by the mouse. AM2 provides the programmer a very flexible way to monitor whatever the user is doing on the screen using activities. This functionality is described in Chapter 3, Using Activities (provide cross reference).

But we can do something much simpler here. XFbuttons possess a member called Pressed that specifies what the user wants to happen when the button gets pressed. The value of Pressed must be a list delimited by curly braces and containing two elements. The first element is a message and the second is a handle to the object to which the message should be sent. So, the Pressed member should contain values that look like { message, target }.

In the ADL, a message can also be a list, whose first element is a string called the selector. The selector determines which method will be invoked in the target of the message when the message is sent. The other elements of a message list are arguments to the method. But the message we want to send is so simple that it doesn't possess arguments, just the selector that all messages must have. And in the case of a message without arguments, the message list can be represented simply by the selector string, which is what has happened here. The message is a string, 'Exit. Note that if a string consists of a single word, it can be preceded by a single quote ( ' ) rather than enclosed in double quotes ( " ).

The second part of the value of Pressed must be a handle to the target of the message. A handle is the ADL's version of a pointer or reference. A variable or member declared as a handle can contain references to other objects or variables. In this case, we are using the keyword theApp to specify a very special reference to the application object.

Everything in an ADL program defines a class including the application itself. The application, although it is not preceded by the keyword anonymous and curly braces, defines an anonymous class that includes all global variables and all other class definitions. When the application starts up, a single instance of this application class is created and initialized. This object can be accessed through the keyword theApp which always contains a handle to this application object. So, by making theApp the target of the 'Exit message, we are assuming the application has a method called Exit that doesn't take any arguments. It does. As a matter of fact, it inherits that method from a class called MCapplication that serves as a silent base class to all applications. You can read about MCapplication in the wrapped class documentation in Section 6.1, "Activities and Application Services" 113.

Line 6: The closing brace on this line ends the block of initializations for the member button. It can be thought of as ending the declaration of the member, and all declarations must end with a semicolon.

Line 7: The first curly brace on this line, the closed brace, ends the definition of our anonymous class derived from XFtop. The next word, top, is the name of the instance of this anonymous class. Why do we need to name this instance? Well, this instance is a global variable in the application, and global variables are considered to be members of this application class. And, as we said above, all members must have names. Trust us on this one for now. It makes things come together much more nicely if we have to supply a name for this variable. The second curly brace, the open one, starts the initialization block for this single instance of our anonymous class derived from XFtop.

Line 8: Here we initialize the height of the frame to be the same as the height of the button that it contains. The units are pixels. It turns out that XFtop has a member called, you guessed it, height. We set the frame's height to be the same as the height of the frame's member called button. Note that both the frame and the button have a member, height. We use the . notation to access the member height of the frame's member button. The variable height to the left of the = refers to the frame's member of the same name because this initialization block belongs to the frame, not the button (or any other object).

Now an interesting question. Why do we have to specify the height of the frame but not the height of the button? By default, buttons with text labels are sized to be just big enough to contain the label. You can override that by setting the width and height of a button, but we have not done that here. Which is why the "Hello World" application ends up being so small on the screen. But XFtops have a default size that is very, almost vanishingly small. Why didn't we make them large enough to contain their contents by default? Well, we thought about it and tried it out, but application developers decided that it hardly ever turned out to be what they wanted. So we decided that you had to size the top-level frame. Children of this top-level frame (that is, the widgets contained by it) would have default position in the upper left hand corner. If you have more than one child widget, that is unlikely to be what you want for the second and later widgets. But in this case, we don't have to worry about positioning the button, just sizing the frame around it.

Line 9: This line is like the previous except it sets the width of the frame, not the height.

Line 10: We're done. The curly brace closes the initialization block for the frame top, and because the initialization completes the definition of the anonymous class and its single instance, we must follow it by a semicolon.


AM2 Documentation - 19 NOV 1996

Generated with Harlequin WebMaker