2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
|
|
|
// Copyright (C) 2010-2011 Werner Schweer
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#ifndef __SPANNER_H__
|
|
|
|
#define __SPANNER_H__
|
|
|
|
|
|
|
|
#include "element.h"
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
class Segment;
|
|
|
|
class Spanner;
|
|
|
|
class System;
|
2013-06-16 23:33:37 +02:00
|
|
|
class Chord;
|
2013-06-10 11:03:34 +02:00
|
|
|
class ChordRest;
|
2015-02-28 09:57:46 +01:00
|
|
|
class Note;
|
2013-06-10 11:03:34 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// SpannerSegmentType
|
|
|
|
//---------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-05-26 20:38:22 +02:00
|
|
|
enum class SpannerSegmentType : char {
|
|
|
|
SINGLE, BEGIN, MIDDLE, END
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-07-25 11:49:34 +02:00
|
|
|
// @@ SpannerSegment
|
2014-05-16 13:44:32 +02:00
|
|
|
//! parent: System
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class SpannerSegment : public Element {
|
2012-05-28 11:29:21 +02:00
|
|
|
Q_OBJECT
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
Spanner* _spanner;
|
2013-06-10 11:03:34 +02:00
|
|
|
SpannerSegmentType _spannerSegmentType;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
QPointF _p2;
|
|
|
|
QPointF _userOff2;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
SpannerSegment(Score* s);
|
|
|
|
SpannerSegment(const SpannerSegment&);
|
|
|
|
virtual SpannerSegment* clone() const = 0;
|
2013-06-10 11:03:34 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
Spanner* spanner() const { return _spanner; }
|
|
|
|
Spanner* setSpanner(Spanner* val) { return _spanner = val; }
|
|
|
|
|
2013-03-05 20:23:59 +01:00
|
|
|
void setSpannerSegmentType(SpannerSegmentType s) { _spannerSegmentType = s; }
|
|
|
|
SpannerSegmentType spannerSegmentType() const { return _spannerSegmentType; }
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
void setSystem(System* s);
|
|
|
|
System* system() const { return (System*)parent(); }
|
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
const QPointF& userOff2() const { return _userOff2; }
|
|
|
|
void setUserOff2(const QPointF& o) { _userOff2 = o; }
|
|
|
|
void setUserXoffset2(qreal x) { _userOff2.setX(x); }
|
|
|
|
void setPos2(const QPointF& p) { _p2 = p; }
|
|
|
|
QPointF pos2() const { return _p2 + _userOff2; }
|
|
|
|
const QPointF& ipos2() const { return _p2; }
|
Lyrics multi-system melisma and dashes
Implements melisma and dash lines for lyrics spanning several systems.
The melisma and dash line is based on the `SLine` class and its segments on the `LineSegment` class. Both the whole line and its segments are not selectable, marked as generated and not saved in the score file, which is not changed in any way.
For very wide dash segments, several dashes are drawn; the distance between the dashes is not configurable.
Lyrics layout code in `Measure` class and in `layout.cpp` file has been commented out as the lyrics line layout is all contained in the lyrics.cpp file
The line is registered with the `Score` (to have its layout delayed until all elements are positioned) with a mechanism similar to other `Spanner`'s, but in a different container (`_unmanagedSpanner`), as the owning `Lyrics` should decide when create, register, unregister and delete its line.
The line segments are registered with the `System` they belong to (to have them drawn), in the same way as other `Spanner`'s.
There is code for using the dash metrics of the lyrics font, but it is turned off via a conditional directive, as there does not seem to be a reliable way to determine the dash metrics; conventional values (determined by trials and errors and based on my taste!) are used when the conditional directive is off.
2015-01-11 10:11:44 +01:00
|
|
|
qreal& rxpos2() { return _p2.rx(); }
|
|
|
|
qreal& rypos2() { return _p2.ry(); }
|
2013-06-10 11:03:34 +02:00
|
|
|
|
2013-08-12 10:37:30 +02:00
|
|
|
virtual void startEdit(MuseScoreView*, const QPointF&) override;
|
|
|
|
virtual void endEdit() override;
|
|
|
|
virtual bool isEditable() const override { return true; }
|
2013-05-02 16:12:17 +02:00
|
|
|
|
2013-08-12 10:37:30 +02:00
|
|
|
virtual QVariant getProperty(P_ID id) const override;
|
|
|
|
virtual bool setProperty(P_ID id, const QVariant& v) override;
|
|
|
|
virtual QVariant propertyDefault(P_ID id) const override;
|
2015-03-30 10:06:53 +02:00
|
|
|
void reset() override;
|
2014-05-07 12:10:28 +02:00
|
|
|
virtual void setSelected(bool f) override;
|
|
|
|
virtual void setVisible(bool f) override;
|
2014-10-01 15:15:08 +02:00
|
|
|
virtual void setColor(const QColor& col) override;
|
2014-07-10 14:13:37 +02:00
|
|
|
|
2014-06-20 22:48:34 +02:00
|
|
|
virtual Element* nextElement() override;
|
|
|
|
virtual Element* prevElement() override;
|
2014-07-10 14:13:37 +02:00
|
|
|
virtual bool isSpannerSegment() const override { return true; }
|
2016-02-04 17:06:32 +01:00
|
|
|
virtual QString accessibleInfo() const override;
|
2015-02-02 14:52:13 +01:00
|
|
|
virtual void styleChanged() override;
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
2012-09-12 11:16:36 +02:00
|
|
|
//----------------------------------------------------------------------------------
|
2012-07-16 19:59:32 +02:00
|
|
|
// @@ Spanner
|
|
|
|
/// Virtual base class for slurs, ties, lines etc.
|
|
|
|
//
|
2015-04-24 02:23:37 +02:00
|
|
|
// @P anchor enum (Spanner.CHORD, Spanner.MEASURE, Spanner.NOTE, Spanner.SEGMENT)
|
|
|
|
// @P endElement Element the element the spanner end is anchored to (read-only)
|
|
|
|
// @P startElement Element the element the spanner start is anchored to (read-only)
|
|
|
|
// @P tick int tick start position
|
|
|
|
// @P tick2 int tick end position
|
2012-09-12 11:16:36 +02:00
|
|
|
//----------------------------------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
class Spanner : public Element {
|
2012-05-28 11:29:21 +02:00
|
|
|
Q_OBJECT
|
2012-09-12 11:16:36 +02:00
|
|
|
Q_ENUMS(Anchor)
|
|
|
|
|
|
|
|
public:
|
2014-05-26 20:48:27 +02:00
|
|
|
enum class Anchor : char {
|
|
|
|
SEGMENT, MEASURE, CHORD, NOTE
|
2012-09-12 11:16:36 +02:00
|
|
|
};
|
|
|
|
private:
|
2015-03-27 11:31:40 +01:00
|
|
|
Q_PROPERTY(Ms::Spanner::Anchor anchor READ anchor WRITE setAnchor)
|
|
|
|
Q_PROPERTY(Ms::Element* endElement READ endElement)
|
|
|
|
Q_PROPERTY(Ms::Element* startElement READ startElement)
|
|
|
|
Q_PROPERTY(int tick READ tick WRITE setTick)
|
|
|
|
Q_PROPERTY(int tick2 READ tick2 WRITE setTick2)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-08-13 15:42:40 +02:00
|
|
|
Element* _startElement { 0 };
|
|
|
|
Element* _endElement { 0 };
|
2014-08-22 13:33:36 +02:00
|
|
|
|
|
|
|
Anchor _anchor { Anchor::SEGMENT };
|
2014-08-13 15:42:40 +02:00
|
|
|
int _tick { -1 };
|
|
|
|
int _ticks { 0 };
|
|
|
|
int _track2 { -1 };
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
static QList<QPointF> userOffsets;
|
|
|
|
static QList<QPointF> userOffsets2;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-07-05 11:23:52 +02:00
|
|
|
protected:
|
2014-07-31 16:30:04 +02:00
|
|
|
QList<SpannerSegment*> segments;
|
Fixes #19155, #22861 (duplicate of the former) and #23100.
__References__:
Issues: https://musescore.org/en/node/19155 https://musescore.org/en/node/22861 https://musescore.org/en/node/23100
__Description__:
Allows to change the start and end note to which a glissando is anchored after it has been entered. Either anchor can be changed independently.
The user interface follows the current working of other 'snappable' lines. Once either the start or end grip is selected:
- `[Shift]+[Left]` snaps the anchor to the previous chord, defaulting to its top note.
- `[Shift]+[Right]` snaps to the next chord, defaulting to its top note.
- `[Shift]+[Up]` snaps to the note above (possibly in a chord, voice or staff above the current one).
- `[Shift]+[Down]` snaps to the note below (possibly in a chord, voice or staff below the current one).
This permits to set the anchor points of a glissando to any note in the score, allowing several glissandi between the notes of the same two chords and other complex configurations (glissandi skipping intermediate chords, start and end notes in different voices or staves, and so on).
It is possible to move the anchor to a different staff of the same instrument, but not to a different instrument; also, it is not possible to 'cross' a change of instrument in the same staff.
__Known limitations__:
- The `[Shift]+[Up]` and `[Shift]+[Down]` use the same note-finding functions as the `[Alt]+[Up]` and `[Alt]+[Down]`actions which move the selection cursor to the above and below note, even across voices or staves. Occasionally, in particular if the note immediately above or below is not time-aligned, the algorithm has little expected results; however, the behaviour is already known to the user. Improving the algorithm would benefit both uses.
__Notes__:
- Most of the added infrastructure is not specific to glissando but to any spanner anchored to notes, then it should also add after-the-fact "snap to" note support to note-anchored text line.
- When moving an anchor, the algorithm usually prefers a note in the same voice/staff of the old note if it exists; if there is none, it tries other voices of the same staff.
- The change of anchor is undoable.
- The fix corrects the management of the `Chord::_endsGlissando` flag, taking into account that a chord can be the ending point of several glissandi and removing one of them not necessarily means the chord no longer ends a glissando (another glissando may still exists).
- The fix also improved the rendering of the glissando wavy line, with better alignment with anchor notes and, with glissando text, better text-line spacing.
2015-08-06 11:11:16 +02:00
|
|
|
// used to store spanner properties as they were at start of editing
|
|
|
|
// and detect edit changes when edit is over
|
2013-09-27 11:18:30 +02:00
|
|
|
static int editTick, editTick2, editTrack2;
|
Fixes #19155, #22861 (duplicate of the former) and #23100.
__References__:
Issues: https://musescore.org/en/node/19155 https://musescore.org/en/node/22861 https://musescore.org/en/node/23100
__Description__:
Allows to change the start and end note to which a glissando is anchored after it has been entered. Either anchor can be changed independently.
The user interface follows the current working of other 'snappable' lines. Once either the start or end grip is selected:
- `[Shift]+[Left]` snaps the anchor to the previous chord, defaulting to its top note.
- `[Shift]+[Right]` snaps to the next chord, defaulting to its top note.
- `[Shift]+[Up]` snaps to the note above (possibly in a chord, voice or staff above the current one).
- `[Shift]+[Down]` snaps to the note below (possibly in a chord, voice or staff below the current one).
This permits to set the anchor points of a glissando to any note in the score, allowing several glissandi between the notes of the same two chords and other complex configurations (glissandi skipping intermediate chords, start and end notes in different voices or staves, and so on).
It is possible to move the anchor to a different staff of the same instrument, but not to a different instrument; also, it is not possible to 'cross' a change of instrument in the same staff.
__Known limitations__:
- The `[Shift]+[Up]` and `[Shift]+[Down]` use the same note-finding functions as the `[Alt]+[Up]` and `[Alt]+[Down]`actions which move the selection cursor to the above and below note, even across voices or staves. Occasionally, in particular if the note immediately above or below is not time-aligned, the algorithm has little expected results; however, the behaviour is already known to the user. Improving the algorithm would benefit both uses.
__Notes__:
- Most of the added infrastructure is not specific to glissando but to any spanner anchored to notes, then it should also add after-the-fact "snap to" note support to note-anchored text line.
- When moving an anchor, the algorithm usually prefers a note in the same voice/staff of the old note if it exists; if there is none, it tries other voices of the same staff.
- The change of anchor is undoable.
- The fix corrects the management of the `Chord::_endsGlissando` flag, taking into account that a chord can be the ending point of several glissandi and removing one of them not necessarily means the chord no longer ends a glissando (another glissando may still exists).
- The fix also improved the rendering of the glissando wavy line, with better alignment with anchor notes and, with glissando text, better text-line spacing.
2015-08-06 11:11:16 +02:00
|
|
|
static Note * editEndNote, * editStartNote;
|
2013-07-05 11:23:52 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
public:
|
2012-07-16 20:21:31 +02:00
|
|
|
Spanner(Score* = 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
Spanner(const Spanner&);
|
|
|
|
~Spanner();
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
virtual Element::Type type() const = 0;
|
2013-08-22 12:18:14 +02:00
|
|
|
virtual void setScore(Score* s) override;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-25 14:29:18 +02:00
|
|
|
int tick() const { return _tick; }
|
2014-08-13 15:42:40 +02:00
|
|
|
int tick2() const { return _tick + _ticks; }
|
|
|
|
int ticks() const { return _ticks; }
|
2015-01-19 12:37:17 +01:00
|
|
|
|
|
|
|
void setTick(int v);
|
|
|
|
void setTick2(int v);
|
|
|
|
void setTicks(int v);
|
|
|
|
|
2013-09-27 11:18:30 +02:00
|
|
|
int track2() const { return _track2; }
|
|
|
|
void setTrack2(int v) { _track2 = v; }
|
2013-06-25 14:29:18 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
Anchor anchor() const { return _anchor; }
|
|
|
|
void setAnchor(Anchor a) { _anchor = a; }
|
|
|
|
|
|
|
|
const QList<SpannerSegment*>& spannerSegments() const { return segments; }
|
|
|
|
QList<SpannerSegment*>& spannerSegments() { return segments; }
|
|
|
|
|
2013-08-22 12:18:14 +02:00
|
|
|
virtual void add(Element*) override;
|
|
|
|
virtual void remove(Element*) override;
|
|
|
|
virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true) override;
|
|
|
|
virtual void startEdit(MuseScoreView*, const QPointF&) override;
|
|
|
|
virtual void endEdit() override;
|
2012-05-26 14:26:10 +02:00
|
|
|
bool removeSpannerBack();
|
2015-03-10 11:38:27 +01:00
|
|
|
virtual void removeUnmanaged();
|
|
|
|
virtual void undoInsertTimeUnmanaged(int tick, int len);
|
2014-05-26 20:48:27 +02:00
|
|
|
virtual void setYoff(qreal) {} // used in musicxml import
|
2012-09-12 11:16:36 +02:00
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
QVariant getProperty(P_ID propertyId) const;
|
|
|
|
bool setProperty(P_ID propertyId, const QVariant& v);
|
|
|
|
QVariant propertyDefault(P_ID propertyId) const;
|
|
|
|
|
2013-06-16 23:33:37 +02:00
|
|
|
void computeStartElement();
|
|
|
|
void computeEndElement();
|
2015-02-28 09:57:46 +01:00
|
|
|
static Note* endElementFromSpanner(Spanner* sp, Element* newStart);
|
|
|
|
static Note* startElementFromSpanner(Spanner* sp, Element* newEnd);
|
|
|
|
void setNoteSpan(Note* startNote, Note* endNote);
|
2013-06-16 23:33:37 +02:00
|
|
|
|
|
|
|
Element* startElement() const { return _startElement; }
|
2013-06-19 16:25:29 +02:00
|
|
|
Element* endElement() const { return _endElement; }
|
|
|
|
|
2015-01-19 12:37:17 +01:00
|
|
|
Measure* startMeasure() const;
|
|
|
|
Measure* endMeasure() const;
|
|
|
|
|
2014-08-07 10:18:50 +02:00
|
|
|
void setStartElement(Element* e);
|
|
|
|
void setEndElement(Element* e);
|
2013-06-16 23:33:37 +02:00
|
|
|
|
2014-08-22 13:33:36 +02:00
|
|
|
ChordRest* startCR();
|
|
|
|
ChordRest* endCR();
|
2013-06-16 23:33:37 +02:00
|
|
|
|
2014-07-05 12:05:27 +02:00
|
|
|
Chord* startChord();
|
|
|
|
Chord* endChord();
|
2013-06-16 23:33:37 +02:00
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
Segment* startSegment() const;
|
|
|
|
Segment* endSegment() const;
|
2014-05-07 12:10:28 +02:00
|
|
|
|
|
|
|
virtual void setSelected(bool f) override;
|
|
|
|
virtual void setVisible(bool f) override;
|
2014-10-01 15:15:08 +02:00
|
|
|
virtual void setColor(const QColor& col) override;
|
2014-06-20 22:48:34 +02:00
|
|
|
virtual Element* nextElement() override;
|
|
|
|
virtual Element* prevElement() override;
|
2014-05-07 12:10:28 +02:00
|
|
|
|
2014-07-10 14:13:37 +02:00
|
|
|
virtual bool isSpanner() const override { return true; }
|
|
|
|
|
2014-05-07 12:10:28 +02:00
|
|
|
friend class SpannerSegment;
|
2013-06-10 11:03:34 +02:00
|
|
|
};
|
2013-05-13 18:49:17 +02:00
|
|
|
|
|
|
|
} // namespace Ms
|
|
|
|
|
2014-05-12 12:28:07 +02:00
|
|
|
Q_DECLARE_METATYPE(Ms::Spanner::Anchor);
|
2013-05-13 18:49:17 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
#endif
|
|
|
|
|