MuseScore/libmscore/bracket.cpp

406 lines
14 KiB
C++
Raw Normal View History

2012-05-26 14:26:10 +02:00
//=============================================================================
// MuseScore
// Music Composition & Notation
//
2013-09-09 22:22:55 +02:00
// Copyright (C) 2002-2013 Werner Schweer
2012-05-26 14:26:10 +02:00
//
// 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 "bracket.h"
#include "xml.h"
#include "style.h"
#include "utils.h"
#include "staff.h"
#include "score.h"
#include "system.h"
#include "sym.h"
#include "mscore.h"
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// Bracket
//---------------------------------------------------------
Bracket::Bracket(Score* s)
: Element(s)
{
2013-06-27 11:02:42 +02:00
_bracketType = BRACKET_BRACE;
h2 = 3.5 * spatium();
_column = 0;
_span = 0;
_firstStaff = 0;
_lastStaff = 0;
2012-05-26 14:26:10 +02:00
setGenerated(true); // brackets are not saved
}
//---------------------------------------------------------
// setHeight
//---------------------------------------------------------
void Bracket::setHeight(qreal h)
{
h2 = h * .5;
}
//---------------------------------------------------------
// width
//---------------------------------------------------------
qreal Bracket::width() const
{
2013-09-09 22:22:55 +02:00
qreal w = 0;
if (bracketType() == BRACKET_BRACE)
2012-05-26 14:26:10 +02:00
w = point(score()->styleS(ST_akkoladeWidth) + score()->styleS(ST_akkoladeBarDistance));
else if (bracketType() == BRACKET_NORMAL)
2012-05-26 14:26:10 +02:00
w = point(score()->styleS(ST_bracketWidth) + score()->styleS(ST_bracketDistance));
else if (bracketType() == BRACKET_SQUARE)
w = point(score()->styleS(ST_staffLineWidth) + Spatium(0.5));
2013-09-09 22:22:55 +02:00
else if (bracketType() == BRACKET_LINE)
2013-10-29 22:56:13 +01:00
w = point(0.67f * score()->styleS(ST_bracketWidth) + score()->styleS(ST_bracketDistance));
2012-05-26 14:26:10 +02:00
return w;
}
//---------------------------------------------------------
// layout
//---------------------------------------------------------
void Bracket::layout()
{
path = QPainterPath();
if (h2 == 0.0)
return;
if (bracketType() == BRACKET_BRACE) {
2012-05-26 14:26:10 +02:00
qreal w = point(score()->styleS(ST_akkoladeWidth));
#define XM(a) (a+700)*w/700
#define YM(a) (a+7100)*h2/7100
path.moveTo( XM( -8), YM(-2048));
path.cubicTo(XM( -8), YM(-3192), XM(-360), YM(-4304), XM( -360), YM(-5400)); // c 0
path.cubicTo(XM( -360), YM(-5952), XM(-264), YM(-6488), XM( 32), YM(-6968)); // c 1
path.cubicTo(XM( 40), YM(-6976), XM( 40), YM(-6976), XM( 40), YM(-6984)); // c 0
path.cubicTo(XM( 40), YM(-7000), XM( 16), YM(-7024), XM( 0), YM(-7024)); // c 0
path.cubicTo(XM( -8), YM(-7024), XM( -24), YM(-7024), XM( -32), YM(-7008)); // c 1
path.cubicTo(XM( -416), YM(-6392), XM(-544), YM(-5680), XM( -544), YM(-4960)); // c 0
path.cubicTo(XM( -544), YM(-3800), XM(-168), YM(-2680), XM( -168), YM(-1568)); // c 0
path.cubicTo(XM( -168), YM(-1016), XM(-264), YM( -496), XM( -560), YM( -16)); // c 1
path.lineTo( XM( -560), YM( 0)); // l 1
path.lineTo( XM( -560), YM( 16)); // l 1
path.cubicTo(XM( -264), YM( 496), XM(-168), YM( 1016), XM( -168), YM( 1568)); // c 0
path.cubicTo(XM( -168), YM( 2680), XM(-544), YM( 3800), XM( -544), YM( 4960)); // c 0
path.cubicTo(XM( -544), YM( 5680), XM(-416), YM( 6392), XM( -32), YM( 7008)); // c 1
path.cubicTo(XM( -24), YM( 7024), XM( -8), YM( 7024), XM( 0), YM( 7024)); // c 0
path.cubicTo(XM( 16), YM( 7024), XM( 40), YM( 7000), XM( 40), YM( 6984)); // c 0
path.cubicTo(XM( 40), YM( 6976), XM( 40), YM( 6976), XM( 32), YM( 6968)); // c 1
path.cubicTo(XM( -264), YM( 6488), XM(-360), YM( 5952), XM( -360), YM( 5400)); // c 0
path.cubicTo(XM( -360), YM( 4304), XM( -8), YM( 3192), XM( -8), YM( 2048)); // c 0
path.cubicTo(XM( - 8), YM( 1320), XM(-136), YM( 624), XM( -512), YM( 0)); // c 1
path.cubicTo(XM( -136), YM( -624), XM( -8), YM(-1320), XM( -8), YM(-2048)); // c 0
2012-10-12 15:36:57 +02:00
setbbox(path.boundingRect());
2012-05-26 14:26:10 +02:00
}
else if (bracketType() == BRACKET_NORMAL) {
2012-10-17 18:53:26 +02:00
qreal _spatium = spatium();
qreal w = score()->styleS(ST_bracketWidth).val() * _spatium * .5;
2012-10-12 15:36:57 +02:00
qreal x = -w;
2013-11-11 15:11:28 +01:00
w += symWidth(SymId::bracketTop);
2012-10-17 18:53:26 +02:00
qreal bd = _spatium * .25;
2013-11-11 15:11:28 +01:00
qreal y = - symHeight(SymId::bracketTop) - bd;
2012-10-17 18:53:26 +02:00
qreal h = (-y + h2) * 2;
2013-01-02 09:29:17 +01:00
bbox().setRect(x, y, w, h);
2012-05-26 14:26:10 +02:00
}
else if (bracketType() == BRACKET_SQUARE) {
2013-05-15 11:44:18 +02:00
qreal _spatium = spatium();
qreal w = score()->styleS(ST_staffLineWidth).val() * _spatium * .5;
2013-05-15 11:44:18 +02:00
qreal x = -w;
qreal y = -w;
qreal h = (h2 + w) * 2 ;
w += (.5 * spatium() + 3* w);
bbox().setRect(x, y, w, h);
2013-05-15 11:44:18 +02:00
}
2013-09-09 22:22:55 +02:00
else if (bracketType() == BRACKET_LINE) {
qreal _spatium = spatium();
qreal w = 0.67 * score()->styleS(ST_bracketWidth).val() * _spatium * .5;
qreal x = -w;
qreal bd = _spatium * .25;
qreal y = -bd;
qreal h = (-y + h2) * 2;
bbox().setRect(x, y, w, h);
}
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// draw
//---------------------------------------------------------
void Bracket::draw(QPainter* painter) const
{
2013-03-28 21:28:17 +01:00
if (h2 == 0.0)
return;
if (bracketType() == BRACKET_BRACE) {
2012-10-11 11:59:23 +02:00
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(curColor()));
painter->drawPath(path);
}
else if (bracketType() == BRACKET_NORMAL) {
2013-03-28 21:28:17 +01:00
qreal h = 2 * h2;
2012-10-17 18:53:26 +02:00
qreal _spatium = spatium();
qreal w = score()->styleS(ST_bracketWidth).val() * _spatium;
2012-10-11 11:59:23 +02:00
QPen pen(curColor(), w, Qt::SolidLine, Qt::FlatCap);
painter->setPen(pen);
2012-10-17 18:53:26 +02:00
qreal bd = _spatium * .25;
painter->drawLine(QLineF(0.0, -bd, 0.0, h + bd));
2012-10-11 11:59:23 +02:00
qreal x = -w * .5;
2012-10-17 18:53:26 +02:00
qreal y1 = -bd;
qreal y2 = h + bd;
2013-11-07 16:05:00 +01:00
drawSymbol(SymId::bracketTop, painter, QPointF(x, y1));
drawSymbol(SymId::bracketBottom, painter, QPointF(x, y2));
2012-10-11 11:59:23 +02:00
}
else if (bracketType() == BRACKET_SQUARE) {
2013-05-15 11:44:18 +02:00
qreal h = 2 * h2;
qreal _spatium = spatium();
qreal w = score()->styleS(ST_staffLineWidth).val() * _spatium;
QPen pen(curColor(), w, Qt::SolidLine, Qt::SquareCap);
painter->setPen(pen);
painter->drawLine(QLineF(0.0, 0.0, 0.0, h));
painter->drawLine(QLineF(0.0, 0.0, w + .5 *_spatium, 0.0));
painter->drawLine(QLineF(0.0, h , w + .5 *_spatium, h));
2013-05-15 11:44:18 +02:00
}
2013-09-09 22:22:55 +02:00
else if (bracketType() == BRACKET_LINE) {
qreal h = 2 * h2;
qreal _spatium = spatium();
qreal w = 0.67 * score()->styleS(ST_bracketWidth).val() * _spatium;
QPen pen(curColor(), w, Qt::SolidLine, Qt::FlatCap);
painter->setPen(pen);
qreal bd = _spatium * .25;
painter->drawLine(QLineF(0.0, -bd, 0.0, h + bd));
}
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// Bracket::write
//---------------------------------------------------------
void Bracket::write(Xml& xml) const
{
switch(bracketType()) {
case BRACKET_BRACE:
xml.stag("Bracket type=\"Brace\"");
2012-05-26 14:26:10 +02:00
break;
case BRACKET_NORMAL:
xml.stag("Bracket");
break;
case BRACKET_SQUARE:
xml.stag("Bracket type=\"Square\"");
2013-05-15 11:44:18 +02:00
break;
2013-09-09 22:22:55 +02:00
case BRACKET_LINE:
xml.stag("Bracket type=\"Line\"");
break;
2012-05-26 14:26:10 +02:00
case NO_BRACKET:
break;
}
if (_column)
xml.tag("level", _column);
Element::writeProperties(xml);
xml.etag();
}
//---------------------------------------------------------
// Bracket::read
//---------------------------------------------------------
2013-01-11 18:10:18 +01:00
void Bracket::read(XmlReader& e)
2012-05-26 14:26:10 +02:00
{
2013-01-11 18:10:18 +01:00
QString t(e.attribute("type", "Normal"));
2012-05-26 14:26:10 +02:00
if (t == "Normal")
setBracketType(BRACKET_NORMAL);
else if (t == "Akkolade") //compatibility, not used anymore
setBracketType(BRACKET_BRACE);
else if (t == "Brace")
setBracketType(BRACKET_BRACE);
else if (t == "Square")
setBracketType(BRACKET_SQUARE);
2013-09-09 22:22:55 +02:00
else if (t == "Line")
setBracketType(BRACKET_LINE);
2012-05-26 14:26:10 +02:00
else
qDebug("unknown brace type <%s>", qPrintable(t));
2012-05-26 14:26:10 +02:00
2013-01-11 18:10:18 +01:00
while (e.readNextStartElement()) {
if (e.name() == "level")
_column = e.readInt();
2012-05-26 14:26:10 +02:00
else if (!Element::readProperties(e))
2013-01-11 18:10:18 +01:00
e.unknown();
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// startEdit
//---------------------------------------------------------
void Bracket::startEdit(MuseScoreView*, const QPointF&)
{
2013-03-28 21:28:17 +01:00
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// updateGrips
//---------------------------------------------------------
void Bracket::updateGrips(int* grips, QRectF* grip) const
{
*grips = 1;
2013-03-28 21:28:17 +01:00
grip[0].translate(QPointF(0.0, h2 * 2) + pagePos());
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// gripAnchor
//---------------------------------------------------------
QPointF Bracket::gripAnchor(int) const
{
return QPointF();
}
//---------------------------------------------------------
// endEdit
//---------------------------------------------------------
void Bracket::endEdit()
{
endEditDrag();
}
//---------------------------------------------------------
// editDrag
//---------------------------------------------------------
void Bracket::editDrag(const EditData& ed)
{
2013-03-28 21:28:17 +01:00
h2 += ed.delta.y() * .5;
2012-05-26 14:26:10 +02:00
layout();
2013-06-27 11:02:42 +02:00
score()->setLayoutAll(false);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// endEditDrag
// snap to nearest staff
//---------------------------------------------------------
void Bracket::endEditDrag()
{
qreal ay1 = pagePos().y();
qreal ay2 = ay1 + h2 * 2;
int staffIdx1 = staffIdx();
int staffIdx2;
int n = system()->staves()->size();
if (staffIdx1 + 1 >= n)
staffIdx2 = staffIdx1;
else {
qreal ay = parent()->pagePos().y();
System* s = system();
qreal y = s->staff(staffIdx1)->y() + ay;
qreal h1 = staff()->height();
for (staffIdx2 = staffIdx1 + 1; staffIdx2 < n; ++staffIdx2) {
qreal h = s->staff(staffIdx2)->y() + ay - y;
if (ay2 < (y + (h + h1) * .5))
break;
y += h;
}
staffIdx2 -= 1;
}
qreal sy = system()->staff(staffIdx1)->y();
qreal ey = system()->staff(staffIdx2)->y() + score()->staff(staffIdx2)->height();
2013-03-28 21:28:17 +01:00
h2 = (ey - sy) * .5;
2013-05-31 12:23:07 +02:00
score()->undoChangeBracketSpan(staff(), _column, staffIdx2 - staffIdx1 + 1);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// acceptDrop
//---------------------------------------------------------
bool Bracket::acceptDrop(MuseScoreView*, const QPointF&, Element* e) const
{
return e->type() == BRACKET;
}
//---------------------------------------------------------
// drop
//---------------------------------------------------------
Element* Bracket::drop(const DropData& data)
{
Element* e = data.element;
if (e->type() == BRACKET) {
Bracket* b = static_cast<Bracket*>(e);
b->setParent(parent());
b->setTrack(track());
b->setSpan(span());
2012-10-12 15:36:57 +02:00
b->setFirstStaff(firstStaff());
b->setLastStaff(lastStaff());
2012-05-26 14:26:10 +02:00
b->setLevel(level());
score()->undoRemoveElement(this);
score()->undoAddElement(b);
return b;
}
delete e;
return 0;
}
//---------------------------------------------------------
// edit
// return true if event is accepted
//---------------------------------------------------------
bool Bracket::edit(MuseScoreView*, int, int key, Qt::KeyboardModifiers modifiers, const QString&)
{
2012-10-12 15:36:57 +02:00
if (!(modifiers & Qt::ShiftModifier))
return false;
if (key == Qt::Key_Left) {
BracketType bt = staff()->bracket(_column);
// search empty level
int oldColumn = _column;
staff()->setBracket(_column, NO_BRACKET);
for (;;) {
++_column;
if (staff()->bracket(_column) == NO_BRACKET)
break;
}
staff()->setBracket(_column, bt);
staff()->setBracketSpan(_column, _lastStaff - _firstStaff + 1);
score()->moveBracket(staffIdx(), oldColumn, _column);
score()->setLayoutAll(true);
return true;
}
if (key == Qt::Key_Right) {
if (_column == 0)
return true;
int l = _column - 1;
for (; l >= 0; --l) {
if (staff()->bracket(l) != NO_BRACKET)
continue;
2012-05-26 14:26:10 +02:00
BracketType bt = staff()->bracket(_column);
staff()->setBracket(_column, NO_BRACKET);
2012-10-12 15:36:57 +02:00
staff()->setBracket(l, bt);
staff()->setBracketSpan(l, _lastStaff - _firstStaff + 1);
2012-10-12 15:36:57 +02:00
score()->moveBracket(staffIdx(), _column, l);
2012-05-26 14:26:10 +02:00
score()->setLayoutAll(true);
2012-10-12 15:36:57 +02:00
break;
2012-05-26 14:26:10 +02:00
}
2012-10-12 15:36:57 +02:00
return true;
2012-05-26 14:26:10 +02:00
}
return false;
}
2013-05-13 18:49:17 +02:00
}