DynamicSelectionList: derive from SelectionList
the previous implementation did not preserve invariant either, so we'd better use less code.
This commit is contained in:
parent
57ad454b53
commit
1c94064713
|
@ -5,9 +5,10 @@ namespace Kakoune
|
|||
|
||||
DynamicSelectionList::DynamicSelectionList(const Buffer& buffer,
|
||||
SelectionList selections)
|
||||
: m_buffer(&buffer), m_selections(std::move(selections))
|
||||
: m_buffer(&buffer), SelectionList(std::move(selections))
|
||||
{
|
||||
m_buffer->add_change_listener(*this);
|
||||
check_invariant();
|
||||
}
|
||||
|
||||
DynamicSelectionList::~DynamicSelectionList()
|
||||
|
@ -16,51 +17,59 @@ DynamicSelectionList::~DynamicSelectionList()
|
|||
}
|
||||
|
||||
DynamicSelectionList::DynamicSelectionList(const DynamicSelectionList& other)
|
||||
: m_selections(other.m_selections), m_buffer(other.m_buffer)
|
||||
: SelectionList(other), m_buffer(other.m_buffer)
|
||||
{
|
||||
m_buffer->add_change_listener(*this);
|
||||
}
|
||||
|
||||
DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other)
|
||||
{
|
||||
m_selections = other.m_selections;
|
||||
SelectionList::operator=((const SelectionList&)other);
|
||||
if (m_buffer != other.m_buffer)
|
||||
{
|
||||
m_buffer->remove_change_listener(*this);
|
||||
m_buffer = other.m_buffer;
|
||||
m_buffer->add_change_listener(*this);
|
||||
}
|
||||
check_invariant();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSelectionList::DynamicSelectionList(DynamicSelectionList&& other)
|
||||
: m_selections(std::move(other.m_selections)), m_buffer(other.m_buffer)
|
||||
: SelectionList(std::move(other)), m_buffer(other.m_buffer)
|
||||
{
|
||||
m_buffer->add_change_listener(*this);
|
||||
}
|
||||
|
||||
DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other)
|
||||
{
|
||||
m_selections = std::move(other.m_selections);
|
||||
SelectionList::operator=(std::move(other));
|
||||
if (m_buffer != other.m_buffer)
|
||||
{
|
||||
m_buffer->remove_change_listener(*this);
|
||||
m_buffer = other.m_buffer;
|
||||
m_buffer->add_change_listener(*this);
|
||||
}
|
||||
check_invariant();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DynamicSelectionList::reset(SelectionList selections)
|
||||
DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections)
|
||||
{
|
||||
for (auto& sel : selections)
|
||||
assert(&sel.buffer() == m_buffer);
|
||||
m_selections = std::move(selections);
|
||||
SelectionList::operator=(std::move(selections));
|
||||
check_invariant();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DynamicSelectionList::check_invariant() const
|
||||
{
|
||||
for (auto& sel : *this)
|
||||
assert(m_buffer == &sel.buffer());
|
||||
}
|
||||
|
||||
void DynamicSelectionList::on_insert(const BufferIterator& begin, const BufferIterator& end)
|
||||
{
|
||||
for (auto& sel : m_selections)
|
||||
for (auto& sel : *this)
|
||||
{
|
||||
sel.first().on_insert(begin.coord(), end.coord());
|
||||
sel.last().on_insert(begin.coord(), end.coord());
|
||||
|
@ -70,7 +79,7 @@ void DynamicSelectionList::on_insert(const BufferIterator& begin, const BufferIt
|
|||
|
||||
void DynamicSelectionList::on_erase(const BufferIterator& begin, const BufferIterator& end)
|
||||
{
|
||||
for (auto& sel : m_selections)
|
||||
for (auto& sel : *this)
|
||||
{
|
||||
sel.first().on_erase(begin.coord(), end.coord());
|
||||
sel.last().on_erase(begin.coord(), end.coord());
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
class DynamicSelectionList : public BufferChangeListener
|
||||
class DynamicSelectionList : public SelectionList, public BufferChangeListener
|
||||
{
|
||||
public:
|
||||
using iterator = SelectionList::iterator;
|
||||
|
@ -20,34 +20,8 @@ public:
|
|||
DynamicSelectionList(DynamicSelectionList&& other);
|
||||
DynamicSelectionList& operator=(DynamicSelectionList&& other);
|
||||
|
||||
size_t size() const { return m_selections.size(); }
|
||||
bool empty() const { return m_selections.empty(); }
|
||||
|
||||
void clear() { m_selections.clear(); }
|
||||
iterator erase(iterator it) { return m_selections.erase(it); }
|
||||
|
||||
void push_back(Selection selection)
|
||||
{
|
||||
assert(&selection.buffer() == m_buffer);
|
||||
m_selections.push_back(std::move(selection));
|
||||
}
|
||||
|
||||
void reset(SelectionList selections);
|
||||
|
||||
iterator begin() { return m_selections.begin(); }
|
||||
iterator end() { return m_selections.end(); }
|
||||
const_iterator begin() const { return m_selections.begin(); }
|
||||
const_iterator end() const { return m_selections.end(); }
|
||||
|
||||
Selection& front() { return m_selections.front(); }
|
||||
Selection& back() { return m_selections.back(); }
|
||||
const Selection& front() const { return m_selections.front(); }
|
||||
const Selection& back() const { return m_selections.back(); }
|
||||
|
||||
Selection& operator[](size_t index) { return m_selections[index]; }
|
||||
const Selection& operator[](size_t index) const { return m_selections[index]; }
|
||||
|
||||
operator const SelectionList&() const { return m_selections; }
|
||||
DynamicSelectionList& operator=(SelectionList selections);
|
||||
void check_invariant() const;
|
||||
|
||||
const Buffer& buffer() const { return *m_buffer; }
|
||||
|
||||
|
@ -58,7 +32,6 @@ private:
|
|||
const BufferIterator& end) override;
|
||||
|
||||
const Buffer* m_buffer;
|
||||
SelectionList m_selections;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -102,7 +102,7 @@ void Editor::insert(const memoryview<String>& strings, InsertMode mode)
|
|||
|
||||
for (size_t i = 0; i < selections().size(); ++i)
|
||||
{
|
||||
Selection& sel = m_selections[i];
|
||||
auto& sel = m_selections[i];
|
||||
BufferIterator pos = prepare_insert(*m_buffer, sel, mode);
|
||||
size_t index = std::min(i, strings.size()-1);
|
||||
m_buffer->insert(pos, strings[index]);
|
||||
|
@ -119,7 +119,7 @@ std::vector<String> Editor::selections_content() const
|
|||
return contents;
|
||||
}
|
||||
|
||||
static void merge_overlapping(DynamicSelectionList& selections)
|
||||
static void merge_overlapping(SelectionList& selections)
|
||||
{
|
||||
for (size_t i = 0; i < selections.size(); ++i)
|
||||
{
|
||||
|
@ -174,8 +174,7 @@ void Editor::clear_selections()
|
|||
pos = utf8::previous(pos);
|
||||
|
||||
Selection sel = Selection(pos, pos);
|
||||
m_selections.clear();
|
||||
m_selections.push_back(std::move(sel));
|
||||
m_selections = SelectionList{ std::move(sel) };
|
||||
}
|
||||
|
||||
void Editor::flip_selections()
|
||||
|
@ -190,11 +189,7 @@ void Editor::keep_selection(int index)
|
|||
check_invariant();
|
||||
|
||||
if (index < m_selections.size())
|
||||
{
|
||||
Selection sel = std::move(m_selections[index]);
|
||||
m_selections.clear();
|
||||
m_selections.push_back(std::move(sel));
|
||||
}
|
||||
m_selections = SelectionList{ std::move(m_selections[index]) };
|
||||
}
|
||||
|
||||
void Editor::remove_selection(int index)
|
||||
|
@ -207,15 +202,14 @@ void Editor::remove_selection(int index)
|
|||
|
||||
void Editor::select(const BufferIterator& iterator)
|
||||
{
|
||||
m_selections.clear();
|
||||
m_selections.push_back(Selection(iterator, iterator));
|
||||
m_selections = SelectionList{ {iterator, iterator} };
|
||||
}
|
||||
|
||||
void Editor::select(SelectionList selections)
|
||||
{
|
||||
if (selections.empty())
|
||||
throw runtime_error("no selections");
|
||||
m_selections.reset(std::move(selections));
|
||||
m_selections = std::move(selections);
|
||||
}
|
||||
|
||||
void Editor::select(const Selector& selector, SelectMode mode)
|
||||
|
@ -272,9 +266,8 @@ void Editor::multi_select(const MultiSelector& selector)
|
|||
}
|
||||
if (new_selections.empty())
|
||||
throw nothing_selected();
|
||||
|
||||
m_selections.reset(std::move(new_selections));
|
||||
merge_overlapping(m_selections);
|
||||
merge_overlapping(new_selections);
|
||||
m_selections = std::move(new_selections);
|
||||
}
|
||||
|
||||
class LastModifiedRangeListener : public BufferChangeListener
|
||||
|
@ -315,10 +308,7 @@ bool Editor::undo()
|
|||
LastModifiedRangeListener listener(buffer());
|
||||
bool res = m_buffer->undo();
|
||||
if (res)
|
||||
{
|
||||
m_selections.clear();
|
||||
m_selections.push_back({listener.first(), listener.last()});
|
||||
}
|
||||
m_selections = SelectionList{ {listener.first(), listener.last()} };
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -327,16 +317,14 @@ bool Editor::redo()
|
|||
LastModifiedRangeListener listener(buffer());
|
||||
bool res = m_buffer->redo();
|
||||
if (res)
|
||||
{
|
||||
m_selections.clear();
|
||||
m_selections.push_back({listener.first(), listener.last()});
|
||||
}
|
||||
m_selections = SelectionList{ {listener.first(), listener.last()} };
|
||||
return res;
|
||||
}
|
||||
|
||||
void Editor::check_invariant() const
|
||||
{
|
||||
assert(not m_selections.empty());
|
||||
m_selections.check_invariant();
|
||||
}
|
||||
|
||||
void Editor::begin_edition()
|
||||
|
|
Loading…
Reference in New Issue
Block a user