TweetFollow Us on Twitter

Expanded Lists
Volume Number:9
Issue Number:8
Column Tag:C Workshop

Related Info: List Manager

Expanding the List Manager

Adding graphics to lists with Custom LDEFs

By Mark W. Batten, Washington, DC

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

The List Manager is not especially well-named. The term “list” suggests one column of text, as in a shopping list or an address list. In fact, the List Manager is much more flexible: it can maintain information in rows and columns, as in a spreadsheet, and can manage data of any kind, including graphics.

The purpose of this article is to demonstrate two simple list definition procedures, or LDEFs, that extend the List Manager’s text-only list to include graphics. First, we’ll create a list of icons with text underneath, sort of like those that appear in Finder windows. Second, we’ll develop a list that puts a small icon next to each entry, the way the standard Open and Save dialog boxes do.

Setting up the application for our LDEFs

When using a custom LDEF, the List Manager leaves the drawing of each cell -- and the interpretation of the data in the cell -- entirely up to you. So to create a list that has both text and graphics in a list, all you have to do is put the graphics data and text in each cell. The LDEF will then interpret the data when it draws the cell. In our example, we just have the application stuff the icon data into the cell, followed by the text (a Pascal string), using List Manager routines:

/* 1 */

 LSetCell(IconPtr,128,theCell,LH);
 LAddToCell(IconName,(int)IconName[0]+1,theCell,LH);

Example 1: The Icon List

The List Manager sends four different kinds of messages to LDEFs: “initialize,” “draw,” “highlight,” and “close.” The initialize and close routines are rarely needed unless your LDEF needs to allocate its own memory for storage; we’ll focus here on the draw and highlight routines to show how they interpret the icon and text data.

Our first example is a list of icons with text underneath. Such a list has lots of uses: showing the user the files in an individual directory, or in an archive file; asking the user to choose from among a list of options; or any time you want to present a list of items in a graphically appealing way. Let’s examine the DoDraw routine in detail.

/* 2 */

doDraw(select,r,offset,LH)
Boolean select;
Rect *r;
int offset;
ListHandle LH;
{

The List Manager sends an LDrawMsg for each cell in the list, so the DoDraw routine’s task is to draw one cell. The cell to draw is passed to the LDEF in two parameters: the Rect r is the rectangle in which to draw the cell, and offset holds the offset into the list’s cell data where the information for this cell begins.

The routine begins with a number of cosmetic effects: it fills the cell with a gray pattern, and then draws a border around the icon. These obviously aren’t essential, but are included here because they help the icon stand out against the background and to give it a three-dimensional appearance:

/* 3 */

 FillRect(r,grey);
 r->top+=(r->bottom-r->top-32)/2;
 r.left+=(r->right-r->left-32)/2;
 r->bottom=r->top+32;
 r->right=r->left+32;
 InsetRect(r,-4,-4); 
 r1=*r;
 FillRect(r,wite); 
 FrameRect(r); 
 InsetRect(r,3,3);
 FrameRect(r); 
 InsetRect(r,1,1); 
 PenPat(dark);
 for(i=1;i<3;i++){
 MoveTo(r->left-(i+1),r->bottom+i);
 LineTo(r->right+i,r->bottom+i);
 MoveTo(r->right+i,r->top-(i+1));
 LineTo(r->right+i,r->bottom+i); 
 }
 PenNormal();

Now we draw the icon. To do so, we have to set up a BitMap that we can pass to CopyBits. Because each cell begins with icon data (which the application put there, remember?), the BitMap’s baseAddr should point to the beginning of the cell’s data. The other BitMap fields are easy, since they’re determined by the size of an icon:

/* 4 */

 HLock((**LH).cells); 
 icon.baseAddr=(char *)(*(**LH).cells)+offset;
 SetRect(&icon.bounds,0,0,32,32);
 icon.rowBytes=4;

Now we’re ready to draw the icon and move on to the text, which the application stored in the cell right after the 128 bytes of icon data. Note that the destination BitMap is supplied by the ListRec, which maintains a GrafPtr for the port the list appears in:

/* 5 */

 src=icon.bounds;
 CopyBits(&icon,&((**LH).port->portBits),&src,r,0,0L); 
 offset+=128;

Now we’re ready to draw the text under the icon. First, let’s copy the text out of the cell data into a local string variable:

/* 6 */

 q=(char *)(*(**LH).cells)+offset; 
 s=p;
 len=*s++=*q++;
 while(--len>=0)*s++=*q++; 
 HUnlock((**LH).cells);

Now we want to center the text in the cell. If the text is too long, though, we don’t want it to run off the edges, so we curtail the string and add a “ ” character to the end. In this example, the LDEF limits text to a maximum of five characters. We also need to erase the text’s rectangle before drawing it, because the text won’t be readable if we just draw the string over the gray pattern we painted into the cell:

/* 7 */

 if(*p>5){ 
 p[5]=0xC9; /* ' ' */
 *p=5;
 }
 c=(r->left+16)-(StringWidth(p)/2);
 GetFontInfo(&inf); 
 i=r->bottom+inf.ascent+inf.descent+inf.leading;
 SetRect(&r1,c,r->bottom+4,c+StringWidth(p),i);
 EraseRect(&r1);
 MoveTo(c,i); 
 DrawString(p);

That’s all there is to it; the final lines just invert the icon if the cell is supposed to be highlighted, first clearing the high bit of the global variable HiliteMode to ensure that the highlighting will use the highlight color on color machines:

/* 8 */

 if(select){
 HiliteMode&=127;
 InvertRect(r);
 }

Example 2: Open and Save Lists

Our second example is the kind of list seen in the Mac’s Open and Save dialog boxes: a list of text items with a small icon (“SICN”) to the left of each entry. This type of list could be handled in much the same way as Example 1, but let’s experiment with a slightly different technique that uses a little less memory.

For our example, we indicate a file’s type with one of three SICNs: a generic application icon for applications, a folder icon for folders, and a generic document icon for all others. With so few icons, there’s no need to store the actual data in each individual cell. Instead, as part of the setup, we have the application read in the appropriate SICN resource and store it in the ListHandle’s userHandle field:

/* 9 */

 SmIcons=Get1Resource('SICN',128); 
 (**(LH)).userHandle=SmIcons;

Then, in storing data in the cells, the application puts in the text, followed by one byte that indicates which SICN in the list to use:

/* 10 */

 PBGetCatInfo(&theParamBlk,false); /* get a file's info */
 LDoDraw(false,LH);
 b=(**(LH)).dataBounds.bottom;
 theCell.v=LAddRow(1,++b,LH); 
 theCell.h=0; 
 if((theParamBlk.ioFlAttrib & 16)!=0)theType=0;
 else{
 if(theParamBlk.ioFlFndrInfo.fdType=='APPL')theType=2; 
 else theType=1;
 }
 LSetCell(n,(int)(*n+1),theCell,LH);
 LAddToCell(&theType,1,theCell,LH);
 LDoDraw(true,LH);

Now let’s look at the Example 2 LDEF’s DoDraw routine to see how to interpret this data. Here we begin by erasing the cell, which is more appropriate for this list than the gray pattern we used in Example 1. Then we set up the destination rectangle to the left edge of the cell, and set up the bounds and rowBytes of the source BitMap:

/* 11 */

 dst=*r; 
 dst.right=dst.left+16;
 SetRect(&icon.bounds,0,0,16,16); 
 icon.rowBytes=2;

To set up the baseAddr field, we first retrieve the byte that we stored at the end of the text. Because there are 32 bytes in each small icon, we multiply the flag byte by 32 to get the proper position in the small icon list, stored in the userHandle. A call to CopyBits completes the drawing:

/* 12 */

 HLock((**LH).cells);
 s=q=(char *)*(**LH).cells;
 q+=off; 
 s+=off;
 q+=(*q+1); 
 icnoff=*q<<5;
 HLock((**LH).userHandle);
 icon.baseAddr=(*(**LH).userHandle)+icnoff;
 CopyBits(&icon,&((**LH).port->portBits),&(icon.bounds), &dst,0,0L);
 HUnlock((**LH).userHandle);

Drawing the text is then similar to Example 1, except that we move the pen to the 
right of the small icon and center it in the cell:

/* 13 */

 GetFontInfo(&inf); 
 len=inf.ascent+inf.descent+inf.leading;
 MoveTo(dst.right+2,(r->bottom+r->top+len)/2-inf.descent);
 DrawString(s);
 HUnlock((**LH).cells);
 if(select)InvertRect(r);

This example uses black-and-white icons, but color icons could be handled the same way; just use a PixMap instead of a BitMap.

Example 1 Source Code
#include "SetUpA4.h"
Pattern grey={ 170,85,170,85,170,85,170,85 },
 wite={ 0,0,0,0,0,0,0,0 },
 dark={ 119,238,221,187,119,238,221,187 };

pascal void main(message,select,r,theCell,offset,len,LH)
int message,offset,len;
ListHandle LH;
Cell theCell;
Boolean select;
Rect *r;
{
 int l;

 RememberA0();
 SetUpA4();
 switch(message){
 case 0: break;
 case 1: 
 case 2: doDraw(select,r,offset,LH); break;
 case 3: break;
 }
 RestoreA4();
}

doDraw(select,r,offset,LH)
Boolean select;
Rect *r;
int offset;
ListHandle LH;
{
 BitMap icon; 
 Rect src,r1; 
 char p[32],*q,*s,c; 
 register int len,i;
 FontInfo inf;
 
 FillRect(r,grey);
 r->top+=(r->bottom-r->top-32)/2;
 r->left+=(r->right-r->left-32)/2;
 r->bottom=r->top+32;
 r->right=r->left+32;
 InsetRect(r,-4,-4); 
 r1=*r;
 FillRect(r,wite); 
 FrameRect(r); 
 InsetRect(r,3,3);
 FrameRect(r); 
 InsetRect(r,1,1); 
 PenPat(dark);
 for(i=1;i<3;i++){
 MoveTo(r->left-(i+1),r->bottom+i);
 LineTo(r->right+i,r->bottom+i);
 MoveTo(r->right+i,r->top-(i+1));
 LineTo(r->right+i,r->bottom+i); 
 }
 PenNormal();

 HLock((**LH).cells);
 icon.baseAddr=(char *)(*(**LH).cells)+offset;
 SetRect(&icon.bounds,0,0,32,32); 
 icon.rowBytes=4;
 src=icon.bounds;
 CopyBits(&icon,&((**LH).port->portBits),&src,r,0,0L);
 offset+=128;
 
 q=(char *)(*(**LH).cells)+offset; 
 s=p;
 len=*s++=*q++;
 while(--len>=0)*s++=*q++; 
 HUnlock((**LH).cells);
 
 if(*p>5){ 
 p[5]=0xC9; 
 *p=5;
 }
 c=(r->left+16)-(StringWidth(p)/2);
 GetFontInfo(&inf); 
 MoveTo(c,r->bottom+inf.ascent+inf.descent+inf.leading); 
 DrawString(p); 
 if(select){
 HiliteMode&=127;
 InvertRect(r);
 }
}

Example 2 Source Code

#include "SetUpA4.h"
Pattern grey={ 170,85,170,85,170,85,170,85 };

pascal void main(message,select,r,theCell,offset,len,LH)
int message,offset,len;
ListHandle LH;
Cell theCell;
Boolean select;
Rect *r;
{
 /* This routine is the same as in Example 1 */
}

doDraw(select,r,offset,LH)
Boolean select;
Rect *r;
int offset;
ListHandle LH;
{
 BitMap icon; 
 Rect dst; 
 char *q,*s,icnoff; 
 int len;
 FontInfo inf;
 
 EraseRect(r); 
 dst=*r; 
 dst.right=dst.left+16;
 SetRect(&icon.bounds,0,0,16,16); 
 icon.rowBytes=2;
 HLock((**LH).cells);
 s=q=(char *)*(**LH).cells;
 q+=off; 
 s+=off;
 q+=(*q+1); 
 icnoff=*q<<5;
 HLock((**LH).userHandle);
 icon.baseAddr=(*(**LH).userHandle)+icnoff;
 CopyBits(&icon,&((**LH).port->portBits),&(icon.bounds),
 &dst,0,0L);
 HUnlock((**LH).userHandle);
 
 GetFontInfo(&inf); 
 len=inf.ascent+inf.descent+inf.leading;
 MoveTo(dst.right+2,(r->bottom+r->top+len)/2-inf.descent);
 DrawString(s);
 HUnlock((**LH).cells);
 if(select){
 HiliteMode&=127;
 InvertRect(r);
 }
}

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Black Hole Joyrider (Games)
Black Hole Joyrider 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Guide your spacecraft through the gravity well of a powerful black hole using only your retro-thrusters and dwindling fuel... | Read more »
My Koi (Games)
My Koi 1.0 Device: iOS iPhone Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: My Koi is a beautiful and relaxing fish pond app. Customise and name each fish. Feed them daily. Watch them grow. Collect new fish.... | Read more »
Never Gone (Games)
Never Gone 1.0.2 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.2 (iTunes) Description: ###IMPPORTANT### Never Gone's HD art resources require devices with more than 1GB RAM, so please note that iPhone 4/4s, iPad 2/... | Read more »
INKS. (Games)
INKS. 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: From the makers of BAFTA-winning Lumino City comes INKS. INKS updates pinball for a new generation. It combines the joy of pinball with... | Read more »
How to maximise your profits in Bakery B...
Running a bakery can be an expensive venture. You’ll need to continuously upgrade your oven, your kitchen supplies, and even your ingredients to keep customers happy. Most of these renovations in Bakery Blitz cost a pretty penny, but we have a few... | Read more »
How to manage your time in Bakery Blitz
It can be tricky, especially when you risk burning your kitchen to the ground if you forget a cake in the oven, so make sure to use these time management tricks to keep your bakery running smoothly. Don’t collect the money right away [Read more] | Read more »
Model 15 (Music)
Model 15 1.0 Device: iOS iPhone Category: Music Price: $29.99, Version: 1.0 (iTunes) Description: The Moog Model 15 App is the first Moog modular synthesizer and synthesis educational tool created exclusively for iPad, iPhone and... | Read more »
How to deal with wind in Angry Birds Act...
Angry Birds Action! is a physics-based puzzler in which you're tasked with dragging and launching birds around an obstacle-littered field to achieve a set objective. It's simple enough at first, but when wind gets introduced things can get pretty... | Read more »
How to get three stars in every level of...
Angry Birds Action! is, essentially, a pinball-style take on the pull-and-fling action of the original games. When you first boot it up, you'll likely be wondering exactly what it is you have to do to get a good score. Well, never fear as 148Apps... | Read more »
The beginner's guide to Warbits
Warbits is a turn-based strategy that's clearly inspired by Nintendo's Advance Wars series. Since turn-based strategy games can be kind of tricky to dive into, see below for a few tips to help you in the beginning. Positioning is crucial [Read... | Read more »

Price Scanner via MacPrices.net

12-inch 128GB iPad Pros on sale for up to $10...
B&H Photo has 12″ 128GB WiFi iPad Pros on sale for up to $100 off MSRP, each including free shipping. B&H charges sales tax in NY only: - 12″ Space Gray 128GB WiFi iPad Pro: $899 $50 off MSRP... Read more
Global Tablet Sales Slump Continues, iPad’s F...
Another miserable showing for the global slate tablet category in calendar Q1/16, with global tablet shipments falling another 1ten percent to 46.5 million units during the according to Strategy... Read more
Revel Systems to Showcase iPad POS Platform w...
Revel Systems, specialists in iPad Point of Sale management solution for brick-and-mortar retail, food businesses and more, today announced that it will showcase its innovative iPad Point of Sale... Read more
13-inch 2.5GHz MacBook Pro on sale for $999,...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $999 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
Apple refurbished 2015 iMacs available for up...
Apple now has a full line of Certified Refurbished 2015 21″ & 27″ iMacs available for up to $350 off MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are... Read more
Indian Smartphone Market Grows Annually by 12...
India’s smartphone market grew by 12 percent year-over-year, with 24.4 million units shipping in Q1 2016. The top five vendors stayed the same, with Samsung in the lead, followed by Micromax, Intex... Read more
Get Notifications When Your Friend’s Phone Ba...
Calgary, Canada based Stonelight Pictures has announced the release of Battery Share 1.0.1, its new utility for iOS 9 supported devices. The company notes that people are spending more time on their... Read more
11-inch 1.6GHz/128GB MacBook Air on sale for...
Amazon has the current-generation 11″ 1.6GHz/128GB MacBook Air (sku MJVM2LL/A) on sale for $749.99 for a limited time. Their price is $150 off MSRP, and it’s the lowest price available for this model... Read more
Price drops on clearance 2015 13-inch MacBook...
B&H Photo has dropped prices on clearance 2015 13″ MacBook Airs by up to $250. Shipping is free, and B&H charges NY sales tax only: - 13″ 1.6GHz/4GB/128GB MacBook Air (MJVE2LL/A): $799, $200... Read more
Mac minis on sale for up to $100 off MSRP
B&H Photo has Mac minis on sale for up to $100 off MSRP including free shipping plus NY sales tax only: - 1.4GHz Mac mini: $449 $50 off MSRP - 2.6GHz Mac mini: $649 $50 off MSRP - 2.8GHz Mac mini... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Automotive Sales Consultant - Apple Ford Linc...
…you. The best candidates are smart, technologically savvy and are customer focused. Apple Ford Lincoln Apple Valley is different, because: $30,000 annual salary Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Simply Mac *Apple* Specialist- Service Repa...
Simply Mac is the largest premier retailer of Apple products in the nation. In order to support our growing customer base, we are currently looking for a driven Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.