21.2 Standard Programmer Interface

updating-output  (stream &rest args &key unique-id (id-test #'eql) cache-value (cache-test #'eql) fixed-position all-new parent-cache record-type) &body body [Macro]

Introduces a caching point for incremental redisplay. [annotate]

The stream argument is not evaluated, and must be a symbol that is bound to an output recording stream. If stream is t, *standard-output* is used. body may have zero or more declarations as its first forms. [annotate]

record-type specifies the class of output record to create. The default is standard-updating-output-record. This argument should only be supplied by a programmer if there is a new class of output record that supports the updating output record protocol. [annotate]

Note: In mcclim the macro returns the created output record, which makes a lot of sense. Is that part of the spec and required for new output-record classes? [edit]-- Orm Finnendahl 2011-01-04 15:29Z
Note: At least "21.1.1 Examples of Incremental Redisplay" describes this behaviour (third pragagraph). [edit]-- Janis Dzerins 2011-01-24 16:18Z

updating-output must be implemented by expanding into a call to invoke-updating-output, supplying a function that executes body as the continuation argument to invoke-updating-output. The exact behavior of this macro is described under invoke-updating-output. [annotate]


invoke-updating-output  stream continuation record-type unique-id id-test cache-value cache-test &key all-new parent-cache [Generic Function]

Introduces a caching point for incremental redisplay. Calls the function continuation, which generates the output records to be redisplayed. continuation is a function of one argument, the stream; it has dynamic extent. [annotate]

If this is used outside the dynamic scope of an incremental redisplay, it has no particular effect. However, when incremental redisplay is occurring, the supplied cache-value is compared with the value stored in the cache identified by unique-id. If the values differ or the code in body has not been run before, the code in body runs, and cache-value is saved for next time. If the cache values are the same, the code in body is not run, because the current output is still valid. [annotate]

unique-id provides a means to uniquely identify the output done by body. If unique-id is not supplied, CLIM will generate one that is guaranteed to be unique. unique-id may be any object as long as it is unique with respect to the id-test predicate among all such unique ids in the current incremental redisplay. id-test is a function of two arguments that is used for comparing unique ids; it has indefinite extent. [annotate]

cache-value is a value that remains constant if and only if the output produced by body does not need to be recomputed. If the cache value is not supplied, CLIM will not use a cache for this piece of output. cache-test is a function of two arguments that is used for comparing cache values; it has indefinite extent. [annotate]

If fixed-position is true, then the location of this output is fixed relative to its parent output record. When CLIM redisplays an output record that has a fixed position, then if the contents have not changed, the position of the output record will not change. If the contents have changed, CLIM assumes that the code will take care to preserve its position. The default for fixed-position is false. [annotate]

Note: So, how come fixed-position is not part of the signature of invoke-updating-output? Is it supposed to be a &key argument? [edit]-- Robert Strandh 2005-08-17 21:41Z
Note: It's a keyword argument. It's not explicitly included in invoke-updating-output's signature because it's part of the &rest list that is passed when the updating output record is constructed. [edit]-- Tim Moore 2006-02-06 16:44Z

If all-new is true, that indicates that all of the output done by body is new, and will never match output previously recorded. In this case, CLIM will discard the old output and do the redisplay from scratch. The default for all-new is false. [annotate]

The output record tree created by updating-output defines a caching structure where mappings from a unique-id to an output record are maintained. If the programmer specifies an output record some output record P via the parent-cache argument, then CLIM will try to find a corresponding output record with the matching unique-id in the cache belonging to P. If neither parent-cache is not provided, then CLIM looks for the unique-id in the output record created by immediate dynamically enclosing call to updating-output. If that fails, CLIM use the unique-id to find an output record that is a child of the output history of stream. Once CLIM has found an output record that matches the unique-id, it uses the cache value and cache test to determine whether the output record has changed. If the output record has not changed, it may have moved, in which case CLIM will simply move the display of the output record on the display device. [annotate]


The text in this paragraph could use some work. For instance "If the programmer specifies an output record some output record P..." should be replaced by simply "If the programmers specifies some output record P...". And the "neither" in "If neither parent-cache is not provided...".

It would be nice also to indicate that "simply move"-ing the display of an output record is not a simple thing, since CLIM must guarantee that the effects of replaying the output records is the same as if the were all drawn freshly in the right order.

[edit]-- Robert Strandh 2005-08-17 21:53Z


redisplay  record stream &key (check-overlapping t) [Function]
redisplay-output-record  record stream &optional (check-overlapping t) x y parent-x parent-y [Generic Function]

Minor issue: The coordinate system stuff affected by the x/y and parent-x/y arguments is entirely bogus. The proposal to make "stream relative" coordinates for output records instead of "parent relative" coordinates will eliminate this completely. --- SWM [annotate]

(redisplay-output-record record stream) causes the output of record to be recomputed. CLIM redisplays the changes "incrementally", that is, it only displays those parts that have been changed. record must already be part of the output history of the output recording stream stream, although it can be anywhere inside the hierarchy. [annotate]

When check-overlapping is false, this means that CLIM can assume that no sibling output records overlap each other at any level in the output record tree. Supplying a false value for this argument can improve performance of redisplay. [annotate]

Implementation note: redisplay-output-record is implemented by first binding stream-redisplaying-p of the stream to true, then creating the new output records by invoking compute-new-output-records. Once the new output records have been computed, compute-difference-set is called to compute the difference set, which is then passed to note-child-output-record-changed. [annotate]

Note: note-output-record-child-changed * [edit]-- DK 2021-11-23 17:43Z

The other optional arguments can be used to specify where on the stream the output record should be redisplayed. x and y represent where the cursor should be, relative to (output-record-parent record), before we start redisplaying record. parent-x and parent-y can be supplied to say: do the output as if the parent started at positions parent-x and parent-y (which are in absolute coordinates). The default values for x and y are (output-record-start-position record). The default values for parent-x and parent-y are [annotate]

  stream (output-record-parent record))

record will usually be an output record created by updating-output. If it is not, then redisplay-output-record will be equivalent to replay-output-record. [annotate]


replay-output-record only draws, but what about other overlapping records? When the record is translucent, then the result is also not idempotent.

Should we replay the history instead?

(stream-replay stream record)

[edit]-- DK 2021-11-28 21:09Z

Dear DK,

Short answer: You should.

Long answer: You shouldn't draw anything at all. The description says so: "[...] causes the output of record to be recomputed. CLIM redisplays the changes 'incrementally' [...]" You compute, CLIM redisplays. Just let CLIM know what is dirty and let the event loop pick that up.

[edit]-- Gilbert Baumann 2022-01-23 17:38Z