The Multiple Column Adventure

Over on the Tinderbox Wiki, Erc Abrahamsen started a discussion about exporting things in multiple columns. Multiple columns are a nice alternative to a long linear list; for example, here are the chapters of my forthcoming book on The Tinderbox Way.,

Table of Contents

  • Introduction: The Tinderbox Way
  • Notes
  • Lists and Containers
  • Attributes and Values
  • Prototypes
  • Emergent Structure
  • Agents
  • Links
  • Sharing Lists and Outlines
  • Sharing Notes: Personal Information Pages
  • Composing Print Documents
  • Sharing Notes: Writing Weblogs
  • Sharing Notes: Weblogs and Cheese Sandwiches
  • Why Is Tinderbox So Complicated?
  • Meeting Notes
  • Information Farming
  • Planning With Tinderbox

CSS3 will include multi-column lists, but few browsers implement much of CSS3. So, that won't work today. You can achieve multiple columns by floating the list elements, but this creates other potent hangups. How might we get this done right now?

The lists above are generated by three agents, named Column 1, Column 2, and Column 3, Each of those agents extracts a few items from a master list, called List. For example, Column 1's query is

#first(../list, $ChildCount(../list)/3)

and column 3 is

#inside(../list) & (!#inside(../Column 1) & (!#inside(../Column 2)

So, each agent grabs one column, and formats it as a list. The lists, in turn, have a fixed width and are floated, so each list follows the previous one. If we add new things to the list, the list grows automatically. (Requires Tinderbox 3.6 or later)

Making it Happen

My first reaction was, "this won't work, because Tinderbox can't do division," But I was wrong: Tinderbox does do division! Tinderbox is a big program, and it offers lots of ways to get stuff done. I'd forgotten about this one.

By second reaction was, "this won't work, because the second argument to #first has to be a number. But, why not let it be an expression? Where would the harm be?

Unfortunately, we're right up against the release deadline. Could we make the change without fouling up other parts of Tinderbox? It means changing AgentQuery and AgentQueryParser, as well as building an unexpected connection from AgentQuery to ActionExpressionParser, a class that was really meant to be private to ActionParser. It's a whole bunch of complex moving parts.

It turned out to be practical, because these parts of Tinderbox have a good test vise in place. The test vise, in turn, is part of the Windows project: it makes sure agents do the same things on Macintosh and on Windows. So, the Windows port (and the big investment we've made in making Macintosh and Windows share so much code) has had nice benefits for Macintosh users — even before we've got Tinderbox for Windows to beta 1.