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

BBEdit 11.6.6 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
Brackets 1.9.0 - Open Source Web design...
Brackets is an Open-Source editor for Web design and development built on top of Web technologies such as HTML, CSS, and JavaScript. The project was created and is maintained by Adobe, and is... Read more
Audio Hijack 3.3.4 - Record and enhance...
Audio Hijack (was Audio Hijack Pro) drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio... Read more
Tunnelblick 3.7.1a - GUI for OpenVPN.
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
Amazon Chime 4.3.5721 - Amazon-based com...
Amazon Chime is a communications service that transforms online meetings with a secure, easy-to-use application that you can trust. Amazon Chime works seamlessly across your devices so that you can... Read more
Posterino 3.3.7 - Create posters, collag...
Posterino offers enhanced customization and flexibility including a variety of new, stylish templates featuring grids of identical or odd-sized image boxes. You can customize the size and shape of... Read more
Airmail 3.2.9 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL, Outlook.com, Live.com. Airmail was designed... Read more
Arq 5.8.4 - Online backup to Google Driv...
Arq is super-easy online backup for Mac and Windows computers. Back up to your own cloud account (Amazon Cloud Drive, Google Drive, Dropbox, OneDrive, Google Cloud Storage, any S3-compatible server... Read more
Microsoft Remote Desktop 8.0.39 - Connec...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
Arq 5.8.4 - Online backup to Google Driv...
Arq is super-easy online backup for Mac and Windows computers. Back up to your own cloud account (Amazon Cloud Drive, Google Drive, Dropbox, OneDrive, Google Cloud Storage, any S3-compatible server... Read more

Latest Forum Discussions

See All

Clash of Clans' gets a huge new upd...
Clash of Clans just got a massive new update, and that's not hyperbole. The update easily tacks on a whole new game's worth of content to the hit base building game. In the update, that mysterious boat on the edge of the map has been repaired and... | Read more »
Thimbleweed Park officially headed to iO...
Welp, it's official. Thimbleweed Park will be getting a mobile version. After lots of wondering and speculation, the developers confirmed it today. Thimbleweed Park will be available on both iOS and Android sometime in the near future. There's no... | Read more »
Pokémon GO might be getting legendaries...
The long-awaited legendary Pokémon may soon be coming to Pokémon GO at long last. Data miners have already discovered that the legendary birds, Articuno, Moltres, and Zapdos are already in the game, it’s just a matter of time. [Read more] | Read more »
The best deals on the App Store this wee...
If you’ve got the Monday blues we have just the thing to cheer you up. The week is shaping up to be a spectacular one for sales. We’ve got a bunch of well-loved indie games at discounted prices this week along with a few that are a little more... | Read more »
Honor 8 Pro, a great choice for gamers
Honor is making strides to bring its brand to the forefront of mobile gaming with its latest phone, the Honor 8 Pro. The Pro sets itself apart from its predecessor, the Honor 8, with a host of premium updates that boost the device’s graphical and... | Read more »
The 4 best outdoor adventure apps
Now that we're well into the pleasant, warmer months, it's time to start making the most of the great outdoors. Spring and summer are ideal times for a bit of trekking or exploration. You don't have to go it alone, though. There are plenty of... | Read more »
Things 3 (Productivity)
Things 3 3.0.1 Device: iOS iPhone Category: Productivity Price: $7.99, Version: 3.0.1 (iTunes) Description: Meet the all-new Things! A complete rethinking of the original, award-winning task manager – with a perfect balance between... | Read more »
Oddball mash-up Arkanoid vs Space Invade...
In a move no one was really expecting, Square Enix has put forth an Arkanoid/Space Invaders mash-up aptly titled Arkanoid vs Space Invaders. The game launched today on both iOS and Android and the reviews are actually quite good. [Read more] | Read more »
Arkanoid vs Space Invaders (Games)
Arkanoid vs Space Invaders 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: LAUNCH SALE: GET THE GAME AT 20% OFF! Two of the most iconic classic games ever made meet in Arkanoid vs Space... | Read more »
The best new games we played this week
Things got off to a bit of a slow start this week, but as we steadily creep towards Friday a bunch of great games have started cropping up. If you're looking for a quality new release to play this weekend, we've got you covered. Here's a handy... | Read more »

Price Scanner via MacPrices.net

touchbyte Releases PhotoSync 3.2 for iOS With...
Hamburg, Germany based touchbyte has announced the release of PhotoSync 3.2 for iOS, a major upgrade to the versatile and powerful app to transfer, backup and share photos and videos over the air.... Read more
Emerson Adds Touchscreen Display and Apple Ho...
Emerson has announced the next evolution of its nationally recognized smart thermostat. The new Sensi Touch Wi-Fi Thermostat combines proven smarthome technology with a color touchscreen display and... Read more
SurfPro VPN for Mac Protects Data While Offer...
XwaveSoft has announced announce the release and immediate availability of SurfPro VPN 1.0, their secure VPN client for macOS. SurfPro VPN allows Mac users to protect their internet traffic from... Read more
13-inch Touch Bar MacBook Pros on sale for $1...
B&H Photo has 13″ MacBook Pros in stock today for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 13″ 2.9GHz/512GB Touch Bar MacBook Pro Space Gray (... Read more
Tuesday deal: $200 off 27-inch Apple iMacs
Amazon has select 27″ iMacs on sale for $200 off MSRP, each including free shipping: - 27″ 3.3GHz iMac 5K: $2099 $200 off MSRP - 27″ 3.2GHz/1TB Fusion iMac 5K: $1799 $200 off MSRP Keep an eye on our... Read more
Five To Six Million 10.5-inch iPad Pro Tablet...
Digitimes’ Siu Han and Joseph Tsai report that upstream supply chain shipments for Apple’s new 10.5-inch iPad Pro have been increasing, with monthly shipment volume expected to hit 600,000 units by... Read more
Georgia Tech Students Win Toyota and Net Impa...
Earlier this year, a team of students at Georgia Tech realized that there was a critical gap in transportation services for people who use wheelchairs, and wondered if the solution could be in the... Read more
13-inch 2.0GHz Space Gray MacBook Pro on sale...
Amazon has the 13″ 2.0GHz Space Gray non-Touch Bar MacBook Pro (MLL42LL/A) on sale for $1299.99 including free shipping. Their price is $200 off MSRP, and it’s currently the lowest price available... Read more
Roundup of 15-inch MacBook Pro sale prices, m...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $200 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 15″ 2.7GHz... Read more
15-inch 2.2GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 15″ 2.2GHz Retina MacBook Pro (MJLQ2LL/A) on sale for $1849 including free shipping plus NY & NJ sales tax only. Their price is $150 off MSRP. Read more

Jobs Board

*Apple* Technical Support - Atrilogy (United...
Our direct client is looking for an Apple Technical Support / Apple Help Desk Specialist for a Full Time Direct Hire role in West Los Angeles by Playa Vista, CA Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
Director *Apple* Platform, IS Data Manageme...
…a real difference. Come, shine with us! Astellas is announcing a Director Apple Platform, IS Data Management Lead opportunity in Northbrook, IL. Purpose & Scope: Read more
Director *Apple* ERP Integration Lead - Ast...
…make a real difference. Come, shine with us! Astellas is announcing a Director Apple ERP Integration Lead opportunity in Northbrook, IL. Purpose & Scope: This role Read more
Associate Director *Apple* Platform -- SAP...
…real difference. Come, shine with us! Astellas is announcing a Associate Director Apple Platform -- SAP Security, Risks and Controls Lead opportunity in Northbrook, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.