You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.4 KiB
191 lines
4.4 KiB
/*
|
|
Rosegarden
|
|
A sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <bownie@bownie.com>
|
|
|
|
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 "SnapGrid.h"
|
|
#include "Composition.h"
|
|
|
|
namespace Rosegarden {
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// SnapGrid
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
const timeT SnapGrid::NoSnap = -1;
|
|
const timeT SnapGrid::SnapToBar = -2;
|
|
const timeT SnapGrid::SnapToBeat = -3;
|
|
const timeT SnapGrid::SnapToUnit = -4;
|
|
|
|
SnapGrid::SnapGrid(RulerScale *rulerScale, int ysnap) :
|
|
m_rulerScale(rulerScale),
|
|
m_snapTime(SnapToBeat),
|
|
m_ysnap(ysnap)
|
|
{
|
|
// nothing else
|
|
}
|
|
|
|
void
|
|
SnapGrid::setSnapTime(timeT snap)
|
|
{
|
|
assert(snap > 0 ||
|
|
snap == NoSnap ||
|
|
snap == SnapToBar ||
|
|
snap == SnapToBeat ||
|
|
snap == SnapToUnit);
|
|
m_snapTime = snap;
|
|
}
|
|
|
|
timeT
|
|
SnapGrid::getSnapSetting() const
|
|
{
|
|
return m_snapTime;
|
|
}
|
|
|
|
timeT
|
|
SnapGrid::getSnapTime(double x) const
|
|
{
|
|
timeT time = m_rulerScale->getTimeForX(x);
|
|
return getSnapTime(time);
|
|
}
|
|
|
|
timeT
|
|
SnapGrid::getSnapTime(timeT time) const
|
|
{
|
|
if (m_snapTime == NoSnap) return 0;
|
|
|
|
Rosegarden::Composition *composition = m_rulerScale->getComposition();
|
|
int barNo = composition->getBarNumber(time);
|
|
std::pair<timeT, timeT> barRange = composition->getBarRange(barNo);
|
|
|
|
timeT snapTime = barRange.second - barRange.first;
|
|
|
|
if (m_snapTime == SnapToBeat) {
|
|
snapTime = composition->getTimeSignatureAt(time).getBeatDuration();
|
|
} else if (m_snapTime == SnapToUnit) {
|
|
snapTime = composition->getTimeSignatureAt(time).getUnitDuration();
|
|
} else if (m_snapTime != SnapToBar && m_snapTime < snapTime) {
|
|
snapTime = m_snapTime;
|
|
}
|
|
|
|
return snapTime;
|
|
}
|
|
|
|
timeT
|
|
SnapGrid::snapX(double x, SnapDirection direction) const
|
|
{
|
|
return snapTime(m_rulerScale->getTimeForX(x), direction);
|
|
}
|
|
|
|
timeT
|
|
SnapGrid::snapTime(timeT time, SnapDirection direction) const
|
|
{
|
|
if (m_snapTime == NoSnap) return time;
|
|
|
|
Rosegarden::Composition *composition = m_rulerScale->getComposition();
|
|
int barNo = composition->getBarNumber(time);
|
|
std::pair<timeT, timeT> barRange = composition->getBarRange(barNo);
|
|
|
|
timeT snapTime = barRange.second - barRange.first;
|
|
|
|
if (m_snapTime == SnapToBeat) {
|
|
snapTime = composition->getTimeSignatureAt(time).getBeatDuration();
|
|
} else if (m_snapTime == SnapToUnit) {
|
|
snapTime = composition->getTimeSignatureAt(time).getUnitDuration();
|
|
} else if (m_snapTime != SnapToBar && m_snapTime < snapTime) {
|
|
snapTime = m_snapTime;
|
|
}
|
|
|
|
timeT offset = (time - barRange.first);
|
|
timeT rounded = (offset / snapTime) * snapTime;
|
|
|
|
timeT left = rounded + barRange.first;
|
|
timeT right = left + snapTime;
|
|
|
|
if (direction == SnapLeft) return left;
|
|
else if (direction == SnapRight) return right;
|
|
else if ((offset - rounded) > (rounded + snapTime - offset)) return right;
|
|
else return left;
|
|
}
|
|
|
|
int
|
|
SnapGrid::getYBin(int y) const
|
|
{
|
|
if (m_ysnap == 0) return y;
|
|
|
|
int cy = 0;
|
|
|
|
std::map<int, int>::const_iterator i = m_ymultiple.begin();
|
|
|
|
int nextbin = -1;
|
|
if (i != m_ymultiple.end()) nextbin = i->first;
|
|
|
|
for (int b = 0; ; ++b) {
|
|
|
|
if (nextbin == b) {
|
|
|
|
cy += i->second * m_ysnap;
|
|
++i;
|
|
if (i == m_ymultiple.end()) nextbin = -1;
|
|
else nextbin = i->first;
|
|
|
|
} else {
|
|
|
|
cy += m_ysnap;
|
|
}
|
|
|
|
if (cy > y) {
|
|
return b;
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
SnapGrid::getYBinCoordinate(int bin) const
|
|
{
|
|
if (m_ysnap == 0) return bin;
|
|
|
|
int y = 0;
|
|
|
|
std::map<int, int>::const_iterator i = m_ymultiple.begin();
|
|
|
|
int nextbin = -1;
|
|
if (i != m_ymultiple.end()) nextbin = i->first;
|
|
|
|
for (int b = 0; b < bin; ++b) {
|
|
|
|
if (nextbin == b) {
|
|
|
|
y += i->second * m_ysnap;
|
|
++i;
|
|
if (i == m_ymultiple.end()) nextbin = -1;
|
|
else nextbin = i->first;
|
|
|
|
} else {
|
|
|
|
y += m_ysnap;
|
|
}
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
|
|
}
|