Book Contents          Previous Chapter          Next Chapter

Cards

Cards, Stacks, and Forms

This chapter discusses cards, viewables that conveniently collect and display other viewables in scenes. This chapter also discusses lists of cards called stacks, and forms, viewables that provide a means for sharing information among related cards.

About Cards, Stacks, and Forms

Many package scenes collect their data into units of related information, with each unit containing roughly one screen of data. Magic Cap provides cards as a way to organize these units of information that fill most of a scene's screen area. For example, each page in the notebook is a card, as is each name card in the name card file.

Various cards in their scenes

Some scenes contain only a single card, such as the message scene that is used when creating a new telecard. Scenes that contain multiple cards usually collect the cards together into a list called a stack of cards, also called a stack. Scenes that display stacks of cards are stack scenes. For example, the notebook and the name card file both collect their cards into stacks and display them using stack scenes.

Often, a group of cards in a stack shares some information or a common basic appearance. Magic Cap uses forms to represent this shared information or common appearance. Forms are viewables that contain the information shared by the group of cards. For example, all name cards in the name card file share a form, and all index cards in the name card file share a different form. The notebook uses several forms: one for plain paper, one for lined paper, one for graph paper, and one for list paper.

Each form includes items shared by all its cards. For example, in the name card file, the form for name cards includes boxes that contain addresses and telephone numbers and a viewable object used by group name cards to list their members. The form for index cards simply provides the visual background for those cards and contains no shared objects.

Similarly, the notebook forms provide shared objects and background appearance for notebook pages. The forms for plain paper and for lined paper include two text fields, one for the title of the page and one for the page's body text. The form for graph paper includes a text field for the page's title and a ruling object that draws the grid on the page. All the different notebook forms provide the spiral notebook background.

Each form includes a list of form items, the objects that are shared among all the cards that use the form, such as the two text fields provided by the plain paper form in the notebook. Although the text fields themselves are shared, the data that provides the objects' content (that is, the text objects themselves) are not shared - each card has different text in these objects.

To accommodate having different data for shared objects on each card, each card keeps track of the data that it places into the form items. When the card becomes current, it installs its own data into the form items. When the card is no longer current, it removes its data from the form items and stores the data in its extra data. For example, when a new plain paper notebook page becomes current, it installs its title and body text into the text fields provided by the form.

The following figure shows an example of a card in a stack (a notebook page) and indicates which parts are provided by which objects.

Card in its stack

When Magic Cap shows a scene with its stack, card, and form, the following view hierarchy is created (indented lines indicate subviews):

You can use the card's Stack and Form attributes to get and set its stack and form. However, you'll usually indicate the card's stack and form when you declare the card in your instance definition file. You probably won't change these attributes directly at runtime.

You can create scenes that display a single card or a collection of cards. Many stacks of cards allow users to add new cards or remove existing cards. Stack scenes and cards provide navigation features that allow users to look through information and move from one card to another.

You may want to provide a way for users to work with cards that aren't on the screen. You can create tiny stand-ins for cards called minicards to represent cards that aren't being displayed.

When you display cards in a stack scene, you can control various settings of the stack, such as what happens when you add new cards, how to move cards to another stack, and how to remove existing cards entirely.

The following diagram illustrates the relationships among cards, stacks, forms, and stack scenes.

References among cards, stacks, forms, and stack scenes

In addition to cards, stacks, and forms, this chapter also discusses classes StackScene, FormElement, and MiniCard.

Navigation and Scenes

As with scenes, you can go directly to cards. Call GoTo to open any card in its scene. To record the spot on the screen where the user touched to go to the new card, call GoToVia. The new scene's step-back spot will be set to the viewable you pass when calling GoToVia. You can also call GoToNext or GoToPrevious to display the next or previous card in the stack, or GoRelative to move a specified number of cards forward or backward in the stack.

Every card has a default scene, the scene that will be used to display the card when opened outside its usual scene. For example, if an unsent telecard is on the desk and the user touches it, it's displayed by its default scene. You can override DefaultScene to return the default scene for your card subclass.

Magic Cap uses minicards as tiny representatives of cards. Minicards act as proxies in representing cards that aren't currently displayed. For example, when the user moves a telecard out of the in box and onto the desk, a minicard represents the unopened card on the desk. When the user slides a page out of the notebook index, a minicard represents the page.

Minicards

You can call InstallMiniCard to create a minicard for a card and install it as a subview in any scene or viewable. You can display the card associated with a minicard by calling the minicard's TapCenter operation. The card zooms out and replaces the minicard and its scene.

You can specify the image to use for the card's minicard by overriding the card's CardIcon operation, which also specifies the image to use when displaying cards in a list view. Similarly, you can override ContentIcon to specify the image to be used for your card when Magic Cap displays it in the out of memory window or other similar content list.

To place a minicard in the out box, you can call the minicard's HopToOutBox operation. If the current scene is the desk or any scene that has an out box, the minicard will hop to the out box on the screen. If the current scene has no out box, a window with an out box will appear, the minicard will hop to the out box in that window, and the window will disappear. The following figure shows the window and out box that appear when the current scene has no out box.

Out box appears in a window

Current Card

The current card is the card being displayed on the screen. The current card is a subview of the current scene. You can determine the current card by reading the iCurrentCard indexical. Magic Cap calls the current card's AboutToShow operation just before drawing it on the screen. You can override AboutToShow to have objects of your card subclass perform some action before they are drawn. Similarly, you can override AboutToHide to have your objects perform some action before they are removed from the screen.

You can use the stack scene's CardNumber attribute to determine the current card's relative position in the stack. If you want to display a particular card and you know its card number, you can call GoToCardNum. You can call DeleteCurrentCardWithConfirmation on the stack scene to delete the current card.

Magic Cap keeps track of whether a card has ever been displayed on the screen. You can find out if a card has ever been displayed by calling WasSeen. You can also call SetWasSeen to change the setting that determines whether the card has been displayed.

Forms

Each card can be associated with a form. The card's form provides two kinds of objects for the cards that use it.

For example, the meeting form in the datebook provides the hourly schedule bar and buttons, static objects that are the same for every meeting. The form also provides text fields containing the meeting information, dynamic objects that can have different contents for every meeting, and a time interval drawn on the schedule bar, another object that be different for every meeting.

The most common way to include static objects in your form is by building them in as subviews. When you declare a form in your instance definition file, you specify all the objects you want on the form, including static as well as dynamic objects, as a view chain that is a subview of the form. Magic Cap will draw the form and its subviews when the user goes to a card that uses the form.

To have your form provide a decorative background, specify the background object in the form's border field in your instance definition file. When the user goes to a card that uses the form, the background will be drawn along with the form.

Dynamic form objects appear on every card that uses the form, but each card stores its own data for the dynamic form objects. Most classes that are commonly used as dynamic form objects, including text fields, switches, sliders, choice boxes, and all other controls, are designed to retain their per-card data automatically by inheriting the interface of class FormElement. For information on creating your own kinds of form elements, see this chapter's Creating Your Own Form Elements section.

The form's formItems field refers to an object list that specifies the dynamic form objects that inherit from class FormElement. Note that the dynamic form items referred to by the formItems field are also listed in the view hierarchy as subviews of the form.

When the user is finished looking at a card and goes to another card or scene, the card calls its StoreFormData operation. StoreFormData checks the form's formItems list. If the list contains any objects, StoreFormData gets the data from the form objects, stores it as the card's extra data, then empties the form objects so that the next card to use the form won't display another card's data. When a new card is installed in the scene, the card calls ExtractCardData to get the values from the card's extra data and place them back in the form objects.

You can easily use dynamic form objects that inherit from class FormElement. In your instance definition file, include the dynamic form objects in the form's subview's view chain. In the formItems field, specify an object list that consists of the dynamic form objects. If you set up the form this way, the dynamic objects will automatically save and restore their data as the user moves from card to card. The following diagram shows an example of a form.

Form with its subviews and form items

Note that you refer to each dynamic form object at least twice: once as a member of a view chain, referred to by its neighbors in the view chain, and once as an automatically updated dynamic form object, referred to by the formItems object list. Note also that the form can contain subviews that aren't in the formItems list, such as the stamp in the example above. These subviews will be drawn on every card, but won't have card-specific data installed automatically.

You can add viewables to a form at runtime with Magic Cap Simulator. You can get many viewables, including switches, sliders, choice boxes, and text fields, from the Magic Hat. Text fields are available in the tool holder on the control bar. After creating one of these, you can use a put in form coupon from the misc. drawer of the Magic Hat's extras category to put the object in the form. The extras category is only available in Magic Cap Simulator, not in communicator versions of Magic Cap.

If the user adds objects that are members of class FormElement, Magic Cap adds the objects to the FormItems list automatically. When the user goes to another card, the card calls StoreFormData, which in turn calls Form_UpdateFormItems, which then examines all the objects on the form. Items that are members of FormElement are added to the FormItems list if not already in that list.

Forms include an Image attribute and associated image field. If you specify an image for a form in your instance definition file or at runtime, the image will be drawn in the center of the form whenever the form is installed in the scene.

You can get or change the form items at runtime by using the FormItems attribute.

Creating Your Own Form Elements

Magic Cap provides a large collection of classes, including all text fields and all controls, that inherit from class FormElement and so can be used as dynamic form objects just by specifying them in the formItems field. You can also create your own class that acts as a dynamic form object, storing and retrieving its data as the user moves from card to card.

To create your own class of dynamic form object, inherit the interface of class FormElement in your new class's declaration. Then, override the four operations defined by FormElement. Override IsFormElement to return true if you want the object to be treated as a form element. Override FormData and SetFormData to move the object's contents to and from the form. Override FormDataInfo to provide information about the dynamic data.

You can also create a new class of dynamic form object by subclassing an existing dynamic form element class, such as TextField or Control. In this case, you probably won't have to override the FormElement operations to implement your new class. For more information, see Magic Cap Class and Method Reference for the class you're interested in.

Stacks and Stack Scenes

You can make a new card in the stack by calling the stack scene's CreateNewCard operation. CreateNewCard makes a new card in the stack by copying the stack's prototype card, which is available through the stack's ProtoCard attribute. The prototype card is a model that includes all objects that should be present on newly created cards. You can declare your own prototype card in your instance definition file, or you can use a supplied card, such as iPrototypeCard. After the new card is created, Magic Cap goes to the new card.

When a new card is created in the stack, it can be added before or after the current card, or as the first or last card in the stack. You can call SetInsertOrder to specify where you want newly created cards to go. Call InsertOrder to determine the current setting. You can also set the stack's insert order in its stackFlags field in the instance definition file.

You can remove a card from its stack and install it in another by calling MoveToStack. You can take a card out of its stack and remove it from the screen view list by calling DetachCard. If you want to destroy the card completely, not just remove it from the stack, call DeleteCard. To delete the current card after getting confirmation from the user, call DeleteCurrentCardWithConfirmation on the stack scene.

Many scenes, especially stack scenes, display a column of five buttons along the right side of the screen, between the top and bottom bars. Although many scenes have these buttons, Magic Cap doesn't provide any explicit support for this feature in its scene classes. Instead, scenes simply declare these buttons as subviews in instance definition files. If your scene has five buttons down the right side, you should set each button's viewFlags field to $10101000 and its border field to iSquareButtonBorderUp. You should use the following x-y coordinate pairs for the buttons' relative origins and content sizes:

-----------------------------------------------
button position   relative origin  content size
   from top
-----------------------------------------------
       1          <211,-104>       <50,41>
       2          <211, -53>       <50,43>
       3          <211, -1>        <50,43>
       4          <211, 51>        <50,43>
       5          <211, 102>       <50,43>
-----------------------------------------------

VERSION NOTE: Note that the content size of the first button is <50,41>, while the size of all others is <50,43>. You could make the button sizes more uniform while occupying the same total amount of space by setting the sizes of two of them to <50,42> and the other three to <50,43>. However, due to the way Magic Cap draws dithered grays, setting the content size of one button to <50,42> produces an unattractive dithered line beneath the button. In addition, Magic Cap is optimized to draw buttons with border iSquareButtonBorderUp and content size <50,43> quickly.

When a stack scene is current, the name bar normally displays arrows that the user can touch to move to the next or previous card. When the user goes to the first or last card in the stack, one of the two arrows in the name bar vanishes to show that there are no more cards in that direction. However, you can set a stack to allow the user to treat the cards as if they were laid out in a circle, continuing past the last card to the first card, or past the first to the last. Continuing through the cards in this way is called wrapping, because the path through the cards seems to wrap around the edges of the stack, from one end to the other. To turn on wrapping, set the wrapFlag in the stackFlags field of the stack's instance definition, or use the CanWrap attribute to set or clear this feature.

Stack scenes usually display arrows in the name bar along with the number of the current card and the total number of cards in the stack. You can suppress that display by setting the blankTitle scene flag, or by overriding ShowNameBarInfo.

The stack of cards refers to its scene with the StackScene attribute. The scene refers back to its stack with the Stack attribute.

Stacks include a setting that indicates whether there are cards in the stack that haven't been opened by the user. You can get or change this setting by calling ContainsNewItems or SetContainsNewItems. This feature is used mainly by class MailStack, which shows stacks of telecards, as in the in box and out box. MailStack is the only Magic Cap class that changes this setting to true.

You must call SetContainsNewItems to change the flag to true in your stack subclass to indicate the presence of new cards if you want to support this feature. The stack scene changes this setting to false when the user goes to the stack. You can use this feature in conjunction with the WasSeen and SetWasSeen operations to indicate whether the user has read a telecard.

Large Cards and Scrolling

Some cards are too large to fit on the screen completely. You can make a card larger by calling its ExtendBottom operation. For example, the notebook calls ExtendBottom when the user touches the extend button. You can call RevealTop if you want to ensure that the top of the card has scrolled into view on the screen, or RevealBottom to make sure that the bottom of the card can be seen. If you want to ensure that a particular viewable on the card is visible, you can call RevealViewable.

These cards usually have scroll arrows that let the user see the entire card. For information on adding scroll arrows to your card, see this book's Scrolling chapter.

Electronic Mail

Your package can create a telecard, then present the telecard to the user in the message scene, which provides standard buttons for addressing and sending the telecard. In addition, you can add other electronic mail features to your package. For information on using electronic mail from your package, see the Electronic Mail chapter of this book.

Creating Card, Stack, and Form Objects

You'll declare instances of StackOfCards, StackScene, and Form in your instance definition file. You'll probably never create any objects of these classes at runtime. You'll usually declare instances of class Card in your instance definition files, but your package may allow the creation of new cards at runtime. Instances of class MiniCard are usually created at runtime by copying a prototype object.

Flags and Indexicals

Class Card defines various flags that you can use to customize the appearance and behavior of its members. You'll use these flags primarily when you declare cards in instance definition files. Several card flags that are commonly tested at runtime are available via operations. Others must be examined directly in the card's cardFlags field.

Card flags let you determine information about the card, such as whether it is a postcard, letter, or envelope, whether the card has been mailed, whether the user can change the card, and many other settings. For more information on card flags, see the Card chapter of Magic Cap Class and Method Reference and the Utilities.h file.

Class StackOfCards defines a few flags that you can use to customize the appearance and behavior of its members. Stack flags determine whether the stack will wrap when the user goes past the first or last card, whether the stack can be deleted, and other settings. You'll use these flags primarily when you declare stacks in instance definition files.

Most stack flags are available via operations, while others must be examined directly in the card's stackFlags field. For more information on stack flags, see the StackOfCards chapter of Magic Cap Class and Method Reference and the Utilities.h file.

Magic Cap provides many indexicals that contain useful cards and stacks or information about cards and stacks. Some indexicals, such as iReplyCard and iForwardCard specify prototype cards for various uses. The iCurrentSceneStack is the stack associated with the current scene. Several indexicals provide access to the most common stacks in Magic Cap, such as iInBoxStack, iNameCardsStack, and iNoteCardStack.

See the Indexicals.h file for more information on indexicals.

Card and Stack Information in the Package Root List

When you declare a stack and its cards in your instance definition file, you should list the cards individually in the software package object's install list, with their stack as the receiver. In addition, you should list all your package's stacks in item 22 (iPackageStacks) in the package root list. By doing putting your cards in the install list and your stacks in iPackageStacks, Magic Cap can handle the cards properly if the user moves the cards out of the package and then packs up the package or removes the PC card containing the package, or if the cards somehow become disconnected from the package.

For more information on items in the root list, see the Software Packages chapter of this book.

Subclasses of Card and Stack

Magic Cap includes many subclasses of Card that specialize its behavior in various ways. Many built-in scenes in Magic Cap uses card subclasses to display their information. For example, book pages in the library, folders in the file cabinet and elsewhere, and name cards are all card subclasses. Because these classes are specialized for their particular uses, you'll probably use class Card or create your own subclasses.

There are a few highly specialized subclasses of StackOfCards in Magic Cap, such as MailStack, used for a collection of telecards, and NameCardStack, used exclusively by the name card file. You might use class SortedStack, which mixes in SortedList to create a stack whose cards are always in order.

Reference

For more information, see these topics in Magic Cap Class and Method Reference:

class Card

operations and attributes:

CardIcon
CloseCard
ContentIcon
DefaultScene
ExtractCardData
Form
GetOrMakeAgent
GoRelative
GoTo
GoToNext
GoToPrevious
GoToVia
InstallMiniCard
OpenCard
RevealBottom
RevealTop
RevealViewable
SetWasSeen
Stack
StoreFormData
WasSeen

class StackOfCards

operations and attributes:

CanWrap
ContainsNewItems
DeleteCard
DetachCard
InsertOrder
MoveToStack
ProtoCard
SetContainsNewItems
SetInsertOrder
StackScene

class Form

operations and attributes:

FacilityName
GetOrMakeAgent
Image
UpdateFormItems

fields:

border
formItems
image

class StackScene

operations and attributes:

CardNumber
Confirmation
CreateNewCard
DeleteCurrentCardWithConfirmation
GoToCardNum
ShowNameBarInfo
Stack

class FormElement

class MiniCard

operations and attributes:

HopToOutBox
TapCenter

indexicals:

iCurrentCard
iCurrentSceneStack
iForwardCard
iPrototypeCard
iReplyCard

Book Contents          Previous Chapter          Next Chapter