MuseScore/libmscore/tremolobar.cpp
2017-12-13 15:50:04 +01:00

274 lines
8.3 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2010-2011 Werner Schweer
//
// 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 and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "tremolobar.h"
#include "score.h"
#include "undo.h"
#include "staff.h"
#include "chord.h"
#include "note.h"
#include "xml.h"
namespace Ms {
//---------------------------------------------------------
// TremoloBar
//---------------------------------------------------------
TremoloBar::TremoloBar(Score* s)
: Element(s)
{
setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE | ElementFlag::ON_STAFF);
setLineWidth(score()->styleS(StyleIdx::tremoloBarLineWidth));
lineWidthStyle = PropertyFlags::STYLED;
}
//---------------------------------------------------------
// layout
//---------------------------------------------------------
void TremoloBar::layout()
{
qreal _spatium = spatium();
if (parent())
setPos(0.0, -_spatium * 3.0);
else
setPos(QPointF());
/* we place the tremolo bars starting slightly before the
* notehead, and end it slightly after, drawing above the
* note. The values specified in Guitar Pro are very large, too
* large for the scale used in Musescore. We used the
* timeFactor and pitchFactor below to reduce these values down
* consistently to values that make sense to draw with the
* Musescore scale. */
qreal timeFactor = _userMag / 1.0;
qreal pitchFactor = -_spatium * .02;
polygon.clear();
for (auto v : _points)
polygon << QPointF(v.time * timeFactor, v.pitch * pitchFactor);
qreal w = _lw.val() * _spatium;
setbbox(polygon.boundingRect().adjusted(-w, -w, w, w));
}
//---------------------------------------------------------
// draw
//---------------------------------------------------------
void TremoloBar::draw(QPainter* painter) const
{
QPen pen(curColor(), _lw.val() * spatium(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
painter->drawPolyline(polygon);
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
void TremoloBar::write(XmlWriter& xml) const
{
xml.stag("TremoloBar");
writeProperty(xml, P_ID::MAG);
writeProperty(xml, P_ID::LINE_WIDTH);
writeProperty(xml, P_ID::PLAY);
for (const PitchValue& v : _points) {
xml.tagE(QString("point time=\"%1\" pitch=\"%2\" vibrato=\"%3\"")
.arg(v.time).arg(v.pitch).arg(v.vibrato));
}
xml.etag();
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
void TremoloBar::read(XmlReader& e)
{
while (e.readNextStartElement()) {
auto tag = e.name();
if (tag == "point") {
PitchValue pv;
pv.time = e.intAttribute("time");
pv.pitch = e.intAttribute("pitch");
pv.vibrato = e.intAttribute("vibrato");
_points.append(pv);
e.readNext();
}
else if (tag == "mag")
_userMag = e.readDouble(0.1, 10.0);
else if (tag == "lineWidth")
setLineWidth(Spatium(e.readDouble()));
else if (tag == "play")
setPlay(e.readInt());
else
e.unknown();
}
}
//---------------------------------------------------------
// undoSetUserMag
//---------------------------------------------------------
void TremoloBar::undoSetUserMag(qreal val)
{
undoChangeProperty(P_ID::MAG, val);
}
//---------------------------------------------------------
// undoSetLineWidth
//---------------------------------------------------------
void TremoloBar::undoSetLineWidth(Spatium val)
{
undoChangeProperty(P_ID::LINE_WIDTH, val);
}
//---------------------------------------------------------
// undoSetPlay
//---------------------------------------------------------
void TremoloBar::undoSetPlay(bool val)
{
undoChangeProperty(P_ID::PLAY, val);
}
//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
QVariant TremoloBar::getProperty(P_ID propertyId) const
{
switch (propertyId) {
case P_ID::LINE_WIDTH:
return lineWidth();
case P_ID::MAG:
return userMag();
case P_ID::PLAY:
return play();
default:
return Element::getProperty(propertyId);
}
}
//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
QVariant TremoloBar::propertyDefault(P_ID propertyId) const
{
switch (propertyId) {
case P_ID::LINE_WIDTH:
return score()->styleV(StyleIdx::voltaLineWidth);
case P_ID::MAG:
return 1.0;
case P_ID::PLAY:
return true;
default:
return Element::propertyDefault(propertyId);
}
}
//---------------------------------------------------------
// setProperty
//---------------------------------------------------------
bool TremoloBar::setProperty(P_ID propertyId, const QVariant& v)
{
switch (propertyId) {
case P_ID::LINE_WIDTH:
lineWidthStyle = PropertyFlags::UNSTYLED;
setLineWidth(v.value<Spatium>());
break;
case P_ID::MAG:
setUserMag(v.toDouble());
break;
case P_ID::PLAY:
setPlay(v.toBool());
score()->setPlaylistDirty();
break;
default:
return Element::setProperty(propertyId, v);
}
score()->setLayoutAll();
return true;
}
//---------------------------------------------------------
// propertyStyle
//---------------------------------------------------------
PropertyFlags& TremoloBar::propertyFlags(P_ID id)
{
switch (id) {
case P_ID::LINE_WIDTH:
return lineWidthStyle;
default:
return Element::propertyFlags(id);
}
}
//---------------------------------------------------------
// resetProperty
//---------------------------------------------------------
void TremoloBar::resetProperty(P_ID id)
{
switch (id) {
case P_ID::LINE_WIDTH:
setProperty(id, propertyDefault(id));
lineWidthStyle = PropertyFlags::STYLED;
break;
default:
return Element::resetProperty(id);
}
}
//---------------------------------------------------------
// styleChanged
// reset all styled values to actual style
//---------------------------------------------------------
void TremoloBar::styleChanged()
{
if (lineWidthStyle == PropertyFlags::STYLED)
setLineWidth(score()->styleS(StyleIdx::voltaLineWidth));
}
//---------------------------------------------------------
// reset
//---------------------------------------------------------
void TremoloBar::reset()
{
if (lineWidthStyle == PropertyFlags::UNSTYLED)
undoChangeProperty(P_ID::LINE_WIDTH, propertyDefault(P_ID::LINE_WIDTH), PropertyFlags::STYLED);
Element::reset();
}
//---------------------------------------------------------
// spatiumChanged
//---------------------------------------------------------
void TremoloBar::spatiumChanged(qreal oldValue, qreal newValue)
{
_lw *= (newValue / oldValue);
Element::spatiumChanged(oldValue, newValue);
}
}