Defined in ListView.Def Inherits from GridView, AcceptsTyping
A list view is a grid view that displays an object list. Class ListView implements the functions of the abstract class GridView. List views show up everywhere in Magic Cap: they display lists of messages in the in box, they display choice lists in choice boxes, and they are the directories in the Hallway and Downtown.
Remember that if the documentation and the software (especially the definition files) disagree, always trust the software.
List views come in two basic flavors: the flavor that takes some action when you touch an item in it, and the flavor that just lets you make a selection. The second flavor usually appears with an "accept" button. List views appear as pieces of many different user interfaces in Magic Cap; exactly how you'll use the list view depends on how it's presented.
Instantiate: sometimes Subclass: sometimes Call its methods: rarely
You will probably not need to call any of the methods of class ListView. Just put your list view objects into place in your object definition files and set their flags appropriately. You might need to create custom subclasses of class ListView if none of the provided subclasses meet your needs. Methods you might override when you subclass are described later in this chapter.
Class ListView defines the following methods:
Method | Description |
---|---|
Matching list items to cells | |
CellToIndex | Given a row and column, return the index of the list item to put in that cell |
IndexToCell | Given an index into the list, calculate the row and column of the cell it will be displayed in |
ValueAt | Given a list item, return the value to be displayed in the list view |
Manipulating objects in cells | |
DeleteSelection | Remove the item in the selected cell from the view's list |
EditName | Bring up the name editor for the selected object |
GoTo | Go to the selected object if possible |
TouchedObject | Do the appropriate thing when an item in the view is tapped |
Confirm | Accept current state of listView (does nothing unless overridden) |
TapObject | Simulate a tap on a line of the list view |
framework methods | |
AboutToHide, AboutToShow | Overridden to handle observing the view's list |
AdjustSize | Overridden to include displayed list in size calculation |
Draw | Overridden to draw scroll arrows if necessary |
DrawCell | Overridden to respect list view flags |
DrawRow | Overridden to handle items that don't fit in the view |
Editable | Overridden to return true only if keyboardScroll flag is set |
MaximumScrollOffset | Overridden to turn off horizontal scrolling |
TextInfo | Overridden to use summaryString field and number of items in list to construct a text info string |
MatchText | Overridden to step through the view's list looking for a match |
Notice | Overridden to request a redraw of the view if the list changes |
RowCount | Overridden to calculate and return the number of rows required to display all the items in the list view |
List, SetList | Get and set the list to be displayed by the view |
Touch | Overridden to handle selecting touched cell and tapping on scroll arrows |
TypeKeys | Overridden to move the selection to the next row starting with or after the typed character |
When you create a subclass of class ListView, you might override these methods under the following circumstances:
Method | When to override |
---|---|
TouchedObject | If tapping an item in your list view subclass should do something special |
DrawCell | To customize the way your list view's cells are drawn |
RowHeight | If your rows need to be tall |
Confirm | To accept current state of ListView |
Swallow | To allow your list view to swallow certain kinds of morsels |
Class ListView defines the following fields:
Field | Type | Description |
---|---|---|
inherited from SingleLinkable: | ||
next | Object | next item in view list |
inherited from Linkable: | ||
previous | Object | previous item in view list |
inherited from Viewable: | ||
superview | Viewable | container for this object |
subview | Viewable | first object contained by this object |
relativeOrigin | Dot | origin relative to superview |
contentSize | Dot | size of content rectangle |
viewFlags | Unsigned | property settings |
labelStyle | TextStyle | text style of viewable's label |
color | Unsigned | color of viewable's content |
altColor | Unsigned | alternative color (used only by Control and DrawShadowedImage) |
shadow | Shadow | shadow drawn with object |
sound | Sound | sound associated with object |
inherited from HasBorder: | ||
border | Border | the gridview's border |
inherited from ScrollableByMicron: | ||
scrollOffset | Dot | stores the list view's scroll position |
inherited from GridView: | ||
gridFlags | Flags | flags that control grid view behavior |
cellTextStyle | TextStyle | text style used to display list view entries (also determines row height) |
columnTitles | Text | a text object that contains \n delimited column titles |
emptyMessage | Text | message shown if the list view is empty (that is, the row count is 0 and there are no row lines) |
selectedColumn | Unsigned | selected column |
selectedRow | Unsigned | selected row |
titleTextStyle | TextStyle | used for column and row titles |
defined by ListView: | ||
list | FixedList | the list displayed by the list view |
summaryString | Text | a string used in constructing a summary of the list view's contents |
As with grid view objects, each column of a list view needs four extra data fields to describe it. Append the column number to the field names. The four fields are:
offsetn | The position of the left edge of this column, expressed as the number of microns from the left edge of the list view. |
keyn | The key to pass to TextInfo (if you've set the valueIsTextInfo column flag) or to Attribute (if you've set the valueIsAttribute column flag) when constructing a string to display in the list view. See the section on attribute codes later in this chapter for a list of possible codes. |
typen | The type of the data displayed in this column. The type is passed to ValueToText, which uses the information to construct a string for the list view to display. See the section on type codes later in this chapter for a list of possible types. |
flagsn | Additional flags that control how the column is displayed and specify what kind of information is in the column. See the column information flags description later in this chapter for more information on the available flags. |
Include one set of each of these fields for each column in your list view. For example, a list view with three columns would include 12 extra fields in its instance definition.
Here's how class ListView fills in each of its cells with a value from its fixed list:
Class Object defines the TextInfo and Attribute methods. For complete descriptions of these methods, please see the chapter on class Object. Class Utilities defines the ValueToText method. See the chapter on class Utilities for a list of the type numbers used by ValueToText.
Version note: Unfortunately, the chapter on class Object is out of date, and the chapter on class Utilities doesn't yet exist. To get a list of type numbers for ValueToText, see the file Utilities.h. What promise the future holds!
Here's an example of a list view with two columns:
Instance ListView 'Biking to work: a debate' 135; next: nilObject; previous: nilObject; superview: (Scene 'BookExamples' 8); subview: nilObject; relativeOrigin: <-4.0,-45.0>; contentSize: <437.0,126.0>; viewFlags: 0x70110000; labelStyle: iJot12; color: 0xFF000000; altColor: 0xFF000000; shadow: nilObject; sound: nilObject; border: nilObject; scrollOffset: <0.0,0.0>; gridFlags: 0x12320000; cellTextStyle: iBook10; columnTitles: (Text 136); emptyMessage: (Text 137); selectedColumn: 0; selectedRow: 0; titleTextStyle: iSign12; list: (ObjectList 'Reasons' 139); summaryString: (Text 138); offset1: <8.0>; key1: 0; type1: 3.s; flags1: 2.s; offset2: <200.0>; key2: 0; type2: 3.s; flags2: 2.s; End Instance; Instance Text 136; text: 'Pro\nCon'; End Instance; Instance Text 137; text: 'No arguments.'; End Instance; Instance Text 138; text: 'about biking to work.'; End Instance; Instance ObjectList 'Reasons' 139; length: 9; entry: (Text 140); entry: (Text 141); entry: (Text 161); entry: (Text 142); entry: (Text 143); entry: nilObject; entry: (Text 144); entry: (Text 145); entry: nilObject; End Instance; Instance Text 140; text: 'You\'ll get fit.'; End Instance; Instance Text 141; text: 'You\'ll get sweaty.'; End Instance; Instance Text 142; text: 'It\'s relaxing.'; End Instance; Instance Text 143; text: 'It takes longer than driving.'; End Instance; Instance Text 144; text: 'You\'ll save money.'; End Instance; Instance Text 145; text: 'You might get rained on.'; End Instance;
Both columns have their flags field set to 2, so they both display the text info of the list element they contain. Since both columns display text, they're both type IDString, 3.
Here's what this list view looks like:
If the list field were nilObject, or contained an empty object list, the example list view would look like this:
List views display the text object in the emptyMessage field when they're empty. The empty message uses a bold variety of the text style given in the cellTextStyle field.
This section describes four kinds of constants used by class ListView: grid flags, column information flags, attribute codes, and type codes.
Set these flags in the gridFlags field of your list view objects. Class ListView inherits this field from class GridView, and uses all the grid flags defined by GridView. The flags described in this section are used only by class ListView and its subclasses, and aren't part of the basic behavior of grid views.
#define selectModeMask0x80000000
Set this flag if you'd like users to select items in your list view. If this flag is set, class ListView's Touch method just selects the list item touched by the user. If this flag isn't set, ListView_Touch calls TouchedObject with the object the user just touched.
#define useContainerListMask 0x20000000
Set this flag if your list view should use its enclosing card's list (or its superview's list, if it isn't enclosed in a card). The List method checks this flag. If it's set, ListView_List will pass along the List call to the list view's superview or enclosing card.
#define keyboardScrollMask0x08000000
Set this flag if your list view should scroll to the next line matching a typed character. This flag is probably useful only if your list view displays its items in alphabetical order. The Editable method returns true if this flag is set. The TypeKeys method does nothing if it isn't.
#define scrollToSelectedMask 0x04000000
Set this flag if the current scene should scroll to a particular location when the location's entry in the list is selected. For example, directory listings like the ones in the hallway and downtown use this flag to scroll to the entrance that matches a tapped list entry.
The TouchedObject method checks this flag.
#define useClassListMask0x00400000
If this flag is set, the AboutToShow method won't start observing the list view's list. The List method will return ClassList_. You will probably never set this flag unless you're writing a class browser hack.
#define menuResizeHMask0x00100000
Set this flag if your list view should adjust its width to accomodate its widest entry. The AdjustSize method checks this flag.
#define alwaysOneSelectedMask0x00080000
Set this flag if one of the items in your list view must always be selected. If there's no other selection, the AboutToShow method will automatically select the first list entry.
The AboutToShow and SetSelected methods check this flag.
#define setCurrentContactMask0x00040000
Set this flag if the iCurrentContact indexical should be kept in synch with your list view's selection. You'll find yourself setting this flag often for list views that list people or address cards.
The AboutToShow methods checks this flag. If the flag is set, AboutToShow checks the iCurrentContact indexical. AboutToShow sets the list view's selection to be the current contact, if a current contact exists. If one doesn't exist, AboutToShow sets iCurrentContact to the list view's selection.
The SetSelected method also checks this flag. If it's set, SetSelected updates the iCurrentContact indexical to the current list view selection. The Touch method does the same.
#define dontTrackMask0x00020000
Set this flag if your list view should not track touches or change its selection because of a touch. You'll find this flag handy if your list view just displays an informative list that you don't expect your users to interact with.
The Touch method checks this flag. If it's set, Touch returns without doing anything.
#define showRemainingMask0x00010000
Set this flag if the last line of your list view should display the number of items that won't fit on the screen. You won't want to set this flag if you've set the listViewArrow flag.
The DrawRow method checks this flag. If it's set, and the list is too long too fit in the view, DrawRow puts the string "(and n more)" into the last line of the list view. It draws the string using the same text style the rest of the list uses.
Here are two list views, identical save for size, that both set this flag:
#define useListElementPerCell0x00000400
Set this flag if your list view should map list elements to cells in the view instead of mapping to rows. The CellToIndex and IndexToCell methods check this flag in the process of mapping cell locations to list indices.
Here's an example of a list view that sets the per cell flag:
Here's how the same list view looks with the per cell flag turned off:
These two views both use the same object list, but the top one puts one list item into each cell. The bottom list puts one list item into each row. When the per cell flag isn't set, CellToIndex returns the row number as the list index to use to fill in each cell. So both columns in a row will display the same list element.
You will want to set this flag for list views with multiple columns where each cell should display a different object in your list. Don't set it when you want all columns in a row to display the same object, such as when each column displays a different attribute of the object.
#define useItemSelected0x00000040
Set this flag you're using list views to implement menus for choice boxes. That is, the system uses this flag to do just that, but you probably won't need to use it yourself.
Class TargetedListView uses this flag. Plain ListView objects or objects from other subclasses of ListView will not respect this flag.
The TouchedObject method checks this flag. If it's set, TouchedObject calls ItemSelected on the list view's target (which will probably be a choice box), passing the row number of the selection as the theIndex parameter.
#define emboldenGroupsMask0x00000010
Set this flag if your list view should use a boldface font to display the names of groups. If your list view is a PeopleList object, you'll probably want to set this flag. The DrawCell method checks this flag.
#define confirmOnSelectMask0x00000008
Set this flag if the list view should call Confirm on itself every time its selection changes. ListView_Touch checks this flag when a new selection is made, and calls Confirm if its set.
If you've set this flag, be sure you've also subclassed ListView and overridden Confirm.
#define listViewArrowMask0x00000002
Set this flag if your list view should display scroll arrows when its list is too long to fit. You won't want to use this flag if you're using the show remaining flag.
Instead of setting this flag, you could put scroll arrow objects into your list view yourself. Putting in arrows yourself uses more memory and is slightly slower than setting the listViewArrow flag. You'll want to roll your own scroll arrows if the automatically chosen arrow positions aren't to your liking.
The AdjustSize method checks this flag, and adds space in the list view for scroll arrows if necessary. The Draw method also checks this flag and draws the required scroll arrows. The Touch method handles touches on scroll arrows.
Set these flags in the flagsn extra field to control how the list view draws column n. The first four flags specify the kind of information the column should display, and the second four specify how the column should be drawn.
#define valueIsAttribute0x0001
Set this flag if your list contains objects and this column should display an attribute of those objects. Use the column key field to specify the number of the attribute to display.
If this flag is set, ValueAt will return the result of this call:
Attribute(object, key);
where the key parameter is the value in the column's key field.
#define valueIsTextInfo0x0002
list contains objects, return TextInfo(object, key) */
Set this flag if your list contains objects and this column should display the text info of each object. Use the column's key field to specify the kind of text information you want. For a list of keys understood by TextInfo, see the chapter on class Object and the list in the next section of this chapter.
If you don't set either valueIsAttribute or valueIsTextInfo, ValueAt will return the object itself as the value.
#define valueIsEditable0x0004
This flag is currently unused. Please don't set it. (If you set it, it will have no effect.)
#define valueIsAbbreviated0x0040
The ValueAt method checks this flag. If it's set, ValueAt calls TextInfo with the abbrevFlag parameter set to true. Not all classes that implement TextInfo use the abbrevFlag parameter.
The next four flags affect how the column is drawn. The DrawCell method checks them and changes a cell's text style appropriately.
#define omitColumnLine0x0008
Set this flag to suppress all lines between columns.
Version note: This flag is unimplemented in Magic Cap 1.0.
#define forceCentered0x0010
Set this flag if you want to force the column contents to be centered.
#define forceRightAligned0x0020
Set this flag if you want to force this column's contents to be aligned with the column's right edge.
#define allowSpillRight0x0080
Set this flag if this column should spill over to the right if the column to the right is empty. Here are two list views, identical save for the column flags for the middle columns:
The first one doesn't set the allowSpillRight flag. Its middle column is too small, so most of its text is hidden. The second does set the allowSpillRight flag. Its text spills over into the empty "Padding" column. The third list view also sets the spill right flag for the second column, but the third column isn't empty. Columns won't spill over into space that isn't empty.
The key codes determine which attribute or kind of text info of an object should be displayed in the current column. To display an object's attribute, set the valueIsAttribute column flag and use the attribute number in the key field. To display an object's text info, set the valueIsTextInfo column flag and put the text info code into the key field. This section lists text info codes.
For example, suppose you have a view displaying a list of telecards. If column 4 has has this code:
key4: 3;
column 4 will display the subject of each telecard.
The available text info codes are:
Attribute | Number | Description |
---|---|---|
kSenderName | 1 | the name of a card's sender, in last,first order with disambiguating integer if necessary |
kReceiverName | 2 | the name of a card's receiver, in last,first order with disambiguating integer if necessary |
kSubject | 3 | the subject of a telecard |
kDateSent | 4 | the date a card was sent |
kDateReceived | 5 | the date a card was received |
kTypeDescription | 6 | text description of item type (such as, "Postcard to Mom") |
kTypeIcon | 7 | icon for item type |
kSenderOrReceiver | 8 | if WasSent, senderName else receiverName |
kDuration | 9 | duration of call |
kDateTimeSent | 10 | show both date and time |
kContactLocation | 11 | location of contact (i.e. Home phone) |
kOrderedSwitch | 12 | for OrderListView, the switch that sez whether item is ordered |
kContactPhoneNumber | 13 | phone number of contact location |
kPhoneAreaCode | 14 | area code |
kPhonePrefix | 15 | dialing prefix |
kPhoneLocalTolls | 16 | local tolls of NumberingPlan |
kSelectedSwitch | 17 | for LocationListView, the switch that indicates selected item |
kContentDescription | 18 | content description for ContentListView_ |
kCheckboxColumn | 19 | placeholder for checkbox column in CheckboxListView_ |
kDisplayNameUnflipped | 20 | first, last with disambiguating integer if necessary |
kSizeInKBytes | 21 | the size of the object in kilobytes |
Here's an example of a list view that uses these key codes to display different attributes of an object in different columns. This object is a of a subclass of class ListView, class SummaryListView.
Instance SummaryListView 1451; next: (ScrollArrow 11614); previous: nilObject; superview: (Scene 'Mailbox report' 1329); subview: nilObject; relativeOrigin: <0.0,-23.0>; contentSize: <480.0,210.0>; viewFlags: 0x100E0000; labelStyle: iBook12; color: 0xFF000000; altColor: 0xFF000000; shadow: nilObject; sound: nilObject; border: iBorderBlack1; scrollOffset: <0.0,0.0>; gridFlags: 0x11200100; cellTextStyle: iBook12; columnTitles: (Text 11612); emptyMessage: (Text 9127); selectedColumn: 0; selectedRow: 0; titleTextStyle: iBook12Bold; list: (SummaryStack 9125); summaryString: nilObject; checkImage1: iRoundCheckMarkOff; checkImage2: iRoundXOff; checkAttribute1: operation_IsCollected; checkAttribute2: operation_IsDeleted; ignoreAttribute: operation_IsForwarded; offset1: <5.0>; key1: 7; // kTypeIcon type1: 3.w; // irrelevant flags1: 2.w; // irrelevant offset2: <42.0>; key2: operation_OriginatorName; // kSenderName type2: 7.w; // typeIDObject flags2: 1.w; // valueIsAttribute offset3: <168.0>; key3: 4; // kDateSent type3: 3.w; flags3: 66.w; //valueIsTextInfo|valueIsAbbreviated offset4: <235.0>; key4: 21; // kSizeInKBytes type4: 3.w; flags4: 34.w; //valueIsTextInfo | forceRightAligned offset5: <271.0>; key5: 0; // empty column for spacing type5: 0.w; // typeIDNone flags5: 1.w; // valueIsAttribute offset5: <276.0>; key5: operation_Subject; // kSubject type5: 7.w; // typeIDObject flags5: 1.w; // = valueIsAttribute offset5: <394.0>; key5: 19; // kCheckboxColumn type5: 0.w; // typeIDObject flags5: 0.w; offset5: <427.0>; key5: 22; // kCheckbox2Column type5: 7.w; // typeIDObject flags5: 1.w; // valueIsAttribute End Instance;
List views display strings, but your data won't always be in string format to start with. Specify the type of your data in each column's type field. The type is passed to ValueToText as the typeNumber parameter.
These are the type codes you can use in the column type extra field:
#define typeIDNone 0 #define typeIDFlags 1 #define typeIDBoolean 2 #define typeIDString 3 #define typeIDDouble 4 #define typeIDPoint 5 #define typeIDRect 6 #define typeIDObject 7 #define typeIDMicron 8 #define typeIDDot 9 #define typeIDBox 10 #define typeIDPixelDot 11 #define typeIDPixelBox 12 #define typeIDSignedByte 13 #define typeIDSigned 14 #define typeID7BitCharacters 15 #define typeIDPointer 16 #define typeIDSignedShort 17 #define typeIDFixed 19 #define typeIDCharactersPointer 20 #define typeIDUnsignedByte 21 #define typeIDUnsigned 22 #define typeIDUnsignedShort 23 #define typeIDCharacters 24 #define typeIDCharacter 25 #define typeIDLiteral 26
You can also find this list in the file Generic.h.
operation TouchedObject(touchInput: TouchInput; object: Object; column: Unsigned; row: Unsigned) Call: rarely Override: sometimes
The system calls TouchedObject from ListView_Touch if the selectMode flag is not set. The system calls Touch when the user taps a cell of the list view.
The touchInput parameter is passed along unchanged from the original Touch call. The object parameter is the object in the touched cell. The column and row parameters are the column and row numbers of the touched cell.
Override TouchedObject if tapping an item in your list view subclass should do something special. For example, you might want to go to a special destination when an object is touched. Or you might want to play a special sound.
ListView_TouchedObject already handles a number of special cases where touching an item in a list view should have an effect. Those special cases are:
If the item is none of the above, TouchedObject calls the item's GoTo methods.
operation DrawCell(canvas: Canvas; clip: Path; column: Unsigned; row: Unsigned; bounds: Box) Call: rarely Override: sometimes
The system calls DrawCell on each cell of the list view while drawing it. Override DrawCell if you need to customize the way your list view's cells are drawn.
operation RowHeight(row: Unsigned): Micron Call: rarely Override: sometimes
The system calls RowHeight while drawing a list view. The row parameter is the number of the row to check. RowHeight returns the height of the given row in microns. Class ListView doesn't override RowHeight. Class GridView defines RowHeight to return the height of the cell's text style.
Override RowHeight if your rows are taller than their text style. For example, you might using a custom subclass of ListView to display images in addition to text.
operation Confirm(), safe, common, noFail Call: rarely Override: sometimes
Override Confirm to do any work you need to accept current state of a ListView. For example, you might be using a custom subclass of ListView to allow your user to select an item from a list. When the user taps an "accept" button, you could call Confirm on the list view to ensure that the selection is valid.
If the list view's confirmOnSelect flag is set, the SetSelected and Touch methods will also call Confirm.
operation Swallow(morsel: Object; where: Dot; realSwallow: Boolean): Boolean Call: rarely Override: sometimes
Override Swallow to allow your list view to swallow certain kinds of morsels.
In your override, you probably want to call the inherited Swallow method for all other kinds of morsels. Do so with code that looks like this:
/* call inherited for all uninteresting morsels */ if (!Implements(morsel, InterestingMorselClass_)) return InheritedSwallow(self, morsel, where, realSwallow); /* go on to process interesting morsels */
See Viewable_Swallow for more information on the Swallow method's parameters and return value.