On Sunday, January 19, 2014 10:01:30 AM UTC-5, Edward K. Ream wrote:
>
> On Saturday, January 18, 2014 1:51:30 AM UTC-6, Edward K. Ream wrote:
>
> > I am going to completely rewrite phase 2.
>
> Done.
>
Earlier today I completed the last part of the "hard part" of this project:
all organizer nodes appear to be handled correctly. As a result, all
imported nodes are moved to their proper positions. Bugs could still
remain, but all the test cases I can think of pass. This is a major
milestone. The last two hours of work have finally arrived!
This post will explain how the code the reliably calculates the child index
of all moved nodes. The code is surprisingly simple, but the background is
a hairy, so it is important to document the details now, while all the
(background) complications are fresh in my mind. This post is pre-writing
for yet another section of the theory of operation.
Previously, the main line (vc.demote) attempted to keep track of a variable
called n, which was intended to be the child index to be used when moving
bare organizer nodes. But this had no chance whatever of working.
Happily, a simpler way does work. To see why it works, we must be *very*
clear about what is going on:
1. There is never any problem moving any node to a *non-bare* organizer
node. All children of such organizers are added *in order*. In other
words, the n argument is never needed.
2. So the problem is determining the proper child index to be used when
moving a *bare* organizer node. By definition, the bare organizer will be
the n'th child of an imported (already existing) node. This is the
**anchor** for the bare organizer. It doesn't matter whether the imported
node is an existing organizer node. Furthermore, there is *no*
OrganizerData instance for the anchor (unless the anchor is also an
existing organizer node!).
3. The general idea is to associate an **offset** for every anchor node.
Rather than creating an AnchorData class to hold this offset, it is easier
to maintain a single dict, vc.anchor_offset_d, that holds the offset for
each anchor. Keys are positions (of the anchor) and values are ints.
4. The code increments the offset for every (bare) organizer added to the
children of an anchor, and decrements the offset for every child of the
anchor that is moved into an organizer node (no matter where the organizer
is).
5. The following code determines n (for bare organizers only!). It
appears in vc.add_organizer_node::
anchor = p.parent()
d = self.anchor_offset_d
n0 = d.get(anchor,0)
d[anchor] = n0 + 1
childIndex = p.childIndex()
n = childIndex + n0
Here, p is the to-be-moved node. The is the node that causes the bare
organizer to be inserted as a child of the anchor, so the organizer will
have the same childIndex of p, as modified by n0, the offset.
We add 1 for the bare organizer node, *not* for the to-be-moved node.
6. The only other part of the puzzle is decrementing the offset when moving
nodes into organizers, of whatever kind. This is done in vc.add::
# Subtract 1 from the vc.anchor_offset_d entry for p.parent().
d = self.anchor_offset_d
key = p.parent()
d[key] = n = d.get(key,0)-1
Once again, p is the existing, to-be-moved node.
And that is that. The project now has met its original design goals!
Next up: restoring custom headlines. It's tricky, but nowhere near as
tricky as moving nodes.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/groups/opt_out.