Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <deque>
26 :
27 : #include "draw/types/color.h"
28 :
29 : #include "../types/types.h"
30 :
31 : #include "engravingitem.h"
32 :
33 : namespace mu::engraving {
34 : class Spanner;
35 :
36 : //---------------------------------------------------------
37 : // @@ SpannerSegment
38 : //! parent: the Spanner it belongs to; placed on a System during layout
39 : //---------------------------------------------------------
40 :
41 : class SpannerSegment : public EngravingItem
42 : {
43 0 : OBJECT_ALLOCATOR(engraving, SpannerSegment)
44 :
45 : public:
46 :
47 : ~SpannerSegment() override;
48 :
49 : virtual double mag() const override;
50 : virtual Fraction tick() const override;
51 :
52 : //! The spanner that owns this segment - derived from the ownership parent,
53 : //! so that it can never go stale.
54 470920 : Spanner* spanner() const { return toSpanner(ownershipParent()); }
55 : void setSpanner(Spanner* val);
56 :
57 13909 : void setSpannerSegmentType(SpannerSegmentType s) { m_spannerSegmentType = s; }
58 43683 : SpannerSegmentType spannerSegmentType() const { return m_spannerSegmentType; }
59 26499 : bool isSingleType() const { return spannerSegmentType() == SpannerSegmentType::SINGLE; }
60 2574 : bool isBeginType() const { return spannerSegmentType() == SpannerSegmentType::BEGIN; }
61 14463 : bool isSingleBeginType() const { return isSingleType() || isBeginType(); }
62 7571 : bool isSingleEndType() const { return isSingleType() || isEndType(); }
63 10 : bool isMiddleType() const { return spannerSegmentType() == SpannerSegmentType::MIDDLE; }
64 1072 : bool isEndType() const { return spannerSegmentType() == SpannerSegmentType::END; }
65 :
66 : int subtype() const override;
67 : TranslatableString subtypeUserName() const override;
68 :
69 : //! The system this segment is currently laid out on; null if not placed.
70 19519 : System* system() const { return m_system; }
71 : //! Records the placement only. Reserved for System itself, which maintains its own
72 : //! segment list; everyone else must use moveToSystem(), so that a non-null system()
73 : //! always implies that the segment is in that system's segment list - otherwise the
74 : //! pointer is left dangling when the system is destroyed.
75 11983 : void setSystem(System* s) { m_system = s; }
76 : //! Detach from the current system's segment list and attach to the given one.
77 : void moveToSystem(System* s);
78 : EngravingItem* layoutParent() const override;
79 : EngravingItem* accessibleParentItem() const override;
80 :
81 : //! A segment is owned by its spanner; a system merely places it, see
82 : //! setSystem()/moveToSystem(). This overload hides EngravingItem::setOwnershipParent,
83 : //! so that no other parent can be set by accident.
84 : void setOwnershipParent(Spanner* spanner);
85 :
86 1929 : const PointF& userOff2() const { return m_offset2; }
87 42 : void setUserOff2(const PointF& o) { m_offset2 = o; }
88 0 : void setUserXoffset2(double x) { m_offset2.setX(x); }
89 1252 : void setUserYoffset2(double y) { m_offset2.setY(y); }
90 : real_t& rUserXoffset2() { return m_offset2.rx(); }
91 : real_t& rUserYoffset2() { return m_offset2.ry(); }
92 :
93 5257 : void setPos2(const PointF& p) { m_p2 = p; }
94 : //TODO: rename to spanSegPosWithUserOffset()
95 9962 : PointF pos2() const { return m_p2 + m_offset2; }
96 : //TODO: rename to spanSegPos()
97 4602 : const PointF& ipos2() const { return m_p2; }
98 : PointF& rpos2() { return m_p2; }
99 137 : real_t& rxpos2() { return m_p2.rx(); }
100 2 : real_t& rypos2() { return m_p2.ry(); }
101 :
102 0 : bool isEditable() const override { return true; }
103 :
104 : muse::ByteArray mimeData(const PointF& dragOffset) const override;
105 :
106 : void spatiumChanged(double ov, double nv) override;
107 :
108 : PropertyValue getProperty(Pid id) const override;
109 : bool setProperty(Pid id, const PropertyValue& v) override;
110 : PropertyValue propertyDefault(Pid id) const override;
111 : virtual EngravingObject* propertyDelegate(Pid) const override;
112 : void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
113 : using EngravingObject::undoChangeProperty;
114 :
115 : PointF defaultPos() const override;
116 :
117 : Sid getPropertyStyle(Pid id) const override;
118 : void resetProperty(Pid id) override;
119 : void styleChanged() override;
120 : void reset() override;
121 :
122 : void setSelected(bool f) override;
123 : void setVisible(bool f) override;
124 : void setColor(const Color& col) override;
125 : void setZ(int val) override;
126 :
127 : bool collectForDrawing() const override;
128 :
129 : EngravingItem* nextSegmentElement() override;
130 : EngravingItem* prevSegmentElement() override;
131 : String accessibleInfo() const override;
132 : void triggerLayout() const override;
133 :
134 : std::list<EngravingObject*> linkListForPropertyPropagation() const override;
135 : bool isPropertyLinkedToMaster(Pid id) const override;
136 :
137 : virtual bool isUserModified() const override;
138 :
139 : bool allowTimeAnchor() const override;
140 :
141 : protected:
142 :
143 : SpannerSegment(const ElementType& type, Spanner*, ElementFlags f = ElementFlag::ON_STAFF | ElementFlag::MOVABLE);
144 : SpannerSegment(const SpannerSegment&);
145 :
146 : PointF m_p2;
147 : PointF m_offset2;
148 :
149 : private:
150 : String formatBarsAndBeats() const override;
151 : String formatStartBarsAndBeats(const Segment* segment) const;
152 : String formatEndBarsAndBeats(const Segment* segment) const;
153 :
154 : System* m_system = nullptr; // current layout placement; not owned, not copied
155 : SpannerSegmentType m_spannerSegmentType = SpannerSegmentType::SINGLE;
156 : };
157 :
158 : //----------------------------------------------------------------------------------
159 : // @@ Spanner
160 : /// Virtual base class for slurs, ties, lines etc.
161 : //
162 : // @P anchor enum (Spanner.CHORD, Spanner.MEASURE, Spanner.NOTE, Spanner.SEGMENT)
163 : // @P endElement EngravingItem the element the spanner end is anchored to (read-only)
164 : // @P startElement EngravingItem the element the spanner start is anchored to (read-only)
165 : // @P tick int tick start position
166 : // @P tick2 int tick end position
167 : //----------------------------------------------------------------------------------
168 :
169 : class Spanner : public EngravingItem
170 : {
171 0 : OBJECT_ALLOCATOR(engraving, Spanner)
172 : public:
173 : enum class Anchor : unsigned char {
174 : SEGMENT, MEASURE, CHORDREST, NOTE
175 : };
176 :
177 : ~Spanner() override;
178 :
179 : virtual double mag() const override;
180 :
181 : virtual void setScore(Score* s) override;
182 :
183 121912 : virtual Fraction tick() const override { return m_tick; }
184 50395 : Fraction tick2() const { return m_tick + m_ticks; }
185 4546 : Fraction ticks() const { return m_ticks; }
186 :
187 : void setTick(const Fraction&);
188 : void setTick2(const Fraction&);
189 : void setTicks(const Fraction&);
190 :
191 : bool isVoiceSpecific() const;
192 : track_idx_t track2() const;
193 : void setTrack2(track_idx_t v);
194 : track_idx_t effectiveTrack2() const;
195 :
196 905 : bool playSpanner() const { return m_playSpanner; }
197 1 : void setPlaySpanner(bool p) { m_playSpanner = p; }
198 :
199 : virtual Anchor anchor() const = 0;
200 :
201 22349 : const std::vector<SpannerSegment*>& spannerSegments() const { return m_segments; }
202 : void setSpannerSegments(const std::vector<SpannerSegment*>& s) { m_segments = s; }
203 4703 : SpannerSegment* frontSegment() { return m_segments.front(); }
204 130 : const SpannerSegment* frontSegment() const { return m_segments.front(); }
205 2089 : SpannerSegment* backSegment() { return m_segments.back(); }
206 105 : const SpannerSegment* backSegment() const { return m_segments.back(); }
207 6041 : SpannerSegment* segmentAt(int n) { return m_segments[n]; }
208 : const SpannerSegment* segmentAt(int n) const { return m_segments[n]; }
209 5912 : size_t nsegments() const { return m_segments.size(); }
210 10442 : bool segmentsEmpty() const { return m_segments.empty(); }
211 : void eraseSpannerSegments();
212 : bool eitherEndVisible() const;
213 :
214 : virtual void triggerLayout() const override;
215 : virtual void add(EngravingItem*) override;
216 : virtual void remove(EngravingItem*) override;
217 : virtual void removed() override;
218 : EngravingItemList accessibleChildren() const override;
219 77 : virtual void scanElements(std::function<void(EngravingItem*)>) override {}
220 : bool removeSpannerBack();
221 : virtual void removeUnmanaged();
222 : virtual void insertTimeUnmanaged(const Fraction& tick, const Fraction& len);
223 :
224 : PropertyValue getProperty(Pid propertyId) const override;
225 : bool setProperty(Pid propertyId, const PropertyValue& v) override;
226 : PropertyValue propertyDefault(Pid propertyId) const override;
227 :
228 : virtual void computeStartElement();
229 : void computeEndElement();
230 :
231 : static Note* endElementFromSpanner(Spanner* sp, EngravingItem* newStart);
232 : static Note* startElementFromSpanner(Spanner* sp, EngravingItem* newEnd);
233 : void setNoteSpan(Note* startNote, Note* endNote);
234 :
235 638307 : EngravingItem* startElement() const { return m_startElement; }
236 156786 : EngravingItem* endElement() const { return m_endElement; }
237 :
238 : Measure* startMeasure() const;
239 : Measure* endMeasure() const;
240 :
241 : Measure* findStartMeasure() const;
242 : Measure* findEndMeasure() const;
243 :
244 : void setStartElement(EngravingItem* e);
245 : virtual void setEndElement(EngravingItem* e);
246 :
247 : ChordRest* startCR();
248 : ChordRest* endCR();
249 :
250 : Chord* startChord();
251 : Chord* endChord();
252 :
253 : ChordRest* findStartCR() const;
254 : ChordRest* findEndCR() const;
255 :
256 : Chord* findStartChord() const;
257 : Chord* findEndChord() const;
258 :
259 : Segment* startSegment() const;
260 : Segment* endSegment() const;
261 :
262 : bool elementAppliesToTrack(const track_idx_t refTrack) const override;
263 :
264 : virtual void setSelected(bool f) override;
265 : virtual void setVisible(bool f) override;
266 : virtual void setAutoplace(bool f) override;
267 : virtual void setColor(const Color& col) override;
268 : virtual void setZ(int val) override;
269 : Spanner* nextSpanner(EngravingItem* e, staff_idx_t activeStaff);
270 : Spanner* prevSpanner(EngravingItem* e, staff_idx_t activeStaff);
271 : virtual EngravingItem* nextSegmentElement() override;
272 : virtual EngravingItem* prevSegmentElement() override;
273 :
274 : using EngravingObject::undoChangeProperty;
275 :
276 : void pushUnusedSegment(SpannerSegment* seg);
277 : SpannerSegment* popUnusedSegment();
278 : void reuse(SpannerSegment* seg); // called when segment from unusedSegments
279 : // is added back to the spanner.
280 : int reuseSegments(int number);
281 : void fixupSegments(unsigned int targetNumber, std::function<SpannerSegment* ()> createSegment);
282 :
283 : bool isUserModified() const override;
284 :
285 0 : virtual bool allowTimeAnchor() const override { return false; }
286 :
287 : protected:
288 :
289 2358 : Spanner(const ElementType& type, EngravingObject* parent, ElementFlags = ElementFlag::NOTHING);
290 : Spanner(const Spanner&);
291 :
292 : virtual void doComputeStartElement();
293 : virtual void doComputeEndElement();
294 :
295 3025 : virtual bool isInSpannerMap() const { return true; }
296 :
297 : private:
298 : bool canBeCrossStaff() const;
299 :
300 : friend class SpannerSegment;
301 :
302 : EngravingItem* m_startElement = nullptr;
303 : EngravingItem* m_endElement = nullptr;
304 :
305 : bool m_playSpanner = true;
306 :
307 : Fraction m_tick = Fraction(-1, 1);
308 : Fraction m_ticks = Fraction(0, 1);
309 : track_idx_t m_track2 = muse::nidx;
310 :
311 : std::vector<SpannerSegment*> m_segments;
312 : std::deque<SpannerSegment*> m_unusedSegments; // Currently unused segments which can be reused later.
313 : // We cannot just delete them as they can be referenced
314 : // in undo stack or other places already.
315 : };
316 : } // namespace mu::engraving
|