Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/engraving/dom/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
case ElementType::GUITAR_BEND: return new GuitarBend(parent->isNote() ? toNote(parent) : dummy->note());
case ElementType::TREMOLOBAR: return new TremoloBar(parent);
case ElementType::LYRICS: return new Lyrics(parent->isChordRest() ? toChordRest(parent) : dummy->chord());
case ElementType::LYRICSLINE: return new LyricsLine(parent);
case ElementType::FIGURED_BASS: return new FiguredBass(parent->isSegment() ? toSegment(parent) : dummy->segment());
case ElementType::STEM: return new Stem(parent->isChord() ? toChord(parent) : dummy->chord());
case ElementType::SLUR: return new Slur(parent);
Expand All @@ -247,7 +248,6 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
case ElementType::PARTIAL_LYRICSLINE: return new PartialLyricsLine(parent);
case ElementType::PARENTHESIS: return new Parenthesis(parent);

case ElementType::LYRICSLINE:
case ElementType::TEXTLINE_BASE:
case ElementType::TEXTLINE_SEGMENT:
case ElementType::GLISSANDO_SEGMENT:
Expand Down Expand Up @@ -446,6 +446,9 @@ MAKE_ITEM_IMPL(LayoutBreak, MeasureBase)
CREATE_ITEM_IMPL(Lyrics, ElementType::LYRICS, ChordRest, isAccessibleEnabled)
COPY_ITEM_IMPL(Lyrics)

CREATE_ITEM_IMPL(LyricsLine, ElementType::LYRICSLINE, EngravingItem, isAccessibleEnabled)
COPY_ITEM_IMPL(LyricsLine)

CREATE_ITEM_IMPL(Measure, ElementType::MEASURE, System, isAccessibleEnabled)
COPY_ITEM_IMPL(Measure)

Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class Factory
static Lyrics* createLyrics(ChordRest* parent, bool isAccessibleEnabled = true);
static Lyrics* copyLyrics(const Lyrics& src);

static LyricsLine* createLyricsLine(EngravingItem* parent, bool isAccessibleEnabled = true);
static LyricsLine* copyLyricsLine(const LyricsLine& src);

static Measure* createMeasure(System* parent, bool isAccessibleEnabled = true);
static Measure* copyMeasure(const Measure& src);

Expand Down
10 changes: 2 additions & 8 deletions src/engraving/dom/line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,14 +596,6 @@ void LineSegment::rebaseAnchors(EditData& ed, Grip grip)
return;
}

if (isTrillSegment()) {
EngravingItem* startElement = spanner()->startElement();
if (startElement && startElement->isChord() && toChord(startElement)->staffMove() != 0) {
// This trill is on a cross-staff chord. Don't try to rebase its anchors when dragging.
return;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good one, thanks for the tidy up


// don't change anchors on keyboard adjustment or if Ctrl is pressed
// (Ctrl+Left/Right is handled elsewhere!)
if (ed.key == Key_Left || ed.key == Key_Right || ed.key == Key_Up || ed.key == Key_Down || ed.modifiers & ControlModifier) {
Expand Down Expand Up @@ -771,6 +763,8 @@ void LineSegment::dragGrip(EditData& ed)
}
}

undoChangeProperty(Pid::GENERATED, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a slightly weird place to do this, because:

  • I think it's already handled somewhere at a lower level, EngravingObject::undoChangeProperty if I'm not mistaken. In other words any time any property is edited the element is also automatically un-flagged as generated, so I'm not 100% sure this is needed.
  • If it only applies to lyrics lines should it perhaps go there, instead?


EditTimeTickAnchors::updateAnchors(this);

triggerLayout();
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class LineSegment : public SpannerSegment

protected:
virtual void rebaseOffsetsOnAnchorChanged(Grip grip, const PointF& oldPos, System* sys);
virtual void rebaseAnchors(EditData&, Grip);

private:
void undoMoveStartEndAndSnappedItems(EditData& ed, bool moveStart, bool moveEnd, Segment* s1, Segment* s2);
Expand All @@ -90,7 +91,6 @@ class LineSegment : public SpannerSegment
static PointF deltaRebaseRight(const Segment* oldSeg, const Segment* newSeg);
static Fraction lastSegmentEndTick(const Segment* lastSeg, const Spanner* s);
LineSegment* rebaseAnchor(Grip grip, Segment* newSeg);
void rebaseAnchors(EditData&, Grip);
};

//---------------------------------------------------------
Expand Down
15 changes: 13 additions & 2 deletions src/engraving/dom/lyrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ TranslatableString Lyrics::subtypeUserName() const

void Lyrics::add(EngravingItem* el)
{
LOGD("Lyrics::add: unknown element %s", el->typeName());
if (el->isLyricsLine()) {
LyricsLine* separator = toLyricsLine(el);
m_separator = separator;
score()->addUnmanagedSpanner(separator);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you actually understood what "unmanaged spanners" are? Cause I never had the time to properly look into it so I really never did 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No not really! We could probably remove this distinction at this point.

} else {
LOGD("Lyrics::add: unknown element %s", el->typeName());
}
}

//---------------------------------------------------------
Expand All @@ -107,7 +113,6 @@ void Lyrics::remove(EngravingItem* el)
// be sure each finds a clean context
LyricsLine* separ = m_separator;
m_separator = 0;
separ->resetExplicitParent();
separ->removeUnmanaged();
}
} else {
Expand Down Expand Up @@ -591,4 +596,10 @@ void Lyrics::removeInvalidSegments()
}
}
}

void mu::engraving::PartialLyricsLine::setIsEndMelisma(bool val)
{
m_isEndMelisma = val;
styleChanged();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why styleChanged()? It looks a bit unrelated. If it's just about resetting some properties I'd consider doing that directly

}
}
21 changes: 13 additions & 8 deletions src/engraving/dom/lyrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ class Lyrics final : public TextBase
bool avoidBarlines() const { return m_avoidBarlines; }
void setAvoidBarlines(bool v) { m_avoidBarlines = v; }

protected:

private:

friend class Factory;
Expand Down Expand Up @@ -140,14 +138,15 @@ class LyricsLine : public SLine

LineSegment* createLineSegment(System* parent) override;
void removeUnmanaged() override;
void styleChanged() override;

virtual Lyrics* lyrics() const { return toLyrics(explicitParent()); }
Lyrics* nextLyrics() const { return m_nextLyrics; }
void setNextLyrics(Lyrics* l) { m_nextLyrics = l; }
virtual bool isEndMelisma() const { return lyrics() && lyrics()->ticks().isNotZero(); }
bool isDash() const { return !isEndMelisma(); }
bool setProperty(Pid propertyId, const PropertyValue& v) override;
PropertyValue propertyDefault(Pid id) const override;
Sid getPropertyStyle(Pid) const override;

protected:
LyricsLine(const ElementType& type, EngravingItem* parent, ElementFlags = ElementFlag::NOTHING);
Expand Down Expand Up @@ -182,10 +181,15 @@ class LyricsLineSegment : public LineSegment
virtual bool lyricsAddToSkyline() const { return lyrics()->addToSkyline(); }
virtual double lineSpacing() const { return lyrics()->lineSpacing(); }
Color color() const override { return lyrics()->color(); }
int gripsCount() const override { return 0; }
Grip initialEditModeGrip() const override { return Grip::NO_GRIP; }
Grip defaultGrip() const override { return Grip::NO_GRIP; }
bool needStartEditingAfterSelecting() const override { return false; }

PropertyValue getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const PropertyValue&) override;
PropertyValue propertyDefault(Pid propertyId) const override;
EngravingObject* propertyDelegate(Pid propertyId) const override;

bool allowTimeAnchor() const override { return false; }

virtual bool isEditAllowed(EditData&) const override { return false; }

struct LayoutData : public LineSegment::LayoutData {
public:
Expand All @@ -199,6 +203,7 @@ class LyricsLineSegment : public LineSegment

protected:
LyricsLineSegment(const ElementType& type, LyricsLine* sp, System* parent, ElementFlags f = ElementFlag::NOTHING);
void rebaseAnchors(EditData&, Grip) override;
};

class PartialLyricsLine final : public LyricsLine
Expand All @@ -214,7 +219,7 @@ class PartialLyricsLine final : public LyricsLine

Lyrics* lyrics() const override { return nullptr; }

void setIsEndMelisma(bool val) { m_isEndMelisma = val; }
void setIsEndMelisma(bool val);
bool isEndMelisma() const override { return m_isEndMelisma; }

void setVerse(int val) { m_verse = val; }
Expand Down
89 changes: 73 additions & 16 deletions src/engraving/dom/lyricsline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,28 @@ namespace mu::engraving {
// LyricsLine
//---------------------------------------------------------

static const ElementStyle lyricsLineElementStyle {
{ Sid::lyricsDashLineThickness, Pid::LINE_WIDTH }
};

LyricsLine::LyricsLine(EngravingItem* parent)
: SLine(ElementType::LYRICSLINE, parent, ElementFlag::NOT_SELECTABLE)
: SLine(ElementType::LYRICSLINE, parent)
{
setGenerated(true); // no need to save it, as it can be re-generated
setDiagonal(false);
setLineWidth(style().styleS(Sid::lyricsDashLineThickness));
initElementStyle(&lyricsLineElementStyle);
setAnchor(Spanner::Anchor::SEGMENT);
m_nextLyrics = 0;
setGenerated(true); // no need to save it, as it can be re-generated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GENERATED is also a flag I believe, so you could add the flag to the constructor's arguments instead of setting it here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated needs to be set to true after initElementStyle as any call to undoChangeProperty sets generated to false. The base class constructor where flags are set is called first.

}

LyricsLine::LyricsLine(const ElementType& type, EngravingItem* parent, ElementFlags f)
: SLine(type, parent, f)
{
setGenerated(true); // no need to save it, as it can be re-generated
setDiagonal(false);
setLineWidth(style().styleS(Sid::lyricsDashLineThickness));
initElementStyle(&lyricsLineElementStyle);
setAnchor(Spanner::Anchor::SEGMENT);
m_nextLyrics = 0;
setGenerated(true); // no need to save it, as it can be re-generated
}

LyricsLine::LyricsLine(const LyricsLine& g)
Expand All @@ -66,15 +70,6 @@ LyricsLine::LyricsLine(const LyricsLine& g)
m_nextLyrics = 0;
}

//---------------------------------------------------------
// styleChanged
//---------------------------------------------------------

void LyricsLine::styleChanged()
{
setLineWidth(style().styleS(Sid::lyricsDashLineThickness));
}

//---------------------------------------------------------
// createLineSegment
//---------------------------------------------------------
Expand Down Expand Up @@ -128,6 +123,27 @@ bool LyricsLine::setProperty(Pid propertyId, const engraving::PropertyValue& v)
return true;
}

PropertyValue LyricsLine::propertyDefault(Pid id) const
{
switch (id) {
case Pid::LINE_WIDTH:
return styleValue(Pid::LINE_WIDTH, getPropertyStyle(Pid::LINE_WIDTH));
case Pid::OFFSET:
return lyrics() ? lyrics()->offset() : SLine::propertyDefault(id);
default:
return SLine::propertyDefault(id);
}
}

Sid LyricsLine::getPropertyStyle(Pid propertyId) const
{
if (propertyId == Pid::LINE_WIDTH) {
return isEndMelisma() ? Sid::lyricsLineThickness : Sid::lyricsDashLineThickness;
}

return SLine::getPropertyStyle(propertyId);
}

void LyricsLine::doComputeEndElement()
{
if (!isEndMelisma()) {
Expand All @@ -146,8 +162,14 @@ void LyricsLine::doComputeEndElement()
// LyricsLineSegment
//=========================================================

void LyricsLineSegment::rebaseAnchors(EditData&, Grip)
{
// Don't rebase lyric line anchors on drag
return;
}

LyricsLineSegment::LyricsLineSegment(LyricsLine* sp, System* parent)
: LineSegment(ElementType::LYRICSLINE_SEGMENT, sp, parent, ElementFlag::ON_STAFF | ElementFlag::NOT_SELECTABLE)
: LineSegment(ElementType::LYRICSLINE_SEGMENT, sp, parent, ElementFlag::ON_STAFF)
{
setGenerated(true);
}
Expand All @@ -168,6 +190,42 @@ double LyricsLineSegment::baseLineShift() const
return -style().styleD(Sid::lyricsDashYposRatio) * segLyrics->fontMetrics().xHeight();
}

PropertyValue LyricsLineSegment::getProperty(Pid propertyId) const
{
if (EngravingObject* delegate = propertyDelegate(propertyId)) {
return delegate->getProperty(propertyId);
}

return LineSegment::getProperty(propertyId);
}

bool LyricsLineSegment::setProperty(Pid propertyId, const PropertyValue& val)
{
if (EngravingObject* delegate = propertyDelegate(propertyId)) {
return delegate->setProperty(propertyId, val);
}

return LineSegment::setProperty(propertyId, val);
}

PropertyValue LyricsLineSegment::propertyDefault(Pid propertyId) const
{
if (EngravingObject* delegate = propertyDelegate(propertyId)) {
return delegate->propertyDefault(propertyId);
}

return LineSegment::propertyDefault(propertyId);
}

EngravingObject* LyricsLineSegment::propertyDelegate(Pid propertyId) const
{
if (propertyId == Pid::GENERATED) {
return lyricsLine();
}

return LineSegment::propertyDelegate(propertyId);
}

//=========================================================
// PartialLyricsLine
//=========================================================
Expand Down Expand Up @@ -251,7 +309,6 @@ void PartialLyricsLine::doComputeEndElement()

static const ElementStyle partialLyricsLineSegmentElementStyle {
{ Sid::lyricsPlacement, Pid::PLACEMENT },
{ Sid::lyricsPosBelow, Pid::OFFSET },
{ Sid::lyricsMinTopDistance, Pid::MIN_DISTANCE },
};

Expand Down
11 changes: 11 additions & 0 deletions src/engraving/dom/trill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ void TrillSegment::symbolLine(SymId start, SymId fill, SymId end)
setbbox(r);
}

void TrillSegment::rebaseAnchors(EditData& ed, Grip grip)
{
EngravingItem* startElement = spanner()->startElement();
if (startElement && startElement->isChord() && toChord(startElement)->staffMove() != 0) {
// This trill is on a cross-staff chord. Don't try to rebase its anchors when dragging.
return;
}

LineSegment::rebaseAnchors(ed, grip);
}

//---------------------------------------------------------
// scanElements
//---------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/trill.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class TrillSegment final : public LineSegment
void symbolLine(SymId start, SymId fill);
void symbolLine(SymId start, SymId fill, SymId end);

protected:
void rebaseAnchors(EditData& ed, Grip grip) override;

private:
Sid getPropertyStyle(Pid) const override;

Expand Down
29 changes: 29 additions & 0 deletions src/engraving/dom/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,4 +1847,33 @@ std::vector<EngravingItem*> filterTargetElements(const Selection& sel, Engraving
}
return result;
}

Lyrics* searchNextLyrics(Segment* s, staff_idx_t staffIdx, int verse, PlacementV p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a big fan of this utils class, as it ends up containing a miscellaneous of things that are completely unrelated to each other, whereas I've always felt that most of these utiliy functions could just be in their related DOM class, perhaps as static functions. But let's rethink about that another time, I've no problem with this staying here for now.

{
Lyrics* l = nullptr;
const Segment* originalSeg = s;
while ((s = s->next1(SegmentType::ChordRest))) {
if (!segmentsAreAdjacentInRepeatStructure(originalSeg, s)) {
return nullptr;
}

track_idx_t strack = staffIdx * VOICES;
track_idx_t etrack = strack + VOICES;
// search through all tracks of current staff looking for a lyric in specified verse
for (track_idx_t track = strack; track < etrack; ++track) {
ChordRest* cr = toChordRest(s->element(track));
if (cr) {
// cr with lyrics found, but does it have a syllable in specified verse?
l = cr->lyrics(verse, p);
if (l) {
break;
}
}
}
if (l) {
break;
}
}
return l;
}
}
Loading
Loading