Skip to content

Commit

Permalink
Merge pull request #17237 from mike-spa/clefsAndKeySigPositioning
Browse files Browse the repository at this point in the history
Clefs and key signatures positioning improvement
  • Loading branch information
RomanPudashkin authored May 1, 2023
2 parents cf86789 + e011fd2 commit a76d6d3
Show file tree
Hide file tree
Showing 257 changed files with 880 additions and 75 deletions.
11 changes: 8 additions & 3 deletions src/engraving/libmscore/chordrest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,15 @@ EngravingItem* ChordRest::drop(EditData& data)
{
KeySig* ks = toKeySig(e);
KeySigEvent k = ks->keySigEvent();
delete ks;

// apply only to this stave
score()->undoChangeKeySig(staff(), tick(), k);
if (data.modifiers & ControlModifier) {
// apply only to this stave, before the selected chordRest
score()->undoChangeKeySig(staff(), tick(), k);
delete ks;
} else {
// apply to all staves, at the beginning of the measure
return m->drop(data);
}
}
break;

Expand Down
182 changes: 179 additions & 3 deletions src/engraving/libmscore/clef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "segment.h"
#include "staff.h"
#include "stafftype.h"
#include "undo.h"

#include "log.h"

Expand Down Expand Up @@ -96,7 +97,10 @@ const ClefInfo ClefInfo::clefTable[] = {

Clef::Clef(Segment* parent)
: EngravingItem(ElementType::CLEF, parent, ElementFlag::ON_STAFF), symId(SymId::noSym)
{}
{
_clefToBarlinePosition = ClefToBarlinePosition::AUTO;
_isHeader = parent->isHeaderClefType();
}

//---------------------------------------------------------
// mag
Expand Down Expand Up @@ -406,6 +410,8 @@ PropertyValue Clef::getProperty(Pid propertyId) const
case Pid::CLEF_TYPE_TRANSPOSING: return _clefTypes._transposingClef;
case Pid::SHOW_COURTESY: return showCourtesy();
case Pid::SMALL: return isSmall();
case Pid::CLEF_TO_BARLINE_POS: return _clefToBarlinePosition;
case Pid::IS_HEADER: return _isHeader;
default:
return EngravingItem::getProperty(propertyId);
}
Expand All @@ -424,9 +430,26 @@ bool Clef::setProperty(Pid propertyId, const PropertyValue& v)
case Pid::CLEF_TYPE_TRANSPOSING:
setTransposingClef(v.value<ClefType>());
break;
case Pid::SHOW_COURTESY: _showCourtesy = v.toBool();
case Pid::SHOW_COURTESY:
_showCourtesy = v.toBool();
if (_showCourtesy && isHeader() && selected()) {
Clef* courtesyClef = otherClef();
if (courtesyClef) {
score()->deselect(this);
score()->select(courtesyClef, SelectType::ADD, staffIdx());
}
}
break;
case Pid::SMALL:
setSmall(v.toBool());
break;
case Pid::SMALL: setSmall(v.toBool());
case Pid::CLEF_TO_BARLINE_POS:
if (v.value<ClefToBarlinePosition>() != _clefToBarlinePosition && !_isHeader) {
changeClefToBarlinePos(v.value<ClefToBarlinePosition>());
}
break;
case Pid::IS_HEADER:
setIsHeader(v.toBool());
break;
default:
return EngravingItem::setProperty(propertyId, v);
Expand All @@ -435,6 +458,152 @@ bool Clef::setProperty(Pid propertyId, const PropertyValue& v)
return true;
}

void Clef::changeClefToBarlinePos(ClefToBarlinePosition newPos)
{
_clefToBarlinePosition = newPos;

if (!explicitParent()) {
return;
}

Segment* seg = segment();
Measure* meas = seg->measure();

staff_idx_t nStaves = score()->nstaves();
for (staff_idx_t staffIndex = 0; staffIndex < nStaves; ++staffIndex) {
Clef* clef = static_cast<Clef*>(seg->elementAt(staffIndex * VOICES));
if (clef) {
clef->setClefToBarlinePosition(newPos);
}
}

Segment* endBarlineSeg = nullptr;
Segment* endRepeatSeg = nullptr;
Segment* startRepeatSeg = nullptr;

// Search first segment at this tick
Segment* firstSegAtThisTick = seg;
while (true) {
Segment* prev1 = firstSegAtThisTick->prev1();
if (prev1 && prev1->tick() == seg->tick()) {
firstSegAtThisTick = prev1;
} else {
break;
}
}
for (Segment* s = firstSegAtThisTick; s && s->tick() == seg->tick(); s = s->next1enabled()) {
// Scan all segments at this tick looking for the ones we need
if (s->isEndBarLineType() && s->measure()->repeatEnd()) {
endRepeatSeg = s;
} else if (s->isEndBarLineType()) {
endBarlineSeg = s;
} else if (s->isStartRepeatBarLineType()) {
startRepeatSeg = s;
}
}

if (newPos == ClefToBarlinePosition::AFTER) {
undoChangeProperty(Pid::SHOW_COURTESY, false, propertyFlags(Pid::SHOW_COURTESY));
}

if (newPos == ClefToBarlinePosition::AUTO) {
if (endBarlineSeg) {
// Clef before the end bar line
Measure* destMeas = endBarlineSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, endBarlineSeg);
seg->setRtick(endBarlineSeg->rtick());
seg->setParent(destMeas);
} else if (endRepeatSeg) {
// Clef after the end repeat
Measure* destMeas = endRepeatSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, endRepeatSeg->next());
seg->setRtick(endRepeatSeg->rtick());
seg->setParent(destMeas);
} else if (startRepeatSeg) {
// End of previous measure
Measure* destMeas = startRepeatSeg->measure()->prevMeasure();
if (destMeas) {
meas->segments().remove(seg);
destMeas->segments().push_back(seg);
seg->setRtick(destMeas->ticks());
seg->setParent(destMeas);
}
}
} else if (newPos == ClefToBarlinePosition::BEFORE) {
if (endBarlineSeg || endRepeatSeg) {
// Before the bar line
Segment* refSeg = endBarlineSeg ? endBarlineSeg : endRepeatSeg;
Measure* destMeas = refSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, refSeg);
seg->setRtick(refSeg->rtick());
seg->setParent(destMeas);
} else if (startRepeatSeg) {
// End of previous measure
Measure* destMeas = startRepeatSeg->measure()->prevMeasure();
if (destMeas) {
meas->segments().remove(seg);
destMeas->segments().push_back(seg);
seg->setRtick(destMeas->ticks());
seg->setParent(destMeas);
}
}
} else if (newPos == ClefToBarlinePosition::AFTER) {
bool isAtMeasureEnd = seg->rtick() == meas->ticks();
if (startRepeatSeg) {
// After the start repeat
Measure* destMeas = startRepeatSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, startRepeatSeg->next());
seg->setRtick(startRepeatSeg->rtick());
seg->setParent(destMeas);
} else if (isAtMeasureEnd) {
Measure* destMeas = meas->nextMeasure();
if (destMeas && !destMeas->header()) {
meas->segments().remove(seg);
destMeas->segments().push_front(seg);
seg->setRtick(Fraction(0, 1));
seg->setParent(destMeas);
} else if (destMeas) {
Segment* refSeg = destMeas->firstEnabled();
while (refSeg && refSeg->header()) {
refSeg = refSeg->nextEnabled();
}
if (refSeg) {
meas->segments().remove(seg);
destMeas->segments().insert(seg, refSeg);
seg->setRtick(refSeg->rtick());
seg->setParent(destMeas);
}
}
}
}

if ((newPos == ClefToBarlinePosition::AUTO || newPos == ClefToBarlinePosition::BEFORE)) {
undoChangeProperty(Pid::SHOW_COURTESY, true, PropertyFlags::STYLED);
}
}

void Clef::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
{
if (id == Pid::SHOW_COURTESY) {
if (v.toBool() != _showCourtesy) {
score()->undo(new ChangeProperty(this, id, v, ps));
Clef* pairedClef = otherClef();
if (pairedClef) {
score()->undo(new ChangeProperty(pairedClef, id, v, ps));
}
if (!segment()->isHeaderClefType()) {
setGenerated(false);
}
}
} else {
EngravingObject::undoChangeProperty(id, v, ps);
}
}

//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
Expand All @@ -446,6 +615,8 @@ PropertyValue Clef::propertyDefault(Pid id) const
case Pid::CLEF_TYPE_TRANSPOSING: return ClefType::INVALID;
case Pid::SHOW_COURTESY: return true;
case Pid::SMALL: return false;
case Pid::CLEF_TO_BARLINE_POS: return ClefToBarlinePosition::AUTO;
case Pid::IS_HEADER: return false;
default: return EngravingItem::propertyDefault(id);
}
}
Expand Down Expand Up @@ -489,5 +660,10 @@ void Clef::clear()
{
setbbox(RectF());
symId = SymId::noSym;
Clef* pairedClef = otherClef();
if (selected() && !isHeader() && pairedClef) {
score()->deselect(this);
score()->select(pairedClef, SelectType::ADD, staffIdx());
}
}
}
7 changes: 7 additions & 0 deletions src/engraving/libmscore/clef.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class Clef final : public EngravingItem
bool _showCourtesy = true;
bool m_isSmall = false;
bool _forInstrumentChange = false;
M_PROPERTY(ClefToBarlinePosition, clefToBarlinePosition, setClefToBarlinePosition)
M_PROPERTY(bool, isHeader, setIsHeader)

ClefTypeList _clefTypes { ClefType::INVALID };

Expand Down Expand Up @@ -148,6 +150,11 @@ class Clef final : public EngravingItem
EngravingItem* prevSegmentElement() override;
String accessibleInfo() const override;
void clear();

void changeClefToBarlinePos(ClefToBarlinePosition newPos);

void undoChangeProperty(Pid id, const PropertyValue& v) { EngravingObject::undoChangeProperty(id, v); }
void undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps) override;
};
} // namespace mu::engraving
#endif
7 changes: 7 additions & 0 deletions src/engraving/libmscore/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4871,6 +4871,12 @@ void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool fo
} else {
st = SegmentType::HeaderClef;
}
} else if (e->rtick() == Fraction(0, 1)) {
Measure* curMeasure = e->findMeasure();
Measure* prevMeasure = curMeasure ? curMeasure->prevMeasure() : nullptr;
if (prevMeasure && !prevMeasure->sectionBreak()) {
moveClef = true;
}
} else if (e->isClef()) {
Clef* clef = toClef(e);
if (clef->segment()->isHeaderClefType()) {
Expand Down Expand Up @@ -4962,6 +4968,7 @@ void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool fo
clef->setTrack(track);
clef->setClefType(ct);
clef->setParent(destSeg);
clef->setIsHeader(st == SegmentType::HeaderClef);
score->undo(new AddElement(clef));
clef->layout();
}
Expand Down
Loading

0 comments on commit a76d6d3

Please sign in to comment.