Java • 53:15
Ensure your product's success in the Macintosh market by taking advantage of Mac OS X interface enhancements. Learn how using MRJAppBuilder, Sheets, and anti-aliased fonts can help you deliver a full Macintosh user experience. JNI and JDirect are also covered.
Speakers: Peter Steinauer, Eric Albert
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. My name is Pete Steinauer. I'm the engineering manager of the Java Platform Classes team here at Apple Computer. What I'm going to be going over today is some of the things that you need to do to take your 100% pure Java application and bring it to Mac OS X. You're going to have to excuse me. This is early for me.
What our goals are in this session is to go over some minimal changes that you need to make to your applications to be able to make it run and behave well on Mac OS X. Before we get into that, I want to make it clear that on Mac OS X, even better than Mac OS 9, you can take JARS and other applications from other platforms and just run them on Mac OS X. There's no changes that you have to make to your application to make them run.
What I'm going to be talking about today is the kinds of things that you can do to your application so that they'll mesh better with Mac OS X. And the goal with these changes is that these changes be very minor, that you don't have to do much of anything to make things run very well on Mac OS X. In designing our implementation of Java on top of Mac OS X, some of our goals for some of these tweaks were to make APIs that blend very well with Suns, so that you can do very minor things to your applications.
And have them behave much more closely to--have them match much more closely other applications that are running on Mac OS X. And with the ultimate goal being applications that feel like Mac OS X applications. So what I'm going to go over first is some of the basics, the things that you should be doing in your design already, but become more important when you're doing this kind of work.
So these--the first thing I'm going to be going over is pure Java cross-platform changes that will aid you in the steps that you're going to be doing. And then I'm going to go into some simple tweaks that you can do that require often no code changes, but sometimes very minor code changes.
And then I'm going to go into some more complex features that you can take or leave, you don't need to adopt, but will make your application run that much faster. And at the very end, I'm going to go into some of the packaging details that you need to take--you need to be aware of to deploy your application on Mac OS X.
So the basics, cross-platform changes. What I want to emphasize here is first of all that Everything that we're going to be demoing today is based on clean, 100% pure swing implementations. The reason I say swing is you can implement and Classic AWT runs perfectly fine on Mac OS X, but we've discovered over the years that when you implement in Classic AWT and you implement expecting certain behaviors on one platform, it's very hard to carry them to the other platforms. The Classic AWT doesn't work well for that kind of situation. So what we recommend is that you focus on swing applications.
They run much better on Mac OS X and you have to make far fewer changes. A huge number of the bugs that we get into Apple on the Classic AWT are, "This widget doesn't behave like Windows." It's like, "Well, no, it's a Mac OS choice or it's a Mac OS button. They're not going to behave like Windows." Swing does a much better job of making those kind of things mesh.
The other thing you need to be aware of, and a lot of this is just good design. I mean, nothing new. Nothing new here, but it becomes much more important. Things like modularity, things like keeping an eye on platform differences. You need to be aware that even if you write 100% pure Java application, there are differences in platforms and there are minor tweaks that you're going to make.
And if you design your code in a way that is modular, that you--cons things up on the fly as you need to, and factor out the sections of your code that you expect may require platform differences, it's going to be that much easier to make the minor tweaks that you need to make. To make your application run well on multiple platforms.
Native methods is another thing. The minute you start going down the native method path, you're really tying yourself into the platform. And you need to make sure that you factor out your native methods. You isolate how you do those because the behavior of native methods, how you bind those up, that kind of thing, is very different from platform to platform to platform. I mean, we've got JNI. We've got those kind of things. We also support JDIRECT, which I'll talk about in a second.
But the fact of the matter is the minute you start talking about native methods, you're binding yourself much more closely to the platform that you're running on. So isolating those is always a good thing. And then launchability. That's a totally simple thing, but will allow you--allow us to help you out in a lot of ways.
If you follow SunSpec as far as packaging things up in jars, using the jar extension mechanisms, and also making sure you do things like specifying your main method in the jar and that kind of thing, you're going to get that much closer to something that we can help you out with, that we can help you out with later. So with that, I'm going to bring Eric up to run through the beginnings of the demo that we're going to be building on throughout the course of the session. This is Eric Albert. He's one of the engineers on the Java Platform Classes team.
Okay, so what we have here, actually, is basically the way that you would end up launching a Java application on a variety of different platforms. So from the command line java-jar, you can use the dash jar flag as long as your manifest is correctly configured. And so when I hit return, then this application comes up, and this is basically how this app would look on Solaris or on Windows.
So this is using Sun's default cross-platform look and feel, which is metal. It's the default on Solaris and on Windows. And what we have here, actually, is something that lets us navigate through the file system from Java's perspective, which is from a Unix perspective. And so you can see all of our files here, and you can see if I go through and, say, take a look at my applications. Well, your users, at least on the Mac, are expecting, or will typically expect to see mail.app as, say, a regular application.
But in fact, it is actually a directory, because that's the way that applications are packaged on this system. And within there, we have a contents directory. Inside that, all kinds of different things. And the actual application binary is way on down here. So this is an application just as it would look on other systems. Nothing at all has been done here to get it to run specially on the Mac OS. And so if you just take your code and port, then this may be what you'll end up with.
But Pete was talking about modularity. And at the same time, so even though this application doesn't look like a Mac OS X app, it's been written in a way to make adding support for additional platforms and adding any platform-specific code relatively easy. So one good example of this is the way that the menu bar is designed here.
Actually, I should go back to this briefly and show that we have file and edit menus here. Of course, your users will expect those on all platforms, and almost all applications do have that. And so we've got new, open, save, and close. And you'll notice close is option F4.
Edit, cut, copy, and paste, or control X, control C, control V, etc. But if you've factored out your menu items in such a way that allows you to add in additional ones for specific platforms, then you'll end up being in really good shape when the time comes to add, say, specific accelerators for Mac OS X.
Our menu bar class actually takes advantage of Java's resource bundle class to load the appropriate resources for the platform that it's actually running on. And so it grabs those resources and then goes through and constructs menus dynamically based on what those resources happen to be. Building the keystrokes that it gets out of those resources and grabbing appropriate actions out of those resources that correspond to the given menu items that it has. So ideally what you end up doing then is saying rather than say associating specific actions with platform specific code, I'm going to write generic actions within my application that I can then use as a bottleneck for all platform code.
and David Oh, that's right. One other thing that I did want to mention is that this also works great actually for localization. So when you have something like this that lets you load specific resources, then you can trivially add specific localizations to your application and ship in multiple languages, and we'll get a chance to show that to you later.
So now back to Peter. Okay, great. So that's just the kind of setting the stage for some of the changes that we're going to be making next. So now what I want to do is, if we can get the slides back up on here, is talk about the simple tweaks that we can make to--slide, slide, slides--the simple tweaks that we can make to applications that will make them harmonize much better with Mac OS X.
The first thing that you'll need to be aware of is how to distinguish between the platforms. The two kinds of things that you're going to want to be aware of is how to distinguish between platforms and how to distinguish between specific features and versions on a platform. And the most common way and the way that we recommend for distinguishing between the platforms is using the OS.name property.
This is the way that any number of other Java applications use. On Mac OS 9 MRJ, the OS.name property will be Mac Space OS, intercapped. And on Mac OS X, because the infrastructure is fundamentally different, we've changed the OS name to be Mac OS X. As far as features, we've changed the OS name to be Mac OS X. Features, what you should be doing--and this is where it gets a little touchy and it depends very much on the platform. You should be looking on Mac OS 9--or on Mac OS in general, Mac OS X and Mac OS 9 at the MRJ version property.
We've carried the MRJ version property through from MRJ into Java on Mac OS X. And this is the best way to tell between features. Each major release that we do, we're going to bump this. And so if you're relying on specific bug fixes that we've got or specific APIs and features, the best thing to be checking for is the MRJ version property in that situation. Okay. situation.
Then the look and feel. We actually cheated in this demo, just for dramatic effect, I guess. On Mac OS X, the standard look and feel that's enabled by default is the Mac OS look and feel. So if you do nothing, if you create a simple Java application using standard swing without setting a look and feel, you're going to get the Mac OS, the Aqua look and feel.
We actually, on this demo, forced it just for dramatic effect. But if you need to, for whatever reason later in your application, force a look and feel other than the standard platform look and feel, what you need to use is the UIManagerSetLookAndFeel. And within that, you just call UIManager.GetSystemLookAndFeel class name. Or if you want the metal look and feel, call GetCrossPlatformLookAndFeel.
And that will force it. What you then need to make sure that you do is call UpdateComponentTreeUI because that will force any UI elements that you've already added to your application. So you can see that the menu bar is instantiated to be bound. The thing you need to be aware of is this is called on a frame and it will walk down a frame. So if you've done things like creating a frame, creating a menu bar, but you haven't associated them, you need to associate them before you call GetComponentTreeUI. Otherwise, the menu bar won't pick up the look and feel changes.
The next thing is menu definition. One of the coolest things that I found about the Mac look and feel that we've implemented is that it allows you to put the menu bar in the right place. Menu bars in Windows drive me insane. I just can't stand them. And so on Swing, we've allowed you to move the menu bar out of the frame into the menu bar. We didn't put this on by default for two reasons. First of all, it's part of Sense Conformance Kit that they check to make sure that behaviors are correct.
But more importantly from my perspective, you need to be aware of where the menu bar is in your application. And your application needs to take into account that the menu bar may be up there. The best example of why this is a problem is if you look at an application like the Beanbox.
The Beanbox has three frames that it operates on. The menu bar is associated with the main frame. We've run into this on MRJA in the past where the menu bar being up in the actual menu bar on the system, if you activate another frame, the menu bar goes away. That's not what you're going to see. That's not what your users are going to expect.
So you need to be aware that when frames activate, the menu bar that's associated with that frame is active. So we didn't want to force it up to the top to begin with because we got a lot of user feedback that that's just wonky and weird. And so we wanted to make sure that your application is architected for that. But assuming that it is, it's totally easy to enable this. All you need to do is call set J menu bar on your frame or on your dialog.
And you should be doing that anyway. That's just standard practice for Swing. The thing you need to be aware of is you can't have any heavyweight AWT menu bars associated with it at the time. And currently, menu bars on J dialogs don't work right now. We don't see a lot of applications. And it's kind of weird on the Macintosh to have menu bars in your dialog anyway. So I'd recommend that you don't do that. But if you do, don't expect it to go to the top. That doesn't work right now.
But once you've called set J menu bar on your frame or your dialog, all you need to do is enable the Ecom Apple Mac OS use screen menu bar. And set that to true. You can either do that programmatically in your code or you can do that as a command line switch. But it's as easy as that.
So what I'm going to do now is go into some of the simple HI things that you need to be aware of when you're working on your application to make it harmonize best with the Macintosh. One of the things that Macintosh users, and actually not just Macintosh users, any platform users come to expect is that the UI is laid out in a way that they expect. Things like menus. Menus are laid out on the Macintosh. File menu, new, open, close, save, quit.
Edit menu has things in the right place. The preferences on Mac OS X is in the right place, that kind of thing. Preferences on Mac OS 9 is in the edit menu. And that the accelerators are what you expect. And the accelerators are where I found, actually in writing this demo, very wildly from platform to platform. I don't use Windows much at all. And looking at the Windows accelerators, it was just completely wonky.
And that Mac OS doesn't have the same keyboard mnemonics. So when you're architecting your application, you need to be aware that those are the kind of things that users are going to depend on. Windows and dialog layout. This is less critical, but you still need to be aware of it. Insofar as things like dialogs. Macintosh users expect an OK in the bottom right. That's the default button that is activated when you hit return. It cancels right next to it that is clicked on when you hit escape.
But that's not the case. That certain dialogs are laid out in a certain way. Those kind of things you need to be aware of. If you take advantage of the standard things like the J option pane and that kind of thing, we'll do it for you. But if you're counting up your own dialogs on the fly, then you need to be aware of this.
The best way to do, to figure out this kind of stuff is just sit down and use the standard application. Sit down and use text edit on the Mac for a little while. Look at how things are laid out. That's the best way. Also pick up the latest HI guidelines.
We actually have just published the latest Aqua user guide. You can go to the web. I've actually got a link at the end of the presentation on where to get that kind of stuff. So just splash around there. So with that, I'm going to kick it back over to Eric and he'll show you how to turn this on.
[Transcript missing]
Okay, so how do we end up using that? Well, we've got our platform, and so now back in our main class, in the Dear True Browser class, we can actually check that platform, and if we are on a generic Java platform, which is what we said Solaris was, then use the cross-platform look and feel. So UIManager.setLookAndFeel, UIManager.getCrossPlatformLookAndFeel ClassName. That's how we got Metal, and it's actually useful from time to time for testing, and also if you're doing any custom UI or anything like that, to use Metal on Mac OS X.
But of course, we'd actually prefer that you end up using Aqua, which is the system look and feel, and so for any platform here other than a generic Java platform, we use the system look and feel class name, and then, of course, call SwingUtilities.updateComponentTreeUI. So that gives us... So that gives us Aqua. That's a really good start, and that's with changing practically nothing in our code.
Now we need a menu bar. So step one, create a menu bar on this frame and call setJMenubar on that. As long as you're doing that right now in your code, hopeful you are for a menu bar rather than, say, adding it to a JPanel and laying that out within your window. But if you do call setJMenubar, then you're halfway there.
The next step is to set this property, comma, Apple Mac OS useScreenMenubar. You can do this cross-platform, of course. So you can run this on all platforms. There's no platform check here. On other platforms, it will, of course, just be ignored. And you do, again, have to do this before calling setJMenubar. As long as you do that before calling that method, then when you do call that method, your menu bar will be grabbed.
You can insert it up at the top of the screen in the global menu bar and your Mac users will be a lot happier than they'd otherwise be. So here, now we've got the look and feel. We've got the global menu bar. What about things like the menu layout and the keyboard shortcuts? Well, I mentioned before that we had platform-specific resources for all of those that are loaded by our generic main menu bar class. Here, for example, is the classic Mac OS version of this. So we've got a two-dimensional array of objects here.
The first element in that array is just a list of the menus that we actually have on this platform. In this case, we have file and edit menus. And then for each menu, we have each of the menu items in turn. So the name of the menu item, whatever its mnemonic is, and since keyboard navigation of menus does not exist on classic Mac OS or on Mac OS X, then we simply set that to null. A string that corresponds to the shortcut for that menu item.
And so, meta n may look a little bit strange. Meta is the generic Java term for what corresponds to the command key on the Mac OS and perhaps other keys on other platforms. So it turns out that Swing's keystroke class, when it sees this string, will actually grab meta and translate that into the command key glyph.
And so you'll actually get the correct glyph within the menu. And then, perhaps the most important part here, an action associated with that menu item. And so we can then do this on all platforms and point all of our platforms, say the new action on all platforms, through to exactly the same bottleneck in our code. Meaning that we don't have to change the new action or opening files or closing documents or anything like that for any platform specific stuff.
And since this is classic Mac OS, then we've got open, close, save. We've got quit at the bottom of the file menu. And then our edit menu is undo, cut, copy, paste, and preferences. How does this change on Mac OS X? Well, in a couple of ways. Most notably, the quit menu is not in the file menu. It'll end up in the application menu and we'll show you later how to take advantage of that.
The other item that's worth noting here is that we've got a help menu. So if you go in and you take a look at the HI guidelines, then you'll see that it's strongly recommended that all applications do provide some sort of help. Your users will definitely appreciate that if you do.
And so, because we unfortunately didn't have time to do that, we're going to do that now. So if we didn't have time to write complete help, we just wanted to show the menu, then we actually put our about box here, even though that should really be in the application menu. And we'll show you how to create an about box within the app menu later.
The other thing that I should mention is, just to reiterate again, that these actions are exactly the same. So again, this is going to point through exactly the same bottleneck in the code. Now, I mentioned previously that creating your resources in this format makes localization easy. And in fact, it actually does. So we've got the, we've got a German version of our Mac OS X menu bar layout.
So you'll notice that the class name has an underscore DE at the end, DE being the localization code for German. And, well, all the strings are different. I have no idea what all of them mean, but I presume that's file edit and help. And, well, Pete wrote that. He knows German. But when, so when you run this and your language is actually set to German, as I'll show you in a minute, then your application will just automatically appear in German.
So if you are at all interested in supporting multiple languages, this is definitely the way that you want to go. And, of course, there's Windows. And so Windows is quite different. There's no close item there, for example. You have exit instead of quit, and all of your menu items actually have mnemonics associated with them.
And preferences actually end up in a view menu and are called options instead of preferences and strange things like that. So in any case, I'll show you a little bit more about that in a minute. But in any case, now that we have the menu layout, how does actually all of that work? And so I've made two changes to the code from before. One to take out our hack to get it to be Sun OS. And instead we are going to run as if we were on the Mac and with the appropriate menu bar. And so when I go forth and run this application, then it comes up.
And there we have an Aqua application. We have a global menu bar. And this most would behave as a Mac user would expect with a minimal change to your code. So the icons are pretty much all the same and everything like that. Again, we changed very little code and all of a sudden we have an application that looks much more like what your users will expect and much more like all other applications on the system.
Okay, cool. Okay, so that was the easy stuff. That was the, like, no code changes, essentially, to be able to get this stuff up and running. So now what I'm going to go into, and take deep breaths in between, I'm like flying through as I always do, is some of the more complex features.
These actually do require code changes. They should be relatively minimal, and we're going to show you how to make these code changes in such a way that it should be very unobtrusive in your code, in very isolated spots, and have a big bang for the buck, or whatever you want to call it. So I'm going to go through drag and drop.
I'm going to go through the MRJ toolkit. Those of you that have been here in years past have heard me talk about this over and over again. I'm going to go through that briefly, and in conjunction with that, handling some of the basic Apple events, things like OpenDoc, Quit, those kind of things.
I'm going to talk about some new file system manipulation stuff that we've done that we expect to kind of grow, that has kind of grown out of the MRJ toolkit, and we hope to, in the future, replace the old MRJ. So I'm going to go through the MRJ toolkit with some new work that we've got going on right now, and I'm going to spend some time talking about JDirect.
So, drag and drop. Drag and drop, we fully implement Sun's implementation of drag and drop on Mac OS X. So, the Java 2 drag and drop works just fine. And my recommendation for the vast majority of apps is that you use Sun's implementation. It's fine for the 90% case. And we're working with them on some of the issues that caused us to implement some of our own stuff.
So, in addition to the Sun drag and drop, which works for the 90% case, we've also got MRJ drag and drop and MRJ data transfer. And those are more closely modeled after, and those came out of MRJ 2.2, more closely modeled after the Mac OS drag manager. They support things like multiple non-file drag items.
Sun's APIs allow you to drag multiple files, but for other things, you need to use ours. And in addition, conversion and coercion between multiple data types. A good example of an application. That might need to use our drag and drop versus Sun's is an application like a pre-press.
I can see a pre-press application where you're trying to write something that has to interact with Macintosh applications, Photoshop, Illustrator, that kind of thing. In that kind of situation, you might need to get more information from the scrap manager and from the Macintosh drag and drop mechanism than Sun's APIs allow you. We're working with Sun to get some of those kind of bubbled back up so that they can be available on all platforms. But for right now, we... We're working with Sun to get some of those kind of things.
Yeah. ...that's what we've provided you with a stop gap. The only thing that you're going to need to be aware of is some of the visual cues and that kind of thing when you're doing drag and drop. Eric will show that in a little bit in the demo, but visual cues are the only things that you're really going to need to be aware of in drag and drop. The rest of it just works. And it was actually, in playing with it, surprisingly easy to wire up standard Sun drag and drop. To do more complex things, obviously, gets more complex, but for standard drag and drop, it's very easy.
MRJ toolkit. MRJ toolkit we've talked about in the past. I'm not going to spend a ton of time on this. Our stance on the MRJ toolkit APIs is we've brought them over from MRJ because they're very valuable to a number of applications. Unfortunately, they're also very dated. They came from MRJ in the past. The APIs were very specific to Mac OS 9 and a lot of the Mac OS 9 paradigms. And so we're working on new APIs that bind much more closely to Sun's APIs and make a lot more sense going forward.
Unfortunately, those aren't ready yet. We're working on those in-house. We're going to roll those out to you. But they're not quite ready yet. And the MRJ toolkit still has a lot of value. So things like the OS type class, that allows you to get at the four--get at and manipulate and create the four byte, the four character key codes that are used throughout the Mac OS.
The MRJ file utils is a set of very rudimentary functions on a class that allow you to get at the four byte. It allows you to manipulate Mac OS specific attributes on files, things like file types and creators, locating apps and special folders, that kind of thing. There are certain paradigms that we don't support in the MRJ--the MRJ toolkit on Mac OS--on Mac OS X because the paradigm isn't quite the same. Something--things like setting the default type and creator for applications. The Mac OS X mechanism allows for types and creators as well but we're encouraging file name extensions as well. So things like that aren't supported by the MRJ.
So we're encouraging that to be supported on Mac OS X. The MRJ application utils is a set of--is a class that allows you to handle things like installing the standard Apple event handlers. So if you want to be able to respond to the quit event when it's in your application, if you need to be able to open documents about those kind of things, that's where the application utils come in.
And that's actually the one thing that is actually--makes a lot of sense and we don't have a replacement for yet. So adopting the APIs for the basic Apple events is a great way to get at the four byte. is totally easy, it's really simple. All you have to do is implement an interface and register the class that implements that interface.
And I've actually found that provided that you have standard bottlenecks in your code for handling these things, which you would normally have to do anyway, your application needs to be able to deal with an open document. If you've got a standard bottleneck for whether your application deals with that, all you have to do is call it by the right thing or funnel this call through to the right thing and you're good to go. Same thing with quit, same thing with all those kind of things. I, in my application that I wrote, all I had to do was change method name and it worked like a charm.
File system access. This is something that we've been working on in-house. Actually, Eric has been poring over for the last while. What our goal is here is to create a set of APIs that bind much more closely to the Sun APIs, match the paradigms much more closely, and allow you to get at a number of the Mac OS X features. This API right now is a proposal, it's not in the release.
We're actually going to release it to you in sample code by the end of next week so that we can push it out to you. What we want is for you to play with it, you to give us feedback on what makes sense, what doesn't, what's there, what's not, so that we can eventually roll this into the system and be able to take advantage of this throughout our applications and yours.
We didn't want to do that prematurely. We wanted to get feedback from you all first. I'm going to go through the details of it, but make sure that you go to our website and pull down this source, play with it, see if it makes sense for your application. Okay.
The two things we've implemented right now in it are the Mac file and the Mac application class. The Mac file class is intended to be able to deal with Mac OS X specific file attributes. Again, very similar to the MRJ file utils insofar as getting types and creators, that kind of thing, finder attributes and more, which I'll go into in a second.
The Mac application is for launchability kinds of things. One of the things that we get feedback from developers a lot is I need to launch an application. .exec is totally obscure for my application and doesn't make sense on the Mac as well. Actually, it doesn't really work on a lot of platforms, real well.
And we need a more standard way of doing that. So that's what the Mac application class is for. And it's also for dealing with MIME type mapping, mapping files to applications. So the Mac file class, like I said, is a totally standard, straightforward API. It allows you to check if it's an alias, file directory, package.
Get canonical path is an interesting one because this has come up on our lists before and we've gotten a lot of discussion about what we should do with aliases. And we've discovered over the course of MRJ that if you do the right thing for one application with aliases, resolve the aliases to what they really should be, another class of application busts.
And so what we wanted to do here is allow you to resolve it if you need to but not change the underlying classes because we found that changing the way Java I/O file works just busts a whole collection of applications. So we're allowing you to get at aliases and manipulate aliases without busting everyone. Is visible in Finder is another Mac OS X specific kind of paradigm.
There's a distinction between what the file APIs expect is visible, i.e. what Unix shows as visible versus invisible, and what the Mac OS shows as visible or invisible. There's actually a whole slew of things that you can see in the Unix file system as visible, but that your user won't see and you need to be able to make that distinction in a lot of situations. And get icons, standard kinds of stuff.
Mac application is again for dealing with opening documents, manipulating documents, that kind of thing. And so first of all, get file just gets you the Mac file back. But more interesting is the open and open document APIs that allow you to essentially launch applications the way that the Finder would.
So that if you need to launch a web browser, launch a web browser with a page, that kind of thing, this is how you would go about doing that. It also deals with application specific Finder attributes and bundle style attributes. So Eric will show how this is used in a second.
JDirect 3. If you went to Blaine's talk on, when was it, I guess it was Tuesday, on the VM, he talked briefly about JDirect 3. I'm also going to talk briefly about JDirect 3. JDirect 3 is one of these things that I find insanely powerful because it means that I never have to wander into C code. But in general, people don't end up using it a ton. So I'm not going to spend a ton of time on that.
There's a lot of developer documentation. The thing to keep in mind here is if you've already got JDirect code out there, the difference between JDirect 2 and JDirect 3 is important to note. The biggest deal is the new linker class that you see here. You need to be able to do that to tell the VM to bind your native classes to your library.
So this is the sample code that he threw on the screen the other day. What I wanted to do is point out kind of more important things. One of the things that's important to us is how you bind to the toolbox because that's where we use JDirect all over the place. This is how you bind to Carbon, how you bind to other system applications. The only thing that's different between this and the previous example is the library that you're linking against.
It's not your personal library. It's system library framework, core services framework, core services. And the call that you're linking against is new pointer. But this allows you to, and it allows us in our implementation, to get at the entire toolbox. This is how we implement a good portion of AWT and Swing is using JDirect.
There's more examples of this and actually the Mac file APIs and that kind of stuff that we're going to roll out. We're going to roll out the whole source code to the implementation and you can see how to use JDirect. Using it is pretty straightforward once you get used to it but there's some paradigms you need to get used to.
Toolbox Lock. We've been telling you over and over again over the years that the Mac OS toolbox Carbon is not preemptive. It's not preemptive. It's not re-entry. If you interrupt the toolbox, your application will potentially behave poorly or crash. On Mac OS X, this wasn't as big of a deal because as long as you were down in your native code, your toolbox calls weren't going to be preemptive. On Mac OS X, this is a huge deal.
This is a really huge deal because suddenly we've got a real preemptive system. Carbon can, you can be running from multiple threads and the nature of Java is you've got multiple threads running. So you need to make sure that if you're calling the toolbox in your application that you acquire this Carbon lock. This is what we do throughout our code and this is how you make sure that you don't clobber us or we don't clobber you. We don't clobber you.
We try and be real meticulous about making sure that we maintain this lock. And you'll notice that this lock has changed slightly in that we're not acquiring a lock on a specific global piece of information like we did on MRJ. It's a function call. This allows us to do some magic things behind the scenes that allow us to clean it up later. But you need to be aware of this.
So, kick it over to Eric and he'll show how to wire this stuff up. Okay, so the first thing I want to talk about, and there's a very long list of things to go through here, is drag and drop. We've got our application running here, which you've seen before.
And we open our, let's say the applications folder, scroll down here, find mail.app, just to bring that over here, and drag this over. And you'll note that when I drag this over the tree, so I can drop this into the tree and it's going to actually open up the entire tree, go through the hierarchy, and select mail.app in there, then I get a little highlight ring around that.
That's something that we would prefer that you do. So, Sun's drag and drop API does not do that for you automatically, and it turns out to be relatively easy. I'll show you how to do that in a second. But it's always a good idea to give your users feedback when using drag and drop to let them know where you can actually drop something. So when I drag this back here, then the highlight goes away, and then it comes back, and so I let it go, and switch in here, and everything opens up, and mail.app is actually selected in there.
So, to get all of that to work, I'll go back to our tree class here. So, within der tree, within the tree's constructor, we create a new drop target. This is using the standard Sun JDK 1.2 and later drag and drop APIs. Create a new drop target using this as the component, and this also as the event listener. So, you'll see here this implements drop target listener.
Drop Target Listener requires that you implement a couple of methods here. If I go all the way down to the end. First, drag over and drop action changed, we're not actually going to worry about. And in general, you don't have to worry about them all that much. The two important ones here, first of all, are drag enter and drag exit. So again, when you're entered with a drag that you want to accept, then it's a good idea to take advantage of Swing's border facilities and add a border to the component of the right color, in this case, the text highlight color.
and to show that you can actually drop something in there. And of course on drag exit you want to remove that border. On the other hand, you may potentially run into some slight layout issues if you end up actually removing that border, or at least we did in this case.
And so instead we create a border just of the regular text color, and so that ends up showing up in black instead of in yellow, and so the color goes back and forth. There's one other -- well, one thing that you absolutely have to do, if you choose not to go with the highlight border, that's okay, but you really do have to find some way of accepting the drop.
And so this again uses the Sun's standard API to get the transferable object from the drop target drop event to ensure that the file flavor is supported by whatever's being dragged. Grab the transfer data out. This is a list of files in Sun's API, but since we can only process one file at a time with this application, then we ensure that there is actually a file there, get the first file out, and then actually navigate to it. So we have the navigate to method that opens up the tree and goes through it and selects the object that it's asked to select.
So that's drag and drop. The next thing is handling the Apple events. And so in our main class here, we implement comAppleMRJ, MRJQuitHandler, MRJOpenDocumentHandler, and MRJAboutHandler. So we can handle the QuitAppleEvent, OpenDocumentAppleEvent, and AboutAppleEvent. And that only requires changing a couple other lines in the code. So adding three additional lines so that when we are on the Mac, then we call through to MRJApplicationUtils and register the Quit, OpenDocument, and AboutHandlers.
The reason actually why this can be included in the main class and still have it compile across platform is that we do distribute an MRJToolkitStubs that simply has implementations of all of these methods that are stubbed out when not running on the Mac OS. So you can actually, you could even run those on other platforms.
They would simply do nothing. So because we factored this code well, then we have bottleneck routines for quitting, for opening a file, and for handling an AboutBox. And all we have to do is ensure that the names of those are the names that are in our implementation. And so, for example, handle Quit here. Nice and basic, just call system.exit of 0. But if you wanted to do something like prompt the user to save a document or something like that, then you'd go through there. And handle OpenFile there.
And handle About right here. So that's how you go about handling the basic Apple events. And then there's one additional thing to show. Okay, maybe two. So we have a class called InspectorPanel that draws that panel on the right that shows the basic file attributes that you can get from the standard 1.3 file API. So can you read a file? Can you write a file? When was it modified? And so on and so forth.
There's one thing that we'd actually take. So we've taken out of here, which is if we're on the Mac, then we want to add this thing that we factored out into a separate class called MacPropertiesPanel. And what that actually does is to take advantage of the Mac file and Mac application APIs and to show you Macintosh-specific file attributes about them. And before I go forth and actually run that, I want to show one additional thing, which is how we can take it out of the Mac and run it.
So we're going to take advantage of get icon then for our individual tree nodes and grab the Mac file for the file that corresponds to each node in the tree. And if it's an application, then because the application icons look really pretty on Mac OS X, we'll grab the icon and calling get icon on the Mac file, grab it as an image, create an image icon, and then set the icon for that tree node to be the icon of that file. So what does all of this look like? I'll go forth and run it. Peace.
And this comes up, and we've got an additional properties panel in there. So for everything on the system now, you can see, is this an application? Is it a package? Is it an alias? Does it actually show up in the finder? What does it look like? And what's its canonical path? So for example, for aliases, we have an alias to the Java VM framework that's at the root level of the system. So we've got a little bit of a painting glitch with the icon right now, but we'll take care of that. We've got a checkbox here that says, is this an alias? Yes, it is.
Here is the canonical path. So we've done the alias resolution, and that's what it points to. You can then create a file with that string, and you get the actual file on the system that corresponds to. We've also got open here, and so I'll hit open. And even though that appeared at the root level, you can see what opened in the finder was the Java VM framework folder within system library frameworks. So that's alias resolution on Mac OS X.
You also may notice that this list of files is now a lot shorter than it was when we ran the application back in the beginning. The reason for that is that we're only showing the files that are actually visible in the finder. So we're displaying an interface that looks more like what your users will expect when they're navigating through a file dialog. You don't see user and dev and cores and everything like that in here anymore.
And when you go into the Applications folder in here, then you'll notice that the applications are actually no longer folders. And instead they appear to the user as if they are standard applications. And in fact, I'm going to take Mail.app here and hit Open. And you see the dock open up and Mail.app pops up. And there we go, we have mail. So this is how you can take advantage of a Mac file and Mac application APIs to do things that your users on Mac OS X will really appreciate. So now back to Pete to talk about packaging.
Thanks, if we can get the slides back up here real quick. The last thing I want to go over is packaging, and packaging is totally straightforward on Mac OS X. First of all, like I said earlier, the first step in getting your application packaged up right is getting it packaged up in a jar that's available on all applications. One of the things that we're working on in-house that isn't ready yet, but will be available very soon, I don't have specific dates yet, or actually, probably just shouldn't make specific promises yet, but we're going to have a mechanism for allowing for double-clickable jars.
So you'll be able to, in the finder, just double-click on a jar itself and just have it launch. So we've got that running in-house, and there's just some minor glitches that we need to work out with that. But in addition, like you saw in the demos, Mac OS X applications are packages. There's a whole bunch of other things that you can bundle up in Mac OS X bundles.
And so there's a number of tools that you can use for creating Mac OS X bundles. If you notice, JBuilder is bundled up as a, as standard Mac OS X application, or AppBuilder. All of the Java applications on the system are bundled up that way. So you can either use a tool like ProjectBuilder. If you're using ProjectBuilder to design your code, ProjectBuilder will burp out a standard Java application package that will look like a standard application.
JBuilder, apparently I heard rumors of the JBuilder session yesterday talking about bundling up double-clickable applications. In addition, we've also got a mechanism for bundling it up inside of bundling apps and using standard jars so you can just drag a jar over and use MRJ AppBuilder to bundle up jars. And that's totally straightforward too. So the bundling mechanism is very easy and really powerful.
In addition, there's a technology called WebStart that you've seen if you went to Steve Naroff's talk on Tuesday, you saw WebStart being demonstrated. That's a technology that we've got running in-house that we're hoping to push out very soon. It's actually very functional and there's just some like, licensing and legal issues that we need to deal with to get that bundle pushed out.
That's a feature of the Java 2 Standard Edition version 1.4 that's coming out. We're hoping to get it out to you earlier and that's a web-borne mechanism for distributing applications. So there's a number of ways to get your applications out to users. So let me kick it over to Eric one last time and he'll show you the AppBuilder.
Okay. So what we have here is MRJ AppBuilder which is the simplest tool that you can use to build a double-clickable application on Mac OS X. It comes up just like this. And the most straightforward thing to do, assuming that you have a jar with a correct manifest set up, as we do, is to just click on choose, navigate through the file system.
I should mention, by the way, that, so when I showed you the directory tree browser just now, none of things like user and var and temp, et cetera, didn't actually show up. And yet they do in the J file chooser. That's because the Mac file API is relatively new and we do hope to actually . Okay.
So we're going to navigate through the J file chooser and the AWT file dialogue to when you say that your application is willing to, or intends to, take advantage of the Mac file API to display a layout of the file system that your users will expect. So here to navigate through.
and actually select the jar that we built in JBuilder. And ask me to choose a main class. Of course, that's George Free Browser. So the main class name automatically gets inserted here. The class path gets set up correctly. And over in the Merge Files tab here, The jar that I've selected will automatically be merged into the double-clickable application, so you can distribute something that to your users looks just like one file.
Although, of course, it's a packaged application, so it's a directory, etc. But they don't need to worry about that too much. And then we have to set where we want to save that, so we'll save it right next to where that jar is, and navigate back through to there.
"So, I'm going to select that, and then hit build, and actually I guess I had one already. Okay. Tells me that it did actually finish building it and it actually managed to build it successfully. Yay! So, then we can hide that and navigate through. Here's the Dirt Tree Browser application. Just double click on it. Looks like a standard application. And there we go. We have a Mac OS X application.
So if you take advantage of these technologies, if you use the screen menu bar, use the Aqua look and feel, build a double clickable application, ideally take advantage of the extra functionality that we're providing you to integrate your application better with the rest of the system, then as far as your users can tell, this is not a Java app. This is a Mac OS X application. And that'll make them all a lot happier. Great. Thank you.
We can get the slides back up here one last time. What I want to do now is point you at some resources. First of all, the Mac OS X HI guidelines. You can either write that down or you can just go to the Mac OS X developer page under documentation, under the general documentation.
There's a new version of the Aqua HI guidelines. I definitely recommend you pick up that and just leaf through it and see how that compares to your current application. There's also a Mac OS X Java website that will have all of the stuff that we've got -- oh, actually that's -- is that right? Yeah.
Okay. Oh, okay. He flinched up front. So the Mac OS X Java website has a bunch of documentation on the different technologies we've got. It's where the latest release notes go, pointers to the latest builds, and sample code. And the sample code -- the sample code that we've been demonstrating in this session will be posted on that website. So you can go there.
If you're in a super hurry to get it, it's actually on my iDisk. If you go to PAS, it's on my iDisk. And we're just going to push it up there. So I just -- it didn't make the cut. I pushed it up last night. So if you want to pull it from there, you can go ahead and pull it. Otherwise, the sample code will go up on the website so you can look at what we've done and the changes that we've made in detail.
And the Java update -- I'm actually probably going to get in trouble here, but it's ready. It's not -- it's -- it will be posted tomorrow. We pushed it up to the -- we finished it, packaged it up yesterday and gave it to Alan, and it will be up on the website tomorrow. So this has all of the stuff that you've been hearing and all of the different jobs. during all the different Java sessions.
And I got to announce when it was ready first. and Paul So, anyway, from here on out there's actually still more Java sessions. I find it amazing we've gone from like two or three Java sessions to ten just on our stuff. Right after, actually at two o'clock over in Civic there's more information on QuickTime for Java.
The Java graphics stuff will actually be really interesting if you go this afternoon. We're going to be talking about some of the stuff that we've been doing with hardware acceleration, some of the things that you can do in your code to take advantage of this and modify your code slightly to take advantage of some of the new features we've done.
Java security tomorrow morning at nine o'clock in the morning. Scott down here will talk about some of the security related issues. And please, please, please come to the feedback forum tomorrow morning and let us know how we're doing, if you've got any questions, that kind of thing. So, who to contact? Alan.
Alan knows where to find me. Alan is the best person to talk to you if you've got any issues, if you want to get your code to us to add it to our test suite, that kind of thing. Alan's the best person to talk to. You can come directly to me and you're welcome to, but I tend to go dark during development time.