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 "draw/types/color.h"
26 : #include "draw/types/geometry.h"
27 :
28 : #include "modularity/ioc.h"
29 : #include "../rendering/paintoptions.h"
30 :
31 : #include "../infrastructure/ld_access.h"
32 : #include "../infrastructure/shape.h"
33 : #include "../infrastructure/skyline.h"
34 :
35 : #include "../types/fraction.h"
36 : #include "../types/symid.h"
37 : #include "../types/types.h"
38 :
39 : #include "engravingobject.h"
40 : #include "elementgroup.h"
41 :
42 : #include "../editing/editdata.h"
43 :
44 : namespace muse::draw {
45 : class Painter;
46 : }
47 :
48 : #define DECLARE_LAYOUTDATA_METHODS(Class) \
49 : const LayoutData* ldata() const { return static_cast<const Class::LayoutData*>(EngravingItem::ldata()); } \
50 : LayoutData* mutldata() { return static_cast<Class::LayoutData*>(EngravingItem::mutldata()); } \
51 : LayoutData* createLayoutData() const override { return new Class::LayoutData(); } \
52 :
53 : namespace mu::engraving::rendering {
54 : class IScoreRenderer;
55 : }
56 :
57 : namespace mu::engraving {
58 : class IEngravingConfiguration;
59 : class IEngravingContextConfiguration;
60 :
61 : class Transaction;
62 :
63 : template<typename T>
64 0 : inline void dump(const ld_field<T>& f, std::stringstream& ss)
65 : {
66 0 : if (f.has_value()) {
67 0 : dump(f.value(), ss);
68 : } else {
69 0 : ss << "no value";
70 : }
71 0 : }
72 :
73 : class Factory;
74 : class XmlReader;
75 :
76 : #ifndef ENGRAVING_NO_ACCESSIBILITY
77 : class AccessibleItem;
78 : typedef std::shared_ptr<AccessibleItem> AccessibleItemPtr;
79 : #endif
80 :
81 : enum class Pid : short;
82 : class StaffType;
83 :
84 : //---------------------------------------------------------
85 : // ElementFlag
86 : //---------------------------------------------------------
87 :
88 : enum class ElementFlag {
89 : NOTHING = 0x00000000,
90 : DROP_TARGET = 0x00000001,
91 : NOT_SELECTABLE = 0x00000002,
92 : MOVABLE = 0x00000004,
93 : COMPOSITION = 0x00000008, // true if element is part of another element
94 : ON_STAFF = 0x00000010,
95 : SELECTED = 0x00000020,
96 : GENERATED = 0x00000040,
97 : INVISIBLE = 0x00000080,
98 : NO_AUTOPLACE = 0x00000100,
99 : SYSTEM = 0x00000200,
100 : PLACE_ABOVE = 0x00000400,
101 : SIZE_SPATIUM_DEPENDENT = 0x00000800,
102 :
103 : // measure flags
104 : REPEAT_END = 0x00001000,
105 : REPEAT_START = 0x00002000,
106 : REPEAT_JUMP = 0x00004000,
107 : EXCLUDE_FROM_NUMBERING = 0x00008000,
108 : LINE_BREAK = 0x00010000,
109 : PAGE_BREAK = 0x00020000,
110 : SECTION_BREAK = 0x00040000,
111 : NO_BREAK = 0x00080000,
112 : HEADER = 0x00100000,
113 : TRAILER = 0x00200000, // also used in segment
114 : COURTESY_KEYSIG = 0x00400000,
115 : COURTESY_TIMESIG = 0x00800000,
116 : COURTESY_CLEF = 0x01000000,
117 :
118 : // segment flags
119 : ENABLED = 0x02000000, // used for segments
120 : EMPTY = 0x04000000,
121 : WRITTEN = 0x08000000,
122 : END_OF_MEASURE_CHANGE = 0x10000000,
123 : };
124 :
125 : typedef muse::Flags<ElementFlag> ElementFlags;
126 1284403 : DECLARE_OPERATORS_FOR_FLAGS(ElementFlags)
127 :
128 : enum class KerningType : unsigned char
129 : {
130 : KERNING,
131 : NON_KERNING,
132 : KERN_UNTIL_LEFT_EDGE,
133 : KERN_UNTIL_CENTER,
134 : KERN_UNTIL_RIGHT_EDGE,
135 : SAME_VOICE_LIMIT,
136 : ALLOW_COLLISION,
137 : };
138 :
139 : //-------------------------------------------------------------------
140 : // @@ EngravingItem
141 : /// \brief Base class of score layout elements
142 : ///
143 : /// The EngravingItem class is the virtual base class of all
144 : /// score layout elements.
145 : //-------------------------------------------------------------------
146 :
147 : class EngravingItem : public EngravingObject
148 : {
149 8 : M_PROPERTY2(bool, isPositionLinkedToMaster, setPositionLinkedToMaster, true)
150 43 : M_PROPERTY2(bool, isAppearanceLinkedToMaster, setAppearanceLinkedToMaster, true)
151 4799 : M_PROPERTY2(bool, excludeFromOtherParts, setExcludeFromOtherParts, false)
152 :
153 : public:
154 :
155 : virtual ~EngravingItem();
156 :
157 : EngravingItem& operator=(const EngravingItem&) = delete;
158 :
159 : virtual EngravingItem* clone() const = 0;
160 : virtual EngravingItem* linkedClone();
161 :
162 : void deleteLater();
163 :
164 : //! Item-typed variant of ownershipParent(); additionally null when the
165 : //! owner is not an item.
166 : EngravingItem* ownershipParentItem() const;
167 :
168 : //! The parent in the visual hierarchy, which positions are relative to.
169 : //! Defaults to the owner; overridden where placement differs from ownership
170 : //! (e.g. measures are placed on systems, but not owned by them).
171 : virtual EngravingItem* layoutParent() const;
172 :
173 : const std::shared_ptr<IEngravingConfiguration>& configuration() const;
174 : const muse::modularity::ContextPtr& iocContext() const;
175 : const std::shared_ptr<IEngravingContextConfiguration>& contextConfiguration() const;
176 : const std::shared_ptr<rendering::IScoreRenderer>& renderer() const;
177 :
178 : EngravingItem* findAncestor(ElementType t);
179 : const EngravingItem* findAncestor(ElementType t) const;
180 :
181 : Measure* findMeasure();
182 : const Measure* findMeasure() const;
183 : MeasureBase* findMeasureBase();
184 : const MeasureBase* findMeasureBase() const;
185 :
186 : //!Note muse::Returns basic representative for the current element.
187 : //! For example: notes->chord, chords->beam, etc.
188 0 : virtual EngravingItem* elementBase() const { return const_cast<EngravingItem*>(this); }
189 :
190 16859628 : virtual bool isEngravingItem() const override { return true; }
191 :
192 : double spatium() const;
193 : double defaultSpatium() const;
194 :
195 2361431 : inline void setFlag(ElementFlag f, bool v)
196 : {
197 2361431 : if (v) {
198 937325 : m_flags |= f;
199 : } else {
200 1424106 : m_flags &= ~ElementFlags(f);
201 : }
202 2361431 : }
203 :
204 355017 : inline void setFlag(ElementFlag f, bool v) const
205 : {
206 355017 : if (v) {
207 41275 : m_flags |= f;
208 : } else {
209 313742 : m_flags &= ~ElementFlags(f);
210 : }
211 355017 : }
212 :
213 22989051 : inline bool flag(ElementFlag f) const { return m_flags & f; }
214 :
215 : bool selected() const;
216 : virtual void setSelected(bool f);
217 :
218 5621277 : bool visible() const { return !flag(ElementFlag::INVISIBLE); }
219 : virtual void setVisible(bool f);
220 :
221 : virtual bool isInteractionAvailable() const;
222 :
223 314463 : bool sizeIsSpatiumDependent() const override { return !flag(ElementFlag::SIZE_SPATIUM_DEPENDENT); }
224 45030 : void setSizeIsSpatiumDependent(bool v) { setFlag(ElementFlag::SIZE_SPATIUM_DEPENDENT, !v); }
225 : bool offsetIsSpatiumDependent() const override;
226 :
227 : virtual PointF defaultPos() const;
228 : virtual Sid defaultPosSid() const;
229 :
230 : PlacementV placement() const;
231 17972 : void setPlacement(PlacementV val) { setFlag(ElementFlag::PLACE_ABOVE, !bool(val)); }
232 109678 : bool placeAbove() const { return placement() == PlacementV::ABOVE; }
233 42147 : bool placeBelow() const { return placement() == PlacementV::BELOW; }
234 0 : virtual bool placeMultiple() const { return true; }
235 :
236 705804 : bool generated() const { return flag(ElementFlag::GENERATED); }
237 104532 : void setGenerated(bool val) { setFlag(ElementFlag::GENERATED, val); }
238 :
239 18717 : Spatium minDistance() const { return m_minDistance; }
240 14779 : void setMinDistance(Spatium v) { m_minDistance = v; }
241 :
242 : PointF systemPos() const;
243 : virtual PointF pagePos() const; ///< position in page coordinates
244 : virtual PointF canvasPos() const; ///< position in canvas coordinates
245 : double pageX() const;
246 : double canvasX() const;
247 :
248 0 : PointF mapFromCanvas(const PointF& p) const { return p - canvasPos(); }
249 : PointF mapToCanvas(const PointF& p) const { return p + canvasPos(); }
250 :
251 270816 : const PointF& offset() const { return m_offset; }
252 3052 : virtual void setOffset(const PointF& o) { m_offset = o; }
253 0 : void setOffset(double x, double y) { m_offset.setX(x), m_offset.setY(y); }
254 0 : PointF& roffset() { return m_offset; }
255 1399 : real_t& rxoffset() { return m_offset.rx(); }
256 27 : real_t& ryoffset() { return m_offset.ry(); }
257 :
258 : virtual Fraction tick() const;
259 : virtual Fraction rtick() const;
260 :
261 : Fraction beat() const;
262 :
263 66 : bool isNudged() const { return !m_offset.isNull(); }
264 :
265 : bool contains(const PointF& p) const;
266 : bool intersects(const RectF& r) const;
267 :
268 0 : virtual RectF hitBBox() const { return ldata()->bbox(); }
269 0 : virtual Shape hitShape() const { return shape(); }
270 0 : Shape canvasHitShape() const { return hitShape().translate(canvasPos()); }
271 : bool hitShapeContains(const PointF& p) const;
272 : bool hitShapeIntersects(const RectF& rr) const;
273 :
274 0 : virtual int subtype() const { return -1; } // for select gui
275 :
276 : // virtual ElementGroup getElementGroup() { return SingleElementGroup(this); }
277 0 : virtual std::unique_ptr<ElementGroup> getDragGroup(std::function<bool(const EngravingItem*)> /*isDragged*/)
278 : {
279 0 : return std::unique_ptr<ElementGroup>(new SingleElementGroup(this));
280 : }
281 :
282 : virtual void startDrag(EditData&);
283 : virtual RectF drag(EditData&);
284 : virtual void endDrag(EditData&);
285 : /** muse::Returns anchor lines displayed while dragging element in canvas coordinates. */
286 0 : virtual std::vector<LineF> dragAnchorLines() const { return std::vector<LineF>(); }
287 : /**
288 : * A generic \ref dragAnchorLines() implementation which can be used in
289 : * dragAnchorLines() overrides in descendants. It is not made its default
290 : * implementation in EngravingItem class since showing anchor lines is not
291 : * desirable for most element types.
292 : * TODO: maybe Annotation class could be extracted which would be a base
293 : * class of various annotation types and which would have this
294 : * dragAnchorLines() implementation by default.
295 : */
296 : std::vector<LineF> genericDragAnchorLines() const;
297 :
298 0 : virtual bool isEditable() const { return !flag(ElementFlag::GENERATED); }
299 0 : virtual bool needStartEditingAfterSelecting() const { return false; }
300 :
301 : virtual void startEdit(EditData&);
302 : virtual bool isEditAllowed(EditData&) const;
303 : virtual bool edit(EditData&);
304 : virtual void startDragGrip(EditData&);
305 : virtual void dragGrip(EditData&);
306 : virtual void endDragGrip(EditData&);
307 : virtual void endEdit(EditData&);
308 :
309 0 : virtual void editCut(EditData&) {}
310 0 : virtual void editCopy(EditData&) {}
311 :
312 : void updateGrips(EditData&) const;
313 : virtual bool nextGrip(EditData&) const;
314 : virtual bool prevGrip(EditData&) const;
315 : /** muse::Returns anchor lines displayed while dragging element's grip in canvas coordinates. */
316 0 : virtual std::vector<LineF> gripAnchorLines(Grip) const { return std::vector<LineF>(); }
317 :
318 0 : virtual int gripsCount() const { return 0; }
319 0 : virtual Grip initialEditModeGrip() const { return Grip::NO_GRIP; }
320 0 : virtual Grip defaultGrip() const { return Grip::NO_GRIP; }
321 : /** muse::Returns grips positions in page coordinates. */
322 0 : virtual std::vector<PointF> gripsPositions(const EditData& = EditData()) const { return std::vector<PointF>(); }
323 :
324 : bool hasGrips() const;
325 :
326 : track_idx_t track() const;
327 : virtual void setTrack(track_idx_t val);
328 :
329 : int z() const;
330 : virtual void setZ(int val);
331 :
332 : staff_idx_t staffIdx() const;
333 : void setStaffIdx(staff_idx_t val);
334 : virtual staff_idx_t effectiveStaffIdx() const; // for system objects migrating
335 : bool isTopSystemObject() const;
336 : virtual staff_idx_t vStaffIdx() const;
337 : voice_idx_t voice() const;
338 : void setVoice(voice_idx_t v);
339 : Staff* staff() const;
340 : bool hasStaff() const;
341 : const StaffType* staffType() const;
342 : bool onTabStaff() const;
343 : Part* part() const;
344 : Part* originPart() const; // Delegates to an origin part for items in shared parts
345 :
346 : virtual void add(EngravingItem*);
347 : virtual void remove(EngravingItem*);
348 306400 : virtual void added() {}
349 15386 : virtual void removed() {}
350 : virtual void change(EngravingItem* o, EngravingItem* n);
351 :
352 : virtual void spatiumChanged(double /*oldValue*/, double /*newValue*/);
353 : virtual void localSpatiumChanged(double /*oldValue*/, double /*newValue*/);
354 :
355 : // debug functions
356 : virtual void dump() const;
357 : virtual TranslatableString subtypeUserName() const;
358 : virtual String translatedSubtypeUserName() const;
359 :
360 : virtual void setColor(const Color& c);
361 : virtual Color color() const;
362 : virtual Color curColor(const rendering::PaintOptions& opt) const;
363 : Color curColor(bool isVisible, const rendering::PaintOptions& opt) const;
364 : Color curColor(bool isVisible, Color normalColor, const rendering::PaintOptions& opt) const;
365 :
366 : void undoSetVisible(bool v);
367 : void undoAddElement(EngravingItem* element, bool addToLinkedStaves = true);
368 :
369 : static ElementType readType(XmlReader& node, PointF*, Fraction*);
370 : static EngravingItem* readMimeData(Score* score, const muse::ByteArray& data, PointF*, Fraction*);
371 :
372 : virtual muse::ByteArray mimeData(const PointF& dragOffset = PointF()) const;
373 : /**
374 : muse::Return true if this element accepts a drop at canvas relative \a pos
375 : of given element \a type and \a subtype.
376 :
377 : Reimplemented by elements that accept drops. Used to change cursor shape while
378 : dragging to indicate drop targets.
379 : */
380 2 : virtual bool acceptDrop(EditData&) const { return false; }
381 :
382 : /**
383 : Handle a dropped element at canvas relative \a pos of given element
384 : \a type and \a subtype. muse::Returns dropped element if any.
385 : The ownership of element in DropData is transferred to the called
386 : element (if not used, element has to be deleted).
387 : The returned element will be selected if not in note edit mode.
388 :
389 : Reimplemented by elements that accept drops.
390 : */
391 0 : virtual EngravingItem* drop(Transaction&, EditData&) { return 0; }
392 :
393 : mutable bool itemDiscovered = false; // helper flag for bsp
394 :
395 : void scanElements(std::function<void(EngravingItem*)> func) override;
396 : virtual bool collectForDrawing() const;
397 :
398 : virtual void reset() override; // reset all properties & position to default
399 :
400 : double magS() const;
401 :
402 : bool isPrintable() const;
403 : virtual bool isPlayable() const;
404 817336 : virtual double absoluteFromSpatium(const Spatium& sp) const { return sp.val() * spatium(); }
405 :
406 10547388 : bool systemFlag() const { return flag(ElementFlag::SYSTEM); }
407 27138 : void setSystemFlag(bool v) const { setFlag(ElementFlag::SYSTEM, v); }
408 :
409 : virtual bool isSystemObjectBelowBottomStaff() const;
410 :
411 211915 : bool header() const { return flag(ElementFlag::HEADER); }
412 70546 : void setHeader(bool v) { setFlag(ElementFlag::HEADER, v); }
413 :
414 314756 : bool trailer() const { return flag(ElementFlag::TRAILER); }
415 3800 : void setTrailer(bool val) { setFlag(ElementFlag::TRAILER, val); }
416 :
417 72 : bool selectable() const { return !flag(ElementFlag::NOT_SELECTABLE); }
418 226701 : void setSelectable(bool val) { setFlag(ElementFlag::NOT_SELECTABLE, !val); }
419 :
420 0 : bool dropTarget() const { return flag(ElementFlag::DROP_TARGET); }
421 5852 : void setDropTarget(bool v) const { setFlag(ElementFlag::DROP_TARGET, v); }
422 :
423 288141 : bool composition() const { return flag(ElementFlag::COMPOSITION); }
424 794 : void setComposition(bool v) const { setFlag(ElementFlag::COMPOSITION, v); }
425 :
426 0 : virtual bool isMovable() const { return flag(ElementFlag::MOVABLE); }
427 :
428 2270935 : bool enabled() const { return flag(ElementFlag::ENABLED); }
429 107724 : void setEnabled(bool val) { setFlag(ElementFlag::ENABLED, val); }
430 :
431 : bool autoplace() const;
432 2150 : virtual void setAutoplace(bool v) { setFlag(ElementFlag::NO_AUTOPLACE, !v); }
433 1149705 : bool addToSkyline() const { return !(m_flags & (ElementFlag::INVISIBLE | ElementFlag::NO_AUTOPLACE)) && !ldata()->isSkipDraw(); }
434 :
435 1406 : bool excludeVerticalAlign() const { return m_excludeVerticalAlign; }
436 0 : void setExcludeVerticalAlign(bool v) { m_excludeVerticalAlign = v; }
437 :
438 : PropertyValue getProperty(Pid) const override;
439 : bool setProperty(Pid, const PropertyValue&) override;
440 : void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
441 : using EngravingObject::undoChangeProperty;
442 : PropertyValue propertyDefault(Pid) const override;
443 :
444 : bool custom(Pid) const;
445 : virtual bool isUserModified() const;
446 :
447 : void drawSymbol(SymId id, muse::draw::Painter* p, const PointF& o = PointF(), double scale = 1.0) const;
448 : void drawSymbols(const SymIdList&, muse::draw::Painter* p, const PointF& o = PointF(), double scale = 1.0) const;
449 : void drawSymbols(const SymIdList&, muse::draw::Painter* p, const PointF& o, const SizeF& scale) const;
450 : double symHeight(SymId id) const;
451 : double symWidth(SymId id) const;
452 : double symWidth(const SymIdList&) const;
453 : RectF symBbox(SymId id) const;
454 : RectF symBbox(const SymIdList&) const;
455 : virtual Shape symShapeWithCutouts(SymId id) const;
456 :
457 : PointF symSmuflAnchor(SymId symId, SmuflAnchorId anchorId) const;
458 :
459 : double symAdvance(SymId id) const;
460 : bool symIsValid(SymId id) const;
461 :
462 : bool concertPitch() const;
463 : virtual EngravingItem* nextElement(); // selects the next score element, (notes, rests etc. as well as articulation etc.)
464 : virtual EngravingItem* prevElement(); // selects the next score element, (notes, rests etc. as well as articulation etc.)
465 : virtual EngravingItem* nextSegmentElement(); //< Used for navigation
466 : virtual EngravingItem* prevSegmentElement(); //< next-element and prev-element command
467 :
468 : #ifndef ENGRAVING_NO_ACCESSIBILITY
469 : virtual void setupAccessible();
470 : AccessibleItemPtr accessible() const;
471 : void initAccessibleIfNeed();
472 : #endif
473 :
474 : bool accessibleEnabled() const;
475 : void setAccessibleEnabled(bool enabled);
476 :
477 : //! Parent in the accessibility hierarchy: the layout parent when placed; the head of
478 : //! the tree the unattached objects form when attached to nothing; null in between,
479 : //! i.e. while attached to something that does not place it.
480 : virtual EngravingItem* accessibleParentItem() const;
481 : //! Children in the accessibility hierarchy: the items that name this one as their
482 : //! accessibleParentItem(). Those are the children it owns, unless ownership and
483 : //! placement diverge, in which case the item that places them lists them instead.
484 : virtual EngravingItemList accessibleChildren() const;
485 :
486 : virtual String accessibleInfo() const;
487 0 : virtual String screenReaderInfo() const { return accessibleInfo(); }
488 : // if the screen-reader needs a special string (see note for example)
489 : // used to return info that will be appended to accessibleInfo
490 0 : virtual String accessibleExtraInfo() const { return String(); }
491 : virtual String formatBarsAndBeats() const;
492 :
493 : virtual void triggerLayout() const;
494 : virtual void triggerLayoutAll() const;
495 : virtual void triggerLayoutToEnd() const;
496 :
497 : double styleP(Sid idx) const;
498 :
499 : virtual void setParenthesesMode(const ParenthesesMode& v, bool addToLinked = true, bool generated = false);
500 : ParenthesesMode parenthesesMode() const;
501 80 : inline Parenthesis* paren(const DirectionH& dir) const { return dir == DirectionH::LEFT ? m_leftParenthesis : m_rightParenthesis; }
502 3361699 : Parenthesis* leftParen() const { return m_leftParenthesis; }
503 3361699 : Parenthesis* rightParen() const { return m_rightParenthesis; }
504 : void setLeftParen(Parenthesis* paren) { m_leftParenthesis = paren; }
505 : void setRightParen(Parenthesis* paren) { m_rightParenthesis = paren; }
506 :
507 : struct BarBeat
508 : {
509 : int bar = 0;
510 : int displayedBar = 0;
511 : double beat = 0.0;
512 : };
513 : BarBeat barbeat() const;
514 :
515 : virtual EngravingItem* findLinkedInScore(const Score* score) const;
516 : EngravingItem* findLinkedInStaff(const Staff* staff) const;
517 :
518 : struct LayoutData {
519 749526 : virtual ~LayoutData() = default;
520 :
521 593175 : virtual void reset()
522 : {
523 593175 : m_shape.reset();
524 593175 : m_mask.reset();
525 : //! NOTE Temporary removed, have problems, need investigation
526 : //m_pos.reset();
527 593175 : }
528 :
529 652740 : virtual bool isValid() const { return m_shape.has_value() && m_shape.value().bbox().isValid(); }
530 :
531 1203570 : bool isSkipDraw() const { return m_isSkipDraw; }
532 198960 : void setIsSkipDraw(bool val) { m_isSkipDraw = val; }
533 :
534 5256637 : double mag() const { return m_mag; }
535 682675 : void setMag(double val) { m_mag = val; }
536 :
537 118604 : bool isSetPos() const { return m_pos.has_value(); }
538 11586265 : const PointF& pos(LD_ACCESS mode = LD_ACCESS::CHECK) const
539 : {
540 : //! NOTE Temporarily to mute a lot of messages
541 11586265 : mode = (LD_ACCESS::CHECK == mode) ? LD_ACCESS::MAYBE_NOTINITED : mode;
542 11586265 : return m_pos.value(mode);
543 : }
544 :
545 195650 : void setPos(const PointF& p) { doSetPos(p.x(), p.y()); }
546 312767 : void setPos(double x, double y) { doSetPos(x, y); }
547 1238015 : void setPosX(double x) { doSetPos(x, pos(LD_ACCESS::MAYBE_NOTINITED).y()); }
548 511314 : void setPosY(double y) { doSetPos(pos(LD_ACCESS::MAYBE_NOTINITED).x(), y); }
549 76606 : void move(const PointF& p) { doSetPos(pos(LD_ACCESS::MAYBE_NOTINITED).x() + p.x(), pos(LD_ACCESS::MAYBE_NOTINITED).y() + p.y()); }
550 157217 : void moveX(double x) { doSetPos(pos(LD_ACCESS::MAYBE_NOTINITED).x() + x, pos(LD_ACCESS::MAYBE_NOTINITED).y()); }
551 46703 : void moveY(double y) { doSetPos(pos(LD_ACCESS::MAYBE_NOTINITED).x(), pos(LD_ACCESS::MAYBE_NOTINITED).y() + y); }
552 :
553 83962 : bool isSetBbox() const { return m_shape.has_value(); }
554 57 : void clearBbox() { m_shape.reset(); }
555 : const RectF& bbox(LD_ACCESS mode = LD_ACCESS::CHECK) const;
556 :
557 246252 : bool isSetShape() const { return m_shape.has_value(); }
558 : void clearShape() { m_shape.reset(); }
559 : Shape shape(LD_ACCESS mode = LD_ACCESS::CHECK) const;
560 :
561 1074553 : void setShape(const Shape& sh) { m_shape.set_value(sh); }
562 :
563 : void setBbox(const RectF& r);
564 :
565 346117 : void setBbox(double x, double y, double w, double h) { setBbox(RectF(x, y, w, h)); }
566 0 : void addBbox(const RectF& r)
567 : {
568 0 : DO_ASSERT(!std::isnan(r.x()) && !std::isinf(r.x()));
569 0 : DO_ASSERT(!std::isnan(r.y()) && !std::isinf(r.y()));
570 0 : DO_ASSERT(!std::isnan(r.width()) && !std::isinf(r.width()));
571 0 : DO_ASSERT(!std::isnan(r.height()) && !std::isinf(r.height()));
572 :
573 : //DO_ASSERT(!isShapeComposite());
574 0 : mutShape().addBBox(r);
575 0 : }
576 :
577 51345 : void setHeight(double v)
578 : {
579 51345 : RectF r = bbox();
580 51345 : r.setHeight(v);
581 51345 : setBbox(r);
582 51345 : }
583 :
584 778731 : void setWidth(double v)
585 : {
586 : #ifndef NDEBUG
587 778731 : setWidthDebugHook(v);
588 : #endif
589 778731 : RectF r = bbox();
590 778731 : r.setWidth(v);
591 778731 : setBbox(r);
592 778731 : }
593 :
594 14163 : void setMask(const Shape& m) { m_mask.set_value(m); }
595 50 : const Shape& mask() const { return m_mask.value(); }
596 :
597 : void connectItemSnappedBefore(EngravingItem* itemBefore);
598 : void disconnectItemSnappedBefore();
599 : void connectItemSnappedAfter(EngravingItem* itemAfter);
600 : void disconnectItemSnappedAfter();
601 2880 : void disconnectSnappedItems() { disconnectItemSnappedBefore(); disconnectItemSnappedAfter(); }
602 391833 : EngravingItem* itemSnappedBefore() const { return m_itemSnappedBefore; }
603 391996 : EngravingItem* itemSnappedAfter() const { return m_itemSnappedAfter; }
604 : void scanConnectedItemsInSnappingChain(const System* system, const std::function<void(EngravingItem*)>& func) const;
605 :
606 : void dump(std::stringstream& ss) const;
607 :
608 : protected:
609 :
610 0 : virtual void supDump(std::stringstream& ss) const { UNUSED(ss); }
611 :
612 : #ifndef NDEBUG
613 : void doSetPosDebugHook(double x, double y);
614 : void setWidthDebugHook(double w);
615 : #endif
616 :
617 2538272 : inline void doSetPos(double x, double y)
618 : {
619 : #ifndef NDEBUG
620 2538272 : doSetPosDebugHook(x, y);
621 : #endif
622 2538272 : m_pos.mut_value().setX(x),
623 2538272 : m_pos.mut_value().setY(y);
624 2538272 : }
625 :
626 0 : Shape& mutShape() { return m_shape.mut_value(); }
627 : bool isShapeComposite() const { return m_shape.has_value() && m_shape.value().isComposite(); }
628 :
629 : friend class EngravingItem;
630 :
631 : const EngravingItem* m_item = nullptr;
632 : bool m_isSkipDraw = false;
633 : double m_mag = 1.0; // standard magnification (derived value)
634 : ld_field<PointF> m_pos = "pos"; // Reference position, relative to _parent, set by autoplace
635 : ld_field<Shape> m_shape = "shape";
636 : ld_field<Shape> m_mask = "mask";
637 :
638 : EngravingItem* m_itemSnappedBefore = nullptr;
639 : EngravingItem* m_itemSnappedAfter = nullptr;
640 :
641 : // STAVE SHARING
642 : EngravingItem* m_sharedItem = nullptr;
643 : std::vector<EngravingItem*> m_originItems;
644 : };
645 :
646 : const LayoutData* ldata() const;
647 : LayoutData* mutldata();
648 :
649 : virtual double mag() const;
650 2875719 : Shape shape(LD_ACCESS mode = LD_ACCESS::CHECK) const { return ldata()->shape(mode); }
651 0 : virtual double baseLine() const { return -height(); }
652 :
653 21105 : RectF pageBoundingRect(LD_ACCESS mode = LD_ACCESS::CHECK) const { return ldata()->bbox(mode).translated(pagePos()); }
654 26702 : RectF canvasBoundingRect(LD_ACCESS mode = LD_ACCESS::CHECK) const { return ldata()->bbox(mode).translated(canvasPos()); }
655 :
656 : virtual PointF staffOffset() const;
657 51732 : double staffOffsetY() const { return staffOffset().y(); }
658 :
659 : virtual bool isPropertyLinkedToMaster(Pid id) const;
660 : virtual bool isUnlinkedFromMaster() const;
661 : void unlinkPropertyFromMaster(Pid id);
662 : void relinkPropertiesToMaster(PropertyGroup propGroup);
663 : void relinkPropertyToMaster(Pid propertyId);
664 : PropertyPropagation propertyPropagation(const EngravingItem* destinationItem, Pid propertyId) const;
665 0 : virtual bool canBeExcludedFromOtherParts() const { return false; }
666 : virtual void manageExclusionFromParts(bool exclude);
667 :
668 : EngravingItem* sharedItem() const;
669 : const std::vector<EngravingItem*>& originItems() const;
670 : static void connectSharedItem(EngravingItem* sharedItem, EngravingItem* originItem);
671 : static void disconnectSharedItem(EngravingItem* sharedItem, EngravingItem* originItem);
672 : static void disconnectAllOriginItems(EngravingItem* sharedItem);
673 : static void disconnectSharedTree(EngravingItem* item);
674 :
675 : virtual bool isBefore(const EngravingItem* item) const;
676 :
677 : /** The staff this item would be centered against if it were centered between staves, or
678 : * nullptr if there is none. `system` limits the search to the staves visible on that
679 : * system; if null, the system this item is laid out on is used.
680 : */
681 : const Staff* staffToCenterAgainst(bool above, const System* system = nullptr) const;
682 :
683 : //! --- Old Interface ---
684 8180 : void setbbox(const RectF& r) { mutldata()->setBbox(r); }
685 90325 : double height() const { return ldata()->bbox().height(); }
686 49841 : void setHeight(double v) { mutldata()->setHeight(v); }
687 :
688 1311840 : double width(LD_ACCESS mode = LD_ACCESS::CHECK) const { return ldata()->bbox(mode).width(); }
689 778731 : void setWidth(double v) { mutldata()->setWidth(v); }
690 :
691 4509636 : virtual const PointF pos() const { return ldata()->pos() + m_offset; }
692 2261359 : virtual double x() const { return ldata()->pos().x() + m_offset.x(); }
693 1075462 : virtual double y() const { return ldata()->pos().y() + m_offset.y(); }
694 246665 : virtual void setPos(double x, double y) { mutldata()->setPos(x, y); }
695 53496 : virtual void setPos(const PointF& p) { mutldata()->setPos(p.x(), p.y()); }
696 :
697 2556 : virtual void move(const PointF& s) { mutldata()->move(s); }
698 :
699 0 : virtual bool allowTimeAnchor() const { return false; }
700 :
701 79460 : virtual bool hasVoiceAssignmentProperties() const { return false; }
702 : bool appliesToAllVoicesInInstrument() const;
703 : void setInitialTrackAndVoiceAssignment(track_idx_t track, bool curVoiceOnlyOverride);
704 : void checkVoiceAssignmentCompatibleWithTrack();
705 : virtual bool elementAppliesToTrack(const track_idx_t refTrack) const;
706 : void setPlacementBasedOnVoiceAssignment(DirectionV styledDirection);
707 : //! ---------------------
708 :
709 : protected:
710 189440 : EngravingItem(const ElementType& type, EngravingObject* parent = nullptr, ElementFlags = ElementFlag::NOTHING);
711 : EngravingItem(const EngravingItem&, bool link = false);
712 :
713 : #ifndef ENGRAVING_NO_ACCESSIBILITY
714 : virtual AccessibleItemPtr createAccessible();
715 : void notifyAboutNameChanged();
716 : #endif
717 :
718 : virtual LayoutData* createLayoutData() const;
719 : virtual const LayoutData* ldataInternal() const;
720 : virtual LayoutData* mutldataInternal();
721 :
722 : mutable int m_z = 0;
723 : Color m_color; // element color attribute
724 :
725 : track_idx_t m_track = muse::nidx; // staffIdx * VOICES + voice
726 :
727 : static bool elementAppliesToTrack(const track_idx_t elementTrack, const track_idx_t refTrack, const VoiceAssignment voiceAssignment,
728 : const Part* part);
729 :
730 : private:
731 :
732 : friend class Factory;
733 :
734 : #ifndef ENGRAVING_NO_ACCESSIBILITY
735 : void doInitAccessible();
736 : AccessibleItemPtr m_accessible;
737 : #endif
738 :
739 : bool m_accessibleEnabled = false;
740 :
741 : PointF m_offset; // offset from reference position, set by autoplace or user
742 :
743 : Spatium m_minDistance; // autoplace min distance
744 : mutable ElementFlags m_flags;
745 :
746 : bool m_excludeVerticalAlign = false;
747 :
748 : mutable LayoutData* m_layoutData = nullptr;
749 :
750 : Parenthesis* m_leftParenthesis = nullptr;
751 : Parenthesis* m_rightParenthesis = nullptr;
752 : void setHasLeftParenthesis(bool v, bool addToLinked = true, bool generated = false);
753 : void setHasRightParenthesis(bool v, bool addToLinked = true, bool generated = false);
754 : };
755 :
756 : using ElementPtr = std::shared_ptr<EngravingItem>;
757 :
758 : //---------------------------------------------------------
759 : // ElementList
760 : //---------------------------------------------------------
761 :
762 : class ElementList : public std::vector<EngravingItem*>
763 : {
764 : OBJECT_ALLOCATOR(engraving, ElementList)
765 : public:
766 145547 : ElementList() {}
767 : bool remove(EngravingItem*);
768 : void replace(EngravingItem* old, EngravingItem* n);
769 : };
770 :
771 : extern bool elementLessThan(const EngravingItem* const, const EngravingItem* const);
772 : } // mu::engraving
773 :
774 : #ifndef NO_QT_SUPPORT
775 0 : Q_DECLARE_METATYPE(mu::engraving::ElementPtr)
776 0 : Q_DECLARE_METATYPE(mu::engraving::ElementType)
777 : #endif
|