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 : #include "measurerepeat.h"
24 :
25 : #include "translation.h"
26 :
27 : #include "style/style.h"
28 :
29 : #include "measure.h"
30 : #include "staff.h"
31 :
32 : #include "log.h"
33 :
34 : using namespace mu;
35 : using namespace mu::engraving;
36 :
37 : namespace mu::engraving {
38 : //---------------------------------------------------------
39 : // MeasureRepeat
40 : //---------------------------------------------------------
41 :
42 134 : MeasureRepeat::MeasureRepeat(DummyParentOr<Segment> parent)
43 134 : : Rest(ElementType::MEASURE_REPEAT, parent), m_numMeasures(0)
44 : {
45 : // however many measures the group, the element itself is always exactly the duration of its containing measure
46 134 : setDurationType(DurationType::V_MEASURE);
47 134 : }
48 :
49 134 : void MeasureRepeat::setNumMeasures(int n)
50 : {
51 134 : IF_ASSERT_FAILED(n <= MAX_NUM_MEASURES) {
52 0 : m_numMeasures = MAX_NUM_MEASURES;
53 0 : return;
54 : }
55 :
56 134 : m_numMeasures = n;
57 : }
58 :
59 : //---------------------------------------------------------
60 : // firstMeasureOfGroup
61 : //---------------------------------------------------------
62 :
63 206 : Measure* MeasureRepeat::firstMeasureOfGroup() const
64 : {
65 206 : return measure()->firstOfMeasureRepeatGroup(staffIdx());
66 : }
67 :
68 118 : const Measure* MeasureRepeat::referringMeasure(const Measure* measure) const
69 : {
70 118 : IF_ASSERT_FAILED(measure) {
71 0 : return nullptr;
72 : }
73 :
74 118 : const Measure* firstMeasure = firstMeasureOfGroup();
75 118 : if (!firstMeasure) {
76 0 : return nullptr;
77 : }
78 :
79 118 : const Measure* referringMeasure = firstMeasure->prevMeasure();
80 :
81 118 : int measuresBack = m_numMeasures - measure->measureRepeatCount(staffIdx());
82 :
83 144 : for (int i = 0; i < measuresBack && referringMeasure; ++i) {
84 26 : referringMeasure = referringMeasure->prevMeasure();
85 : }
86 :
87 118 : return referringMeasure;
88 : }
89 :
90 : //---------------------------------------------------------
91 : // numberRect
92 : /// returns the measure repeat number's bounding rectangle
93 : //---------------------------------------------------------
94 :
95 1282 : PointF MeasureRepeat::numberPosition(const RectF& numberBbox) const
96 : {
97 1282 : double x = (symBbox(ldata()->symId).width() - numberBbox.width()) * .5;
98 : // -pos().y(): relative to topmost staff line
99 : // - 0.5 * r.height(): relative to the baseline of the number symbol
100 : // (rather than the center)
101 1282 : double staffTop = -pos().y();
102 : // Single line staff barlines extend above top of staff
103 1282 : if (staffType() && staffType()->lines() == 1) {
104 0 : staffTop -= 2.0 * spatium();
105 : }
106 1282 : double yNumberPos = absoluteFromSpatium(style().styleS(Sid::measureRepeatNumberPos) + m_numberOffset);
107 1282 : double y = std::min(staffTop, -symBbox(ldata()->symId).height() / 2) + yNumberPos - 0.5 * numberBbox.height();
108 :
109 1282 : return PointF(x, y);
110 : }
111 :
112 1282 : RectF MeasureRepeat::numberRect() const
113 : {
114 1282 : RectF r = symBbox(ldata()->numberSym);
115 1282 : r.translate(numberPosition(r));
116 1282 : return r;
117 : }
118 :
119 : //---------------------------------------------------------
120 : // propertyDefault
121 : //---------------------------------------------------------
122 :
123 1066 : PropertyValue MeasureRepeat::propertyDefault(Pid propertyId) const
124 : {
125 1066 : switch (propertyId) {
126 82 : case Pid::MEASURE_REPEAT_NUMBER_OFFSET:
127 82 : return 0.0_sp;
128 984 : default:
129 984 : return Rest::propertyDefault(propertyId);
130 : }
131 : }
132 :
133 : //---------------------------------------------------------
134 : // getProperty
135 : //---------------------------------------------------------
136 :
137 1066 : PropertyValue MeasureRepeat::getProperty(Pid propertyId) const
138 : {
139 1066 : switch (propertyId) {
140 82 : case Pid::SUBTYPE:
141 82 : return numMeasures();
142 82 : case Pid::MEASURE_REPEAT_NUMBER_OFFSET:
143 82 : return m_numberOffset;
144 902 : default:
145 902 : return Rest::getProperty(propertyId);
146 : }
147 : }
148 :
149 : //---------------------------------------------------------
150 : // setProperty
151 : //---------------------------------------------------------
152 :
153 0 : bool MeasureRepeat::setProperty(Pid propertyId, const PropertyValue& v)
154 : {
155 0 : switch (propertyId) {
156 0 : case Pid::SUBTYPE:
157 0 : setNumMeasures(v.toInt());
158 0 : break;
159 0 : case Pid::MEASURE_REPEAT_NUMBER_OFFSET:
160 0 : setNumberOffset(v.value<Spatium>());
161 0 : triggerLayout();
162 0 : break;
163 0 : default:
164 0 : return Rest::setProperty(propertyId, v);
165 : }
166 0 : return true;
167 : }
168 :
169 : //---------------------------------------------------------
170 : // ticks
171 : //---------------------------------------------------------
172 :
173 265 : Fraction MeasureRepeat::ticks() const
174 : {
175 265 : if (measure()) {
176 265 : return measure()->stretchedLen(staff());
177 : }
178 0 : return Fraction(0, 1);
179 : }
180 :
181 : //---------------------------------------------------------
182 : // accessibleInfo
183 : //---------------------------------------------------------
184 :
185 0 : String MeasureRepeat::accessibleInfo() const
186 : {
187 0 : return muse::mtrc("engraving", "%1; Duration: %Ln measure(s)", nullptr, numMeasures()).arg(EngravingItem::accessibleInfo());
188 : }
189 :
190 : //---------------------------------------------------------
191 : // subtypeUserName
192 : //---------------------------------------------------------
193 :
194 0 : muse::TranslatableString MeasureRepeat::subtypeUserName() const
195 : {
196 0 : return muse::TranslatableString("engraving", "%Ln measure(s)", nullptr, numMeasures());
197 : }
198 : }
|