summaryrefslogtreecommitdiffstats
path: root/src/base/SnapGrid.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/SnapGrid.h')
-rw-r--r--src/base/SnapGrid.h183
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