summaryrefslogtreecommitdiffstats
path: root/src/base/Staff.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/Staff.cpp')
-rw-r--r--src/base/Staff.cpp213
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);
+ }
+}
+
+
+}