On Sun, Feb 02, 2020 at 08:36:53PM -0500, Scott Kostyshak wrote: > The logic in RandomAccessList is overly > complicated (and inefficient) and I'm working on simplifying it by using > a splice instead of all of those swaps.
The attached patch implements the splice approach. I've tested the patch in a few situations and it works well. With the splice approach it is now efficient and the logic is cleaner. However, the patch uses a special case that is not elegant for when the next sibling is at the end of the document. I cannot seem to use iterCont_ for the last paragraph in this case. The cases could probably be combined but I don't have a good understanding of RandomAccessList. I don't expect anyone to take a look but I post it just in case. Scott
From 7750175d366f23f23778a9a0e53ef05320723b22 Mon Sep 17 00:00:00 2001 From: Scott Kostyshak <skost...@lyx.org> Date: Sun, 2 Feb 2020 16:19:29 -0500 Subject: [PATCH] Paragraph-move-down now moves sub-items as well --- src/Text3.cpp | 49 +++++++++++++++++++++++++++++++--- src/support/RandomAccessList.h | 17 ++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Text3.cpp b/src/Text3.cpp index f5444e7baa..b84b2a87bf 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -671,12 +671,53 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) switch (act) { case LFUN_PARAGRAPH_MOVE_DOWN: { - pit_type const pit = cur.pit(); - cur.recordUndo(pit, pit + 1); - pars_.swap(pit, pit + 1); + depth_type const cur_depth = pars_[cur.pit()].params().depth(); + pit_type pit = cur.pit() + 1; + Paragraph cpar; + while (pit != pit_type(pars_.size())) { + cpar = pars_[pit]; + // <= because it's possible to go e.g. from depth 2 to 0 + if (cpar.params().depth() <= cur_depth) + break; + ++pit; + } + if (cpar.params().depth() < cur_depth) { + // we did not encounter an equal depth before a smaller + // depth, so there is no sibling. e.g.: + // 1. hello + // a. blah <cur> + // 2. goodbye + break; + } + if (cpar.params().depth() > cur_depth) { + // all paragraphs below cur have larger depth + // so there is no next sibling. e.g.: + // 1. hello <cur> + // a. blah + // <end of document> + break; + } + pit_type const next_sib = pit; + + // this is the depth of the paragraph below whose "family" we + // want to move. + depth_type next_sib_depth = cpar.params().depth(); + pit_type pit2 = next_sib + 1; + while (pit2 != pit_type(pars_.size())) { + cpar = pars_[pit2]; + // <= because it's possible to go e.g. from depth 2 to 0 + if (cpar.params().depth() <= next_sib_depth) + break; + ++pit2; + } + pit_type const next_sib_end = pit2 - 1; + + cur.recordUndo(cur.pit(), next_sib_end); + pars_.swap(cur.pit(), next_sib - 1, next_sib_end); needsUpdate = true; cur.forceBufferUpdate(); - ++cur.pit(); + // move the cursor with the paragraph contents where it was. + cur.pit() = next_sib_end - (next_sib - cur.pit()) + 1; break; } diff --git a/src/support/RandomAccessList.h b/src/support/RandomAccessList.h index 2565d62513..2ce5d5d228 100644 --- a/src/support/RandomAccessList.h +++ b/src/support/RandomAccessList.h @@ -246,6 +246,23 @@ public: return it; } + void swap(size_t from_beg, size_t from_end, size_t to_end) + { + // swap of contiguous ranges of elements: + // + // swap elements from_beg through from_end with + // elements from_end + 1 through to_end. + // The ranges do not need to be the same length. + + if (to_end + 1 == iterCont_.size()) { + // using iterCont_[to_end + 1] does not work for this case. + container_.splice(container_.end(), container_, iterCont_[from_beg], iterCont_[from_end + 1]); + } else { + container_.splice(iterCont_[to_end + 1], container_, iterCont_[from_beg], iterCont_[from_end + 1]); + } + recreateVector(); + } + void swap(size_t i, size_t j) { size_t const p = std::max(i, j); -- 2.20.1
signature.asc
Description: PGP signature
-- lyx-devel mailing list lyx-devel@lists.lyx.org http://lists.lyx.org/mailman/listinfo/lyx-devel