diff options
Diffstat (limited to 'src/base/Staff.cpp')
-rw-r--r-- | src/base/Staff.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/base/Staff.cpp b/src/base/Staff.cpp new file mode 100644 index 0000000..e34aaca --- /dev/null +++ b/src/base/Staff.cpp @@ -0,0 +1,213 @@ +// -*- c-basic-offset: 4 -*- + +/* + Rosegarden + A sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + The moral right of the authors to claim authorship of this work + has been asserted. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "Staff.h" + +namespace Rosegarden +{ + +Staff::Staff(Segment &t) : + m_segment(t), + m_viewElementList(0) +{ + // empty +} + +Staff::~Staff() +{ + if (m_viewElementList) m_segment.removeObserver(this); + notifySourceDeletion(); + delete m_viewElementList; +} + +ViewElementList * +Staff::getViewElementList() +{ + return getViewElementList(m_segment.begin(), m_segment.end()); +} + +ViewElementList * +Staff::getViewElementList(Segment::iterator from, + Segment::iterator to) +{ + if (!m_viewElementList) { + + m_viewElementList = new ViewElementList; + + for (Segment::iterator i = from; i != to; ++i) { + + if (!wrapEvent(*i)) continue; + + ViewElement *el = makeViewElement(*i); + m_viewElementList->insert(el); + } + + m_segment.addObserver(this); + + } + + return m_viewElementList; +} + +bool +Staff::wrapEvent(Event *e) +{ + timeT emt = m_segment.getEndMarkerTime(); + return + (e->getAbsoluteTime() < emt) || + (e->getAbsoluteTime() == emt && e->getDuration() == 0); +} + +ViewElementList::iterator +Staff::findEvent(Event *e) +{ + // Note that we have to create this using the virtual + // makeViewElement, because the result of equal_range depends on + // the value of the view absolute time for the element, which + // depends on the particular subclass of ViewElement in use. + + //!!! (This is also why this method has to be here and not in + // ViewElementList -- ViewElementList has no equivalent of + // makeViewElement. Possibly things like NotationElementList + // should be subclasses of ViewElementList that implement + // makeViewElement instead of having makeViewElement in Staff, but + // that's for another day.) + + ViewElement *dummy = makeViewElement(e); + + std::pair<ViewElementList::iterator, + ViewElementList::iterator> + r = m_viewElementList->equal_range(dummy); + + delete dummy; + + for (ViewElementList::iterator i = r.first; i != r.second; ++i) { + if ((*i)->event() == e) { + return i; + } + } + + return m_viewElementList->end(); +} + +void +Staff::eventAdded(const Segment *t, Event *e) +{ + assert(t == &m_segment); + (void)t; // avoid warnings + + if (wrapEvent(e)) { + ViewElement *el = makeViewElement(e); + m_viewElementList->insert(el); + notifyAdd(el); + } +} + +void +Staff::eventRemoved(const Segment *t, Event *e) +{ + assert(t == &m_segment); + (void)t; // avoid warnings + + // If we have it, lose it + + ViewElementList::iterator i = findEvent(e); + if (i != m_viewElementList->end()) { + notifyRemove(*i); + m_viewElementList->erase(i); + return; + } + +// std::cerr << "Event at " << e->getAbsoluteTime() << ", notation time " << e->getNotationAbsoluteTime() << ", type " << e->getType() +// << " not found in Staff" << std::endl; +} + +void +Staff::endMarkerTimeChanged(const Segment *segment, bool shorten) +{ + Segment *s = const_cast<Segment *>(segment); + + assert(s == &m_segment); + + if (shorten) { + + m_viewElementList->erase + (m_viewElementList->findTime(s->getEndMarkerTime()), + m_viewElementList->end()); + + } else { + + timeT myLastEltTime = s->getStartTime(); + if (m_viewElementList->end() != m_viewElementList->begin()) { + ViewElementList::iterator i = m_viewElementList->end(); + myLastEltTime = (*--i)->event()->getAbsoluteTime(); + } + + for (Segment::iterator j = s->findTime(myLastEltTime); + s->isBeforeEndMarker(j); ++j) { + + ViewElementList::iterator newi = findEvent(*j); + if (newi == m_viewElementList->end()) { + m_viewElementList->insert(makeViewElement(*j)); + } + } + } +} +void +Staff::segmentDeleted(const Segment *s) +{ + assert(s == &m_segment); + (void)s; // avoid warnings + /* + std::cerr << "WARNING: Staff notified of segment deletion: this is probably a bug " + << "(staff should have been deleted before segment)" << std::endl; + */ +} + +void +Staff::notifyAdd(ViewElement *e) const +{ + for (ObserverSet::const_iterator i = m_observers.begin(); + i != m_observers.end(); ++i) { + (*i)->elementAdded(this, e); + } +} + +void +Staff::notifyRemove(ViewElement *e) const +{ + for (ObserverSet::const_iterator i = m_observers.begin(); + i != m_observers.end(); ++i) { + (*i)->elementRemoved(this, e); + } +} + +void +Staff::notifySourceDeletion() const +{ + for (ObserverSet::const_iterator i = m_observers.begin(); + i != m_observers.end(); ++i) { + (*i)->staffDeleted(this); + } +} + + +} |