diff options
Diffstat (limited to 'src/base/SnapGrid.h')
-rw-r--r-- | src/base/SnapGrid.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/base/SnapGrid.h b/src/base/SnapGrid.h new file mode 100644 index 0000000..e0c9ec5 --- /dev/null +++ b/src/base/SnapGrid.h @@ -0,0 +1,183 @@ +// -*- 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. +*/ + +#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 |