//====================================================================== // MusE // Linux Music Editor // knob_and_meter.cpp // (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) // // 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; version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //========================================================= #include #include "knob_and_meter.h" #include #include "mmath.h" #include #include #include #include #include namespace MusEGui { //--------------------------------------------------------- // The QwtKnob widget imitates look and behaviour of a volume knob on a radio. // It contains // a scale around the knob which is set up automatically or can // be configured manually (see @^QwtScaleIf@). // Automatic scrolling is enabled when the user presses a mouse // button on the scale. For a description of signals, slots and other // members, see QwtSliderBase@. //--------------------------------------------------------- //--------------------------------------------------------- // KnobWithMeter //--------------------------------------------------------- KnobWithMeter::KnobWithMeter(QWidget* parent, const char* name) : Knob(parent, name) { // hasScale = false; // // d_borderWidth = 4; // d_shineWidth = 3; // d_totalAngle = 270.0; // d_scaleDist = 1; // d_symbol = Line; // d_maxScaleTicks = 11; // d_knobWidth = 30; // _faceColSel = FALSE; // d_faceColor = palette().color(QPalette::Window); // d_rimColor = palette().mid().color(); // d_shinyColor = palette().mid().color(); // d_curFaceColor = d_faceColor; // d_altFaceColor = d_faceColor; // d_markerColor = palette().dark().color().darker(125); // d_dotWidth = 8; // // l_slope = 0; // l_const = 100; // // setMinimumSize(30,30); // setUpdateTime(50); } //------------------------------------------------------------ // QwtKnob::setTotalAngle // Set the total angle by which the knob can be turned // // Syntax // void QwtKnob::setTotalAngle(double angle) // // Parameters // double angle -- angle in degrees. // // Description // The default angle is 270 degrees. It is possible to specify // an angle of more than 360 degrees so that the knob can be // turned several times around its axis. //------------------------------------------------------------ // void Knob::setTotalAngle (double angle) // { // if (angle < 10.0) // d_totalAngle = 10.0; // else // d_totalAngle = angle; // d_scale.setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle); // } // //------------------------------------------------------------ // Knob::setRange // Set the range and step size of the knob // // Sets the paramaters that define the shininess of the ring // surrounding the knob and then proceeds by passing the // parameters to the parent class' setRange() function. //------------------------------------------------------------ // void Knob::setRange(double vmin, double vmax, double vstep, int pagesize) // { // //if(vmin == d_minValue && vmax == d_maxValue && vstep == d_step && pageSize == d_pageSize) // p4.0.45 // // return; // // // divide by zero protection. probably too cautious // if (! (vmin == vmax || qMax(-vmin, vmax) == 0)) // { // if (vmin * vmax < 0) // l_slope = 80.0 / qMax(-vmin, vmax); // else // { // l_slope = 80.0 / (vmax - vmin); // l_const = 100 - l_slope * vmin; // } // } // SliderBase::setRange(vmin, vmax, vstep, pagesize); // } // //------------------------------------------------------------ // QwtKnob::drawKnob // const QRect &r -- borders of the knob //------------------------------------------------------------ void KnobWithMeter::drawKnob(QPainter* p, const QRect& r) { const QPalette& pal = palette(); QRect aRect; aRect.setRect(kRect.x() + d_borderWidth, kRect.y() + d_borderWidth, kRect.width() - 2*d_borderWidth, kRect.height() - 2*d_borderWidth); int width = kRect.width(); int height = kRect.height(); int size = qMin(width, height); p->setRenderHint(QPainter::Antialiasing, true); QPainterPath drawingPath, updatePath, finalPath, cornerPath; // // draw the rim // QLinearGradient linearg(QPoint(r.x(),r.y()), QPoint(size, size)); linearg.setColorAt(1 - M_PI_4, d_faceColor.lighter(125)); linearg.setColorAt(M_PI_4, d_faceColor.darker(175)); p->setBrush(linearg); p->setPen(Qt::NoPen); p->drawEllipse(r.x(),r.y(),size,size); // // draw shiny surrounding // QPen pn; pn.setCapStyle(Qt::FlatCap); pn.setColor(d_shinyColor.lighter(l_const + abs(value() * l_slope))); pn.setWidth(d_shineWidth * 2); p->setPen(pn); p->drawArc(aRect, 0, 360 * 16); // // draw button face // QRadialGradient gradient(size/2, size/2, size-d_borderWidth, size/2-d_borderWidth, size/2-d_borderWidth); gradient.setColorAt(0, d_curFaceColor.lighter(150)); gradient.setColorAt(1, d_curFaceColor.darker(150)); p->setBrush(gradient); p->setPen(Qt::NoPen); p->drawEllipse(aRect); // // draw marker // //drawMarker(p, d_angle, isEnabled() ? d_markerColor : Qt::gray); drawMarker(p, d_angle, pal.currentColorGroup() == QPalette::Disabled ? pal.color(QPalette::Disabled, QPalette::WindowText) : d_markerColor); } //------------------------------------------------------------ //.F QwtSliderBase::valueChange // Notify change of value // //.u Parameters // double x -- new value // //.u Description // Sets the slider's value to the nearest multiple // of the step size. //------------------------------------------------------------ // void Knob::valueChange() // { // recalcAngle(); // d_newVal++; // repaint(kRect); // SliderBase::valueChange(); // } // //------------------------------------------------------------ //.F QwtKnob::getValue // Determine the value corresponding to a specified position // //.u Parameters: // const QPoint &p -- point // //.u Description: // Called by QwtSliderBase //------------------------------------------------------------ // double Knob::getValue(const QPoint &p) // { // double newValue; // double oneTurn; // double eqValue; // double arc; // // const QRect& r = rect(); // // double dx = double((r.x() + r.width() / 2) - p.x() ); // double dy = double((r.y() + r.height() / 2) - p.y() ); // // arc = atan2(-dx,dy) * 180.0 / M_PI; // // newValue = 0.5 * (minValue() + maxValue()) // + (arc + d_nTurns * 360.0) * (maxValue() - minValue()) // / d_totalAngle; // // oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_totalAngle; // eqValue = value() + d_mouseOffset; // // if (fabs(newValue - eqValue) > 0.5 * oneTurn) // { // if (newValue < eqValue) // newValue += oneTurn; // else // newValue -= oneTurn; // } // // return newValue; // // } // //------------------------------------------------------------ //.- //.F QwtKnob::setScrollMode // Determine the scrolling mode and direction // corresponding to a specified position // //.u Parameters // const QPoint &p -- point in question // //.u Description // Called by QwtSliderBase //------------------------------------------------------------ // void Knob::getScrollMode( QPoint &p, const Qt::MouseButton &/*button*/, int &scrollMode, int &direction)// prevent compiler warning : unsused parameter // { // int dx, dy, r; // double arc; // // /*Qt::ButtonState but= button ;*/ // prevent compiler warning : unsused variable // r = kRect.width() / 2; // // dx = kRect.x() + r - p.x(); // dy = kRect.y() + r - p.y(); // // if ( (dx * dx) + (dy * dy) <= (r * r)) // point is inside the knob // { // scrollMode = ScrMouse; // direction = 0; // } // else // point lies outside // { // scrollMode = ScrTimer; // arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI; // if ( arc < d_angle) // direction = -1; // else if (arc > d_angle) // direction = 1; // else // direction = 0; // } // return; // } // //------------------------------------------------------------ //.F QwtKnob::rangeChange // Notify a change of the range // //.u Description // Called by QwtSliderBase //------------------------------------------------------------ // void Knob::rangeChange() // { // if (!hasUserScale()) // { // d_scale.setScale(minValue(), maxValue(), // d_maxMajor, d_maxMinor); // } // recalcAngle(); // resize(size()); // repaint(); // } void KnobWithMeter::mousePressEvent(QMouseEvent *e) { // if (e->button() == Qt::MidButton || e->modifiers() & Qt::ControlModifier) { // int xpos = e->x() - width() /2; // double v = float(e->y()) / height() * 1.2; // // double halfRange = (maxValue() - minValue())/2; // double midValue = minValue() + halfRange; // // apply to range // if (xpos < 0) { // left values // v = -v; // } // setValue(v * halfRange + midValue); // SliderBase::valueChange(); // emit sliderMoved(value(),id()); // sliderMoved is used by auxChanged // // // fake a left-click to make the knob still "stick" to // // the mouse. // QMouseEvent temp(e->type(), e->pos(), Qt::LeftButton, e->buttons(), e->modifiers()); // SliderBase::mousePressEvent(&temp); // return; // } Knob::mousePressEvent(e); } //--------------------------------------------------------- // resizeEvent //--------------------------------------------------------- void KnobWithMeter::resizeEvent(QResizeEvent* ev) { Knob::resizeEvent(ev); // int width, width_2; // // const QRect& r = rect(); // // // printf("resize %d %d %d\n", r.height(), r.width(), d_knobWidth); // // // width = MusECore::qwtMin(MusECore::qwtMin(r.height(), r.width()), d_knobWidth); // width = MusECore::qwtMin(r.height(), r.width()); // width_2 = width / 2; // // int x = r.x() + r.width() / 2 - width_2; // int y = r.y() + r.height() / 2 - width_2; // // kRect.setRect(x, y, width, width); // // x = kRect.x() - d_scaleDist; // y = kRect.y() - d_scaleDist; // int w = width + 2 * d_scaleDist; // // d_scale.setGeometry(x, y, w, ScaleDraw::Round); } //------------------------------------------------------------ // paintEvent //------------------------------------------------------------ void KnobWithMeter::paintEvent(QPaintEvent* e) { /* QPainter p(this); const QRect &r = e->rect(); if ((r == kRect) && d_newVal ) { // event from valueChange() if (d_newVal > 1) // lost paintEvents()? drawKnob(&p, kRect); else { drawMarker(&p, d_oldAngle, d_curFaceColor); drawMarker(&p, d_angle, d_markerColor); } } else { p.eraseRect(rect()); if (hasScale) d_scale.draw(&p); drawKnob(&p, kRect); } d_newVal = 0; */ const QRect &r = e->rect(); QPainter p(this); p.setRenderHint(QPainter::Antialiasing, true); if(hasScale) d_scale.draw(&p); ///drawKnob(&p, kRect); drawKnob(&p, r); //drawMarker(&p, d_oldAngle, d_curFaceColor); //drawMarker(&p, d_angle, d_markerColor); d_newVal = 0; } //------------------------------------------------------------ //.- //.F QwtKnob::drawMarker // Draw the marker at the knob's front // //.u Parameters //.p QPainter *p -- painter // double arc -- angle of the marker // const QColor &c -- marker color // //.u Syntax // void QwtKnob::drawMarker(QPainter *p) // //------------------------------------------------------------ // void Knob::drawMarker(QPainter *p, double arc, const QColor &c) // { // // QPen pn; // int radius; // double rb,re; // double rarc; // // rarc = arc * M_PI / 180.0; // double ca = cos(rarc); // double sa = - sin(rarc); // // radius = kRect.width() / 2 - d_borderWidth + d_shineWidth; // if (radius < 3) radius = 3; // int ym = kRect.y() + radius + d_borderWidth - d_shineWidth; // int xm = kRect.x() + radius + d_borderWidth - d_shineWidth; // // switch (d_symbol) // { // case Dot: // // p->setBrush(c); // p->setPen(Qt::NoPen); // rb = double(MusECore::qwtMax(radius - 4 - d_dotWidth / 2, 0)); // p->drawEllipse(xm - int(rint(sa * rb)) - d_dotWidth / 2, // ym - int(rint(ca * rb)) - d_dotWidth / 2, // d_dotWidth, d_dotWidth); // // break; // // case Line: // // pn.setColor(c); // pn.setWidth(2); // p->setPen(pn); // // rb = MusECore::qwtMax(double((radius - 1) / 3.0), 0.0); // re = MusECore::qwtMax(double(radius - 1), 0.0); // // p->setRenderHint(QPainter::Antialiasing, true); // p->drawLine( xm, // ym, // xm - int(rint(sa * re)), // ym - int(rint(ca * re))); // // break; // } // // // } // //------------------------------------------------------------ // //.F QwtKnob::setKnobWidth // Change the knob's width. // //.u Syntax //.f void QwtKnob::setKnobWidth(int w) // //.u Parameters //.p int w -- new width // //.u Description // The specified width must be >= 5, or it will be clipped. // //------------------------------------------------------------ // void Knob::setKnobWidth(int w) // { // d_knobWidth = MusECore::qwtMax(w,5); // resize(size()); // repaint(); // } // //------------------------------------------------------------ // //.F QwtKnob::setBorderWidth // Set the knob's border width // //.u Syntax //.f void QwtKnob::setBorderWidth(int bw) // //.u Parameters //.p int bw -- new border width // //------------------------------------------------------------ // void Knob::setBorderWidth(int bw) // { // d_borderWidth = MusECore::qwtMax(bw, 0); // resize(size()); // repaint(); // } //------------------------------------------------------------ //.- //.F QwtKnob::recalcAngle // Recalculate the marker angle corresponding to the // current value // //.u Syntax //.f void QwtKnob::recalcAngle() // //------------------------------------------------------------ // void Knob::recalcAngle() // { // d_oldAngle = d_angle; // // // // // calculate the angle corresponding to the value // // // if (maxValue() == minValue()) // { // d_angle = 0; // d_nTurns = 0; // } // else // { // d_angle = (value() - 0.5 * (minValue() + maxValue())) // / (maxValue() - minValue()) * d_totalAngle; // d_nTurns = floor((d_angle + 180.0) / 360.0); // d_angle = d_angle - d_nTurns * 360.0; // // } // // } // //------------------------------------------------------------ // setFaceColor //------------------------------------------------------------ // void Knob::setFaceColor(const QColor c) // { // d_faceColor = c; // if(!_faceColSel) // //update(FALSE); // repaint(); // } //------------------------------------------------------------ // setAltFaceColor //------------------------------------------------------------ // void Knob::setAltFaceColor(const QColor c) // { // d_altFaceColor = c; // if(_faceColSel) // //update(FALSE); // repaint(); // } //------------------------------------------------------------ // selectFaceColor //------------------------------------------------------------ // void Knob::selectFaceColor(bool alt) // { // _faceColSel = alt; // if(alt) // d_curFaceColor = d_altFaceColor; // else // d_curFaceColor = d_faceColor; // //update(FALSE); // repaint(); // } //------------------------------------------------------------ // setMarkerColor //------------------------------------------------------------ // void Knob::setMarkerColor(const QColor c) // { // d_markerColor = c; // //update(FALSE); // repaint(); // } } // namespace MusEGui