Editor: undo and redo select all ranges modified instead of the last one

This commit is contained in:
Maxime Coste 2013-05-02 19:31:58 +02:00
parent 4c4b6a404d
commit 564cfb084e

View File

@ -128,11 +128,18 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
return lhs.begin() < rhs.begin(); return lhs.begin() < rhs.begin();
} }
static void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection) template<bool already_sorted = false>
void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection)
{ {
if (selections.size() == 1) if (selections.size() == 1)
return; return;
if (already_sorted)
{
kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
}
else
{
const auto& main = selections[main_selection]; const auto& main = selections[main_selection];
const auto main_begin = main.begin(); const auto main_begin = main.begin();
main_selection = std::count_if(selections.begin(), selections.end(), main_selection = std::count_if(selections.begin(), selections.end(),
@ -144,6 +151,7 @@ static void sort_and_merge_overlapping(SelectionList& selections, size_t& main_s
return sel.begin() < main_begin; return sel.begin() < main_begin;
}); });
std::stable_sort(selections.begin(), selections.end(), compare_selections); std::stable_sort(selections.begin(), selections.end(), compare_selections);
}
for (size_t i = 0; i+1 < selections.size() and selections.size() > 1;) for (size_t i = 0; i+1 < selections.size() and selections.size() > 1;)
{ {
@ -339,50 +347,51 @@ void Editor::multi_select(const MultiSelector& selector)
check_invariant(); check_invariant();
} }
class LastModifiedRangeListener : public BufferChangeListener class ModifiedRangesListener : public BufferChangeListener_AutoRegister
{ {
public: public:
LastModifiedRangeListener(Buffer& buffer) ModifiedRangesListener(Buffer& buffer)
: m_buffer(buffer) : BufferChangeListener_AutoRegister(buffer) {}
{ m_buffer.change_listeners().insert(this); }
~LastModifiedRangeListener()
{ m_buffer.change_listeners().erase(this); }
void on_insert(const BufferIterator& begin, const BufferIterator& end) void on_insert(const BufferIterator& begin, const BufferIterator& end)
{ {
kak_assert(begin.is_valid()); kak_assert(begin.is_valid());
kak_assert(end.is_valid()); kak_assert(end.is_valid());
m_first = begin; m_ranges.update_insert(begin.coord(), end.coord());
m_last = utf8::previous(end); auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin,
[](const BufferIterator& it, const Selection& sel)
{ return it < sel.begin(); });
m_ranges.emplace(it, begin, utf8::previous(end));
} }
void on_erase(const BufferIterator& begin, const BufferIterator& end) void on_erase(const BufferIterator& begin, const BufferIterator& end)
{ {
kak_assert(begin.is_valid()); kak_assert(begin.is_valid());
m_first = begin; m_ranges.update_erase(begin.coord(), end.coord());
if (m_first >= m_buffer.end()) auto pos = begin;
m_first = utf8::previous(m_buffer.end()); if (pos >= buffer().end())
m_last = m_first; pos = utf8::previous(buffer().end());
}
const BufferIterator& first() const { return m_first; } auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin,
const BufferIterator& last() const { return m_last; } [](const BufferIterator& it, const Selection& sel)
{ return it < sel.begin(); });
m_ranges.emplace(it, pos, pos);
}
SelectionList& ranges() { return m_ranges; }
private: private:
BufferIterator m_first; SelectionList m_ranges;
BufferIterator m_last;
Buffer& m_buffer;
}; };
bool Editor::undo() bool Editor::undo()
{ {
LastModifiedRangeListener listener(buffer()); ModifiedRangesListener listener(buffer());
bool res = m_buffer->undo(); bool res = m_buffer->undo();
if (res) if (res and not listener.ranges().empty())
{ {
m_selections = SelectionList{ {listener.first(), listener.last()} }; m_selections = std::move(listener.ranges());
m_main_sel = 0; m_main_sel = m_selections.size() - 1;
sort_and_merge_overlapping<true>(m_selections, m_main_sel);
} }
check_invariant(); check_invariant();
return res; return res;
@ -390,12 +399,13 @@ bool Editor::undo()
bool Editor::redo() bool Editor::redo()
{ {
LastModifiedRangeListener listener(buffer()); ModifiedRangesListener listener(buffer());
bool res = m_buffer->redo(); bool res = m_buffer->redo();
if (res) if (res and not listener.ranges().empty())
{ {
m_selections = SelectionList{ {listener.first(), listener.last()} }; m_selections = std::move(listener.ranges());
m_main_sel = 0; m_main_sel = m_selections.size() - 1;
sort_and_merge_overlapping<true>(m_selections, m_main_sel);
} }
check_invariant(); check_invariant();
return res; return res;