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 : #include "textline.h"
23 :
24 : #include "score.h"
25 : #include "system.h"
26 : #include "text.h"
27 : #include "../editing/editproperty.h"
28 :
29 : using namespace mu;
30 :
31 : namespace mu::engraving {
32 : //---------------------------------------------------------
33 : // textLineSegmentStyle
34 : //---------------------------------------------------------
35 :
36 : static const ElementStyle textLineSegmentStyle {
37 : { Sid::textLineMinDistance, Pid::MIN_DISTANCE },
38 : };
39 :
40 : //---------------------------------------------------------
41 : // systemTextLineSegmentStyle
42 : //---------------------------------------------------------
43 :
44 : static const ElementStyle systemTextLineSegmentStyle {
45 : { Sid::systemTextLineMinDistance, Pid::MIN_DISTANCE },
46 : };
47 :
48 : //---------------------------------------------------------
49 : // textLineStyle
50 : //---------------------------------------------------------
51 :
52 : static const ElementStyle textLineStyle {
53 : { Sid::textLineFontFace, Pid::BEGIN_FONT_FACE },
54 : { Sid::textLineFontFace, Pid::CONTINUE_FONT_FACE },
55 : { Sid::textLineFontFace, Pid::END_FONT_FACE },
56 : { Sid::textLineFontSize, Pid::BEGIN_FONT_SIZE },
57 : { Sid::textLineFontSize, Pid::CONTINUE_FONT_SIZE },
58 : { Sid::textLineFontSize, Pid::END_FONT_SIZE },
59 : { Sid::textLineFontStyle, Pid::BEGIN_FONT_STYLE },
60 : { Sid::textLineFontStyle, Pid::CONTINUE_FONT_STYLE },
61 : { Sid::textLineFontStyle, Pid::END_FONT_STYLE },
62 : { Sid::textLineTextAlign, Pid::BEGIN_TEXT_ALIGN },
63 : { Sid::textLineTextAlign, Pid::CONTINUE_TEXT_ALIGN },
64 : { Sid::textLineTextAlign, Pid::END_TEXT_ALIGN },
65 : { Sid::textLinePosition, Pid::BEGIN_TEXT_POSITION },
66 : { Sid::textLinePosition, Pid::CONTINUE_TEXT_POSITION },
67 : { Sid::textLinePosition, Pid::END_TEXT_POSITION },
68 : { Sid::textLineHookHeight, Pid::BEGIN_HOOK_HEIGHT },
69 : { Sid::textLineHookHeight, Pid::END_HOOK_HEIGHT },
70 : { Sid::textLineLineWidth, Pid::LINE_WIDTH },
71 : { Sid::textLineDashLineLen, Pid::DASH_LINE_LEN },
72 : { Sid::textLineDashGapLen, Pid::DASH_GAP_LEN },
73 : { Sid::textLinePlacement, Pid::PLACEMENT },
74 : { Sid::textLineLineStyle, Pid::LINE_STYLE },
75 : { Sid::textLineFontSpatiumDependent, Pid::TEXT_SIZE_SPATIUM_DEPENDENT },
76 : { Sid::textLineEndLineArrowHeight, Pid::END_LINE_ARROW_HEIGHT },
77 : { Sid::textLineEndLineArrowWidth, Pid::END_LINE_ARROW_WIDTH },
78 : { Sid::textLineBeginLineArrowHeight, Pid::BEGIN_LINE_ARROW_HEIGHT },
79 : { Sid::textLineBeginLineArrowWidth, Pid::BEGIN_LINE_ARROW_WIDTH },
80 : { Sid::textLineEndFilledArrowHeight, Pid::END_FILLED_ARROW_HEIGHT },
81 : { Sid::textLineEndFilledArrowWidth, Pid::END_FILLED_ARROW_WIDTH },
82 : { Sid::textLineBeginFilledArrowHeight, Pid::BEGIN_FILLED_ARROW_HEIGHT },
83 : { Sid::textLineBeginFilledArrowWidth, Pid::BEGIN_FILLED_ARROW_WIDTH },
84 : { Sid::textLineMusicalSymbolSize, Pid::BEGIN_TEXT_MUSIC_SYMBOLS_SIZE },
85 : { Sid::textLineMusicalSymbolSize, Pid::CONTINUE_TEXT_MUSIC_SYMBOLS_SIZE },
86 : { Sid::textLineMusicalSymbolSize, Pid::END_TEXT_MUSIC_SYMBOLS_SIZE },
87 : { Sid::dummyMusicalSymbolsScale, Pid::BEGIN_TEXT_MUSICAL_SYMBOLS_SCALE },
88 : { Sid::dummyMusicalSymbolsScale, Pid::CONTINUE_TEXT_MUSICAL_SYMBOLS_SCALE },
89 : { Sid::dummyMusicalSymbolsScale, Pid::END_TEXT_MUSICAL_SYMBOLS_SCALE },
90 : };
91 :
92 : //---------------------------------------------------------
93 : // systemTextLineStyle
94 : //---------------------------------------------------------
95 :
96 : static const ElementStyle systemTextLineStyle {
97 : { Sid::systemTextLineFontFace, Pid::BEGIN_FONT_FACE },
98 : { Sid::systemTextLineFontFace, Pid::CONTINUE_FONT_FACE },
99 : { Sid::systemTextLineFontFace, Pid::END_FONT_FACE },
100 : { Sid::systemTextLineFontSize, Pid::BEGIN_FONT_SIZE },
101 : { Sid::systemTextLineFontSize, Pid::CONTINUE_FONT_SIZE },
102 : { Sid::systemTextLineFontSize, Pid::END_FONT_SIZE },
103 : { Sid::systemTextLineFontStyle, Pid::BEGIN_FONT_STYLE },
104 : { Sid::systemTextLineFontStyle, Pid::CONTINUE_FONT_STYLE },
105 : { Sid::systemTextLineFontStyle, Pid::END_FONT_STYLE },
106 : { Sid::systemTextLineTextAlign, Pid::BEGIN_TEXT_ALIGN },
107 : { Sid::systemTextLineTextAlign, Pid::CONTINUE_TEXT_ALIGN },
108 : { Sid::systemTextLineTextAlign, Pid::END_TEXT_ALIGN },
109 : { Sid::systemTextLineHookHeight, Pid::BEGIN_HOOK_HEIGHT },
110 : { Sid::systemTextLineHookHeight, Pid::END_HOOK_HEIGHT },
111 : { Sid::systemTextLineLineWidth, Pid::LINE_WIDTH },
112 : { Sid::systemTextLineDashLineLen, Pid::DASH_LINE_LEN },
113 : { Sid::systemTextLineDashGapLen, Pid::DASH_GAP_LEN },
114 : { Sid::systemTextLinePlacement, Pid::PLACEMENT },
115 : { Sid::systemTextLineLineStyle, Pid::LINE_STYLE },
116 : { Sid::systemTextLineMusicalSymbolSize, Pid::BEGIN_TEXT_MUSIC_SYMBOLS_SIZE },
117 : { Sid::systemTextLineMusicalSymbolSize, Pid::CONTINUE_TEXT_MUSIC_SYMBOLS_SIZE },
118 : { Sid::systemTextLineMusicalSymbolSize, Pid::END_TEXT_MUSIC_SYMBOLS_SIZE },
119 : { Sid::dummyMusicalSymbolsScale, Pid::BEGIN_TEXT_MUSICAL_SYMBOLS_SCALE },
120 : { Sid::dummyMusicalSymbolsScale, Pid::CONTINUE_TEXT_MUSICAL_SYMBOLS_SCALE },
121 : { Sid::dummyMusicalSymbolsScale, Pid::END_TEXT_MUSICAL_SYMBOLS_SCALE },
122 : { Sid::systemTextLineFontSpatiumDependent, Pid::TEXT_SIZE_SPATIUM_DEPENDENT },
123 : };
124 :
125 : //---------------------------------------------------------
126 : // TextLineSegment
127 : //---------------------------------------------------------
128 :
129 34 : TextLineSegment::TextLineSegment(TextLine* sp, bool system)
130 34 : : TextLineBaseSegment(ElementType::TEXTLINE_SEGMENT, sp, ElementFlag::MOVABLE | ElementFlag::ON_STAFF)
131 : {
132 34 : setSystemFlag(system);
133 34 : initStyle();
134 :
135 34 : m_text->setTextStyleType(propertyDefault(Pid::TEXT_STYLE).value<TextStyleType>());
136 34 : m_endText->setTextStyleType(propertyDefault(Pid::TEXT_STYLE).value<TextStyleType>());
137 34 : }
138 :
139 : //---------------------------------------------------------
140 : // propertyDelegate
141 : //---------------------------------------------------------
142 :
143 322 : EngravingObject* TextLineSegment::propertyDelegate(Pid pid) const
144 : {
145 322 : if (pid == Pid::SYSTEM_FLAG) {
146 0 : return static_cast<TextLine*>(spanner());
147 : }
148 322 : return TextLineBaseSegment::propertyDelegate(pid);
149 : }
150 :
151 : //---------------------------------------------------------
152 : // TextLine
153 : //---------------------------------------------------------
154 :
155 113 : TextLine::TextLine(DummyParentOr<EngravingItem> parent, bool system)
156 113 : : TextLineBase(ElementType::TEXTLINE, parent)
157 : {
158 113 : setSystemFlag(system);
159 :
160 113 : initStyle();
161 :
162 113 : setBeginText(u"");
163 113 : setContinueText(u"");
164 113 : setEndText(u"");
165 113 : setBeginTextOffset(PointF(0, 0));
166 113 : setContinueTextOffset(PointF(0, 0));
167 113 : setEndTextOffset(PointF(0, 0));
168 113 : setLineVisible(true);
169 :
170 113 : setBeginHookType(HookType::NONE);
171 113 : setEndHookType(HookType::NONE);
172 113 : setBeginHookHeight(1.5_sp);
173 113 : setEndHookHeight(1.5_sp);
174 113 : setGapBetweenTextAndLine(0.5_sp);
175 :
176 113 : setBeginFilledArrowHeight(1.0_sp);
177 113 : setBeginFilledArrowWidth(0.85_sp);
178 113 : setEndFilledArrowHeight(1.0_sp);
179 113 : setEndFilledArrowWidth(0.85_sp);
180 :
181 113 : setBeginLineArrowHeight(1.0_sp);
182 113 : setBeginLineArrowWidth(0.5_sp);
183 113 : setEndLineArrowHeight(1.0_sp);
184 113 : setEndLineArrowWidth(0.5_sp);
185 :
186 113 : resetProperty(Pid::BEGIN_TEXT_PLACE);
187 113 : resetProperty(Pid::CONTINUE_TEXT_PLACE);
188 113 : resetProperty(Pid::END_TEXT_PLACE);
189 113 : }
190 :
191 0 : TextLine::TextLine(const TextLine& tl)
192 0 : : TextLineBase(tl)
193 : {
194 0 : }
195 :
196 : //---------------------------------------------------------
197 : // initStyle
198 : //---------------------------------------------------------
199 :
200 167 : void TextLine::initStyle()
201 : {
202 167 : if (systemFlag()) {
203 1 : initElementStyle(&systemTextLineStyle);
204 : } else {
205 166 : initElementStyle(&textLineStyle);
206 : }
207 167 : }
208 :
209 68 : void TextLineSegment::initStyle()
210 : {
211 68 : if (systemFlag()) {
212 4 : initElementStyle(&systemTextLineSegmentStyle);
213 : } else {
214 64 : initElementStyle(&textLineSegmentStyle);
215 : }
216 68 : }
217 :
218 : //---------------------------------------------------------
219 : // createLineSegment
220 : //---------------------------------------------------------
221 :
222 34 : LineSegment* TextLine::createLineSegment()
223 : {
224 34 : TextLineSegment* seg = new TextLineSegment(this, systemFlag());
225 34 : seg->setTrack(track());
226 : // note-anchored line segments are relative to system not to staff
227 34 : if (anchor() == Spanner::Anchor::NOTE) {
228 0 : seg->setFlag(ElementFlag::ON_STAFF, false);
229 : }
230 34 : seg->initStyle();
231 :
232 34 : return seg;
233 : }
234 :
235 : //---------------------------------------------------------
236 : // propertyDefault
237 : //---------------------------------------------------------
238 :
239 1508 : PropertyValue TextLine::propertyDefault(Pid propertyId) const
240 : {
241 1508 : switch (propertyId) {
242 135 : case Pid::BEGIN_TEXT:
243 : case Pid::CONTINUE_TEXT:
244 : case Pid::END_TEXT:
245 135 : return "";
246 45 : case Pid::LINE_VISIBLE:
247 45 : return true;
248 135 : case Pid::BEGIN_TEXT_OFFSET:
249 : case Pid::CONTINUE_TEXT_OFFSET:
250 : case Pid::END_TEXT_OFFSET:
251 270 : return PointF(0, 0);
252 90 : case Pid::BEGIN_HOOK_TYPE:
253 : case Pid::END_HOOK_TYPE:
254 90 : return HookType::NONE;
255 474 : case Pid::BEGIN_TEXT_PLACE:
256 : case Pid::CONTINUE_TEXT_PLACE:
257 : case Pid::END_TEXT_PLACE:
258 474 : return TextPlace::LEFT;
259 68 : case Pid::TEXT_STYLE:
260 68 : return systemFlag() ? TextStyleType::SYSTEM_TEXTLINE : TextStyleType::TEXTLINE;
261 561 : default:
262 561 : return TextLineBase::propertyDefault(propertyId);
263 : }
264 : }
265 :
266 : //---------------------------------------------------------
267 : // allowTimeAnchor
268 : //---------------------------------------------------------
269 0 : bool TextLine::allowTimeAnchor() const
270 : {
271 0 : return !(anchor() == Spanner::Anchor::NOTE);
272 : }
273 :
274 : //---------------------------------------------------------
275 : // setProperty
276 : //---------------------------------------------------------
277 :
278 6692 : bool TextLine::setProperty(Pid id, const engraving::PropertyValue& v)
279 : {
280 6692 : switch (id) {
281 0 : case Pid::PLAY:
282 0 : break;
283 170 : case Pid::PLACEMENT:
284 170 : setPlacement(v.value<PlacementV>());
285 170 : break;
286 6522 : default:
287 6522 : return TextLineBase::setProperty(id, v);
288 : }
289 170 : triggerLayout();
290 170 : return true;
291 : }
292 :
293 : //---------------------------------------------------------
294 : // getProperty
295 : //---------------------------------------------------------
296 :
297 1283 : PropertyValue TextLine::getProperty(Pid id) const
298 : {
299 1283 : switch (id) {
300 45 : case Pid::PLAY:
301 45 : return PropertyValue();
302 1238 : default:
303 1238 : break;
304 : }
305 1238 : return TextLineBase::getProperty(id);
306 : }
307 :
308 : //---------------------------------------------------------
309 : // undoChangeProperty
310 : //---------------------------------------------------------
311 :
312 0 : void TextLine::undoChangeProperty(Pid id, const engraving::PropertyValue& v, PropertyFlags ps)
313 : {
314 0 : if (id == Pid::SYSTEM_FLAG) {
315 0 : score()->undo(new ChangeTextLineProperty(this, v));
316 0 : for (SpannerSegment* s : spannerSegments()) {
317 0 : score()->undo(new ChangeTextLineProperty(s, v));
318 0 : triggerLayout();
319 : }
320 0 : return;
321 : }
322 0 : TextLineBase::undoChangeProperty(id, v, ps);
323 : }
324 :
325 56 : Sid TextLine::defaultPosSid() const
326 : {
327 56 : if (systemFlag()) {
328 4 : return placeAbove() ? Sid::systemTextLinePosAbove : Sid::systemTextLinePosBelow;
329 : }
330 52 : return placeAbove() ? Sid::textLinePosAbove : Sid::textLinePosBelow;
331 : }
332 : } // namespace mu::engraving
|