An object is a real object in Perl, and a list with a first element being the class id in TCL (the rest being the contests, in what follows the first element of the rest is referenced as the first element of the object).
The particular elements of the list represent:
Tk::Text::String
, class id is S
.
Tk::Text::MarkLeft
with id L
, and Tk::Text::MarkRight
with
id R
.
Tk::Text::TagOn
with id T
, and Tk::Text::TagOff
with
id t
.
Tk::Text::EmbWin
with id W
.
The inter-leaf separators are dumped as on object of class
Tk::Text::BlockSeparator
, with id |
, the contents being the
``depth'' of the separator. Note that the minimal possible depth is 1
for separators between leaves of the same parent.
Tk::Text::Block
, the class id isB
.
Tk::Text::Empty
, the class id being E
. The contenst is the
list of the block name, and (optionally) instance data.
I
An empty block (without leaves) occupies 1 unit of the index space.
Note that a block (however complicated) always fits in one line of the
index space. In particular, the usual bindings for up
and down
will move you out of a block. (You should expect it, since leaves of a
block may be placed one under another, but may be not.)
.t get
,
selection and search) see the contents of a block as a string of the
same size as the size of block in the index space. The start of the
block looks like {
, end like }
, interleaf separators like |
.
An empty block looks like .
.
Note that a string representation of a block (however complicated) always fits in one line.
If inserted text contains no newlines, it is added to the leaf of tree the insertion point is in (i.e., at or after the start of, and before the end of). If it contains newlines, then the resulting leaf is split into several at the inserted newlines. All the new leaves have the same parent node as the initial leaf. Registered callback will be called on insertion of newlines (not implemented).
Details are subject to change.
A layout procedure takes a variable number of input arguments. The first element is a list containing the block name and widget name, (possibly with an addition, say, if instance data is present in the block, it will be the next element). The second element gives the horizontal offset of the start of the block inside the ambient line (it can be different from the absolute horizontal position if the block is inside some other block). The remaining elements specify the tree structure of the block and the layout details of the leaves. Any child of the root node of the tree provides one argument of the function. All the arguments are lists, and
y
offset inside the block, width, I
There are three possible formats of the elements in this list. All
are lists of numbers (and should be of the form {dd ... dd}
)
of lengths 1, 7, or 13. The first number is either repeat count, or
id of additional line to show (i.e., the same data as returned by
textWidget block addline index
command). Lists of different length have
the following meaning:
The remaining elements of the list provide x and y offsets of the upper-left corner inside the ambient block, width, total width, height, and baseline of the block as a whole, or of a group of leaves, or a leaf. If it describes a group of leaves, the leaves are laid out as by default layout procedure. Width, height, and baseline information is used for displaying background of the line.
If all the leaves are laid out, then this list describes an additional element to draw if the first element is greater than 0, i.e. it is considered a Block ID of an additional drawing element, and the rest specifies the layout of this element. If it is 0, then this element of the list is ignored exactly as in other cases.
Summary:
{ig ig ig w ig h b}
{rc xo yo w tw h b}
{rc}
{bi xo yo w tw h b}
w
is not very important), put after leaves.
Setting the -layoutdepth
and/or -layoutwidths
options for a block
forces the layout procedure to be called with agruments corresponding
to modified tree structure.
If -layoutdepth
is set, the depth of the tree is modified to be the
given number. If the true depth of the tree is too small, tree is
extended from the root side, if it too deep, the subtrees on the
maximal allowed depth level are mocked as lines with repeat count.
If -layoutwidths
is set, this can restrict the number of branches
going out of any node of the modified tree. The value of this option
should be a list, elements of this list are either numbers, or lists
of the form {min max}
. (A single number
is equivalent to a pair
{number number}
). N-th element of the list controls the number of
branches going out of nodes on the distance N from the root. If there
are too few branches, it adds branches that contain simulated groups
of leaves with repeat count 0. If there are too many branches, it
groups several last brunches into one with appropriate I-layoutdepth
if the depth of the node is less
than -layoutdepth
.)>
{}
.
In the latter case index1 and index2 should be outside of any block, or properly inside the same block. The newlines (or, correspondingly, interleaf separators of enclosing block) are converted into interleaf separators of newly created block. This is prohibited for empty blocks.
index
.
-getFlags
If bit 1
is set, the string representation of a text range
always gives a string of the same length as the length of the
interval in the index space. If some text annotation results in an
empty string in the standard representation, it is represented as an
appropriate number of *
s if this bit is set. Currently this
concerns embedded windows only, which are represented as *
.
All undocumented bits are reserved and should be 0.
Note that it is not enough to use a tag even for gray background, since the border of the tag is inside the rectangle that contains the letter, and to get a correct pedestal look we want the border to surround the letter, not to be drawn outside of them.
In what follows we use TCL as the language for callback. Of course, the resulting code will be much simpler in some other languages.
First, we create the 2 new additional elements to display:
(or we could use existing ones, if possible). The third row creates a row in the text widget that is empty, and has tag ``backgr1''. This row will show the background only, and we will use it to show the raised background behind the block. The fourth row memorizes the id of this additional line, and the fifth one returns the text in the widget to its initial state. The line is not shown anymore, but the way to show it is preserved in a safe place. The second element is created in the same way.
Next, since we are satisfied with the way the leaves of the tree are places on the screen (i.e., one under another), we do not want to be concerned with internal structure of the block tree, so we ask the widget to lie about internal structure of the tree:
Now the data given to myLayoutCmd
will be always the same, as if
the block consisted of one leaf only that is the direct child of the
root. So the arguments the myLayoutCmd
receives are the following
ones:
Now $c
, $w
, $tw
, $h
, $b
contain the count, width,
total width, height and baseline of the contents of the block.
Next we extend the total width of the row.
We will not replace the width of the row, so mouse events could be directed to outside of the block if clicked in the extended area. (In fact they won't, since we will extend the size of the ambient block.) Next we calculated widths of additonal rows,
and their height and baselines. All is prepared now to layout the rows:
Note that the same list $addrow1 is good for specifying the size of the total block, since the first element of the list (that is $backgrId) is ignored in the information for the whole block. Now we need to move the real contents of the block 5 points to the right and down with respect to the rectangle occupied by the block, and return the calculated information:
Note that it is vital to put addrow2 after addrow1, since it should be drawn after the addrow1 for it to appear to be on top of addrow1.
That's all! Now you can create a binding for insertion of empty block
into the widget (this binding supposes that bindtags
are reverted):
This binding moves the insertion point inside the block, so you are ready to fill block with whatever information you need.
Sample code in the distribution of extended text widget provides other examples of blocks: superSub, Fraction, and so on.
While it is possible to implement this kind of block using the same types of blocks as in the previous section, we will need a lot of code change in the bindings if we use this approach: a usual block takes at least 2 positions in the index space, so it is possible to make an insertion inside this block. Thus we either need correction of keybindings that move the insertion point, or should correct the the insertion code to check whether the insertion happens inside a block of this type. If we do not do this, we need additional decision how to handle blocks of this type that have not-empty contents.
The solution is to use ``empty'' blocks that take only 1 position in the
index space, so it is impossible to insert text inside them. We make
block type empty by using configuration option -empty
:
Note the spaces in the name of layoutcmd: No quoting is performed
during the call, so 5
and 35
become first two arguments of
layoutTab
procedure. This procedure can be as simple as follows:
The only ``working'' row is the set w
one. It calculates the width
of the block using the following rule: