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,
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());

View File

@ -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;
};
};

View File

@ -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()