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.
rosegarden/src/base/SnapGrid.h

182 lines
5.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.
*/
#ifndef _SNAP_GRID_H_
#define _SNAP_GRID_H_
#include "RulerScale.h"
#include <map>
namespace Rosegarden {
/**
* SnapGrid is a class that maps x-coordinate onto time, using a
* RulerScale to get the mapping but constraining the results to a
* discrete set of suitable times.
*
* (It also snaps y-coordinates, but that bit isn't very interesting.)
*/
class SnapGrid
{
public:
/**
* Construct a SnapGrid that uses the given RulerScale for
* x-coordinate mappings and the given ysnap for y-coords.
* If ysnap is zero, y-coords are not snapped at all.
*/
SnapGrid(RulerScale *rulerScale, int ysnap = 0);
static const timeT NoSnap;
static const timeT SnapToBar;
static const timeT SnapToBeat;
static const timeT SnapToUnit;
enum SnapDirection { SnapEither, SnapLeft, SnapRight };
/**
* Set the snap size of the grid to the given time.
* The snap time must be positive, or else one of the
* special constants NoSnap, SnapToBar, SnapToBeat or
* SnapToUnit.
* The default is SnapToBeat.
*/
void setSnapTime(timeT snap);
/**
* Return the snap size of the grid, at the given x-coordinate.
* (The x-coordinate is required in case the built-in snap size is
* SnapToBar, SnapToBeat or SnapToUnit, in which case we need to
* know the current time signature.) Returns zero for NoSnap.
*/
timeT getSnapTime(double x) const;
/**
* Return the snap setting -- the argument that was passed to
* setSnapTime. This differs from getSnapTime, which interprets
* the NoSnap, SnapToBar, SnapToBeat and SnapToUnit settings to
* return actual timeT values; instead this function returns those
* actual constants if set.
*/
timeT getSnapSetting() const;
/**
* Return the snap size of the grid, at the given time. (The time
* is required in case the built-in snap size is SnapToBar,
* SnapToBeat or SnapToUnit, in which case we need to know the
* current time signature.) Returns zero for NoSnap.
*/
timeT getSnapTime(timeT t) const;
/**
* Snap a given x-coordinate to the nearest time on the grid. Of
* course this also does x-to-time conversion, so it's useful even
* in NoSnap mode. If the snap time is greater than the bar
* duration at this point, the bar duration will be used instead.
*
* If d is SnapLeft or SnapRight, a time to the left or right
* respectively of the given coordinate will be returned;
* otherwise the nearest time on either side will be returned.
*/
timeT snapX(double x, SnapDirection d = SnapEither) const;
/**
* Snap a given time to the nearest time on the grid. Unlike
* snapX, this is not useful in NoSnap mode. If the snap time is
* greater than the bar duration at this point, the bar duration
* will be used instead.
*
* If d is SnapLeft or SnapRight, a time to the left or right
* respectively of the given coordinate will be returned;
* otherwise the nearest time on either side will be returned.
*/
timeT snapTime(timeT t, SnapDirection d = SnapEither) const;
/**
* Snap a given y-coordinate to the nearest lower bin coordinate.
*/
int snapY(int y) const {
if (m_ysnap == 0) return y;
return getYBinCoordinate(getYBin(y));
}
/**
* Return the bin number for the given y-coordinate.
*/
int getYBin(int y) const;
/**
* Return the y-coordinate of the grid line at the start of the
* given bin.
*/
int getYBinCoordinate(int bin) const;
/**
* Set the default vertical step. This is used as the height for
* bins that have no specific height multiple set, and the base
* height for bins that have a multiple. Setting the Y snap here
* is equivalent to specifying it in the constructor.
*/
void setYSnap(int ysnap) {
m_ysnap = ysnap;
}
/**
* Retrieve the default vertical step.
*/
int getYSnap() const {
return m_ysnap;
}
/**
* Set the height multiple for a specific bin. The bin will be
* multiple * ysnap high. The default is 1 for all bins.
*/
void setBinHeightMultiple(int bin, int multiple) {
m_ymultiple[bin] = multiple;
}
/**
* Retrieve the height multiple for a bin.
*/
int getBinHeightMultiple(int bin) {
if (m_ymultiple.find(bin) == m_ymultiple.end()) return 1;
return m_ymultiple[bin];
}
RulerScale *getRulerScale() {
return m_rulerScale;
}
const RulerScale *getRulerScale() const {
return m_rulerScale;
}
protected:
RulerScale *m_rulerScale; // I don't own this
timeT m_snapTime;
int m_ysnap;
std::map<int, int> m_ymultiple;
};
}
#endif