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: wwdc2007-147
$eventId
ID of event: wwdc2007
$eventContentId
ID of session without event part: 147
$eventShortId
Shortened ID of event: wwdc07
$year
Year of session: 2007
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC07 • Session 147

Advanced Java Development on Mac OS X

Mac OS X Essentials • 1:02:20

Listen as members of Apple's Java engineering team show you how to add polish to your Java application. Learn how to use resolution-independent artwork, adopt custom Aqua controls from within Swing, and how to open documents from the Finder. You will also discover tricks for integrating toolkits such as SWT and Cocoa within your application, and find out if your application should go 64-bit. This session covers the advanced features you need to maximize the features of Java on Mac OS X Leopard.

Speakers: Scott Kovatch, Mike Swingler

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Good afternoon everybody. Thank you for hanging around to the end of WWDC this year. My name is Scott Kovatch, and I am an engineer on the Java team here at Apple. And now you have the answer to the question to who is that guy that's been hobbling around on crutches all week.

And so we got a lot of good stuff for you today, and thanks for sticking around till the end, and I hope we're going to, hope to make it worth your while. So let's get started. So this is the last stage on the Java world tour. Today's session is about polishing your application, and sort of putting on those little, last little final touches. You know, we've gave you the good overview yesterday morning, and we had a session yesterday about you know, the basics of bringing an application to Mac OS X built in Java.

And today's session has really got two parts in it. We're going to sort of continue on the theme of what we did in the bring your application session yesterday, so sort of taking those final steps. And then we're going to continue on and talk about what's new in Leopard, and talk some of the new things that you can take advantage to put in your applications on Mac OS X.

So, so far what have we done? So you built an app, learned how to build an application, you know how to modify the Info.plist to you know, do the basic things you need to be an application. And we've also set properties via the Java dictionary for things like the screen menu bar.

So today we're going to add a few more features to that application so you can get a great Mac OS X application in Java. And we're not going to break "write once test run anywhere, run everywhere." I still cannot say that. I've been practicing this for four weeks, and I still cannot say that phrase correctly. Write once, run anywhere. Thank you.

( applause )

All right. So here's what we're going to learn today. Today we're going to talk about handling a few more of those basic Apple events, and you know, beyond the quit event that you learned about yesterday.

We got some what we call best practices. There are a lot of things that we see come up time and time again on Java Dev, and that come into DTS. And we're going to talk about a few of those today, and what we think are the best ways to handle them on the Mac. They're also actually probably going to be valid on other platforms as well, but they tend to crop up more on the Mac for whatever reason.

We're going to look at some of the new Aqua look and feel features that we've added in Leopard, and show you how you can take advantage of those. And we're going to talk about using Java with other toolkits, that's sort of the really advanced part of the session. We'll talk about how Java fits in with some of the other native libraries on the Mac, I'm sorry, the native user interface libraries on the Mac, and some other Java toolkits as well.

So to get the most out of this session, at least the first part of it anyway, you should be comfortable building a Java application in any IDE, doesn't matter. I'm going to use Xcode today, but for what we're going to talk about it doesn't really matter. You need to know what the Info.plist file is and why you need to modify it, or why you would want to modify it.

And last of all, be sure that you're comfortable getting and setting system properties. Now for a lot of what I'm going to do, that's really not important. But up to this point you know, if you got that part, if you are clear on that part, the rest of this should be pretty easy.

And finally can you make one of these? If you can do that, you're set. I mean you know, with a title like Advanced Java, I imagine a lot of people are well beyond this stage. But how many people out here are new to the Mac this year, this is the first time they've come? Okay, great.

All right, let's first talk about some of the core application events that your application can receive. All of them tell your application to do something, and they're usually triggered by the Finder, or some other process on the Mac. They're not anything that you know, come from within your application, they come from some action outside your application. You know, quit, you know, the obvious one is you know, how to quit gracefully, which you learned about yesterday.

The other ones you'll get are you'll be told when your application has started, you'll be told that when to reopen the application. And what that means is when the, your application is in the dock, and the user is doing something else in the system, and they want to come back to your application, they click on your application in the dock. That's called reopening the application. And you get an event for that. Now what you want to do with that depends on your application. If you're document based, typically you want to open a new untitled window for example.

And the other two are printing a document and opening a document. Those are the two we're going to focus on today. The last two, okay, before we do that. These are the corresponding interfaces that go along with those events. And the first three, quit, open, and reopen, are pretty straightforward. I mean you'll just get, if you register for them you get them, and you either handle them or you don't. But the last two, handlePrintFile and handleOpenFile, actually need a little bit more than just registering for the event and handling it.

So when you go about, when you want to open a handle, handle opening files in your application, first of all you know, what happens, what does that mean? What does opening a document entail? When are you going to have to do that? Well, if the user double clicks on a document that's been associated with your application, that's the most obvious case. If they drag a document onto your open application icon you'll get an open file event.

And finally, if the user right clicks and, in the Finder, I'm sorry, control clicks or gets a context menu on a file icon, if your file can handle that file, it will show up in the list of applications that can open that file. And if the user chooses that, then you'll be sent an open file event.

So to handle opening events, well yes, you got to register for the event with the application, you learned how to do that yesterday so I'm not going to go into too much detail. But the other thing you have to do is you have to tell LaunchServices what kind of files you can handle.

And you know, registering for documents is sort of the you know, sort of the global theme here. But you know, we're really talking about working with LaunchServices. And what you do in your application bundle you have to tell LaunchServices about your document types. It's a pretty straightforward thing to do, and basically you're going to add a new entry to your Info.plist, fill in all the data, and here's a, sort of a quick example of how, show you the tool that we're going to use here in just a minute to do this, but this is a property list editor.

And here you can see a list of document types that have already been registered. We're going to add a new one and fill in these three particular pieces of data. And finally, check your work. And I'll show you what I mean by that here in the demonstration. All right, so let's go over to the demo machine here.

This is not painful, for those of you who are worried about me.

( laughter )

I'm used to this by now. All right, so the first thing I want to show you here, oops, is we have the OS X adapter sample code that you've been working with all along, and I've already built it. Made a slight modification to it, you're going to see why in a minute.

But here I've got a jpeg file, and I want my application to open jpegs. So let's try dragging this over, and we can see that nope, nothing's going to happen here. You know, the Finder just you know, treats this as we're trying to put this file in the folder. All right. So let's take a look at the Info.plist file.

And here you see, well we've got a few already. We've got the CFBundle document types, and we see that gif files are registered, and bmps, and tiff and ping. And well, you know, there's your answer, we haven't registered for jpeg files. So I could do this right here in an Xcode, but that's not something you really want to do.

If you mess up the XML in some subtle way, you know, you're basically hosed. And it's going to be really very hard to tell what you did wrong. So the best way to do that is in Xcode to do a control click on the file and say open with Finder, and the default application for property list is property list editor.

Let's open up the property list here, and we'll look at our CFBundle document types. And here we've got an array of dictionaries. Okay, that's what the CFBundle document types are, it's an array of dictionaries. So it's got all the information about each type of file that we can handle. And here's the simple one for the png, we'll expand all the, so here we have the extensions, the type name, and I'll explain what that is in a moment, and the type role. So let's go ahead and add a new one.

And I click on the document types, I'm going to add a new child. And the first thing I got to do is, it by default assumes a string, so we're going to turn this into a dictionary, and we'll expand that. And we'll do a new child. And let's go ahead and start, basically we're going to add the same things that we added over here for a png, but this time we're going to do it for jpegs. So the first thing is CFBundleTypeExtensions, and we have to turn that into an array.

And we'll add a new child, and the first one is jpg. And you'll notice as I'm typing these, I'm being very careful to hit return after I add the, or set the value for a given line. One of the quirks of property list editor is that if you just click and go somewhere else, you'll end up editing a completely different line than you thought you were editing. And I've done this so many times that I think it's worth mentioning to you guys, so.

So we'll close that up. And what I've done here is I've said that jpg and jpeg are the extensions for this particular type. That's enough for now. There's other possibilities, but. And we'll go back here and add these last two descriptors, CFBundleTypeName, and the type then, the name descriptor, if your document has a, sort of a custom type, and the user views a list of folders in the Finder, it will use the CFBundleTypeName for the kind part, for the kind column in that list of files. So you know, if you have some special type, or you have multiple document types for your application, this is the kind that gets associated with the extension. So here we'll just say jpeg files, and last of all is CFBundle type role.

And there are multiple value, there, I believe at least three types of values, there are now more in Leopard. But the two that you're going to care more, most about for your typical work are viewer and editor. And in this case I'm going to use viewer because the OS X adapter does nothing to edit jpeg files, it's just we're going to open it and view it. So there you go, that's all the data we need. So I'll save that, and we will rebuild. And now we see that, aha, oh what happened there? What did I do wrong?

And there we go. Bring that back up here, now the Finder thinks that oh yes, this file, this application can handle jpeg files. And if I drop it, sure enough, there we get our nice little landscape here. Now you're going to say well wait a minute, what about that handle open file part? Well that part's already in the code, so if you look at the OS X adapter sample code, you'll see how we implemented the handle open file.

We get the full path to the file that was dropped on us from the application event, and in this example we open up an image viewer. So that's pretty much it, that's pretty, that's how you go about adding a new document type to your application. All right, so let's head back to the slides here.

Okay. So another thing you want to look at for your application is the file manager. And this is part of the EAWT, this is, also goes with the application events we've been talking about all along. The different package, it's an EIO, com.apple.eio. And it is a Java API to a number of common file and bundle related operations. Now if you learn, you know what a bundle is by now, just a hierarchy of folders.

And you know, there's the package and the name of the class that we're going to look at. There's actually some other interesting things in there that you might want to take advantage of, but we're going to focus today on resources, and specifically resources in your application's bundle. And the main use of file manager will help you find localized resources.

And this is all based on the user's language selection. And when I mean the language selection, we go to the international menu, and we look at the language list. And here what, users can pick a ordering of languages that they prefer when they, when running an application. So the best example I always think of this is a Swiss user for example, who understands French and German, and maybe Italian as well. So the first thing you, a French Swiss user would say is oh I understand French best, so I'll put French at the top of the list. But I'm comfortable with German too, so if German's there I'll put that second, I'd rather have French first, and Italian third.

So if you use the file manager API, your application from Java can just deal with the situation without any problems. So these are the two calls. We have a get resource that just takes a resourceName, and by resourceName we basically mean a file name here. We're going to go find the file named resourceName inside your bundle. And we've got a variant that will look in a subdirectory of the resources directory.

But what's interesting about this you know, what this does, if you look at the contents and resources directory of your bundle, you can specify a number of localizations, you know, do all the localizations for your strings, and your other resources. These calls will find the right resource based on the current, on the user's current language selection. And if it can't find it in the primary, it'll find it in the secondary, and if it can't find it there it'll go find it in the third.

Now you know, if you're comfortable with Java and you've done localization in Java before, you're saying to yourself okay, well this is silly. Why should I use this if Java already has localization built into it? You know, I stick all my resources into my Jar file, and in the right directory, and the resource bundle goes off and finds it. Well there's a slight problem with this on the Mac.

Java's only got one fallback language, and typically what happens is you provide a default set, which is English, and the user's main language, we pick that up. And they find your resources for that language, but if they don't find it for the particular language that they ask for, they're going to get English, and not their second choice.

And generally this just leads to a bad user experience. And if you use the Mac OS ones, you're going to get the experience that they expect with all their other non-Java applications, so that they're going to get the right language, we're going to get the right language for the string that they've asked for.

And remember you write once, run anywhere. You know, I ran a little pseudocode that says if you're on a Mac, we'll call FileManager.getResource, otherwise we'll go to the resource bundle that we've already got, and we'll get a string from it. Now one thing I didn't write on this slide, but it actually came up this week and I wanted to call it out, is that there's nothing about getResource that says this has to be a text file of strings.

All getResource does is return you a path to someplace inside your bundle for some file. And if that some you know, some sort of like a command line tool that you bundle inside your application, you can stick that in the non-localized part of your resources, just in contents resources, and call getResource.

We'll go find it for you, and then you can run runtime.exec on it, for example. This is a, it's a handy way to stuff things inside your application and not worry about you know, well how am I going to find it, because I don't have you know, I don't know what path, where my, what current directory we're in or anything like that. If you bundle it all up and use get resource, you'll be able to find it that way, much in the same way as you would a string, so. Just wanted to call that out, cause that's actually turned into an interesting little problem these days.

And last thing is, this is a non-issue on Java 6. We gave feedback to Sun actually in the Java 4 or 5 timeframe that you know, this happens quite frequently. That you'll end up with a situation where the menu bar is in one language, and the user's application is in another.

And we told Sun you know, you know, this is a problem, okay, because you don't have a way to look up other languages other than the one that the user's currently on. So in Java 6 what we will do is report back that the user's current language preference is to Java. And then Java will look it up you know, like we want it to on a Mac.

And so you know, that's a, that's the way that we're trying to make Java better for everybody. But now after I said that, that's not working yet in the developer preview that we released today. But we do know about it, and we'll get, we'll keep working on it. But it's an assumption you can make when you start working with Java 6.

So okay, I put in that little on a Mac in brackets. And this sort of gets back to what Ben covered yesterday, but I want to reinforce it here. You want to know which VM is running your code. There are times when you need to know what platform you're on.

And you know, I'll click through these. You know, these are sort of the tried and true ways. You ask what os.name is, you ask what Java.version is, and then you can figure out oh okay, I know I'm on a Mac, I know I'm on Windows, or I know this bug was fixed because I'm running this version of the JDK. On the Mac that's not enough. What you're also going to want to do is look at java.runtime.version, and let's talk a little bit about why that is.

Usually you know, you know, if you're a Windows developer you're saying duh right now because, right, this is how you do it, we know how to do this. Well you can't assume on the Mac that java.version is unique from release to release. There's a couple of reasons for this. We could have only just fixed bugs, you know. We had to do a rapid turnaround and fix a few bugs, and we did that before Sun could update their JDK, so we just updated ours. So therefore java.version hasn't changed.

We will always append the build information at the end of java.runtime.version. And for any given version of Java, 1.4.2, 1.5.0, that number's always going to increase. So to sort of explain what I'm saying here, I did a little example where we did Java -version on the command line, and this was taken from Tiger.

But if you look at Java., the first part here, we see, I'm pointing down here which you can't see. And up here we see the 1.5.0_07, that's java.version. java.runtime.version is out there after build. And if you parse off that, the piece after the dash, that'll give you the build number that goes along with the version.

And with that you can make, draw some conclusions about what was fixed, what was not fixed. This is true on Sun's JVM as well on Windows, and Solaris and elsewhere. However, typically when they, whenever they release they always bump up the bug fix version, the _07 part. So that's generally not a problem elsewhere. But on the Mac you're going to need to know how to do this, because we've done it before, I can't guarantee we won't do it again, we probably will do it again. So that's something to keep in mind.

And finally, we strongly recommend that you use reflection to find all of these classes that we've been talking about that are Mac only. We do this in the OS X adapter example, and that actually does a really good job, and it's a really good job of using reflection in general, so you might want to take a look at that. But that'll give you some idea of how you would go about finding some of these classes at runtime, so you don't have to worry about stubs or anything like that.

Okay. Now let's talk a little about using runtime.exec. Because this is actually something that comes up not so much any more, but it tends to happen more on a Mac because, well you'll see why here in just a minute. First of all, runtime.exec does not use any shell, doesn't use your current user shell, doesn't use a default shell, or anything like that. It will attempt to exec what you pass to it.

The default case of runtime.exec, which takes just a big command, is very naive in how it operates. It's just going to break it up according to whatever space it, wherever it finds a space in the command, and will just try to execute it. So here's an example, and this happens more on the Mac because I think users tend to put spaces in their file names more often. If we're going to open this file, 2005 annual report.rtf. So here's the first try, you know, we'll do, we'll just try to open that line cause you know, open in terminal's how you go about opening a file from the command line.

Well you end up with a string array that looks like this, you know, with all the pieces, parts divided up. So you think to yourself oh yeah right, that's right, my file has spaces in it so I need to you know, put quotes around it. So you try it again and you try to backslash and put quotes in there. And well gee, that's no better. Because that's what it looks like to runtime.exec, it just looks like a file with quotes in the name, in the pieces, in the parts.

The way to do this is the string array version of runtime.exec, in fact I would go so far to say you should do this on all platforms, but it works, it's more obvious on the Mac. But just make an array with all the arguments that you want to pass called runtime.exec, there you go. That's going to work every time.

All right. So that's sort of finishing up the sort of your introduction to building applications on the Mac. The rest of today's talk is about getting ready for the new features in Leopard, and using the Leopard preview that you got this week. And we're going to start off with Mike Swingler, who's going to cover the new Swing features that we have. And, Mike? Why don't you take it from here for a while.

( applause )

Thanks Scott. Well today I'm here to tell you about some of the new features and controls, and some exciting stuff that we've added for Java on Leopard. Well first of all who we're talking to today, these are for Swing developers, so you know, we clipped our CP guys or you know, service side folks, you can take a little nap for a while.

And we're specifically targeting the Swing developers who want to go the extra mile on the Mac. But since you're choosing Java in the first place, we know that you want to remain compatible and portable, and you know, that if on a Mac should be kind of reduced to the bare minimum necessity. And so we're looking to help you out here, and write once run anywhere should look really good too.

So this is our agenda for my little segment here. And you know, we're going to talk about why we're using client properties in Swing, we'll show you some kind of new and exciting small and mini controls that have never been in Java before. We've got new JButton styles, a bunch of fun stuff you can do to your window frames, talk a little bit about borders, and finally wrap up with resolution-independent images, as you might have heard in Guy Fullerton's talk in The Presidio.

So why are we using client properties? Client properties are this really cool thing that Sun put on the root JComponent object, that allows you to assign just kind of arbitrary key value pairs. You know, the key is a string, and you can put whatever you want as the object on the other end. And well, by default they don't do anything, they're basically like little hints. And they're inert on other platforms, and we thought this would be a really great place to put some stuff for the Mac.

So the first client property I'd like to talk about is JComponent.sizeVariant. And so these are just the regular size controls that you know and love and use today, and you know, they're nice. But today we're introducing small and mini size variant controls as well. You know, small is good for when you're wanting to group together a bunch of buttons, kind of in a, in sort of a logic grouping.

If you got a lot of you know, fields of checkboxes, you know, they're really good for just kind of visual containment. Mini controls really are only appropriate in very, very limited circumstances. You don't want to put them on your main application windows, cause they're really small and they're kind of hard to peck at.

Mini controls are particularly good for palettes, and we'll see a little bit more about that later. Other, let's see, buttonTypes, okay. So these are some kind of buttonTypes that we've had in Mac OS X for a while, the default, the bevel, and the square. You've probably noticed if you shrink a button down, it kind of turns into a square style, if you pull a button kind of big it turns into a bevel style. And you really didn't have a lot of control over that. Well today if you put a bevel as the string in the JButton.buttonType client property, you will always get a bevel button, and it will stay like that.

Some other additional styles that we're adding today are the textured variant, the recessed style, like you see in a Safari bookmarks bar, the roundRect, which is actually pretty, which is used for when you have a field of buttons inside some sort of scrolling view, some sort of grid view. You'll notice this in iTunes, kind of the buy it now button.

Gradient style buttons, which you normally notice at the bottom of source lists, they have you know, a little plus, a little minus, and a little gear, stuff like that. And also help. Please don't set any text or imagery on this style though, because it already has a question mark there for you.

Some additional buttonTypes are segmented. And so if you've ever seen the view switcher in the Finder, going between you know, icon list and column, and now cover flow view, you can build those two in your Java apps. You actually build them out of separate JButtons. So you just assign the first end cap, the last end cap, any middle ones. If your buttons are all on their own there's the only style as well. And we also have round rect style, the textured, which you know, should go on your textured windows when you're trying to simulate the unified toolbar look.

And, I'm sorry, segmented capsule go on toolbars when you're doing a unified toolbar look. Textured is for when you're down below lower in the window. And you know, just look to iTunes as an example of that. And they just squeeze and fit together. And when you put them inside of a box layout or any other layout manager that will assume, that will abut them all together.

Next I'd like to talk about JComboBoxes. And this is the JComboBox that we all know and love. It's, on the Mac we actually have a special name for this, this is called a popup. And popups are kind of good when you just have an ordinary sort of selection of choices, and you select a variety of items, you know, chicken, beef, or fish, you know. No real action associated with that. Well we also have another style called popdowns. And if, when you set the isPopdown style to a Boolean true, you can actually have the style which simulates more of an action button sort of idea.

Popdowns, the popup menu always shows down below the menu, the popup, the little window that pops up with your choices will only show above the control. So popdowns are only, should only be used in cases where you have actions that you're actually going to select, and something is in fact going to happen, you know. When you simply choose a normal choice in a popup there's no action that's supposed to take place. And you'll have to install your own selection, not, selection manager on that to get the right behavior so the title stays the same, even when your selection changes.

We also have the square style as well, because they kind of look cool. And you might have seen them before in Mail, in the compose window if you've got a variety of views, a variety of accounts that you want to switch between when you send a message. So, and I don't think we have any guidance for that except for use them when they look cool. Next the search field is another control that we've enhanced. And there hasn't really been anything all that terribly interesting about text fields. You know, you kind of stretch them and they become big and they become small. But today we're going to give you search.

The search field -

( applause )

Thank you. The search field, you'll get a ton of behavior automatically. The little x will show up as you type in text in the field, as you delete text, or you know, you drag and drop operations out of it, it'll go away by itself.

The icon with the magnifying glass, you get a little triangle that shows that there's a popdown if you install a popup, a Jpopup menu as another client property in addition to the search variant in the textfield.variant class, client property rather. The preferred way that you would use this would be to attach a document listener to the document of the text field itself, because if you try and install your own key listeners, and your own mouse listeners, and your drag event listeners, you're bound to miss something in trying to you know, have complete control of it.

Adding, actually just listening to the abstract document is probably the most common way that you can get a nice good crisp feel of live search, and then still be able to handle all the input methods, and mouse and drag operations that could possibly happen on the search field.

So now let's move on to windows. This is just a plain old document window you'd bring up in Java. But something that we're adding that we're really excited about is if you install a file object that actually backs the window that is in fact a document window, you get a little icon up at the top.

And if you click on that icon while holding down the command key, you actually get a popup, which well, document modified also shows a dirty bit on there. But you get a popup that shows where the file really does live and exist on disk. And if you drag the icon, it'll actually drag it just like you're dragging it from the top of text edit or Xcode, or any other good Cocoa application.

And so another thing that you can change on windows are the styles. So you have a palette style window here. Well the window style should actually reflect that. So if you just say that the window style is small, you actually get palette style window. Other JFrame decorations you can use, you can use the brush metal look and feel.

This looks particularly well, gives you that nice kind of unified appearance between your title bar and your toolbar, especially when your content area takes up the full width of your window. The draggable window background is kind of a property set sort of to match the expectation that when you grab the background of the window it really does move.

Might want to experiment with that. And you can also change the opacity of the window, it's sort of fun to play around with, but I haven't really found many particularly interesting examples except maybe in kind of full screen applications. Oh, and very important. JFrames themselves are not JComponents. However, if you get their root panes you do get the Jcomponent, which then you can set the client property on. Kind of a little where did it go sort of problem.

So another feature that we've added, not necessarily client property, but something that we've installed in the Aqua look and feel UI manager for you are the title border, title borders that actually match the Mac OS X style. By default, when you create a new border using just new title border, or using the border factory, you're going to get something that just has this sort of etched line around it. And it's not great, and I wish I could change it, but we can't.

Because in order to use the Mac OS X style that has kind of a deep inset sort of recessed turns the background a lot darker, you have to really change the assumption of the opacity of several of your components. You have to set opaque false on a number of components that go inside that.

And if we did that automatically for you by default, performance would drop in a hole, and for some very kind of common cases, and you'd file bugs and yell at me, and that would be bad.

( laughter )

So we're still going to keep performance up, but we'd like you to use this border style. This is something that you see already on JTabbed panes, to no cause of trouble of its own.

And the, if you just snarf the Aqua variant of the title border, and use that for your own title borders, you can provide that as a parameter yourself. Or even better, if you just put it as the official title border border in the UI manager, just replaces them everywhere in your application.

Works really great. And finally, switching gears again, resolution-independent images are something that we will allow you to access in Java. By default Java has absolutely no concept of what resolution independence is. Fundamentally everything is points, and points is pixels, and pixels is points. And there's no way you can really know the better, cause we can't change the API to expose this to you. So for now, the best thing that we can do is just say that everything in Java coordinates is relative in points, and there's no real need for you to know kind of the underlying details, except in this one little case of images.

So we're doing something here today, so if your application is bundled in you know, Mac OS X bundle format, and you have a resources directory, you can toss your images in there, particularly PDF and ICNS are interesting types, multi res tiffs also work as well. And you throw them into your application, but you can ask for them by name in the same way that you could ask the NSImage API for a named image.

This will also fetch out system images that we have artwork for on the system, like the network icon logo, and the variety of things that Guy talked about in the icons.h file that's on the system. And this will load just about anything NSImage will load from the image named API. You just prepend this NSImage:// on the beginning of whatever the name of the image is.

Normally this API is used to fetch files, but we kind of figured that since no files are likely to have that prefix in them because of the well, double slashes, we thought this was a pretty good kind of way to kind of bend the rules a little bit.

And so what's the catch of all these things? Well let's see, client properties, they kind of work everywhere. They don't, they work in bundled applications, any sort of WebStart or applet context, everything, nothing is, it's all fair game. They work on all the, they don't do anything on any other platforms, they are simply no ops.

So the very specific catches we have is that NSImage will only work with a bundled application, cause you can't fetch anything out of a bundle if you're not, if you're just a double clickable jar, you've got no bundle. You might be able to fetch stuff from the system, maybe. And unprivileged applets in WebStart should not be putting files, trying to claim that they're windows actually are represented or backed by some sort of file on the file system, because that would be a lie.

And so where you find all these magic goodie strings? Well we put them in the release notes for DP6. The, however Java 5, all of these client properties will work on Java 5, they're documented in the release notes, with the only exception of the sheets client property, which is not something that was on the Leopard CD. That's why we didn't make a big hubbub about it today.

So in summary you know, we talked about how we're using client properties, saw some of the nice controls that we're adding with the small and mini variants. The release notes will tell you precisely which controls all have the mini variants. The new button styles, including all the segmented controls, also have small and mini variants as well for almost all of them.

Ones that don't should look exactly the same as the small variant, JFrame, the JFrame styles, and kind of when it's appropriate to use them on palettes, and we covered some borders and resolution-independent images. So I'm going to turn it back to Scott for toolkit integration.

( applause )

Okay. So, toolkit integration, what does that mean?

Well, after a while we sort of think that there are other ways that you're going to want to use Java. Now we are sort of hoping that after you've been to WWDC this year, you know, you're going to take a look at some of the technologies we presented and think wow, some of that's, stuff is really cool, how can I use that? But you know, we'll get to that in just a minute.

So basically what we're going to talk about is how you go about using Java in other toolkits. This comes up on a regular basis, and we've had some good stories, some not so great stories. But with Leopard we really got, we've really got answers for just about anybody who wants to do this.

So there are three main toolkits we have in mind here. First there's Cocoa, you have the SWT, which is the user interface toolkit from the Eclipse project, and finally Carbon. So what's the answer on Cocoa? Use JNI, all right? We said it yesterday, I'll say it again today, don't use Cocoa Java. It's deprecated, and as you're going to see in a moment, it's partially gone.

Tech note 2147, right? If you're using JNI, please read and understand this document. It's got a lot of great examples about what to do on the right thread. And I can sum it up basically as don't call Java from the AppKit thread, don't call AppKit, don't make AppKit calls from a Java event thread, Java event handler. That's the, in a nutshell, that's what's going on. But tech note 2147 will give y!Gou a lot more information.

Watch your threads, that's another way of saying it. Cocoa Java does not exist in a 64-bit runtime.d It is not available in Java 1.5 on Leopard. I'm sorry, it's, well it, actually it doesn't pay attention to the version so, but it's not available in the 64-bit runtime adt all. So in particular I'm talking about the implementations you see in these two files, NSJavaVirtualMachine and NSJavaConfiguration.

So, let's say you know, you've been watching these sessions this week, and you think core animation rocks, core data rocks, okay? I'd love to use that in an application. But you know, I've got a lot of non-UI code, you know, I've got my existing Java code. It's not a big deal to call that code from a Cocoa application with JNI, that's really not that bad.

UI code is a lot harder. I mean tech note 2147, that'll get you most of the way there. But the main focus there is creating new windows. And admittedly, that's not hard either. Once you get a new window open, there's not much that you have to worry about.

So what about your old UI code? Say you bought some Swing library, some Swing package, or you've written a really cool control that you need, or you know, you've got some code that you just can't give up. Well we've got an answer for you in Leopard. It's called the JavaFrameEmbedding.framework.

And what is that? Well it does a couple of things for you. The JavaFrameEmbedding takes care of starting up the Java VM for you in the right way. So by that I mean we start it on another thread, you know, we do all the right things so that it will come up correctly and the AWT will work in your application.

We're going to hand you a java.awt.Frame, and basically what you're going to end up with is an NSView in your window that will represent a Java frame. We've got a delegate and notification callback mechanism. I'm going to show you how you go about using those, but basically the purpose of that is to provide you a safe way to manipulate the frame, and a safe way to set up your Cocoa user interface to use, to work with the Java.

We're going to make sure, and the reason for that is we're going to make sure that all the operations happen on the right thread. This works with Interface Builder, and I'm going to show you a little example that shows you how you can drag out a view, and set it up to use, to say this chunk of the window is for Java, and we can set it up in Interface Builder.

And to show you that, let's go over to the demo machine, and I'll show you my little sample application I've written. Now if you've downloaded this from the server, we're out of sync with what I've got here today. We're going to take care of that as soon as we can, but the code that you have is actually correct. So if you build it and it doesn't run, or it doesn't build, don't worry about that, the code is right. So let's look here.

And the first thing I'm going to do is I've got the, what I call the interesting source files. I mean we've got a, everything over here on the left, but I'm going to hide that for you. Actually very briefly, all you have to do is add this framework to your project, that's all you're going to need to do, and it's got all the headers in there. You know, take a look at those when you get a chance. But I've got the interesting files in my popup here. And along the way I'm also going to give a little bit of information about using JNI as well in your application.

Because we've got different versions at any given time, there's no way for you to control via JNI which version of Java's going to load. You know, by default it's going to use the default JVM, which is 1.5. But if you wanted to use 1.4 or 1.6, there's no way you can really control that.

So if you set this environment variable, Java JVM version to the version that you want, the first JNI operation will use that Java VM. And this is how you go about selecting it. And the reason it's here in the main is that I want to do this before NSApplication starts up, because as we're going to see in a minute, my Java frame view is going to start up Java for me.

All right. So let's see here. Let's go over here to Interface Builder, and going to take a look at the nib for this application. So as you can see, I've created an instance of this application delegate class, and let's open up our window here. And we see that inside here I've got a custom view, and it's class is Java frame view, which goes with the Java frame view in the framework that we've added.

And if we control click on it, we see that we've already set up the delegate relationship. I've already done that here in Interface Builder. And when I mouse over it, the matching one highlights over here in the window for the nib, so you can see how that's set up.

And we've got a few other buttons. They're currently disabled right now, and the reason that is is that when this application comes up, you won't be able to interact with that window. And I'm going to show you how we'll, when to turn those on. And we got a little table view here, and we got some sample data that I'm going to show you. And so that's sort of the nib right now, for right now. So you're going to create a custom NSView, and give it a class of Java frame view.

Let's close up that. And now let's go back over here. Okay, let's go look at that delegate class. And thanks to the power of code folding, I am going to limit our discussion here to what you actually need to care about for this application. So in the wake from nib, what I've done here is I've built up as an NSString my class path.

This project is going to use a jar that we're building, and I'm going to use the SwingX project and its support class. And then I've added all that to a java.class.path argument. And then I use Java frame to use set Java startup options to pass those arguments into the VM. So this is how you go about setting a custom class path with this package.

And the other thing I have to do, remember I said we have a delegate and a notification mechanism. Well we already set up the delegate, as I showed you Interface Builder. But the next thing I have to do is register as a listener with NS notification center for this message right here, JavaFrameDid, JavaFrameViewDidCreateJavaFrame.

So the first thing I want to do is I want to go up here and, first I'm going to show you the delegate method, because that's the first thing that gets called. Now in this method you're going to be passed a, the Java frame that you can manipulate, and you're going to get a JNI environment to work with as well. Don't cache this JNI environment. You don't know what thread it came from, and when you don't know what thread it came from, you don't know if it's ever going to be valid again.

So in this case, what I do is I find the classes that I need that's going to go into that Java frame, I call my setup method, which in this case is just a static method that manipulates the contents of the frame, and I check for JNI exceptions and make sure that we're okay before we hand over control back to the framework. Do not do anything related to AppKit in this method, because you're not on the AppKit thread.

Okay. Now once that's all set up, then you're going to get the notification. That's going to come on the AppKit thread. And in this case, we're going to turn on all those buttons, and we're going to enable them. And then we're going to say that the Java frame is now ready to go.

So at this point I'm going to run the application so you can see what's going on. And, all right. So here we have, all right. So what I've done here is I've grabbed a little bit of geocaching data, I, well, I hope to do some more in the future, but this is from geocaching.com.

And you are looking at Greenwich in London, as you can tell by the almost zero longitudes there. And what I have here is the JX map viewer from the SwingX project, which is a great open source project that Josh Marinacci introduced last year at JavaOne. And I'm using it here to embed their map viewer inside my window.

And this data's coming from open street map, which is the other reason it's from London, it's because there's a lot of good data there. But anyway, if I click on something in my table view, I jump to that location in the map. And of course I can drag this around, because it's you know, it's a map viewer. And I can change the zoom level, you know, with that slider, come back out like this, go back in. And with these check boxes I can also hide and show these controls. And sometimes we'll crash, so. All right.

But, be that as it may. So the next thing I want to show you is what happens when, what are you supposed to do when the user clicks on one of those AppKit elements? So let's specifically talk about the table selection changing. So here what we do is we make sure that it's okay to talk to the Java view. Then again we use JNI to find this method, set new center point. And we get the selected longitude, latitude and longitude, and then we call this method, setNewCenterPoint. All right? So now let's go see what setNewCenterPoint is doing.

Well right there we create a new geo position, and we move the map to that location. But very importantly, I wrap this up in a SwingUtilities.invokeLater. That's because I know this method was called from the AppKit thread. So if you're doing something in response to the user interface in AppKit, you always want to wrap it in an invokeLater, or a SwingUtilities.invokeLater that will guarantee that the AWT operations happen on the AWT event thread. So that's sort of a quick overview. I hope you're going to take advantage of this. And please give us any feedback. So with that, let's go back to slides and finish up.

Okay. All right, let's move on to talk about the SWT a little bit. The SWT, for those of you who don't know, it comes from the Eclipse project. And as I mentioned, it's their user interface toolkit. It's the thin interface over all UI toolkits, and on the Mac that's Carbon.

We first released support for embedding, this has allowed you to embed a AWT frame inside an SWT frame, we did that last year at JavaOne. We fixed that up a little bit more in Java 5 update four for Tiger earlier this year. Now we think we've got pretty good integration between the two You know, it's, we're pretty comfortable with how it works.

So we're going to continue to support the SWT, we really believe that Eclipse is an important part of Java development on the Mac, and we really like the things that they're doing. You know, we work very closely with the SWT team in particular, but you know, the whole Eclipse community, we're more than happy to have them on the Mac.

We've, in Leopard we've made a number of bug fixes to the embedding support, specifically on, there have been a number of bugs related to focus. We fixed a long standing problem with shutting down an application that uses the SWT and the AWT together. And just in general, the overall stability is much better than it's been, than what we have on Tiger right now. New in Leopard, we've added the ability to deploy via WebStart. This is like a two year old feature, and we actually had a few little breakthroughs in the past couple of months, and we're now able to announce that we can, you can deploy via WebStart on Leopard.

So, if you're going to use the SWT in your application, how do you go about doing it? Well, there are a few things that are different between the SWT and the AWT. The SWT wants to control the entire application, wants to be like a Carbon application. And because of that, it wants to start the Java VM on the first thread so that the SWT will run properly. Well, you can do that in just about any technology we've got. So if you're on a command line, which is what Eclipse is going to do, do Java -XstartOnFirstThread.

In a WebStart application you need to pass that in Java VM args, that same -XstartOnFirstThread. We'll figure out the right things to do and start up the application appropriately. And if you're bundling an application, we support that as well, and the Java dictionary. You just want to set the property StartOnMainThread. And this is not a property in the Java property sense, but it's just a key that you're going to put in the Java dictionary. So StartOnMainThread and evaluate with true.

So that's pretty much it for what we've done with SWT and Leopard. You know, it, because the SWT is based on Carbon, when you do find problems, please file a bug with us so we can get it to the Carbon team. And if you find a problem, you know, file it in both places. The Eclipse has their own Bugzilla, so I'm sure the SWT wants, team wants to know about it, but we need to know about it too, cause at this point it's likely that it's a problem that we may have caused in this beta.

And last of all is Carbon. For Carbon developers, they haven't felt a lot of love when it comes to Java over the years. You know, the SWT is based on Carbon, and we've been able to glean a lot of knowledge from that work that we've done over the years.

And if you're a Carbon developer and you wanted to use Java, we basically said sorry, you're out of luck, you can't do it. Well now we've been able to take that, advantage of that work, and put that to your benefit. And now Carbon apps can now use the AWT. I don't know if this is something you need to do.

You know, Carbon is only available in 32-bit now in Leopard, but we've now got the ability for a Carbon application to start up the AWT and have it just work. And again, follow tech note 2147. G Same rules apply there for Carbon applications as it does on Leopard, as it does with Cocoa applications.

And that's really all I need to say about Carbon for this year. So in summary, let's finish up, and talk about what we covered again today. We want you to make a great OS X application, not just a Java app that comes over to the Mac. And we hope we've given you, between yesterday's session and the first part of today's session we've given you all the tools and all the information you need to do that.

You want to think cross-platform when you're adding this kind of functionality. So we've sort of given you some guidelines about how to do that, and we want you to think about reflection, and take, and read up on that for the right, the best way to do that on the Mac.

Use the appropriate Swing controls now. We've given you a lot of great new features you can use to use the right control at the right time, and you want to take a look at the release notes to find out when to do that. And finally, there's the right way and a wrong way to integrate Java with your native code. And if you read tech note 2147 you'll learn the right way. And we've given you a lot of new options this year in Leopard, and we hope you'll be able to take advantage of some of those in your application.

So for more information talk to Matt, or I don't think, we didn't put it on here, but Java Dev is also a good place for these kinds of discussions. There's a lot of great people that know how to answer these kinds of questions when the Java team can't get there to do it first. And please be sure to check out the sample code, we'll make sure that this example is ready to go when you need it.