diff --git a/libmscore/barline.cpp b/libmscore/barline.cpp index 34d6b9c65d7ed..9ec6c83ed9636 100644 --- a/libmscore/barline.cpp +++ b/libmscore/barline.cpp @@ -142,6 +142,7 @@ static void undoChangeBarLineType(BarLine* bl, BarLineType barType, bool allStav } } } + else if (segmentType == SegmentType::BarLine) {} //TODO: also allow changes on barlines added by user } break; case BarLineType::START_REPEAT: { @@ -534,22 +535,33 @@ void BarLine::draw(QPainter* painter) const switch (barLineType()) { case BarLineType::NORMAL: { qreal lw = score()->styleP(Sid::barWidth) * mag(); + // a bar line added to the first cr of a measure is a user BeginBarLine (for ossias / cutaway). + // Normal/broken/dotted barlines overlap previous measure's EndBarLine + int overlap = 1; + if (parent()) + overlap = segment()->segmentType() == SegmentType::BeginBarLine && !segment()->measure()->header() ? -1 : 1; painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::FlatCap)); - painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2)); + painter->drawLine(QLineF(lw * .5 * overlap, y1, lw * .5 * overlap, y2)); } break; case BarLineType::BROKEN: { qreal lw = score()->styleP(Sid::barWidth) * mag(); + int overlap = 1; + if (parent()) + overlap = segment()->segmentType() == SegmentType::BeginBarLine && !segment()->measure()->header() ? -1 : 1; painter->setPen(QPen(curColor(), lw, Qt::DashLine, Qt::FlatCap)); - painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2)); + painter->drawLine(QLineF(lw * .5 * overlap, y1, lw * .5 * overlap, y2)); } break; case BarLineType::DOTTED: { qreal lw = score()->styleP(Sid::barWidth) * mag(); + int overlap = 1; + if (parent()) + overlap = segment()->segmentType() == SegmentType::BeginBarLine && !segment()->measure()->header() ? -1 : 1; painter->setPen(QPen(curColor(), lw, Qt::DotLine, Qt::FlatCap)); - painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2)); + painter->drawLine(QLineF(lw * .5 * overlap, y1, lw * .5 * overlap, y2)); } break; @@ -1152,7 +1164,7 @@ void BarLine::endEditDrag(EditData& ed) } bool localDrag = ed.control() || segment()->isBarLine(); - if (localDrag) { + if (localDrag || !generated()) { // Don't set global span from dragging user added (non generated) bar lines Segment* s = segment(); for (int staffIdx = staffIdx1; staffIdx < staffIdx2; ++staffIdx) { BarLine* b = toBarLine(s->element(staffIdx * VOICES)); diff --git a/libmscore/chordrest.cpp b/libmscore/chordrest.cpp index d8694b96960f0..641bf644e12a8 100644 --- a/libmscore/chordrest.cpp +++ b/libmscore/chordrest.cpp @@ -437,14 +437,12 @@ Element* ChordRest::drop(EditData& data) bl->setTrack(staffIdx() * VOICES); bl->setGenerated(false); - if (tick() == m->tick()) - return m->drop(data); - BarLine* obl = 0; for (Staff* st : staff()->staffList()) { Score* score = st->score(); Measure* measure = score->tick2measure(m->tick()); - Segment* seg = measure->undoGetSegmentR(SegmentType::BarLine, rtick()); + SegmentType segmentType = tick() == m->tick() ? SegmentType::BeginBarLine : SegmentType::BarLine; + Segment* seg = measure->undoGetSegmentR(segmentType, rtick()); BarLine* l; if (obl == 0) obl = l = bl->clone(); diff --git a/libmscore/measure.cpp b/libmscore/measure.cpp index 054ab610d2038..5098ffe9254b8 100644 --- a/libmscore/measure.cpp +++ b/libmscore/measure.cpp @@ -250,8 +250,14 @@ Measure::Measure(const Measure& m) void Measure::layoutStaffLines() { - for (MStaff* ms : _mstaves) - ms->lines()->layout(); + int staffIdx = 0; + for (MStaff* ms : _mstaves) { + if (score()->staff(staffIdx)->cutaway() && isCourtesyClef(staffIdx)) + ms->lines()->layoutPartial(width(), 4.0 ,false); // draw a shortened staff (4.0 sp wide) only for the antecipated Clef. + else + ms->lines()->layout(); + staffIdx += 1; + } } //--------------------------------------------------------- @@ -2088,7 +2094,7 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular) // StartRepeatBarLine: at rtick == 0, always BarLineType::START_REPEAT // BarLine: in the middle of a measure, has no semantic // EndBarLine: at the end of a measure - // BeginBarLine: first segment of a measure, systemic barline + // BeginBarLine: first segment of a measure, systemic barline (or begin bar line added by user) SegmentType st = SegmentType::Invalid; Fraction t = e.tick() - tick(); @@ -2449,7 +2455,7 @@ bool Measure::visible(int staffIdx) const } if (system() && (system()->staves()->empty() || !system()->staff(staffIdx)->show())) return false; - if (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx)) + if (score()->staff(staffIdx)->cutaway() && isEmpty(staffIdx) && !isCourtesyClef(staffIdx)) return false; return score()->staff(staffIdx)->show() && _mstaves[staffIdx]->visible(); } @@ -2733,6 +2739,34 @@ bool Measure::hasVoice(int track) const return false; } +// isCourtesyClef +/// Check if the measure is empty except for a clef before end bar line + +bool Measure::isCourtesyClef(int staffIdx) const + { + if (!isEmpty(staffIdx)) + return false; + Segment* s = last()->prev(); + /*if (s->segmentType() != SegmentType::Clef) + return false;*/ + int strack; + int etrack; + if (staffIdx < 0) { + strack = 0; + etrack = score()->nstaves() * VOICES; + } + else { + strack = staffIdx * VOICES; + etrack = strack + VOICES; + } + for (int track = strack; track < etrack; ++track) { + Element* e = s->element(track); + if (e && e->isClef()) + return true; + } + return false; + } + //------------------------------------------------------------------- // isEmpty /// Check if the measure is filled by a full-measure rest, or is diff --git a/libmscore/measure.h b/libmscore/measure.h index 98f6ace347bd3..d23a24c833ab0 100644 --- a/libmscore/measure.h +++ b/libmscore/measure.h @@ -219,6 +219,7 @@ class Measure final : public MeasureBase { void checkMultiVoices(int staffIdx); bool hasVoice(int track) const; bool isEmpty(int staffIdx) const; + bool isCourtesyClef(int staffIdx) const; bool isFullMeasureRest() const; bool isRepeatMeasure(const Staff* staff) const; bool visible(int staffIdx) const; diff --git a/libmscore/stafflines.cpp b/libmscore/stafflines.cpp index 905a112f61fb7..e67855a54d677 100644 --- a/libmscore/stafflines.cpp +++ b/libmscore/stafflines.cpp @@ -123,6 +123,51 @@ void StaffLines::layoutForWidth(qreal w) } } +//--------------------------------------------------------- +// layoutPartial +//--------------------------------------------------------- + +void StaffLines::layoutPartial(qreal w, qreal wPartial, bool alignLeft) + { + const Staff* s = staff(); + qreal _spatium = spatium(); + wPartial *= spatium(); + qreal dist = _spatium; + setPos(QPointF(0.0, 0.0)); + int _lines; + if (s) { + setMag(s->mag(measure()->tick())); + setColor(s->color()); + const StaffType* st = s->staffType(measure()->tick()); + dist *= st->lineDistance().val(); + _lines = st->lines(); + rypos() = st->yoffset().val() * _spatium; + } + else { + _lines = 5; + setColor(MScore::defaultColor); + } + lw = score()->styleS(Sid::staffLineWidth).val() * _spatium; + qreal x1 = pos().x(); + qreal x2 = x1 + w; + qreal y = pos().y(); + bbox().setRect(x1, -lw * .5 + y, w, (_lines-1) * dist + lw); + + if (_lines == 1) { + qreal extraSize = _spatium; + bbox().adjust(0, -extraSize, 0, extraSize); + } + + lines.clear(); + for (int i = 0; i < _lines; ++i) { + if (alignLeft) + lines.push_back(QLineF(x1, y, x1 + wPartial, y)); + else + lines.push_back(QLineF(x2-wPartial, y, x2, y)); + y += dist; + } + } + //--------------------------------------------------------- // draw //--------------------------------------------------------- diff --git a/libmscore/stafflines.h b/libmscore/stafflines.h index 92d54b6bbd99f..5e4a6dc4e4416 100644 --- a/libmscore/stafflines.h +++ b/libmscore/stafflines.h @@ -38,6 +38,7 @@ class StaffLines final : public Element { Measure* measure() const { return (Measure*)parent(); } qreal y1() const; void layoutForWidth(qreal width); + void layoutPartial (qreal width, qreal widthPartial, bool alignRight); }; } // namespace Ms