summaryrefslogtreecommitdiff
path: root/muse2/muse/widgets/drange.cpp
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2010-10-13 19:34:22 +0000
committerRobert Jonsson <spamatica@gmail.com>2010-10-13 19:34:22 +0000
commit8a2c2824a59d7644e13bc52c9a0ecbd641f21f95 (patch)
tree064ad3f2bf8daab0ad27b128abd86a9bbdb1e496 /muse2/muse/widgets/drange.cpp
parenta27706d9629e8b592cca4659f865b70adef24e6d (diff)
new branch muse2, first checkin
Diffstat (limited to 'muse2/muse/widgets/drange.cpp')
-rw-r--r--muse2/muse/widgets/drange.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/muse2/muse/widgets/drange.cpp b/muse2/muse/widgets/drange.cpp
new file mode 100644
index 00000000..5c986403
--- /dev/null
+++ b/muse2/muse/widgets/drange.cpp
@@ -0,0 +1,262 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: drange.cpp,v 1.2.2.1 2009/03/09 02:05:18 terminator356 Exp $
+//
+// Copyright (C) 1997 Josef Wilgen
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2,
+// as published by the Free Software Foundation.
+//
+// (C) Copyright 2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <cmath>
+#include "mmath.h"
+#include "drange.h"
+
+const double DoubleRange::MinRelStep = 1.0e-10;
+const double DoubleRange::DefaultRelStep = 1.0e-2;
+const double DoubleRange::MinEps = 1.0e-10;
+
+//-----------------------------------------------------------
+// This class is useful as a base class or a member for sliders.
+// It represents an interval of type double within which a value can
+// be moved. The value can be either an arbitrary point inside
+// the interval (see @DoubleRange::setValue@), or it can be fitted
+// into a step raster (see @DoubleRange::fitValue@ and
+// @DoubleRange::incValue@).
+//
+// As a special case, a DoubleRange can be periodic, which means that
+// a value outside the interval will be mapped to a value inside the
+// interval when @DoubleRange::setValue@, @DoubleRange::fitValue@,
+// @DoubleRange::incValue@ or @DoubleRange::incPages@ are called.
+//------------------------------------------------------------
+
+//---------------------------------------------------------
+// doubleRange
+//---------------------------------------------------------
+
+DoubleRange::DoubleRange()
+ {
+ d_minValue = 0;
+ d_maxValue = 100.0;
+ d_prevValue = 0.0;
+ d_exactPrevValue = 0.0;
+ d_exactValue = 0.0;
+ d_value = 0.0;
+ d_step = 0.1;
+ d_periodic = FALSE;
+ }
+
+//---------------------------------------------------------
+// setNewValue
+//---------------------------------------------------------
+
+void DoubleRange::setNewValue(double x, bool align)
+ {
+ d_prevValue = d_value;
+
+ double vmin = qwtMin(d_minValue, d_maxValue);
+ double vmax = qwtMax(d_minValue, d_maxValue);
+
+ // Range check
+
+ if (x < vmin) {
+ if ((d_periodic) && (vmin != vmax))
+ d_value = x + ceil((vmin - x) / (vmax - vmin))
+ * (vmax - vmin);
+ else
+ d_value = vmin;
+ }
+ else if (x > vmax) {
+ if ((d_periodic) && (vmin != vmax))
+ d_value = x - ceil( ( x - vmax) / (vmax - vmin ))
+ * (vmax - vmin);
+ else
+ d_value = vmax;
+ }
+ else
+ d_value = x;
+
+ d_exactPrevValue = d_exactValue;
+ d_exactValue = d_value;
+
+ // align to grid
+ if (align) {
+ if (d_step != 0.0)
+ d_value = d_minValue + rint((d_value - d_minValue) / d_step ) * d_step;
+ else
+ d_value = d_minValue;
+
+ // correct rounding error at the border
+ if (fabs(d_value - d_maxValue) < MinEps * qwtAbs(d_step))
+ d_value = d_maxValue;
+
+ // correct rounding error if value = 0
+ if (fabs(d_value) < MinEps * qwtAbs(d_step))
+ d_value = 0.0;
+ }
+ if (d_prevValue != d_value)
+ valueChange();
+ }
+
+//---------------------------------------------------------
+// fitValue
+// Adjust the value to the closest point in the step
+// raster.
+// The value is clipped when it lies outside the range.
+// When the range is @DoubleRange::periodic@, it will
+// be mapped to a point in the interval such that
+//---------------------------------------------------------
+
+void DoubleRange::fitValue(double x)
+ {
+ setNewValue(x, true);
+ }
+
+//---------------------------------------------------------
+// setValue
+// Set a new value without adjusting to the step raster
+// The value is clipped when it lies outside the range.
+// When the range is @DoubleRange::periodic@, it will
+// be mapped to a point in the interval such that
+//
+// new value := x + n * (max. value - min. value)
+//
+// with an integer number n.
+//---------------------------------------------------------
+
+void DoubleRange::setValue(double x)
+ {
+ setNewValue(x, false);
+ }
+
+//---------------------------------------------------------
+// setRange
+// Specify range and step size
+// - A change of the range changes the value if it lies outside the
+// new range. The current value
+// will *not* be adjusted to the new step raster.
+// - vmax < vmin is allowed.
+// - If the step size is left out or set to zero, it will be
+// set to 1/100 of the interval length.
+// - If the step size has an absurd value, it will be corrected
+// to a better one.
+//---------------------------------------------------------
+
+void DoubleRange::setRange(double vmin, double vmax, double vstep, int pageSize)
+ {
+ bool rchg = ((d_maxValue != vmax) || (d_minValue != vmin));
+
+ if (rchg) {
+ d_minValue = vmin;
+ d_maxValue = vmax;
+ }
+
+ //
+ // look if the step width has an acceptable
+ // value or otherwise change it.
+ //
+ setStep(vstep);
+
+ //
+ // limit page size
+ //
+ d_pageSize = qwtLim(pageSize,0, int(qwtAbs((d_maxValue - d_minValue) / d_step)));
+
+ //
+ // If the value lies out of the range, it
+ // will be changed. Note that it will not be adjusted to
+ // the new step width.
+ setNewValue(d_value, false);
+
+ // call notifier after the step width has been
+ // adjusted.
+ if (rchg)
+ rangeChange();
+ }
+
+//---------------------------------------------------------
+// setStep
+// Change the step raster
+//
+// The value will *not* be adjusted to the new step raster.
+//---------------------------------------------------------
+
+void DoubleRange::setStep(double vstep)
+ {
+ double newStep,intv;
+
+ intv = d_maxValue - d_minValue;
+
+ if (vstep == 0.0)
+ newStep = intv * DefaultRelStep;
+ else {
+ if (((intv > 0) && (vstep < 0)) || ((intv < 0) && (vstep > 0)))
+ newStep = -vstep;
+ else
+ newStep = vstep;
+
+ if ( fabs(newStep) < fabs(MinRelStep * intv) )
+ newStep = MinRelStep * intv;
+ }
+
+ if (newStep != d_step) {
+ d_step = newStep;
+ stepChange();
+ }
+ }
+
+//---------------------------------------------------------
+// setPeriodic
+// Make the range periodic
+//
+// When the range is periodic, the value will be set to a point
+// inside the interval such that
+//
+// point = value + n * width
+//
+// if the user tries to set a new value which is outside the range.
+// If the range is nonperiodic (the default), values outside the
+// range will be clipped.
+//---------------------------------------------------------
+
+void DoubleRange::setPeriodic(bool tf)
+ {
+ d_periodic = tf;
+ }
+
+//------------------------------------------------------------
+// incValue
+// Increment the value by a specified number of steps
+//
+// As a result of this operation, the new value will always be
+// adjusted to the step raster.
+//------------------------------------------------------------
+
+void DoubleRange::incValue(int nSteps)
+ {
+ setNewValue(d_value + double(nSteps) * d_step, true);
+ }
+
+//---------------------------------------------------------
+// incPages
+// Increment the value by a specified number of pages
+//---------------------------------------------------------
+
+void DoubleRange::incPages(int nPages)
+ {
+ setNewValue(d_value + double(nPages) * double(d_pageSize)
+ * d_step, true);
+ }
+
+//---------------------------------------------------------
+// step
+//---------------------------------------------------------
+
+double DoubleRange::step() const
+ {
+ return qwtAbs(d_step);
+ }
+