On Sun, 14 Mar 1999, Asger Alstrup Nielsen wrote:
[...]
> Yes, this would not be as efficient as your scheme, because your scheme targets
> precisely the insets that are affected, while my idea is much worse, because we
> visit all insets.
> However, your scheme involves some administration of the signals and slots.
> What if we cut to the clipboard? What if we paste into a different document?
> The answer to all of these questions might be easy, but the point is that we
> have to take care of these details. And when there are too many details to
> take care of, it's easy to miss one, and we get the bugs that are hard to find.
Everything below was written about two weeks ago and was the precursor to
the code that started this thread. Hopefully it'll fill in some of the
missing details from the code. If anything this experiment has shown that
while everyone will read code there is still a need for some design
discussion. That said my code did get a response faster than Asgers
design document so Asger's conjecture was 90% right.
I'm still working on the automatic update upon insertion/removal from a
buffer. Mind you, making the cutBuffer into a real Buffer (like an emacs
scratch buffer) does have a certain appeal.
###############################################
Inset Madness
LyX 1.1.x is currently driving towards everything being in an inset.
This is good. However, we still have several parts of the code that
want to check what type of inset is at the current cursor position or
that want to search through the entire document looking for specific
inset types and then asking them a simple question like "How wide are you?"
Mostly, its references (and Bibkeys in particular) that are handled
this way.
So what can be done about it?
Well, I am thinking that signals/slots could again come to our rescue
since they can provide us with a couple of cool things. First some code:
class Buffer {
...
Signal3<int* width, Painter, LyXFont> bibitemMaxWidth;
Signal2<int* width, LString> bibitemWidest;
...
};
class InsetBibkey : Inset {
...
InsetBibkey(Buffer *);
void maxWidth(int*, Painter, LyXFont);
void widest(int*, LString);
...
Connection mw;
Connection w;
};
InsetBibkey::InsetBibkey(Buffer *owner) : owner_(owner)
{
mw = connect_to_method(owner_.bibitemMaxWidth,
this, &InsetBibkey::maxWidth);
w = connect_to_method(owner_.bibitemMaxWidth,
this, &InsetBibkey::maxWidth);
...
}
void InsetBibkey::maxWidth(int *max, Painter pain, Font fon)
{
if (*max < width(pain, fon)) {
*max = width(pain, fon);
}
}
Then when we need to know the maxWidth of the Bibkeys in the buffer we
just activate the signal with appropriate parameters. This will also
speed things up considerably because we effectively have an automatically
maintained list of bibitems.
Automaticaly maintained??
Yes, since the connections are automatically removed when the inset is
destroyed. But this still leaves us with the same old cut/paste problem.
The simplest solution might well be to make the cutbuffer of type Buffer.
Then we can use Buffer::cutInset() and Buffer::insertInset() to copy
it to the cutbuffer (styled after the emacs scratch buffer) like this:
cutbuffer.insertInset(buf.cutInset(cursor));
We'd need to ensure that insertInset() called setOwner(Buffer*).
Hmmm. This is a bit awkward because its not automatic.
A weird idea might be to change the interface about and do:
Inset::moveIntoBuffer(Buffer*, cursor, ...);
Then everything we do is via insets and they can "automatically" fill in
their necessary fields and then hand over the rest of the insertion to
Buffer::insertInset().
************
I'm sure there are probably a number of other areas that could use
signals/slots in this way (and as demonstrated it would also be
considerably faster than the scan-through-the-buffer method).
++++++++++++++
On a related topic is the need for Paragraph to be just a list<> or vector<>
of Insets. This is possibly best described as an InsetParagraph.
class InsetParagraph : Inset {
private:
vector<Inset*> paragraph;
...
}
Thus we have defined our tree structure completely in terms of Insets
since an InsetParagraph can be one of the Insets in the vector.
InsetText contains just a string of text and so forth. This guarantees
we can eliminate those silly insetmarkers and so forth. Okay, so a fair
bit has already been done in this direction so maybe I'm just reiterating
what we're already doing.
Moving a cursor through this structure involves moving through each inset
in turn (from its beginning to end). To support fast random access we
can easily provide caching of the sizes of the insets. This might be
very useful if we have multiple levels of paragraphs. One good question
is: How does a paragraph get to hold another paragraph within it?
Allan. (ARRae)