Book Contents Previous Chapter Next Chapter
This chapter describes viewables, objects that are members of class Viewable. All objects displayed on the screen by Magic Cap are members of class Viewable; that is, they are instances of classes that descend from class Viewable. This chapter also describes what happens when the user touches viewables on the screen.
Some viewables
Viewable classes perform the tasks of managing objects on the screen. Many of these tasks are related to drawing and redrawing viewables and involve x-y coordinates, viewable parts, hiliting, labels, images, shadows, and visibility and other viewable states. In addition, viewables work with tools to handle user touches, including selection, moving, copying, stretching, and dropping viewables.
This section presents fundamental concepts that include basic data structures for describing x-y coordinates and the component parts of viewables. These topics together describe the geometry of viewables.
Magic Cap imposes an x-y coordinate plane and places viewables on that plane. Magic Cap represents points on the coordinate plane with the data type Dot. For simplicity and unlike most elements in Magic Cap, dots are simple data structures rather than objects. Type Dot is defined as follows:
typedef struct { long h; long v; } Dot;
A dot simply consists of the x and y coordinates (represented by the h and v fields, respectively) that identify a point on the coordinate plane.
Magic Cap also defines type Box for describing rectangles on the coordinate plane. Boxes, like dots, are defined as simple data structures rather than as a class of objects. Following is the definition for type Box:
typedef struct { long left; long top; long right; long bottom; } Box;
A box is defined by specifying the x-y coordinates that describe its upper-left and lower-right corners.
NOTE: Magic cap also defines a class Box, which is a simple framed viewable. Type Box and class Box are not related, so be sure not to confuse the two.
Magic Cap uses x-y coordinates to specify the location of viewables. For more information on x-y coordinates and the coordinate plane, see the section X-Y Coordinates below.
Viewables are divided into various parts. Some of a viewable's parts are associated with distinct objects related to the viewable. For example, each viewable can have a shadow, described by a shadow object that is an attribute of the viewable. The following figure shows an example viewable: an image with a border, a shadow, and a label.
An example viewable
There are three important rectangles associated with each viewable. Magic Cap uses type Box to represent each rectangle. The content box describes the main part of the viewable; for example, a stamp's content box encloses its image. The border box indicates the part a viewable where the outer edge of its border is drawn if it has a border. Many viewables have no borders; the border boxes of those viewables are the same as their context boxes. The bounds box encloses the viewable and all adornments drawn with the viewable, including its label, border, and shadow.
Boxes are indicated by thin gray lines
Magic Cap provides operations to get and set the boxes in viewables: ContentBox and SetContentBox for the content box, BorderBox to get the border box, and BoundsBox to get the bounds box.
The border box and bounds box can't be set directly. Instead, they are changed indirectly when you change the content box with SetContentBox. You can customize how the boxes are computed by overriding CalcContentBox, CalcBorderBox or CalcBoundsBox.
You can also set the content's width and height separately by calling SetContentWidth and SetContentHeight. You can determine the width and height of the content box separately by calling ContentHeight and ContentWidth.
You can determine the absolute size of the content box in pixels by calling ContentSize, and you can set the size of the content box with SetContentSize.
You can use AdjustSize to have objects of your viewable subclass recalculate their content box when you perform some action on them. To do this, override AdjustSize to perform the calculation that resizes the content box, and call AdjustSize after taking the action that should cause the viewable to resize its content.
Each viewable can have a border drawn outside its content box. The viewable's border box encloses the viewable and its border. The viewable's Border attribute provides access to its border. Users can add borders to most viewables by dropping border coupons on them. The following figure shows several examples of viewables with borders.
Viewables with borders
NOTE: Although viewables provide a Border attribute, support for borders is incomplete in class Viewable. To add borders, your viewable subclass should inherit from mixin class HasBorder. See the Borders and Shadows section of this chapter for more information.
When the user slides a viewable on the screen, Magic Cap draws the viewable with a shadow as a visual cue to indicate that it has temporarily been lifted above other objects on the screen as it is being moved. When the user stops sliding the viewable, the shadow disappears. In addition to this temporary shadow, viewables can have a shadow that is always drawn, even when the viewable isn't being moved. For example, windows are drawn with a shadow, and users can add shadows to most viewables by dropping shadow coupons on them. The viewable casts its shadow downward and to the right, as if the light source were at the upper-left corner of the screen. The viewable's Shadow attribute provides access to its shadow. The following figure shows some examples of viewables with their shadows.
Viewables with shadows
Each viewable has a label that can display the viewable's name. A viewable can display its label at any one of 15 different positions, as shown in the following figure.
Available label positions
Labels can have borders. In the preceding figure, label positions 0 through 7, 13, and 14 are shown with borders. Although every viewable has a label, many viewables don't display their labels in any position.
You can show or hide the label, change the label's location, change the label's text with a text coupon from the keyboard's label maker, or turn its border on or off by tinkering with the viewable in Magic Cap Simulator. You can call SetTextData to change the label's text; call Label to get the label's text. You can use the ShowLabel attribute to get and set whether the label is shown, and the LabelLoc attribute gets and sets the position of the viewable's label. The BorderLabel attribute gets and sets whether the label is drawn with a border. The CanShowLabel attribute determines if the viewable's label should ever be shown. You can override CanShowLabel in your viewable subclasses to prevent the label from ever appearing. You can get or set the label's text style by using the ContentTextStyle attribute.
When the user touches a viewable on the screen, Magic Cap determines which viewable was touched, then asks the viewable to determine which part of it was touched. These topics are covered in detail in this chapter's Touching Viewables section. See the Hit Testing section for more information about parts of viewables.
This section describes how viewables can be related and connected. These relationships determine how viewables are drawn and how they behave when users touch them.
Viewables can be connected together in an ordered list. When the viewables are drawn, this list determines their back-to-front positions on the screen. This list is maintained by the viewables themselves rather than by a separate list object. Each viewable keeps track of the viewable behind and in front of itself. A list of viewables connected together in this way is called a view chain.
Given a viewable, you can call its Next operation to get the viewable in front of it in its view chain, or its Previous operation to get the viewable behind it in its view chain. If a viewable is rearmost or frontmost in its list, the appropriate operation returns nil. When the user rearranges viewables on the screen and changes their back-to-front positioning, Magic Cap updates the viewables to reflect their changed order, and Next and Previous return the updated information.
Viewables can also be associated by a containment relationship. If a viewable is contained by another, it is drawn inside its container, and its appearance is clipped to its container; that is, no part of it is drawn that would appear outside its container. Graphically, a viewable contained by another appears to be tucked inside its container, as shown in the following figure.
Viewables clipped by their container
A viewable contained by another is the subview of its container. A viewable that contains another is the superview of its contained object. Given a viewable, you can call its Superview operation to get its containing viewable, or its FirstSubview operation to get its rearmost contained object. If a viewable has no container or no contained object, the appropriate operation returns nilObject.
When the user rearranges viewables on the screen and changes their containment relationship by sliding viewables into and out of other viewables, Magic Cap updates the viewables to reflect their changed status, and Superview and FirstSubview return the updated information. You can call SwitchContainer to remove a viewable from its container and install it in another container. If a viewable has no subview, its Empty attribute returns true.
As with view chains, the containment relationships are maintained by the viewables themselves, rather than separate controlling objects: each viewable keeps track of its superview and subview.
Each viewable can refer to exactly one subview. However, a contained viewable may be part of a view chain. In that case, all the viewables in the chain are considered subviews of the same superview. Every subview refers to its superview. The superview refers to a subview, always the rearmost (first) view in its chain. Viewable relationships are shown in the following figure.
Viewables in a view chain
You should avoid setting your viewable's subview to a viewable that is not rearmost in its view chain. Magic Cap expects a viewable's subview to be rearmost in its view chain.
Call AddBefore or AddAfter to insert a new viewable in a view chain, AddFirst to add a new viewable to the beginning of the chain, or AddLast to add a new object to the end of the chain. These operations are inherited from classes SingleLinkable and Linkable, both ancestors of viewables.
Before adding a viewable to the view chain, be sure the viewable you're about to add has no subviews. To add a viewable that has subviews, first detach the subviews by calling Unlink, then add the new viewable to the chain, then restore the subviews by calling SetSubview.
You can disable a viewable's ability to act as a superview: use the CanContain attribute to get or change the setting of a viewable's superview capability. If you want to create a subclass of viewable with objects that should never be made frontmost in their view chain, you can override their CanBringToFront attribute to return false. For example, cards override CanBringToFront to always return false, ensuring that cards are never brought to the front of their view chain.
This section describes how viewables are grouped together into view chains and containment relationships to form complex collections of objects. This section also describes the most important such collection of viewables: the one that contains the viewables on the screen.
Viewables are often collected into a view hierarchy, a potentially complex group of viewables that can include multiple view chains and containment relationships. The viewables on the Magic Cap screen are an example of a view hierarchy.
Magic Cap defines exactly one object of class Screen. This screen object is the ultimate superview of all viewables that are drawn on the Magic Cap screen. The screen and its subviews form the screen view hierarchy, which contains all the objects visible to the user. If a viewable is drawn on the screen, it is in the screen view hierarchy. You can test whether a viewable is in the screen view hierarchy by using the OnScreen attribute. However, not every viewable in the screen view hierarchy is necessarily drawn on the screen: a viewable may have coordinates that place it off the screen, for example.
All implementations of Magic Cap 1.0 have a screen size of 480 by 320 pixels. Future versions may support other screen sizes. One pixel equals 256 microns (a micron is one millionth of a meter). You can convert micron values to pixels with the MicronToPixel macro defined by Magic Cap. If you must put explicit coordinate values in your package, you can use this macro to specify the values in microns, then convert them to pixels at runtime, making your package more independent of changes to Magic Cap screens in future versions.
The screen isn't the only example of a view hierarchy. There are many other collections of viewables, assembled into view hierarchies offscreen, which are drawn on the screen at the appropriate time. For example, a simple view hierarchy might be assembled for a window that displays an announcement to the user. This hierarchy might include an image, a text object, and the window itself. When the appropriate situation arises for displaying the window, it is added to the screen view hierarchy and shown on the screen.
The user can change containment and back-to-front ordering by moving viewables around on the screen. The user can deposit a viewable into a willing container simply by sliding it to that new container. In addition, whenever the user moves a viewable, the viewable is brought to the front of its view chain.
When you create packages, you'll specify most of your viewables at build time in instance definition files. You'll use these instance definitions to organize your viewables into various view hierarchies. Magic Cap will place these viewables into the screen view hierarchy when they are needed, according to user actions or your package's code.
For example, suppose you create a package that installs a door in the Magic Cap hallway. When the user opens the door to start using your package, Magic Cap installs your package's scene and its subviews in the screen view hierarchy. Your scene is installed as the first subview of the screen. The screen's other subviews (the name bar and the control bar) are installed in front of your scene.
Because the first subview is rearmost, the name bar and the control bar will always be drawn over the scene if the bars and the scene overlap, making sure they are always visible. To avoid this overlap, you should create your scene in your instance definition file with a content size of 480 by 256 pixels to ensure that it fits between the name bar and the control bar in Magic Cap 1.0.
Magic Cap defines x-y coordinates that indicate the positions of viewables on the screen. Each viewable denotes its position by expressing its own center point as a position relative to its superview's center point. In this way, every viewable that contains other viewables imposes its own local coordinate system on its subviews. Magic Cap assigns coordinate 0,0 (the origin) to the center of every superview.
NOTE: The location of the origin is an arbitrary choice in any graphics system. The center was chosen as the origin for viewables as part of an overall design strategy for fast viewable drawing in Magic Cap.
X-coordinate values increase from left to right, and y-coordinate values increase from top to bottom. Coordinates are always expressed in microns. You can convert from microns to pixels with the MicronToPixel macro.
Although coordinate values are expressed in microns in Magic Cap, you will find it much more convenient to define them in pixels in your instance definition file. To specify fields of this type, use a pair of values enclosed in angle brackets. If you include a decimal point after the whole-number portion of a value, ObjectMaker will assume the value is in pixels and will automatically convert it microns at build time. To specify a value in microns, do not include a decimal point.
Following are examples of coordinate values specified in pixels:
Instance MiniViewable relativeOrigin: <3.0,-19.5>; // pixels contentSize: <292.0,23.0>; // pixels End Instance;
When you use the Inspector to view objects at runtime, coordinates are always displayed as pixels. If you examine the actual values in memory using a debugger, you'll see that they are stored as microns.
Because viewables express their origin in coordinates relative to their superview, the origin is known as the relative origin. Magic Cap provides the RelativeOrigin and SetRelativeOrigin operations to get and set a viewable's relative origin.
You can also get and set the viewable's origin in global coordinate, which are coordinates relative to the upper-left corner of the screen. Call Origin to get the origin of the viewable in global coordinates; call SetOrigin to set a new origin for the viewable, using global coordinates. When you use global coordinates, x-coordinate values increase from left to right and y-coordinate values increase from top to bottom, as with local coordinates.
You can find out the absolute height and width of a viewable's content box by calling Thickness.
The following figure shows an example of a screen view hierarchy.
A sample view hierarchy
This figure shows a modified screen from the Hello World sample package. The following view hierarchy describes this screen (indented lines indicate subviews):
The ultimate superview is the screen object, which is always the outermost container of viewables displayed on the screen. By convention, the screen's first subview is always a scene object, containing everything except the bars at the top and bottom of the screen.
The scene's first subview is the viewable named "Hello Concepts", and the next subview is the outer box. The outer box's subviews are two stamps and another box, and the inner box has two subviews itself, both switches. Note that in general, the deeper a viewable is in the hierarchy, the smaller its area: the screen object fills the entire screen; the scene encloses the area between the top and bottom bars; the subviews cover a smaller area.
Viewables that have the same superview are connected in a view chain. In this example, the scene, name bar, and control bar have the same superview (the screen), so they form a view chain. Other view chains in the example include the "Hello Concepts" viewable and the outer box; the two stamps and the inner box; and the two switches.
To demonstrate how viewables use their relative origins, the view hierarchy above is repeated below, this time including the relative origin of each viewable in pixels. Remember that the upper-left corner of the screen is location 0,0.
Each viewable's relative origin indicates the distance between its center and its superview's center. A viewable with two positive coordinates in its relative origin, such as the "good night" stamp in the hierarchy above, is centered below and to the right of the center of its superview (the "outer" box), while a viewable with two negative coordinates, such as the "try" switch, is centered above and to the left of the center of its superview (the "inner" box).
If a viewable has 0,0 as its relative origin, its center is at the same location as its superview's center.
This section discusses how to ensure that viewables are drawn and redrawn appropriately on the screen. This section also includes information on how to implement drawing if you create your own subclass of viewable.
When the user manipulates viewables, Magic Cap takes care of redrawing the viewables that are affected by the user's action - you don't have to take any action to make sure the screen is redrawn correctly. The process for drawing Magic Cap viewables is typically as follows:
Magic Cap asks a viewable to draw itself by calling its Draw operation. You should override Draw if you create a subclass of Viewable that defines objects drawn differently than objects of its superclass.
This automatic redrawing takes place whether the viewables are system objects, such as built-in stamps, or viewables created by packages, including your own packages. You can implement Draw in any viewable subclasses you create, and Magic Cap will call it automatically when your viewables have to be drawn.
Viewables define many operations that change their appearance, such as SetHilited, Hop, SetName, SetVisible, and SwitchContainer. Every operation that changes a viewable also ensures that the viewable is redrawn - you don't have to take any action to update the screen.
However, if you perform redrawing in an unusual way, such as by changing the fields of a viewable directly, you may have to take action yourself to make sure the the changed viewable is redrawn correctly. Magic Cap provides a set of operations you can call to ensure that the viewable is redrawn, as follows:
operation DirtyBox(dirtyBox: Box); // Part of the viewable or subview has changed operation DirtyContent(); // The content part of the viewable has changed operation DirtyBounds(); // The viewable has changed; all of it must be redrawn operation DirtyHide(); // The viewable is going away, moving, or changing operation DirtyShow(); // The viewable is about to appear or reappear
You can call these operations when you want to force all or part of a viewable or its subviews to be redrawn. When you call one of these dirtying operations, you inform Magic Cap that part of the screen is no longer drawn correctly and must be redrawn. The dirtying calls don't actually redraw anything. Instead, they mark parts of the screen as needing redrawing. Magic Cap updates the dirty parts of the screen by calling the Draw operation of the appropriate viewables at idle time - when no other actions are pending - or immediately when the user switches scenes. For more information on these operations, see the Viewable chapter of Magic Cap Class and Method Reference.
If you want to force Magic Cap to redraw the dirty parts of the screen immediately, without waiting for the next periodic update, you can call RedrawNow. This operation asks all dirty viewables to redraw at once. To avoid slowing down Magic Cap unnecessarily, you should call RedrawNow only when you want to redraw all the dirty viewables on the screen immediately.
As mentioned above, Magic Cap calls a viewable's Draw operation if the viewable has been marked dirty and must be redrawn. Although class Viewable defines operation Draw, no method is included for it. Instead, concrete viewable subclasses must override Draw to perform their drawing action.
When you override Draw, you can use several techniques to perform your drawing. If your viewable contains an image that rarely or never changes, you can use the Image attribute to associate your viewable with an image. If you do, you should call DrawShadowedImage in your subclass to draw the viewable's image along with its shadow, if any. Class Stamp uses this technique. Each stamp has an image, and Stamp_Draw simply calls DrawShadowedImage.
If your viewable is more dynamic and can't be described by an image, you can use Magic Cap's graphics operations to perform drawing in its Draw override. Class Canvas defines many graphics operations you can use, including FillBox, CopyPixels, and InvertBox. For more information on class Canvas and graphics operations, see the appropriate chapters of Magic Cap Class and Method Reference.
When a viewable is drawn, Magic Cap ensures that only the appropriate area of the screen changes, prohibiting any drawing from taking place outside the bounds of the viewable. The process of restricting drawing to a given area is called clipping. Whenever a viewable is drawn, a clipping path defines the area in which drawing will occur.
When Magic Cap calls Draw to ask a viewable to draw itself, it passes a clipping path to limit the drawing that will take place. Magic Cap forms this clipping path by computing the area of the viewable that is not covered by any objects in front of it. When you override Draw, any drawing you do will automatically be limited to the area described by the clipping path.
Although Magic Cap prevents anything from being drawn outside the clipping path, it takes some time to perform drawing, even if the drawing is clipped and never appears on the screen. If you can use logic inside your Draw override to determine that some part of your viewable need not be drawn, you should simply avoid drawing that part.
You may also be able to speed up your drawing if you can reduce the area of the clipping path. Normally, you'll just draw and let Magic Cap's clipping mechanism prevent anything from being drawn outside the clipping path. If you know that some additional part of the viewable should be clipped, you can modify the clipping path with operations of class Path before passing it on to graphics operations.
Call Clipped to determine if a particular box in the viewable is clipped by its superviews or subviews.
When the user takes an action that involves a momentary selection of a viewable, such as holding a border coupon over a box before dropping it in, sliding a telecard to the out box, or tapping a button, one of the viewable involved is drawn in a special highlighted state to indicate that something is about to happen to it. Magic Cap provides support for highlighting viewables and redrawing them in their normal state when appropriate. Class Viewable defines the Hilited attribute, but you must create a subclass if you want your viewables to draw in a highlighted state.
You can use the Hilited attribute to get and set a viewable's highlighted state. If you create your own viewable subclasses, you can use this attribute in your Draw override to determine whether the viewable is highlighted.
Each viewable includes a main color and an alternate color. Viewable subclasses decide how to use these two colors for each part of the viewable. The main color is typically used to fill the viewable. The alternate color is often not used at all, or is used if the viewable draws its parts in two different colors. The label's color is determined by the text style of the label, and the shadow's color comes from the shadow object.
Call PartColor to determine the color for a particular part of the viewable, or SetPartColor to change the color of a part. If you create a viewable subclass with additional parts, you can override PartColor and SetPartColor to handle the colors for the new parts. When the user drops a color coupon on a viewable, the coupon calls SetPartColor to change the viewable's color.
Magic Cap provides an elaborate system for converting user touches on the screen into actions. This section describes in detail what happens when the user touches the screen, the effects of the current tool on the touching process, and what happens when the user slides and drops viewables. This section doesn't cover lower-level details of user touches.
When the user touches the screen, Magic Cap calls Touching, Tap, Action, Press, Pressing, and Pressed at appropriate times during the touching process. You can override these operations to perform an action at a particular time in the touching process. The most commonly overridden operation is Action.
The Action operation is used to perform an object's typical or usual function. For example, the keyboard gadget at the bottom of the screen overrides Action to display the onscreen keyboard. The overridden Action also checks the option key to determine whether the advanced keyboard should appear. You can override Action to make a viewable perform a particular function.
Action is often overridden by writing a Magic Script for a particular viewable. When you create a Magic Script for an object, you effectively create a subclass of the object with your script installed as an overridden implementation of the corresponding operation of the class.
You might override MovePress, CopyPress, or StretchPress if you want to perform a special action when the user touches a viewable with the move, copy, or stretch tool. See the section Touching with the Arranging Tools for more information.
When the user slides a viewable across the screen, Magic Cap calls DragTrack to track the touch and handle all actions as the viewable slides.
As the user moves the viewable, DragTrack repeatedly determines which viewable is immediately under it on the screen and checks to see if that underlying viewable, called the target, is interested in the viewable that the user is sliding. When the user finally releases the sliding viewable, one of three things happens to it, depending on the target:
As the user begins to slide the viewable, DragTrack calls HitTest to determine the target, then calls Swallow on the target to ask if the target is interested in accepting the sliding viewable and performing some action with it. If the target doesn't want to swallow, DragTrack calls CanAcceptCoupon on the target to ask if it will accept the sliding viewable as a coupon. If the target refuses to accept the sliding viewable as a coupon, DragTrack calls CanAccept to check whether the target will simply accept the sliding viewable as a subview.
If the target won't swallow the sliding viewable or accept it as a subview or coupon, DragTrack asks the target's superview about its interest, repeating recursively for the superview when the sliding viewable is rejected. The screen, the ultimate object in the onscreen view hierarchy, will accept any object as a subview.
This process of asking the prospective viewable about its interest in the sliding viewable is used to provide user interface feedback during the sliding process. For example, targets are usually drawn highlighted when they show an interest in swallowing or accepting the sliding viewable, and DragTrack plays sounds to indicate that the sliding viewable has been copied, has left its container, or has been dropped into a new container.
Every time the user moves the sliding viewable, DragTrack calls HitTest again to determine the target, then repeats the process of asking the target about its interest. When the user releases the sliding viewable, DragTrack finishes the tracking process by calling the sliding viewable's Pressed operation. The action that takes place depends on the interest expressed by the target.
If the target doesn't want to swallow or accept the sliding viewable, it can express two kinds of refusal, depending on the value it returns for Swallow or CanAccept. Usually, a disinterested target returns kCantSwallow or kCantAccept. If the user releases the sliding viewable at that point, it simply stays where it's released and becomes a subview of the frontmost view that accepts subviews. Scenes always accept subviews, so the viewable becomes a subview of the scene if all viewables in front of the scene reject it.
If the user releases the touch and the target returns kSpitOut, the sliding viewable hops back to its original position and DragTrack calls SpatOut to give the target a chance to perform some action, such as posting an announcement. Depending on the target's preference, one of the following actions takes place:
When a touch has been classified as one that will allow the user to slide a viewable across the screen, Magic Cap calls the viewable's DragTrack operation. DragTrack is large and complex, handling the many cases of moving viewables out of and into containers, keeping track of various flags, determining whether containers can accept objects, and much more.
You should never override DragTrack, except to perform some action before or after calling the inherited implementation. Instead, you can customize its action by overriding some of the many operations it calls. For example, you can override CanChangeContainers to indicate whether the viewable can move to a new container.
When the stretch tool is current and a touch has been classified as one which will allow the user to slide a viewable across the screen, Magic Cap calls the viewable's StretchTrack operation. StretchTrack handles the details of resizing the viewable as the user slides along the screen. You might override StretchTrack if you want to change the way your viewables are resized. For more information on overriding StretchTrack, see its description in the Viewable chapter of Magic Cap Class and Method Reference.
This section provides advanced information about the touching process. Most programmers won't need all the detailed information in this section.
Magic Cap maintains the current tool as a way to determine or modify what happens when the user touches the screen. Many tools are visible to users, such as the pencils, lines, shapes, move, copy, and stretch tools available by touching the tool holder at the bottom of the screen. Other tools are invisible and not directly selectable by the user. For example, when the user is going through a lesson from Magic Cap's Getting Started book, a special tool (iLessonTool) is used to ensure that the user touches the right places on the screen. You can determine the current tool by reading iCurrentTool.
Even if the user hasn't chosen a tool, Magic Cap still has a current tool that takes part in the touching process. This default tool is the touch tool, specified by iTouchTool.
When the user touches the screen, Magic Cap determines which viewable has been touched. This viewable is called the target of the touch. The tool, the target, and the other viewables on the screen participate in deciding what action will take place in response to the touch.
When the user touches the screen, Magic Cap creates a touch input object that describes the touch. The touch input object calls the current tool's ChooseableTool_GetToolTarget operation to determine which viewable was touched and sets the target to be that viewable. After setting the target, the tool's GetToolTarget operation continues and calls the target's ConstrainToolTarget operation. This gives the target a chance to perform any actions, including changing the tool or the target itself.
The tool calls ConstrainToolTarget for the target's superview recursively; that is, it calls ConstrainToolTarget for all of the target's superviews up to and including the screen object. If any viewable changes the tool, the tool stops calling ConstrainToolTarget for that touch. If any viewable changes the target, the tool calls ConstrainToolTarget for the new target and its superviews. This process determines which tool and target will be used to handle the user touch.
When the tool calls ConstrainToolTarget, it passes a pointer to the current tool. You can override ConstrainToolTarget to make it change the tool, customizing the behavior that occurs when the user touches your viewable. For example, class Drawers overrides ConstrainToolTarget to change the tool to the touch tool unless the user is holding down the option key. This allows touches on drawers in the stamper to open a drawer no matter what the current tool is.
After the tool and target are determined, Magic Cap calls the tool's TouchTarget operation. This gives the tool a chance to influence the touch handling. Many specialized tools handle the action of the user touch in their TouchTarget operation. For example, pencils and all other drawing tools handle the drawing process entirely in their TouchTarget operation.
The arranging tools - move, copy, stretch, and touch - do not perform their action in TouchTarget. Instead, these tools call operations of the target: MoveTouch, CopyTouch, StretchTouch, and Touch, respectively. You can override these operations to further control the touching process in your viewable subclass.
The most commonly used arranging tool is the touch tool, implemented by class TouchTool. When the user touches a viewable with the touch tool, the tool's TouchTarget operation calls the viewable's Touch operation to classify the touch as either a tap or a press. This classification is based on whether the user moves the touch a specified distance without releasing. Once the user has moved the specified distance, 20 pixels by default, the touch is classified as a press. If the user releases the touch without moving this distance, the touch is classified as a tap.
NOTE: The TapPressCriteria operation allows you to change the default distance for classifying a touch from the default value of 20 pixels. TapPressCriteria also allows you to classify a touch based on the length of time the user has touched the viewable. See the Viewable chapter of Magic Cap Class and Method Reference for more information about TapPressCriteria.
Touch calls the viewable's TouchKind operation to classify the touch. TouchKind returns immediately, without necessarily waiting long enough to classify the touch. TouchKind returns one of the following symbolic constants:
TouchKind returns dontKnow if the user is touching a viewable, but has not yet moved it 20 pixels or released it. If TouchKind returns dontKnow, Touch calls Touching to allow the viewable to take some action before the touch is classified, then TouchKind, repeating these two calls until the touch is classified.
If the touch is classified as a tap, the Tap operation is called, which plays the viewable's sound and call its Action operation.
If the touch is classified as a press, the viewable calls the Press operation, which calls Touching and Pressing repeatedly until the press is done, then calls Action, then calls Pressed to indicate that the press is done. You can override Touching, Tap, Action, Press, Pressing, and Pressed to customize your viewable subclass's behavior when the user touches with the touch tool and those operations are called.
Press calls AutoMove to determine if the viewable is one that that the user can slide across the screen without having to use the move tool. For example, class Stamp overrides AutoMove to return true, allowing users to slide stamps without requiring the move tool.
The move tool's behavior is implemented by class MoveTool, and the copy tool's behavior is implemented by class CopyTool. When the user touches a viewable with the move or copy tool, the tool's TouchTarget operation calls the viewable's MoveTouch or CopyTouch operations, respectively. Both MoveTouch and CopyTouch call TouchKind to classify the touch. Unlike Touch, they don't call Touching repeatedly before the touch is classified.
If the touch is classified as a tap, both MoveTouch and CopyTouch call Touch, which then calls Tap. If the touch is classified as a press, MoveTouch and CopyTouch call MovePress and CopyPress respectively. Both MovePress and CopyPress call the viewable's DragTrack operation, which tracks the user's touch across the screen, moving or copying the viewable as appropriate. DragTrack makes sure that dirty viewables are redrawn when necessary.
The stretch tool's behavior is implemented by class StretchTool. When the user touches a viewable with the stretch tool, the tool's TouchTarget operation calls the viewable's StretchTouch operation. StretchTouch calls TouchKind to classify the touch. Unlike Touch, it doesn't call Touching repeatedly before the touch is classified.
If the touch is classified as a tap, StretchTouch calls Touch, which then calls Tap. If the touch is classified as a press, StretchTouch calls StretchPress. StretchPress calls the viewable's StretchTrack operation, which tracks the user's touch, stretching the viewable appropriately. StretchTrack makes sure that dirty viewables are redrawn when necessary.
When the user touches the screen, Magic Cap creates a touch input object that describes the touch. As the touch is handled, the touch input object is passed to many of the operations described above, including ConstrainToolTarget, Touch, Tap, and Press. The touch input object provides information about the touch, including the touch's starting and ending points and the status of the option key when the touch was made.
You can call TapHere and TapCenter to simulate touches. These operations create touch input objects that cause Magic Cap to behave just as if the user had tapped the given location. Call TapHere to simulate a tap at a particular coordinate. Calling TapCenter simulates a tap at the center of a given viewable.
In addition to acting as targets, viewables can act as tools themselves. Although you probably don't think of viewables as tools, you can give a viewable the ability to act as a tool so that it can make the ultimate decision about what happens when the user touches it. The touch processing eventually calls the tool's TouchTarget operation, giving the tool final control. For example, information windows act as tools when touched; they use this ability to close themselves when the user touches anywhere inside them.
To give your viewables the ability to act as tools, inherit from class Tool when you create your viewable subclass. Then, override ConstrainToolTarget to change the current tool to the viewable itself. This will give ultimate control to the viewable's own TouchTarget operation.
When the user touches the screen, the touch input object uses a process called hit testing to determine which viewable was touched. You can perform your own hit testing to determine which viewable contains a given point. For example, phone number labels on address cards use hit testing to determine what's under the spot where they are sliding in order to perform special processing when they pass over certain underlying objects.
Given a point on the screen, you can call HitTest to determine which viewable contains that point. Once you know which viewable contains the point, you can call InsidePart to determine which part of the viewable contains the point. If the viewable has an image, you can call InsideImage to test which part of the image includes the given point.
Viewables define the following standard part codes that can be returned by InsidePart:
#define partNothing 0 /* outside content */ #define partLabel (-2) /* in label */ #define partContent 1 /* inside content */
InsidePart calls CalcInsidePart to perform the work of determining which part was touched. If you create your own viewable subclasses, you can override CalcInsidePart and implement your own part codes to report which part of the viewable contains the given point. For example, corridors such as the hallway can return a part code indicating that the user touched the floor. The list above contains the part codes defined by class Viewable. See Utilities.h for a complete list of part codes returned by other Magic Cap viewables.
You should override CalcInsidePart to return your custom part codes where appropriate. In your overridden CalcInsidePart, you can call various operations of class Measurement for further hit testing. These operations include BoxBoundsDot to determine if a given box contains a given dot and BoxBoundsBox to see if one box is inside another.
This section describes some of the miscellaneous features provided for viewables. Some features of viewables are defined in class Viewable, but not fully supported except by subclasses. For example, although class Viewable defines attributes and operations for working with images and borders, these features are dormant in viewables unless activated by a subclass.
Magic Cap provides a set of operations that animate the movement of viewables on the screen. This animated action, visible throughout Magic Cap's user interface, is called hopping. For example, when the user creates a new message, then taps send, the message becomes a miniature card and hops to the out box; when the user chooses a tool, the newly selected tool hops to the tool position at the bottom of the screen.
You can call Hop to animate a viewable moving from its current position to a given destination. If you have a destination that is another viewable, you can call HopToViewable to animate the viewable move. If you want a viewable to travel to the tote bag or to the trash, you can simply call HopToToteBag or HopToTrash.
For more control over the animation, call HopFancy, which lets you specify various parameters of the animation, including the hopping speed and acceleration.
Class HasBorder, a mixin, provides full support for shadows and borders. To make a viewable subclass with shadows and borders, you should inherit from class HasBorder.
The Shadow attribute gets and sets the viewable's shadow. Even if the viewable has no shadow, calling Shadow returns a shadow if the user is sliding the viewable on the screen and it is being drawn with a shadow. The ShadowOffset attribute controls the distance of the shadow from the viewable.
Each viewable can be associated with an image object. Although class Viewable provides attributes and operations for images, support for images is dormant unless provided by a subclass. Viewables that have an image use it when they draw themselves. Stamps draw simply by displaying their images, while buttons use their images when drawing as part of a more complex drawing operation. You can use images however you wish in any viewable subclass. There's no special class or mixin that you must inherit from.
If you want to provide images in your subclass of viewable, override the Image attribute to get and set the image. When working with viewables that have images, you can use the Image attribute to get or set the image associated with a viewable. Call ImageBox to determine the box that should be used to draw the image. Given a point inside an image, you can call InsideImage to determine which part of the image contains the point.
A viewable can be made invisible, removing it from the screen if it's being displayed. The viewable stays in the view hierarchy, but it isn't drawn or hit tested. Use the Visible attribute to get and set the viewable's visibility. You can also call ShowSubviews to make the viewable's subview and its view chain visible.
Sometimes it is convenient to perform an action just as a viewable is about to be drawn on the screen, or just before a viewable is removed from the screen. If you create a viewable subclass with objects that should perform an action at these times, you can override AboutToShow or AboutToHide. The appropriate operation will be called when the viewable is being drawn or removed. For example, song stamps have a flag that indicates whether they should play their songs whenever they are displayed. To implement this, class SongStamp overrides AboutToShow to play the song if the flag is set and overrides AboutToHide to stop the song if it is being played.
Magic Cap provides features that support associating text with viewables. Every viewable has at least one text item: its object name, which is shown in its label. The label is drawn with its associated text style. You can use the ContentTextStyle attribute to get or set the label's text style. If you create a viewable subclass that uses other text objects, you can override the TextStyle and SetTextStyle operations to get and set the text styles of additional text objects.
Each viewable is associated with a sound object. When the user touches the viewable, Magic Cap plays the sound. The Sound attribute lets you get or set the sound that a viewable plays, and you can call PlaySound to play the viewable's sound. If you want to ensure that a sound is played, even if the viewable itself has no sound, you can call PlaySoundWithDefault.
Many viewables contain multiple objects, any one of which can be selected by the user for some action. For example, a choice box can include several different choices, with one choice selected at any time. If you want to implement selection in your viewable subclass, you can override the Selected attribute to return the selected object. If your subclass includes text objects, you can override SelectFirstTextField and SelectNextTextField, which control the selection of text fields for typing. Your overridden versions of these operations determine the order in which fields will be selected.
Magic Cap includes a find command in the Magic Lamp that searches viewables for text or other viewables. You can perform searches like this programmatically by calling SearchFor, which searches for text, viewables, or images. You can override SearchFor if you want objects of your subclass to search for other objects.
The Searchable attribute determines whether the subclass has objects that should be searched. Viewables set Searchable to true by default. You should override Searchable to give your viewables the ability to avoid searches. If you create a viewable subclass that has items that should be searched by the find command, you should override the Searchable attribute. You should override MatchText if you want to customize the way your subclass searches for text. Override MatchViewable to provide a custom searching technique for viewables.
If you create a viewable subclass, you can have Magic Cap call an operation in your viewables at idle time, when no other actions are pending. When Magic Cap isn't performing any other actions, it calls the screen's Idle operation, which in turn calls Idle for all its subviews; that is, all viewables in the screen view hierarchy. If you want objects of your viewable subclass to perform some periodic action, you can override Idle. For example, clocks override Idle to update their display at idle time.
Each viewable can control whether the user is allowed to use drawing tools, such as pencils, inside it. If you create a viewable subclass, you can override the CanDrawIn attribute to explicitly prohibit or allow drawing inside the viewables, or to ask the superview to make the decision. For example, stamps override CanDrawIn to prohibit drawing inside them.
When the user creates a telecard or note card, the card can be extended by adding space at the bottom. If your viewable subclass defines objects that could be extended by adding space at the bottom, you can override operation CanExtendBottom to indicate that your viewables can be extended.
You can use the Disabled attribute to make the viewable unable to accept touches, and therefore unable to be highlighted. If you create your own viewable subclasses, you can use this attribute in your Draw override to determine exactly how to draw the viewable. Disabling objects is dormant in viewables. The Disabled attribute gets and changes the disabled setting, but it has no effect on how viewables behave unless supported by a subclass. For example, buttons that set their disabled attribute to true can't be touched and don't draw their images.
Each viewable includes an orientation setting that allows it to be drawn in a rotated position. The viewable can be drawn rotated at 90 degree positions, and each rotated image can be flipped horizontally or vertically, providing 16 different images. However, no more than 8 of these orientations will appear distinct. For example, a viewable that has been flipped vertically and rotated left 90 degrees appears the same as a viewable flipped horizontally and rotated right 90 degrees.
Viewable in various orientations
More symmetrical viewables have even fewer distinct images. A viewable with left and right sides that are mirror images, such as a star shape drawn with Magic Cap's shape tools, has only four distinct images.
You can use the Orientation attribute to get or set a viewable's orientation. Orientation is dormant in viewables. It is supported in animations, controls, and shapes. You can implement orientation in any viewable subclass by overriding the Orientation attribute. If you implement orientation, you should also use the orientation value when drawing your viewable. If your viewable uses an image to display itself and your subclass calls DrawShadowedImage, the orientation will be applied to the viewable when it is drawn.
Magic Cap provides a large collection of stamps, viewable objects that users add to cards and other objects.
Stamps
Members of class Stamp are used as decorations, placed by users on telecards, name cards, notebook pages, and in other places. In addition, Magic Cap packages use stamps to provide graphical meaning in the user interface. Some stamps have additional functions. For example, song stamps play a digitized song when touched and sound stamps record sound from the communicator's microphone. Sticky notes are stamps that zoom open into small windows and contain other viewables.
Some stamps have a semantic meaning that affects the behavior of Magic Cap features. For example, users can set rules in the in box to handle specially any incoming telecards that have the urgent, confidential, or low priority stamps.
Even if your package defines no stamps of its own, you will likely include some stamps as subviews of your scenes and windows.
Stamps are designed mainly as graphic adornments that users can add to telecards, notebook pages, and other places. You'll rarely call any operations of stamps. Instead, you'll include stamps as subviews in some of your own viewables. If your package provides original stamps for users, you might install the stamps in the stamper. For information on installing stamps that appear in the stamper when your scene is current, see the Scenes chapter of this book.
NOTE: You can use Magic Cap Simulator to create a stamp from any Macintosh graphic image. With Magic Cap running, select the image you want on the Macintosh, choose Copy from the Edit menu, select the Magic Cap window, and choose Paste from the Edit menu. For more information, see Guide to CodeWarrior Magic.
Stamps can be set to perform some action when the user touches them, although this feature is rarely used for stamps. Instead, Magic Cap defines class Button, a subclass of stamp, for objects that take some immediate action when the user touches them.
Buttons
When the user touches a button, it highlights to enter a momentary-on state that indicates to the user that it is being touched. When the touch is released, the button returns to its usual display and the button's Action operation is called. Magic Cap provides various subclasses of button that implement buttons with specialized behavior.
In addition to buttons, Magic Cap defines other subclasses of stamps that are designed to perform some immediate action when the user touches, including classes Gadget and Icon. Each gadget is connected to some other viewable, usually a gadget window. When the user touches a gadget, the associated viewable is shown or hidden. Similarly, each icon is connected to another viewable, usually a scene. When the user touches an icon, the user goes to the associated scene. For more information on these and other stamp subclasses, see the Buttons and Controls chapter of this book.
After the user releases the button and it returns to its usual display, it doesn't retain any setting indicating that it was pressed. Magic Cap defines controls as viewables that allow users to interactively manipulate some setting, displaying information about the setting as users touch.
Controls
Magic Cap provides various kinds of controls, including switches, meters, sliders, and choice boxes. All controls display their setting and allow users to touch them to change the setting. For more information about buttons and controls, see the Buttons and Controls chapter of this book.
For more information, see these topics in Magic Cap Class and Method Reference:
class Viewable
operations and attributes:
AboutToHide AboutToShow Action AddAfter AddBefore AddFirst AddLast AdjustSize AllowedToLeaveScene Border BorderBox BorderLabel BoundsBox CalcBorderBox CalcBoundsBox CalcInsidePart CanAccept CanAcceptCoupon CanBringToFront CanChangeContainers CanContain CanDrawIn CanExtendBottom CanShowLabel Clipped ConstrainToolTarget ContentBox ContentHeight ContentSize ContentTextStyle ContentWidth CopyTouch DirtyBounds DirtyBox DirtyContent DirtyHide DirtyShow Disabled DragTrack Draw DrawShadowedImage Empty FirstSubview Hilited HitTest Hop HopFancy HopToToteBag HopToTrash HopToViewable Idle Image ImageBox InsideImage InsideImage InsidePart Label LabelLoc MatchText MatchViewable MoveTouch Next OnScreen Orientation Origin PartColor PlaySound PlaySoundWithDefault Press Pressed Pressing Previous RedrawNow RelativeOrigin Searchable SearchFor Selected SelectFirstTextField SelectNextTextField SetContentBox SetContentSize SetHilited SetName SetOrigin SetPartColor SetRelativeOrigin SetSubview SetTextData SetTextStyle SetVisible Shadow ShadowOffset ShowLabel ShowSubviews Sound SpatOut StretchPress StretchTouch StretchTouch StretchTrack Superview Swallow SwitchContainer Tap TapCenter TapHere TextStyle Thickness Touch Touching TouchKind Visible
class ChooseableTool
operations and attributes:
GetToolTarget TouchTarget
class MoveTool
class CopyTool
class StretchTool
class BackgroundWithBorder
indexicals:
iCurrentTool iTouchTool
Book Contents Previous Chapter Next Chapter