MuseScore/libmscore/tremolobar.cpp

196 lines
6 KiB
C++
Raw Normal View History

2012-05-26 14:26:10 +02:00
//=============================================================================
// 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"
2014-04-09 16:09:21 +02:00
#include "xml.h"
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2018-08-01 11:46:07 +02:00
//---------------------------------------------------------
// tremoloBarStyle
//---------------------------------------------------------
static const ElementStyle tremoloBarStyle {
{ Sid::tremoloBarLineWidth, Pid::LINE_WIDTH },
};
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// TremoloBar
//---------------------------------------------------------
TremoloBar::TremoloBar(Score* s)
: Element(s, ElementFlag::MOVABLE | ElementFlag::ON_STAFF)
2012-05-26 14:26:10 +02:00
{
2018-08-01 11:46:07 +02:00
initElementStyle(&tremoloBarStyle);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// layout
//---------------------------------------------------------
void TremoloBar::layout()
{
qreal _spatium = spatium();
if (parent())
setPos(0.0, -_spatium * 3.0);
else
setPos(QPointF());
2016-09-20 14:44:43 +02:00
/* 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. */
2016-09-20 17:13:54 +02:00
qreal timeFactor = _userMag / 1.0;
qreal pitchFactor = -_spatium * .02;
2016-09-20 14:44:43 +02:00
2016-09-20 17:13:54 +02:00
polygon.clear();
2016-09-20 14:44:43 +02:00
for (auto v : _points)
2016-09-20 17:13:54 +02:00
polygon << QPointF(v.time * timeFactor, v.pitch * pitchFactor);
2016-09-20 14:44:43 +02:00
qreal w = _lw.val();
2016-09-20 17:13:54 +02:00
setbbox(polygon.boundingRect().adjusted(-w, -w, w, w));
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// draw
//---------------------------------------------------------
void TremoloBar::draw(QPainter* painter) const
{
QPen pen(curColor(), _lw.val(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
2012-05-26 14:26:10 +02:00
painter->setPen(pen);
2016-09-20 17:13:54 +02:00
painter->drawPolyline(polygon);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
2016-11-19 11:51:21 +01:00
void TremoloBar::write(XmlWriter& xml) const
2012-05-26 14:26:10 +02:00
{
xml.stag(this);
2018-03-27 15:36:00 +02:00
writeProperty(xml, Pid::MAG);
writeProperty(xml, Pid::LINE_WIDTH);
writeProperty(xml, Pid::PLAY);
for (const PitchValue& v : _points) {
2012-05-26 14:26:10 +02:00
xml.tagE(QString("point time=\"%1\" pitch=\"%2\" vibrato=\"%3\"")
.arg(v.time).arg(v.pitch).arg(v.vibrato));
}
xml.etag();
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
2013-01-11 18:10:18 +01:00
void TremoloBar::read(XmlReader& e)
2012-05-26 14:26:10 +02:00
{
2013-01-11 18:10:18 +01:00
while (e.readNextStartElement()) {
2016-09-20 17:13:54 +02:00
auto tag = e.name();
if (tag == "point") {
2012-05-26 14:26:10 +02:00
PitchValue pv;
2013-01-11 18:10:18 +01:00
pv.time = e.intAttribute("time");
pv.pitch = e.intAttribute("pitch");
pv.vibrato = e.intAttribute("vibrato");
2012-05-26 14:26:10 +02:00
_points.append(pv);
e.readNext();
2012-05-26 14:26:10 +02:00
}
2016-09-20 17:13:54 +02:00
else if (tag == "mag")
_userMag = e.readDouble(0.1, 10.0);
2018-04-12 12:58:26 +02:00
else if (readStyledProperty(e, tag))
;
2016-09-20 17:13:54 +02:00
else if (tag == "play")
setPlay(e.readInt());
2018-08-01 11:46:07 +02:00
else if (readProperty(tag, e, Pid::LINE_WIDTH))
;
2012-05-26 14:26:10 +02:00
else
2013-01-11 18:10:18 +01:00
e.unknown();
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
2018-03-27 15:36:00 +02:00
QVariant TremoloBar::getProperty(Pid propertyId) const
{
switch (propertyId) {
2018-03-27 15:36:00 +02:00
case Pid::LINE_WIDTH:
2016-09-20 17:13:54 +02:00
return lineWidth();
2018-03-27 15:36:00 +02:00
case Pid::MAG:
2016-09-20 17:13:54 +02:00
return userMag();
2018-03-27 15:36:00 +02:00
case Pid::PLAY:
2016-09-20 17:13:54 +02:00
return play();
default:
return Element::getProperty(propertyId);
}
}
//---------------------------------------------------------
// setProperty
//---------------------------------------------------------
2018-03-27 15:36:00 +02:00
bool TremoloBar::setProperty(Pid propertyId, const QVariant& v)
{
switch (propertyId) {
2018-03-27 15:36:00 +02:00
case Pid::LINE_WIDTH:
2016-09-20 17:13:54 +02:00
setLineWidth(v.value<Spatium>());
break;
2018-03-27 15:36:00 +02:00
case Pid::MAG:
setUserMag(v.toDouble());
break;
2018-03-27 15:36:00 +02:00
case Pid::PLAY:
2016-09-20 17:13:54 +02:00
setPlay(v.toBool());
score()->setPlaylistDirty();
break;
default:
return Element::setProperty(propertyId, v);
}
2018-04-12 12:58:26 +02:00
triggerLayout();
return true;
}
2016-09-20 17:13:54 +02:00
//---------------------------------------------------------
2018-04-12 12:58:26 +02:00
// propertyDefault
2016-09-20 17:13:54 +02:00
//---------------------------------------------------------
2018-08-01 11:46:07 +02:00
QVariant TremoloBar::propertyDefault(Pid pid) const
2016-09-20 17:13:54 +02:00
{
2018-08-01 11:46:07 +02:00
switch (pid) {
2018-04-12 12:58:26 +02:00
case Pid::MAG:
return 1.0;
case Pid::PLAY:
return true;
2016-09-20 17:13:54 +02:00
default:
2018-08-01 11:46:07 +02:00
for (const StyledProperty& p : *styledProperties()) {
if (p.pid == pid) {
if (propertyType(pid) == P_TYPE::SP_REAL)
return score()->styleP(p.sid);
return score()->styleV(p.sid);
}
}
return Element::propertyDefault(pid);
2016-09-20 17:13:54 +02:00
}
}
2013-05-13 18:49:17 +02:00
}