Archive for the ‘coding’ Category

Fully Interactive JTables (aka Mouseover Editing)

May 17th, 2007 | Kevin

What sucks about JTables? Everything, of course—but that’s a developer’s perspective. To the user, cell editing is rough around the edges: when and where to click, and how many times—it’s never perfectly clear. Cells in a table just don’t provide the mouseover feedback that regular components do. If only a JTable behaved like a bunch of components thrown into a giant GridBag or TableLayout

mouseover-screenshot.png

Mouseover Editing simulates just that. The idea is to attach a MouseListener to the JTable and call editCellAt(row, col) whenever the cursor moves over a new cell. In other words, even though only one cell in a table can be fully interactive (the editing cell) at any given time, as long as we keep moving that cell to stay underneath the user’s cursor, the whole table will appear to be fully interactive. If done correctly, this will appear to the user as though he’s interacting with a bunch of real components (rather than rendered stamps) inside a giant Grid/GridBag/TableLayout.

Most importantly, the user will get mouseover feedback about which cells are editable, and how to edit them. Checkboxes, buttons, and comboboxes (if the L&F supports it) will highlight to indicate press-ability and the cursor will turn to a text caret when hovering over cells that contain textfields. When done correctly, the effect is nearly seamless and very satisfying.

Here’s a webstart demo. Read on for the solution in code.

Read the rest of this entry »

Custom Alpha Compositing

March 27th, 2007 | Carl

Every so often (can’t be more than once every two or three days), Swing doesn’t quite do what we need, and we end up writing customized code. In this case, all the available AlphaComposite instances provided with Java were variations on the theme of combining the colors and alpha channel of both source images into a target image. (Wikipedia’s Alpha Compositing article is good background on the topic).

What if what you really wanted was the color from one image and the alpha channel from another? You’d be out of luck, but for the talents of Brien. Here’s what you normally get with a standard AlphaComposite.SRC_OVER sort of technique. In the following two examples, the icon is opaque and the rectangle is partially opaque black fading to transparency.

AlphaComposite.SRC_OVER

What we needed looks more like this:

SourceAlphaComposite

Read on to find out how we did it, and why. Read the rest of this entry »

Unicode and happy user experiences

March 6th, 2007 | Carl

Everyone agrees that it’s crucial to do validation on user input so that, among other things, your application never tries to write a value that’s too long into a database field with a specific limit. Users of your application shouldn’t, however, be left guessing whether the megabyte they pasted (and you know they will) into the eensy-teensy text field really got saved to the database or not. So you should limit the text field itself so they get immediate feedback, rather than via some Johnnie-come-lately error message, or worse, a bunch of text gets dropped in the bit bucket.

One fairly well established technique is to write a DocumentFilter, and when insertString() or replace() is called, validate the added text and truncate as necessary to ensure the database field length is not exceeded.

Now the fun part. What happens when you try to store your comments on N’Ko, Mongolian, Bopomofo (phonetic markers, now commonly used as an input character set for Mandarin), or even ancient Viking runes? You get two choices, store as ASCII or ISO-8859-1 (aka Latin-1), or whatever, and you lose data. Oops. Or convert to UTF-16 or UTF-8. Hm. Wait a minute, now the value (in bytes) is somewhere between 1-3 times as many bytes as the original String length. So, how do you limit the text field to the number of bytes the database will permit? If you picked UTF-16, it’s pretty simple, divide the database limit by two. But it’s pretty wasteful of space, usually. On the other hand, you can’t predict exactly how many bytes the UTF-8 representation needs until you try it out.

The following algorithm will produce a String which, if converted to supplied Charset, will be no more than maxBytes in length. It could be less, depending on the charset chosen and the text being trimmed. This happens because it removes whole characters at once, which may trim several bytes, jumping you from 1 byte over the limit to two under.


public static String limitStringByBytes(String string, int maxBytes, String encoding) {
   if(string == null)
      return string;
   int i = string.length() - 1;
   int shaveBytes = computeByteLength(string,encoding) - maxBytes;
   while ( shaveBytes > 0 && i >= 0 ) {
      shaveBytes -= computeByteLength( string.charAt( i ), encoding );
      i--;
   }
   if( (i+1) <= 0 )
      return "";
   else if( (i+1) >= string.length() )
      return string;
   else
      return string.substring(0, i + 1 );
}

As a final note (thanks to the comments by one of our faithful and numerous readers), we would like to acknowledge that we have indeed ignored the existence of the supplementary planes of Unicode mappings, sticking to the Basic Multilingual Plane in this example. This avoids the even more intricate hassle of dealing with surrogate pairs. If one of these rather obscure character encodings (Byzantine Music Symbols, Phoenician, or my personal favorite, Deseret [editors note: yeah, I didn't know what it was either. Wikipedia to the rescue], for example) should appear, it’s possible that they might be truncated mid-character. According to the Unicode standard, this is an error, but also a very unlikely situation to encounter. Free Palantir t-shirt to the first person who posts a working example that properly deals with surrogates.

Tips and tricks for immutable objects

February 20th, 2007 | Bob

IBM DeveloperWorks has a good article on tips and tricks when creating immutable objects. Everyone knows that a good way to enforce thread safety without locks or explicit customization is to use immutable objects. This article covers some of the tricky parts of doing that:

  • You have to remember to make the members final.
  • You can cache state but not compute it in the constructor if you make it a write-once field. (Which, interestingly, does not mean it’s only written once. It means that it’s only ever written with one value.)
  • Write-once fields are guaranteed for both primitives and objects, but there’s no guarantee with objects that you see the same object reference between accesses.

Read the whole thing.

Add speel checking to your Swng text components (the squiggly way)

February 12th, 2007 | Brien



web start | download source

Marking up txt

Let’s hook Swing text components up to some tokenizing logic: a spell checker (the example above uses Jazzy), a regex (the example above will pick out some electronic musicians), or something more advanced.

Like all Swing components, text components are factored into an MVC setup. The model is javax.swing.text.Document; the view is javax.swing.plaf.TextUI (which delegates out to a javax.swing.text.View, which is generated from some ViewFactory); and the controller is the text component itself. A very simple way to add the notion of a token to this setup is to create a new kind Document – a TokenDocument.

When text is inserted into a token document, not only does it need to be tokenized, but existing tokens need to be shifted. We could do this manually; however, all javax.swing.text.Document provide something called a sticky position (javax.swing.text.Position) that that will do the shifting for us. Sticky positions are automatically updated by the document to reflect insertions and deletions of text. They also are guaranteed to maintain their ordering – that is, if position A is <= position B, it will always remain that way. This means the token document can maintain sorted trees of sticky positions (to store tokens) without worrying that their sort order will change.

Once we have the tokens in the model, we need to hook them into the view. We do this through a custom TextUI. It basically does everything a BasicTextUI does except it also paints a token layer underneath the highlights (above the background). In general with the javax.swing.text package, whenever code start painting outside of the view bounds (for each offset, this is the tightest bounding box for the letter at that offset), the dirty region needs to be expanded to include everywhere that was painted. In this code, you’ll see a line in the UI to deal with the dirty region.

Playing wth lines

Custom strokes like the squiggle stroke (above left) and smoothed noise stroke (above right) help give meaning to lines. Also, they can make an interface more fun.

Wrap pu

In this code, we extended the UI to paint lines under text. To change the display of the text itself, we would have to write our own View implementation (or more likely, extend PlainView [0]). This is not exclusive of the approach we took here. A more powerful View implementation could work in tandem with our custom UI, opening up even more ways to present information extracted from user-entered text.

Until next time!

[0] There’s a great introduction to this at Customizing a Text Editor, an article on the Sun Developer Network.

LICENSE — I wrote this using the Jazzy spell check engine + some open source trinkets (especially a Perlin noise generator). Except Jazzy (which is LGPL’d), all of it is Apache/BSD licensed.

Pipes: using unix pipelines for beautiful answers to quick and dirty questions

February 7th, 2007 | Ari

/loony/bin

As we approach a release at Palantir we usually cut to a stable branch that QA can start testing as a release candidate. Further bug fixing and testing may continue on trunk by the developers, but we code review changes before committing them to the stable branch. As the time to really cut the release gets truly imminent we start asking questions like:

What changes are on trunk that are not in the stable branch?

We’re less concerned with what the changes are and more concerned with who owns the changes. What really want to know is:

Do the changes on trunk represent pending changes that should be moved to stable or are they further development that shouldn’t be put into the stable branch for this release?

For the most part, the person that can answer that question is the coder who made the changes on trunk. To that end, what we really would love to have would be a report of all files in trunk that differ from the stable branch and who last touched the file. There isn’t really an svn command that will do this succintly, so I started thinking about how to accomplish this. I had an inkling that it could be all solved with a single Unix pipeline and so I set out on my way to craft such a beast. Here’s what I came up with in about ten minutes:

for name in `diff -r --brief --exclude=.svn pgstable/src pgtrunk/src  | awk '{print $4}' | grep pgtrunk `; do
    author=`svn info $name | grep -E "Last Changed Author" | awk '{print $4}'`;
    echo $author    $name;
done | sort | sed 's/pgtrunk\\/src\\///' > difflist.txt

Which produces output that looks like this:

gbush com/palantir/foo/Bar.java
bclinton com/palantir/baz/Fargle.java

How did I come up with such a beast? I deconstruct this inscrutable wonder after the jump.
Read the rest of this entry »

Music for coding

January 25th, 2007 | Ari

It’s amazing to me how much the music I’m listening to defines my energy level and output. Couple that with the open office environment we have at Palantir, and I end spending a good portion of the work day listening to music on my headphones. I often use different music for coding than debugging, as the tempo of the two activities feels very different to me. As my coworkers know, I’m a total beat-head and lover of drum machines, but even within that, I like to mix it up a bit. Here’s a quick list of the internet radio I like to listen to while coding:

  • HBR1 - the crazy Germans at HBR1 give us Psytrance on tap, probably the most driving of all the genres. The I.D.M. Tranceponder Stream stream is pretty consistently driving and great to code to.
  • Proton Radio - really good house music. Probably the best on the web. Consistently good to code to, slightly less energetic than the HBR1 pystrance streams. [stream link here].
  • SomaFM - an grand old institution of internet radio, SomaFM is operated out of San Francisco and has streams for every taste. People like Brien, who like things a bit more chill, love their famous flagship stream, Groove Salad. Their trance stream, known as Tag’s Trance Trip is similar to HBR1’s channels, but slightly less psy and a bit more classically trance-ish. There’s a are 11 different streams coming out of SomaFM, all worth checking out.
  • Digitally Imported Radio - they have a whole bunch of streams, without fancy names, split by genre. I’m personally a fan of their house and breaks streams, but there are many more.
  • BreaksFM - Breaks out of the UK. This station has some great underground, really big breaks. Occasionally, there’s a little too much talking by the DJ over the stream, but the music so exceptional, it more than makes up for it. Stream links: Channel 1 Channel 2.

Swing hack: making transparent components disappear

January 10th, 2007 | Brien

We encounter overlapping components a lot in our application, in situations ranging from a huge drag-and-drop panel across the main frame to small, unavoidable collisions in some of our smaller components. These overlaps almost always involve a transparent component that is used to paint something cool to the screen. Since the final layout looks visually good, it’s easy to think Swing is feeling good. However, this usually isn’t true.

Even though a component is transparent, Swing may still think it occupies some area. You can test this by creating a large transparent panel over a text box and calling SwingUtilities.getDeepestComponentAt(frame, textbox_midx, textbox_midy). You’d expect it to return the textbox; however, it actually returns the transparent panel! Whoa, that’s kind of silly, but what does it matter? The most noticeable loss is the cursor of the textbox. The cursor of the transparent panel will show up instead, even though it’s visually wrong. Other losses would be anything that relies on getDeepestComponentAt, findComponentAt, etc. to return an accurate result.

So how do we make a transparent component disappear to Swing? We were using the hack described by Alex Potochkin in “A well-behaved GlassPane,” for a while, but it turns out things like Container.findComponentAt() actually use Component.contains(). Setting it to a constant false has the effect of hiding all child components as well as the transparent component itself. A better Swing hack might be one that reports a point (x, y) contained in a parent component if it is contained in any child component. That’s what I have below. Just override JComponent.contains() and you’re set!

Here’s a code snippet illustrating the point:


  @Override
  public boolean contains(final int x, final int y) {
   return childrenContains( this, x, y );
  }

  /**
   * Tests whether any of the children in basec contain the given point
   * (in basec’s coordinate system). This does not call
   * basec.findComponentAt or basec.contains.
   */
  public static boolean childrenContains(final Container basec, final int x, final int y) {
    synchronized ( basec.getTreeLock() ) {
      final int size = basec.getComponentCount();
      for ( int i = 0; size > i; i++ ) {
        final Component c = basec.getComponent( i );
        if ( null != c ) {
          if ( c.contains( x - c.getX(), y - c.getY() ) ) {
            return true;
          }
        }
      }
    }
    return false;
  }

Palantir

Bad Behavior has blocked 494 access attempts in the last 7 days.