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

Slack 2.7.1 - Collaborative communicatio...
Slack is a collaborative communication app that simplifies real-time messaging, archiving, and search for modern working teams. Version 2.7.1: You're nearly finished signing in when suddenly – bonk... Read more
Dashlane 4.8.4 - Password manager and se...
Dashlane is an award-winning service that revolutionizes the online experience by replacing the drudgery of everyday transactional processes with convenient, automated simplicity - in other words,... Read more
FileZilla 3.27.1 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.27.1: Fixed Vulnerabilities: Change client... Read more
f.lux 39.984 - Adjusts the color of your...
f.lux makes the color of your computer's display adapt to the time of day, warm at night and like sunlight during the day. Ever notice how people texting at night have that eerie blue glow? Or wake... Read more
Merlin Project 4.2.7 - $289.00
Merlin Project is the leading professional project management software for OS X. If you plan complex projects on your Mac, you won’t get far with a simple list of tasks. Good planning raises... Read more
Sound Studio 4.8.10 - Robust audio recor...
Sound Studio lets you easily record and professionally edit audio on your Mac. Easily rip vinyls and digitize cassette tapes, or record lectures and voice memos. Prepare for live shows with live... Read more
Google Chrome 60.0.3112.101 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Microsoft Office 2016 15.37 - Popular pr...
Microsoft Office 2016 - Unmistakably Office, designed for Mac. The new versions of Word, Excel, PowerPoint, Outlook and OneNote provide the best of both worlds for Mac users - the familiar Office... Read more
Sketch 46.2 - Design app for UX/UI for i...
Sketch is an innovative and fresh look at vector drawing. Its intentionally minimalist design is based upon a drawing space of unlimited size and layers, free of palettes, panels, menus, windows, and... Read more
beaTunes 5.0.4 - Organize your music col...
beaTunes is a full-featured music player and organizational tool for music collections. How well organized is your music library? Are your artists always spelled the same way? Any R.E.M. vs REM?... Read more

The best apps for viewing the solar ecli...
If you somehow missed the news, many parts of the United States will be witness to a total solar eclipse on August 21 for the first time in over 90 years. It'll be possible to see the eclipse in at least some capacity throughout the continental U... | Read more »
The 5 best mobile survival games
Games like ARK: Survival Evolved and Conan Exiles have taken the world of gaming by storm. The market is now flooded with hardcore survival games that send players off into the game's world with nothing but maybe the clothes on their back. Never... | Read more »
Portal Walk (Games)
Portal Walk 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Portal Walk is adventure and relaxing platform game about Eugene. Eugene stuck between worlds and trying to find way back home.... | Read more »
Technobabylon (Games)
Technobabylon 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: City of Newton, 2087. Genetic engineering is the norm, the addictive Trance has replaced almost any need for human interaction,... | Read more »
5 reasons why 2v2 is the best mode in Cl...
Supercell has been teasing fans with 2v2 windows that allow players to team up for limited periods of time. The Summer of 2v2 was just this past July, but players are already clamoring for more of that sweet, sweet team-based action. The fans have... | Read more »
The best deals on the App Store this wee...
It seems like the week's only just started, and yet here we are with a huge pile of discounted games to sort through. There are some real doozies on sale this week. We're talking some truly stellar titles. Let's take a look at four of the best... | Read more »
Cat Quest Guide - How to become a purrfe...
Cat Quest is an absolutely charming open-world RPG that's taken the gaming world quite by storm. This game about a world populated by furry kitty warriors is actually a full-length RPG with sturdy mechanics and a lovely little story. It's certainly... | Read more »
Silly Walks Guide - How to strut your st...
Silly Walks is an all new adventure game that lives up to its name. It sees you playing as a variety of snack foods as you teeter-totter your way to rescue your friends from the evil blender and his villainous minions. It's all very . . . well... | Read more »
The best mobile point-and-click adventur...
Nostalgia for classic point-and-click adventure games has reached an all-time high in recent years, and the rise of mobile games have provided a perfect platform for this old-school genre. This week we're going to take a look at some of the best... | Read more »
Titanfall: Assault Beginner's Guide...
Respawn's dazzling mech battler Titanfall has gotten its first mobile game at long last -- Titanfall: Assault. Assault transforms that parkour FPS action into a card battler not dissimilar to Clash Royale. Titanfall: Assault isn't just another... | Read more »

Price Scanner via MacPrices.net

New iOS 11 Productivity Features Welcome But...
The iOS community is in late summer holding mode awaiting the September arrival of the iPhone 8 and iOS 11. iOS 11 public betas have been available for months — number six was released this week —... Read more
Samsung Electronics Launches New Portable SSD...
Samsung Electronics America, Inc. has announced the launch of Samsung Portable SSD T5 – its newest portable solid state drive (PSSD) that raises the bar for the performance of external memory... Read more
TrendForce Reports YoY Gain of 3.6% for 2Q17...
Market research firm TrendForce reports that the global notebook shipments for this second quarter registered a sequential quarterly increase of 5.7% and a year-on-year increase of 3.6%, totaling 39.... Read more
Sale! 10-inch iPad Pros for $50 off MSRP, no...
B&H Photo has 10.5″ iPad Pros in stock today and on sale for $50 off MSRP. Each iPad includes free shipping, and B&H charges sales tax in NY & NJ only: – 10.5″ 64GB iPad Pro: $599, save $... Read more
Sale! 2017 13-inch Silver 2.3GHz MacBook Pro...
Amazon has new 2017 13″ 2.3GHz/128GB Silver MacBook Pro on sale today for $100 off MSRP including free shipping. Their price is the lowest available for this model from any reseller: – 13″ 2.3GHz/... Read more
WaterField Unveils Collaboratively-Designed,...
In collaboration with customers and seasoned travelers, San Francisco maker WaterField Designs set out to create the preeminent carry-on system to improve the experience of frequent fliers. The... Read more
Miya Notes Mac-Client for Google Keep (Launch...
MacPlus Software has announced te launch of Miya Notes for Google Keep 1.0, a powerful Mac-client for Google Keep. Millions of people use Google Keep on their phones and online, but a convenient Mac... Read more
Apple refurbished iMacs available starting at...
Apple has previous-generation Certified Refurbished 2015 21″ & 27″ iMacs available starting at $849. Apple’s one-year warranty is standard, and shipping is free. The following models are... Read more
2017 13-inch MacBook Airs on sale for $100 of...
B&H Photo new 2017 13″ MacBook Airs on sale today for $100 off MSRP, starting at $899: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $100 off MSRP – 13″ 1.8GHz/256GB MacBook Air (MQD42LL/A... Read more
12-inch MacBooks on sale for $100 off MSRP
Amazon has 2017 12″ Retina MacBooks on sale for $100 off MSRP. Shipping is free: 12″ 1.2GHz Space Gray MacBook: $1199.99 $100 off MSRP 12″ 1.2GHz Silver MacBook: $1198 $101 off MSRP 12″ 1.2GHz Gold... Read more

Jobs Board

*Apple* Customer Experience (ACE) Leader - A...
…management to deliver on business objectivesTraining partner store staff on Apple products, services, and merchandising guidelinesCoaching partner store staff on Read more
*Apple* Solutions Consultant (ASC) - Poole -...
Job Summary The people here at Apple don't just create products - they create the kind of wonder that's revolutionised entire industries. It's the diversity of those Read more
Business Development Manager, *Apple* iClou...
Job Summary Apple is seeking an entrepreneurial person to help grow the Apple iCloud business, a service that is integral to the Apple customer experience. Read more
Product Metrics Manager - *Apple* Media Pro...
Job Summary Apple is seeking a product manager responsible for overseeing the instrumentation and analysis of usage data, in order to make data driven product Read more
iOS Wallet & *Apple* Pay Engineer - App...
Job Summary The iOS Apple Pay & Wallet team is looking for talented,...now add credit and debit cards to Wallet using Apple Pay. You can use Apple Pay in Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.