Library: libbe.so
Most Be applications have an interactive and graphical user interface. When they start up, they present themselves to the user on-screen in one or more windows. The windows display areas where the user can do something--there may be menus to open, buttons to click, text fields to type in, images to drag, and so on. Each user action on the keyboard or mouse is packaged as an interface message and reported to the application. The application responds to each message as it's received. At least part of the response is always a change in what the window displays--so that users can see the results of their work.
To run this kind of user interface, an application has to do three things. It must:
The application, in effect, carries on a conversation with the user. It draws to present itself on-screen, the user does something with the keyboard or mouse, the event is reported to the application in a message, and the application draws in response, prompting more user actions and more messages.
The Interface Kit structures this interaction with the user. It defines a set of C++ classes that give applications the ability to manage windows, draw in them, and efficiently respond to the user's instructions. Taken together, these classes define a framework for interactive applications. By programming with the kit, you'll be able to construct an application that effectively uses the capabilities of the Be operating system.
This chapter first introduces the conceptual framework for the user interface, then describes all the classes, functions, types, and constants the kit defines. The reference material that follows this introduction assumes the concepts and terminology presented here.
A graphical user interface is organized around windows. Each window has a particular role to play in an application and is more or less independent of other windows. While working on the computer, users think in terms of windows--what's in them and what can be done with them--perhaps more than in terms of applications.
The design of the software mirrors the way the user interface works: it's also organized around windows. Within an application, each window runs in its own thread and is represented by a separate BWindow object. The object is the application's interface to the window the system provides; the thread is where all the work that's centered on the window takes place.
Because every window has its own thread, the user can, for example, scroll the contents of one window while watching an animation in another, or start a time-consuming computation in an application and still be able to use the application's other windows. In its interaction with the user, each window acts on its own, independently of other windows. A window won't stop working when the user turns to another window.
In a multitasking environment, any number of applications might be running at the same time, each with its own set of windows on-screen. The windows of all running applications must cooperate in a common interface. For example, there can be only one active window at a time--not one per application, but one per machine. A window that comes to the front must jump over every other window, not just those belonging to the same application.
Because it would be difficult for each application to manage the interaction of its windows with every other application, windows are assigned, at the lowest level of the operating system, to a separate entity, the Application Server. The server's principal role in the user interface is to provide applications with the windows they require.
Everything a program or a user does is centered on the windows the Application Server provides. Users type into windows, click buttons in windows, drag images to windows, and so on; applications draw in windows to display the text users type, the buttons they can click, and the images they drag.
The Application Server, therefore, is the conduit for an application's message input and drawing output:
The server relieves applications of much of the burden of basic user-interface work. The Interface Kit organizes application's interaction with the server and further simplifies the work of building a user interface.
Every window in an application is represented by a separate BWindow object. Constructing the BWindow establishes a connection to the Application Server--one separate from, but initially dependent on, the connection previously established by the BApplication object. The server creates a window for the new object and dedicates a separate thread to it.
The BWindow object is a kind of BLooper--so, when it's first shown on-screen, it spawns a thread for the window in the application's address space and begins running a message loop where it receives and responds to interface messages from the server. The window thread in the application is directly connected to the dedicated thread in the server.
The BWindow object, therefore, is in position to serve three crucial roles:
All other Interface Kit objects play roles that depend on a BWindow. They draw in a window, respond to interface messages received by a window, or act in support of other objects that draw and respond to messages.
For purposes of drawing and message handling, a window can be divided up into smaller rectangular areas called views. Each view corresponds to one part of what the window displays--a scroll bar, a document, a list, a button, or some other more or less self-contained portion of the window's contents.
An application sets up a view by constructing a BView object and associating it with a particular BWindow. The BView object is responsible for drawing within the view rectangle and for handling interface messages directed at that area.
A window is a tablet that can retain and display rendered images, but it can't draw them; for that it needs a set of BViews. A BView is an agent for drawing, but it can't render the images it creates; for that it needs a BWindow. The two kinds of objects work hand in hand.
Each BView object is an autonomous graphics environment for drawing. Some aspects of the environment, such as the list of possible colors, are shared by all BViews and all applications. But within those broad limits, every BView maintains an independent graphics state. It has its own coordinate system, current colors, drawing mode, clipping region, font, pen position, and so on.
The BView class defines the functions that applications call to carry out elemental drawing tasks--such as stroking lines, filling shapes, drawing characters, and imaging bitmaps. These functions are typically used to implement another function--called Draw()--in a class derived from BView. This view-specific function draws what is shown in the view rectangle.
The BWindow will call the BView's Draw() function whenever the window's contents (or at least the part that the BView has control over) need to be updated. A BWindow first asks its BViews to draw when the window is initially placed on-screen. Thereafter, they might be asked to refresh the contents of the window whenever the contents change or when they're revealed after being hidden or obscured. A BView might be called upon to draw at any time.
Because Draw() is normally called automatically (whenever the window is updated), not by the application, it can be considered to draw passively. It presents the view as it currently appears. For example, the Draw() function of a BView that displays editable text would draw the characters that the user had inserted up to that point and would highlight whatever characters happen to be selected at the time.
BViews also draw actively in response to messages reporting the user's actions. For example, text is highlighted as the user drags over it and is replaced as the user types. Each change is the result of a system message reported to the BView. For passive drawing, the application implements a function (Draw()) that others may call. For active drawing, it calls the drawing functions itself (it may even call Draw()).
The drawing that a BView does is often designed to prompt a user response of some kind--an empty text field with a blinking caret invites typed input, a menu item or a button invites a click, an icon looks like it can be dragged, and so on.
When the user acts, system messages that report the resulting events are sent to the BWindow object, which determines which BView elicited the user action and should respond to it. For example, a BView that draws typed text can expect to respond to messages reporting the user's keystrokes. A BView that draws a button gets to handle the messages that are generated when the button is clicked. The BView class derives from BHandler, so BView objects are eligible to handle messages dispatched by the BWindow.
Just as classes derived from BView implement Draw() functions to draw within the view rectangle, they also implement the hook functions that respond to interface messages. These functions are discussed in the section Hook Functions for Interface Messages .
Largely because of its graphics role and its central role in handling interface messages, BView is the biggest and most diverse class in the Interface Kit. Most other Interface Kit classes are derived from it.
A window typically contains a number of different views--all arranged in a hierarchy beneath the top view, a view that's exactly the same size as the content area of the window. The top view is a companion of the window; it's created by the BWindow object when the BWindow is constructed. When the window is resized, the top view is resized to match. Unlike other views, the top view doesn't draw or respond to messages; it serves merely to connect the window to the views that the application creates and places in the hierarchy.
As illustrated in the following diagram, the view hierarchy can be represented as a branching tree structure with the top view at its root. All views in the hierarchy (except the top view) have one, and only one, parent view. Each view (including the top view) can have any number of child views.
In this diagram, the top view has four children, the container view has three, and the border view one. Child views are located within their parents, so the hierarchy is one of overlapping rectangles. The container view, for example, takes up some of the top view's area and divides its own area into a document view and two scroll bars.
When a new BView object is created, it isn't attached to a window and it has no parent. It's added to a window by making it a child of a view already in the view hierarchy. This is done with the AddChild() function. A view can be made a child of the window's top view by calling BWindow's version of AddChild().
Until it's assigned to a window, a BView can't draw and won't receive reports of events. BViews know how to produce images, but it takes a window to display and retain the images they create.
The view hierarchy determines what's displayed where on-screen, and also how user actions are associated with the responsible BView object:
Although children wait for their parents when it comes time to draw and parents defer to their offspring when it comes to time to respond to interface messages, sibling views are not so well behaved. Siblings don't draw in any predefined order. This doesn't matter, as long as the view rectangles of the siblings don't overlap. If they do overlap, it's indeterminate which view will draw last--that is, which one will draw in front of the other.
Similarly, it's indeterminate which view will be associated with mouse events in the area the siblings share. It may be one view or it may be the other, and it won't necessarily be the one that drew the image the user sees.
Therefore, it's strongly recommended that sibling views should be arranged so that they don't overlap.
The Application Server, window threads, and the view hierarchy provide the context for all drawing and message handling in the Interface Kit. The classes in the kit work together to define a program framework for structuring these two tasks. The classes at the core of the framework--BWindow and BView--have been mentioned above and will be examined more extensively under Drawing and Responding to the User below. Other kit classes either derive from BWindow and BView or support the work of those that do. The kit defines several different kinds of BViews that you can use in your application. But every application does some unique drawing and has some application-specific responses to messages, so it must also invent some BViews of its own.
To learn about the Interface Kit for the first time, it's recommended that you first read the Drawing and Responding to the User sections, then look at the BView and BWindow class descriptions, followed by the descriptions of other classes as they interest you. It also might be useful to look at supporting classes--like BPoint, BRect, and BScreen--early. (And, if you haven't already looked at the classes in the Application Kit, be sure to do so. A program must have a BApplication object before it can use the Interface Kit.)
The Be Book, in lovely HTML, for the BeOS Preview Release.
Copyright © 1997 Be, Inc. All rights reserved.
Be is a registered trademark; BeOS, BeBox, BeWare, GeekPort, the Be logo, and the BeOS logo are trademarks of Be, Inc.
Last modified June 28, 1997.