DynamicSelectionList: derive from SelectionList

the previous implementation did not preserve invariant
either, so we'd better use less code.
This commit is contained in:
Maxime Coste 2012-12-12 14:21:50 +01:00
parent 57ad454b53
commit 1c94064713
3 changed files with 34 additions and 64 deletions

View File

@ -5,9 +5,10 @@ namespace Kakoune
DynamicSelectionList::DynamicSelectionList(const Buffer& buffer, DynamicSelectionList::DynamicSelectionList(const Buffer& buffer,
SelectionList selections) SelectionList selections)
: m_buffer(&buffer), m_selections(std::move(selections)) : m_buffer(&buffer), SelectionList(std::move(selections))
{ {
m_buffer->add_change_listener(*this); m_buffer->add_change_listener(*this);
check_invariant();
} }
DynamicSelectionList::~DynamicSelectionList() DynamicSelectionList::~DynamicSelectionList()
@ -16,51 +17,59 @@ DynamicSelectionList::~DynamicSelectionList()
} }
DynamicSelectionList::DynamicSelectionList(const DynamicSelectionList& other) 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); m_buffer->add_change_listener(*this);
} }
DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other) DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other)
{ {
m_selections = other.m_selections; SelectionList::operator=((const SelectionList&)other);
if (m_buffer != other.m_buffer) if (m_buffer != other.m_buffer)
{ {
m_buffer->remove_change_listener(*this); m_buffer->remove_change_listener(*this);
m_buffer = other.m_buffer; m_buffer = other.m_buffer;
m_buffer->add_change_listener(*this); m_buffer->add_change_listener(*this);
} }
check_invariant();
return *this; return *this;
} }
DynamicSelectionList::DynamicSelectionList(DynamicSelectionList&& other) 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); m_buffer->add_change_listener(*this);
} }
DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other) DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other)
{ {
m_selections = std::move(other.m_selections); SelectionList::operator=(std::move(other));
if (m_buffer != other.m_buffer) if (m_buffer != other.m_buffer)
{ {
m_buffer->remove_change_listener(*this); m_buffer->remove_change_listener(*this);
m_buffer = other.m_buffer; m_buffer = other.m_buffer;
m_buffer->add_change_listener(*this); m_buffer->add_change_listener(*this);
} }
check_invariant();
return *this; return *this;
} }
void DynamicSelectionList::reset(SelectionList selections) DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections)
{ {
for (auto& sel : selections) SelectionList::operator=(std::move(selections));
assert(&sel.buffer() == m_buffer); check_invariant();
m_selections = std::move(selections); 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) 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.first().on_insert(begin.coord(), end.coord());
sel.last().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) 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.first().on_erase(begin.coord(), end.coord());
sel.last().on_erase(begin.coord(), end.coord()); sel.last().on_erase(begin.coord(), end.coord());

View File

@ -6,7 +6,7 @@
namespace Kakoune namespace Kakoune
{ {
class DynamicSelectionList : public BufferChangeListener class DynamicSelectionList : public SelectionList, public BufferChangeListener
{ {
public: public:
using iterator = SelectionList::iterator; using iterator = SelectionList::iterator;
@ -20,34 +20,8 @@ public:
DynamicSelectionList(DynamicSelectionList&& other); DynamicSelectionList(DynamicSelectionList&& other);
DynamicSelectionList& operator=(DynamicSelectionList&& other); DynamicSelectionList& operator=(DynamicSelectionList&& other);
size_t size() const { return m_selections.size(); } DynamicSelectionList& operator=(SelectionList selections);
bool empty() const { return m_selections.empty(); } void check_invariant() const;
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; }
const Buffer& buffer() const { return *m_buffer; } const Buffer& buffer() const { return *m_buffer; }
@ -58,7 +32,6 @@ private:
const BufferIterator& end) override; const BufferIterator& end) override;
const Buffer* m_buffer; const Buffer* m_buffer;
SelectionList m_selections;
}; };
}; };

View File

@ -102,7 +102,7 @@ void Editor::insert(const memoryview<String>& strings, InsertMode mode)
for (size_t i = 0; i < selections().size(); ++i) 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); BufferIterator pos = prepare_insert(*m_buffer, sel, mode);
size_t index = std::min(i, strings.size()-1); size_t index = std::min(i, strings.size()-1);
m_buffer->insert(pos, strings[index]); m_buffer->insert(pos, strings[index]);
@ -119,7 +119,7 @@ std::vector<String> Editor::selections_content() const
return contents; return contents;
} }
static void merge_overlapping(DynamicSelectionList& selections) static void merge_overlapping(SelectionList& selections)
{ {
for (size_t i = 0; i < selections.size(); ++i) for (size_t i = 0; i < selections.size(); ++i)
{ {
@ -174,8 +174,7 @@ void Editor::clear_selections()
pos = utf8::previous(pos); pos = utf8::previous(pos);
Selection sel = Selection(pos, pos); Selection sel = Selection(pos, pos);
m_selections.clear(); m_selections = SelectionList{ std::move(sel) };
m_selections.push_back(std::move(sel));
} }
void Editor::flip_selections() void Editor::flip_selections()
@ -190,11 +189,7 @@ void Editor::keep_selection(int index)
check_invariant(); check_invariant();
if (index < m_selections.size()) if (index < m_selections.size())
{ m_selections = SelectionList{ std::move(m_selections[index]) };
Selection sel = std::move(m_selections[index]);
m_selections.clear();
m_selections.push_back(std::move(sel));
}
} }
void Editor::remove_selection(int index) void Editor::remove_selection(int index)
@ -207,15 +202,14 @@ void Editor::remove_selection(int index)
void Editor::select(const BufferIterator& iterator) void Editor::select(const BufferIterator& iterator)
{ {
m_selections.clear(); m_selections = SelectionList{ {iterator, iterator} };
m_selections.push_back(Selection(iterator, iterator));
} }
void Editor::select(SelectionList selections) void Editor::select(SelectionList selections)
{ {
if (selections.empty()) if (selections.empty())
throw runtime_error("no selections"); throw runtime_error("no selections");
m_selections.reset(std::move(selections)); m_selections = std::move(selections);
} }
void Editor::select(const Selector& selector, SelectMode mode) void Editor::select(const Selector& selector, SelectMode mode)
@ -272,9 +266,8 @@ void Editor::multi_select(const MultiSelector& selector)
} }
if (new_selections.empty()) if (new_selections.empty())
throw nothing_selected(); throw nothing_selected();
merge_overlapping(new_selections);
m_selections.reset(std::move(new_selections)); m_selections = std::move(new_selections);
merge_overlapping(m_selections);
} }
class LastModifiedRangeListener : public BufferChangeListener class LastModifiedRangeListener : public BufferChangeListener
@ -315,10 +308,7 @@ bool Editor::undo()
LastModifiedRangeListener listener(buffer()); LastModifiedRangeListener listener(buffer());
bool res = m_buffer->undo(); bool res = m_buffer->undo();
if (res) if (res)
{ m_selections = SelectionList{ {listener.first(), listener.last()} };
m_selections.clear();
m_selections.push_back({listener.first(), listener.last()});
}
return res; return res;
} }
@ -327,16 +317,14 @@ bool Editor::redo()
LastModifiedRangeListener listener(buffer()); LastModifiedRangeListener listener(buffer());
bool res = m_buffer->redo(); bool res = m_buffer->redo();
if (res) if (res)
{ m_selections = SelectionList{ {listener.first(), listener.last()} };
m_selections.clear();
m_selections.push_back({listener.first(), listener.last()});
}
return res; return res;
} }
void Editor::check_invariant() const void Editor::check_invariant() const
{ {
assert(not m_selections.empty()); assert(not m_selections.empty());
m_selections.check_invariant();
} }
void Editor::begin_edition() void Editor::begin_edition()