Mercurial > hg > svcore
diff base/Selection.cpp @ 24:bb9291d84810
* Add ffwd/rewind
* Abstract out MultiSelection
author | Chris Cannam |
---|---|
date | Wed, 08 Feb 2006 17:59:16 +0000 |
parents | 73d85d19919f |
children | 935a2419a77c |
line wrap: on
line diff
--- a/base/Selection.cpp Mon Feb 06 17:24:52 2006 +0000 +++ b/base/Selection.cpp Wed Feb 08 17:59:16 2006 +0000 @@ -91,3 +91,98 @@ m_endFrame == s.m_endFrame); } + +MultiSelection::MultiSelection() +{ +} + +MultiSelection::~MultiSelection() +{ +} + +const MultiSelection::SelectionList & +MultiSelection::getSelections() const +{ + return m_selections; +} + +void +MultiSelection::setSelection(const Selection &selection) +{ + clearSelections(); + addSelection(selection); +} + +void +MultiSelection::addSelection(const Selection &selection) +{ + m_selections.insert(selection); + + // Cope with a sitation where the new selection overlaps one or + // more existing ones. This is a terribly inefficient way to do + // this, but that probably isn't significant in real life. + + // It's essential for the correct operation of + // getContainingSelection that the selections do not overlap, so + // this is not just a frill. + + for (SelectionList::iterator i = m_selections.begin(); + i != m_selections.end(); ) { + + SelectionList::iterator j = i; + if (++j == m_selections.end()) break; + + if (i->getEndFrame() >= j->getStartFrame()) { + Selection merged(i->getStartFrame(), + std::max(i->getEndFrame(), j->getEndFrame())); + m_selections.erase(i); + m_selections.erase(j); + m_selections.insert(merged); + i = m_selections.begin(); + } else { + ++i; + } + } +} + +void +MultiSelection::removeSelection(const Selection &selection) +{ + //!!! Likewise this needs to cope correctly with the situation + //where selection is not one of the original selection set but + //simply overlaps one of them (cutting down the original selection + //appropriately) + + if (m_selections.find(selection) != m_selections.end()) { + m_selections.erase(selection); + } +} + +void +MultiSelection::clearSelections() +{ + if (!m_selections.empty()) { + m_selections.clear(); + } +} + +Selection +MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing) +{ + // This scales very badly with the number of selections, but it's + // more efficient for very small numbers of selections than a more + // scalable method, and I think that may be what we need + + for (SelectionList::const_iterator i = m_selections.begin(); + i != m_selections.end(); ++i) { + + if (i->contains(frame)) return *i; + + if (i->getStartFrame() > frame) { + if (defaultToFollowing) return *i; + else return Selection(); + } + } + + return Selection(); +}