Counters: A GUI Fest Challenge


Challenge problem

from http://www.cs.chalmers.se/~magnus/GuiFest-95/postchallenge.html

The "Multiple Counter" program shows a counter which can be incremented manually or periodically. The counter can at any time be copied, giving a new counter with its own independent state, which is copied from the old counter in the very moment of creation. A counter can also be linked, giving a new view to the same counter. One can think of the copying and linking as being analogous to ln and cp applied to files under Unix.

A counter view looks something like this:

+------------+
| 	     |
| +--------+ |
| | 0      | |
| +--------+ |
|            |
|            |
| +--------+ |
| | Manual | |
| +--------+ |
|            |
| +--------+ |
| | Auto   | |
| +--------+ |
|            |
| +--------+ |
| | Copy   | |
| +--------+ |
|            |
| +--------+ |
| | Link   | |
| +--------+ |
+------------+ 

It contains the following elements:

If possible, it should be possible to distinguish counters that are linked - eg. links have the same background colour or window title, copies have a different colour or title, or perhaps by layout - links placed across the screen, copies placed down the screen.

A solution in fudgets, and one in K.

A K Solution

A counter is either a copy of an existing counter, or a link to one.

When the copy button of a counter C is pressed, the following operations are performed:

When count[i] changes, D updates itself from count[i]; when D changes, it updates count[i] with its new value.

When the link button of a counter C is pressed, the following operation is performed:

If D is linked from C, then both D and C depend on count[i]: if either changes, count[i] is updated, and so the other link will update itself from count[i].

Let's step through the code.

Initialize the count variable:

count:()

p0 is a dictionary containing five variables:

p0.value	0
p0.auto		0
p0.manual 	code which increments value
p0.copy		code which calls the copy functiuon with a symbol of its dictionary
p0.link		code which calls the copy function with a symbol of its dictionary
p0[`value`auto`manual`copy`link]:(0;0;"value+:1";".k.copy _d";".k.link _d")

Classify the variables in p0:

p0[.;`c]:`data`check`button`button`button

value is a data widget, auto is a checkbutton, manual, copy, and link are buttons.

p0..l:$I:0

I, initialized to 0, is incremented whenever a new counter is manufactured. p0's label is "0".

copy:{`show$~@[~new[];`d`t`l;:;(".k.count ",i;".k.count[",i,";_i]:_v ._i";i:$-1+#count,:. x)]}

The copy function contains one line of code, and has the form:

`show$~@[x;y;:;z]

A new counter-name is generated. Its dependency, trigger, and label attributes are defined. Input to the function x is the counter whose copy button was pressed; that counter is appended to count.

link:{`show$~.[~new[];();:;.~x]}

The link function. The function contains one line of code, and has the same form as copy, except that it is much simpler. A new counter is created, and its value is the counter x which is input to the link function.

new:{`$".k.p",$I+:1}

The new function. Make a new counter name by incrementing I and appending it to ".k.p".

.t..t:"{if[.k.count[x;`auto];.k.count[x;`value]+:1]}'!#.k.count;"
\t 1

Every second the timer .t is updated with the current time. The timer trigger checks each counter to see if auto is on. If so, it increments its value.

copy`.k.p0

Kick things off by making a copy of the counter template p0.

Example: