Text peer widgets

TIP #169 [L1 ] proposes adding peer text widget capability so multiple text widgets can share the same underlying data:

  • a large BTree containing all the text, tags, marks, etc
  • the undo/redo stack
  • etc.

(Peer widgets are now implemented in Tcl/Tk 8.5.)

Video Demo

The problem is how to implement this, given that Tk 8.5 has added the requirement for all widget logical lines to cache their display pixel heights. The pixel height of any logical line will typically depend on the widget it's in (particularly the width of that widget, unless we have disabled text wrapping). This means we will typically need for each logical line one pixel height cache for each peer widget. On top of that the internal 'Node' structures in the BTree also store the pixel height at that point in the tree, so we'll need multiple pixel heights there.

It seems there are two possible implementation strategies:

  • dynamically extend the TkTextLine and Node structures to maintain one such pixel count for each peer widget
  • store the pixel information in a separate widget-specific data structure

What are the pros and cons of these approaches?

The first of them has several cons: every time we create or delete a peer widget, we'll need to go through the entire BTree and adjust every Node and TkTextLine (typically reallocating them all to make more or less space).

The second approach would require more complex synchronisation code to ensure the BTree and each pixel-data-structure are up to date (as text lines are added, deleted, or as the BTree is rebalanced, for example). It would make deleting a peer widget very easy and fast, but creating a new peer widget would effectively require duplicating the entire pixel-data-structure of another one.

So, in both approaches peer creation will involve lots of allocation (in the first lots of reallocation, in the second just new allocation).

In the first approach peer deletion is a hassle, while in the second it is trivial.

Editing the BTree is easy in the first approach (the information is stored right there, so easy to invalidate pixel counts, throw away deleted TkTextLines, etc), but in the second approach all edits must then be synchronized with each peer pixel-data-structure. This would require a mapping mechanism from each TkTextLine and each Node to a unique pixel-count for each peer widget. Every change would then require adding/deleting/modifying some elements of the map. Perhaps a simple Hash-map lookup could be used based on the address of each TkTextLine or Node?

Another implementation issue is whether it is currently possible in Tk to have the same embedded image or embedded window show up in two text widgets simultaneously? Remember you can embed images or arbitrary widgets inside a text widget, but can those be displayed in two places at once?

DKF: Duplicating images is easy; the Tk image infrastructure is designed for it. Arbitrary widgets are not duplicatable.

Duoas: I am (ambivalently) really excited about this. However, sometimes you want the text to vary from its peer. The quintessential examples are already given: sel, insert, current. I'd like to be able to make a tag appear in one peer and not another. (Without that capability, I am stuck doing the "copy and paste" peer method.) I'm bound and determined to make my application work like it ought, and not the way existing software thinks it ought, so either way I just thought I'd throw that suggestion out there for y'all.