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

WWDC02 • Session 404

Tailoring Java Applications for Mac OS X

Java • 50:13

Common development and deployment tips and techniques are featured in this session designed to help developers deliver Java applications that look and feel like native Mac OS X applications. Bundling suggestions, use of runtime properties, best UI practices, and accessing native libraries are discussed.

Speakers: Matt Drance, Scott Adler

Unlisted on Apple Developer site

Transcript

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

Okay. Hi, everyone. So, end of the day Tuesday. How's everybody holding up? Glad to hear it. So, my name is Matt Drance. I'm a Java guy in developer tech support. So if you write in a Java problem to DTS at Apple.com, there's a pretty good chance you'll be talking to me. And after I'm done talking, hopefully you'll think that's a good thing. So welcome to session 404, Tailoring Java Applications for Mac OS X. And what are we going to be talking about today? There's a couple things we... There we go.

A couple things we want to talk about at 5:00 today. First thing, which is the goal of all of our Java sessions this week, is to make your Java applications first-class citizens on Mac OS X. Second thing would be to take advantage of some features that are specific to Mac OS X, only available here, but available to you through Java. And with those two things in mind, because it's Java, we want you to still be able to maintain your cross-platform compatibility while taking advantage of these special things.

So specifically, what are we going to be talking about? First thing I'm going to go over is some general cross-platform development practices, things you should be keeping in mind whether you're supporting Mac or Windows or Linux or anywhere you want to deploy. Then I'm going to go over some techniques for deployment on Mac OS X.

And then we're going to go a little deeper and more specific into enhancements and special features that you can take advantage of on this platform. So if you've been to the other Java sessions today, you've probably seen this diagram up here. And what we're going to be focusing on in this session is the desktop area, or the double-clickable applications.

So, moving on to the cross-platform practices. I'm going to jump right into code. We're not going to talk about features or the future or anything like that. I'm going to talk about things you can do right now. In particular, I'm going to talk about menu shortcuts, contextual menus, JDesktop pane and using multiple document interface-based GUIs, and just things to keep in mind when you're placing your components or generating or painting custom components.

And I'm going to be using a do and don't format for these tips because basically I've constructed this talk based on a lot of developers who have come over to the Mac from Windows or another platform with their Java applications and kind of seen things that have jumped out at me.

So we're going to start off with menu shortcuts. And for all of you who are just out of curiosity, do we have anybody in here who's actually a Java developer mainly on Windows and is coming over here just kind of to explore the Mac? And excellent. Welcome. Glad to have you here.

So as Java developers, most of you probably realize that on different platforms, keyboard shortcuts for menus use different keys. So why is that a problem for you? Well, if you're writing one Java application that you want to run on multiple platforms and you want it to behave the way a normal application would on that host platform, you need to specify the right shortcut key.

On Windows you have control, and on the Mac you use the Apple key or the command key. So how do you know? How do you know you're on a Mac? How do you know you're on Windows? How do you know which key to use? Well, the good thing is that it doesn't really matter.

Not a lot of people know about this, but there's an abstracted call in the Java AWT Toolkit class called GetMenuShortcutKeyMask. And what this does is basically defers to the host platform's toolkit implementation and finds out what the proper shortcut key should be. So you make this one call in your Java application, and on Windows it'll return ControlMask, on the Mac it'll return MetaMask, which is what evaluates the command. So this is great because this is really Java at its best. Basically, you're saying, I don't care what platform I'm on, I want this app to behave properly.

And Java takes care of it for you. It's less work, it's only one line of code, you don't have to figure out which platform you're on, you don't have to figure out what the right key is. It's more accurate. If for some reason, Sun in Java 1.6 decides to either kill the meta mask or suddenly announce support for the command key with a new mask and then we adapt to that and you've been hard coding meta, you might be in some trouble.

You won't be if you use this call. And like I said, it's portable. It'll work the right way on So the alternative to using this would be, like I said, hard coding the modifier key. I'm on Windows. Windows is the only place I'll ever be, so I'm sending control for my menu shortcut. It's the same on the Mac, right? No, not really.

So most people, when they come over, they do their best to kind of detect what platform they're on. They set control if it's Windows. They set meta if it's Mac. And that does work, but it's a little more extra work. And if you were working from Windows initially, setting control, you decide you want to come over to Mac, you've got to reopen your source tree and include that condition everywhere you made a menu shortcut. If you did the toolkit call in the first place, you don't ever have to worry about that again.

So I'm going to show you a quick example of this. This is the code that you would use. It's only actually two lines, but because I want you to be able to read it, it wraps to about ten. Just create the J menu item, set the accelerator, and normally just generate a keystroke, but instead of explicitly saying control or meta, you would just make the toolkit call.

So with that, I'd like to move over to the demo machine. And the screensaver went on, even though I told it not to. So I've got a couple applications here. The first one's going to be dealing with menu shortcuts. So I've written a very simple text editor here, and I try to model it after the kind of things I normally see on Windows.

So, I've got a couple of applications here. And it's got all your standard things. It's got boldface or maybe underline, italic, etc., etc. But we go to the menus, and this is what I like to call the carrot farm. When I come over, a lot of times we work with some developers from Windows, they bring their application over.

Most of the time it looks and works fine, comes up, but we see all these control icons all over the place. And what's the best yardstick for Macintosh UI is the finder. You'll see that you may never have noticed it, but every single menu shortcut on the Macintosh is command based. It may have an additional mask, but everything's using command So this is a perfect example of what you could have avoided if you had been using the toolkit call. We can go back to the slides.

Moving on to contextual menus. Contextual menus has another sort of abstracted call similar to the toolkit mask, which is mouseEvent.isPopupTrigger. Now this is another call that just defers to the host OS to find out what kind of thing is supposed to bring up a contextual menu. Now, that seems pretty simple, but I've seen a lot of people do things like check on the mouse event whether the control key is down, which is what triggers the contextual menu on a Mac, control click.

Or the button to mask, for example, on Windows, right click brings down the contextual menu. You make the is pop-up trigger call, similar to the control meta issue with the menu shortcuts. You make one call, everything's taken care of, you don't have to worry about where you are or what you're supposed to be doing. Now, there is one caveat.

And that's when the pop-up trigger is recognized. And this is something I've seen on Java dev a couple times and hopefully this will put it to rest finally. There are two different mouse event calls, mouse released and mouse pressed, and there are two different areas where the pop-up trigger is actually recognized, actually occurring.

On Windows it occurs on the mouse released, and on the Mac it occurs on the mouse pressed. So in order to have these contextual menus work on both platforms, you just want to basically do your contextual menu logic in both of these calls. Here's a quick code example of that.

As you can see, I've got the logic down at the bottom. Well, it's kind of pseudo-code, but, and I'm calling it both in mouse pressed and mouse released in my mouse listener. And there's no repercussions to doing it in both places. The right platform will call the right method. It's never going to get called twice or anything like that.

So now we're going to talk a little bit about JDesktop panes and MDI, JInternalFrames. And if, for those of you who are Mac users, you probably know that the MDI layout is not too Mac-like. A lot of Mac users expect to see things like a single container, something like Project Builder, where there's a dynamic container that does manage multiple files, but everything's in front of the user. Things aren't suddenly disappearing off the screen. or, of course, just free-floating frames all over the place.

So, in the interest of being compatible with the Mac look and feel, we would suggest that if you're doing something like word processing or image editing, that if you have multiple documents you need to keep open at the same time, we suggest you either use multiple separate free-floating J-frames or a single dynamic container, kind of like what J-Builder uses.

You have one view panel that updates based on the file you selected, or Project Builder does a very similar thing. Or you could do something like an application like LimeWire, which LimeWire does. And basically they have a bunch of different panes that are separated by tabs, but it's in one single parent container. And to show you what I'm talking about, I'm going to do another quick demo.

So what I did was I took the logic from our text editor, this is going to be a common theme here, and I put it into another application. Now, there's, you'll see that there's just something about this app that doesn't seem right. And, you know, I'm going to go ahead Now, there are things here like... This still works. It's still my... Still my text editor. I can still do things like bold and italics and stuff like that.

Then I start to move things around a little bit, and all of a sudden my frame is gone. Now, you guys are all power users. You're all developers. This probably is no big thing to you. But a Mac user very possibly has never experienced this before. And they might get pretty confused that they're expected to be able to move their frame all over the desktop and they find it disappearing on them. Gets even more confusing if we were to go over to Metal. I'm sorry, not Metal, Aqua.

Now, we're going to do something like this, and then I'm going to bring up a finder window. These two windows look really similar. This one I can move all over the place, this one I cannot. This one I can bring over into limbo. It gets even more interesting when we minimize our windows. I'm going to bring my finder window down. It goes into the dock where I expect. Now I'm going to minimize this window and work on some other ones.

And now we have a magical new doc just within the context of our application. And this is actually a great feature because we have an aquified doc for JDesktop Paints. But in the interest of making grand...grandmas not confused as possible, this can get pretty freaky. This new doc of course moves around with the parent frame and you either have a user who's very confused and not sure which...what Windows is going to go where? Or they suddenly think that they can move the dock around wherever they want.

So in the best interest of looking the best on all platforms, we'd suggest you stay away from the JDesktop pane because it really only resembles that one platform that most of the people in this conference probably are not the biggest fans of. Now the one thing about using a JDesktop pane that I hear from a lot of people is that, well, the thing the JDesktop pane lets them do is use a single J menu bar to control all the frames that are in there, or namely just the one that's in the front, but that's good enough. I hear that, and that'll be something we're going to be talking about in a few minutes.

Demo's gone. So now the last thing I want to talk about as far as compatibility is the specifics of moving things around, placing components, sizing components, designing them. The thing you need to keep in mind, especially with swing, is that not all look and feels are the same. Metal is different from windows, is different from motif, is different from Aqua.

So one of the things that we really, really think you should do, and this seems like a no-brainer, but a lot of people don't do it, is use layout managers. Don't go to the trouble of setting explicit XY coordinates for your components. Sometimes you would want to do that, but you can run into a lot of trouble if you suddenly move over to another platform that has another default look and feel that has different button sizes and things like that.

You'll suddenly find things painting over each other, overlapping, ending up in places that you didn't expect. If you use a layout manager, things might change as you move across look and feels, but it will still at least conform to the same general layout that you set, because you're using a layout manager and you know how it behaves.

And we also would suggest that you didn't use your own colors or fonts or shapes or anything like that for your custom components. We would suggest that you query the UI manager and find out what the color for a button should be, what the font should be for the look and feel, and things like that. Perfect example of this is, I don't have a demo for it, but we were at Java 1 a couple months ago, and we had a Java compatibility lab, much like the one we have in Room M downstairs. Feel free to say hello.

And we had a guy who came over, I can't remember what developer, I can't remember what company the developer was from, but he had a bunch of applets that he was used to running in Windows and Solaris. He wanted to come over and try them on Mac OS X. They came up pretty well and they worked and everything. But he had basically a tabbed pane interface. He had two tabs. And in Metal and Motif and Windows, the tabs can start from the left, all the way on the left of the pane, and they move to the right.

That's fine. On Aqua, they're centered, as some of you may or may not have noticed. Tabs in Aqua are centered, and even as you add one of them, you can have one and you can have six. They just all start to spread out from the middle. And this, to most people, would never be a problem, but for him it was because he was painting either a label or a specific button right in the center of the real estate where the tabs should be.

Now, it was fine for him on Metal and Windows and Motif because he knew his two tabs would be on the left and he knew how big the tabs were. So he just did some math and he just plopped that label right in there. So he came over to Mac OS X and his label's gone. And he was actually pretty irate.

He thought that we did something bad. He thought we broke Java. He was going to tell Sun on us. And I guess I can understand him being frustrated, but the fact is that look and feels are different. And that Sun has no specification saying where tabs should be.

And if some other company comes out with a third-party look and feel that some power user decides to set for their default on Mac OS X or Linux or whatever, you might have a heck of a time running into things like that. So really, you should really use layout managers, and you can avoid problems like this.

So that's about it for the compatibility practices. I'm going to move on to application deployment, things you can do to drop your applications on a Mac OS X computer. And the most obvious, of course, is the double clickable application, the dot app bundle. If you're working in Project Builder, you've already got this. You may not even know it, but you click build and run in Project Builder.

You're Java files are compiled. You get a JAR file built, and that's thrown into a .app bundle, double-clickable by the user. You can pull it out of the build directory and put it in an installer, and you're ready to go. If you're developing using some other IDE, developing on another platform, and you want to, you know, have an application that's as Mac-like as possible, we have something called MRJ App Builder that comes with our developer tools.

And you can drag your JAR files right into MRJ App Builder, automatically adds them to your class path, it generates an Info.plist for your runtime properties, and you click build application, and there you go, you have your .app bundle. And for those of you who feel particularly tough, you can go ahead and build your .app on your own, because after all, it is just a folder. And we have a bunch of bundle services documentation on the developer website, which is under techpubs, macos10, and from there you click on documentation. documentation essentials. You can find out a lot about how the bundles work.

And of course, there's Java Web Start. If you were coming from the Java in the browser session, I don't want to talk too much about it, but there is a particularly cool new feature that's coming out, which of course is the desktop install on Web Start. Once the user has downloaded an application, they can optionally have it installed down on the desktop as a double clickable app.

And that's why you see Web Start kind of creeping into the double clickable applications area in that diagram I showed you in the beginning. And as a last resort, we have the double-clickable JAR. If your JAR file has a legitimate manifest that specifies a main class, the user can just double-click it in Finder and your application will come up fine.

So when you're installing on Mac OS X, there are some directories that you probably want to or need to know about. The first, of course, is the magical Java home. This is something that a lot of Windows Solaris script-based installers need to find out when they're building their startup script. And because we know where Java is on every Mac OS X system, because we're the ones who install it, you can count on that Java home being library, slash library, slash Java, slash home.

As far as extension libraries that you may want to install, you can likewise put those into slash library, slash Java, slash extensions. And this is going to be the functional equivalent of what would be libxed off of the Java home directory on other platforms. But we would encourage you to use this one.

I'll get to that in the next slide. And you can also do Java extension installation on a user level, which is basically the same path, but it's off of the user's home, as opposed to the system level, the system root, which would be available to all users. Thank you.

So you should really take note of these directories if you didn't know them before and you're looking to install on Mac OS X, especially the extensions directories, because the basic idea is that these are part of the boot class path and they will be included as third-party libraries. The reason you should really remember them is because if you went to the old Windows habits or the Sun JDK habits and installed things in libx, you might run, you will run into problems when we update the Java VM through software update because basically we have a versioning system with multiple directories and we move up and we basically will install a new Java root.

That will leave your old directories and your old libx directory behind. So you want to use, the library Java extensions, however, will be properly updated to the new version. So you want to use the above directory and not libx. Basically you don't want to put anything into or below Java home. But you can count on it as a symbolic link to get to your Java and Java C executables.

So now I want to talk about your basic runtime properties, the things you would set and get using system get property later on. On most platforms, you would specify those at the command line using dash D or anything like that, and of course you can do that on Mac OS X too, because we have the terminal.

Now on double clickable applications, you can also specify these properties in the Info.plist file. Info.plist, for those of you who have never dug around in it, it's a hierarchical XML based properties file based on small dictionary tags, and there's a Java dictionary, and then a property sub-dictionary of that, and that's where you would include your runtime properties.

So what I'm going to show you right now is how you would go about setting those in Project Builder. This is another question that comes up a lot. A lot of people have been building their applications and manually going into the bundle and editing their Info.plist file, and I promise you don't have to do that.

So this is just a quick variation of the Hello World project that comes up when you start a new swing project in Project Builder. I'm going to run it right now. And bear with me here, this isn't a very real world example, but just want to be quick.

Now it says hello world. Anybody who's used Project Builder has seen this application before. But what's happening is this, this string is being pulled from a system property that I'm setting using a runtime property in the application. And if I want to change this text, I'm going to have to do a Basically, we're going to go into Project Builder, go to the Project menu, go down to Edit, Active Target.

I'm going to click the Application Settings tag, go to Expert, and These are all our info P list properties. This is our Java dictionary. I'm going to open that. There's properties. Go down there. I see a couple properties here. And here's the property that I put in, the WWDC.hello message. And we're just going to change this.

Say hello WWDC. I didn't change any code. This normally would be a dash D property on the command And there, our text is different. So for those of you who didn't think that could be done using Project Builder, who are opening up your Info.plist and bbedit, your days of woe are over. Okay, back to the slides.

So now we're going to start talking about the Mac OS X specifics. Things like, very important, detecting a Macintosh client, or more specifically something that's using Aqua as its look and feel. There are some things, I tried my best to give you things that would work on both platforms as well as possible, but there are some times when you're going to need to find out what platform you're on and do one thing or another. And we'll tell you what the best way to do that is.

I'm going to talk about taking advantage of Aqua in general as a look and feel for your swing apps. I'm going to talk about some Mac-specific runtime properties that we specified just earlier in Project Builder. I'm going to talk about the application menu and the MRJ handler interfaces we provide to take advantage of those. And some of the Mac OS X native services that are available to you through Java.

So how do we find out if we're running on a Mac? A lot of people typically know about the OS.name property, which is a standard Java property on all virtual machines. And usually people just get that, they get the string back, and then they parse it for Mac or Win, and they find out what they're on. And, you know, it typically works. And it's probably safe to, because we're probably not going to take the Mac out of Mac OS anytime soon.

But it is a little, it is a little potentially unreliable because you're doing string parsing. A better way to do it is to use a string that's not on the Mac. would be to simply get the MRJ version property. And what is this property? This is something that we set when we launched Java.

And it evaluates to a number, of course. And the number's not really important. What's important is that the number is there. This is a property that's only set through the system on Mac OS X. If you're on Windows and you make a request for this property, you get null. And that's how you know you're not on a Mac. If it's not null, you are. And the other good thing about this is that it's available to applets.

We've modified the security settings for property access to applets in the sandbox so that you can check this version, because there are a lot of people who are doing applet stuff, and they do different things on Windows, different things on Mac. So this is our way of making it easier for you to come to the Macintosh if you didn't have a signature or a certificate before.

And to go a step further, if there's something that you want to specifically do if you're using Aqua as opposed to just being on a Mac. You don't need to know the class name. You don't need to know the fully qualified package and class that we use for our look and feel. All you need to do is query the UI manager. Once you've determined you're on a Mac, query the UI manager for the system look and feel class name.

You'll get the fully qualified class name for the Aqua look and feel. And then you can just compare that to the look and feel that's currently running using UIManager.getLookAndFeel. So you combine these two things. If MRJ version is not equal to null, if get system look and feel class name is equal to look and feel, that means you're on a Macintosh and you're using Aqua.

So let's talk about Aqua. As most of you probably know, Aqua on Mac OS X is absolutely free. It's the default look and feel for swing applications. If you're using AWT, which is heavyweight, obviously you're going to be pulling out of the Aqua native resources. You get things like the animated default button, translucent menus, G&E effect, etc., etc. And one of the other things that comes with using Aqua is there's actually a very, very interesting document called the Aqua Human Interface Guidelines, which is usually intended for people writing Carbon and CoCoLapse. And we've abstracted most of these things for you when you're using Layout Managers.

But it's actually a very good read, especially if for some reason you want to be a Mac programmer and you're not interested in, you know, you're not interested in necessarily portability and the only language you know is Java and you want to make a real kick-ass Mac application.

You can go ahead and read this document and find out a lot of really subtle things about control placement and sizing and stuff like that that you may not have known. So what's an example of this? An example of the guidelines, they state that scroll bars in Aqua should always be visible regardless of what's happening. If you have a window that might at some point show a scroll bar, you should show it from the very beginning and obviously show it as initially disabled.

And the reason for this is that Java doesn't, Java swing doesn't normally have a scroll bar. It doesn't have this behavior. If you have a J scroll pane and, for example, in a text editor, you won't see the scroll bar until you start to run off the bottom. And then the scroll bar will suddenly appear and it'll actually shift the content in because it needs to take up some more real estate to create that scroll bar.

So if you automatically set the JScrollPane policy to always show the scroll bar, you won't have that kind of graphical jump that occurs when the scroll bar suddenly appears. And that's mainly the reason that the HI guidelines specify that for Aqua. And how do you do that in Java? It's really easy.

Here we started our JScrollPane and there's two quick lines, set vertical scroll bar policy, set horizontal scroll bar policy. Set those to always be on. Now believe it or not, there are some Mac users who really pay attention to this kind of stuff. And if you get flamed, Don't say I didn't tell you.

But the other advantage of this is this is a very low, you know, it's a low risk, low maintenance thing that you can do to really just kind of make the, make your Java app look as much like a native Mac app as possible. And people on Windows probably wouldn't notice that you did or didn't do this.

So let's talk about some of the specific runtime properties that are here on Mac OS X. We've got, of course, properties for file dialogs to handle package and app bundles. Now, normally those are folders. So Java needs to know what to do with those. Should they be treated as folders that you can navigate into, or should they be treated as selectable files? Now, we also have similar properties for the swing version of file dialog, JFileChooser. Those aren't runtime properties that you would put in InfoPlist. Those are properties that you would put on a per instance basis using Java. That would be the demo machine. Can we get the slides back? Thank you.

Where was I? Yeah, you set the J file chooser properties using the put client property method that's available to all swing classes. Now, I'm mentioning both, but we usually suggest people use the AWT file dialog, and that's just basically because it's a native link, it uses the navigation services dialog, you get the nice column navigation. J file chooser is completely abstracted, so it just uses a generic tree navigation UI that's available to all swing classes. that's not really familiar to the Mac.

There's also the small tabs property, which a lot of people make use of. I'm mentioning this because tabs on Aqua are definitely bigger than they are on other platforms. So a lot of people like to use this property to kind of have their UI be a little more in sync with the way it looks on, in the metal looking field or on Windows. And the other reason that we did it is because the HI guidelines specify that you should have two different tab sizes in Aqua.

We also have switches for anti-aliasing of graphics and text using Quartz and hardware acceleration. If you went to Gerard's session, I believe, this morning, he could tell you about a lot of the new things that we're doing with that. and there's, this is just the tip of the iceberg. There are a lot of Mac specific properties in Mac OS X and I would encourage you to go to the web. I'll have a link to this tech note later but the tech note is number two oh three one.

So, what's the big one? What's the big Mac property that everybody likes to use? It, of course, would be the screen menu bar. And what's the problem here? The problem is that swing J menus, swing J menu bars are associated with a specific J frame. They appear inside the frame.

And that's not very Mac-like at all. Every Mac application has always had the J menu, has had its menu bar at the top of the screen. So we've inserted a runtime property that will very simply let you do that. You don't have to do any different code. You call sit J menu bar and we put it up at the top of the screen where we like to say it belongs.

So what are the potential problems with this? Well, if you take my advice from a few slides back where I suggested you use multiple J frames, You have the issue of, yes, we bring it to the top, but every menu bar is still tied to a single frame. So what happens when we have two frames and only one menu bar? Menu bar will suddenly disappear. So how do we do this? How do we, how do we create the illusion of a system-wide menu bar? Because Java doesn't have one.

Basically, you can do a bunch of things. You can have one JMenuBar that you throw around every frame based on which one is in focus, and that doesn't work out too well. Believe me, I've tried it. And you could also have a menu, a factory sort of thing where you create a J, a new JMenuBar identical for every frame that you made. And, you know, you can I'm going to show you a little bit of what that might look like right now.

So I'm going to go back to... We don't need that anymore. I'm going to go back to that swing application we used last time real quickly. I'm going to edit my runtime properties again. Now, if you're using Project Builder, you don't need to worry about the screen menu bar property. It's actually set by default. And you'll probably notice that I turned it off because I knew I was going to come back here. And new screen menu bar is set to true, so maybe it's already there.

So this is what it looks like. Looks much more like a normal Mac application. And I can show you this as a contrast. This is our other application straight out of Windows. and this one has the menu bar tied to the frame. This one's up at the top. So everything's great, right? Not really.

So here's my second frame. I'm still in the same application. I just want to work on another document. Now my menu bar's gone. Well, what happened? So what's the best way of doing this? How do we solve this problem? Well, like I said, you can just make a factory. That generates a new identical menu bar for all of your frames and sets it to that frame when you create a new one. And this is half the problem. So here's my text editor.

And I'll create a new, another new, another new. So, all these JFrames now have menus. Now this is nothing really special. I mean, anybody who's done Java before has probably done some sort of factory thing. This is not that big a deal. And you know, of course it's functional. I'm not, I'm not a... I'm not bluffing you.

But what happens is it's very easy to just assign an identical J menu bar to every frame and have it work with all the actions. You get into the gray area where we have things like checkbox items and stateful things. So this is the autosave checkbox on the menu bar for frame two.

Now there's absolutely no reason For that to be checked when I go over to frame number three, because it's a separate menu bar, even though it looks the same. It's a separate menu bar for a separate frame. So what happens when we want to have application global things like this? Well, through the use of actions and property change listeners, which is what I'm using here, you can see that I check it in one window, it shows up in the other, which is very similar to how something like bbedit would work. And I uncheck it over here, it's gone. Check it again. So basically the state of these menu items is the same as it is in the other. And the state of this is being ricocheted through all the menu bars. So it really creates the illusion of having.

A single application global menu bar. And once we get into synchronizing state, we can have all kinds of fun with things like menu item groups for J Radio button menu items, and that opens the door for us to create another part of the Aqua HI guidelines, which is the window menu. So right here, I've got every one of these frames that gets created.

registered with this menu manager factory that is automatically adding these windows to the window menu. And of course it's adding them to all eight window menus because I'm moving across and these are all separate menus. So I can minimize, I can select this and bring it to the front and it will select the proper window. And this is all mainly property change listener and action signalization.

So if I do something like bringing this up, We can do bring all to front now, and we can do it only for windows that aren't in the dock. And so the cool thing about this particular sample is that once you conform to what this needs to do, and basically it needs to use actions, and actions are nothing non-standard, you make a single call to register your window with the menu manager as a developer who would use something like this. And the window menu just kind of does its own business absolutely for free.

There's nothing you need to do to state how you want it to behave, to state which window to minimize when I click Apple M or anything like that. And this will be up on the site as sample code for those of you who are particularly interested in doing a multiple frame. Mac Application in Java. It's something that shows up on the list a lot. So keep an eye out for that.

So let's move on and talk about the application menu. There are three general interfaces. You'll notice on Mac OS X you have menu with the application's name, There's an about menu item, there's a preferences menu item, and a quit menu item. And how do you take advantage of those? Well, you can implement these three interfaces. and basically implement the proper methods, handle about for the about handler, handle quit for the quit handler, etc. And then you register them with the Mac OS runtime using the MRJ application utils. Register, quit about, prefs, hamlet, call.

And basically what this allows you to do is do some handling when the menu item is triggered. You select about, you can bring up dialogue, you select quit, you can do some clean up work on whatever windows you have open, you do preferences, you can bring up preferences.

The only thing about this that you might want to do is, you know, most people, because there's no application menu on other platforms, a lot of people put exit in the file menu, for example. So if you don't want to, if you want to avoid confusion, you might want to place these special menu items conditionally.

[Transcript missing]

How would you keep compatibility if you were going to use these? Because these are Macintosh-specific packages. They're COM, Apple, MRJ packages. They're Mac-specific APIs. Well, we have a stubs jar that you can download from the developer website that you can basically include if you're building on Windows, if you want to deploy somewhere else. You just include the zip when you're building and when you're installing. And basically those calls will evaluate to no ops on a platform that doesn't have a Mac OS runtime.

Like I said, including these files will make everything work pretty well. So at this point, I want to bring Scott up, and he's going to talk about some of the native services that we have available to Java programs. Thanks, Matt. So I'm going to talk a little bit about the bundled Mac OS X services, and these are things that we've put into Java that are Mac OS X-specific services that we've given you access to from Java. You've probably seen these shown in a couple other sessions, so it's probably not new to you, so I'll kind of zip through them.

The first is we took the Carbon Text-to-Speech framework, and as an experiment we wrapped it in Java classes, and then we did all the work of doing the JDIRECT calls and things directly to that framework, and then hooked that up so that you can easily create a synthesizer and just give it text that you want to speak.

We also have the Carbon Speech Recognition engine, so you can actually use speech recognition in your Java applications if you want. We keep saying Carbon because that's where this came from, and if you saw Scott Forstall's keynote, you know that you can actually mix and match a lot of things from different services from different frameworks.

And so we're pulling some stuff out of Carbon, and then leads gracefully into the Cocoa Spelling Framework, which this is actually kind of a cool integration feature, because we took this Cocoa Spelling Framework, and the way it was integrated is we integrated it into JText panes and JText areas so that you could automatically just attach the spelling framework to your text panes and text areas and things like that.

And it's a couple lines of code for you, but you don't have to change all of your handling. We handle the way that we draw the red underlines and things like that. So it's a good example of how we can do that. It's a good example of how you can do this stuff.

Again, both are additions. The spelling framework is really the addition to Swing, but they're additions to the Java platform. And you can get them from connect.apple.com. We had some issues with our installers and we fixed those, so the new version should be up there and you should be able to install them and play around with them.

So I'll just show you a quick demo of it. I was assured that it was on this machine and we were all hooked up, so let's see. So this, I took Matt's demo program and just added to it the speech and spelling framework. A couple lines of code in all cases, basically. And so in this case, I could type in something saying, And I could say speak all. Steve Jobs doesn't like this voice.

And you can all be deafened by that. I understand why he doesn't like it. So that was just really simple. So all we have is this--all I did is I grabbed the text out of this text pane and threw it to my synthesizer. It was probably three lines of code. Speak selected, just as easy. Like.

Oh, that's not too big a space, but... Jobs, jobs. So that's really easy. I mean, it's just standard Java stuff. All I had to do was install our speech framework onto here, which is just dropping a jar in place. That's it. And then let's see. What else? So I can do--okay, so that's all for speech. For spelling, I can do things like misspell some words. That spells--that's better. And... And then I can say spell check all text.

And there we go. We just got underlines on all the things where we're, where we've made mistakes. And if I hold down the modifier key, which we, is gotten correctly on this, on basic swing stuff, and I click, I get contextual menus right here in place. And I didn't add this myself. This was all done in the, in the spelling framework that is what I installed. All I did was I said attach a spelling, attach spelling to this component, maybe one line of code, and automatically it's added to here.

There's nothing custom to this J text area that's in here. So I can also do things like I can turn on spell checking while typing. And if I remember this correctly, I can do As soon as I... There's some small characters it doesn't mark because it thinks you're doing acronyms, but when you start making mistakes and I can... Do that and just correct those in line and it should just correct them there. That's the whole thing.

So those are two examples of things that we installed that we've bundled for you in Java. Now, there's a whole bunch of other native libraries that you want to get access to. So you may have native libraries of your own. You may want to get to frameworks that already exist on the Mac. So how do you do that? And the standard way to do that in Java is to use JNI. And you want access to native code. You write JNI for it.

You run the JNI header creator, and you create all this glue that lets you get to C functions and all that fun stuff. It's very standard. It's not simple to do, but you can do it. A lot of people do it. If any of you saw the E-Beam demo, they used a little bit of JNI to get to the USB port because they wanted to use the native USB drivers because there weren't good enough ones available in Java yet. So they just had a USB driver, and they wrote some JNI, and the rest of their app is all pure Java, but they just have this tiny little bit that talks to it, and it ends up creating sockets for them for a USB connection.

And so this is a really good standard thing. And then we have JDIRECT3, which is specific to Mac OS X. And obviously you're talking to native libraries, so if you're talking to native libraries on Mac OS X, you already are platform-specific in some ways, so it doesn't hurt to use JDIRECT3. And it's really easy access to your native libraries. And the big thing is that you don't have to create glue to do this. We do the glue creation for you, so it's a little easier to handle there.

So a little talk about some of our old APIs. We talked a little bit, and we haven't really mentioned 1.4 at all, and we kind of want to mention it here in this context. 1.4 drag and drop has actually been improved significantly over our 1.1, 1.2, and 1.3 implementations.

And it's time for us to get on to the 1.4 drag and drop bandwagon. So we're planning on deprecating the MRJ drag and drop. What that means is we have some work cut out for us, which is we want to give you the functionality that's inside of MRJ drag and drop on top of 1.4.

So we're planning on extending what's in 1.4 to give you the multiple items drag that you get with MRJ drag and drop and interaction with the finder and that kind of drag and drop support. So we know you need that. We know we're going to give it, but we're going to give it to you as an extension to 1.4, and we're planning on deprecating MRJ drag and drop.

And then MRJ file utils. Those were a carryover back from Mac OS 9, and they handle things like type and creator setting and a lot of nine specific things. And we're planning on also deprecating these. And if there's anything specific in there that you need as another solution, we're going to extend the existing file classes and possibly make a new Mac file kind of object that talks about anything that's specific to files. But the MRJ file utils are kind of old and outdated, and they're sort of a source of problems for us on Mac OS X.

Back to Matt. Okay. Thanks a lot, Scott. Scott has been doing the marathon today. He's been presenting for three hours straight, I think. So, yeah, give him a hand, ladies and gentlemen. Scott Adler. Thanks a lot, Scott. So it looks like I talk too fast because we are already at our summary points. So what do we want you to take away from this? We want you to use Aqua.

It's pretty hard not to, actually. You need to do a lot of work to set a look and feel other than Aqua. So we would recommend that you don't do it, because we think it looks pretty good. And use the cross-platform programming techniques that I suggested. There are a lot more than the ones I mentioned. I thought I wasn't going to have enough time, so I cut some of them down.

And feel free to take advantage of some of the features we were talking about in Mac OS X. The ones that are specific, the ones that might be subjected to locking you in, go ahead and add them conditionally. So where do you go from here? You can get the speech and spelling frameworks as well as any seeds that might be coming out at connect.apple.com, which is the ADC website. You can use your Apple developer connection login and password. You can go to our developer Java section, which should be having some new documentation coming out with Jaguar. Be on the lookout for that.

And there's of course the Java dev mailing list. For those of you who are not familiar with the list and not using it, it's an excellent resource. There are a lot of really intelligent people on it who answer a lot of questions. You know a lot about Java programming on the Mac. Many of them don't even work for Apple.

and myself and Ted, who's another Java DTS fellow, monitor this list. We answer it also. And our engineers also are pretty actively posting to it when somebody's not breathing down their necks to release something. And of course, if you fell asleep during this session, I would be happy to answer your questions later at the low, low price of one developer incident with an email to DTS at Apple.com.

So, where can you get some more information? I already made a reference to the tech note on the developer website, and these are all off developer.apple.com. 2031 is the one that talks about all our runtime properties, everything that you can set to change things. A kind of print version of what we talked about today will be available on the web at the end of this week. It's probably a subset, but there will be the kind of code snippets that I mentioned here.

And we also have a newer MRJ toolkit stubs because with the Java 131 update that shipped, I guess, around February, we included support for the prefs handler, and that was a new addition to the Mac OS, and we didn't update the stubs yet. So the stubs are now updated. You should be able to get them off the sample code section of the developer website. Where do we go from here? You can go to Room C for Java Web Services. Tomorrow at 10:30. Tomorrow at 3:30, we have some virtual machine internals.

In Room C Friday, there's a Java performance section, which I believe is talking about things that you can do as well as things that we're doing to enhance performance of Java on Mac OS X. And very important, something that I hope everybody shows up to, is the feedback forum tomorrow at 5 o'clock.

We really want to hear everything that you have to say. People are usually very vocal and active, and I really appreciate that. And I would encourage you to continue. Thank you. And who to contact? Alan is the man. Alan is always the man. And he actually answers emails. Feel free to speak to him.