Skip to content

Commit

Permalink
Merge pull request #2135 from MarcSabatella/22626-system-dividers
Browse files Browse the repository at this point in the history
fix #22626: automatic system dividers
  • Loading branch information
lasconic committed Aug 15, 2015
2 parents 7c6ad68 + 7ac83bf commit 0391880
Show file tree
Hide file tree
Showing 12 changed files with 668 additions and 133 deletions.
3 changes: 3 additions & 0 deletions libmscore/element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static const ElementName elementNames[] = {
ElementName("SlurSegment", QT_TRANSLATE_NOOP("elementName", "Slur Segment")),
ElementName("StaffLines", QT_TRANSLATE_NOOP("elementName", "Staff Lines")),
ElementName("BarLine", QT_TRANSLATE_NOOP("elementName", "Bar Line")),
ElementName("SystemDivider", QT_TRANSLATE_NOOP("elementName", "System Divider")),
ElementName("StemSlash", QT_TRANSLATE_NOOP("elementName", "Stem Slash")),
ElementName("Line", QT_TRANSLATE_NOOP("elementName", "Line")),

Expand Down Expand Up @@ -657,6 +658,7 @@ void Element::writeProperties(Xml& xml) const
if (!userOff().isNull()) {
if (type() == Element::Type::VOLTA_SEGMENT
|| type() == Element::Type::GLISSANDO_SEGMENT || isChordRest()
|| type() == Element::Type::SYSTEM_DIVIDER
|| (xml.clipboardmode && isSLineSegment()))
xml.tag("offset", userOff() / spatium());
else
Expand Down Expand Up @@ -1287,6 +1289,7 @@ Element* Element::create(Element::Type type, Score* score)
case Element::Type::KEYSIG: return new KeySig(score);
case Element::Type::TIMESIG: return new TimeSig(score);
case Element::Type::BAR_LINE: return new BarLine(score);
case Element::Type::SYSTEM_DIVIDER: return new SystemDivider(score);
case Element::Type::ARPEGGIO: return new Arpeggio(score);
case Element::Type::BREATH: return new Breath(score);
case Element::Type::GLISSANDO: return new Glissando(score);
Expand Down
1 change: 1 addition & 0 deletions libmscore/element.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ class Element : public QObject, public ScoreElement {
SLUR_SEGMENT,
STAFF_LINES,
BAR_LINE,
SYSTEM_DIVIDER,
STEM_SLASH,
LINE,

Expand Down
62 changes: 62 additions & 0 deletions libmscore/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3528,6 +3528,17 @@ void Score::layoutPage(const PageContext& pC, qreal d)
system->move(QPointF(0.0, y));
}
}
// remove system dividers
for (System* s : *page->systems()) {
for (MeasureBase* mb : s->measures()) {
if (!mb->isMeasure())
continue;
for (Element* e : mb->el()) {
if (e->type() == Element::Type::SYSTEM_DIVIDER)
mb->remove(e);
}
}
}
return;
}

Expand Down Expand Up @@ -3615,6 +3626,57 @@ void Score::layoutPage(const PageContext& pC, qreal d)
system->move(QPointF(0.0, y));
if (system->addStretch())
y += system->stretchDistance();

if (system->isVbox())
continue;

// add / remove system dividers
bool divideLeft = styleB(StyleIdx::dividerLeft);
bool divideRight = styleB(StyleIdx::dividerRight);
if (system == page->systems()->last()) {
// no dividers for last system of page
divideLeft = false;
divideRight = false;
}
MeasureBase* first = system->firstMeasure();
MeasureBase* last = system->lastMeasure();
for (MeasureBase* mb : system->measures()) {
if (!mb->isMeasure())
continue;
SystemDivider* divider1 = nullptr;
SystemDivider* divider2 = nullptr;
for (Element* e : mb->el()) {
if (e->type() != Element::Type::SYSTEM_DIVIDER)
continue;
SystemDivider* sd = static_cast<SystemDivider*>(e);
if (sd->generated())
mb->remove(sd);
else if (mb == first && divideLeft && sd->dividerType() == SystemDivider::Type::LEFT)
divider1 = sd;
else if (mb == last && divideRight && sd->dividerType() == SystemDivider::Type::RIGHT)
divider2 = sd;
else // this was non-generated, but no longer applies
mb->remove(sd);
}
if (mb == first && divideLeft) {
if (!divider1) {
divider1 = new SystemDivider(this);
divider1->setGenerated(true);
divider1->setParent(mb);
addElement(divider1);
}
divider1->setDividerType(SystemDivider::Type::LEFT);
}
if (mb == last && divideRight) {
if (!divider2) {
divider2 = new SystemDivider(this);
divider2->setGenerated(true);
divider2->setParent(mb);
addElement(divider2);
}
divider2->setDividerType(SystemDivider::Type::RIGHT);
}
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions libmscore/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1715,9 +1715,8 @@ void Measure::write(Xml& xml, int staff, bool writeSystemElements) const
int strack = staff * VOICES;
int etrack = strack + VOICES;
foreach (const Element* el, _el) {
if (!el->generated() && ((el->staffIdx() == staff) || (el->systemFlag() && writeSystemElements))) {
if (!el->generated() && ((el->staffIdx() == staff) || (el->systemFlag() && writeSystemElements)))
el->write(xml);
}
}
Q_ASSERT(first());
Q_ASSERT(last());
Expand Down Expand Up @@ -2314,6 +2313,11 @@ void Measure::read(XmlReader& e, int staffIdx)
noText->setParent(this);
staves[noText->staffIdx()]->setNoText(noText);
}
else if (tag == "SystemDivider") {
SystemDivider* sd = new SystemDivider(score());
sd->read(e);
add(sd);
}
else if (tag == "Ambitus") {
Ambitus* range = new Ambitus(score());
range->read(e);
Expand Down
16 changes: 16 additions & 0 deletions libmscore/style.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ static const StyleTypes2 styleTypes2[] = {
{ StyleIdx::bracketDistance, StyleType("bracketDistance", StyleValueType::SPATIUM) }, // system bracket distance
{ StyleIdx::akkoladeWidth, StyleType("akkoladeWidth", StyleValueType::SPATIUM) },
{ StyleIdx::akkoladeBarDistance, StyleType("akkoladeBarDistance", StyleValueType::SPATIUM) },
{ StyleIdx::dividerLeft, StyleType("dividerLeft", StyleValueType::BOOL) },
{ StyleIdx::dividerLeftSym, StyleType("dividerLeftSym", StyleValueType::STRING) },
{ StyleIdx::dividerLeftX, StyleType("dividerLeftX", StyleValueType::DOUBLE) },
{ StyleIdx::dividerLeftY, StyleType("dividerLeftY", StyleValueType::DOUBLE) },
{ StyleIdx::dividerRight, StyleType("dividerRight", StyleValueType::BOOL) },
{ StyleIdx::dividerRightSym, StyleType("dividerRightSym", StyleValueType::STRING) },
{ StyleIdx::dividerRightX, StyleType("dividerRightX", StyleValueType::DOUBLE) },
{ StyleIdx::dividerRightY, StyleType("dividerRightY", StyleValueType::DOUBLE) },
{ StyleIdx::clefLeftMargin, StyleType("clefLeftMargin", StyleValueType::SPATIUM) },
{ StyleIdx::keysigLeftMargin, StyleType("keysigLeftMargin", StyleValueType::SPATIUM) },
{ StyleIdx::timesigLeftMargin, StyleType("timesigLeftMargin", StyleValueType::SPATIUM) },
Expand Down Expand Up @@ -425,6 +433,14 @@ StyleData::StyleData()
{ StyleIdx::bracketDistance, QVariant(0.1) },
{ StyleIdx::akkoladeWidth, QVariant(1.6) },
{ StyleIdx::akkoladeBarDistance, QVariant(.4) },
{ StyleIdx::dividerLeft, QVariant(false) },
{ StyleIdx::dividerLeftSym, QVariant(QString("systemDivider")) },
{ StyleIdx::dividerLeftX, QVariant(0.0) },
{ StyleIdx::dividerLeftY, QVariant(0.0) },
{ StyleIdx::dividerRight, QVariant(false) },
{ StyleIdx::dividerRightSym, QVariant(QString("systemDivider")) },
{ StyleIdx::dividerRightX, QVariant(0.0) },
{ StyleIdx::dividerRightY, QVariant(0.0) },
{ StyleIdx::clefLeftMargin, QVariant(0.64) },
{ StyleIdx::keysigLeftMargin, QVariant(0.5) },
{ StyleIdx::timesigLeftMargin, QVariant(0.5) },
Expand Down
8 changes: 8 additions & 0 deletions libmscore/style.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ enum class StyleIdx : unsigned char {
bracketDistance,
akkoladeWidth,
akkoladeBarDistance,
dividerLeft,
dividerLeftSym,
dividerLeftX,
dividerLeftY,
dividerRight,
dividerRightSym,
dividerRightX,
dividerRightY,

clefLeftMargin,
keysigLeftMargin,
Expand Down
4 changes: 2 additions & 2 deletions libmscore/symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ void Symbol::layout()
{
// foreach(Element* e, leafs()) done in BSymbol::layout() ?
// e->layout();
ElementLayout::layout(this);
BSymbol::layout();
setbbox(_scoreFont ? _scoreFont->bbox(_sym, magS()) : symBbox(_sym));
ElementLayout::layout(this);
BSymbol::layout(); // adjustReadPos() happens here
}

//---------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion libmscore/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Symbol : public BSymbol {
void setAbove(bool);

virtual qreal baseLine() const { return 0.0; }
Segment* segment() const { return (Segment*)parent(); }
virtual Segment* segment() const { return (Segment*)parent(); }
};

//---------------------------------------------------------
Expand Down
131 changes: 131 additions & 0 deletions libmscore/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "chordrest.h"
#include "iname.h"
#include "spanner.h"
#include "sym.h"

namespace Ms {

Expand Down Expand Up @@ -1180,5 +1181,135 @@ Element* System::prevElement()
}
return re;
}

//---------------------------------------------------------
// SystemDivider
//---------------------------------------------------------

SystemDivider::SystemDivider(Score* s) : Symbol(s)
{
setSystemFlag(true);
setTrack(0);
// default value, but not valid until setDividerType()
_dividerType = SystemDivider::Type::LEFT;
_sym = SymId::systemDivider;
}

//---------------------------------------------------------
// SystemDivider
//---------------------------------------------------------

SystemDivider::SystemDivider(const SystemDivider& sd) : Symbol(sd)
{
_dividerType = sd._dividerType;
}

//---------------------------------------------------------
// setDividerType
//---------------------------------------------------------

void SystemDivider::setDividerType(SystemDivider::Type v)
{
ScoreFont* sf = _score->scoreFont();
_dividerType = v;
if (v == SystemDivider::Type::LEFT) {
SymId symLeft = Sym::name2id(_score->styleSt(StyleIdx::dividerLeftSym));
if (!symIsValid(symLeft))
sf = sf->fallbackFont();
setSym(symLeft, sf);
setXoff(_score->styleD(StyleIdx::dividerLeftX));
setYoff(_score->styleD(StyleIdx::dividerLeftY));
setAlign(AlignmentFlags::LEFT | AlignmentFlags::VCENTER);
}
else {
SymId symRight = Sym::name2id(_score->styleSt(StyleIdx::dividerRightSym));
if (!symIsValid(symRight))
sf = sf->fallbackFont();
setSym(symRight, sf);
setXoff(_score->styleD(StyleIdx::dividerRightX));
setYoff(_score->styleD(StyleIdx::dividerRightY));
setAlign(AlignmentFlags::RIGHT | AlignmentFlags::VCENTER);
}
}

//---------------------------------------------------------
// drag
//---------------------------------------------------------

QRectF SystemDivider::drag(EditData* ed)
{
setGenerated(false);
return Symbol::drag(ed);
}

//---------------------------------------------------------
// layout
//---------------------------------------------------------

void SystemDivider::layout()
{
Symbol::layout();
// center vertically between systems
rypos() -= bbox().y();
Measure* m = measure();
if (m) {
System* s1 = m->system();
if (!s1)
return;
rypos() += s1->height() + (s1->distance() + s1->stretchDistance()) * 0.5;
// center horizontally under left/right barline
if (dividerType() == SystemDivider::Type::LEFT)
rxpos() -= width() * 0.5;
else
rxpos() += m->width() + width() * 0.5;
}
adjustReadPos();
}

//---------------------------------------------------------
// write
//---------------------------------------------------------

void SystemDivider::write(Xml& xml) const
{
if (dividerType() == SystemDivider::Type::LEFT)
xml.stag(QString("SystemDivider type=\"left\""));
else
xml.stag(QString("SystemDivider type=\"right\""));
writeProperties(xml);
xml.etag();
}

//---------------------------------------------------------
// read
//---------------------------------------------------------

void SystemDivider::read(XmlReader& e)
{
Align a = align() & AlignmentFlags::VMASK;
ScoreFont* sf = score()->scoreFont();
if (e.attribute("type") == "left") {
_dividerType = SystemDivider::Type::LEFT;
SymId sym = Sym::name2id(score()->styleSt(StyleIdx::dividerLeftSym));
if (!symIsValid(sym))
sf = sf->fallbackFont();
setSym(sym, sf);
setAlign(a | AlignmentFlags::LEFT);
setXoff(score()->styleB(StyleIdx::dividerLeftX));
setYoff(score()->styleB(StyleIdx::dividerLeftY));
}
else {
_dividerType = SystemDivider::Type::RIGHT;
SymId sym = Sym::name2id(score()->styleSt(StyleIdx::dividerRightSym));
if (!symIsValid(sym))
sf = sf->fallbackFont();
setSym(sym, sf);
setAlign(a | AlignmentFlags::RIGHT);
setXoff(score()->styleB(StyleIdx::dividerRightX));
setYoff(score()->styleB(StyleIdx::dividerRightY));
}
Symbol::read(e);
}

}

30 changes: 30 additions & 0 deletions libmscore/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "element.h"
#include "spatium.h"
#include "symbol.h"

namespace Ms {

Expand Down Expand Up @@ -192,6 +193,35 @@ class System : public Element {
typedef QList<System*>::iterator iSystem;
typedef QList<System*>::const_iterator ciSystem;

class SystemDivider : public Symbol {
Q_OBJECT
Q_ENUMS(Type)

public:
enum class Type : char { LEFT, RIGHT };

private:
Type _dividerType;

public:
SystemDivider(Score* s = 0);
SystemDivider(const SystemDivider&);

virtual SystemDivider* clone() const override { return new SystemDivider(*this); }
virtual Element::Type type() const override { return Element::Type::SYSTEM_DIVIDER; }

Type dividerType() const { return _dividerType; }
void setDividerType(Type v);

virtual QRectF drag(EditData*) override;
virtual void layout() override;
virtual void write(Xml&) const override;
virtual void read(XmlReader&) override;

virtual Segment* segment() const override { return 0; }
Measure* measure() const { return (Measure*)parent(); }
};


} // namespace Ms
#endif
Expand Down
Loading

0 comments on commit 0391880

Please sign in to comment.