Main

GUI Archives

January 14, 2003

Automated GUI Testing

One of the buggest deals that people in my office seem to make about XP is the emphasis on Testing. (We could care less about Pair Programming, Iteration driven stuff, and the way they do story management, none of us including me really get disagree that what we have in those areas seems to work). But from all of the reading most of the supprot I have seen is foducsing on either object components or the lowest of the gui portions if even that. For the longest time I have been trying to find a good GUI test too I can integrate with the build, I think I found a hidden gem. But let's look at what's out there and why I didn't use it...

  • Abbot - Serious GUI bug in 1.4, that pane on the right you are supposed to put stuff like classpath and class name in? Doesn't work, won't remember the values or persist it to the model. Hence it is unusable for record.
  • Pounder - I forgot exactly why, but it behaved poorly for me out of the box. I seem to recall it used java.awt.Robot to do alot of the work, which would have been good or bad depending on what you are trying to test. But the use on Linux and the fact component sized change frequently would have been bad news for it. It also takes over the computer to take over the test and does it in real time, good or bad based on how you look at it. The other problem is that it records every stinking possible awt event that exists! Too much clean up on the test when you are done.
  • JFCUnit - The lack of a record option is a killer here. If I'm not going to design the grid bag container by hand I sure am not going to write the test cases by hand. Especialy since some of the GUI is dynamicaly generated and the structure of those components beneath that pane are difficult to derive by hand. Yea, there is aFAQ item that involved wriring your own but it took less effort to keep on looking
  • Jemmy - (a) Lack of JUnit Integration, and (b) Lack of a record option, see my entry on JFCUnit. (a) might not be such a big deal if (b) wasn't there and (c) I had infinite time.
  • Any commercial test suite - I don't know if anyone noticed out there but there is a recession going on. The cost for a autometed GUI test suite to use on the scale we want to (every developer that checks in code) it would cost us at leas one head count. I don't want to see any more of my colleagues leave, we've already gotten rid of the stinkers (and some of the good ones). That's why I'm being cheap about it.

Well, that seems to be the extent of the GUI test tools out there, and they've all got there blockers that encourage me to look elsewhere. Or is that all of them? In doing a google search on "Java GUI Test Tools" I stumbeled upon the mention of a java-gui-testing group on Yahoo Groups, where I learned about the hidden gem I previously mentioned:

  • Marathon - not perfect but Good Enough. Record option, junit playback, was able to get it working with my detateched test harness. Dosen't record random key strokes like I would like it to, but it referes to the JComponents principally by the setName(...) value you gave to it. It uses Jython to record the test and play back the test script. The API for the types of tests it has is a little limited, but the whole set of Java APIs are exposed so you can do whatever you need to inside of the jython script, so to add some custom valdiation logic you don't have to write a whole new stinking java class. And it integrates into my JUnit setup, with the tests showing up in the junitreport.

Good Enough, and much better than what I had before. What I had before was my memory and intuition of what I thought would break. But that tends to be unreliable under time pressure. Doing the same tests over and over again, and when it's automated you don't have to worry about the Intern or Script Monkey (which is not the same as a QA person) finding a better job!

Update : Glen posted about this sunday, and I learned that after I wrote this. So I didn't get to "out" marathon in the java.blogs community. But I felt my selection reasons and some more exposure would be good for marathon.

January 24, 2003

The Disappearance of the Consistent UI?

Damien noticed my entry on Netbeans does SWT!, I wonder if he saw my entry on Eclipse does Swing! Damien focused on an example from jgoodies about how Karsten made an ugly UI look more like eclipse. The point he wanted to make was how an emulated UI will never look like the "native" UI. Most of hose little nits that he mentnioned however are either fixed in the 1.4 release of java or are an artifact of the custom GUI (probobly because of drop shadows). But there really is a greater issue lurking beneath the surface not constrained to Java.

Remember when all GUIs used to look the same and be consistent? Think way back, think back even farther than that. Think back to the first release of most GUI shells for OSes, and for the first few demo apps released by those companies. Ever since then the GUIs have been changing, and as we get to the present day we have such wildly different looks and feel even from the same OS provider. On my Win2k laptop I am currently running Outlook XP. The toolbar and the menus are wildly different from, say, Internet Explorer. Same company using the same "native" windows look and feel. Even within IE with the right stylesheet arguments you can make the scollbar turn green and take up half the screen as well.

But what is the "native" look and feel? The skin on mozilla I use uses the same native look and feel, looks different from the previous two as well, and it uses MFC as well! I know it does because on my home machine running WinXP I get the nice rounded buttons and funky menus. What's different? Fonts, control borders, insets, margins, colors, etc. Does it look like the "native" widget set? No. But it is!

On WindowsXP not even the window borders are consistent, the command prompt being the worst offender. Microsoft is not alone in this: Apple is a pretty bad offender when it comes to that as well. You can have Platinum/Aqua/brushed metal on your screen all at the same time. I am sure if you tried hard enough you could even get pre-platinum system 7 as well. With the new X11 server you can bring in motif and whatever else you have on the Linux front. And Linux practically uses it's mildly controlled anarchy in the area of "native" widget sets as a marketing bullet.

Is this bad? Has the user sufferd uniformly because of this? No and no. Let me wax philosopical for a minute. Waht is a cow? I mean the most basicness of a cow? Do all cows look alike? Can we agree on one "perfect" form and look of a cow? Is there even one? What about male cows? Are they cows? Does the fact we have to distinguish them as male make them not cows at all or a special kind of cow? If we spent our entire lives living in a cave looking at a shadow cast by a clay figurene of a cow would we be able to recognize a cow if we then went outside and were being charged at by a rodeo bull? Ok, I may have went too far with the last one, but it is a classical question about categorization and characteristics. A point that I want to make that event though the GUIs are not all consistent what they are consistent on are some of the characteristics and idioms. Buttons looks like buttons, menu bars pop up menus, text boxes accept keyboard input, so on and so forth. But even with these items there are some differences. In MacOS you cannot have a button in a dialog gain keyboard focus (you cannot "tab" into it). And then there are other vendors who tried to do there own things with native UIs. Remember Borland's Object Windows Library? Think oversized green check mark.

So where I am going with this is to say that an argument that differences in the JFC PLAF implementation of a Windows look and feel means it is inferior is to say that all GUIs are inferior. It is an argument that is not specific to the JFC and can be applied to every GUI out there to varying degrees. Even the fangled spangeled SWT falls victim to this because there is no least common denominator between all of the GUI platforms it wishes to target. This is becasue some of the requirements of different GUI standards are downright mutually exclusive (the MacOS menu bar being one of the more obvious and flagrant ones). But GUIs have come to the point where for the most part they are consistently usable, if not consistently pleasent to the eye. Jersy milk cows and Angus beef cattle are still, after all, cows.

February 4, 2003

SWT Claims: Show me the money

Yesterday Jon Lipsky posted a nice real world comparison of Swing v.s. SWT. A Sun emplyee also had a rather lenghty comparison It looks like people are starting to verify some of SWTs high claims.

One of the biggest problems I have with SWT is that the implementation is not cross platform, but is a sperate undertaking for each platform. This leads to wildly differnt user experiences! The applicaiton I am baseing this statement is Eclipse 2.1 M4 build, under both Windows 2000 and Redhat 8 with the GTK build. The first thing I have to say is that the performance and user responsiveness is so different it's like I am using two differnt applicaitons. On Linux doing multiple ctl+clicks on the source tree takes about 2 second per click for eclipse to repsond to. I can get way ahead of the appplcation, and this leads to ghost un-selections because SWT gets confused. And then a tree update from a mass "organize imports" has massive flashing on the tree. Blech! But on windows it responds just fine. But both platforms still freeze updates to the GUI when doing large operaitons, like compiling the 1023 in my current project when I change one seemingly innocent preference about code quality checks. (As an aside, responsiveness is so importaint that Sun dedicated a entire chapter to it in their Java Look and Feel: Advanced Topics book.)

Another area is that by using the native widgets you immediately upen yourself up to inherent differences of user experience. Like adding jar files to the extrnal library list: on Linux you get a tree control where you can do multiple selections across directories. Windows gives you the standard one directory look. And on windows I can click a column top to get that column to re-sort automatically. Not so on linux, you got to use some wierd triangle menu to change the sort. Stuff like this is why a look and feel that is consistant across platforms is so good. If you don't need to behave the same across platforms then why aren't you writing it with kylix or C#? You get all the native widget goodness you need out of that. If you're going to whine about native performance use native coode then!

And then there is the unproven marketing hype, such as this gem:

The real question isn't about what results expert programmers can get using Swing vs. SWT, but rather what results *average* programmers will get using Swing vs. SWT. In this light, Swing doesn't compare to SWT. [ a comment on jason]

The though of threading your own event queue and disposing of your own object is going to make the *average* java programmer run away in fear. And then manageing all of the paltform specific GUI nuances is going to eat up whatever time they may have saveed assuming they have saved any. Since the person who wrote this is a vendor for an unreleased SWT GUI Builder the perhaps he will be able to show me the money. Then we can judge for ourselves when the product is released. It's got some stiff competition with existing mature tools such as the GUI builder in NetBeans, it'a like codeing a GUI in visual basic, except for the part where you write the visual basic, which is to say it's nothing like visual basic, but I digress.

February 20, 2003

Conflicting UI requirements

Here's another entry in the mutually exclusive UI requirements file:

If all the items in a menu are unavailable, do not make the menu unavailable. If the menu itself is still available, users can display the menu and view all its (unavailable) items. Similarly, if all the items in a submenu are currently not available, do not make the original menu title unavailable. [ Java Look and Feel Design Guidelines (emphasis added)]
If all items in a menu are disabled, disable its menu title. If you disable a menu item or its title, the user can still browse to it or choose it. You should include a status bar message, balloon tip, or other context-sensitive Help support indicating that the command is unavailable and why. If you use a status bar message, display it when the input focus moves to the corresponding item. [ Official Guidelines for User Interface Developers and Designers from Microsoft (emphasis added) ]

What sucks more is when you get a bug assigned saying that your app should behave one way after you've sepnt time explicitly coding it to behave the other way...

February 21, 2003

JTree Woes (or why src.jar is a ture gift)

Nothing is worse than inexplicable behavior. Obscure behavior is close, but decidedly better.

So I've got this bug in my GUI code relating to changing names in a JTree, basically the structure of the JTree stays the same but the length of one of the names of one of the nodes expands significantly at times. The problem is that the new text is not displayed! (or actually, only 4 pixes of the new text is displayed, for another obscure reason).

My natural inclination is to blame my own code, so I dig into the debugger and stop it durring a swing rendering of the tree (two moniters would sure be nice for this). The first rendeering is perfect. The preferred size on the second (larger) rendering is also perfect. WTF? So after a few failed attempts to move stuff around I think to look at the rendering Graphics object, and lo and behold the clip is set to the first rendering size! This has me really confused, becuse I never have to handle passing around the Graphics object and I have become used to trusting that the rigght clipping is set up (that's a magical black box labeled "Efficient dirty region rendering" in my world). So then I (properly) conclude the causal factor is outside my code. Too bad, 'cause I still have to fix it.

This is where I am truely thankful that Sun ships most of the Java code that comes with the JDK in src.zip. I can crack open the implementation classes and look around and find what the real culprit is: JTree is caching the preferred sizes of the tree nodes when it is drawing it, and it's called an optimization. When you are using straight GDM code on a 200Mhx Pentium MMX running Windows 95 I suppose that optimizations like that make sense, but that is, like, so last millenia.

The problem is that this is a faulty optimization, because it clearly isn't keeping up to date or allowing for a hook to change the size of the widgets. Fourtionlatly my diging around also gives me anoter clue: when JTree.setLargeModel is set to true these cachings are ignored. I've always wondered what that property did! But the documentation is so... vauge. It was a real.... bummer. Six hours of head scratching work and the A-Ha moment comes and all I have to show for it is one measaly line of code.

There is still one last mystery in this though: this fix requires largeModel to be true and for rowHeight to be set to a non-zero value. Using the Windows Look And Feel sets this row height automatically, but not for Swing, and for the life of me I cannot find that code in the Windows Look and Feel code. So I just set the value to a previously rendered value when I am done with my data load thread, and it's all good on Linux. So a total of three lines changed (the second change was quite long, and I had to wrap it onto the next line).

March 8, 2003

Use The Source, Duke!

As a continuation from my Problems with JTree I cam a cross another gem for the Obscure Java Nuances list: How do you override an existing keybinding on JTable to make it do something else?

Here's the real-world use case, I'm createig a frame that shows a long list of tabular data that the user may want to drill down on to get more specific info that what is available in the table columns, you know, like multi-paragraph data? So I gout the double and right click menu stuff wokring and while playing with it I came to the conclusing that a user using the keyboard to navigate the table may want to uset the enter key to bring up the dialog. Very standard situation UI... use the keyboard to navigate to the widget in question and press the enter key to interact with it. Simple enough?

So the obvious first course of action, use the NetBeans GUI editor to listen to keyboard events on the table and act when I see the enter key. Should be a 2 minut hack right? Worng. The listener will never see the Enter key typed action because of Input Map, Action Map, and the standard key assignments for JTable. In the spreadsheet work that JTable is based off of enter means "go down one row" rather than "do the default action." Which is all fine and dandy except for the fact that like any good UI I am perverting teh default compnent sets for my own purposes.

InputMap and ActionMap aren't a problem for me, I've used them before and it's merely a hassle writing a few more lines of code. Add the action, bind it to to the VK_ENTER KeyStroke, compile run and... WTF!? It's still going to the next row!? Drop in some code, so I see what I am overriding in the Input map, nothing, look to see what other actions are mapped in the InputMap, nothing at all. A quick internet search using the Google(tm) search engine service reveals that people are more interest in doing the oposite of what I am doing. At this point I heard a Alec Guinness whisper to me "Use the Source"

It never ceases to amaze me how when you are looking for the question to a very specific answer how much more information you can get from looking at source code for something that you may not understand than from reading all of the documentation in the world. The reason for this I assume is that no one can ever document every possible question a developer may ever have. However when you do something non-standard that should be a clue that you should document it.

Deep in the bowels of the basic plaf implemenation of the JTable UI in a method that hasn't been used since Java 1.2.2 I find the answer in a comment...

// We register all actions using ANCESTOR_OF_FOCUSED_COMPONENT
// which means that we might perform the appropriate action
// in the table and then forward it to the editor if the editor
// had focus. Make sure this doesn't happen by checking our
// InputMaps.

It turns out that all of the default key bindings for a JTable are stored in the InputMap for when it is an ancestor component and not the focused compnent. On deeper reflection it makes sense when you think of the cell editors and such. But without that information it is difficut, ney impossible to make that logical leap since it is at it's core a design decision.

So where is this documented? In the JavaDocs? No. In the JTable tutorials? No. In the default key bindings for JTable? Even though it would make sense no. Thank goodness that Java ships the source to exposed classes, or else I never would have made the leap. When all else fails... Use the Source, Duke.

June 14, 2003

Swiss Army IDE Problem

The approriately names BileBlog was spewing some bile about IDEs lately...

There's also the gui editor issue. I despise it, and will gleefully delete it from my plugins dir once it shows up there. It's such a shame that market forces demand junk like this. To be fair though, I have some sympathy to it being added as a lot of big companies demand bloated shite like this, so it makes sense from a business perspective. Although it's particularly amusing seeing the various comments that have been made about it. A whole bunch of 'well I never use swing but I tried it and blahblah' rubbish. Serious swing developers I suspect are likely to scoff and stick to using their own hand rolled magic. Still, I'm sure java needs yet more ignorant mediocre inexperienced developers dabbling in swing eh? [The BileBlog ]

There's a couple of things I want to address in this little bit. But Wow, in four short days he's spewed a lot of bile that really chaps his hide about java in gerenal. I've probobly got enough for three posts off of this.

Issue #1 : IDE Bloat. Yea, I've noticed this alot lately. All the IDEs need to have some fangleled spangeled tool to do the latest programming fad. Well based on what was said at JavaOne I'de say it's only going to get worse. The 20% that can do without it are probobly using Emacs or TextPad anyway. But if sun wants that other 80% to come over (you know: those other 7 Million developers they want coding in Java instead of VB) They live and breate by and IDEs slick add on tools. And they want it all in the same program.

The type of slick progams they want are stuff like the new Project Rave (and hardcore developers will yawn, principally because it's not for them). Be ready becuase if Sun is serious about those developers they will have to cater to their whims. We're talking about the corperate IT guys who only write software for their department and other such "internal use only" tools that extist because of VB. What's going to happen is that if developing something is not easy they'll put it back on their never ending stadk of stuff to do and work on something else or (more likely) use some other tool.

It's like dating: You'll generally go for what's available and (given a choice) you avoid stuff that's difficult to deal with (or go without). And if it dosen't fulfull your needs you're likely to move on. Sun wants Java to appeal to the lowest common denominator by being flexible, without attachment, and easy!

June 17, 2003

GUI Design Tools are Not Just for the Weak

Now on issue #2 that I see with monsuier BileBlog's rant on IDEs. The most relevent poriton of that previous quote is as follows.

Serious swing developers I suspect are likely to scoff [at IDEA's GUI designer tool] and stick to using their own hand rolled magic. Still, I'm sure java needs yet more ignorant mediocre inexperienced developers dabbling in swing eh? [The BileBlog ]

I suspect that he's never done serious Swing development, I also suspect that a serious OSS developer would use an an OSS version control system as well (and by suspect I mean "I'm speaking out of my ass here"). There is no doubting that hand-rolled magic is sometimes the only difference between a sophomore CS project and a shrink-wrapped product. But if I were going to write a GUI in nothing but hand-rolled magic I would need at least two to three times the schedule to accomplish it.

Why? Well, as I blogged nearly eight months ago productivity matters. There are times that you want to spend a lot of time tweaking the little tidbits, and there are lots of times you could honestly care less. That's why I like start out in the GUI designer rather than blank java class. Yea, I could do all the GridBagLayouts by hand. I could also make the vertical FlowLayouts line up nicely inside multiple BoxLayouts by hand, and I could even write my own layout manager to deal with my personal nits if I wished (in fact that was one of the first things I did with Java GUIs more than seven years ago). But why should I visualize the insets, gridwidths, and weightxs in my mind when I can visualize them with my eyes? GUI designers also speed up the tweak/compile/run loop we all get in just to see if you got a titled border on the right component or to see if you fill propertu on a component needs to be GridBagConstraints.HORIZONTAL or GridBagConstraints.BOTH or whether that box layout looks silly with an alignmentX of .96.

GUI designers are not just about layout stuff either (something the reviews indicate the IDEA designer focuses on exclusively). It's about basic wire-work as well. Do I really want to write the boilerplate code to attach some method to a actionPerformed listener added to a JButton or would I rather jump right into the code preping the data for the SOAP call? (the latter, because it's gonna have to be written anyway). When code is truly boilerplate (like button presses and menu selections) and can be automated it should be, wether it's as a language feature, an API convienece, or as a feature of the development tool.

Believe me, there are many times where hand-rolled magic is the way to go. But that time is not when you are saying "JTree here, JButton there."

June 25, 2003

Know Your Role! (But Fill in Where You're Needed)

Some discussion has been happening recently about programmers and GUI design. One particular thread had to do witht he bifurcation between what I will loosley call Graphics People and Coding People. Two overly broad generalizations I know, but when you are looking at the perspective of creating a UI for an application subtleties like database/build/swing coders and artists/layout/graphic designers. Sometimes it's good and sometimes it's bad. Jon Tirsen had a bit to say about this. What I want to blog about is specilization in the development process.

But first I'm going to start talking about some of the small details about the US Army. The Army has about a bajillion job assignments called MOSes. These range from combat roles like eliete special ops and calvary scout to support roles like MP, cook, and decontamination specialist. But despite all of these specialization all must go through the same basic training even though their advanced training is much different. One of the reasons for this is so you can expect some basic skills out of anyone wearing an army uniform, namly you can give them an M16 rifle and expect them to be able to use it with some basic proficiency. At the same time you aren't going to expect an Army Ranger to beable to act as an advocate at a court-marshal and you woudn't want an MP providing cover fire from an Apache LongBow. But when a defensive line falls and headquarters is under attack you want to be able to hand everyone in sight a rifle and have them defend the camp.

So how does this relate to GUI work? Code types and Graphic Types represent two broad specializations when it comes to making an application. Unfortionatly this can lead to what Jon wrote about where the specializations become a class segregation. Situations like that are definatly bad. However I don't think the world of total equivilence is a good realm to live in. There needs to be some form of specilization if for no other reason then some people are better at some things (through training or talent) than others. The people who know how to make a graphic design look essentialy the same across 4 different browsers probobly aren't the same people who know how to ensure the cache consistency of the data behind the page and how to prevent double posting of forms.

This generalization is a two edged sword however, you may need the graphics people and the data people to do stuff others specialize in occationally. Perhaps they are on vacation and a new icon needs to be made, or an HTML page needs to be re-done for new data. A coder type could do it if needed but given the choice a graphics type would be better. Perhaps a field on a form needs to accept a phone number with dashes in it but strip it to just numbers for the database before submission. A coder type may be perfect for that but perhaps he has some nasty synchronization bug he's dealing with so the graphics person has to do some text processing and data tricks.

More and more projects now a days are much to big for one person to possibly do everything even if time wasn't a factor. That's why we work in teams. Nearly all teams have specilized roles, but it is the effective team that knows when to live within those roles and when to step outside of them.

June 28, 2003

Use Resource Files for GUI Text

This may seem like an obvious statement for people who do a lot of GUI work, but I will say this because it simply cannot be said enough. Don't hardcode strings! That falls into the good old "no magic constants rule" (unless that constant is the 32-bit signed int -1258207934). How do you go about it?

  • Take all your strings and save them in some file that is not part of your main code. There are several options: you could put them all in a code file full of constant values, you could put them in a properties file, or (my favorite) you could put them in an internationalzied resource bundle.
  • Use meaningful names. SC_EN_000854 may be just the same to a compiler as LOGIN_DIALOG_LABEL_USER_NAME, in fact it's shorter and probobly compiles just a millisecond faster. But take my advice: use the human readable form
  • Use some consistent strategy to create these names. Ther are at least three things it should include: what part of the application it's in, what particualr GUI element it applies to, and some indication of what it says. The order doesn't matter and you can even use short varients or (for location and type) encoded varients. But be consistent! The previous exampel could just as easily be LB_D_LOGIN_UID if you are coding it as type/location/meaning.

So why are these importiant? You mean I can't say "that's just the way you shold do it?" Ok, ok. There is a point to this blog entry rather than random rules. Why do I consider this importaint? Any guesses? Umm... you there, yea the one waving his hand up and down and shouting out "internationalization," you can sit down and calm down because you're wrong. Yes it is a very nice side effects but I think there are better reasons. You there, on the front row. "Maintainable code?" Well, it is maintanable code, but that's not the only reason we do it. Anyone else? How about you. Yes, the cynical one sitting in the back corner. "Management!" Ok, close enough, I'll take it.

It's not just management; it's tech writers, QA, marketing folks, and even other coders with better grammer and speling skills then you. To be more precice it's everyone else who wants to put their fingers in the GUI that isn't actually writing the GUI code. If you mis-spel a word and the strings are all over the code good luck finding the string. You could just search on the mis-speling and fix all occurances of that one. But in those cases people only catch the problems they can see, so the biggest stinkers may get over looked because they don't come up that often (for error dialogs they may never come up). With a centralized set of string files you can run a spel checker over it, but don't try this with java code bacuse signal to noise goes down. You can even hand it off to someone with linguistic skills who can fix all the bad grammer as well. Oh yea, I almost forgot. It's easier to internationalize as well, but you'll probobly have the other problems sooner if you are in anything but the smallest development teams.

Even though my reasons for this are entierly prgamatic it won't end all the problems. While some people care about colons v.s. hyphens for separator cues others care about what shade of grey the background is. Should it be windows grey, swing grey, or bike shed grey?

July 1, 2003

Apple UI Requirements: Apart from the Crowd (Again)

The long list of appleisms in the Aqua UI go on and on. apple seems to pride itself with these quirks but when they are subtle they can lead to user confusion. The subject of today's abuse is the ellipses in menu items.

What? There are ellipses in menu items? You mean just randomly? No, ther actually is are very intentional time they are added to the end of menu items. Genearally they are used when selecting the command from the menu alone won't finish the command. Go ahead and look at the File menu of the browser you are in. Close and Work Offline are commands that just suddenly work. Save As and Open do have the ellipses because you need to enter the name of a file or page to finish it.

But let's say you had an item on the menu "Crash Browser" (in Netscape 2.0 this was accomplished with complex javascripts). As a good UI since the command has potentially sever effects dialog pops up asking "Crash Browser: Are You Sure?" So should this menu command have ellipses? On Gnome, Java, KDE, and Windows, yes. On MacOSX, no.

Label the menu item with a trailing ellipsis ("...") only if the command requires further input from the user before it can be performed. Do not add an ellipsis to items that only present a confirmation dialog (such as Delete), or that do not require further input (such as Properties, Preferences or About). [ GNOME Human Interface Guidelines ]
Ellipses (...) are punctuation marks that indicate the omission of one or more words that must be supplied in order to make a construction complete. In your menus, you can use ellipses in a similar way: to indicate that the command issued by a menu item needs more specification in order to make it complete.
  • If a menu item does not fully specify a command and users need a dialog box to finish the specification, use an ellipsis after the menu item. For example, after choosing Save As..., users are presented with a file chooser to specify a file name and location.
  • Do not use an ellipsis mark simply to indicate that a secondary or utility window will appear. For example, choosing Preferences displays a dialog box; because that display is the entire effect of the command, however, Preferences is not followed by an ellipsis.
[Java Look and Feel Design Guidelines]
Notice that every item in a menu that first opens a dialog requiring additional information must be labelled with a trailing ellipsis (...) (e.g. Save As..., Open...). There's no space between the menu item and the "...". A simple confirmation dialog is not considered a dialog that requires additional information. [KDE Standards]
However, not every command that results in the display of a window should include an ellipsis. Do not include an ellipsis for commands that simply display a window or view or change the existing view within a window. Similarly, do not use ellipses for commands that display a collection of objects or options, unless the intended action requires that the user select or confirm the selection of one or more elements of the collection. Also, do not include an ellipsis for commands that may result in a confirming message box. [Microsoft Windows User Experience]

Java comes the closest to no explicitly prohibiting it, but it is a very long stretch to say that a confirmation dialog is "more specification." And What about Aqua?

An ellipsis character (…) after a menu item or button label indicates to the user that additional information is required to complete a command. You should use an ellipsis in the following cases:
  • An action that requires further user input to complete or presents an alert allowing the user to cancel the action. Examples include Find, Go To, Open, Page Setup, and Print.
  • An action that opens a settings window. The main function of settings windows is to allow the user to change some aspect of the application, not the document content. Examples include Set Title, Preferences, and Options.

A very long wided debate can be had about where ellipses means "not done yet" vs. "window coming" (and I am sure at some point they had one or more of those in Cupertino), and if someone was determined to make their app behave properly on Apple they might consider changing the text when an Apple platform is detected. But that's just too much effort for a subtle cue that most users probobly miss anyway.

July 3, 2003

Do Your Homework! (UI Standards)

Anyone remeber the (sometimes contentious) debates on software teams about coding conventions? Tabs vs. spaces, two space vs. four space vs. eight space indents, curly braces on same line vs. a new line, braces for all control structures vs. only where explicitly needed. You could probobly go on and on about what the little nits are in formatting your code. That's why coding conventions were invented; Apache, Sun, and GNU are just a few of the conventions that come to mind.

But if people get up-tight over stuff the end user dosen't see you'de think there would be a lot of demagauging going on in larger organizations where the UI is a seperate team entirely separate from the core of the applications. Well, there isn't as much mostly because codified standards do exist in what the user should see and how they should interact. Most of these standards deal with low level controls and widgets, but do address higher level concerns. Here are a few that I have found on the web.

Of course none of the ones I've found (or for that matter looked for) deal with web page design. That may be a bias on my part that web pages should be content and not a full featured applicaiton. But the idioms and patterns for interacting with and developing a page at a time system are quite different than a "rich" applicaiton.

Another thing I've found interesting is the widly varying level of depth that each standard goes into. For example the Microsoft standard (and to a lesser extent the Java standards) goes into pixel level counting and positioning, while others merely make mention of the screen size and don't address pixel level positioning. They all do have some basic overall usability principals that drive the desicions that are addressed before they get in to the sometimes arbitrary rules. And they all (at least now) say Multiple Document Interface (MDI) bad, Single Document Interface (SDI) good (although Microsoft's take is "MDI bad, but if you're doing it here's how it's done").

Of course the down side of following a standard is that when using one to justify design decisions you are bound to pretty much the whole standard. You cannot just bring up standards when it helps your decisions but ignore it when you disagree with it.

July 7, 2003

How Would You Like Your Three Panes?

Diego is considering going to a different three pane layot for the next release of Clever Cactus (a java based PIM/Mail application). The old school of three paned navigation was useherd in by Netscape Communicator's e-mail program, and Outlook and Outlook Express lead the charge. It is now such a common idiom that almost all off-line rss aggrigators use the old school three pane navigation of channels on left, news item summary on the top right, and the full news items on the bottom left. The new trend seems to be to left middle right three panes. FeedDeamon defaults to three column, and the betas of Outlook from the new Office Betas start out in three column view. Diego is considering going that rout for Clever Cactus and has spent Another weblog entry hashing over more of the detals. However I am of the opinion that three column navigation won't fly. Why?

The most importiant issue in my eye is the issue of the center point. Like a fine piece of art, the content in a gui window should draw our eye to the most relevent or used area. The middle (actual middle or precieved middle) of the window should contain the most used window in the applicaiton. In the three column layout that is going to be the level 2 navigation, not the content pane that is going to be banished to the right side of the pane. Which for western readers the right side is the side most likely to be ignored. (Theater and broadway musicals use this fact to great effect). But there are other areas where we are trained to focus on the middle column of a three column layout. Look at most weblogs out there, most either put perifiery information to the left or the right of the main entry, and some put the info on both the left and the right, even Diego's own weblog uses three columns and places the most relevent content in the middle. Most (all?) modern software IDEs follow this ideal as well: the main editing pane tends to be in the middle while all of the auxiluary informational panes are scattered around the left, right, bottom, and top. It's BorderLayout to the extreme.

Another issue is that a usable three column layout requres a lot of horizontal real estate. We don't all have 16:9 apple cinema layouts so we have to deal with the 4:3 layout of most monitors. And not veryone likes to run every application maximized. About the only application I maximize is NetBeans, and that is because there is usually a lot of non-linier information I need accessible at once. Everything tends to take up about half to three quarters of the horizontal space with the widest content pane taking up about a half of the real sceen space. All the windows also take up 75% to 90% of the vertical space. By adding more horizontal exclusive space it requries me to widen my window.

It also adds more un-needed information to the window. I don't need to see all 30 options on the second level of navication, I am almost exclusively intereted in the top few from that stack. And the few time I do need that space in outlook (usually when I am seraching manually) I tend to make the preview pane much shorter. But as long as the current item is focused in the level 2 navigation I can minimize the needed space to use that level.

Finally it's been tried before. NeXT tried it first and moved it to early builds of the Aqua interfaces and there moans and moans of how hard it was to use. Part of it may have been resistance to new stuff in the new MacOS but if you look at all of the other UIs apple has done since basically none of them do what the NeXT finder did. Russ posted a bunch of GUI links to modern mac applications put out by apple and none of them do a three column layout left to right. All of the main content panes are large and take up the center point. In places where this represents a third level of navigation either the first pane is not shown or it is done where the panes are top left, bottom left, and center-right.

If any new direction in Clever Cactus should be taken perhaps it should be the TL-BL-CR format, with multi-line rows (like quicken or palm's versa mail) containing the second level navigation items. Three column just dosen't float my boat.

July 8, 2003

Interface Modes, Fitt's Law, and the Menu Bar

I've been reading Jef Raskin's book The Humane Interface and he has a big section about how modeless interfaces are a goal yet a few chapters later he discusses Fitt's Law and is ravings and how wonderful the Macintosh menu bar is WRT ease of use with a mouse. The problem is that while being an glowing example of Fitt's law the menu bar violates modelessness.

First let's address Fitt's law. Fitt's law says that the expected time to perform a gesture is directly proportional to the distance traveled by the cursor and inversley proportional to the size of the target area. A big button close is quicker to click then a small button far away. The arguement goes that since the menu is at the edge of the screen the vertical dimensions of the menu items are essentially infinite and thus easier to move the cursor to the menu from a greater distance. Once you become familiar with the interface you don't look at the menu as much as you just remeber how to move the mouse to get there quickly.

The issue of modality however is can be technically argued away in Jef's two part definition of modes. The second part essentially requires that the same gesture does two different thing at two different times for the interface to be modal. In this case clicking at 100, 0 (or thereabouts) bringing up the Foo menu. Where the entire Macintosh UI creates one huge mode shift is in the treatment of the menu bar. Depending on the application whose window you have focused (or just closed) the menu bar is the menu bar for that application. So the menu at 100, 0 could be wildly different between applcation. A team Jef was on was once so obsessed with removing a mode from a computer that they even designed a computer without a power button! (Engineering was convinced it was an error in the spewcification and put a power switch on anyway.)

But then there is the second part of the modality definition that starts to break down this paradox: "the current state of the interface is not the user's locus of attention." If you are selecting a menu clearly the locus of attention should be the menu. Also the window you are looking at should be a locus of attention just before the menu item is selected.

But let's go back to how you interact with th system once yoar familiar with it. It's the ability to go to a menu item from "memory" that indicates the fact the locus of attention is not the menu bar. It's this interaction that makes the menu bar modal. It's not a non-recoverable error either, because no commands are really supposed to be invoked from a single click of the menu bar the user will have to focus attention on the drop down menu. So before any command occurs the user will realize that the menu bar was in a different mode.

It seems then that the bashing other windowing systems get for attaching the menu to the window is only half deserved, since by being less efficent with Fitt's law they are less likely to be subject to accidental user mode-based mis-gestures. Fitt's law may allow the menu to be brought up faster, but that is at the risk of modal user-errors.

July 10, 2003

SWT: I Still Don't Get It

The lone programmer blogged about my old entry on SWT claims referring to it as a "short critique." I think he was being kind, it was a rant all the way. But his entry reminded me of the old saying "If all you have is a screwdriver everything looks like a screw."

I find it kind of funny that he almost admits that SWT sucks on GTK and Mac OS right now. And then he continues to defend the native widgets of SWT by saying it grants "consistency between the apps on a particular platform." News flash: SWT widgets are normalized across platforms just like swing widgets are. And swing provides the same native client look. Have you seen the new XP look and feel in JDK 1.4.2? It looks just like windows themes, and it even keeps up with arbitrary changes. Why? It gets it's UI painting resources from the native OS DLLs. That's one big reason you won't see it do XP on Win2K, the theme information Java needs isn't in Win2K. With SWT you do get native widgets, complete with slow table re-draws.

But this brings me back to my screwdriver argument. If you want native cool thingies like Mac OS dock integration, sliding accessory windows, windows notificaitons, balloon help, Linux GNOME panel integration, etc. etc. Use the right language! (or at the very least the right APIs). You want all those slick dock integration APIs? Use Objectve C and the Coca APIs. You want Gnome panel integration? Use the Gnome APIs in their particualr language (C, Python, Perl, or Java-GNOME) . You want neeto-skeeto integration with Longhorn? Use C# (but that may make you part of the problem). Just because it can be approximated in Java dosen't mean that you have to use Java! Use the right language for the task. If platform specific features are essential to the user experience use the tools designed to deliver that integration.

Jeez, it seems that Java is a religion. I just hope that they don't start refering to people at java conferences as "the faithful."

November 15, 2003

The many lives of javax.swing.Action

Gregg Bolinger been using swing for a while mentioned in My Approach to Menu's in SWING about how he extends and uses the Swing action alot. After being buried deep in Swing for nearly two years now I have to concur: Actions are more importiant than you may initially think.

For the Swing code I've written at my job I use Actions to back the actions of menu items, toolbar buttons, popup menu items, some of the regular old buttons, and even handeling Drag and Drop actions too! (Since the drag and drop is another way to invoke a menu action I just wire in the call to the actions for a successful drop).

Like Gregg I've overloaded abstract action, but I've gone crazy with stuffing in the standard behavior. First I populate all of the action values from a resource bundle. This allows for easier I18n of the action and it also keeps a lot of the related actions visual looks in the same file. This is handy when someone decides they don't like the menu accelerators you've selected or that all of te Icons need to be re-done and stored in a differnt place Next I populate a large amount of standard information into the value cache of the action itself:

  • Name
  • Location in the Menu Bar (i.e. file/new/widget or help/about
  • Location in the Tool Bar
  • Location in standard Pop-up
  • Toggelable (creates checkbox menu item or toggle toolbar button)
  • Asynchronous (spins a thread for the action)
  • Icon (along with rollover and selected varients)
  • Tool Tip
  • Mnemonic
  • Accelerator

And that's just what I can remember early in the morning on a weekend. I also provide standard methods to get a menu item and toolbar button out of the action so I can handle things like the checkbox menu items and global options such as show/hide menu icons and tooltips. I also try and limit any code that does any user initiated actions to live in the action methods of these objects.

By doing this it keeps a lot of the non-gui code out of the gui and I can stress out about bizzare JTable behavior without tripping over a database call to delete a row.

November 24, 2003

Thick and Rich Like Snickers Cake

It appears that I've been getting some drubbing over what I call thick and thin. One coward who wouldn't leave a real name in the comments section stated that

Are you implying the Swing == thick ?????
This is completely false.A Swing client could be thick or thin.

One of the things I learned in school is to make statements that don't contradict themselves, like calling something completely false and then immediatly stating that part of the time it is true. This is predicate logic, typically covered in the sophomore year of most CS departments, which the responder must have been too drunk to remember. Mr. "Look at me I'm Anonymous!" should have just said that my choice of words was imprecise in his opinion.

Neil kindly pointed out that Sun has been using the term "Rich Client". I always thought that term was a reaction to the (formerly) negative connotation of a thick client, when they were client/server applications (such as your typical PowerBuilder app). Perceiving it to be marketing fluff I had quickly expunged this term from my vocabulary. But the lines and definitions between thick and thin are getting very blurred and stuff like WebStart is even obliterating some of those lines.

But sometimes things can be too rich. If you ever cook a Snickers Cake be sure to use semi-sweet chocolate chips instead of milk chocolate chips. That was a little too rich and thick.

April 8, 2004

GridBagLayout, Best Done Visually

When Eclipse first rolled out their visual editor there were a couple of things I didn't like. The first was something that I had grown accustomed to in NetBeans (mostly because I saw how much it failed in Visual Cafe). The management of the components was not managed by a seperate code area or data file but it is extracted from the source and compiled code. What a recipe for screwed up code. What NetBeans does is it manages a <foo>.form file next to your <foo>.java and uses "guarded blocks" to render the meaning of that .form file, blocks you cannot edit directly. However you can render and insert code anyplace in that process (via the properties sheet) if you are an absolute control freak. It was hard to get used to initially, but for writing GUIs I think that it is the way, ultimately, to handle GUI writing in an IDE. What Eclipse is trying to do is Two-Way Editing, which I've never been able to be a well behaved enough coder to live with. It's usually turned into two way farking within the first ten minutes of use, and that's the ten minutes I decide that what I have is better.

That problem was a little annoyance compared to the second major hole in the Visual Editor, one that alan also found. This crippling problem is that there is no support for GridBagLayout. This is more than "a little way to go" but is a gigantic hole right in the bulls eye IMHO. I knew that this was going to be an issue when the demo video for the Visual Editor totally glossed over layout managers and went straight to absolute positioning. Absolute positioning is bad. It lives in that 20% of the 80/20 rule: the 20% that is english/windows/defaults only. Of course I am not targeting the 20% of the market that is english only, windows only, and default graphics setup (that other 80% either uses a non-windows platform, a language other than english, or they do things like crank up their font points). NetBeans does have a GridBagLayout editor, and a good one to boot. In fact if it didn't have one I may still to this day be a "code GUIs by hand" bigot.

Thank goodness for quality tools.

April 9, 2004

Make your MFC Apps look like Metal?!

Some people see beauty in the strangest things, like this abandoned project to provide MFC controls that look like Swing Components. It is four years abandoned, but even four years ago the author refused to make the fonts bold and use the horrible Lucida fonts.

That fonts are the biggest problem with the swing look and feel, even more than the "Owe my eyes it's purple" color scheme. So why did the ocean theme just fix the colors and never the fonts? That's going to make the ocean theme the least used new feature of JDK 1.5.

May 17, 2004

Groovy, Verbosity, and Swing

While I was on vacation in Hawaii Jonathan Simon lamented about how people still aren't getting it.. I think that the single biggest problem creating the misconception that swing is slow is that people don't understand or use threading on their GUIs. Two main problems exist. First any event you handle is inside the event dispatch thread which is also responsible for painting the GUI. Second, practically any manipulation of a JComponent must be done from within the event dispatch thread. Practically a paradox, but it can be dealt with.

Consider an action event that updates a label named jLabel with a string value from a long running method called takesTenSeconds. You may be tempted to do something like

public void actionPerformed(ActionEvent e) {
    jLabel.setText(takesTenSeconds());
}

but then you violate the first rule: no long running calls in the event thread. With anonymous methods it can be handled however...

public void actionPerformed(ActionEvent e) {
    (new Thread(new Runnable() {
        public void run() {
            jLabel.setText(takesTenSeconds());
        }
    }).start();
}

That's some progress. But we now violate the second rule: Don't use thread unsafe methods on JComponents or mess with models they use. In this case it will not be a problem, but when you start with JTrees, JTables, JLists, JComboBoxes, and the like you can create these lovely stack traces to system.out involving concurrent modification, null pointer, index out of bounds, and other stuff that looks bad to QA and clients. How do we fix this?

public void actionPerformed(ActionEvent e) {
    (new Thread(new Runnable() {
        public void run() {
            final String newText = takesTenSeconds();
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    jLabel.setText(newText);
                }
            });
        }
    }).start();
}

A code snippet that a random VB developer would assume is one line morphs to 3 times it size in characters and (depending on your codeing style) 10 lines in the code. Even with another utility method for the background call we have to make two runnable classes, whether anonymous, inner, or stand alone that's a lot of code bloat. What would be nice is a more concise syntax for a runnnable. Enter Groovy and closures. This can be made much smaller with the creation of a few simple utility closures...

invokeAndWait = { SwingUtilities.isEventDispatchThread() ? it() : SwingUtilitites.invokeAndWait(it); }
invokeLater = { SwingUtilities.invokeLater(it) }
invokeOutside = { SwingUtilities.isEventDispatchThread() ? Thread.start(it) : it() }

From this, the proper way becomes much shorter...

invokeOutside {
    text = takesTenSecondes()
    invokeLater { jLabel.text = text}
}

With some tweaking on the sample closures it could probably even be reduced to...

invokeLater { jLabel.text = invokeOutside { takesTenSeconds() } }

I think that the greatest problem with the swing APIs are not that they are too complex or too poorly explained. The biggest problem I see is that to do simple things the correct way, it can get quite verbose. Kind of like reliable file I/O, but you get far fewer urgent-1 bug in the GUI than in core I/O routines. Perhaps the best thing isn't to change the Swing APIs, but to add more syntactic sugar.

May 25, 2004

Extending Swing via Listeners

With a framework as nimble as Swing there are many ways to skin a cat. This is possibly one of the sources of many complains about Swing. For example Sam Dalton wrote a class that implements a dialog that closes when the escape key is pressed. Subclassing JDialog is certainly one way t do it, but I probably would have simply wrote a utility method...

static void makeDisposeOnEscapeKey(final RootPaneContainer rootPane) { Action action = new AbstractAction() { public void actionPerformed(ActionEvent arg0) { ((java.awt.Window)rootPane).dispose(); } }; KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); rootPane.getRootPane() .getActionMap() .put(action,action); rootPane.getRootPane() .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(stroke, action); }

A couple of changes reflect my swing codeing preferences. First, I call dispose() instead of hide(). My reasons are twofold: first until a window is disposed it takes up native graphics resources, and can essentially be a big memory leak until the object becomes inaccessible and is finalized. The second reason has to do with a clean JVM exit. While any AWT resources are realized (i.e. have native OS resources allocated) the AWT event thread will keep running and the JVM will not exit. If all of the windows are disposed() then the AWT event thread will enter a state that will allow the JVM to terminate. No more calls to System.exit(0).

The second thing I changed was which action map I put the escape key in. Sam used WHEN_FOCUSED which is fine if there are no focusable components in the dialog. But throw in a button or text field and the action may never get fired. There are actually two options here, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW. I chose the latter because this is also how the JMenuItems register their accelerator keys and the desired operation is essentially the same. Since we are adding the action to the JRootPane there are no differences between the two.

By using a utility method we can also add this behavior to any free standing component. One of the issues Swing has to deal with is that higher up in the AWT hierarchy dialogs and frames were separated. To deal with this they created an interface javax.swing.RootPaneContainer so that they can treat all root level components the same. Hence this behavior can be added to any JFrame, JDialog, JWindow, JApplet, or JInternalFrame.

And please, if you have obnoxious splash screens either have a user preference to turn it off or add this to the JWindow so the user can click it and press escape. Wouldn't that be nice.

May 27, 2004

Swing and Groovy: Low-Carb Coding, not Syntactic Sugar

Use Groovy and shed KLOCs over night. Sounds like some advert for the latest weight pill, but here is some empirical evidence. I was able to re-write the ButtonDemo.java section of the SwingSet2 demo that comes in your JDK distribution with about one third of the source code lines and one half of the total characters.

There are two principal contributors to this amazing weight loss* (YMMV of course). The first and IMHO nicest features is the use of closures. For those of you who either didn't major in Computer Science or suppressed the trauma of the sophomore year functional programming classes you may wonder what closures are. Closures are a very particular name for a very particular type of "first class function," or way to confuse the code segment and the data segment. They are very tight and concise, and most importantly can be assigned to specific event listeners in less than one line of code. And most importantly, Groovy closures look like simple java blocks.

Another feature allowing for the compression in size is the way the SwingBuilder handles JavaBeans properties. It looks like a constructor taking some sort of a python type dictionary as the arguments, but really the code that is generated is to call the default constructor and set the specific bean properties after the bean is constructed. It allows for readable compression of setting multiple properties in one line.

The demo is currently waiting to be added to Groovy itself as a sample, but here's a quick comparison of Groovy vs. Plain Java setting up the "Enabled" CheckBox on the right side of the demo to give you a taste.

checkBox(text:"Enabled", mnemonic:'E', selected:true,
  toolTipText:"Click here to enable or disable the buttons.",
  actionPerformed: { event |
    btns.each { it.enabled = event->source->selected } } )

Groovy is 3 or 4 lines depending on what your end column is set to

JCheckBox enabled = new JCheckBox("Enabled");
enabled.setToolTipText("Click here to enable or disable the buttons.");
enabled.setSelected(true);
enabled.addItemListener(buttonDisplayListener);
enabled.setMnemonic('e');
// nearly 45 lines later in a different method and
// an anonymous nested class
public void itemStateChanged(ItemEvent e) {
  JCheckBox cb = (JCheckBox) e.getSource();
  if(cb.getText().equals("Enabled")) {
  for(int i = 0; i < currentControls.size(); i++) {
    c = (Component) currentControls.elementAt(i);
    c.setEnabled(cb.isSelected());
    c.invalidate();
  }
  // code for other buttons

Plain Java is 10+lines, not counting comments. Plus the code doing the checkbox action isn't interrupted by 40+ lines of other code. I am really starting to like Groovy alto and I am sorely tempted to actually use it in shipping code, but I plan on at least waiting until it is declared 1.0 soup and not beta.

June 24, 2004

JDNC and the SwingX Project

After a year from when it was announced finally we see something from the JDNC project. Let me say I think it has a brighter future than the JSF project. Web Clients have their role, but just like Television Actors sometimes they overextend themselves. On a quick pass it looks a whole lot like XAML will be for longhorn, except you don't have to wait until after the Star Wars Episode III Special Edition DVD is out to use it in production.

But I am straying from the point I want to make. XML is the topmost layer of the JDNC project. What I am more excited about is the standard swing component extensions, which comprises the lowest layer of the JDNC project. For the level of Swing that I have been coding at those provide the most tangible value today. Why? Couldn't I just write or fork a TreeTable or Form interface of my own? Yes I could, and it would forever live inside the walled garden that is proprietary apps. Don't get me wrong, I've already done it for a DataPicker widget. But what this offers is a common standard extension to the swing components from Sun, one where the components might one day make it into the JDK.

Back when JDIC was announce I nearly wrote an article calling for a STSC project: Standards Track Swing Components. Some collector project on java.net where common swing components could try and evolve in some sort of a standard environment and possibly be included in the standard J2SE one day. It's much to late late at night for me to recount the details of how it would have gone down, but it would have been a standard set of common widgets that have some brand of authority. For example: look at the number and quality of data picker widgets, wouldn't it be nice to have a standard one like MFC does? And look at the widgets that Java Look and Feel (and the advanced topics) describes that do not exist in the JDK: sorting tables (two ways none the less), tree tables, Wizards, badged icons, and even toobar drop downs. All this in a published "do this" standard and no common implementation. No wonder VBers run from swing, they see cool stuff like that and say "I'll stick with MS" when the article starts talking about TableModel, EventListeners, and when to call repaint().

The SwingX subproject in JDNC can fill this role in my opinion. In fact they have a good portion of the items I just listed as part of their standard package (althought the date picker needs serious help, I don't think it will be hard to get it). Two suggestions I would have would be first to formally make SwingX a subproject of JDNC. Next they need to either drop the LGPL for a variant of the MPL or require a dual license for all submitted patches so that contributions can be brought into the core Java Runtime in the Mustang or later release. A Joint Copyright Assignment is required to contribute code.

If those things are done then when a kewl component like the JSpinner is released, it can first be hashed out in SwingX and then placed in the JDK later. Telling people that they have to upgrade their client JDK just because I used a spin box for number entry got me some strange looks and a good bit of grief.

October 13, 2004

An ocean, an ocean of blue

I had a dream the other night.

I was stranded in the middle of a vast ocean, an ocean of bright blue. I tried to swim to the edges, but at every edge I was met bu bright bright blue. The ocean wasn't all blue, sometimes it would fade into white, and then back into blue, but it was still a bright blue. And the ocean was a bold ocean, still a very bold ocean.

Then I realized it was a dream, but if I work up the ocean would fade and I would find myself on a vivid blue corrugated metal slab, and the blue was so vivid it looked purple. A bold purple.

I couldn't decide if I wanted wake up or stay in my dream. I desperately wanted another choice.

November 30, 2005

You know you progam GUIs when....

You know you spend too much time programming GUIs when you have a meeting debating the meaning of a two word checkbox and decide to change it to a 10 word label, and the meeting takes an hour.

I suppose that's better than looking for workarounds for app server bug that affect you. But not by much.

February 5, 2006

Flattening the JSplitPane Divider

You can do just about anything with Swing... Iff you know the magic internal classes to monkey with.

Today's example has to do with the JSplitPane. For a GUI I am working on I needed to allow a list box on the left to be resized by the user while keeping some content on the right, but it can't be to obtrusive or distracting. This is obviously what the JSplitPane was meant to solve, except for the part where the implementation always paints the whole freaking thing! What I want is what is on the bottom and what I get by default is on the top.
flatdivider.png flatdividerXP.png
So how do I fix this? I need to override the UI painters. Usually this isn't for the faint of heart, but in this case it is for the faint of heart! You see the basic plaf split panel divider painter only paints the associated border for the split pane divider, and maybe the expand buttons.

So all we need to insure is (a) we use some variant of the BasicSplitPaneDivider and (b) that it doesn't get any border set to it. I'll wave my hand over some access issues and complaints about global defaults, and show you what finally worked...

jSplitPane.setUI(new BasicSplitPaneUI() {
    public BasicSplitPaneDivider createDefaultDivider() {
        return new BasicSplitPaneDivider(this) {
            public void setBorder(Border b) {
            }
        };
    }
});
jSplitPane.setBorder(null);

The how without the why is that I create my own UI for the BasicSplitPane that uses a custom BasicSplitPaneDivider that is oblivious to any border set on it.

Here the complete demo that spits up the frames I took the screen shots from.

import java.awt.GridLayout; 
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;

public class FlatSplitPaneDivider {
    
    public static void flattenSplitPane(JSplitPane jSplitPane) {
        jSplitPane.setUI(new BasicSplitPaneUI() {
            public BasicSplitPaneDivider createDefaultDivider() {
                return new BasicSplitPaneDivider(this) {
                    public void setBorder(Border b) {
                    }
                };
            }
        });
        jSplitPane.setBorder(null);
    }
    
    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        
        JFrame f  = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200, 200);

        JPanel p = new JPanel();
        p.setLayout(new GridLayout(0, 1));
        f.getContentPane().add(p);
        
        JSplitPane sp = new JSplitPane();
        sp.setLeftComponent(new JLabel("<html>This is the Top Left Label"));
        sp.setRightComponent(new JLabel("<html>This is the Top Right Label"));
        sp.setDividerLocation(100);
        p.add(sp);
        
        sp = new JSplitPane();
        sp.setLeftComponent(new JLabel("<html>This is the Bottom Left Label"));
        sp.setRightComponent(new JLabel("<html>This is the Bottom Right Label"));
        sp.setDividerLocation(100);
        flattenSplitPane(sp);
        p.add(sp);
        
        f.setVisible(true);;
        
    }
}

About GUI

This page contains an archive of all entries posted to ... And They Shall Know Me By My Speling Errors in the GUI category. They are listed from oldest to newest.

Inst.Ant is the next category.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.33