You are on page 1of 67

ct ions

an

as
Mark Bernstein

Copyright

2015 by Eastgate

Tinderboxr"

is a trademark

the property

of Eastgate

of their respective

The story and example expense


mentioned

Systems, Inc. All Rights Reserved.


Systems, Inc. All other trademarks

owners.
account data used here is a work of fiction. All persons,

therein are imaginary, and any resemblance

entirely coincidental.

herein are used illustratively and are

to actual places, institutions,

places, and institutions

or persons alive or dead, is

Table of Contents
1. Actions and Dashboards

2. A Look At The Data

3. Collecting

Notes with Agents

12

4. Summarizing Agent Information

With Display Expressions

23

5. Summarizing

With Dashboard Notes

33

Agent Information

6. Actions For Automating

Routine Chores

40

7. Progress Bars

47

8. Seeing The Data

55

9. Treemaps

60

1. Actions and Dashboards


Tinderbox is the tool for notes, a unique and powerful approach to
visualizing, organizing, and sharing information about complex problems.
Tinderbox makes it easy to make notes, even for ambitious and complex
projects that may last for months or years and may take unexpected twists
and turns. Tinderbox can actively work with you, taking actions to help keep
your notes organized and to help you visualize and understand them.
If you'd like to know more about the design of Tinderbox and why it behaves
as it does, you may enjoy The Tinderbox Way, a book about Tinderbox that is
published by Eastgate. (order here)

You don't need to read this


There are lots of ways to use Tinderbox. The approach here is not the only or
the best way to use Tinderbox. As you use Tinderbox, you will notice many
alternate ways to do things; don't assume the method used here is the best
for you.

If you're just getting started with Tinderbox, you might want to read some of
Getting Started With Tinderbox first. You'll find that tutorial in the Tinderbox
Help menu.
Actions can help reduce boring and routine chores, freeing you to
concentrate on matters that do require your full attention. They can help
avoid mistakes and oversights, such as filling in dates or copying routine
metadata. Not every Tinderbox project requires lots of actions. If you find it
easier to do something yourself, there may be no reason to have Tinderbox
do it for you.

Things Change
This tutorial was originally written for Tinderbox 6.3. New versions of
Tinderbox appear frequently, and the version you're using is probably newer.
Nearly 100 official Tinderbox versions have already been released to
customers, and updates arrive frequently.
Details of the sample document may have changed since the screen shots in
this tutorial were captured, and as a result some of the results will differ
numerically from those illustrated here.

Some details discussed here may vary from the version of the program you
are using. Don't worry too much: the underlying principles and concepts still
apply. If you're stuck, feel free to ask on the Tinderbox Forum, or email
Eastgate.

TheProblem
In this tutorial, we '11explore and analyze some expenses incurred during a
fictional business trip. The sample data and analytical tools can be found in a
Tinderbox document you can download from:
http:/ /www.eastgate.com/ download/ ActionsAndDashboards.dmg
In this tutorial, we explore some ways we can use Tinderbox to automate,
analyze, and visualize this rather mundane information. Realistically, you
would be unlikely to want to invest this much care in such mundane and
manageable data, but the same techniques can be applied to your own,
subtler problems.
Suspend your disbelief: If you're confronting problems that don't seem
analogous to those described here, Tinderbox might still be able to help.

Again, ask in the Tinderbox forum, where lots of Tinderbox users welcome
such questions, or email Eastgate.
Other Resources

Other places to find information about Tinderbox include:


Tinderbox Help, a detailed manual found in the Help menu.
Getting Started With Tinderbox, a tutorial found in the Help menu.
The Tinderbox Forum, http://eastgate.com/Tinderbox/forum/, is an active and friendly
meeting place for active Tinderbox users from a wide range of fields.
aTbRef - a Tinderbox Reference - is a technical reference for Tinderbox written by
Tinderbox user Mark Anderson and available both as a web site and a Tinderbox
document at http://www.acrobatfaq.com/atbref6/.
Mark Bernstein's book The Tinderbox Way discusses the core ideas that underlie
Tinderbox. It is available as an eBook from Eastgate.

2.

A LookAtTheData

Lise Nakamura is Vice President of Design at TK Corporation. an


international technology company that creates tools to help parents keep
track of what their children are doing 1 In an increasingly complex and
mobile world, TK's products have been wildly successful and the underlying
technology has found spinoff opportunities in fields ranging from warehouse
management to law enforcement.
On April 24, the weekly meeting of the Executive Planning Committee
discussed repeated delays and performance issues with the overseas supply
chain for the company's crucial new product, slated to be announced in a
mere four months. The natural person to look into these problems is Don
Frost, VP of Operations and Nakamura's supervisor. Unfortunately, Frost is
not available until April 28: he is recently divorced and his daughter is
competing in an invitational tournament in Chicago this weekend. CEO Ken
Biggs is reluctant to wait, and the committee agrees that Nakamura will
leave for the Paris office on the first available flight.

1 All

the people, places, and institutions mentioned here are fictitious, or are used fictitiously.

Over the course of the following weeks, Nakamura visits a number of cities
across Europe and North Africa, meeting with TK personnel, contractors,
vendors, government officials, heads of charitable foundations and other
stakeholders in order to understand the causes for these problems.
The first, leftmost tab in the example Tinderbox document is simply a list of
expenses incurred during this trip.
e

=- Expense

I=IExpen.. .

Chara ... I~

lnfrastr .. . -

Account. tbx

Status

~-'-~~~~-'-,.-~~___;:_~~~--

ii]

Ed'tec!

Protot...

Chara ...

laBJExpen .. . ~

cities

Expe nse Account


T LI

HTML

Expense Account

T LI

Boston

ti

O ()

Friday, 2'+
April
flight to Paris

Cl

lunch

El
ti

guidebook

[j

maps

T LI

Friday,2lf April

Start Date

ti

Prev iew

4/24/2015, 6:33 PM

Sent abroad without notice or advance planning


during weekly Executive Planning Committee.
Purpose: troubleshoot repeated delays and
quality issues th at imperil the crucial TK launch .

power adapter
0

Paris

ti

Saturday, 25 April

Cl

car to hotel

ti

evening dress

Cl

taxi

ti

Sunday,26 April

[j

lunch

Authorization : Ken Biggs, oral ("Why are you


still here?")
Note to Accounting: the overnight bag I keep in
my trunk is meant for overnight trips to New
York or SF. It's not up to open-ended European
jaunts. This is going to cost a fortune. If you have
tears, prepare to shed them , and consider the
ramifications of a delayed or botched product
launch.

...

This list contains three kinds of notes. Each type of note has its own
prototype and appearance:
1. City notes are containers for each major stop in Nakamura's trip. Their
titles are bold.

2. Summary notes briefly outline each day's business, both for mandatory
record-keeping and to provide context to the Account Department when
they come to authorize reimbursement. Their titles use the Sketchnote
font.
3. Expense notes describe one expenditure, explaining who was paid, how
the payment was made, and occasionally providing additional detail for
the benefit of the Accounting or Legal departments. Their titles use plain
font.

Prototypes
Click on the Prototypes tab to see the prototypes used in this document. In
the upper right-hand corner of the map, the adornment named Data
Prototypes contains prototypes used to characterize these expenses:

City
Summary
Draft Summary
Expense

The prototype defines what sort of note each note is. Every expense record
adopts Expense as its prototype, so it's easy to find expenses and separate
them from other notes.
Second, the prototype defines the base appearance of each note. The
distinctive font and color the Summary notes and the bold font of City notes
are inherited from the prototype; we don't need to remember to set these
manually, and have no worries about
accidental inconsistencies.

,.,Expense Account.tbx

~ ~ ~ ~-- =~--~~---~

attributes that are particularly relevant to


notes of that type.
City simply records the $Currency typically
used in that place and the $StartDate of our visit to that city.
Summary uses $StartDate

to record the day it summarizes.

Edited

~~- -m~ .. ~.
HTML

Third, each prototype defines some key

ncy

rt oate

Preview

10

Each Expense records a list of information about a single expenditure.


$StartDate is the date of payment, and $City is the place where the
payment was made. $Recipient is a user
attribute where we record whom we paid.
o Expense
We record the $Amount we paid, the
$Currency we used, and the equivalent of
this payment in US $Dollars 2 $Method
records whether the recipient was paid in
cash or credit card. Finally, $Tags holds a
set of tags that will help us (and the
Accounting Department) categorize and account for each expense. Tags
might include "lodging", "travel", "meals" (with additional tags such as

HTML

Preview

,----------,

"lunch" and "dinner"), as well as tags about client accounts or projects


associated with the expense.
Every expense needs to record this information. It does us little good, for
example, to know that we spent 46.50 on dinner in Zurich if we forget to

Later, we will arrange this Tinderbox document so it automatically performs the currency conversions for us, and fills out many of
these fields automatically. If we expect to have only a few expenses over a short period of time, we could simply fill these out
manually; if we will be using this project daily for months or years, we might eventually decide to automate some of the more tedious
or error-prone chores as we have done in this example.

11

record whether we paid in Euros or Dollars or Swiss Francs. The list of key
attributes helps ensure that we will capture the information we need.
rr2r

Resist the temptation to add unnecessary key attributes. When you are in a hurry, you'll

be tempted to skip over them or to add the data later, but questions that can be answered
today with ease may prove nettlesome to recall next week, or the night before the expense
report is due.

12

3. Collecting Notes with Agents


Tinderbox agents constantly scan your document, looking for notes that
match their specific criteria. When an agent finds a note that satisfies the
agent's query, it creates an alias of that note inside the agent. The agent may
perform an action on the matching note. Finally, the agent may sort the
aliases it has gathered.
In this chapter, we will focus on agent queries - on the ways agents look for
notes that interest us.
To begin, open your copy of the Expense Account sample document and
select the tab labeled "Examples". This container holds a number of simple
agents discussed below. As you read, feel free to add your own agents to this
container.

Collecting Expenses
The first agent in the Example is named All Expenses, and collects every
note that uses the Expense prototype. In outline view, click on All Expenses
to select it, and click on its disclosure triangle to expand it. Inside the agent,

13

you will see a 1ong list of aliases' one


for each expense recorded in the

_.___

Action Inspector, marked with a e


icon, and choose the Query pane.
This Query is simply a logical
expression which is applied in turn
to every note; if the result is true, the
note's alias is gathered by the agent,
while if the result is false the agent
takes no further action on that note.
Agent: All Expenses
Query: $Prototype=="Expense"

<>

All Expenses

entire document.
With All Expenses selected, open
the Inspector by choosing Inspector
from the Windows menu. Select the

._ A,...
c.....
t io___
n_,,
l_
ns__
p___
ec_to,...
r_
:E
_x_,,
pe_n_se
_A
_,_
c_c_ou...,
nt
4

Action

Rule

Examples:
$Text.contains{ Lincoln");
$Prototype-=' Person ;

Edict

Sort
Items Found
51

$Prototype=="Expense"

Case insens itive

Priority

--- ---

I Normal

14

The unusual operator"==" is the comparison operator, and is true if two things are equal.
We use it here to avoid confusion with the assignment operator"=", which sets the value
of an attribute.

Note that, in the right-hand corner of this pane, Tinderbox displays the
number of notes currently found by this agent.
Sorting Expenses

Next, switch to the Sort pane of the


Action Inspector. Here, we choose
how the aliases inside the agent
should be arranged. Initially, they
are sorted using the system attribute
$StartDate, in the Event category.
The expenses are arranged in
chronological order, with the first
expenses - lunch at the airport and a
Paris guidebook- at the top and the
latest expenses at the bottom.
We can easily choose different

Act ion Inspector: Expense Account

<>

All Expenses
I

Query

Act ion

Rule

Edict

Sort By

reverse

I StartDate

I case -sens itive

I~

and by
_ d_o_n_
't _so_rt~

-- -

l_c_a_
se_-s_e_
ns_it1_
've~

_. B_

15

sorting criteria. Be sure that All Expenses is still selected, and click on the
Sort By pulldown menu and select Dollars from the User category, near the
top of the menu. The list is now sorted by expense, starting with a $4.99
downloadable map. Click on the reverse checkbox to invert the sort order;
now, the first item is our costly same-day flight from Boston to Paris.
For convenience, collapse the outline disclosure triangle of All Expenses
before continuing.

Keeping An Eye On Agents


The Agents and Rules pane of the
Tinderbox Inspector provides useful
information on what your agents are
doing from moment to moment.

Tinderbox Inspector: Expense Account

<>

Expense Account

Info

Agents & Rules

17 agents
meals

The upper bar in this inspector


chief interest here. We can see
glance how many agents this
document contains, and that
Tinderbox is currently working
the agent named "meals". The

is our
at a

11 rules
days
Indicates the most recently evaluated rule and
agent. The marker reflects the agent's position
the document outline

on
blue

. I
te
S 1mpeno

Oed icts

in

16

marker gradually moves from left to right as Tinderbox runs agents from the
start of your document to its end, and you can judge from its progress how
much time it takes for Tinderbox to bring all your agents up to date.

Collecting Specific Expenses


We might use agents to examine some specific expense categories. For
example, the agent Meals gathers all expenses relating to meals.
Agent:
Query:
Sort:

Meals
$Prototype==''Expense''
$StartDate

& $Tags.contains(''meal'')

To qualify for this agent, a note must be an expense and it must have the tag
"meal." The ampersand (&) is the logical "and" operator; the query is true if
its left side is true and its right side is also true.
$Tags is a set attribute - a list of labels or "tags," separated by semicolons.
The expression
$Tags.contains(''meal'')

is true if one of the elements in $Tags is "meal".

17

Tinderbox knows that if the left side of the & is false, the result must be false and that
there is no need for further work. Knowing this can sometimes make your agents more
efficient.

Again, view the query and sort in the inspector, and expand the agent in
outline view to see which notes it has gathered. It's always a good idea to
examine what your agents find!

Collecting Major Expenses


We might require special authorization for certain expenses. The agent
Authorization Required looks for all expenses over $1000, and also for all
cash expenditures of any amount.
Agent: Authorization
Required
Query: inside(/Examples/All
Expenses) & ($Dollars>1000

$Method=''cash'')

The first clause is true for all notes that are inside the agent All Expenses
inside the container Examples. In this case, we might equivalently have
written
$Prototype==''Expense''

18

but if All Expenses required lots of computing work to finds its results,
inside() lets other agents take advantage of that work without having to
replicate it.
The second clause
($Dollars>1000

$Method==''cash'')

is contained in parentheses because we want its result to be true if either the


cost exceeded the $1000 threshold of if the payment was made in cash. The
"I" symbol is the logical "or" operator, and is true if either its left clause is
true or if its right-clause is true.

Weekends,
Only
Because a proposed cost-control initiative advocates minimizing business
travel over weekends, we might need to identify expenditures on Saturdays
and Sundays.
Agent: Weekends Only
Query: $Prototype==''Expense''
Sort:
$StartDate

& ( $StartDate.weekday==6l$StartDate.weekday==7)

The .weekday facet of date attributes returns the weekday as a number,


where "1" corresponds to Monday and "7" corresponds to Sunday. We sort

19

this agent's results by $StartDate for clarity, so expenses from our first
weekend abroad aren't mixed with expenses from our second weekend.

May Day
We might want to locate all expenses from a specific date.
Agent: May Day
Query: $Prototype==''Expense''
Sort:
$StartDate

& $StartDate==date(''5/1/2015''

This is simple enough, but does raise a few tricky issues concerning dates.
First, the date() operator converts strings to dates. The string can be any
date that Tinderbox recognizes, including dates expressed in your
computer's local date preferences. If we were using a computer configured
with British date preferences (in System Preferences:Language and Region),
we'd write "1/5/2015" in conformance with British usage. Alternatively, we
could write "May 1, 2015" in either in the US or 1 May 2015 in the UK.
Second, Tinderbox dates always include a time of day. By convention, the
equality operator ==is true if two dates fall on the same calendar day. If
event A begins on Monday morning and event B begins on Monday

20

== $StartDate(B)

afternoon, then $StartDate(A)

is true, even though

$ St a r t Da t e (A) < $ S t a r t Da t e ( B) is also true 3.

~aking A Timeline
Lise Nakamura's trip is long and complicated, and the Accounting
Department might find it a bit confusing. A timeline can help sort things out.

lvienna

lzurich

!Boston
lstavange r(bycar)

!Marra1<esh

fnearComo

laoston

!Gothenburg

!Torino

!Pars

!London:
Watchfu/Co r,
!Te/Aviv

loijon

4/26/20 15

5/3/20 15

5/ 10/20 15

5/ 17/201 5

All Tinderbox date attributes record a moment in time, including the time of day. When people ask whether two dates are equal,
though, they most often want to know if they refer to the same calendar day, not the same second.

21

We begin by making an agent to gather all the City notes.


Agent: All Cities
Query: $Prototype=="City"

Next, we '11focus the view to focus only on the results of this agent. Select
All Cities and choose Focus View

,.. Expense Ace


from the View menu. Finally,
~~ Expense . . . =Prototype- ~ All Cities
=Characters =In
choose Timeline from the View
Expense Ac.count
T l:l
All Cities
menu. We see a simple timeline of
l:l
Zurich
the cities visited in the course of this
l:l
near Como
.
l:l
Vienna
trip.
l:l
Gothenburg
JJ ()

To return to the outline view, choose


Outline from the View menu and
then click on Examples in the
breadcrumb bar to expand the view
to the Examples container.

l:l

Paris

l:l

Torino

l:l

London: Watchfu/Con

l:l

Tel Aviv

l:l

Stavanger (by car)

Mistakes: Finding Missing Tags


We use $Tags to assign each expenditure to one or more categories, so the
Accounting Department can handle each expense appropriately. Common

22

tags include "entertainment", "transportation", "lodging", and "meals".


Meals are also tagged with "breakfast", "lunch" or "dinner" where
appropriate. Tags might indicate particular colleagues or customers whose
bill was paid, accounts that might be charged for the expense, and other
short memoranda.
In the rush of work, we might forget to tag an expense; an agent can easily
find any expenses without tags.
Agent: No Tags
Query: $Prototype==''Expense''

& $Tags==''''

Only slightly more work is required to locate expenses for meals that aren't
tagged with a particular meal.
Agent: No Meal
& $Tags.contains(''meal'')
Query: $Prototype==''Expense''
& !($Tags.contains(''breakfast'')
I $Tags.contains(''lunch'')
$Tags.contains(''dinner'')
)

The "!" operator is the "not" operator: if what follows it is true, it returns
false.

23

4. Summarizing Agent Information With


Display Expressions
The agent queries we created in the
.
.
,
previous section are expressions values or combinations of values.
Another use for expressions is the
note's Display Expression, a formula
Tinderbox uses to determine how
each note should be labelled 4 Each
note can have its own Display
Expression, stored in its attribute
$DisplayExpression.
The Title pane of the Text inspector
lets you inspect and change display
expressions. Simply type the Display
Expression in the appropriate text
4

All Expenses:55
Subtitle

Caption

Co lor:

automatic

Alignment:

left
Map

Size:

l 14
n

Hover

Text
A
V

Outline

14

Bold

Strikethrough

Display Expression
$Name+ ": "+$Ch ildCount

II

Display Express ion Enabled

If a note has no $DisplayExpression, Tinderbox displays the note's $Name. If the note has a $DisplayExpression, Tinderbox
evaluates the expression and displays the result.

24

box and press [Return].


~The

Display Expression is a formula, a recipe for constructing the name. Don't confuse
the expression with its result. Several notes might have the identical expression but, since
the notes are different, they would display different results.

Counting Notes
The first agent we created in the Examples container collected every Expense
in the document.
Agent: All Expenses
Query: $Prototype== Expense
11

11

To keep track of the total number of


expenses in the document, we could set
up this agent to display the number of
expenses it found in its title.
DisplayExpression:

$Name+
11

11
:

Sandbox
a place for experimental agents
All Expenses: 55

+$ChildCount

When applied to strings like $Name, the"+" operator joins two strings
together. Thus, Tinderbox starts with the note's $Name, appends a colon,
and then appends the number of children inside the agent.
Alternatively, we might write

25

DisplayExpression:

$ChildCount+''

Expenses''

to label the agent "55 Expenses."

Total Expense
Rather than reporting the number of expenses, we might be interested in the
cumulative total. Rather than change the agent All Expenses again, we'll
define a new agent.
Agent: Total
Query: inside(/Examples/All
Expenses)
Display Expression: $Name+'': ''+sum(children,$Dollars)

The query simply matches all notes that the agent named "All Expenses" has
found; this is a convenient shortcut that lets agents work together without
duplicating work.
The display expression adds up the value of $Dollars for all the agent's
children, and appends the result to the agent's name. This will display the
total as a number.
Total: 16167
Since we know the result is expressed in our local currency, we might format
it more suitably:

26

Display

Expression:

$Name+'': ''+sum(children,$Dollars).format(''$'')

This takes the number


sum(children,$Dollars)

and asks Tinderbox to format it


[Number].format(format-string)

The"$" argument to format means "format this number according to the


computer's local currency formatting." The result will look something like
this:
Total: $16,167.00
The currency symbol and conventions for punctuating currency are based on
the locale you choose in System Preferences: Language & Region.

First and Last Notes


Instead of knowing the total, we might want our agent to tell us about the
dates covered in its list of expenses.
Agent: Range
Query: inside(/Examples/All
Expenses)
Sort:
StartDate
Display Expression: $Name+'': ''+$StartDate(child).format(''l'')

27

We sort the agent to ensure that the first child is the earliest expense. The
"l" argument to the format() operator formats the date using your locale's
short date format. In the US, the result should look something like this:
Range: 4/25/15
Elsewhere, the date will be formatted according to your system settings
We might display the latest expense, too, changing the display expression to
$Name+'': ''+$StartDate(child).format(''l'')+''-''+$StartDate(lastChild).format(''l'')

The result will now look something like:


Range: 4/24/15 - 5/7 /15
Of course, the actual results might differ depending on your system's
language and format settings.

Taking The Average, Finding The Range


Perhaps we need the average dinner bill.
Agent: Dinners
Query: inside(/Examples/All
Expenses)&$Tags.contains(''dinner'')
Sort:
StartDate
Display Expression: $Name+'': ''+avg(children,$Dollars).format(''l'')

28

Alternatively, we might be interested in the largest and the smallest dinner


expenses. Let's construct the display expression step by step; this is usually
the best approach to building a complex expression.
We begin very simply.
Display

Expression:

$Name+'': ''

This displays:
Dinners:
The min and max operators require a list of values. We can create a list using
the co 11 ec t () function.
Display

Expression:

$Name+'': ''+collect(children,$Dollars)

This displays a list of dinner bills separated by semicolons:


Dinners: 153.36;223.65;45.36;46.44;34.56;248.83

....

Tinderbox has gone through each of the agent's children, collected its value
of $Dollars, and appended it to this list. To find the smallest bill, we pass the
list to min():
Display

Expression:

$Name+'': ''+min(collect(children,$Dollars))

This displays something like:

29

Dinners: 20.8
As before, we'll format the result as currency.
Display Expression:

$Name+'': ''+min(collect(children,$Dollars)).format(''$'')

which displays:
Dinners: $20.80
Finally, we'll add a dash and then find the largest dinner bill:

Display Expression:

$Name+'': ''+ min(collect(children,$Dollars)).format(''$'')


+'' - '' + max(collect(children,$Dollars)).format(''$'')

Which displays something like


Dinners: $20.80 - $525.00

30

Incrementally building and testing complex expressions lets you re.fine your
work in small and simple steps and helps identify mistakes at once.

SummaryTables
In maps, when an agent has located some notes, we
typically see those notes inside the agent.
Sometimes, it's more informative to list those notes
by name, perhaps appending some additional
columns of information we want to see. We can add
a summary table to any container or agent to do this.
For example, select the tab named Status and locate
the agent "missing tags". This agent looks for any Expense reports that have
no tags; because every expense should have some category or explanation,

31

we'll need to locate any unexplained expenses before submitting our report
to the Accounting Department.
<>

We can inspect the agent's query by selecting


it and opening the action inspector. The agent
looks through the entire document and finds
notes that use Expense as a prototype but that
have no tags.
The summary table is drawn in the agent's
title bar below the agent's name, provided
there's sufficient space. To give us room to
display the table, select the agent and then
drag the top of the title bar upward, so the
title bar fills the agent.

missing tags

)@M
Act ion

Rule

Examp es:
$Text contains( Lincoln");
$Prototype=="Person ;

Edict

Sort
Items Found

Protot ype="Expense "&$Tags==""

Z) Case insensitive

Next, click on the Summary Table widget, marked


here with a blue arrow. Each column in the summary
table is listed in turn: here, we have only a single
column which lists the note's name. We could add
additional columns here if we wished. Click

Priority

Normal
---

32

anywhere outside the Summary Table Properties popover to dismiss it.


As downloaded, the sample file has no
untagged expenses and so the summary
table is empty. Double-click the map
background to create a new note, name
it "test expense", and use the note's
prototype tab to select the Prototype
"Expense". After a few seconds, the
note will appear in the summary table.
[if

You may choose File ~ Update Agents


Now to ask Tinderbox to update all
agents right away.

Summary Table Propert ies

IHeading
Name

G] - ll

Expression

$Name

Use Headings

Finally, delete "test expense"; after a few seconds, the note will disappe ar
from the summary table.
[if

Remember to delete the text expense, so it doesn't clutter results in subsequent


chapt ers.

33

5. Summarizing Agent Information With


Dashboard Notes
Display expressions work well if we want to extract one key aspect of an
agent, provided that we remember to look at the agent. Sometimes, we might
want to display several aspects of an agent, or of several agents that might be
scattered throughout your document.
A Tinderbox dashboardis simply a collection of notes that display summary
information of interest in a single convenient place. The expense account
sample file includes a dashboard container named Status. Click on its map
view tab for an overview of the entire document.

A Dashboard
Note
The left-hand side of this dashboard has several notes that use the prototype
Dashboard for a distinctive appearance. The Dashboard prototype is located
in the Prototypes folder, and has the following properties:
Color: "3" (matching the background color)
BorderColor: transparent

34

BorderStyle: plain
Shadow: false
SubtitleSize: 75
SubtitleColor: greens

Using the Inspector to set all these parameters for each dashboard note
could be tedious, but prototypes lets notes inherit all these characteristics in
one step, and also let you modify the appearance of all dashboard notes by
changing the prototype.

Counting Notes: Subtitle


We begin with the note "transactions," which counts the total number of
expenses found in the entire document. This note has a Rule:
Name: transactions
Rule: $Subtitle=$ChildCount(/Infrastructure/all

expenses)

This rule asks Tinderbox to locate the child count of another note - an
agent named "all expenses" inside a container named "Infrastructure" - and
then to store the result in this note's subtitle.

s The color "green" in this document has been defined as #5e8663 - a neutral gray-green.

35

Tinderbox constantly evaluates rules, running the rules for each note until it
reaches the end of the document and then starting over at the document's
beginning6.

transactions

55
Getting The Total
In the upper left-hand corner of the dashboard, we see a
note named "total cost" that adds up the cost of every
expense in the document. Again, we construct a rule
which finds the total cost and stores that cost in Subtitle.
Let's consider how we might write this rule in small and
simple steps.

total cost

42

Name: total cost


Rule: $Subtitle=42

6 A second kind of rule, called an Edict, is run less frequently than regular rules and is useful when the result of a rule will seldom
change.

This is very simple indeed - it takes the number "42" and stores it in
$Subtitle. Once the rule runs, this dummy value will appear in the dashboard.
(You may need to deselect the note to allow the screen to update.)
We'd like the subtitle to be formatted as currency.
total cost

Name: total cost


Rule: $Subtitle=42.format("$")

$42.00

Finally, we replace the dummy value with the real value.


We'll look inside the container named Expense Account and total up all the
dollars expended:
Name: total cost
Rule: $Subtitle=sum(descendants(/Expense

Account),$Dollars).format("$")

total cost

___
11,955.30

37

The Places We've Been


Each expense entry records the city where the expense was incurred. How
many cities have we visited?
First, we need a list of all the expenses. The expression
find(Prototype==''Expense'')

builds exactly this list, returning the $Path for each note that uses "Expense"
as its prototype. Next, we find the value of $City for each expense:
collect(find($Prototype=''Expense''),

$City)

Once we have the list of cities, we remove all any duplicates:


collect(find($Prototype=''Expense''),

$City).unique

and, to wrap everything up, we get the size of the remaining list
collect(find($Prototype=''Expense''),

$City).unique.size

cities

14
So, our dashboard note is:
Name: cities
Rule: $Subtitle=collect(find($Prototype=''Expense''),$City).unique.size

38

First and Last

What is the earliest expense associated with this trip? We already have an
agent /Infrastructure/ all expenses that locates every expense record. It
keeps the expenses sorted by date, so the earliest expense will be that agent's
first child.
$StartDate(child(/Infrastructure/all

expenses))

The latest date, conversely, would be


$StartDate(lastChild(/Infrastructure/all

expenses))
start

For convenience, we can store this data in the $StartDate of this


dashboard note.
$StartDate=$StartDate(child(/Infrastructure/all

expenses))

Finally, we format the date and store the result in the dashboard
note's subtitle.
Name: start
Rule: $StartDate=$StartDate(child(/Infrastructure/all
m/d
$Subtitle=$StartDate.format(
11

11

expenses));

4/24
end

5/7

39

How long have we been away? Our start date is now conveniently available
as
$StartDate(/Status/start)

and our end date is simply


$StartDate(/Status/end)

so we can very easily write a note that reports how long we've
been away from the office.
Name: days
Rule: $Subtitle=days($StartDate(/Status/start),

$StartDate(/Status/end))

days

13

40

6. Actions For Automating Routine Chores


In the previous chapter, we used rules to manipulate and move data to some
dashboard notes. Now, we turn to actions that help keep your information
organized, consistent, and up to date.
Tinderbox provides four kinds of actions:
Rules are actions that are applied periodically to a single note
Edicts are like rules, but are performed less frequently
Agent actions are applied to notes that match the agent's query
OnAdd actions are applied when notes are added to a container or are
placed atop an adornment

Keeping Your Data Consistent


We use the $Tags field, a set attribute, to annotate each expense with
information about purpose and context. In many cases, the Accounting
Department requires tags to process each expense and to apply the charge to
the appropriate account. Other tags are for our own convenience, so we can
more readily relocate various kinds of expenses.

41

For example, all expenses related to transportation should be tagged with


"transportation" and also with the kind of transport: plane, train, rented car,
taxi, and so forth. If we're in a hurry or distracted, we might omit one of
these tags.
Click on the Infrastructure tab to view an outline of the Infrastructure
container. There you will find an agent named "taxis" that looks for notes
whose title contains the letters "taxi" or that are tagged with "taxi".
Name:
Query:
Action:

taxis
inside(/Infrastructure/all
expenses)
$Tags.contains(''taxi''))
$Tags=$Tags+''taxi;transportation''

& ($Name.contains(''taxi'')

The action makes adds the tags "transportation" and "taxi" to the tags of
any expense the agent finds. Since $Tags is a set, duplicate tags are ignored;
if "taxi" or "transportation" - or both - have already been added, the action
leaves them untouched. But if one or both tags were forgotten, this agent
automatically adds them.

Currency Conversion
When we add an expense item, we write down the $Amount we paid and the
$Currency we used. In the US, the value of $Currency will be "$", in the

42

UK, $Currency will be"", in the EU, "". Our company maintains
accounts in dollars, and Ms. Nakamura will want to be reimbursed in dollars;
naturally, we want to be clear and consistent in converting currency
Inside the Infrastructure container, you will find a container named
"currency conversion" that automates conversion of other currency into
dollars. The first agent,"$", simply copies $Amount to $Dollars since no
conversion is needed:
Name: $
Query: inside(/Infrastructure/all
Action:$Dollars=$Amount

expenses)&$Currency=''$''

The next agent, "", converts euros to dollars:


Name:
Query: inside(/Infrastructure/all
expenses)&$Currency=''''
Action:$D0llars=$Amount*$ExchangeRate(/Config/euro)

Whenever this agent finds an expense denominated in euros, it multiplies the


base amount by the value of the user attribute $ExchangeRate taken from
the note named "euro" in the container Config. When filing the expense
report, we simply fill in the current exchange rate in this note, and all eurodenominated expenses will automatically be updated.
The agent""

does precisely the same thing, using /Config/:

43

Name: f
Query: inside(/Infrastructure/all
expenses)&$Currency="f"
Action:$D0llars=$Amount*$ExchangeRate(/Config/f)

Similar agents convert Swiss Francs (CHF) and Israeli Shekels (ILS). We
never need to record more than one amount per transaction, and there is no
risk of an accidental mistake or inconsistency when applying conversion
rates.

Saving Steps: Copying Currency


Next, let's revisit the raw expense reports.
Click the left-most tab "Expense Account"
and scroll to the top of the outline. Select
the note "Boston" and view its OnAdd
action in the Action Inspector.
Boston uses the prototype "City" and
inherited this action from its prototype. The
action contains four distinct steps: whenever
we add a note inside Boston,
1. The note's $City is set to the name of its parent,

which is "Boston".

e
L...=

Act ion Inspector: Expense Account


---L....:l

__,_

--'

<>

Boston
Query

ExarnplE. ;iiuolor

'rnd '.

$City=$Name(parent);
$Prototype="Expense";
$Currency
= $Currency(parent);
$StartDate
= $StartDate(prevSibling)

44

2. The note's $Prototype is set to "Expense."


3. If no $Currency has been specified, the note's $Currency is set to the $Currency of its
parent. The currency of Boston is"$", so expenses in Boston will use dollars unless you
specify otherwise.
4. If no $StartDate has been specified, the note's $StartDate is set to the start date of the
previous sibling in that city.

Note that these are all initial assumptions, not hard and fast constraints. If
we want the note to be a summary, we can change the prototype from
"Expense" to "Summary". If we want to specify a different date or use a
different currency, we are free to do so. By providing reasonable guesses,
Tinderbox saves time and avoid missing data.
Saving Steps: Initial Values

The City notes in our expense container serve two functions. First, they
organize expenses according to the major stops in our trip, breaking up the
long list of expense records into manageable segments. Second, each City
container has an OnAdd action, inherited from the prototype, which enters
some preliminary guesses about each newly-created note.
OnAdd: $Prototype="Expense";
$City=$Name(parent);
$Currency
$Currency(parent);
$StartDate I= $StartDate(prevSibling)

I=

45

When we create a note inside a city, Tinderbox takes several actions:


Tinderbox guesses that the note is likely to be an Expense, and sets the
prototype accordingly.
Tinderbox guesses that the City in which the expense was incurred
corresponds to the City in which we were staying. This might be wrong we might have been visiting a suburb or we might have been in transit to a
new destination - but it's a reasonable first assumption.
The currency for the expense is set to the Currency used in that city.
Again, this might be incorrect, but it's a good first guess. We use the
conditional assignment operator I=here so that the assignment is ignored
if $Currency already has a value - if, for example, we're moving an
expense record that we'd accidentally filed in the wrong place.
The $StartDate for this expense, if it hasn't already been set, is the same as
the $StartDate for the expense immediately above it. This lets us rapidly
enter several expenses for the same date.
OnAdd actions are only performed when we create a note or add that note to
a new container; they're suggestions, not constraints. If Tinderbox guesses
that we wanted to make an Expense but we really wanted to create a new

46

Summary, we simply change the prototype for the new note. Tinderbox
might guesses that we had lunch in London, since that's where we are
staying; if we were actually in Oxford, we simply change the City.

47

7. Progress Bars
Inside the Expense Account container, we have three kinds of notes:
Summaries provide narrative context for each day
Cities mark arrivals in each new place
Expenses record individual expenditures

It is clearly desirable to record each expense promptly, while the details are
fresh in our mind. Summaries are indispensable and mandatory, but these
always pose a problem. First, the traveller is frequently exhausted at the end
of the day, and the last thing he or she wants to do is to stay up writing a
narrative for the Accounting department. Second, the key elements from the
day's activities might not always be immediately apparent, and a few day's
perspective may help focus the summary on the most consequential matters.
Nevertheless, the summary is important and ought to be written while
matters remain fresh in our mind. One section of the Status dashboard keeps
track of summaries and draft summaries, reminding us of what has been
done and what remains to do.

Open the Status tab and scroll to the


upper right-hand section of the map
to find the Summaries dashboard.
At a glance, we see that we have
written six summaries, one of which
is very short. We have an additional
eighteen notes that use the prototype
"Draft Summary". Fifteen have yet
to be written, and two more are very
brief.

Summaries
Bummaries

drafts

6
I

empty
I

short

15 1
short drafts

1
I

empty di afts

0
I

1s

2
I

If we go to the Expense Account tab,


ok
ok drafts
we might change the prototype for
5
1
the April 24 summary back to Draft
I
I
I
I
Summary. Right-click the icon to
the left of the note title and select
Draft Summary from the menu of prototypes. Return to the Status tab; we
find that we have one fewer summary and one more draft. Go back to the
Expense Account tab and change the April 24 summary back to Summary;
the Status tab will return to its previous state.

49

Working With Progress Bars


Before examining the details of these status-monitoring
helpful to explore how progress bars work.
To begin, create a note named "Progress."
modify its appearance as follows:

tools, it may be

Use the Appearance inspector to

Color: "6"
Accent Color: "3"
Border Color: black
Border Style: plain
Border Width: narrow
Shadow: off (unchecked)

Progress

42

Then, use the Text inspector to add a subtitle.


Title alignment: center
Subtitle:
42
Subtitle Color: green
Subtitle Size: (adjust slide

to match illustration)

Finally, open the Plot pane of the Appearance inspector


and choose "bar" from the Pattern menu. Enter
$Subtitle in the plot's Expression field, and ensure that
Minimum and Maximum are empty.

50

If no explicit minimum or maximum are chosen for a progress bar,


Tinderbox assumes that minimum is O and the
maximum is 100. As we see above, the progress bar is
roughly 4 2 /ofull.

Prog ress

If we prefer a vertical gauge, we select vbar rather than


bar from the Pattern menu.
If you now change the subtitle from "42" to, say, "75", the proportions of
the bar will be updated to reflect the new value.

Expected Progress
Next, select the note named "summaries" and open the Rule pane of the
Action Inspector.
Rule: $Subtitle=find(Prototype="Summary").size

The rule makes a list of all the summary notes in the document, recording the
size of that list in the note's subtitle.

51

Next, switch to the note's Plot


inspector. The plot pattern is "bar"
- a progress bar - and the
expression being plotted is simply
the $Subtitle just set in the note's
rule.
The bar's minimum value is 0. The
.
.
maximum 1s:
1+$Subtitle(/Status/days).toNumber

We already know the length of the


trip; in the preceding chapter, we
recorded the number of days
between the first and final expense in
the note "days." We might well want
a summary for both the first and
final days of the trip, so the number
of summaries we expect is one
greater than the number of days in
the trip. Finally, because $Subtitle is

Appearance Inspector: Expense Account

,0.

<>

summaries
I

Interior
Pattern
Express ion

Border

Shadow

Bkgnd

I bar

~~~~~~~~--

L---1

$_Su
_b_tit_le______

Minimum

lo

Plot Color

green

Background

lO

white

Maximum

__J

I 1+$Subti11

bar($Subtitle,0, 1+$Subtitle(/
Status/days). toNumber)

52

a string, we explicitly convert $Subtitle to a number with toN urnbe r to ensure


that Tinderbox understands that we want to "+" to add two numbers
together, rather than to append the two strings.

Spotting Trouble
We might create Summary (or Draft Summary) notes as placeholders,
intending to come back later and flesh them out. The note "empty" finds
summaries with no text:
Rule: $Subtitle=find(Prototype==''Summary''

& $WordCount==0).size

Similarly, "empty drafts" finds draft summaries without text.


Rule: $Subtitle=find(Prototype==''Draft

Summary'' & $WordCount==0).size

The notes "short" and "short drafts" identify summaries and drafts that are
very short - less than 100 words long.
Rule: $Subtitle=find(Prototype=''Summary''

& $WordCount>0 & $WordCount<100).size

Setting A Target
It can be difficult to write summaries immediately, but too often we may
return from a long trip to find that we've postponed writing summaries for

53

days on end. This can leads to long evenings of tedium, forgotten details, and
unpleasant memos from the Accounting Department.
The number of draft summaries is a useful indicator that
paperwork is piling up. For this trip, we might attempt a
resolution to keep: we'll try to keep the number of
unfinished drafts down to three or four.

drafts

1a I

The progress bar's target is specified in the Plot Inspector, and may be a
constant number (here it's "4") or an expression. The marker is drawn using
the note's $PlotColor, alternating with the contrasting color from the
progress bar.

Color Coding
Dashboards might want to call attention to problems. In the example above,
we have too many unfinished drafts: we resolved to aim for four drafts at a
time, and we currently have 18.
We can use a rule to change the appearance of notes that require attention.
For example, we could use this three-part rule (in which we've added some
extra space a line-breaks for clarity on the page):

54

$MyNumber=find(Prototype="Draft Summary").size;
$Subtitle=$MyNumber;
if($MyNumber>4){$SubtitleColor="dark bright red"} else {$SubtitleColor=;}

First, as before, we make a list of drafts, count them, and store the result in
$My Number. Next, we copy that result to the subtitle. And third, if the
result shows that we have more than four drafts, we set the subtitle color to
dark bright red; otherwise, the action
$SubtitleColor=;

tells Tinderbox to use the inherited or default $SubtitleColor.


Many visual properties of dashboard notes can be effective indicators like
this. $Color and $Color2 change the colors used by
the progress bar. $BorderColor changes the border
&
drafts
color and $Border changes its thickness. $Badge adds
18
an named image or "badge" to the note's upper rightI
hand corner.
if($MyNumber>8){$Badge="alert"} else {$Badge=;}

adds a warning symbol if far too many drafts have piled up.

55

8. Seeing The Data


Pie Charts
In Chapter Six, we used a group of
agents to manage exchange rates,
converting currency from Euros,
Pounds, and Krona to dollars. We
might find it useful to see an
overview of the fraction of our
expenses that was remitted in each
currency. A dashboard pie chart can
do this at a glance.

os

CHF

ILS

0
D

MAD
SEK

by currency

!li;?Asa rule, prefer progress bars and histograms to pie charts. The pie chart is generally
overused and is frequently uninformative. In addition, readers are not very skilled at
judging the relative sizes of arcs and wedges, making pie charts hard to read unless the
reader already knows what the chart means to convey. Still, when you need to examine
the proportion of a few categories, pie charts can be a good solution.

To begin, we create an agent "by currency" that collects those agents we


defined in Chapter 6:

56

Query: inside(/Infrastructure/currency

conversion)&$AgentQuery!=""

Note that agents always have an AgentQuery, while regular notes have no
use for one, so locating notes with a query is a good way to locate agents 7
Next, select the "By Currency agent, open
the Appearance Inspector, and select the
Plot pane. Several settings merit noting.

e
'--=

Appearance Inspector: Expense Account


, __. ~
'--'-- ___ -'----" 4__
T <>

Each child of the agent represents one


segment of the pie. In this case, each
currency agent represents one segment
Expression can be any attribute or
combination of attributes we might wish to
analyze. Here, for each agent, we locate
all the children of the original agent and
sum their $Dollars values, giving us the
total expenditure in each currency.

Pattern

Border

Shadow

Bkgnd

pie

Express ion

[ sum(chi ldren(orig inal),$Dol lars)

Minimum

[ auto

Plot Color

Background

Maximum

[ au_to
.__
_

_,

blac k

~ _____
J _
__;;_

----pie(sum(children(orlginal),
$Dollars))

0 $

D t:

CHF

The background of the pie chart is drawn


1

IO I

by currency
Interior

The pattern is "pie", requesting a pie chart.

Smart Adornments also have queries, but because agents never examine adornments that need not concern us here ,

57

in Color "2', and is opaque.


The pie chart legend is drawn to the
right of the chart, if space allows.
The colors used in the pie chart are
chosen in turn from a list of colors in
the note's $PlotColorList; for this
note, the $PlotColorList is:

Os
0

CHF

ILS

0
0

MAD
SEK

by currency

green;lighter
green;darker
green;light
green;black;white;blue

If you change the first color from green to red, the segment for $ will change
color.

Bar Graphsand Plots


We might perhaps be interested in how our expenses were distributed
throughout the trip. Are the expenses clustered at the start of the trip or the
end? We some periods especially costly?
A quick and easy way to visualize expenses over time is simply to build a
chronologically-sorted list of all the expenses, and then plot each expense.

58

Agent: expenses by day


Query: inside(/Infrastructure/all
Sort:
StartDate

expenses)

Appearance Inspector: Expense Account

ii

-4

<>

expenses by day
Int erior

Once again, we request a plot - this time a bar graph


- inside the agen ti
The Expression for the plot is very simple: we draw a
vertical bar proportional to the cost of each
reported expense.

Border

Shadow

Minimum

Plot Co lor

green

Back ground

white

bargraph($Dollars,0, 1000)

A few plane tickets are especially costly. We choose


a maximum value of $1000 for the graph's vertical
axis so small expenses like taxi trips remain visible.

Often, the plot background is translucent to allow us to see notes inside


the agent or container. For clarity, we choose an opaque white
background.
We see some big expenses early in
the trip - the plane flight to Paris,
the hotel in Zurich. Costs diminish
for a time, but seem to gradually
escalate toward the end of the trip.

expenses by day

(lo

59

It might also be helpful to see how the costs are distributed. Are there lots of
expenses for the same amount? Are there anomalous expense reports? The
agent named distribution of expenses helps us keep an eye on these questions.
Agent: distribution
of expenses (log)
Query: inside(/Infrastructure/all
expenses)
Sort:
$Dollars

Where in expenses byday we set


the plot's expression to display
$Dollars, here we use a
logarithmic scale by displaying
log($Dollars). We see a fairly
distribution of expenses (log)
even distribution of costs, with
perhaps a somewhat fewer small
expenses than we might otherwise expect. This might suggest that we're
simply not reporting expenditures that are very small, or that we're simply
not making small expenditures.

60
Expense Account
Boston

Paris

fri &ay, 2tt


April

London: WatchfulCon

Saturday, 25

flight to
Paris

Sunday,26 April

Draft: Frida

April

D D
,~~
o OyM~C'"
D
I
I
1~D~D
DD
evening dri

~ g,idebook

IDraft: Saturday, 2 May


registration
I Draft: Sunday,3 May

lp,b ,,ooh I

Ilunch

lunch

dinner

hotel

drinks

I
power adapter

~I

Tel Aviv

Dijon

Monday,

flight: Lor

Ziirich

Tuesday,28
April

n ['""m

Wednesday,6
May

I Vienna
I Draft: Thursday, 7 May

D
DD~
taxi to
dinner

coffee c taxi to hotel

I lunch

taxi to Alliance
Against
Exploitation

May

[workout clothes

Ouarzazate

I lunch

[[ lunch

Gothenburg

[ J -Mm
,
Dratt:1car rental

[Bar Z

I flowers

9. Treemaps

M~

I[ hotel

~D

Draft: Thursday,
1ttM ay

Draft: Friday,15
May

Stavanger

Draft : Saturday, 16
May

traffi c fine return ren flight to l(

I.,.,
..'"'''.

rhotol

Oraft:Wed1Ibreakfast

Torino

IDraft: Thursday,30 April

IDraft: Saturday, 9 11

0[J[J

Marrakesh

near Como

Wednesd1lunch

II pharmacy
: Holmbrich breakfast (suppl)

Iclinic

~~

D
nft,
r,.,,,,.5M,y
Dnft,

1.,.,.
....

maps

IIflight
I

Boston

Draft : Sunday, 17 May

IIta xi
I

61

The Treemap view is designed to display the structure of your Tinderbox


document in detail by using screen space efficiently. On my Macintosh, an
outline can only display about 25 notes at a time, but the treemap can easily
display more than 100 notes while showing how they are related.
To begin, select the rightmost tab named "Expense Account" in the sample
document. This opens a treemap view of the Expense Account container, just
as the leftmost tab opens an outline view of that container.
Each note appears in the treemap as a rectangle. If a note has children, its
interior is divided among its children. Those children, in turn, divide their
interior space among their children. This continues until we've drawn all the
notes, or until the notes become too small to see.
The area of each note is proportional to the number of descendants that not
contains. Within the parent rectangle, notes are arranged roughly in order,
right-to-left and top-to-bottom, though Tinderbox can move notes around to
help make sure everything fits.

62

As in other views, click on any note to select that note. Double-click a


container to focus the view on that container; or use the breadcrumb bar to
expand the view to the parent note's container.

Weighted Treemaps
Initially, treemaps apply equal weight to
every note. We can instead tie the area of
each note to that note's properties. For
example, we might make the areas of each
note proportional to the expense it records.
In the treemap tab, note the small "Info" button. Click that button to display
the the treemap popover.
The treemap expression can be any
Treemap Expression:
$Dollars
numerical expression. If a note's
Color Expression:
$Dollars
Start:
1I End:
result is zero or negative, that note is
Border Color:
omitted from the treemap;
otherwise, the note's area will be
roughly proportional to the result and the sum of the results of the note's
descendants.
11

11

1I

63
Expense Account
Boston

London: WatchfulCon

flight to Paris

Oyster

CI registration

dinner

-Idinner I
_[theater

Tel Aviv
flight: London-> Tel Aviv

hotel

-.....
Vienna

clinic

hotel

H olmbrich Security: retainer

Paris

I dinner

evening dress

----

l hote-1

~
Dijon
---

Marrakesh

--

hotel

Zurich
~di =
nne=r ~

-~ho~tel----------,
Ouarzazate
dinner

Stavanger
car rental flight

flight

LJL
nea r Como

I[hotel

flowers

Idinner

Torino

~ traffic

fine

Ireturn renta l car

Here, the treemap expression is simply $Dollars: each Expense note is


drawn with an area proportional to that expense; bus fares are very small and
costly hotels are much larger. We also use $Dollars for the color expression:
the least costly expenses are white and the most expensive are green.

64

Note that the daily summaries no longer appear in the treemap; because they
do not record an expense, their $Dollars attribute is zero and they are
omitted. The very-expensive last-minute flight at the start of the trip
occupies a great deal of space; the pre-flight snack and guidebook, which
were accorded equal weight in our first treemap, are now tiny slivers to the
right of the plane ticket.
::::--~

---- -

--.,.....

Color Coding
The color expression can be used to
highlight specific elements in the
treemap. For example, try this color
.
expression:

-----

- --- -- ..
- --~ -

-
..
-_...--~

...

if($Tags.contains(meal)){1}else{0}

Expenses for meals will use the End Color; other expenses will use the Start
Color.
\/e might want to identify transactions that use various currencies. We can
use the same approach to color transactions in currencies other than dollars:
if ($Currency!="$") {1}else{0}

65

Here, if $Currency is not"$" the treemap uses EndColor - light green while if the $Currency is"$" the item uses StartColor - off-white.
Perhaps we want distinct colors for transactions in dollars, euros, and in
other currencies. We could use nested if() statements to accomplish this:
if($Currency=="$"){0}else{if($Currency==""){0.5}

else

{1}}

Now, if the expense was in dollars, we use


StartColor, and if it was in euros, we use a mix
half-way between StartColor and EndColor.
Nested if() statements can quickly become
confusing. Tinderbox lookup tables can be a handy
alternative. We begin with a list of values of
$Currency and the corresponding color value - for
example:
"$:0;

:0.33;

:0.66;

...
--

default:1"

Each value of interest is paired with its associated value, separated by a


colon. The special key value def au 1 t matches any unspecified value. The
ColorExpression is now:
"$:0;

:0.33;

:0.66;

default:1".at($Currency)

66

To make the result clearer, we use a slightly darker green for EndColor.
Now, transactions denominated in dollars, euros, pounds, and in other
currencies can be identified at a
Paris
glance.
Expense Accom t

Boston

~Dijon

flig ht to Pari s

even ing dre ss

Zll r1ch

Even though lookup tables are


simpler to use than complex nested
if() statements, typing them more
than once can be unwieldy. Instead,
we can store them in a configuration
note. Just as we refer to
$ExchangeRate(/Config/)
to find
the exchange rate for sterling, we
could save the lookup table in
$MyString(/Config/treemap).
Now,
our color expr ession is simply:
$MyString(/Config/treemap

) .at($Currency)

ho tel

dinner

din ner

]L

Como
j

owers

Torino

flight : London - >Tel ho tel


Aviv

Ouarzazatle

fligh t

ho tel

IC

Stavanger
flight

re gistration

:J

traffi c fir return rental car

London: WatchfL Tel Aviv

I- ~

j hotel

car rent al

Vienna

"'~"~'~""""w~,

hotel
flight

Marrakesh

lw"

You might also like