Skip to content

Techniques of Java UI Development

18
Feb
2008

Too often these days I see Java developers new to the psuedo-science of UI development finding themselves completely lost before they even get started.  There are a lot of misconceptions about the “best” and “easiest” way to create a professional UI in Java, and precious few resources which attempt to clear up the confusion.

In this article, I’m going to make use of the Swing framework simply because it’s more widely known.  All of the same techniques and processes apply to SWT with equal validity.  I’ll walk through the steps required to create a simple form UI in the easiest and most maintainable fashion.  I’m well aware that there are faster ways of doing this, but in my experience, this process will lead to more maintainable and less rigid UIs.

Note: These steps will obviously be different if you’re working in a team or with a designer.  The intention of this article is not to present the “be all, end all” of UI design practices, but rather to be a set of guidelines for the common-case developer.

Design

It may surprise you, but the very first step in creating a UI is design.  You have to know fairly precisely how you want the UI to look and (more importantly) behave.  This step is more than just drawing a few mockups in Illustrator.  This is sitting down and hashing out what you want the controls to do when the window is resized, if the state of any controls should be tied to that of others, whether your labels LEFT aligned or RIGHT, etc.  Often I find the easiest way to start is with a diagram:

 Diagram

This is what my diagram would look like, but it’s important to note that this isn’t a “one size fits all” style.  The point of the diagram is to give you a medium to lay out the semantics of a panel and to help you understand just what it is you have to do.  This step becomes invaluable later on as you start actually writing code.

The important thing about this diagram is that it is annotated.  Anyone can just draw a picture of what they want the UI to look like, what components to use, how they should be spaced.  The real meat of the question is not what does it look like, but how does it behave.  One of the biggest questions Java UI developer have to answer (as opposed to, say .NET developers) is how do the controls behave when the form is resized.  This is a much more complicated question than “where should the component be placed” or “how should it look”.  In essence, the question is asking “what sort of layout manager configuration do you need?”

There are two directions which need to be considered: vertical and horizontal resize.  This may not be news, but it’s something that a lot of developers (myself included) seem to forget.  The way the form scales horizontally is just as important as how it scales vertically, so it is critical that these considerations are dealt with in the design phase.  You’ll notice on my diagram that I have annotated almost every component with scaling constraints, dictating visually how the component will behave as the form changes size.  For example, all but one of the text fields scale out horizontally, but remain with a fixed height.  The one text field which does not scale horizontally is annotated so that it remains with completely fixed dimensions, both vertical and horizontal.  It’s also important to note that the City text field scales horizontally, “pushing” the State combo box as it does so.  Thus the state selection is always right aligned, the city label is left aligned, and the intervening space is filled with the city text field.  This sort of “resize mapping” (to coin a phrase) must be considered before any code is written.

You’ll notice that there is just a single annotation indicating behavior when the form resizes vertically.  This is because, like most form-based UIs, there isn’t really a good way to deal with this situation.  In this case, I just drew a line through the form where I thought I saw the most logical split and indicated annotatively that this “non-component” should be what scales vertically.  Thus the buttons remain fixed to the bottom, while the remainder of the components build down from above.  Some forms have text areas (multi-line text fields) which may scale vertically, filling this space.  Our form however has no components which logically scale in the vertical direction, thus we invent a non-component which fills the gap in our imagination.  This non-component will only be reflected in the layout constraints, we won’t have to add anything extra to the panel itself.

When drawing this diagram, note that I wasn’t afraid to make mistakes and then annotatively clarify them.  For example, I made the form to narrow to clearly express the intent of the layout.  The City and State fields take up more room than I expected.  Rather than starting from scratch, I just draw the fields as it seems most intuitive and then indicate with arrows that they should be aligned with the other text fields.  Likewise, the Line 1 and Line 2 fields should actually stretch all the way to the edge of the section.  This wasn’t clear in the diagram, so I added the –| annotation to remind myself of this fact.  Always remember that we’re not trying to make an unambiguous specification, just a reminder to ourselves.  It’s a design aid, nothing more.

The final bit of annotative goodness which needs to be observed is the “disables” marker attached to the Address checkbox and the section below it.  This marker indicates some basic UI state behavior: when the checkbox is selected, the section will be enabled; otherwise the section below (and all its components) will be disabled and no data may be entered.  Note that the annotation doesn’t say “clears” or “resets”, since we just want the section to be disabled and ignored.  Someone may disable the address section only to realize later (prior to saving) that they actually do need to enter an address.  They would likely want all of their previous changes to still be there, rather than completely lost.

Notice what we didn’t annotate here.  We didn’t clutter our design with intuitive concepts like “Save button saves the contents and closes the window”.  Rather, we left that up to our imagination and (likely) prodigious memory.  Remember that this diagram is for our use, not our manager or the other developers in our team.  If we were building a diagram for external consumption, we would have had to make an effort to be more clear.  As it is, we can trust ourselves to build a UI that makes sense according to convention.

First Steps

So we have our design diagram in hand, it’s finally time to consider some code.  It’s usually around this time that developers start thinking about what tools to use and how they can be of help.  Let me start out by saying flat-out that I am not in favor of any graphical UI design tool.  Don’t get me wrong, I think Matisse is a brilliant bit of engineering and a credit to the entire NetBeans team, but it’s not a silver bullet.  In fact, I don’t even think it’s a bullet worth firing.  I could create the code for the diagramed UI in a few minutes using Matisse, but what would the code look like?  Would it be code worth coding?

image

javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  .addGroup(jPanel1Layout.createSequentialGroup()
    .addContainerGap()
    .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jLabel3)
          .addComponent(jLabel4)
          .addComponent(jLabel5))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jTextField4, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
          .addComponent(jTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
          .addGroup(jPanel1Layout.createSequentialGroup()
            .addComponent(jTextField5, javax.swing.GroupLayout.DEFAULT_SIZE, 282, Short.MAX_VALUE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(jLabel6)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 
                 javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addComponent(jLabel7)
        .addGap(18, 18, 18)
        .addComponent(jTextField6, javax.swing.GroupLayout.PREFERRED_SIZE, 93, 
            javax.swing.GroupLayout.PREFERRED_SIZE)))
    .addContainerGap())
);

Oh yeah, I’m looking forward to working with that code.  What’s actually worse is you can’t work with that code.  NetBeans prevents you from editing the auto-generated sections of the code.  Meaning if Matisse got it wrong (and it did a couple times during the construction of the screenshot), there’s no way for you to fix it by hand.  And even assuming you drop back to your favorite external editor to make your fix, the next time you open the file in NetBeans, your changes will be overwritten.  Matisse is a totally dominating, uncompromising beast that takes over your UI and doesn’t let go.

Honestly, this isn’t a stab at NetBeans in any way.  Matisse does a fine job auto-generating its code and it’s amazingly good at inferring layout constraints based on convention and control placement.  It’s no substitute for fine-grained manual control however.  People may argue that “UI design is a visual task”, but that’s what the design diagram is for.  I’ve worked with some fairly complex Swing UIs in my time, and let me tell you that if you don’t know how to write the code by hand, you’ll never be able to maintain it.  And if you can’t maintain your UI code, that’s going to cause tons of problems down the road.  So no quick and easy tools for our UI-making.

If we’re going to write the code by hand (and we are), then we’re going to need to decide which layout manager(s) to make use of.  This is where the diagram can be extremely helpful.  Just looking at our design suggests a grid based approach, a subpanel (for the address) and a footer panel for the buttons (probably using something like FlowLayout).  Working from the high-level down to the fine-grained details:

  1. From top down: we have a body, some empty space which stretches on resize and a footer section.  This suggests the use of BorderLayout with the “body” as the CENTER constraint and our button panel as SOUTH
  2. Button panel appears to keep the components centered, so FlowLayout would be the most appropriate
  3. Body panel seems to be a grid of two columns, one for the labels and one for the text fields.  The Address component spans both grids with a left offset of 15-20 pixels.  Below this is the address panel which spans both columns and stretches to fill.  The address panel is not set to stretch vertically, but is rather attached to the top of its cell, allowing empty space to stretch below it
  4. Address panel appears to be a grid divided into four columns.  The first two rows have text fields which span three columns.  The bottom row contains a text field which also spans three columns, but does not stretch to fill

And no, I’m not concerned with resolution independence here.  After all, if Apple doesn’t care, why should I?  :-)

This process mainly depends upon familiarity with layout managers and some experience with form layout.  I happen to know that some of the most powerful layout managers are grid based, so I try to fit most UI designs into a grid.  I also know that Swing comes with a very nice (if limited) default layout manager called BorderLayout.  Many high-level layout constructions fall into a category of problems which are trivial to manage with BorderLayout (like our button footer).  There really are a number of patterns which can be kept in mind during this layout process, but in the end it all comes down to experience.  Once you’ve built a form-based UI, the steps involved in creating another become somewhat instinctive.

We’ve already specified two of the three layout managers we will need for this UI.  All that remains is to select a grid-style manager which can accommodate both fixed and fluid constraints.  We could use GridBagLayout, but for reasons which should be obvious, I like to avoid that one.  Unfortunately, Swing doesn’t really have another grid layout which is powerful enough to accomplish our goals.  So we look outside of the core Swing API.

There are a number of third-party layout managers available, but the one I really favor is a layout manager I ported from SWT a number of years ago.  SWT’s GridLayout is basically most of the power of GridBagLayout, wrapped in a clean and intuitive API.  It’s more than sufficient for our purposes, and it won’t needlessly gum up our code with dozens of verbose constraint definitions.

Fleshing it Out

With all three layout managers chosen and most of the constraints solidified, it’s time to get our hands dirty and actually write some code.  For simplicity of example, we’re just going to put everything into a single class with a main method.  This main method will simply set the look and feel (avoiding metal) and launch the frame:

public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException e) {
            } catch (InstantiationException e) {
            } catch (IllegalAccessException e) {
            } catch (UnsupportedLookAndFeelException e) {
            }
 
            new ContactDetails().setVisible(true);
        }
    });
}

As per convention, all of our components will be created and initialized in the class constructor.  Some people are proponents of the init() or initComponents() convention, but I personally don’t see that it serves any purpose.  If you’re just calling the method from the constructor anyway, why bother?

You’ll notice that we’ve wrapped the entire launch sequence in an invokeLater()This is extremely important.  Swing (or rather, AWT) manages the entire event dispatch queue for you in separate threads.  It’s not like SWT where the event dispatch is manually, er…dispatched.  This means that the main thread is not in fact the EDT (event dispatch thread).  If we just made a call to our constructor within the main thread itself, we would be creating components and interacting with Swing in a thread other than the EDT.  Swing is pretty good at making sure that the event dispatch still works, but odd bugs can creep in around the edges.  Ever wonder why the setVisible(true) invocation sometimes blocks and doesn’t at other times?  This is usually due to the differences between an in-EDT invocation and a main thread call.  Romain Guy turned me on to this misunderstood bit of Swing usage, and I’ve been using it ever since.  Believe me when I say that you’ll save yourself a world of hurt by making sure you’re square with the EDT.

Now that we’re sure our invocations are properly wrapped, we can get started writing the UI layout code, adding the components to the frame.  Honestly, this code is more than slightly verbose and repetitious, so I’m not going to reproduce all of it.  This is just the interesting stuff:

setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 265);
 
JPanel body = new JPanel(new SWTGridLayout(2, false));
getContentPane().add(body);
 
body.add(new JLabel("First Name:"));
 
JTextField firstName = new JTextField();
 
SWTGridData data = new SWTGridData();
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = SWTGridData.FILL;
body.add(firstName, data);
 
body.add(new JLabel("Last Name:"));
 
JTextField lastName = new JTextField();
 
data = new SWTGridData();
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = SWTGridData.FILL;
body.add(lastName, data);
 
JCheckBox address = new JCheckBox("Address");
 
data = new SWTGridData();
data.horizontalSpan = 2;
data.horizontalIndent = 15;
body.add(address, data);
 
JPanel addressPanel = new JPanel(new SWTGridLayout(4, false));
addressPanel.setBorder(BorderFactory.createEtchedBorder());
 
data = new SWTGridData();
data.grabExcessVerticalSpace = true;
data.horizontalAlignment = SWTGridData.FILL;
data.verticalAlignment = SWTGridData.BEGINNING;
data.horizontalSpan = 2;
body.add(addressPanel, data);

 image

Well, this isn’t quite like our diagram, but it’s close enough.  Remember that the diagram is only a guide.  It’s purpose is to focus your thought and allow you to create the layout constraints.  It’s never intended to be a hard-and-fast spec.

You’ll notice how much more readable the manually written code is than its Matisse-generated counterpart.  It may be repetitive and annoying, but it’s very readable, very maintainable.  We could actually add a little bit of abstraction here (e.g. createGridData()) to make things even more readable, but that’s overkill for this example.  Actually, not only is this code readable and maintainable by myself, but I can also check it into a shared repository and other people (potentially using different editors) can make changes to the layout and UI logic and expect them to actually work.  I’ve had nothing but bad experiences when using UI builders in a team setting, especially builders like Matisse which rely on external meta files.

One thing that is worth calling attention to is that magic number pair in the setSize() invocation.  Of course, I could have used pack(), but that rarely sizes a frame as something which looks pleasing to the eye.  I’ve found that the easiest way to get a frame which is sized nicely for most platforms is to put in some easy default width and height (say, 400×400), then once the layout is fixed, size the form by hand.  Literally run the form and resize the window until everything looks good.  Once that’s done, screenshot it and measure the width and height in Paint.  :-)  It may sound crude, but it works surprisingly well.  Of course, the size will have to change a bit, depending on which platform the app is running on, but this is easy enough to handle.  Usually I repeat the process on each platform, taking the largest width-height pair as making that the fixed standard for all platforms.

Conclusion

And there you have it, a simple Java form UI created with minimal fuss and maximum compatibility.  More importantly, the techniques presented in this article can be applied to more UIs in future, and not just forms.  All of us at some point have to build a basic Swing UI, and it’s best if we’re comfortable doing so and able to create something that’s worth keeping around.  Hopefully the concepts I have presented will be useful to you the next time you find yourself faced with a similar situation.

In Search of a Better Build System

26
Nov
2007

There’s a consistent problem with developing applications of any reasonable size, a problem which has dated back even before the early days of C.  The problem is that any application of significance will be composed of several source files.  In fact, reasonable applications are often found to be composed of thousands if not hundreds of thousands of files.  Back in the day, it was felt (for some reason which escapes me) that it would be poor practice to type “gcc -Wall -o filename.o filename.cpp” several thousand times every time the app needed to be recompiled.

So from very early on, developers have been writing tools to aid in the build process.  Some of these tools (most of them) were somewhat ad hoc and specialized.  The most common example which springs to mind is a simple script, which handles the compilation:

#!/bin/sh
 
for f in *.c; do
  name=`echo $f | sed 's/.c//'`
  gcc -Wall -o ${name}.o ${name}.c
done

The limitations of such an approach should be obvious.  For one thing, you can only use this script on a single directory which contains all source files.  This is very rarely the case.  More importantly, there is no linking or dependency checking taking place.  This means that with the exception of very simple applications, this script will outright fail every time.  Of course, you could modify the script extensively to hard-code the dependency information, check for file modification, etc.  However, this would be a long, dull process which would have to be repeated for every application you write.  Not a very productive way to spend your time.

And so was born make.  Make has a number of advantages over the hand-scripted method.  It allows for (fairly) easy dependency specification, it will only compile modified files, it lets you ensure everything happens in the proper order, it’s more maintainable, etc.  However at its core, Make is almost exactly a wrapper around the hand-script method.  As such, it suffers from many of the same limitations, such as a cryptic syntax and a dependence on the underlying shell.  Make is a far cry from hand scripting everything, but it’s hardly the silver bullet developers were looking for.

So as the years went by, more and more solutions were devised, though few of them caught on to the extent that Make had.  To this day, Make is still the de facto standard for C and C++ build systems.  Its dominance is so pervasive that I have even found Java applications which are built using Make, though thankfully these are far and few between.  With Java on the scene, attention turned to a new effort which attempted to unseat Make as the reigning champion of the build tools: Ant.

Ant based its syntax on XML, breaking completely with Make’s bash roots and focusing on the task rather than the dependency.  Because of this clean break, and due to the fact that the Ant interpreter itself is written in Java, Ant is entirely platform agnostic.  An Ant build script written for a Java project can be run on any platform, anywhere (as long as Java is installed).  This immediately gave it a huge boost over Make as it finally enabled developers on platforms such as Windows and MacOS 9 (and earlier), platforms without the advantages afforded by a real shell.  Ant’s rise to dominance in the field of Java build systems was so rapid and so completely unchallenged that it still remains the “proper” way to build a Java application.  Every Java developer has Ant installed, and as such it has become something of a lingua franca in build script land.

Unfortunately Ant, like Make suffers from a number of shortcomings.  Its XML syntax for one, while instantly recognizable and familiar to 99% of developers on this planet, poses problems with verbosity and expressiveness.  For example, Ant doesn’t provide any real mechanism for variables, bona fide procedures or any way to execute arbitrary code without a clean break into Java (a custom Ant Task).  While this tends to keep build scripts somewhat uniform and easily understandable (when you’ve seen one build.xml, you’ve seen them all), it also forms a crippling limitation in many ways.  I’ve used Ant a lot in my time, and let me tell you it can be a real pain.  For simple builds (javac a bunch of source files, copy one or two resources, zip the result, etc) it’s quite sufficient, but headaches set in when dealing with anything complex like chained builds, subprojects or library dependency management.  You can make it work, but it’s not pretty.

The Maven project was started to try to address some of these problems (among other things).  Maven provides full-stack dependancy management (even resolving and downloading third-party libraries), build management, conventions enforcement, IDE interop and so on.  A number of people would say that Ant is completely superceded by Maven, and that Maven is the only way to go for any new Java project.  Unfortunately, like so many successful Java projects of its day (a few examples Spring to mind), Maven refused to maintain its focus.  Instead of being an incredibly simple build system and dependency management tool, Maven has tried to branch out and become the all-encompassing tool to solve everything.  I know I haven’t even scratched the surface of its capabilities in my limited exposure, but I can say that I’ve seen enough.  Maven is amazing, but way way to invasive for my tastes.  It has a knack of making the simple things cryptic, the hard things harder and the complex things impossible.  (by impossible I mean without resorting to hackery like invoking Ant from within Maven or calling out to a shell script)  Now I realize flame wars have been fought on this very subject, but I have to conclude that Maven is just too much and too overwhelming for easy use (and hence, wide adoption).

Fortunately for me, the rise of dynamic languages has brought about some wider options.  Ruby in particular has become a favorite for many different build tool projects (Rake, Raven, etc).  Most interesting is the effort underway to provide a “non-sucky Maven”.  The Buildr project, currently in incubation at Apache, is basically seeking to be a build system which enables trivial application of the most common case (builds and dependencies), as well as the flexibility of a Turing-complete language (Ruby) to make possible just about any build task, no matter how esoteric.

Buildr’s promise is indeed alluring, and at first glance it seems to deliver.  The DSL syntax of the build file is intuitive and easy to grasp.  With this it bundles the full power of Maven, allowing it to be a drop-in replacement for any pre-existing Maven project.  Well, almost.  Buildr doesn’t allow for things like dependency checkout from a source code repository.  It also retains one of Maven’s biggest failings in that it unduly enforces a rigid directory structure.  While it is possible to override this restriction, Buildr’s documentation isn’t exactly clear on how, and to be honest I still haven’t figured out how to get some things working.  Buildr is promising, but not perfect.

Another flaw suffered by all of the new, “avant garde” build tools is that not all of them can be expected on every developer’s machine.  Back in the days of Make and Ant, every developer knew that every other developer could handle a build.xml file and use it to get a fully functional build out the other end.  Unfortunately, while Maven has made tremendous strides in popularity, it is still no where near as ubiquitous as Ant.  Buildr is even less common, additionally requiring the separate installation of a full Ruby runtime, as well as the “buildr” gem.  These considerations are less significant for a small commercial product, where all of the developers are in close contact and outside interference is rare.  However, for the open-source project, standardization in the required tools is critical, otherwise new developers would have no way to contribute.

Unfortunately it’s a bit of a Catch-22.  Even assuming Buildr manages to make good on its promise of being “a build system that doesn’t suck”, it has to gain in popularity before it will be accepted as the de facto standard for Java project builds.  But to gain popularity, Buildr must be accepted by the community.  It’s a tightly knit, closed circle driven by managers remaining content with “the way it’s always been done” and developers refusing to chance the success of their project on the hope that all parties concerned will also show forward thinking in their tool set.  I really don’t envy the Buildr project leads in their task to promote their tool.

So where does this leave me?  Practically speaking, I’m still going to stick with Ant.  Buildr may be interesting, and Maven may be powerful, but neither is the standard yet.  Perhaps even more importantly: I’m lazy.  I know Ant.  I know it very well and I would have to see some pretty clear benefits (and an easy introductory road) to switch my build system of choice.  Right now, I don’t see either of those.  Maven is infamous for having a very steep learning curve.  And as I mentioned before, Buildr’s documentation leaves something to be desired.

I want to help usher in the next era of Java development as much as the next guy.  But I’m not willing to sacrifice the now for the sake of a future which may take a totally different form when it arrives.  So I will (reluctantly) stick with my old standby.  Perhaps someday I’ll come across a build tool which really impresses me enough to make me switch.  Until then you can continue to listen to me whine and complain about the difficulties of whipping Ant into shape.  How lucky for both of us.  :-S

General Purpose Editor Within Eclipse

31
Oct
2007

I’ve blogged before about the difficulties I’ve had in finding a solid, general-purpose text editor for my system.  I looked into VIM for Windows, E, SciTi and many more before finally settling on jEdit.  It’s a really good editor, if a bit rough around the edges.  A lot of people (myself included) would put it on par with TextMate in terms of features, and superior to it in some ways thanks to its cross-platform nature.

As a separate application from my IDE, jEdit performs superbly, but although this solves the problem of editing arbitrary files from file explorer, it still leaves open the problem of editing arbitrary file types within Eclipse.  What I had been doing is using jEdit as an external editor, opening it up any time I needed to open a weird file type within Eclipse.  This works fairly well, but it’s heavy on memory, not integrated with tools like Mylyn (as if there were any tools like Mylyn) and it’s just annoying, dealing with a separate app like that. 

What I really want is some sort of embedded jEdit editor canvas within a normal Eclipse editor part.  One would think this would be very possible, given SWT_AWT and its capabilities.  In fact, I was just about to crack open the jEdit source to see if I could roll something myself when an eternal axiom sprang to mind: Google is your friend.  Actually in this case, I used Eclipse-Plugins.info (which IMHO is still the best Eclipse plugins site, despite lacking an active administrator) and did a quick search for any plugins mentioning the word “jedit”.  A few minutes later, I was perusing the page for the little-known Color Editor plugin.

Color Editor is basically a simple Eclipse editor which will open any file for you.  It’s not much more sophisticated than the standard Text Editor which is the default for unknown file types.  However, what it *does* do is parse jEdit’s mode.xml files, providing semi-advanced syntax highlighting for over 150 file types.  Granted, it doesn’t have all of jEdit’s nice editing features or plugins like SuperAbrevs, but if I need that I’ll open up jEdit itself.  For most of what I do, quick-and-dirty syntax highlighting is all I need.

The problems with this plugin are mainly caused by the fact that it’s quite old and hasn’t really been updated recently.  It still defaults to the old-style jEdit colors, which are ugly as sin.  Also, it doesn’t support as granular syntax highlighting as the current version of jEdit (only 2 comment types, 2 literals, etc).  It doesn’t support easy adding of modes (you have to repackage the plugin JAR file), nor does it allow you to simply point it to the same mode catalog used by jEdit itself (which would simplify management of editor modes).  Despite all of that, it’s still a really nice idea.

The plugin works not by embedding a jEdit editor canvas using SWT_AWT, but by just using the standard Eclipse syntax highlighting techniques coupled with the jEdit mode files.  The downside to this approach is the need to write a whole bunch of mode parser code which is effectively already done within jEdit.  Also, odd bugs can leak in around the edges, since the editor is effectively reverse-engineering the jEdit editor part.  However, the approach does have a very unexpected (and pleasant) silver lining: fonts look good.

I’ve had tons of problems with jEdit’s font rendering on Windows, mainly due to the fact that Swing’s font renderer doesn’t seem to be as sophisticated as Vista’s (or at least, less capable of dealing with monospaced fonts).  But since Color Editor uses native font rendering, the text looks 100% native:

jEdit

jEdit Fonts

Eclipse Color Editor

Color Editor Fonts

I assume you can see the difference.  :-)  So, fonts look great, but if you examine the body of the method in the file a bit more, you’ll see examples of those odd bugs I was talking about.  For some reason, Color Editor thinks that the suite variable, as well as the BaseTests, DBTests, SchemaTests and TypeTests classes are all methods, rather than local variables and classes.  This is annoying, but it’s not the end of the world.  Granted, I haven’t been using this tool for all that long, but I’m guessing that instances like this are fairly rare, and not cause for immediate alarm.  You’ll also notice some evidence of the lessened flexibility in the syntax highlighting engine (fewer types of comments in this case) in the way the javadoc and single-line comments are colorized differently.

Download Color Editor Plugin from gstaff.org  (no update site available)

All you have to do is stick the JAR in your eclipse/plugins directory and start Eclipse with the -clean option (usually unnecessary, but just to be safe).  Color Editor will automatically be registered as the default editor for unknown file types.  If you want to change the default colors (as well you should), you can find the preference under Coloring Editor -> Colors (no idea why the conjugation difference between the editor name and the preference pane).  It’s a bit clumsy to try and set all of the colors to a predefined theme (I made mine look like the current jEdit defaults), but it’s all possible.

Hopefully you’ll find this a useful tool in editing those random shell scripts and who-knows-what-else which got included in the project, but for which Eclipse doesn’t have a separate plugin.

One Wild Week with Ubuntu Linux

29
Oct
2007

As I mentioned in my last post, I managed to erase my hard drive and ruin my productivity for a week all in one fell swoop.  Since I didn’t have a Vista install disk handy, I had to make do with Ubuntu Linux for over a week while I waited for Microsoft to send me a replacement.  Obviously life doesn’t just pause and wait for my computer to catch up, so I was literally forced to use Linux on a daily basis for exactly the same things that I would normally use Windows.  This gave me quite a unique opportunity: A chance to test out an alternate OS under identical circumstances to its competitor.

Compiz

The first thing on my list to try was enabling Compiz.  Yes, I know it’s mostly eye-candy, but there’s also some very useful stuff in there.  3D compositing is extremely useful in a WS if for no other reason than the UI always feels sprightly and responsive, rather than a constant frustrating shade of low-performance.  For example, if you drag a window in vanilla Gnome, there’s repaint lag.  Imperceptible though it may be on most modern systems, it’s still there.  If you drag a Window with Compiz enabled, the lag virtually goes away.  Also, if a window stops responding, Compiz drops its color saturation (similar to Vista’s white overlay), whereas on a non-composited WS, the app would just freeze and stop painting.  Other Compiz treats like subtle shadows (which really help the eye to differentiate windows quickly), a slicker workspace switcher and a really nice expose clone all combine to produce a very competitive environment for those of us coming from the likes of Vista and Leopard.

The downside is it’s very difficult to get working.  As with all things Linux: if you want it done right, you have to do it yourself.  Actually, with Linux it’s more like: If you want it done, you have to do it yourself without documentation.  One of Ubuntu Gutsy Gibbon’s big selling points is that it’s so easy to get working out of the box.  One of the hot new features being pushed by Canonical is that Compiz is now enabled by default on installations.  This is supposed to mean that you don’t have to do anything to get it working.  Unfortunately, it didn’t work out of the box for me (I have an ATI video card).  The error message I got when trying to configure the “Desktop Effects” was utterly unhelpful, and I had to actually figure out for myself that I needed to manually install xserver-xgl (no documentation, no “helpful hints”, nothing).  Even then, it still took a manual kick-in-the-pants to actually get Compiz running for the first time.  And even then things still weren’t a hundred percent.  Setting changes took a logout/login to apply (without any notice).  Key combos conflicted and didn’t work half the time.  All in all, it was a mess.

The second thing was to try to get Eclipse, jEdit and gnome-terminal into a usable state so that I could actually do real work with them.  Fortunately, gnome-terminal is quite amenable to the effort.  I daresay it’s probably the most polished app on the whole OS; everyone should be using it!  So 30 seconds after I opened up gnome-terminal for the first time, I had disabled that oh-so-annoying terminal bell, set the colors to something a bit easier on the eyes and appended ~/.bin to my PATH.  I figured the next easiest would probably be Eclipse.  After all, Linux GTK is supposed to be SWT’s second most stable WS, and Eclipse itself has been running on Linux practically from version 1.0.  Unfortunately, it wasn’t quite so simple…

Eclipse

Oh I didn’t have any real trouble getting Eclipse to start on my Linux system, but starting was about all it could do for a while.  For one thing, it took me nearly three hours to get all of the Europa plugins I use installed again.  Granted, it might have something to do with the major fall release coinciding with the day I was trying to configure my setup, but OSU’s servers are faster than that.  I’m guessing there was something weird going on within the update manager that doesn’t normally happen on Windows (it usually takes me about 10 minutes to configure a fresh Eclipse install).  Once I had gotten everything installed, I tried to open up my old workspaces.  It was about this point that I started to run into trouble.

Everyone should know better than to try to open up a workspace from another system unmodified on a completely different one; especially when crossing OSes.  That’s not to say that I haven’t successfully performed such a procedure in the past, but I didn’t want to take any chances with another three hour wait.  I did the “right thing” and deleted the .metadata directory and open the workspace afresh.  First thing, I used the handy “Import Preferences” wizard to grab all of my saved syntax highlighting, font sizes and classpath variables from a previously exported .epf file.  I sucked the preferences into my workspace, looked around, and everything seemed dandy. 

At least, it did until I hit the “User Libraries” preference pane.  Here, Eclipse gave me an error (something about absolute paths and IClasspath) and refused to show the pane.  This was a situation where something was wrong with the underlying preference for the user libraries and Eclipse wasn’t even allowing me to dig in and fix it!  After messing around with the internal structure of the .metadata directory for an hour or so, trying to erase just that particular preference set, I gave up in disgust, deleted the .metadata directory and started again.

This time, I ran the .epf file through sed (one of the many advantages of once again having a Linux shell at my disposal) and got rid of all the “C:” instances throughout the file.  Eclipse seemed to like this a lot better, and actually deigned to show me the preference pane this time, without the annoying error.  I was able to change all of the paths for the libraries, and once again things compiled nicely.

Unfortunately, not every user is going to have the know-how to do what I did.  I hate to sound immodest, but I do have a bit more Eclipse experience than the average Joe trying to switch his environment from Windows to Linux (a common occurrence these days).  If a problem arising from a common operation leaves me scratching my head for over an hour, it’s probably something which should be addressed.  This sort of complete blocker of a problem which necessitates manual hacking of auto-generated files is really a big no-no.  I may have gotten it working in the end, but the point is that it wasn’t easy.  All it happened to be was yet another source of stress to load onto my already bursting plyurethane sphere.

Tools and the Environment

Ironically, configuring jEdit was a walk in the park, especially compared to Eclipse.  All I needed to do was download the .deb package from jedit.org, provide my user password, copy over my modified JAR (some things just can’t be fixed in the preferences) and away I went.  Ten minutes later I had all my favorite plugins installed and I was developing with pleasure random bash scripts on remote servers.  It still took a little Linux foo to get the warm start working, but compared to what I had been through with the Eclipse setup, it was a walk in the park.

After this, there were no more “big things” to get setup.  I had more-or-less everything I needed to be productive once more, so I turned my attention to the smaller things (yes, I do count 3D compisiting as a “big thing”).  My first task was to disable the track pad and enable center button scrolling on my ThinkPad.  As it turns out, center button scrolling is as easy as telling xserver to emulate a 3-button mouse.  Unfortunately, it seems that disabling the track pad was a bit more complex.  I discovered (to my surprise) that there is actually no way to do this in Linux itself.  I had to go into the BIOS and completely deactivate the device, just to keep it from randomly firing when I brushed it with my palm.

Here I also started to look into things like fonts.  Unfortunately, even installing the Windows fonts package didn’t improve the situation.  Linux has an excellent renderer if all you want to display is Monospace 10pt (which it renders quite nicely), but anything else looks terrible at low sizes and “not quite relaxing” when larger.  Unfortunately, fonts are like the wind: sometimes pleasant, sometimes annoying as hell, always unfixable. 

So I decided to set my sights on a more attainable goal and focused on the mouse acceleration curve.  Windows Vista has a very nice feature which adaptively adjusts the mouse curve based on speed, making the mouse more precise at low speeds and more responsive at high speeds.  This leads to a general feeling of greater ease in mousing.  You don’t really notice what a difference this makes until you try to wrestle the mouse from point A to point B on a system which doesn’t have such a nice curvature.

Anyway, adjusting the mouse curve seems like a pretty normal thing to want to do, right?  Linux is supposed to be an incredibly configurable operating system, so I figured I shouldn’t have a problem.  Well as it turns out, there is no way to do this in xserver.  I couldn’t find any tool, any how-to anywhere which gave instruction on how to rectify this glaring lack of control.  After wasting quite a bit of time Googling around and browsing “man xorg.conf”, I threw in the towel and decided to put up with the sore mouse-finger for a week.

Conclusion

Linux is great.  (what, not the conclusion you were expecting?)  I absolutely love Linux’s terminal, startup times (roughly 3x faster than Vista) and file systems (with ReiserFS managing /home, my perceived FS speeds were in the range of 2x better than NTFS on the same drive).  Unfortunately, Linux just doesn’t have what it takes to be a desktop operating system for the average user.  What I mean by this is it just takes too much manual tweaking and fussing to get things to work right.  As a developer, I may have the ability to fix little glitches that arise in my environment, but that doesn’t mean I have the time or inclination.  I want something that works…now; and I don’t want to lose hair over whether or not the graphical environment is even going to start on the next boot.  I guess it’s back to Vista for me!  *sigh*

Apple Blows Another Great Opportunity

27
Oct
2007

I hate to be yet another blogger taking a potshot at Apple in the wake of the Leopard release, but I just have to say it: Apple, WTF are you thinking?!  There, I said it, now we can be rational about things.

For those of you living in very cramped fox-holes for the past two years, MacOS X 10.5 (Leopard) is Apple’s latest incarnation of the cult-classic OS, MacOS X.  It’s got multiple workspaces, file system versioning, read-only ZFS support and eye-twisting shadows which make your desktop look about half a mile thick.  It’s got a totally redesigned Finder (which coincidentally looks just like iTunes) and added eye candy for both the Dock and the menu bar.  What it doesn’t have is Java 6.

Sun released Java 6 back in what, last November?  Apple’s had quite a while to get their act in gear and bring the latest major release to the table.  In fact, they’ve had even longer than a year, since Java 6 was in open development long before its release.  Apple did release a few developer previous of Java 6 to ADC members, but they discontinued the practice several months ago and haven’t made anything available since.  It’s not as bad as all that though, the preview releases weren’t too much more than a renamed Java 5 with a few new generic APIs.  Either way, Apple really has no excuse for not having Java 6 ready at least to coincide with the latest version of its OS, if not sooner.

To be totally honest, I don’t see how Apple is even justifying this decision to itself and its stockholders.  Consider how many Java developers have switched to Macintosh over the last few years.  I can count on one hand the number of developers I know and respect who still use Windows or Linux as their primary development machine.  It’s startling the shift in the market which has taken place, partially driven by Rails’s major push of TextMate and the waves it caused throughout the rest of the development community, but also caused by the fact that MacOS X really is a very slick, very stable BSD incarnation which can run smoothly as a desktop.  Well, that and the fact that the Apple hardware just looks so cool.

The thing is, all of these Java developers who’ve switched to Mac recently are going to start second guessing that decision.  Java 6 is now a year overdue for the Mac platform, and Apple is giving no indication of rectifying the situation any time soon.  What’s worse, is the version of Java 5 which does come pre-installed on Leopard seems buggy and unstable (disclaimer: I haven’t actually tested this myself, I just have it on good authority).  Without a modern, stable Java, many developers will be simply unable to use the platform as their primary system.  And guess where these developers will turn?  Either to Linux and all the headaches thereof, or back into Microsoft’s waiting (and well-patented) arms.  Is Apple really so big that it can just give the finger to such a large market segment?

Consider too, what this is going to mean for the future of the Mac platform.  In the last couple years, we’ve seen a vast increase in the quality and quantity of applications available for Macintosh.  I don’t think that it’s a coincidence that this has correlated directly with the up-surge in developers switching their primary platform to OS X.  Think about it, developers who use a certain platform are going to write software with that platform in mind.  It’s only natural.  With more and more developers focusing on Macintosh, the quality of applications for the platform increases, as well as number of new projects focusing exclusively or primarily on the platform for final deployment.  In short, it’s exactly what Apple needs to make the platform a dominant player in the market 5 years from now.  By flipping off the developers, Apple is basically saying “Yes, we know you want to write state-of-the-art applications that run exclusively on our platform, bringing more customers to our outlet stores, but the fact is that we don’t want you writing applications for our platform.  Have you heard of Linux?”

Now I know that speaking out against Apple is like blaspheming a divinity, people have been stoned for less, but it still needs to be said.  For the record, I like Macintosh.  I like the Apple products, and I’ve always loved the Mac OS (ever since my first computer running OS 7).  That said, I have never liked Apple as a company, and this latest fiasco is reminding me why not.  Hopefully Apple will see the error of their ways and offer Java 6 as an update sooner rather than later.  And if not, there’s always Windows!