Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-146
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 146
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 146

High Level Toolbox: DataBrowser

Mac OS • 43:10

Learn how DataBrowser enables your application to present data as the Finder does, simplifying your application development and delivering a more consistent user experience. Implement views and highly customizable lists with variable row heights and cells that contain text, icons, checkboxes, and progress bars.

Speakers: Jim Roddden, Johnathon Suker

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning everyone. Please welcome John Galinzi, User Experience Technology Manager. Sorry. Well, good morning. It's a great day and I've certainly realized that I haven't had nearly enough sleep this week and that's probably true for many of you. But this is session 146 and it's High Level Toolbox: DataBrowser.

You know, as part of our renewed interest in user experience at Apple with Aqua and Mac OS X, we've been sort of stressing this message that if you want to have great user experience and you want to deliver the Aqua look and feel, you need to adopt system control. That sort of has come through this year and it's come through in past years. And it's particularly true with X.

And DataBrowser is one of those things coming out of Apple that's sort of a hybrid, high level, powerful new type of control and we're going to talk about that this morning. But DataBrowser is going to allow you to deliver exactly the user experience that we are delivering in lists, in Finder, and in other components of the OS. And it's going to do the right thing on 9 under Platinum. It's going to do the right thing on 10 under Aqua.

So even though it's early in the morning, you need to be paying close attention to what's going on here because DataBrowser, I think, is going to allow you to deliver a really awesome and very consistent user experience within your application. So to get you the info on this stuff, I'd like to welcome Jim Rodden, who's the tech lead for the list manager replacement called DataBrowser. Thanks.

Good morning. Good morning. I want to make sure you're all awake and in the right room, so I want to ask you a couple questions before I get started. Now stand up instead of show of hands. How many of you have ever used the list manager before? Now stand up, stand up, come on, this is audience participation.

Okay. Now how many of you don't use it anymore? Okay, that's a fair number. Now I'm sure the reason for that is pretty consistent. It kind of doesn't present a really sophisticated interface, and it's not very robust, and it has some serious limitations. I'm sure you're using other solutions like power plants, table views, and things like that. DataBrowser is going to take care of all of that stuff for you and present a new user interface, well, an interface that's been around for a while but hasn't been accessible to developers.

So with that, here's what I'm going to cover today. Basically, what is the DataBrowser thing? Go over briefly the programming model that it uses and how you can incorporate that into your code and how it will help you factor your code. And then some simple usage examples get into the coding.

What is this DataBrowser thing? It's a control. I want to emphasize that because it's actually pretty fundamental. It acts just like a push button control or a pop-up menu control or any other control that's been around for a long time. You can send it size control messages, move control messages, etc.

It's a completely self-contained presentation of discrete elements. So anytime you're presenting, say, a set of file system objects or database objects or whatever your application does, you should seriously consider DataBrowser as a solution for presenting that information. It is not the List Manager. List Manager is effectively obsolete now. It's still in Carbon. It's not going away because it's too important for backward compatibility.

But the DataBrowser is simply much, much, much better. It does what everyone wishes the List Manager had done all along, and it does it in a much better way. It takes a totally new programming model. It does not store your data. That was one of the serious limitations of the List Manager because it tried to make assumptions about your data and how it should be stored. And invariably, those assumptions were wrong in many cases.

DataBrowser only stores references to your data. So you can cache your data. You can store your data out on a network or file mapped or whatever's appropriate for your application. And the DataBrowser only asks for the information that it needs to present those elements that are currently on screen.

and its standard equipment. It is a very fundamental part of PEN. The Finder uses it. The Finder list view is a DataBrowser. And it's also in CarbonLib on 9. So you can rely on it to present the standard list style interface to your users. You don't have to reinvent this wheel anymore.

And because it's part of the Finder, and Sherlock, Keychain Access, and many other system components, you can rely on the fact that it is very robust, very fast, and very high performance. And now with that, Johnathon is going to give a quick demo of exactly what it does, so you have a visual image. Thanks, Jim. So here we have a sample application with DataBrowser. The DataBrowser control is actually everything in this window that you see that is not the window frame itself. You'll notice it looks exactly like the Finder.

No big... It's not an uncommon view. And we have some sample data showing here. So DataBrowser does everything that the Finder does. You can have Disclosure Triangles, so you can show more data, hierarchical data. You can do column resizing. You can do column reordering. DataBrowser also supports contextual menus and it supports drag and drop, all internally.

DataBrowser also supports several native data types: checkboxes, icon and text, text only. It also supports icon only, but we don't have any here. It supports date and time, supports relevance ranking, and it supports pop-up menus. One of the nice things since DataBrowser has native data types is that when you do things like resize date and time, the date and time format can grow to match the size of the column.

DataBrowser not only does list view, but it also does column view. And in this case, it's something new to Mac OS 9, but it's not new to Mac OS X. So this presents a column view that is standard in Mac OS X. You can see that it is good for displaying hierarchical data.

You get automatic traversal of aliases. And also, when you click on an end node, you get a custom preview pane. The content of this custom preview pane is entirely up--the drawing of it is entirely up to you. However, you do receive events, so you can have something like a push button.

And even though the control is taking up the entirety of this window, you do have certain control over the--

[Transcript missing]

Can we get the slides back? Thanks. Alright, thank you, Jonathan. One thing I'd like to point out, that the code specific to DataBrowser in that sample app is very small. It's on the order of 50 lines to get the bare minimum.

Now that demonstration does quite a bit more. It actually puts information in the drag and drops and... Handles some of the contextual menu stuff, so it's a little bit bigger than a simple app. It's maybe 100 or so lines, but very little. A lot less than it would take to do the same thing with List Manager or any power plant type table view or any of the other solutions out there. And it insulates you from the details of the presentation.

So just to recap, here's a fairly exhaustive list of the features that you get mostly for free. I mean, you have to do a little bit of work. Some of them you have to turn on some bit flags, set some accessors, and provide some routines of your own to, for instance, like contextual menu, you have to provide the menu to be displayed and you have to handle the response to it.

But that's pretty straightforward stuff. Some key points: It's designed to hold a lot of items. 2 to the 32. These are 32-bit references. Because the finder uses it, the finder has to display the contents of networks and file systems. Tens of thousands of items. That's what this is designed for. So no more 32K data limit or anything like that.

And again, it does a lot of the work for you. It has several native display types. The idea is you provide the data, the raw text, the raw icon. DataBrowser takes care of the formatting. And that list there is not complete for the native types, but it's extensible. If there's a display type that you want, that you think it should support, let us know and we'll see about adding it.

Also supports custom content, so if the view styles there are not sufficient for you, you can add your own content, have more complex information in the cells. And it'll store off the user state. So as the user resizes columns and reorders columns, for instance, you don't have to record that all yourself.

There's a call to ask the DataBrowser, "What is that state?" It'll flatten it out. You can store it off in a pref file and load it back in next time your application is run. Go into detail. Again, it's not just for Finder anymore. This is a screenshot from the 10 Finder. That is a DataBrowser.

Some additional features that it supports that are not necessarily used by the Finder are variable height rows, so you can have individual items have their own unique row height and it tracks with the item. It is not table index based. So as you resort or you add items, that item stays that height that you set it to.

It'll take care of right-to-left support for you. So, for instance, it doesn't at the moment, but at some point in the future, we may want to automatically invert the column ordering on right-to-left systems. You don't have to worry about that. It'll happen for free. And because everyone's using it, it'll happen across the system. Hierarchicalness is completely optional. If you want to present a flat file or flat list, you can. You just don't turn on the hierarchicalness. And you can have it in whatever column you want.

There's two different highlight styles. There's the traditional finder style where it just highlights the bare minimum around the text. Or you can have the band selection, like say in the chooser. And you can use whatever's appropriate for your interface. Under Platinum, it supports different theme backgrounds. So the default is the Finder style with the light gray background and the darker gray for the sort column. But it also supports the white style background like you find in the chooser.

And you can mix and match that with the highlight style so you can customize the look a little bit. Under Aqua, there really only is one theme background style, white, so it doesn't really apply there. But the API works just the same. So you can call the API to turn off the gray background and it doesn't make any difference on Aqua. Just a no-wop, basically.

And one thing that is coming from Aqua back to Platinum is the per column sort ordering. This is something that a lot of the third party implementations of this style of interface have done. Where instead of having one sort ordering, ascending, descending, that applies regardless of what column is the sort column, it's tracked per column. So you can have the first column ascending, second column descending, and as you switch back and forth, it remembers those sort orderings.

Here's an example of the list view under Platinum, or the column view, excuse me. Column view supports some additional features, the most prominent one being alias traversal, because the column view is designed for navigating through a hierarchy

[Transcript missing]

And it's smart about it. It doesn't ask for more data, it just already has that information, or if it already has that container open, it just replicates it.

It supports custom preview. So for instance, in the Finder, how it does the QuickTime preview or the picture preview in the last column, that's supported. Of course, you have to provide the code that actually renders in there and does the tracking in there. But it's completely-- that screen space is up to you. Again, you can have variable heights. The two highlight styles work there as well. This defaults to band selection, but you can turn that off and have the minimal highlight style. And again, you can have custom content in your items.

I don't want to go into too much detail on the performance, but I know some of you are concerned about that. Just again, remember the Finder uses it and NAV Services uses it, so it has to be very high performance. Throw up some numbers here to give you an example.

It's very lightweight, very scalable memory usage. It only uses as much memory based on how many items you've added to be displayed. And as containers are opened, of course those take a little bit more memory, but we've kept it to a minimum. And over the next few months, I'll be working on performance and may get that down even more.

And how many of you remember your algorithms class? Again, you don't need to worry about details, just remember it's fast. Basic idea here is it does binary searches internally. Now this is really just when your code is calling in to get information about items. For instance, is this item selected? Is this container opened? That's your code querying the DataBrowsers state. Internally, DataBrowsers is optimized to basically order one. So interactions with the user and rendering is as fast as it possibly can be.

So this is all you really need to remember. It's fast. And it's optimized for bulk operations. So if you want to do, say, threading, retrieval of your items, whether they be file system items or from a database, you can spawn that off in a thread and whenever you get a large enough chunk, insert it in one step into the DataBrowser and that will give you the best performance. So now I want to talk about the programming model a little bit and how you can use it to help factor your code.

Excuse me. This is not a new paradigm. It's not unique to the DataBrowser. It's very common in various frameworks: PowerPlant, MacApp, ThinkClass Library, for those that remember that. And the Cocoa frameworks are all oriented around the Model-View-Controller paradigm. Basic idea is the controller code is your framework code, it's your initialization, where you throw up your windows, you create your menus. And it's your event dispatching, where you take the raw events, this is a mouse click, and you figure out which subview it belongs to and you route it into that.

DataBrowser takes on the role of the view. It's in charge of presenting your information to the user, putting things on screen. And it takes those raw events, a mouse click for instance, and turns it into a semantic event, a double click or a drag on a particular item. And it talks to your application data, which is the really value add of your application.

It's what makes your application unique. and it stores the items you want to present to the user. Again, you're in charge of the data storage, the management, the caching, and whatever you need to take care of there. Now how do you get those items into the DataBrowser so they're displayed? There's a routine called "add items" where you add the references, unique item IDs, into the DataBrowser such that there's a one-to-one mapping between those item IDs and the data they represent.

DataBrowser uses callbacks to query information about those items as it needs it, so if an item isn't on screen, it's not going to ask for its text string because it doesn't need it. So you can take advantage of that in your caching scheme. Once again, to summarize: controller code creates the windows, creates the DataBrowser, passes events into the various views, including the DataBrowser. DataBrowser queries your application data as it needs it, and your application data sends messages back to the DataBrowser for adding items or changing the state.

Now DataBrowser needs to assume certain things about your data model and how the items relate to each other. It's a very minimal set of assumptions, but it basically defines the structure of the data. The most important of those is that each item has some set of properties. These are defined, again, by unique IDs. There are some that are predefined in the header.

Such as, is this item active? Can this item be selected? Is this item a container? Can this container be opened? So that gives you control over some of the behaviors. and it lets the DataBrowser communicate in a known language. You can define additional properties. For instance, the list view is very free form and, you know, DataBrowser doesn't know what kind of columns you want to present, that's up to you. So each time you create a column in the list view, you're defining a new property.

So there's a one-to-one mapping between columns and properties and those are properties you've defined and that you are telling the DataBrowser, here's some additional information that I have on this item that I want you to know about. And here's how to query details on it. But these are all optional. If you don't respond to the property request, DataBrowser assumes default values. Now, you really should respond to the properties that you define or else nothing's going to be put on screen.

Now one of those important predefined properties is, is an item a container? This is how you get the nested look and the hierarchicalness. And you use the container of a given item when you're adding it. So when you add items to the DataBrowser, you say, put these items inside this parent container. And that's how it creates the internal tree.

To summarize, DataBrowser stores references, not data. Very fundamental design decision. And it queries information about the items as it needs it based on the unique item IDs and the property IDs. And everything is optional. If you don't install a callback, you don't respond to a property, DataBrowser will assume and perform for you a default behavior.

Moving on to the API, that's a big number, 112 API calls. But don't let that intimidate you. I did a breakdown here. Most of those calls are just get set accessors. And if you're not interested in some of those, you can ignore them. These just allow you to customize the behavior and appearance. So it's a very flexible, very rich API.

Now, a trend in the control manager in general, since this is a control, is to move away from type unsafe structures that you turn into a void star pointer and pass in via send control message or set get control data. So these are really just wrappers, literally, they are wrappers in the implementation around get set data calls, but they're type safe, which makes your code more cleaner, more maintainable, less error prone, and the same for on our side. This is over and above the standard control manager calls. For instance, size control, move control, set control visibility. Those work just the same because it is a control.

But when you get right down to it, only six calls are really, really needed to do a bare bones implementation to just throw some information on screen. So most of those calls you don't need. Some of, for instance, the configuration and manipulation calls, some apply to all view styles, whether it be list view or column view. For instance, turn on the scroll bar, turn off the scroll bar.

And some are view style specific. For instance, the list view has a notion of a disclosure column, so you can specify the disclosure column. Whereas that doesn't mean anything to the column view. Conversely, the column view has a notion of a path, but the list view does not.

Plus there are two sets of callbacks broken into two pieces. There's the high level ones that deal with the standard behaviors and the low level ones that apply to the custom content. I'll go into those in a moment. Plus your standard control manager callbacks, key filter, input validation proc, those work as well.

Now the standard callbacks, the high level callbacks, these are what you're mostly interested in for the standard native display types. Most important to these is the Get Set Item Data. This is how the DataBrowser queries your application for text strings, icons, date values to present on screen. Again, you just provide raw data, DataBrowser takes care of the formatting.

It's called Get Set because this is also how the DataBrowser tells you that the user has completed an edit operation. For instance, the user has clicked a checkbox or clicked a pop-up menu or done a text edit. This is how DataBrowser provides that information back to you so you can store it off in your data.

There's item comparison for sorting. You're in charge of the sort operations. It just gives you two item IDs and asks for their relative ordering. So if you want to do secondary, tertiary sort orderings, that's up to you. If you want to have case sensitive or case insensitive sorting, that's up to you. If you don't install a comparison callback, it presents information in insertion order. So if you're providing a list of stack elements, then you get that for free. You don't even need to install a comparison routine.

DataBrowser will notify you of semantic events on items. For instance, double click, container opened, things like item selected, and does that via notification routine. There's some drag and drop handlers for adding data into a drag. Again, the DataBrowser sets up the drag, but you need to provide meaningful information into it, the drag flavors.

You are in charge of specifying whether a given item is interested in a drag. If you respond "yes" you are interested, DataBrowser will take care of highlighting that item appropriately to give the user feedback. And when the drag ultimately is dropped, again, it's your call to handle that because DataBrowser doesn't know what the data is, it just knows something was dropped on something else. And there's a cleanup operator. There's also HelpTags is the follow-on replacement to BalloonHelp. BalloonHelp is going away under Carbon. HelpTags gives a tooltips kind of appearance and interaction.

And DataBrowser supports that natively. Again, you need to provide the content, but the DataBrowser will take care of putting it up on screen and determining which item it goes with. So you can give HelpTags on an item-by-item basis. And same is true with contextual menu. You need to provide the menu, and you need to handle the user's response with just a couple of routines.

Very good. Excuse me. The low-level callbacks are for custom content. If you don't have custom content, you don't need to worry about these callbacks. If you do have custom content, you are telling the DataBrowser, "I want to be in charge of all rendering and tracking and hit testing for this item, wherever it may be on screen, when it's on screen." DataBrowser will give you the bounds at any given moment when you need to draw or hit test.

And the custom content is used for the preview column. That is a custom content space. So if you don't want a preview column, then don't install custom content. You just get a blank column. But if you do want to present preview information in the preview column, you need to install custom callbacks and handle them.

Now with a quick code demonstration of getting a bare bones implementation up and running, Johnathon's going to show that. Okay, so here we have an application that's basically the minimalist DataBrowser. It's a single column with seven elements. You can select them, you can click on the column and reorder them. As Jim said, we have no sort routine in here, so they're in insertion order. So this is your most basic application. Let's see what code was needed to create it.

Actually, Very little code was needed to create it. If you look at it, it's in total about 220 lines. Only about half of those are actually needed for the DataBrowser itself. And so we're just going to go quickly touch on what is actually needed for the DataBrowser. This is a Carbon event application, so we actually, it is a lot smaller because we don't have to do a lot of the event handling ourselves. It's taken care of automatically.

So the first thing we do is we create a window to put the DataBrowser in. We then create the DataBrowser to fill the entirety of that window. We'll then configure the DataBrowser, install the callbacks that are needed by DataBrowser to communicate with our application, and we'll populate the DataBrowser with our item references or item IDs, which will be given to the callback to request the information to be displayed. The rest of the application is basically just showing the window and running it.

So the first thing to do is to configure DataBrowser. Since DataBrowser is taking up the entirety of the window, we don't want to have a focus frame. DataBrowser will manage the focus frame for you if you want one, if you have, say, two DataBrowseers in a window and you want to change the focus between them.

So in ours, since we have a single window and it's taking up the entire contents, we turn it off. The second way that we configure it is DataBrowser installs columns by filling out a parameter block. Jim will be going into detail about this parameter block, but it's not very hard to fill out. It doesn't take very much.

Once you fill out the parameter block with the details about your column, you then add that column to the DataBrowser. And here we're setting the sort property to be the first column. If you have multiple columns, you can specify which of those columns you want to be the sort column initially. If you don't set it, nothing will be highlighted at the very beginning, but as soon as you click on a header button, it will then highlight.

Once you've installed the column into the DataBrowser, you then need to install your callback. Callbacks are also filled out or installed via parameter block. It's very simple. We only have one callback in this application, which is to actually get the data from our data model and return them to the DataBrowser. So we fill out the parameter block and install it into the DataBrowser.

Now that that's done, we need to populate the DataBrowser with our item IDs. Item IDs are entered into DataBrowser by using an array. So here we have a simple array of seven elements. These are actually indices into a simple string array. They can be anything you want. They're just numbers or IDs that are one-to-one mapping to your data model. So we create the array with our seven elements and we store them into DataBrowser.

And that's basically all you need to actually configure DataBrowser itself. We do, of course, have our one callback, which is for requesting the information from our data model. In this case, when DataBrowser needs to display its information, it will request via callback from our application or our data model using the item IDs, passing in an item ID into our callback. In this case, like I said, we have a... an array of strings with seven elements. So each time the callback is called, it gives an item ID. We return a string and DataBrowser displays it.

That's basically it for the application. There's not much to adding DataBrowser to your application. We do have a bit more code here. One of the interesting things is you can resize DataBrowser by a simple size control call. Basically, our...as our window resizes, we just resize the control to follow the bounds of the window. And that's it. Very easy to add. You get a lot of features with very little code. Anyway, here's Jim to describe the APIs and the callbacks more. Thank you, Jonathan.

Alright, here's the sequence that Johnathon just demonstrated to you to create and display a DataBrowser. It's pretty straightforward. You create it, one call. You configure it. There's a couple of steps there. You set up the format. In case of the list view, you need to add your columns. You install your callbacks and you populate with your initial set of items. And the last step is just handling the runtime. Handling the callbacks as the DataBrowser dispatches them and routing the raw events into the DataBrowser. I'll walk you through that.

Here's how you create a DataBrowser. Now you notice it's not using new control. Control Manager is moving away from that model because again, it's not type safe and it's based on the notion of code resources which are not supported in 10. So instead we're moving towards unique type safe routines for everything you want to do.

So it means we have more APIs, but it's no different than all the different structures that were introduced with the Appearance Manager. The arguments to this are a window ref, the bounds that you want, the initial view style, create either a list view or column view. Here we're creating a list view. And you get out a control ref. Pretty straightforward. So there, we've done step one.

Step 2 is formatting it. Now for the list view it's a little bit involved, but the basic idea is you create a param block, you fill out the values of the param block, and you add your column. So the details are really in that param block. First step is to create a property. You're defining a new property, telling the DataBrowser, "Here's a new property I know about and I want you to know about, too." That involves defining a property ID. It's a unique identifier.

This is how the DataBrowser communicates and queries information about that property. You say what visual information you want displayed for that property. This is where the native types come in. In this case, we're displaying icon and text. There's other constants for checkbox, pop-up menu, etc. Then you define some behaviors for the property.

In this case, we want this column to reflect the selection state. So if you want certain columns not to be highlighted when a given item is highlighted, you don't set this flag for those columns that you do. If you want all columns to--say you want a band selection to go all the way across, you need to set this bit flag for each column.

And here we're using the default column flags. They break down into other constants. They control, is this column sortable? So say you don't want sort property. You're just presenting a list and you don't want the user to be able to change the sort ordering. And sort is meaningless. Say you're presenting a stack of information and so sort doesn't have any meaning there.

So you wouldn't set that flag, but that's included in the default constant here. Also controls whether a column is movable. So if you want a column to be glued always to the left, for instance the finder always has the name column glued to the left, you can't move it over to the right, they don't have that flag set.

Next step is to define some behaviors and appearances of the ListView header. First part is the sort order. Again, sort order is on a per column basis. You need to provide an initial sort order. Provide the minimum and maximum width. This is for column resizing. If you don't want a column to be resized, just set these two values to be the same. And then the alignment. These are the standard TE flush default, TE center, left align, right align. And this also affects the appearance of the contents of that column. So the column content and the header text are aligned.

Next, we put these all together into a column descriptor. Again, the steps are: column is a property, contains some header information, some formatting information, and a CFStringRef that is the text to put in the header button. Now, CFStringRefs are the way to communicate textual information with the control manager now. Doing away with Pascal strings because they're difficult to localize, they're script-dependent. CFStringRefs, it's basically a Unicode string, so DataBrowser's Unicode-capable, off the block.

And you need to go to some of the Core Foundation sessions to learn more details about how to use CFStrings. And then you create the column. The last argument here is the ordinal position within it. So you can, as you're adding columns, you can specify what position you want to be in. In this case, we set a very large value. If you choose a value that's more than the number of columns currently in there, it just tacks it on the end. So we've set up the format. Now we're going to install the callbacks. Again, another param block.

Now the KDataBrowserLatestCallbacks constant may seem a little odd, but that's a versioning scheme we came up with so that we can provide backward compatibility In the future, if we need to add to this structure, change its formatting, maybe change the callbacks themselves, add new callbacks, replace callbacks, change argument signatures, we don't want to break your apps that you work on now as we need to make these changes in the future. Using this versioning scheme will allow us.

So the version number maps directly to the structure of this param block. If we need to augment this param block in the future, we'll increment that constant value. And next time you recompile with the new headers that have that new structure, you'll get the new constant. And you may need to do a little bit of work to adjust to the new callbacks, new layout. If you don't want to, you can just revert to the previous constant value. And you'll maintain binary compatibility.

We initialize the structure. For now, this just sets all the values to null. The UPPs just sets them to null. But at some point we may want to provide some default callbacks for you, and this is how you can get them. Basically, initialize it to a safe default value. Then you set each element within the structure to your UPPs that you create, and you install them. Okay, we're done with step two. But there is a step three.

We populate. We create an array of references. Now again, the references are whatever is meaningful to your application. They can be raw object pointers, C++ object pointers. They can be indices into an array that you maintain. They can be some hash table value. Whatever is appropriate. The only thing is that they need to always map one to one consistently to the same piece of data. The arguments to the routine here: the DataBrowser reference, the Control Ref. The parent item, as I mentioned, this is how you get the hierarchicalness. If you want it in the root level of the list, or displaying a flat list, you just say there is no parent.

The parent is the root item. You say how many items are in the array and the array itself. The last argument is a performance opportunity. Suppose You create your array in some order that maps to one of your sort orderings. You can tell the DataBrowser, and if the current sort property happens to match, DataBrowser can save on some sort operations. So it'll make it add a little bit faster. Okay, we're almost done.

Excuse me. All right. There we are. All right. I'm only going to go over one of the callbacks, the most fundamental one, the Get Set Data. As I said, this is used both for retrieving data from your data model and passing it to at the completion of an edit. That's what the last argument is for.

Most of the time, it will be set to false. That just means the DataBrowser says, "What's the text string you want me to display?" When it's set to true, it's saying, "Here's the text string the user just entered," or the new checkbox value the user just entered. And then it's going to update your data store. If you don't want to accept the value, that's fine. You can put up a dialogue to tell the user, "Sorry, that's an invalid new name," or, "You can't check this checkbox right now," and just ignore it.

But the main bulk of this is just a switch statement on the property that's being requested. You have a case entry for each property that you are interested in. If you don't want to respond to a property, DataBrowser assumes a default value. You need to check on whether the DataBrowser is giving you information or asking for information, but then you just install the information into an item data reference. That's a reference to the data that's going to be displayed.

Now if you don't respond to a property, it's important that you return this error code, because that tells the DataBrowser, "Give me the default value." We're almost there. One last easy step. This is your standard control manager calls. Draw one control, handle control click, et cetera. There's some new ones that I'm not going to go into detail here.

If you're interested in them, go to the Carbon enhancement sessions. They'll go over them. But basically, they allow the data browser to set the cursor. For instance, as the user drags over a resizable column, it'll change the arrow cursor into the bidirectional resize cursor. Some routines for doing drag and drop handling, and contextual menu. Again, go to the Carbon enhancement session if you're interested in those. There's an easier way. These Carbon events, and you install the standard event handlers on your window, you get all this for free. That's what the sample application Johnson showed did.

So there, we're done. Pretty straightforward. You create a DataBrowser, you configure it, that's the most involved step, but it's pretty straightforward too. You populate with initial items and you handle the runtime. Now DataBrowser API is quite stable. It's actually been used by the Finder Intents since PR2. And there are a couple of components in Mac OS 9 that use it. So we're pretty confident that it suits everyone's needs. But the DataBrowser does a lot more than those core services, Finder, Sherlock, etc. need. For instance, the variable row heights, custom content.

And so we had to make some best guesses of what reasonable behavior is there, since we don't have any clients that are really using it. So that's where we need your help. Please use them and give us feedback. If something doesn't work the way you think it should, let us know. The goal of the DataBrowser is to do the right thing. As much as possible and save you from work and do work for you. So let us know if DataBrowser can do something additional to make your life even easier.

It's available right now. The Mac OS X CD you got on Monday, DataBrowser is part of Carbon. When you use the Finder ListView, you're using a DataBrowser. It's in CarbonLib 1.1 for 9 only. It went through, it's in the D9 release, which I don't think has been posted just yet. I think it was built last week, going through QuickLooks this week. So it should be posted on the web next week, or maybe it might be there now, I haven't looked.

And you can get it through your Apple Developer Connection account. The APIs are defined in ControlDefinitions.h. Again, it hasn't made it into the Universal Headers releases, but the headers that come with the developer previews or the CarbonLib seeds, it's in there. And here's some contact information. I'm going to bring John back up to go over the rest.

So first of all, if you're working with DataBrowser and need to get some feedback through to Jim or the team, probably the best contact would be to go through myself with John Glunze, the first email address there. And there's also the high-level Toolbox feedback email, [email protected]. And the Carbon mailing list is a great place to basically live and discuss and keep conversations live with other Carbon developers who are using DataBrowser. Documentation address is there.

So some related sessions that you need to think about or consider attending, and these, some of them relate specifically to DataBrowser or some of the APIs that have been discussed here. Others relate to sort of the AQA interface and doing the right thing, and that's sort of where DataBrowser fits in a little bit as well. And most of these are pretty self-explanatory. But a couple that I want to call out is just the Carbon Event Model sessions, which happened on Tuesday. Hopefully you went to those, and if not, hopefully get you some information post the conference.

Carbon Enhancements 1 and 2, talk about some of the APIs that Jim referred to in the last few slides and you can get some info there. And then the feedback forums. Please come to the High-Level Toolbox feedback forums in terms of getting us feedback on High-Level Toolbox or the Aqua forum in terms of feedback on developer adoption of Aqua related issues. So I'd like to invite the team up on stage for a Q&A. If you have any questions, there's a few mics in the aisle.