The Interface Kit: BView


The Interface Kit: BView

Derived from: public BHandler

Declared in: <interface/View.h>


Overview

BView objects are the agents for drawing and message handling within windows. Each object sets up and takes responsibility for a particular view, a rectangular area that's associated with at most one window at a time. The object draws within the view rectangle and responds to reports of events elicited by the images drawn.

Classes derived from BView implement the actual functions that draw and handle messages; BView merely provides the framework. For example, a BTextView object draws and edits text in response to the user's activity on the keyboard and mouse. A BButton draws the image of a button on-screen and responds when the button is clicked. BTextView and BButton inherit from the BView class--as do most classes in the Interface Kit.

The following Kit classes derive, directly or indirectly, from BView:

BControl BButton BMenu
BScrollBar BPictureButton BMenuBar
BScrollView BRadioButton BMenuField
BBox BCheckBox BPopUpMenu
BStringView BColorControl BListView
BTextView BTextControl

Serious applications will need to define their own classes derived from BView.


Views and Windows

For a BView to do its work, you must attach it to a window. The views in a window are arranged in a hierarchy--there can be views within views--with those that are most directly responsible for drawing and message handling located at the terminal branches of the hierarchy and those that contain and organize other views situated closer to its trunk and root. A BView begins life unattached. You can add it to a hierarchy by calling the AddChild() function of the BWindow, or of another BView.

Within the hierarchy, a BView object plays two roles:

The relationship of BViews to BWindows and the framework for drawing and responding to the user were discussed in the introduction to this chapter. The concepts and terminology presented there are assumed in this class description. See especially BView Objects , The View Hierarchy , Drawing beginning on page 18, and Responding to the User beginning on page 41.

BViews can also be called upon to create bitmap images. See the BBitmap class for details.


User Interface

Since they provide the content that's displayed within windows, BViews carry most of the burden of implementing an application's user interface. Often this is simply a matter of how a BView implements a hook function--how Draw() presents the view or how MouseDown() handles a double-click. User-interface guidelines should be followed, but the BView is essentially on its own. However, in some cases the Interface Kit provides a mechanism that derived classes can participate in, if they coordinate with Kit-defined code. Two such mechanisms are described below--keyboard navigation and the drag- and-drop delivery of messages.

Keyboard Navigation

Keyboard navigation is a mechanism for allowing users to manipulate views --especially buttons, check boxes, and other control devices--from the keyboard. It gives users the ability to:

The first ability--navigation between views--is implemented by the Interface Kit. The second--navigation within a view--is up to individual applications, as are most view- specific aspects of the user interface. The only trick, and it's not a difficult one, is to make the two kinds of navigation work together.

To have the BView class you implement participate in the navigation mechanism, you need to coordinate four pieces of code:

Several Kit classes that derive from BView implement these functions. For example, BControl has a simple KeyDown() function and a MakeFocus() function that calls Draw(). If you base your class on BControl, you won't have to implement MakeFocus() and may find that its KeyDown() is adequate for your needs.

Drag and Drop

The BView class supports a drag-and-drop user interface. The user can transfer a parcel of information from one place to another by dragging an image from a source view and dropping it on a destination view--perhaps a view in a different window or even a different application.

A source BView initiates dragging by calling DragMessage() from within its MouseDown() function. The BView bundles all information relevant to the dragging session into a BMessage object and passes it to DragMessage(). It also passes an image to represent the data package on-screen.

The Application Server then takes charge of the BMessage object and animates the image as the user drags it on-screen. As the image moves across the screen, the views it passes over are informed with MouseMoved() function calls. These notifications give views a chance to show the user whether or not they're willing to accept the message being dragged. When the user releases the mouse button, dropping the dragged message, the message is delivered to the BWindow and targeted to the destination BView.

Aside from creating a BMessage object and passing it to DragMessage(), or implementing MouseMoved() and MessageReceived() functions to handle any messages that come its way, there's nothing an application needs to do to support a drag-and-drop user interface. The bulk of the work is done by the Application Server and Interface Kit.


Locking the Window

If a BView is attached to a window, any operation that affects the view might also affect the window and the BView's shadow counterpart in the Application Server. For this reason, any code that calls a BView function should first lock the window--so that one thread can't modify essential data structures while another thread is using them. A window can be locked by only one thread at a time.

By default, before they do anything else, almost all BView functions check to be sure the caller has the window locked. If the window isn't properly locked, they print warning messages and fail.

This check should help you develop an application that correctly regulates access to windows and views. However, it adds a certain amount of time to each function call. Once your application has been debugged and is ready to ship, you can turn the check off by calling BWindow's SetDiscipline() function and passing it an argument of FALSE . The discipline flag is separately set for each window.

BView functions can require the window to be locked only if the view has a window to lock; the requirement can't be enforced if the BView isn't attached to a window. However, as discussed under Views and the Server of the introduction to this chapter, many BView functions, including all those that depend on graphics parameters, don't work at all unless the view is attached--in which case the window must be locked.

Whenever the system calls a BView function to notify it of something --whenever it calls WindowActivated() , Draw(), MessageReceived() or another hook function--it first locks the window thread. The application doesn't have to explicitly lock the window when responding to an update, an interface message, or some other notification. The window is already locked.


Derived Classes

When it comes time for a BView to draw, its Draw() virtual function is called automatically. When it needs to respond to an event, a virtual function named after the kind of event is called--MouseMoved() , KeyDown(), and so on. Classes derived from BView implement these hook functions to do the particular kind of drawing and message handling characteristic of the derived class.

Almost all the BView classes defined in the Interface Kit fall into the first two of these groups. Control devices and organizational views can serve a variety of different kinds of applications, and therefore can be implemented in a kit that's common to all applications

However, the BViews that will be central to most applications fall into the last two groups. Of particular importance are the BViews that manage editable data. Unfortunately, these are not views that can be easily implemented in a common kit. Just as most applications devise their own data formats, most applications will need to define their own data- handling views.

Nevertheless, the BView class structures and simplifies the task of developing application- specific objects that draw in windows and interact with the user. It takes care of the lower- level details and manages the view's relationship to the window and other views in the hierarchy. You should make yourself familiar with this class before implementing you own application-specific BViews.


Hook Functions

AllAttached() Can be implemented to finish initializing the BView after it's attached to a window, where the initialization depends on a descendent view's AttachedToWindow() function having been called.
AllDetached() Can be implemented to prepare the BView for being detached from a window, where the preparations depend on a descendent view's DetachedFromWindow() function having been called.
AttachedToWindow() Can be implemented to finish initializing the BView after it becomes part of a window's view hierarchy.
DetachedFromWindow() Can be implemented to prepare the BView for its impending removal from a window's view hierarchy.
Draw() Can be implemented to draw the view.
FrameMoved() Can be implemented to respond to a message notifying the BView that it has moved in its parent's coordinate system.
FrameResized() Can be implemented to respond to a message informing the BView that its frame rectangle has been resized.
KeyDown() Can be implemented to respond to a message reporting a key-down event.
MakeFocus() Makes the BView the focus view, or causes it to give up being the focus view; can be augmented to take any action the change in status may require.
MouseDown() Can be implemented to respond to a message reporting a mouse-down event.
MouseMoved() Can be implemented to respond to a notification that the cursor has entered the view's visible region, moved within the visible region, or exited from the view.
Pulse() Can be implemented to do something at regular intervals. This function is called repeatedly when no other messages are pending.
WindowActivated() Can be implemented to respond to a notification that the BView's window has become the active window, or has lost that status.


Constructor and Destructor


BView()

      BView(BRect frame, const char *name, ulong resizingMode, ulong flags)

Sets up a view with the frame rectangle, which is specified in the coordinate system of its eventual parent, and assigns the BView an identifying name, which can be NULL.

When it's created, a BView doesn't belong to a window and has no parent. It's assigned a parent by having another BView adopt it with the AddChild() function. If the other view is in a window, the BView becomes part of that window's view hierarchy. A BView can be made a child of the window's top view by calling BWindow's version of the AddChild() function.

When the BView gains a parent, the values in frame are interpreted in the parent's coordinate system. The sides of the view must be aligned on screen pixels. Therefore, the frame rectangle should not contain coordinates with fractional values. Fractional coordinates will be rounded to the nearest whole number.

The resizingMode mask determines the behavior of the view when its parent is resized. It should combine one constant for horizontal resizing,

B_FOLLOW_LEFT
B_FOLLOW_RIGHT
B_FOLLOW_LEFT_RIGHT
B_FOLLOW_H_CENTER

with one for vertical resizing:

B_FOLLOW_TOP
B_FOLLOW_BOTTOM
B_FOLLOW_TOP_BOTTOM
B_FOLLOW_V_CENTER

For example, if B_FOLLOW_LEFT is chosen, the margin between the left side of the view and left side of its parent will remain constant--the view's left side will "follow" the parent's left side. Similarly, if B_FOLLOW_RIGHT is chosen, the view's right side will follow the parent's right side. If B_FOLLOW_H_CENTER is chosen, the horizontal center of the view will maintain a constant distance from the horizontal center of the parent.

If the constants name opposite sides of the view rectangle--left and right, or top and bottom--the view will necessarily be resized in that dimension when the parent is.

If a side is not mentioned, the distance between that side of the view and the corresponding side of the parent is free to fluctuate. This may mean that the view will move within its parent's coordinate system when the parent is resized. B_FOLLOW_RIGHT plus B_FOLLOW_BOTTOM , for example, would keep a view from being resized, but the view will move to follow the right bottom corner of its parent whenever the parent is resized. B_FOLLOW_LEFT plus B_FOLLOW_TOP prevents a view from being resized and from being moved.

In addition to the constants listed above, there are two other possibilities:

B_FOLLOW_ALL_SIDES
B_FOLLOW_NONE

B_FOLLOW_ALL_SIDES is a shorthand for B_FOLLOW_LEFT_RIGHT and B_FOLLOW_TOP_BOTTOM . It means that the view will be resized in tandem with its parent, both horizontally and vertically.

B_FOLLOW_NONE keeps the view at its absolute position on-screen; the parent view is resized around it. (Nevertheless, because the parent is resized, the view may wind up being moved in its parent's coordinate system.)

Typically, a parent view is resized because the user resizes the window it's in. When the window is resized, the top view is too. Depending on how the resizingMode flag is set for the top view's children and for the descendants of its children, automatic resizing can cascade down the view hierarchy. A view can also be resized programmatically by the ResizeTo() and ResizeBy() functions.

The resizing mode can be changed after construction with the SetResizingMode() function.

The flags mask determines what kinds of notifications the BView will receive. It can be any combination of these four constants:

B_WILL_DRAW Indicates that the BView does some drawing of its own and therefore can't be ignored when the window is updated. If this flag isn't set, the BView won't receive update notifications -- it won't be erased to its background color and its Draw() function won't be called.
B_PULSE_NEEDED Indicates that the BView should receive Pulse() notifications.
B_FRAME_EVENTS Indicates that the BView should receive FrameResized() and FrameMoved() notifications when its frame rectangle changes--typically as a result of the automatic resizing behavior described above. FrameResized() is called when the dimensions of the view change; FrameMoved() is called when the position of its left top corner in its parent's coordinate system changes.
B_FULL_UPDATE_ON_RESIZE Indicates that the entire view should be updated when it's resized. If this flag isn't set, only the portions that resizing adds to the view will be included in the clipping region.
B_NAVIGABLE Indicates that the BView can become the focus view for keyboard actions. This flag makes it possible for the user to navigate to the view and put it in focus by pressing the Tab key. See Keyboard Navigation above.

If none of these constants apply, flags can be NULL . The flags can be reset after construction with the SetFlags() function.

See also: SetResizingMode() , SetFlags(), BHandler::SetName()


~BView()

      virtual ~BView(void)

Removes the BView from the view hierarchy and ensures that each of its descendants is also removed and destroyed.


Member Functions


AddChild()

      virtual void AddChild(BView *aView)

Makes aView a child of the BView, provided that aView doesn't already have a parent. If the BView is attached to a window, aView and all its descendants become attached to the same window. Each of them is notified of this change through AttachedToWindow() and AllAttached() function calls.

AddChild() fails if aView already belongs to a view hierarchy. A view can live with only one parent at a time.

When a BView object becomes attached to a BWindow, two other connections are automatically established for it:

See also: BWindow::AddChild(), AttachedToWindow() , BLooper::AddHandler() , BHandler::SetNextHandler() , RemoveChild()


AddLine() see BeginLineArray()


AllAttached() see AttachedToWindow()


AllDetached() see DetachedFromWindow()


AttachedToWindow(), AllAttached()

      virtual void AttachedToWindow(void)
      virtual void AllAttached(void)

Implemented by derived classes to complete the initialization of the BView when it's assigned to a window. A BView is assigned to a window when it, or one of its ancestors in the view hierarchy, becomes a child of a view already attached to a window.

AttachedToWindow() is called immediately after the BView is formally made a part of the window's view hierarchy and after it has become known to the Application Server and its graphics parameters are set. The Window() function can identify which BWindow the BView belongs to.

All of the BView's children, if it has any, also become attached to the window and receive their own AttachedToWindow() notifications. Parents receive the notification before their children, but only after all views have become attached to the window and recognized as part of the window's view hierarchy. This function can therefore depend on all ancestor and descendent views being in place.

For example, AttachedToWindow() can be implemented to set a view's background color to the same color as its parent, something that can't be done before the view belongs to a window and knows who its parent is.

   void MyView::AttachedToWindow()
   {
       if ( Parent() )
           SetViewColor(Parent()->ViewColor());
       inherited::AttachedToWindow();
   }

The AllAttached() notification follows on the heels of AttachedToWindow(), but works its way up the view hierarchy rather than down. When AllAttached() is called for a BView, all its descendants have received both AttachedToWindow() and AllAttached() notifications. Therefore, parent views can depend on any calculations that their children make in either function. For example, a parent can resize itself to fit the size of its children, where their sizes depend on calculations done in AttachedToWindow() .

The default (BView) version of both these functions are empty.

See also: AddChild(), Window()


BeginLineArray(), AddLine() , EndLineArray()

      void BeginLineArray(long count)
      void AddLine(BPoint start, BPoint end, rgb_color color)
      void EndLineArray(void)

These functions provide a more efficient way of drawing a large number of lines than repeated calls to StrokeLine(). BeginLineArray() signals the beginning of a series of up to count AddLine() calls; EndLineArray() signals the end of the series. Each AddLine() call defines a line from the start point to the end point, associates it with a particular color, and adds it to the array. The lines can each be a different color; they don't have to be contiguous. When EndLineArray() is called, all the lines are drawn --using the then current pen size--in the order that they were added to the array.

These functions don't change any graphics parameters. For example, they don't move the pen or change the current high and low colors. Parameter values that are in effect when EndLineArray() is called are the ones used to draw the lines. The high and low colors are ignored in favor of the color specified for each line.

The count passed to BeginLineArray() is an upper limit on the number of lines that can be drawn. Keeping the count close to accurate and within reasonable bounds helps the efficiency of the line-array mechanism. It's a good idea to keep it less than 256; above that number, memory requirements begin to impinge on performance.

See also: StrokeLine()


BeginPicture(), EndPicture()

      void BeginPicture(BPicture *picture)
      BPicture *EndPicture(void)

BeginPicture() instructs the Application Server to begin recording a set of drawing instructions for a picture; EndPicture() instructs the Server to end the recording session. It returns the same object that was passed to BeginPicture().

The BPicture records exactly what the BView draws--and only what the BView draws --between the BeginPicture() and EndPicture() calls. The drawing of other views is ignored, as are function calls that don't draw or affect graphics parameters. The picture captures only primitive graphics operations--that is, functions defined in this class, such as DrawString(), FillArc(), and SetFont(). If a complex drawing function (such as Draw()) is called, only the primitive operations that it contains are recorded.

A BPicture can be recorded only if the BView is attached to a window. The window it's in can be off-screen and the view itself can be hidden or reside outside the current clipping region. However, if the window is on-screen and the view is visible, the drawing that the BView does will both be captured in the picture and rendered in the window.

See also: the BPicture class, DrawPicture()


BeginRectTracking(), EndRectTracking()

      void BeginRectTracking(BRect rect, ulong how = B_TRACK_WHOLE_RECT)
      void EndRectTracking(void)

These functions instruct the Application Server to display a rectangular outline that will track the movement of the cursor. BeginRectTracking() puts the rectangle on-screen and initiates tracking; EndRectTracking() terminates tracking and removes the rectangle. The initial rectangle, rect, is specified in the BView's coordinate system.

This function supports two kinds of tracking, depending on the constant passed as the how argument:

B_TRACK_WHOLE_RECT The whole rectangle moves with the cursor. Its position changes, but its size remains fixed.
B_TRACK_RECT_CORNER The left top corner of the rectangle remains fixed within the view while its right and bottom edges move with the cursor.

Tracking is typically initiated from within a BView's MouseDown() function and is allowed to continue as long as a mouse button is held down. For example:

   void MyView::MouseDown(BPoint point)
   {
       ulong buttons;
   
       BRect rect(point, point);
       BeginRectTracking(rect, B_TRACK_RECT_CORNER);
       do {
           snooze(30.0 * 1000.0);
           GetMouse(&point, &buttons);
       } while ( buttons );
       EndRectTracking();
   
       rect.SetRightBottom(point);
       . . .
   }

This example uses BeginRectTracking() to drag out a rectangle from the point recorded for a mouse-down event. It sets up a modal loop to periodically check on the state of the mouse buttons. Tracking ends when the user releases all buttons. The right and bottom sides of the rectangle are then updated from the cursor location last reported by the GetMouse() function.

See also: ConvertToScreen() , GetMouse()


Bounds()

      BRect Bounds(void) const

Returns the BView's bounds rectangle. If the BView is attached to a window, this function gets the current bounds rectangle from the Application Server. If not, it returns a rectangle the same size as the BView's frame rectangle, but with the left and top sides at 0.0.

See also: Frame()


ChildAt() see Parent()


ConstrainClippingRegion()

      virtual void ConstrainClippingRegion(BRegion *region)

Restricts the drawing that the BView can do to region.

The Application Server keeps track of a clipping region for each BView that's attached to a window. It clips all drawing the BView does to that region; the BView can't draw outside of it.

By default, the clipping region contains only the visible area of the view and, during an update, only the area that actually needs to be drawn. By passing a region to this function, an application can further restrict the clipping region. When calculating the clipping region, the Server intersects it with the region provided. The BView can draw only in areas common to the region passed and the clipping region as the Server would otherwise calculate it. The region passed can't expand the clipping region beyond what it otherwise would be.

If called during an update, ConstrainClippingRegion() restricts the clipping region only for the duration of the update.

Calls to ConstrainClippingRegion() are not additive; each region that's passed replaces the one that was passed in the previous call. Passing a NULL pointer removes the previous region without replacing it. The function works only for BViews that are attached to a window.

See also: GetClippingRegion() , Draw()


ConvertToParent(), ConvertFromParent()

      BPoint ConvertToParent(BPoint localPoint) const
      void ConvertToParent(BPoint *localPoint) const

      BRect ConvertToParent(BRect localRect) const
      void ConvertToParent(BRect *localRect) const

      BPoint ConvertFromParent(BPoint parentPoint) const
      void ConvertFromParent(BPoint *parentPoint) const

      BRect ConvertFromParent(BRect parentRect) const
      void ConvertFromParent(BRect *parentRect) const

These functions convert points and rectangles to and from the coordinate system of the BView's parent. ConvertToParent() converts localPoint or localRect from the BView's coordinate system to the coordinate system of its parent BView. ConvertFromParent() does the opposite; it converts parentPoint or parentRect from the coordinate system of the BView's parent to the BView's own coordinate system.

If the point or rectangle is passed by value, the function returns the converted value. If a pointer is passed, the conversion is done in place.

Both functions fail if the BView isn't attached to a window.

See also: ConvertToScreen()


ConvertToScreen(), ConvertFromScreen()

      BPoint ConvertToScreen(BPoint localPoint) const
      void ConvertToScreen(BPoint *localPoint) const

      BRect ConvertToScreen(BRect localRect) const
      void ConvertToScreen(BRect *localRect) const

      BPoint ConvertFromScreen(BPoint screenPoint) const
      void ConvertFromScreen(BPoint *screenPoint) const

      BRect ConvertFromScreen(BRect screenRect) const
      void ConvertFromScreen(BRect *screenRect) const

ConvertToScreen() converts localPoint or localRect from the BView's coordinate system to the global screen coordinate system. ConvertFromScreen() makes the opposite conversion; it converts screenPoint or screenRect from the screen coordinate system to the BView's local coordinate system.

If the point or rectangle is passed by value, the function returns the converted value. If a pointer is passed, the conversion is done in place.

The screen coordinate system has its origin, (0.0, 0.0), at the left top corner of the main screen.

Neither function will work if the BView isn't attached to a window.

See also: BWindow::ConvertToScreen(), ConvertToParent()


CopyBits()

      void CopyBits(BRect source, BRect destination)

Copies the image displayed in the source rectangle to the destination rectangle, where both rectangles lie within the view and are stated in the BView's coordinate system.

If the two rectangles aren't the same size, the source image is scaled to fit. If not all of the destination rectangle lies within the BView's visible region, the source image is clipped rather than scaled.

If not all of the source rectangle lies within the BView's visible region, only the visible portion is copied. It's mapped to the corresponding portion of the destination rectangle. The BView is then invalidated so its Draw() function will be called to update the part of the destination rectangle that can't be filled with the source image.

The BView must be attached to a window.


CountChildren() see Parent()


DetachedFromWindow, AllDetached()

      virtual void DetachedFromWindow(void)
      virtual void AllDetached(void)

Implemented by derived classes to make any adjustments necessary when the BView is about to be removed from a window's view hierarchy. These two functions parallel the more commonly implemented AttachedToWindow() and AllAttached() functions.

DetachedFromWindow() notifications work their way down the hierarchy of views being detached, followed by AllDetached() notifications, which work their way up the hierarchy. The second function call permits an ancestor view to take actions that depend on calculations a descendant might have to make when it's first notified of being detached.

The BView is still attached to the window when both functions are called.

See also: AttachedToWindow()


DragMessage()

      void DragMessage(BMessage *message, BBitmap *image, BPoint point, BHandler *replyTarget = NULL)
      void DragMessage(BMessage *message, BRect rect, BHandler *replyTarget = NULL)

Initiates a drag-and-drop session. The first argument, message , is a BMessage object that bundles the information that will be dragged and dropped on the destination view. Once passed to DragMessage(), this object becomes the responsibility of --and will eventually be freed by--the system. You shouldn't free it yourself, try to access it later, or pass it to another function. (Since data is copied when it's added to a BMessage, only the copies are automatically freed, not the originals.)

The second argument, image, represents the message on-screen; it's the visible image that the user drags. Like the BMessage, this BBitmap object becomes the responsibility of the system; it will be freed when the message is dropped. If you want to keep the image yourself, make a copy to pass to DragMessage(). The image isn't dropped on the destination BView; if you want the destination to have the image, you must add it to the message as well as pass it as the image argument.

The third argument, point, locates the point within the image that's aligned with the hot spot of the cursor--that is, the point that's aligned with the location passed to MouseDown() or returned by GetMouse(). It's stated within the coordinate system of the source image and should lie somewhere within its bounds rectangle. The bounds rectangle and coordinate system of a BBitmap are set when the object is constructed.

Alternatively, you can specify that an outline of a rectangle, rect, should be dragged instead of an image. The rectangle is stated in the BView's coordinate system. (Therefore, a point argument isn't needed to align it with the cursor.)

The final argument, replyTarget, names the object that you want to handle any message that might be sent in reply to the dragged message. If replyTarget is NULL, as it is by default, any reply that's received will be directed to the BView object that initiated the drag-and-drop session.

This function works only for BViews that are attached to a window.

See also: BMessage::WasDropped() , the BBitmap class


Draw()

      virtual void Draw(BRect updateRect)

Implemented by derived classes to draw the updateRect portion of the view. The update rectangle is stated in the BView's coordinate system. It's the smallest rectangle that encloses the current clipping region for the view.

Since the Application Server won't render anything a BView draws outside its clipping region, applications will be more efficient if they avoid sending drawing instructions to the Server for images that don't intersect with updateRect. For more efficiency and precision, you can ask for the clipping region itself (by calling GetClippingRegion()) and confine drawing to images that intersect with it.

A BView's Draw() function is called (as the result of an update message) whenever the view needs to present itself on-screen. This may happen when:

See also: BWindow::UpdateIfNeeded(), Invalidate() , GetClippingRegion()


DrawBitmap(), DrawBitmapAsync()

      void DrawBitmap(const BBitmap *image)
      void DrawBitmap(const BBitmap *image, BPoint point)

      void DrawBitmap(const BBitmap *image, BRect destination)

      void DrawBitmap(const BBitmap *image, BRect source, BRect destination)

      void DrawBitmapAsync(const BBitmap *image)
      void DrawBitmapAsync(const BBitmap *image, BPoint point)

      void DrawBitmapAsync(const BBitmap *image, BRect destination)

      void DrawBitmapAsync(const BBitmap *image, BRect source, BRect destination)

These functions place a bitmap image in the view at the current pen position, at the point specified, or within the designated destination rectangle. The point and the destination rectangle are stated in the BView's coordinate system.

If a source rectangle is given, only that part of the bitmap image is drawn. Otherwise, the entire bitmap is placed in the view. The source rectangle is stated in the internal coordinates of the BBitmap object.

If the source image is bigger than the destination rectangle, it's scaled to fit.

The two functions differ in only one respect: DrawBitmap() waits for the Application Server to finish rendering the image before it returns. DrawBitmapAsync() doesn't wait; it passes the image to the Server and returns immediately.

See also: Drawing Modes in the chapter introduction, the BBitmap class


DrawChar()

      void DrawChar(char c)
      void DrawChar(char c, BPoint point)

Draws the character c at the current pen position--or at the point specified--and moves the pen to a position immediately to the right of the character. This function is equivalent to passing a string of one character to DrawString() . The point is specified in the BView's coordinate system.

See also: DrawString()


DrawingMode() see SetDrawingMode()


DrawPicture()

      void DrawPicture(const BPicture *picture)
      void DrawPicture(const BPicture *picture, BPoint point) 

Draws the previously recorded picture at the current pen position --or at the specified point in the BView's coordinate system. The point or pen position is taken as the coordinate origin for all the drawing instructions recorded in the BPicture.

Nothing that's done in the BPicture can affect anything in the BView's graphics state --for example, the BPicture can't reset the current high color or the pen position. Conversely, nothing in the BView's current graphics state affects the drawing instructions captured in the picture. The graphics parameters that were in effect when the picture was recorded determine what the picture looks like.

See also: BeginPicture() , the BPicture class


DrawString()

      void DrawString(const char *string)
      void DrawString(const char *string, long length)

      void DrawString(const char *string, BPoint point)

      void DrawString(const char *string, long length, BPoint point)

Draws length characters of string--or, if the number of characters isn't specified, all the characters in the string, up to the null terminator ('\0').

This function places the first character on a baseline that begins at the current pen position--or at the specified point in the BView's coordinate system. It moves the pen to the baseline immediately to the right of the last character drawn. A series of simple DrawString() calls (with no point specified) will produce a continuous string. For example, these two lines of code,

   DrawString("tog");
   DrawString("ether");

will produce the same result as this one:

   DrawString("together");

This is a graphical drawing function, so all the characters to be drawn should have visible representations (including whitespace). Control characters (those with values less than B_SPACE , 0x20) will be rejected (skipped over) but at a substantial price in performance.

See also: MovePenBy(), SetFontName()


EndLineArray() see BeginLineArray()


EndPicture() see BeginPicture()


EndRectTracking() see BeginRectTracking()


FillArc() see StrokeArc()


FillEllipse() see StrokeEllipse()


FillPolygon() see StrokePolygon()


FillRect() see StrokeRect()


FillRoundRect() see StrokeRoundRect()


FillTriangle() see StrokeTriangle()


FindView()

      BView *FindView(const char *name) const

Returns the BView identified by name, or NULL if the view can't be found. Names are assigned by the BView constructor and can be modified by the SetName() function inherited from BHandler.

FindView() begins the search by checking whether the BView's name matches name. If not, it continues to search down the view hierarchy, among the BView's children and more distant descendants. To search the entire view hierarchy, use the BWindow version of this function.

See also: BWindow::FindView(), BHandler::SetName()


Flags() see SetFlags()


Flush(), Sync()

      void Flush(void) const
      void Sync(void) const

These functions flush the window's connection to the Application Server. If the BView isn't attached to a window, neither function has an effect.

For reasons of efficiency, the window's connection to the Application Server is buffered. Drawing instructions destined for the Server are placed in the buffer and dispatched as a group when the buffer becomes full. Flushing empties the buffer, sending whatever it contains to the Server, even if it's not yet full.

The buffer is automatically flushed on every update. However, if you do any drawing outside the update mechanism--in response to interface messages, for example--you need to explicitly flush the connection so that drawing instructions won't languish in the buffer while waiting for it to fill up or for the next update. You should also flush it if you call any drawing functions from outside the window's thread.

Flush() simply flushes the buffer and returns. It does the same work as BWindow's function of the same name.

Sync() flushes the connection, then waits until the Server has executed the last instruction that was in the buffer before returning. This alternative to Flush() prevents the application from getting ahead of the Server (ahead of what the user sees on-screen) and keeps both processes synchronized.

It's a good idea, for example, to call Sync(), rather than Flush(), after employing BViews to produce a bitmap image (a BBitmap object). Sync() is the only way you can be sure the image has been completely rendered before you attempt to draw with it.

(Note that all BViews attached to a window share the same connection to the Application Server. Calling Flush() or Sync() for any one of them flushes the buffer for all of them.)

See also: BWindow::Flush() , the BBitmap class


Frame()

      BRect Frame(void) const

Returns the BView's frame rectangle. The frame rectangle is first set by the BView constructor and is altered only when the view is moved or resized. It's stated in the coordinate system of the BView's parent.

If the BView is not attached to a window, Frame() reports the object's own cached conception of its frame rectangle. If it is attached, Frame() reports the Application Server's conception of the rectangle. When a BView is added to a window, its cached rectangle is communicated to the Server. While it remains attached, the functions that move and resize the frame rectangle affect the Server's conception of the view, but don't alter the rectangle kept by the object. Therefore, if the BView is removed from the window, Frame() will again report the frame rectangle that it had before it was attached, no matter how much it was moved and resized while it belonged to the window.

See also: MoveBy(), ResizeBy(), the BView constructor


FrameMoved()

      virtual void FrameMoved(BPoint parentPoint)

Implemented by derived classes to respond to a notification that the view has moved within its parent's coordinate system. parentPoint gives the new location of the left top corner of the BView's frame rectangle.

FrameMoved() is called only if the B_FRAME_EVENTS flag is set and the BView is attached to a window.

If the view is both moved and resized, FrameMoved() is called before FrameResized(). This might happen, for example, if the BView's automatic resizing mode is a combination of B_FOLLOW_TOP_BOTTOM and B_FOLLOW_RIGHT and its parent is resized both horizontally and vertically.

The default (BView) version of this function is empty.

< Currently, FrameMoved() is also called when a hidden window is shown on-screen. >

See also: MoveBy(), BWindow::FrameMoved() , SetFlags()


FrameResized()

      virtual void FrameResized(float width, float height)

Implemented by derived classes to respond to a notification that the view has been resized. The arguments state the new width and height of the view. The resizing could have been the result of a user action (resizing the window) or of a programmatic one (calling ResizeTo() or ResizeBy()).

FrameResized() is called only if the B_FRAME_EVENTS flag is set and the BView is attached to a window.

BView's version of this function is empty.

See also: ResizeBy(), BWindow::FrameResized() , SetFlags()


GetCharEscapements(), GetCharEdges()

      void GetCharEscapements(char charArray[], long numChars, float escapementArray[], float *factor) const
      void GetCharEdges(char charArray[], long numChars,
         edge_info edgeArray[]) const

These two functions are designed for programmers who want to precisely position characters on the screen or printed page. For each character passed in the charArray , they write information about the horizontal dimension of the character into the escapementArray or the edgeArray. Both functions assume the BView's current font. Therefore, neither has any effect unless the BView is attached to a window.

< These functions provide inaccurate results for bitmap fonts. >

Escapement

An "escapement" is simply the width of a character recorded in very small units. The units are sufficiently tiny to permit detailed information to be kept in integer form for every character in the font--although declared as float s, none of the values in the escapementArray have fractional parts. Because the units are small, escapement values are quite large. (The term "escapement" has its historical roots in the fact that the carriage of a typewriter had to move or "escape" a certain distance after each character was typed to make room for the next character.)

The escapement of a character measures the amount of horizontal room it requires when positioned between other characters in a line of text. It includes a measurement of the space required to display the character itself, plus some extra room on the left and right edges to separate the character from its neighbors. In a proportionally spaced font, each character has a distinctive escapement. The illustration below shows the approximate escapements for the letters 'l' and 'p' as they might appear together in a word like "help" or "ballpark." The escapement for each character is the distance between the vertical lines:

GetCharEscapements() measures the same space that functions such as BView's StringWidth() and BTextView's LineWidth() do, though it measures each character individually and records the result in arbitrary (rather than coordinate) units.

The escapement of a character in a particular font is a constant no matter what the font size. To convert an escapement value to coordinate units, you must multiply it by three values:

  • A floating-point conversion factor,

  • The font size (in points), and

  • The resolution of the output device.
  • GetCharEscapements() writes the conversion factor into the variable referred to by factor. GetFontInfo() can provide the current font size. When the output device is a printer, the resolution should be the actual resolution (the dpi or "dots per inch") at which it prints. When the output device is the screen, the resolution should be 72.0. (This reflects the fact that screen pixels are taken to equal coordinate units--and one coordinate unit is 1/72 of an inch, or roughly equivalent to one typographical point.)

    Edges

    Edge values measure how far a character outline is inset from its left and right escapement boundaries. GetCharEdges() provides edge values in standard coordinate units, not escapement units, that take the size of the current font into account. It places the edge values into an array of edge_info structures. Each structure has a left and a right data member, as follows:

       typedef struct {
           float left;
           float right;
       } edge_info;

    The illustration below shows typical character edges. As in the illustration above, the solid vertical lines mark escapement boundaries. The dotted lines mark off the part of each escapement that's an edge, the distance between the character outline and the escapement boundary:

    This is the normal case. The left edge is a positive value measured rightward from the left escapement boundary. The right edge is a negative value measured leftward from the right escapement boundary.

    However, if the characters of a font overlap, the left edge can be a negative value and the right edge can be positive. This is illustrated below:

    Note that the italic 'l' extends beyond its escapement to the right, and that the ' p' begins before its escapement to the left. In this case, instead of separating the adjacent characters, the edges determine how much they overlap.

    Edge values are specific to each character and depend on nothing but the character (and the font). They don't take into account any contextual information; for example, the right edge for italic 'l' would be the same no matter what letter followed. Edge values therefore aren't sufficient to decide how character pairs can be kerned. Kerning is contextually dependent on the combination of two particular characters.

    See also: GetFontInfo()


    GetClippingRegion()

          void GetClippingRegion(BRegion *region) const

    Modifies the BRegion object passed as an argument so that it describes the current clipping region of the BView, the region where the BView is allowed to draw. It's most efficient to allocate temporary BRegions on the stack:

       BRegion clipper;
       GetClippingRegion(&clipper);
       . . .

    Ordinarily, the clipping region is the same as the visible region of the view, the part of the view currently visible on-screen. The visible region is equal to the view's bounds rectangle minus:

    The clipping region can be smaller than the visible region if the program restricted it by calling ConstrainClippingRegion() . It will exclude any area that doesn't intersect with the region passed to ConstrainClippingRegion() .

    While the BView is being updated, the clipping region contains just those parts of the view that need to be redrawn. This may be smaller than the visible region, or the region restricted by ConstrainClippingRegion() , if:

    This function works only if the BView is attached to a window. Unattached BViews can't draw and therefore have no clipping region.

    See also: ConstrainClippingRegion() , Draw(), Invalidate()


    GetFontInfo()

          void GetFontInfo(font_info *fontInfo) const

    Writes information about the BView's current font into the structure referred to by fontInfo. The font_info structure contains the following fields:

    font_name name The name of the font, which can be as long as 64 characters, plus a null terminator. The name can be set by BView's SetFontName() function.
    float size The size of the font in points. It can be set by SetFontSize().
    float shear The shear angle, which is 90.0° by default and can vary between 45.0° and 135.0°. It can be set by SetFontShear() .
    float rotation The angle of rotation, which is 0.0° by default. It's set by SetFontRotation().
    float ascent How far characters ascend above the baseline.
    float descent How far characters descend below the baseline.
    float leading The amount of space separating lines (between the descent of the line above and the ascent of the line below).

    The ascent, descent, and leading are measured in coordinate units.

    This function works only if the BView is attached to a window.

    See also: SetFontName()


    GetKeys()

          long GetKeys(key_info *keyInfo, bool checkQueue)

    Writes information about the state of the keyboard into the key_info structure referred to by keyInfo. This structure contains fields that match the BMessage entries that record information about a key-down event. They are:

    ulong char_code An ASCII character value, such as 'a' or B_BACKSPACE.
    ulong key_code A code identifying the key that produced the character.
    ulong modifiers A mask indicating which modifier keys are down and which keyboard locks are on.
    uchar key_states[16] A bit array that records the state of all the keys on the keyboard, and all the keyboard locks. This array works identically to the "states" array passed in a key-down message. See Key States for information on how to read information from the array.

    If the checkQueue flag is FALSE, GetKeys() provides information about the current state of the keyboard. When this is the case, the modifiers field contains the same information that the modifiers() function returns.

    However, if the checkQueue flag is TRUE, GetKeys() first checks the message queue to see whether it contains any messages reporting keyboard (key-down or key-up) events. If there are keyboard messages waiting in the queue, it takes the information from the oldest message, places it in the keyInfo structure, and removes the message from the queue. Each time GetKeys() is called, it gets another keyboard message from the queue. If the queue doesn't contain any keyboard messages, it reports the current state of the keyboard, just as if checkQueue were FALSE.

    When called repeatedly in a loop, GetKeys() will empty the queue of keyboard messages and then reflect the current state of the keyboard. In this way, you can be sure that your application has not jumped ahead of the user and overlooked any reports of the user's keyboard actions.

    This function never looks at the current message, even if it happens to report a keyboard event and checkQueue is TRUE. The current message isn't in the queue; to get information about it, you must call BLooper's CurrentMessage() function:

       BMessage *current == myView->Window()->CurrentMessge();

    If GetKeys() takes a keyboard message from the queue, all the key_info fields are filled in from the message. However, if it captures the current state of the keyboard, the char_code and key_code fields are set to 0; these fields are appropriate only for reporting particular events.

    GetKeys() returns B_NO_ERROR if it was able to get the requested information, and B_ERROR if the return results are unreliable.

    See also: KeyDown(), Keyboard Information of the chapter introduction, modifiers()


    GetMouse()

          void GetMouse(BPoint *cursor, ulong *buttons, bool checkQueue = TRUE) const

    Provides the location of the cursor and the state of the mouse buttons. The position of the cursor is recorded in the variable referred to by cursor; it's provided in the BView's own coordinates. A bit is set in the variable referred to by buttons for each mouse button that's down. This mask may be 0 (if no buttons are down) or it may contain one or more of the following constants:

    B_PRIMARY_MOUSE_BUTTON
    B_SECONDARY_MOUSE_BUTTON
    B_TERTIARY_MOUSE_BUTTON

    The cursor doesn't have to be located within the view for this function to work; it can be anywhere on-screen. However, the BView must be attached to a window.

    If the checkQueue flag is set to FALSE, GetMouse() provides information about the current state of the mouse buttons and the current location of the cursor.

    If checkQueue is TRUE, as it is by default, this function first looks in the message queue for any pending reports of mouse-moved or mouse-up events. If it finds any, it takes the one that has been in the queue the longest (the oldest message), removes it from the queue, and reports the cursor location and button states that were recorded in the message. Each GetMouse() call removes another message from the queue. If the queue doesn't hold any B_MOUSE_MOVED or B_MOUSE_UP messages, GetMouse() reports the current state of the mouse and cursor, just as if checkQueue were FALSE.

    This function is typically called from within a MouseDown() function to track the location of the cursor and wait for the mouse button to go up. By having it check the message queue, you can be sure that you haven't overlooked any of the cursor's movement or missed a mouse-up event (quickly followed by another mouse-down) that might have occurred before the first GetMouse() call.

    See also: modifiers()


    HandlersRequested()

          virtual void HandlersRequested(BMessage *message)

    Responds to the B_HANDLERS_REQUESTED message passed as an argument by sending a B_HANDLERS_INFO message in reply. The reply message contains BMessenger objects for the BView's children in an entry labeled "handlers".

    If the received message contains an entry named "index", the BView provides a BMessenger for the child at that index. Otherwise, if the message contains an entry labeled "name", the BView provides a BMessenger for the child with that name. If the message contains neither an index nor a name, the BView places BMessengers for all its children in the "handlers" array of the reply.

    However, if the "index" or "name" doesn't successfully designate a child of the BView, or if the BView doesn't have any children, this function doesn't put any BMessengers in the reply message. Instead, it places an appropriate error code--B_BAD_INDEX , B_NAME_NOT_FOUND, or B_ERROR--in the message under the name "error".

    You can override this function to use different protocols for specifying child views, or to prevent the BView from revealing any information about its children.

    See also: BHandler::HandlersRequested()


    Hide(), Show()

          virtual void Hide(void)
          virtual void Show(void)

    These functions hide a view and show it again.

    Hide() makes the view invisible without removing it from the view hierarchy. The visible region of the view will be empty and the BView won't receive update messages. If the BView has children, they also are hidden.

    Show() unhides a view that had been hidden. This function doesn't guarantee that the view will be visible to the user; it merely undoes the effects of Hide() . If the view didn't have any visible area before being hidden, it won't have any after being shown again (given the same conditions).

    Calls to Hide() and Show() can be nested. For a hidden view to become visible again, the number of Hide() calls must be matched by an equal number of Show() calls.

    However, Show() can only undo a previous Hide() call on the same view. If the view became hidden when Hide() was called to hide the window it's in or to hide one of its ancestors in the view hierarchy, calling Show() on the view will have no effect. For a view to come out of hiding, its window and all its ancestor views must be unhidden.

    Hide() and Show() can affect a view before it's attached to a window. The view will reflect its proper state (hidden or not) when it becomes attached. Views are created in an unhidden state.

    See also: BWindow::Hide() , IsHidden()


    HighColor() see SetHighColor()


    Invalidate()

          void Invalidate(BRect rect)
          void Invalidate(void)

    Invalidates the rect portion of the view, causing update messages --and consequently Draw() notifications--to be generated for the BView and all descendants that lie wholly or partially within the rectangle. The rectangle is stated in the BView's coordinate system.

    If no rectangle is specified, the BView's entire bounds rectangle is invalidated.

    Since only BViews that are attached to a window can draw, only attached BViews can be invalidated.

    See also: Draw(), GetClippingRegion(), BWindow::UpdateIfNeeded()


    InvertRect()

          void InvertRect(BRect rect)

    Inverts all the colors displayed within the rect rectangle. A subsequent InvertRect() call on the same rectangle restores the original colors.

    The rectangle is stated in the BView's coordinate system.

    See also: system_colors() global function


    IsFocus()

          bool IsFocus(void) const

    Returns TRUE if the BView is the current focus view for its window, and FALSE if it's not. The focus view changes as the user chooses one view to work in and then another --for example, as the user moves from one text field to another when filling out an on-screen form. The change is made programmatically through the MakeFocus() function.

    See also: BWindow::CurrentFocus(), MakeFocus()


    IsHidden()

          bool IsHidden(void) const

    Returns TRUE if the view has been hidden by the Hide() function, and FALSE otherwise.

    This function returns TRUE whether Hide() was called to hide the BView itself, to hide an ancestor view, or to hide the BView's window. When a window is hidden, all its views are hidden with it. When a BView is hidden, all its descendants are hidden with it.

    If the view has no visible region--perhaps because it lies outside its parent's frame rectangle or is obscured by a window in front--this function may nevertheless return FALSE. It reports only whether the Hide() function has been called to hide the view, hide one of the view's ancestors in the view hierarchy, or hide the window where the view is located.

    If the BView isn't attached to a window, IsHidden() returns the state that it will assume when it becomes attached. By default, views are not hidden.

    See also: Hide()


    IsPrinting()

          bool IsPrinting(void) const

    Returns TRUE if the BView is being asked to draw for the printer, and FALSE if the drawing it produces will be rendered on-screen (or if the BView isn't being asked to draw at all).

    This function is typically called from within Draw() to determine whether the drawing it does is destined for the printer or the screen. When drawing to the printer, the BView may choose different parameters--such as fonts, bitmap images, or colors--than when drawing to the screen.

    See also: the BPrintJob class, Draw()


    KeyDown()

          virtual void KeyDown(ulong aChar)

    Implemented by derived classes to respond to a message reporting a key-down event. Whenever a BView is the focus view of the active window, it receives a KeyDown() notification for each character the user types, except for those that:

    The argument, aChar, names the character reported in the message. It's an ASCII value that takes into account the affect of any modifier keys that were held down or keyboard locks that were in effect at the time of the keystroke. For example, Shift-i is reported as uppercase 'I' (0x49) and Control-i is reported as a B_TAB (0x09).

    The character can be tested against ASCII codes and these constants:

    B_BACKSPACE B_LEFT_ARROW B_INSERT
    B_ENTER B_RIGHT_ARROW B_DELETE
    B_RETURN B_UP_ARROW B_HOME
    B_SPACE B_DOWN_ARROW B_END
    B_TAB B_PAGE_UP
    B_ESCAPE B_FUNCTION_KEY B_PAGE_DOWN

    B_ENTER and B_RETURN are the same character, a newline ('\n').

    Only keys that generate characters produce key-down events; the modifier keys on their own do not.

    You can determine which modifier keys were being held down at the time of the event by calling BLooper's CurrentMessage() function and looking up the "modifiers" entry in the BMessage it returns. If aChar is B_FUNCTION_KEY and you want to know which key produced the character, you can look up the "key" entry in the BMessage and test it against these constants:

    B_F1_KEY B_F6_KEY B_F11_KEY
    B_F2_KEY B_F7_KEY B_F12_KEY
    B_F3_KEY B_F8_KEY B_PRINT_KEY (Print Screen)
    B_F4_KEY B_F9_KEY B_SCROLL_KEY (Scroll Lock)
    B_F5_KEY B_F10_KEY B_PAUSE_KEY

    For example:

       if ( aChar == B_FUNCTION_KEY ) {
           BMessage *msg = Window()->CurrentMessage();
           long key = msg->FindLong("key");
           if ( msg->Error == B_NO_ERROR ) {
               switch ( key ) {
               case B_F1_KEY:
                   . . .
                   break;
               case B_F2_KEY:
                   . . .
                   break;
                . . .
               }
           }
       }

    The BView version of KeyDown() handles keyboard navigation from view to view through B_TAB characters. If the view you define is navigable, its KeyDown() function should permit B_SPACE characters to operate the object and perhaps allow the arrow keys to navigate inside the view. It should also call the inherited version of KeyDown() to enable between-view navigation. For example:

       void MyView::KeyDown(ulong aChar)
       {
           switch ( aChar ) {
           case B_SPACE:
               /* mimic a click in the view */
               break;
           case B_RIGHT_ARROW:
               /* move one position to the right in the view */
               break;
           case B_LEFT_ARROW:
               /* move one position to the left in the view */
               break;
           default:
               inherited::KeyDown(aChar);
               break;
           }
       }

    If your BView is navigable but needs to respond to B_TAB characters-- for example, if it permits users to insert tabs in a text string--its KeyDown() function should simply grab the characters and not pass them to the inherited function. Users will have to rely on the Option-Tab combination to navigate from your view.

    See also: Keyboard Information in the chapter introduction, B_KEY_DOWN in the Message Protocols appendix, BWindow::SetDefaultButton(), modifiers()


    LeftTop()

          BPoint LeftTop(void) const

    Returns the coordinates of the left top corner of the view--the smallest x and y coordinate values within the bounds rectangle.

    See also: BRect::LeftTop() , Bounds()


    LowColor() see SetHighColor()


    MakeFocus()

          virtual void MakeFocus(bool focused = TRUE)

    Makes the BView the current focus view for its window (if the focused flag is TRUE), or causes it to give up that status (if focused is FALSE). The focus view is the view that displays the current selection and is expected to handle reports of key-down events when the window is the active window. There can be no more than one focus view per window at a time.

    When called to make a BView the focus view, this function invokes MakeFocus() for the previous focus view, passing it an argument of FALSE. It's thus called twice--once for the new and once for the old focus view.

    Calling MakeFocus() is the only way to make a view the focus view; the focus doesn't automatically change on mouse-down events. BViews that can display the current selection (including an insertion point) or that can accept pasted data should call MakeFocus() in their MouseDown() functions.

    A derived class can override MakeFocus() to add code that takes note of the change in status. For example, a BView that displays selectable data may want to highlight the current selection when it becomes the focus view, and remove the highlighting when it's no longer the focus view. A BView that participates in the keyboard navigation system should visually indicate that it can be operated from the keyboard when it becomes the focus view, and remove that indication when the user navigates to another view and it's notified that it's no longer the focus view.

    If the BView isn't attached to a window, this function has no effect.

    See also: BWindow::CurrentFocus(), IsFocus()


    MouseDown()

          virtual void MouseDown(BPoint point)

    Implemented by derived classes to respond to a message reporting a mouse-down event within the view. The location of the cursor at the time of the event is given by point in the BView's coordinates.

    MouseDown() functions are often implemented to track the cursor while the user holds the mouse button down and then respond when the button goes up. You can call the GetMouse() function to learn the current location of the cursor and the state of the mouse buttons. For example:

       void MyView::MouseDown(BPoint point)
       {
           ulong buttons;
           . . .
           buttons = Window()->CurrentMessage()->FindLong("buttons");
           while ( buttons ) {
               . . .
               snooze(20.0 * 1000.0);
               GetMouse(&point, &buttons, TRUE);
           }
           . . .
       }

    It's important to snooze between GetMouse() calls so that the loop doesn't monopolize system resources; 20,000.0 microseconds is a minimum time to wait.

    To get complete information about the mouse-down event, look inside the BMessage object returned by BLooper's CurrentMessage() function. The "clicks" entry in the message can tell you if this mouse-down is a solitary event or the latest in a series constituting a multiple click.

    The BView version of MouseDown() is empty.

    See also: B_MOUSE_DOWN in the Message Protocols appendix, GetMouse()


    MouseMoved()

          virtual void MouseMoved(BPoint point, ulong transit, BMessage *message)

    Implemented by derived classes to respond to reports of mouse-moved events associated with the view. As the user moves the cursor over a window, the Application Server generates a continuous stream of messages reporting where the cursor is located.

    The first argument, point, gives the cursor's new location in the BView's coordinate system. The second argument, transit, is one of three constants,

    B_ENTERED_VIEW,
    B_INSIDE_VIEW, or
    B_EXITED_VIEW

    which explains whether the cursor has just entered the visible region of the view, is now inside the visible region having previously entered, or has just exited from the view. When the cursor crosses a boundary separating the visible regions of two views (perhaps moving from a parent to a child view, or from a child to a parent), MouseMoved() is called for each of the BViews, once with a transit code of B_EXITED_VIEW and once with a code of B_ENTERED_VIEW.

    If the user is dragging a bundle of information from one location to another, the final argument, message, is a pointer to the BMessage object that holds the information. If a message isn't being dragged, message is NULL.

    A MouseMoved() function might be implemented to ignore the B_INSIDE_VIEW case and respond only when the cursor enters or exits the view. For example, a BView might alter its display to indicate whether or not it can accept a message that has been dragged to it. Or it might be implemented to change the cursor image when it's over the view.

    MouseMoved() notifications should not be used to track the cursor inside a view. Use the GetMouse() function instead. GetMouse() provides the current cursor location plus information on whether any of the mouse buttons are being held down.

    The default version of MouseMoved() is empty.

    See also: B_MOUSE_MOVED in the Message Protocols appendix, DragMessage()


    MoveBy(), MoveTo()

          void MoveBy(float horizontal, float vertical)
          void MoveTo(BPoint point)
          void MoveTo(float x, float y)

    These functions move the view in its parent's coordinate system without altering its size.

    MoveBy() adds horizontal coordinate units to the left and right components of the frame rectangle and vertical units to the top and bottom components. If horizontal and vertical are positive, the view moves downward and to the right. If they're negative, it moves upward and to the left.

    MoveTo() moves the upper left corner of the view to point--or to (x, y)--in the parent view's coordinate system and adjusts all coordinates in the frame rectangle accordingly.

    Neither function alters the BView's bounds rectangle or coordinate system.

    None of the values passed to these functions should specify fractional coordinates; the sides of a view must line up on screen pixels. Fractional values will be rounded to the closest whole number.

    If the BView is attached to a window, these functions cause its parent view to be updated, so the BView is immediately displayed in its new location. If it doesn't have a parent or isn't attached to a window, these functions merely alter its frame rectangle.

    See also: FrameMoved() , ResizeBy(), Frame()


    MovePenBy(), MovePenTo() , PenLocation()

          void MovePenBy(float horizontal, float vertical)
          void MovePenTo(BPoint point)
          void MovePenTo(float x, float y)
    
          BPoint PenLocation(void) const

    These functions move the pen (without drawing a line) and report the current pen location.

    MovePenBy() moves the pen horizontal coordinate units to the right and vertical units downward. If horizontal or vertical are negative, the pen moves in the opposite direction. MovePenTo() moves the pen to point--or to (x, y )--in the BView's coordinate system.

    PenLocation() returns the point where the pen is currently positioned in the BView's coordinate system. The default pen position is at (0.0, 0.0).

    Some drawing functions also move the pen--to the end of whatever they draw. In particular, this is true of StrokeLine() , DrawString(), and DrawChar(). Functions that stroke a closed shape (such as StrokeEllipse()) don't move the pen.

    The pen location is a parameter of the BView's graphics environment, which the Application Server maintains. If the BView doesn't belong to a window, MovePenTo() and MovePenBy() cache the location, so that later, when the BView is attached to a window, it can be handed to the Server to become the initial pen location for the BView. If the BView belongs to a window, these functions alter the Server parameter, but don't change any value that may have previously been cached. PenLocation() returns the current pen position if the BView is attached, and the cached value if not.

    See also: SetPenSize()


    MoveTo() see MoveBy()


    NextSibling() see Parent()


    Parent(), NextSibling(), PreviousSibling(), ChildAt() , CountChildren()

          BView *Parent(void) const
          BView *NextSibling(void) const
          BView *PreviousSibling(void) const
          BView *ChildAt(long index) const
          long CountChildren(void) const

    These functions provide various ways of navigating the view hierarchy. Parent() returns the BView's parent view, unless the parent is the top view of the window, in which case it returns NULL. It also returns NULL if the BView doesn't belong to a view hierarchy and has no parent.

    All the children of the same parent are arranged in a linked list. NextSibling() returns the next sibling of the BView in the list, or NULL if the BView is the last child of its parent. PreviousSibling() returns the previous sibling of the BView, or NULL if the BView is the first child of its parent.

    ChildAt() returns the view at index in the list of the BView's children, or NULL if the BView has no such child. Indices begin at 0 and there are no gaps in the list. CountChildren() returns the number of children the BView has. If the BView has no children, CountChildren() returns NULL, as will ChildAt() for all indices, including 0.

    To scan the list of a BView's children, you can increment the index passed to ChildAt() until it returns NULL. However, it's more efficient to ask for the first child and then use NextSibling() to walk down the sibling list. For example:

       BView *child;
       if ( child = myView->ChildAt(0) ) {
           while ( child ) {
               . . .
               child = child->NextSibling();
           }
       }

    See also: AddChild()


    PenLocation() see MovePenBy()


    PenSize() see SetPenSize()


    PreviousSibling() see Parent()


    Pulse()

          virtual void Pulse(void)

    Implemented by derived classes to do something at regular intervals. Pulses are regularly timed events, like the tick of a clock or the beat of a steady pulse. A BView receives Pulse() notifications when no other messages are pending, but only if it asks for them with the B_PULSE_NEEDED flag.

    The interval between Pulse() calls can be set with BWindow's SetPulseRate() function. The default interval is around 500 milliseconds. The pulse rate is the same for all views within a window, but can vary between windows.

    Derived classes can implement a Pulse() function to do something that must be repeated continuously. However, for time-critical actions, you should implement your own timing mechanism.

    The BView version of this function is empty.

    See also: SetFlags(), the BView constructor, BWindow::SetPulseRate()


    RemoveChild()

          virtual bool RemoveChild(BView *childView)

    Severs the link between the BView and childView, so that childView is no longer a child of the BView. The childView retains all its own children and descendants, but they become an isolated fragment of a view hierarchy, unattached to a window.

    If it succeeds in removing childView, this function returns TRUE. If it fails, it returns FALSE. It will fail if childView is not, in fact, a child of the BView.

    Removing a BView from a window's view hierarchy also removes it from the BWindow's flat list of BHandler objects; the BView will no longer be eligible to handle messages dispatched by the BWindow.

    See also: AddChild(), RemoveSelf(), DetachedFromWindow()


    RemoveSelf()

          bool RemoveSelf(void)

    Removes the BView from its parent and returns TRUE , or returns FALSE if the BView doesn't have a parent or for some reason can't be removed from the view hierarchy.

    This function acts just like RemoveChild() , except that it removes the BView itself rather than one of its children.

    See also: AddChild(), RemoveChild()


    ResizeBy(), ResizeTo()

          void ResizeBy(float horizontal, float vertical)
          void ResizeTo(float width, float height)

    These functions resize the view, without moving its left and top sides. ResizeBy() adds horizontal coordinate units to the width of the view and vertical units to the height. ResizeTo() makes the view width units wide and height units high. Both functions adjust the right and bottom components of the frame rectangle accordingly.

    Since a BView's frame rectangle must be aligned on screen pixels, only integral values should be passed to these functions. Values with fractional components will be rounded to the nearest whole integer.

    If the BView is attached to a window, these functions cause its parent view to be updated, so the BView is immediately displayed in its new size. If it doesn't have a parent or isn't attached to a window, these functions merely alter its frame and bounds rectangles.

    See also: FrameResized() , MoveBy(), BRect::Width(), Frame()


    ResizingMode() see SetResizingMode()


    ScrollBar()

          BScrollBar *ScrollBar(orientation posture) const

    Returns a BScrollBar object that scrolls the BView (that has the BView as its target). The requested scroll bar has the posture orientation--B_VERTICAL or B_HORIZONTAL. If the BView isn't the target of a scroll bar with the specified orientation, this function returns NULL.

    See also: ScrollBar::SetTarget()


    ScrollBy(), ScrollTo()

          void ScrollBy(float horizontal, float vertical)
          void ScrollTo(BPoint point)
          void ScrollTo(float x, float y)

    These functions scroll the contents of the view.

    ScrollBy() adds horizontal to the left and right components of the BView's bounds rectangle, and vertical to the top and bottom components. This serves to shift the display horizontal coordinate units to the left and vertical units upward. If horizontal and vertical are negative, the display shifts in the opposite direction.

    ScrollTo() shifts the contents of the view as much as necessary to put point--or (x, y)--at the upper left corner of its bounds rectangle. The point is specified in the BView's coordinate system.

    Anything in the view that was visible before scrolling and also visible afterwards is automatically redisplayed at its new location. The remainder of the view is invalidated, so the BView's Draw() function will be called to fill in those parts of the display that were previously invisible. The update rectangle passed to Draw() will be the smallest rectangle that encloses just these new areas. If the view is scrolled in only one direction, the update rectangle will be exactly the area that needs to be drawn.

    These function don't work on BViews that aren't attached to a window.

    See also: GetClippingRegion()


    SetDrawingMode(), DrawingMode()

          virtual void SetDrawingMode(drawing_mode mode)
          drawing_mode DrawingMode(void) const

    These functions set and return the BView's drawing mode, which can be any of the following nine constants:

    B_OP_COPY B_OP_MIN B_OP_ADD
    B_OP_OVER B_OP_MAX B_OP_SUBTRACT
    B_OP_ERASE B_OP_INVERT B_OP_BLEND

    The drawing mode is one element of the BView's graphics environment, which the Application Server maintains. If the BView isn't attached to a window, SetDrawingMode() caches the mode. When the BView is placed in a window and becomes known to the Server, the cached value is automatically set as the current mode. If the BView belongs to a window, SetDrawingMode() changes the current drawing mode, but doesn't alter any value that may have been previously cached. DrawingMode() returns the current mode if the view is in a window, and the cached value if not.

    The default drawing mode is B_OP_COPY. It and the other modes are explained under Drawing Modes of the introduction to this chapter.

    See also: Drawing Modes in the chapter introduction


    SetFlags(), Flags()

          virtual void SetFlags(ulong mask)
          inline ulong Flags(void) const

    These functions set and return the flags that inform the Application Server about the kinds of notifications the BView should receive. The mask set by SetFlags() and the return value of Flags() is formed from combinations of the following constants:

    B_WILL_DRAW ,
    B_FULL_UPDATE_ON_RESIZE ,
    B_FRAME_EVENTS , and
    B_PULSE_NEEDED

    The flags are first set when the BView is constructed; they're explained in the description of the BView constructor.

    To set just one of the flags, combine it with the current setting:

       myView->SetFlags(Flags() | B_FRAME_EVENTS);

    The mask passed to SetFlags() and the value returned by Flags() can be 0.

    See also: the BView constructor, SetResizingMode()


    SetFontName(), SetFontSize() , SetFontRotation(), SetFontShear()

          virtual void SetFontName(const char *name)
          virtual void SetFontSize(float points)
          virtual void SetFontRotation(float degrees)
          virtual void SetFontShear(float angle)

    These functions set characteristics of the font in which the BView draws text. The font is part of the BView's graphics state. It's used by DrawString() and DrawChar() and assumed by StringWidth(), GetFontInfo(), and GetCharEdges().

    SetFontName() sets the precise name of the font, including the designation of whether it's bold, italic, oblique, black, narrow, or some other style. The name passed to this function must be the same as the name assigned to the font by the vendor. For example, this code

       SetFontName("Futura II Italic ATT");

    sets the BView's font to the TrueType(TM) italic Futura II font.

    For SetFontName() to be successful, the name it's passed must select a font that's installed on the user's machine. The global get_font_name() function can provide the names of all fonts that are currently installed. (Users can see the names listed in the Keyboard application's "Font" menu.)

    A handful of fonts are provided with the release, including Arial MT, Baskerville MT, Courier New, Times New Roman, and their stylistic variations. < Additional fonts can be installed by placing them in the proper subdirectory of /system/fonts and rebooting the machine. > The names of the bitmap fonts that come with the system are:

    Emily
    Erich
    Kate

    At present, they're available in only one size each--12.0 points for Emily and 9.0 points for Erich and Kate. Kate is the default font; it's built into the system. If you ask for a font that isn't available, you'll get Kate instead.

    < Currently, you must specifically ask for a bitmap font. In the future, bitmap equivalents to the outline fonts will be automatically provided for on-screen display. >

    SetFontSize() sets the size of the font. Valid sizes range from 4 points through 999 points. < Currently, fractional font sizes are not supported. >

    SetFontRotation() sets the rotation of the baseline. The baseline rotates counterclockwise from an axis on the left side of the character. The default (horizontal) baseline is at 0°. For example, this code

       SetFontRotation(45.0);
       DrawString("to the northeast");

    would draw a string that extended upwards and to the right. < Currently, fractional angles of rotation are not supported. >

    SetFontShear() sets the angle at which characters are drawn relative to the baseline. The default (perpendicular) shear for all font styles, including oblique and italic ones, is 90.0°. The shear is measured counterclockwise and can be adjusted within the range 45.0° (slanted to the right) through 135.0° (slanted to the left). < Currently, fractional shear angles are not supported. >

    The font name, size, rotation, and shear are all elements of the BView's graphics environment, which the Application Server maintains. If the BView isn't attached to a window, these functions cache the values they're passed so that later, when the BView is placed in a window and becomes known to the Server, the cached values can automatically be established as the current font parameters for the BView. If the BView belongs to a window, these functions alter the current parameters, but don't change any values that may have been previously cached.

    < The SetFontSize(), SetFontRotation() , and SetFontShear() functions don't work for bitmap fonts. >

    Derived classes can override these functions to take any collateral measures required by the font change. For example, BTextView and BListView override them to redisplay the text in the new font.

    See also: GetFontInfo() , AttachedToWindow(), get_font_name()


    SetHighColor(), HighColor() , SetLowColor(), LowColor()

          virtual void SetHighColor(rgb_color color)
          void SetHighColor(uchar red, uchar green, uchar blue, uchar alpha = 0)
    
          rgb_color HighColor(void) const
          virtual void SetLowColor(rgb_color color)
          void SetLowColor(uchar red, uchar green, uchar blue, uchar alpha = 0)
    
          rgb_color LowColor(void) const

    These functions set and return the current high and low colors of the BView. These colors combine to form a pattern that's passed as an argument to the Stroke ...() and Fill...() drawing functions. The B_SOLID_HIGH pattern is the high color alone, and B_SOLID_LOW is the low color alone.

    The default high color is black--red, green, and blue values all equal to 0. The default low color is white--red, green, and blue values all equal to 255. < The alpha component of the color is currently ignored. >

    The versions of SetHighColor() and SetLowColor() that take separate arguments for the red, blue, and green color components work by creating an rgb_color data structure and passing it to the corresponding function that's declared virtual. Therefore, if you want to override either of these functions, you should override the virtual version. (However, due to the peculiarities of C++, overriding any version of an overloaded function hides all versions of the function. For continued access to the nonvirtual version without explicitly specifying the "BView::" prefix, you'll need to reimplement it also.)

    The high and low colors are parameters of the BView's graphics environment, which is kept in the BView's shadow counterpart in the Application Server. If the BView isn't attached to a window, SetHighColor() and SetLowColor() cache the color value so that later, when the BView is placed in a window and becomes known to the Server, the cached value can automatically be established as the current high or low color for the BView. If the BView belongs to a window, they alter the current parameters, but don't change any values that may have previously been cached. HighColor() and LowColor() return the current parameters if the BView is in a window, and the cached values if not.

    See also: Patterns of the chapter introduction, SetViewColor()


    SetPenSize(), PenSize()

          virtual void SetPenSize(float size)
          float PenSize(void) const

    SetPenSize() sets the size of the BView's pen--the graphics parameter that determines the thickness of stroked lines--and PenSize() returns the current pen size. The pen size is stated in coordinate units, but is translated to a device-specific number of pixels for each output device.

    The pen tip can be thought of as a brush that's centered on the line path and held perpendicular to it. If the brush is broader than one pixel, it paints roughly the same number of pixels on both sides of the path.

    The default pen size is 1.0 coordinate unit. It can be set to any non-negative value, including 0.0. If set to 0.0, the size is translated to 1 pixel for all devices. This guarantees that it will always draw the thinnest possible line no matter what the resolution of the device.

    Thus, lines drawn with pen sizes of 1.0 and 0.0 will look alike on the screen (one pixel thick), but the line drawn with a pen size of 1.0 will be 1/72 of an inch thick when printed, however many printer pixels that takes, while the line drawn with a 0.0 pen size will be just one pixel thick.

    The pen size is a parameter of the BView's graphics environment maintained by the Application Server. If the BView isn't attached to a window, SetPenSize() caches the size so that later, when the BView is added to a window and becomes known to the Server, the cached value can automatically be established as the initial pen size for the BView. If the BView belongs to a window, this function changes the current pen size, but doesn't alter any value that may have previously been cached. PenSize() returns the current pen size if the BView is in a window, and the cached value if not.

    See also: The Pen and Picking Pixels to Stroke and Fill of the chapter introduction, StrokeArc() and the other Stroke... () functions, MovePenBy()


    SetResizingMode(), ResizingMode()

          virtual void SetResizingMode(ulong mode)
          inline ulong ResizingMode(void) const

    These functions set and return the BView's automatic resizing mode. The resizing mode is first set when the BView is constructed. The various possible modes are explained where the constructor is described.

    See also: the BView constructor, SetFlags()


    SetSymbolSet()

          virtual void SetSymbolSet(const char *name)

    Determines the set of characters that the BView can display. A symbol set maps graphic symbols (glyphs) to character values (ASCII codes). Sets differ mainly in which symbols they associate with character values beyond the traditional ASCII range (above 0x7f), though they sometimes also differ within the traditional range as well.

    The default symbol set is "Macintosh". However, there are many other possibilities to choose from, including:

    "ISO 8859/9 Latin 5",
    "Legal",
    "PC-850 Multilingual", and
    "Windows 3.1 Latin 2".

    The get_symbol_set_name() global function can provide a list of all currently available symbol sets.

    Except for the bitmap fonts, every font implements every symbol set. However, some fonts may not provide all the characters in every set.

    Derived classes can override this function to take any collateral measures required by the change in symbol set. For example, BTextView and BListView override it to recalculate how displayed text is laid out.

    The symbol set is part of the BView's graphics environment, which is to say that the Application Server maintains it. If the BView isn't attached to a window, SetSymbolSet() copies and caches the name so that later, when the BView is added to a window and becomes known to the Server, it can automatically be established as the BView's current symbol set. If the BView belongs to a window, this function changes the current symbol set, but doesn't alter any string that may have previously been cached.

    See also: SetFontName() , get_symbol_set_name()


    SetViewColor(), ViewColor()

          virtual void SetViewColor(rgb_color color)
          void SetViewColor(uchar red, uchar green, uchar blue, uchar alpha = 0)
    
          rgb_color ViewColor(void) const

    These functions set and return the background color that's shown in all areas of the view rectangle that the BView doesn't cover with its own drawing. When the clipping region is erased prior to an update, it's erased to the view color. When a view is resized to expose new areas, the new areas are first displayed in the view color. The default view color is white, which matches the background color of the window's content area.

    If you know that a BView will cover every pixel in the clipping region when it draws, you may want to avoid having the region erased to a color that will immediately be obliterated. If you set the view color to TRANSPARENT_32_BIT, the Application Server will not draw its background color before updates nor fill new areas with the background color. (Note that, despite the name, this doesn't make the view transparent--you can't see through it to what the view behind it would draw in that region.)

    If the view color is anything but white, the B_WILL_DRAW flag needs to be set, even if the BView does no other drawing except provide a background color. The flag informs the Application Server that there are specific drawing operations (in this case, a specific background color) associated with the view.

    The version of SetViewColor() that takes separate arguments for the red, blue, and green color components works by creating an rgb_color data structure and passing it to the corresponding function that's declared virtual. Therefore, you need override only the rgb_color version to augment both functions. (However, due to the peculiarities of C++, overriding any version of an overloaded function hides all versions of the function. For continued access to the nonvirtual version without explicitly specifying the "BView::" prefix, you'll need to reimplement it also.)

    < The alpha color component is currently ignored. >

    It's best to set the view color before the window is shown on-screen.

    The view color is a parameter of the BView's graphics environment, which the Application Server maintains. If the BView doesn't belong to a window, SetViewColor() caches the color it's passed so that later, when the BView is attached to a window, it can automatically be handed to the Server. If the BView belongs to a window, SetViewColor() alters the Server parameter, but doesn't change any value that may have previously been cached. ViewColor() returns the current parameter if the BView is attached, and the cached value if not.

    See also: The View Color of the introduction to the chapter, SetHighColor()


    Show() see Hide()


    StringWidth()

          float StringWidth(const char *string) const
          float StringWidth(const char *string, long length) const

    Returns how much room is required to draw length characters of string in the BView's current font. If no length is specified, the entire string is measured, up to the null character, '\0', which terminates it. The return value totals the width of all the characters. It measures, in coordinate units, the length of the baseline required to draw the string.

    This function works only for BViews that are attached to a window (since only attached views have a current font).

    See also: GetFontInfo() , GetCharEscapements()


    StrokeArc(), FillArc()

          void StrokeArc(BRect rect, float angle, float span, pattern aPatternction hides all versions of the function.  For 
    continued access to the nonvirtual version without explicitly specifying the "BView::" 
    prefix, you'll need to reimplement it also.)
    

    < The alpha color component is currently ignored. >

    It's best to set the view color before the window is shown on-screen.

    The view color is a parameter of the BView's graphics environment, which the Application Server maintains. If the BView doesn't belong to a window, SetViewColor() caches the color it's passed so that later, when the BView is attached to a window, it can automatically be handed to the Server. If the BView belongs to a window, SetViewColor() alters the Server parameter, but doesn't change any value that may have previously been cached. ViewColor() returns the current parameter if the BView is attached, and the cached value if not.

    See also: The View Color of the introduction to the chapter, SetHighColor()


    Show() see Hide()


    StringWidth()

          float StringWidth(const char *string) const
          float StringWidth(const char *string, long length) const

    Returns how much room is required to draw length characters of string in the BView's current font. If no length is specified, the entire string is measured, up to the null character, '\0', which terminates it. The return value totals the width of all the characters. It measures, in coordinate units, the length of the baseline required to draw the string.

    This function works only for BViews that are attached to a window (since only attached views have a current font).

    See also: GetFontInfo() , GetCharEscapements()


    StrokeArc(), FillArc()

          void StrokeArc(BRect rect, float angle, float span, pattern aPattern = B_SOLID_HIGH)
          void StrokeArc(BPoint center, float xRadius, float yRadius, float angle, float span, pattern aPattern = B_SOLID_HIGH)
    
          void FillArc(BRect rect, float angle, float span, 
             pattern aPattern = B_SOLID_HIGH)
          void FillArc(BPoint center, float xRadius, float yRadius, float angle, float span, pattern aPattern = B_SOLID_HIGH)

    These functions draw an arc, a portion of an ellipse. StrokeArc() strokes a line along the path of the arc. FillArc() fills the wedge defined by straight lines stretching from the center of the ellipse of which the arc is a part to the end points of the arc itself. For example:

    The arc is a section of the ellipse inscribed in rect--or the ellipse located at center, where the horizontal distance from the center to the edge of the ellipse is measured by xRadius and the vertical distance from the center to the edge is measured by yRadius.

    The arc starts at angle and stretches along the ellipse for span degrees, where angular coordinates are measured counterclockwise with 0° on the right, as shown below: