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 "fingering.h"
24 :
25 : #include "translation.h"
26 :
27 : #include "beam.h"
28 : #include "chord.h"
29 : #include "measure.h"
30 : #include "note.h"
31 : #include "part.h"
32 : #include "skyline.h"
33 : #include "staff.h"
34 : #include "stem.h"
35 : #include "system.h"
36 :
37 : using namespace mu;
38 :
39 : namespace mu::engraving {
40 : //---------------------------------------------------------
41 : // fingeringStyle
42 : //---------------------------------------------------------
43 :
44 : static const ElementStyle fingeringStyle {
45 : { Sid::fingeringPlacement, Pid::PLACEMENT },
46 : { Sid::fingeringMinDistance, Pid::MIN_DISTANCE },
47 : };
48 :
49 : //---------------------------------------------------------
50 : // Fingering
51 : // EngravingItem(Score* = 0, ElementFlags = ElementFlag::NOTHING);
52 : //---------------------------------------------------------
53 :
54 282 : Fingering::Fingering(DummyParentOr<Note> parent, TextStyleType tid, ElementFlags ef)
55 282 : : TextBase(ElementType::FINGERING, parent, tid, ef)
56 : {
57 282 : setPlacement(PlacementV::ABOVE);
58 282 : initElementStyle(&fingeringStyle);
59 282 : }
60 :
61 209 : Fingering::Fingering(DummyParentOr<Note> parent, ElementFlags ef)
62 209 : : Fingering(parent, TextStyleType::FINGERING, ef)
63 : {
64 209 : }
65 :
66 : //---------------------------------------------------------
67 : // layoutType
68 : //---------------------------------------------------------
69 :
70 3231 : ElementType Fingering::layoutType() const
71 : {
72 3231 : switch (textStyleType()) {
73 3160 : case TextStyleType::FINGERING:
74 : case TextStyleType::RH_GUITAR_FINGERING:
75 : case TextStyleType::STRING_NUMBER:
76 3160 : return ElementType::CHORD;
77 71 : default:
78 71 : return ElementType::NOTE;
79 : }
80 : }
81 :
82 : //---------------------------------------------------------
83 : // calculatePlacement
84 : //---------------------------------------------------------
85 :
86 468 : PlacementV Fingering::calculatePlacement() const
87 : {
88 468 : Note* n = note();
89 468 : if (!n) {
90 0 : return PlacementV::ABOVE;
91 : }
92 468 : Chord* chord = n->chord();
93 468 : Staff* staff = chord->staff();
94 468 : Part* part = staff->part();
95 468 : size_t nstaves = part->nstaves();
96 468 : bool voices = chord->measure()->hasVoices(staff->idx(), chord->tick(), chord->actualTicks());
97 468 : bool below = voices ? !chord->up() : (nstaves > 1) && (staff->rstaff() == nstaves - 1);
98 468 : return below ? PlacementV::BELOW : PlacementV::ABOVE;
99 : }
100 :
101 0 : bool Fingering::isEditAllowed(EditData& ed) const
102 : {
103 0 : if (isTextNavigationKey(ed.key, ed.modifiers)) {
104 0 : return false;
105 : }
106 :
107 0 : if (ed.key == Key_Left) {
108 0 : return cursor()->column() != 0 || cursor()->hasSelection();
109 : }
110 :
111 0 : if (ed.key == Key_Right) {
112 0 : bool cursorInLastColumn = cursor()->column() == cursor()->curLine().columns();
113 0 : return !cursorInLastColumn || cursor()->hasSelection();
114 : }
115 :
116 0 : return TextBase::isEditAllowed(ed);
117 : }
118 :
119 : //---------------------------------------------------------
120 : // accessibleInfo
121 : //---------------------------------------------------------
122 :
123 0 : String Fingering::accessibleInfo() const
124 : {
125 0 : String rez = EngravingItem::accessibleInfo();
126 0 : if (textStyleType() == TextStyleType::STRING_NUMBER) {
127 0 : rez += u' ' + muse::mtrc("engraving", "String number");
128 : }
129 0 : return String(u"%1: %2").arg(rez, plainText());
130 0 : }
131 :
132 420 : bool Fingering::isOnCrossBeamSide() const
133 : {
134 420 : Chord* chord = note() ? note()->chord() : nullptr;
135 420 : if (!chord) {
136 0 : return false;
137 : }
138 420 : return layoutType() == ElementType::CHORD
139 420 : && chord->beam() && (chord->beam()->cross() || chord->staffMove() != 0)
140 840 : && placeAbove() == chord->up();
141 : }
142 :
143 : //---------------------------------------------------------
144 : // propertyDefault
145 : //---------------------------------------------------------
146 :
147 2298 : engraving::PropertyValue Fingering::propertyDefault(Pid id) const
148 : {
149 2298 : switch (id) {
150 105 : case Pid::PLACEMENT:
151 105 : return calculatePlacement();
152 202 : case Pid::TEXT_STYLE:
153 202 : return TextStyleType::FINGERING;
154 1991 : default:
155 1991 : return TextBase::propertyDefault(id);
156 : }
157 : }
158 : }
|