annotate base/Selection.cpp @ 26:090c22aa726a

* Add the Note layer for pianoroll-type display of note-type data * Complete the MIDI file importer (well, nearly -- it would be nice to be able to import the non-note data as other sorts of models, and that's not done yet). * Minor refactoring in RealTime etc
author Chris Cannam
date Fri, 10 Feb 2006 17:51:36 +0000
parents bb9291d84810
children 935a2419a77c
rev   line source
Chris@8 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@8 2
Chris@8 3 /*
Chris@8 4 A waveform viewer and audio annotation editor.
Chris@8 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@8 6
Chris@8 7 This is experimental software. Not for distribution.
Chris@8 8 */
Chris@8 9
Chris@8 10 #include "Selection.h"
Chris@8 11
Chris@8 12 Selection::Selection() :
Chris@8 13 m_startFrame(0),
Chris@8 14 m_endFrame(0)
Chris@8 15 {
Chris@8 16 }
Chris@8 17
Chris@8 18 Selection::Selection(size_t startFrame, size_t endFrame) :
Chris@8 19 m_startFrame(startFrame),
Chris@8 20 m_endFrame(endFrame)
Chris@8 21 {
Chris@8 22 if (m_startFrame > m_endFrame) {
Chris@8 23 size_t tmp = m_endFrame;
Chris@8 24 m_endFrame = m_startFrame;
Chris@8 25 m_startFrame = tmp;
Chris@8 26 }
Chris@8 27 }
Chris@8 28
Chris@8 29 Selection::Selection(const Selection &s) :
Chris@8 30 m_startFrame(s.m_startFrame),
Chris@8 31 m_endFrame(s.m_endFrame)
Chris@8 32 {
Chris@8 33 }
Chris@8 34
Chris@8 35 Selection &
Chris@8 36 Selection::operator=(const Selection &s)
Chris@8 37 {
Chris@8 38 if (this != &s) {
Chris@8 39 m_startFrame = s.m_startFrame;
Chris@8 40 m_endFrame = s.m_endFrame;
Chris@8 41 }
Chris@8 42 return *this;
Chris@8 43 }
Chris@8 44
Chris@8 45 Selection::~Selection()
Chris@8 46 {
Chris@8 47 }
Chris@8 48
Chris@8 49 bool
Chris@8 50 Selection::isEmpty() const
Chris@8 51 {
Chris@8 52 return m_startFrame == m_endFrame;
Chris@8 53 }
Chris@8 54
Chris@8 55 size_t
Chris@8 56 Selection::getStartFrame() const
Chris@8 57 {
Chris@8 58 return m_startFrame;
Chris@8 59 }
Chris@8 60
Chris@8 61 size_t
Chris@8 62 Selection::getEndFrame() const
Chris@8 63 {
Chris@8 64 return m_endFrame;
Chris@8 65 }
Chris@8 66
Chris@8 67 bool
Chris@9 68 Selection::contains(size_t frame) const
Chris@9 69 {
Chris@9 70 return (frame >= m_startFrame) && (frame < m_endFrame);
Chris@9 71 }
Chris@9 72
Chris@9 73 bool
Chris@8 74 Selection::operator<(const Selection &s) const
Chris@8 75 {
Chris@9 76 if (isEmpty()) {
Chris@9 77 if (s.isEmpty()) return false;
Chris@9 78 else return true;
Chris@9 79 } else {
Chris@9 80 if (s.isEmpty()) return false;
Chris@9 81 else return (m_startFrame < s.m_startFrame);
Chris@9 82 }
Chris@8 83 }
Chris@8 84
Chris@8 85 bool
Chris@8 86 Selection::operator==(const Selection &s) const
Chris@8 87 {
Chris@9 88 if (isEmpty()) return s.isEmpty();
Chris@9 89
Chris@8 90 return (m_startFrame == s.m_startFrame &&
Chris@8 91 m_endFrame == s.m_endFrame);
Chris@8 92 }
Chris@8 93
Chris@24 94
Chris@24 95 MultiSelection::MultiSelection()
Chris@24 96 {
Chris@24 97 }
Chris@24 98
Chris@24 99 MultiSelection::~MultiSelection()
Chris@24 100 {
Chris@24 101 }
Chris@24 102
Chris@24 103 const MultiSelection::SelectionList &
Chris@24 104 MultiSelection::getSelections() const
Chris@24 105 {
Chris@24 106 return m_selections;
Chris@24 107 }
Chris@24 108
Chris@24 109 void
Chris@24 110 MultiSelection::setSelection(const Selection &selection)
Chris@24 111 {
Chris@24 112 clearSelections();
Chris@24 113 addSelection(selection);
Chris@24 114 }
Chris@24 115
Chris@24 116 void
Chris@24 117 MultiSelection::addSelection(const Selection &selection)
Chris@24 118 {
Chris@24 119 m_selections.insert(selection);
Chris@24 120
Chris@24 121 // Cope with a sitation where the new selection overlaps one or
Chris@24 122 // more existing ones. This is a terribly inefficient way to do
Chris@24 123 // this, but that probably isn't significant in real life.
Chris@24 124
Chris@24 125 // It's essential for the correct operation of
Chris@24 126 // getContainingSelection that the selections do not overlap, so
Chris@24 127 // this is not just a frill.
Chris@24 128
Chris@24 129 for (SelectionList::iterator i = m_selections.begin();
Chris@24 130 i != m_selections.end(); ) {
Chris@24 131
Chris@24 132 SelectionList::iterator j = i;
Chris@24 133 if (++j == m_selections.end()) break;
Chris@24 134
Chris@24 135 if (i->getEndFrame() >= j->getStartFrame()) {
Chris@24 136 Selection merged(i->getStartFrame(),
Chris@24 137 std::max(i->getEndFrame(), j->getEndFrame()));
Chris@24 138 m_selections.erase(i);
Chris@24 139 m_selections.erase(j);
Chris@24 140 m_selections.insert(merged);
Chris@24 141 i = m_selections.begin();
Chris@24 142 } else {
Chris@24 143 ++i;
Chris@24 144 }
Chris@24 145 }
Chris@24 146 }
Chris@24 147
Chris@24 148 void
Chris@24 149 MultiSelection::removeSelection(const Selection &selection)
Chris@24 150 {
Chris@24 151 //!!! Likewise this needs to cope correctly with the situation
Chris@24 152 //where selection is not one of the original selection set but
Chris@24 153 //simply overlaps one of them (cutting down the original selection
Chris@24 154 //appropriately)
Chris@24 155
Chris@24 156 if (m_selections.find(selection) != m_selections.end()) {
Chris@24 157 m_selections.erase(selection);
Chris@24 158 }
Chris@24 159 }
Chris@24 160
Chris@24 161 void
Chris@24 162 MultiSelection::clearSelections()
Chris@24 163 {
Chris@24 164 if (!m_selections.empty()) {
Chris@24 165 m_selections.clear();
Chris@24 166 }
Chris@24 167 }
Chris@24 168
Chris@24 169 Selection
Chris@24 170 MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing)
Chris@24 171 {
Chris@24 172 // This scales very badly with the number of selections, but it's
Chris@24 173 // more efficient for very small numbers of selections than a more
Chris@24 174 // scalable method, and I think that may be what we need
Chris@24 175
Chris@24 176 for (SelectionList::const_iterator i = m_selections.begin();
Chris@24 177 i != m_selections.end(); ++i) {
Chris@24 178
Chris@24 179 if (i->contains(frame)) return *i;
Chris@24 180
Chris@24 181 if (i->getStartFrame() > frame) {
Chris@24 182 if (defaultToFollowing) return *i;
Chris@24 183 else return Selection();
Chris@24 184 }
Chris@24 185 }
Chris@24 186
Chris@24 187 return Selection();
Chris@24 188 }